StorageEngine.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Library for extracting information about the available storage engines
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. declare(strict_types=1);
  9. namespace PhpMyAdmin;
  10. use PhpMyAdmin\Engines\Bdb;
  11. use PhpMyAdmin\Engines\Berkeleydb;
  12. use PhpMyAdmin\Engines\Binlog;
  13. use PhpMyAdmin\Engines\Innobase;
  14. use PhpMyAdmin\Engines\Innodb;
  15. use PhpMyAdmin\Engines\Memory;
  16. use PhpMyAdmin\Engines\Merge;
  17. use PhpMyAdmin\Engines\MrgMyisam;
  18. use PhpMyAdmin\Engines\Myisam;
  19. use PhpMyAdmin\Engines\Ndbcluster;
  20. use PhpMyAdmin\Engines\Pbxt;
  21. use PhpMyAdmin\Engines\PerformanceSchema;
  22. use PhpMyAdmin\Util;
  23. /**
  24. * defines
  25. */
  26. define('PMA_ENGINE_SUPPORT_NO', 0);
  27. define('PMA_ENGINE_SUPPORT_DISABLED', 1);
  28. define('PMA_ENGINE_SUPPORT_YES', 2);
  29. define('PMA_ENGINE_SUPPORT_DEFAULT', 3);
  30. define('PMA_ENGINE_DETAILS_TYPE_PLAINTEXT', 0);
  31. define('PMA_ENGINE_DETAILS_TYPE_SIZE', 1);
  32. define('PMA_ENGINE_DETAILS_TYPE_NUMERIC', 2); //Has no effect yet...
  33. define('PMA_ENGINE_DETAILS_TYPE_BOOLEAN', 3); // 'ON' or 'OFF'
  34. /**
  35. * Base Storage Engine Class
  36. *
  37. * @package PhpMyAdmin
  38. */
  39. class StorageEngine
  40. {
  41. /**
  42. * @var string engine name
  43. */
  44. public $engine = 'dummy';
  45. /**
  46. * @var string engine title/description
  47. */
  48. public $title = 'PMA Dummy Engine Class';
  49. /**
  50. * @var string engine lang description
  51. */
  52. public $comment
  53. = 'If you read this text inside phpMyAdmin, something went wrong...';
  54. /**
  55. * @var integer engine supported by current server
  56. */
  57. public $support = PMA_ENGINE_SUPPORT_NO;
  58. /**
  59. * Constructor
  60. *
  61. * @param string $engine The engine ID
  62. */
  63. public function __construct($engine)
  64. {
  65. $storage_engines = self::getStorageEngines();
  66. if (! empty($storage_engines[$engine])) {
  67. $this->engine = $engine;
  68. $this->title = $storage_engines[$engine]['Engine'];
  69. $this->comment = (isset($storage_engines[$engine]['Comment'])
  70. ? $storage_engines[$engine]['Comment']
  71. : '');
  72. switch ($storage_engines[$engine]['Support']) {
  73. case 'DEFAULT':
  74. $this->support = PMA_ENGINE_SUPPORT_DEFAULT;
  75. break;
  76. case 'YES':
  77. $this->support = PMA_ENGINE_SUPPORT_YES;
  78. break;
  79. case 'DISABLED':
  80. $this->support = PMA_ENGINE_SUPPORT_DISABLED;
  81. break;
  82. case 'NO':
  83. default:
  84. $this->support = PMA_ENGINE_SUPPORT_NO;
  85. }
  86. }
  87. }
  88. /**
  89. * Returns array of storage engines
  90. *
  91. * @static
  92. * @staticvar array $storage_engines storage engines
  93. * @access public
  94. * @return array[] array of storage engines
  95. */
  96. public static function getStorageEngines()
  97. {
  98. static $storage_engines = null;
  99. if (null == $storage_engines) {
  100. $storage_engines
  101. = $GLOBALS['dbi']->fetchResult('SHOW STORAGE ENGINES', 'Engine');
  102. if ($GLOBALS['dbi']->getVersion() >= 50708) {
  103. $disabled = (string) Util::cacheGet(
  104. 'disabled_storage_engines',
  105. function () {
  106. return $GLOBALS['dbi']->fetchValue(
  107. 'SELECT @@disabled_storage_engines'
  108. );
  109. }
  110. );
  111. foreach (explode(",", $disabled) as $engine) {
  112. if (isset($storage_engines[$engine])) {
  113. $storage_engines[$engine]['Support'] = 'DISABLED';
  114. }
  115. }
  116. }
  117. }
  118. return $storage_engines;
  119. }
  120. /**
  121. * Returns HTML code for storage engine select box
  122. *
  123. * @param string $name The name of the select form element
  124. * @param string $id The ID of the form field
  125. * @param string $selected The selected engine
  126. * @param boolean $offerUnavailableEngines Should unavailable storage
  127. * engines be offered?
  128. * @param boolean $addEmpty Whether to provide empty option
  129. *
  130. * @static
  131. * @return string html selectbox
  132. */
  133. public static function getHtmlSelect(
  134. $name = 'engine',
  135. $id = null,
  136. $selected = null,
  137. $offerUnavailableEngines = false,
  138. $addEmpty = false
  139. ) {
  140. $selected = mb_strtolower((string) $selected);
  141. $output = '<select name="' . $name . '"'
  142. . (empty($id) ? '' : ' id="' . $id . '"') . '>' . "\n";
  143. if ($addEmpty) {
  144. $output .= '<option value=""></option>';
  145. }
  146. foreach (self::getStorageEngines() as $key => $details) {
  147. // Don't show PERFORMANCE_SCHEMA engine (MySQL 5.5)
  148. if (! $offerUnavailableEngines
  149. && ($details['Support'] == 'NO'
  150. || $details['Support'] == 'DISABLED'
  151. || $details['Engine'] == 'PERFORMANCE_SCHEMA')
  152. ) {
  153. continue;
  154. }
  155. $output .= ' <option value="' . htmlspecialchars($key) . '"'
  156. . (empty($details['Comment'])
  157. ? '' : ' title="' . htmlspecialchars($details['Comment']) . '"')
  158. . (mb_strtolower($key) == $selected
  159. || (empty($selected) && $details['Support'] == 'DEFAULT' && ! $addEmpty)
  160. ? ' selected="selected"' : '')
  161. . '>' . "\n"
  162. . ' ' . htmlspecialchars($details['Engine']) . "\n"
  163. . ' </option>' . "\n";
  164. }
  165. $output .= '</select>' . "\n";
  166. return $output;
  167. }
  168. /**
  169. * Loads the corresponding engine plugin, if available.
  170. *
  171. * @param string $engine The engine ID
  172. *
  173. * @return StorageEngine The engine plugin
  174. * @static
  175. */
  176. public static function getEngine($engine)
  177. {
  178. switch (mb_strtolower($engine)) {
  179. case 'bdb':
  180. return new Bdb($engine);
  181. case 'berkeleydb':
  182. return new Berkeleydb($engine);
  183. case 'binlog':
  184. return new Binlog($engine);
  185. case 'innobase':
  186. return new Innobase($engine);
  187. case 'innodb':
  188. return new Innodb($engine);
  189. case 'memory':
  190. return new Memory($engine);
  191. case 'merge':
  192. return new Merge($engine);
  193. case 'mrg_myisam':
  194. return new MrgMyisam($engine);
  195. case 'myisam':
  196. return new Myisam($engine);
  197. case 'ndbcluster':
  198. return new Ndbcluster($engine);
  199. case 'pbxt':
  200. return new Pbxt($engine);
  201. case 'performance_schema':
  202. return new PerformanceSchema($engine);
  203. default:
  204. return new StorageEngine($engine);
  205. }
  206. }
  207. /**
  208. * Returns true if given engine name is supported/valid, otherwise false
  209. *
  210. * @param string $engine name of engine
  211. *
  212. * @static
  213. * @return boolean whether $engine is valid or not
  214. */
  215. public static function isValid($engine)
  216. {
  217. if ($engine == "PBMS") {
  218. return true;
  219. }
  220. $storage_engines = self::getStorageEngines();
  221. return isset($storage_engines[$engine]);
  222. }
  223. /**
  224. * Returns as HTML table of the engine's server variables
  225. *
  226. * @return string The table that was generated based on the retrieved
  227. * information
  228. */
  229. public function getHtmlVariables()
  230. {
  231. $ret = '';
  232. foreach ($this->getVariablesStatus() as $details) {
  233. $ret .= '<tr>' . "\n"
  234. . ' <td>' . "\n";
  235. if (! empty($details['desc'])) {
  236. $ret .= ' '
  237. . Util::showHint($details['desc'])
  238. . "\n";
  239. }
  240. $ret .= ' </td>' . "\n"
  241. . ' <th>' . htmlspecialchars($details['title']) . '</th>'
  242. . "\n"
  243. . ' <td class="value">';
  244. switch ($details['type']) {
  245. case PMA_ENGINE_DETAILS_TYPE_SIZE:
  246. $parsed_size = $this->resolveTypeSize($details['value']);
  247. $ret .= $parsed_size[0] . '&nbsp;' . $parsed_size[1];
  248. unset($parsed_size);
  249. break;
  250. case PMA_ENGINE_DETAILS_TYPE_NUMERIC:
  251. $ret .= Util::formatNumber($details['value']) . ' ';
  252. break;
  253. default:
  254. $ret .= htmlspecialchars($details['value']) . ' ';
  255. }
  256. $ret .= '</td>' . "\n"
  257. . '</tr>' . "\n";
  258. }
  259. if (! $ret) {
  260. $ret = '<p>' . "\n"
  261. . ' '
  262. . __(
  263. 'There is no detailed status information available for this '
  264. . 'storage engine.'
  265. )
  266. . "\n"
  267. . '</p>' . "\n";
  268. } else {
  269. $ret = '<table class="data">' . "\n" . $ret . '</table>' . "\n";
  270. }
  271. return $ret;
  272. }
  273. /**
  274. * Returns the engine specific handling for
  275. * PMA_ENGINE_DETAILS_TYPE_SIZE type variables.
  276. *
  277. * This function should be overridden when
  278. * PMA_ENGINE_DETAILS_TYPE_SIZE type needs to be
  279. * handled differently for a particular engine.
  280. *
  281. * @param integer $value Value to format
  282. *
  283. * @return array the formatted value and its unit
  284. */
  285. public function resolveTypeSize($value)
  286. {
  287. return Util::formatByteDown($value);
  288. }
  289. /**
  290. * Returns array with detailed info about engine specific server variables
  291. *
  292. * @return array array with detailed info about specific engine server variables
  293. */
  294. public function getVariablesStatus()
  295. {
  296. $variables = $this->getVariables();
  297. $like = $this->getVariablesLikePattern();
  298. if ($like) {
  299. $like = " LIKE '" . $like . "' ";
  300. } else {
  301. $like = '';
  302. }
  303. $mysql_vars = [];
  304. $sql_query = 'SHOW GLOBAL VARIABLES ' . $like . ';';
  305. $res = $GLOBALS['dbi']->query($sql_query);
  306. while ($row = $GLOBALS['dbi']->fetchAssoc($res)) {
  307. if (isset($variables[$row['Variable_name']])) {
  308. $mysql_vars[$row['Variable_name']]
  309. = $variables[$row['Variable_name']];
  310. } elseif (! $like
  311. && mb_strpos(mb_strtolower($row['Variable_name']), mb_strtolower($this->engine)) !== 0
  312. ) {
  313. continue;
  314. }
  315. $mysql_vars[$row['Variable_name']]['value'] = $row['Value'];
  316. if (empty($mysql_vars[$row['Variable_name']]['title'])) {
  317. $mysql_vars[$row['Variable_name']]['title'] = $row['Variable_name'];
  318. }
  319. if (! isset($mysql_vars[$row['Variable_name']]['type'])) {
  320. $mysql_vars[$row['Variable_name']]['type']
  321. = PMA_ENGINE_DETAILS_TYPE_PLAINTEXT;
  322. }
  323. }
  324. $GLOBALS['dbi']->freeResult($res);
  325. return $mysql_vars;
  326. }
  327. /**
  328. * Reveals the engine's title
  329. *
  330. * @return string The title
  331. */
  332. public function getTitle()
  333. {
  334. return $this->title;
  335. }
  336. /**
  337. * Fetches the server's comment about this engine
  338. *
  339. * @return string The comment
  340. */
  341. public function getComment()
  342. {
  343. return $this->comment;
  344. }
  345. /**
  346. * Information message on whether this storage engine is supported
  347. *
  348. * @return string The localized message.
  349. */
  350. public function getSupportInformationMessage()
  351. {
  352. switch ($this->support) {
  353. case PMA_ENGINE_SUPPORT_DEFAULT:
  354. $message = __('%s is the default storage engine on this MySQL server.');
  355. break;
  356. case PMA_ENGINE_SUPPORT_YES:
  357. $message = __('%s is available on this MySQL server.');
  358. break;
  359. case PMA_ENGINE_SUPPORT_DISABLED:
  360. $message = __('%s has been disabled for this MySQL server.');
  361. break;
  362. case PMA_ENGINE_SUPPORT_NO:
  363. default:
  364. $message = __(
  365. 'This MySQL server does not support the %s storage engine.'
  366. );
  367. }
  368. return sprintf($message, htmlspecialchars($this->title));
  369. }
  370. /**
  371. * Generates a list of MySQL variables that provide information about this
  372. * engine. This function should be overridden when extending this class
  373. * for a particular engine.
  374. *
  375. * @return array The list of variables.
  376. */
  377. public function getVariables()
  378. {
  379. return [];
  380. }
  381. /**
  382. * Returns string with filename for the MySQL helppage
  383. * about this storage engine
  384. *
  385. * @return string MySQL help page filename
  386. */
  387. public function getMysqlHelpPage()
  388. {
  389. return $this->engine . '-storage-engine';
  390. }
  391. /**
  392. * Returns the pattern to be used in the query for SQL variables
  393. * related to the storage engine
  394. *
  395. * @return string SQL query LIKE pattern
  396. */
  397. public function getVariablesLikePattern()
  398. {
  399. return '';
  400. }
  401. /**
  402. * Returns a list of available information pages with labels
  403. *
  404. * @return string[] The list
  405. */
  406. public function getInfoPages()
  407. {
  408. return [];
  409. }
  410. /**
  411. * Generates the requested information page
  412. *
  413. * @param string $id page id
  414. *
  415. * @return string html output
  416. */
  417. public function getPage($id)
  418. {
  419. if (! array_key_exists($id, $this->getInfoPages())) {
  420. return '';
  421. }
  422. $id = 'getPage' . $id;
  423. return $this->$id();
  424. }
  425. }