db_structure.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Database structure manipulation
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. /**
  9. *
  10. */
  11. require_once 'libraries/common.inc.php';
  12. /**
  13. * Function implementations for this script
  14. */
  15. require_once 'libraries/structure.lib.php';
  16. // Add/Remove favorite tables using Ajax request.
  17. if ($GLOBALS['is_ajax_request'] && ! empty($_REQUEST['favorite_table'])) {
  18. $fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
  19. $favorite_tables = json_decode($_REQUEST['favorite_tables'], true);
  20. // Required to keep each user's preferences seperate.
  21. $user = sha1($GLOBALS['cfg']['Server']['user']);
  22. // Request for Synchronization of favorite tables.
  23. if (isset($_REQUEST['sync_favorite_tables'])) {
  24. $fav_instance_tables = $fav_instance->getTables();
  25. if (empty($fav_instance_tables)
  26. && isset($favorite_tables[$user])
  27. ) {
  28. foreach ($favorite_tables[$user] as $key => $value) {
  29. $fav_instance->add($value['db'], $value['table']);
  30. }
  31. }
  32. $favorite_tables[$user] = $fav_instance->getTables();
  33. $ajax_response = PMA_Response::getInstance();
  34. $ajax_response->addJSON(
  35. 'favorite_tables',
  36. json_encode($favorite_tables)
  37. );
  38. $ajax_response->addJSON(
  39. 'list',
  40. $fav_instance->getHtmlList()
  41. );
  42. $server_id = $GLOBALS['server'];
  43. // Set flag when localStorage and pmadb(if present) are in sync.
  44. $_SESSION['tmpval']['favorites_synced'][$server_id] = true;
  45. exit;
  46. }
  47. global $db;
  48. $changes = true;
  49. $msg = '';
  50. $titles = PMA_Util::buildActionTitles();
  51. $favorite_table = $_REQUEST['favorite_table'];
  52. $already_favorite = PMA_checkFavoriteTable($db, $favorite_table);
  53. if (isset($_REQUEST['remove_favorite'])) {
  54. if ($already_favorite) {
  55. // If already in favorite list, remove it.
  56. $fav_instance->remove($db, $favorite_table);
  57. }
  58. } elseif (isset($_REQUEST['add_favorite'])) {
  59. if (!$already_favorite) {
  60. if (count($fav_instance->getTables()) == $GLOBALS['cfg']['NumFavoriteTables']) {
  61. $changes = false;
  62. $msg = '<div class="error"><img src="themes/dot.gif" '
  63. . 'title="" alt="" class="icon ic_s_error" />'
  64. . __("Favorite List is full!")
  65. . '</div>';
  66. } else {
  67. // Otherwise add to favorite list.
  68. $fav_instance->add($db, $favorite_table);
  69. }
  70. }
  71. }
  72. $favorite_tables[$user] = $fav_instance->getTables();
  73. $ajax_response = PMA_Response::getInstance();
  74. $ajax_response->addJSON(
  75. 'changes',
  76. $changes
  77. );
  78. if ($changes) {
  79. $ajax_response->addJSON(
  80. 'user',
  81. $user
  82. );
  83. $ajax_response->addJSON(
  84. 'favorite_tables',
  85. json_encode($favorite_tables)
  86. );
  87. $ajax_response->addJSON(
  88. 'list',
  89. $fav_instance->getHtmlList()
  90. );
  91. $ajax_response->addJSON(
  92. 'anchor',
  93. PMA_getHtmlForFavoriteAnchor(
  94. $db, $favorite_table, $titles
  95. )
  96. );
  97. } else {
  98. $ajax_response->addJSON(
  99. 'message',
  100. $msg
  101. );
  102. }
  103. exit;
  104. }
  105. $response = PMA_Response::getInstance();
  106. $header = $response->getHeader();
  107. $scripts = $header->getScripts();
  108. $scripts->addFile('db_structure.js');
  109. $scripts->addFile('tbl_change.js');
  110. $scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
  111. // Drops/deletes/etc. multiple tables if required
  112. if ((!empty($_POST['submit_mult']) && isset($_POST['selected_tbl']))
  113. || isset($_POST['mult_btn'])
  114. ) {
  115. $action = 'db_structure.php';
  116. $err_url = 'db_structure.php?' . PMA_URL_getCommon($db);
  117. // see bug #2794840; in this case, code path is:
  118. // db_structure.php -> libraries/mult_submits.inc.php -> sql.php
  119. // -> db_structure.php and if we got an error on the multi submit,
  120. // we must display it here and not call again mult_submits.inc.php
  121. if (! isset($_POST['error']) || false === $_POST['error']) {
  122. include 'libraries/mult_submits.inc.php';
  123. }
  124. if (empty($_POST['message'])) {
  125. $_POST['message'] = PMA_Message::success();
  126. }
  127. }
  128. require 'libraries/db_common.inc.php';
  129. $url_query .= '&amp;goto=db_structure.php';
  130. // Gets the database structure
  131. $sub_part = '_structure';
  132. require 'libraries/db_info.inc.php';
  133. if (!PMA_DRIZZLE) {
  134. include_once 'libraries/replication.inc.php';
  135. } else {
  136. $server_slave_status = false;
  137. }
  138. require_once 'libraries/bookmark.lib.php';
  139. require_once 'libraries/mysql_charsets.inc.php';
  140. $db_collation = PMA_getDbCollation($db);
  141. $titles = PMA_Util::buildActionTitles();
  142. // 1. No tables
  143. if ($num_tables == 0) {
  144. $response->addHTML(
  145. '<p>' . __('No tables found in database.') . '</p>' . "\n"
  146. );
  147. if (empty($db_is_system_schema)) {
  148. ob_start();
  149. include 'libraries/display_create_table.lib.php';
  150. $content = ob_get_contents();
  151. ob_end_clean();
  152. $response->addHTML($content);
  153. unset($content);
  154. } // end if (Create Table dialog)
  155. exit;
  156. }
  157. // else
  158. // 2. Shows table informations
  159. /**
  160. * Displays the tables list
  161. */
  162. $response->addHTML('<div id="tableslistcontainer">');
  163. $_url_params = array(
  164. 'pos' => $pos,
  165. 'db' => $db);
  166. // Add the sort options if they exists
  167. if (isset($_REQUEST['sort'])) {
  168. $_url_params['sort'] = $_REQUEST['sort'];
  169. }
  170. if (isset($_REQUEST['sort_order'])) {
  171. $_url_params['sort_order'] = $_REQUEST['sort_order'];
  172. }
  173. $response->addHTML(
  174. PMA_Util::getListNavigator(
  175. $total_num_tables, $pos, $_url_params, 'db_structure.php',
  176. 'frame_content', $GLOBALS['cfg']['MaxTableList']
  177. )
  178. );
  179. // tables form
  180. $response->addHTML(
  181. '<form method="post" action="db_structure.php" '
  182. . 'name="tablesForm" id="tablesForm">'
  183. );
  184. $response->addHTML(PMA_URL_getHiddenInputs($db));
  185. $response->addHTML(
  186. PMA_tableHeader($db_is_system_schema, $server_slave_status)
  187. );
  188. $i = $sum_entries = 0;
  189. $overhead_check = '';
  190. $create_time_all = '';
  191. $update_time_all = '';
  192. $check_time_all = '';
  193. $num_columns = $cfg['PropertiesNumColumns'] > 1
  194. ? ceil($num_tables / $cfg['PropertiesNumColumns']) + 1
  195. : 0;
  196. $row_count = 0;
  197. $sum_size = (double) 0;
  198. $overhead_size = (double) 0;
  199. $hidden_fields = array();
  200. $odd_row = true;
  201. $sum_row_count_pre = '';
  202. // Instance of PMA_RecentFavoriteTable class.
  203. $fav_instance = PMA_RecentFavoriteTable::getInstance('favorite');
  204. foreach ($tables as $keyname => $current_table) {
  205. // Get valid statistics whatever is the table type
  206. $drop_query = '';
  207. $drop_message = '';
  208. $already_favorite = false;
  209. $overhead = '';
  210. $table_is_view = false;
  211. $table_encoded = urlencode($current_table['TABLE_NAME']);
  212. // Sets parameters for links
  213. $tbl_url_query = $url_query . '&amp;table=' . $table_encoded;
  214. // do not list the previous table's size info for a view
  215. list($current_table, $formatted_size, $unit, $formatted_overhead,
  216. $overhead_unit, $overhead_size, $table_is_view, $sum_size)
  217. = PMA_getStuffForEngineTypeTable(
  218. $current_table, $db_is_system_schema,
  219. $is_show_stats, $table_is_view, $sum_size, $overhead_size
  220. );
  221. if (! PMA_Table::isMerge($db, $current_table['TABLE_NAME'])) {
  222. $sum_entries += $current_table['TABLE_ROWS'];
  223. }
  224. if (isset($current_table['Collation'])) {
  225. $collation = '<dfn title="'
  226. . PMA_getCollationDescr($current_table['Collation']) . '">'
  227. . $current_table['Collation'] . '</dfn>';
  228. } else {
  229. $collation = '---';
  230. }
  231. if ($is_show_stats) {
  232. if ($formatted_overhead != '') {
  233. $overhead = '<a href="tbl_structure.php?'
  234. . $tbl_url_query . '#showusage">'
  235. . '<span>' . $formatted_overhead . '</span>'
  236. . '<span class="unit">' . $overhead_unit . '</span>'
  237. . '</a>' . "\n";
  238. $overhead_check .=
  239. "markAllRows('row_tbl_" . ($i + 1) . "');";
  240. } else {
  241. $overhead = '-';
  242. }
  243. } // end if
  244. unset($showtable);
  245. if ($GLOBALS['cfg']['ShowDbStructureCreation']) {
  246. list($create_time, $create_time_all) = PMA_getTimeForCreateUpdateCheck(
  247. $current_table, 'Create_time', $create_time_all
  248. );
  249. }
  250. if ($GLOBALS['cfg']['ShowDbStructureLastUpdate']) {
  251. // $showtable might already be set from ShowDbStructureCreation, see above
  252. list($update_time, $update_time_all) = PMA_getTimeForCreateUpdateCheck(
  253. $current_table, 'Update_time', $update_time_all
  254. );
  255. }
  256. if ($GLOBALS['cfg']['ShowDbStructureLastCheck']) {
  257. // $showtable might already be set from ShowDbStructureCreation, see above
  258. list($check_time, $check_time_all) = PMA_getTimeForCreateUpdateCheck(
  259. $current_table, 'Check_time', $check_time_all
  260. );
  261. }
  262. list($alias, $truename) = PMA_getAliasAndTrueName(
  263. $tooltip_aliasname, $current_table, $tooltip_truename
  264. );
  265. $i++;
  266. $row_count++;
  267. if ($table_is_view) {
  268. $hidden_fields[] = '<input type="hidden" name="views[]" value="'
  269. . htmlspecialchars($current_table['TABLE_NAME']) . '" />';
  270. }
  271. /*
  272. * Always activate links for Browse, Search and Empty, even if
  273. * the icons are greyed, because
  274. * 1. for views, we don't know the number of rows at this point
  275. * 2. for tables, another source could have populated them since the
  276. * page was generated
  277. *
  278. * I could have used the PHP ternary conditional operator but I find
  279. * the code easier to read without this operator.
  280. */
  281. list($browse_table, $search_table, $browse_table_label, $empty_table,
  282. $tracking_icon) = PMA_getHtmlForActionLinks(
  283. $current_table, $table_is_view, $tbl_url_query,
  284. $titles, $truename, $db_is_system_schema, $url_query
  285. );
  286. if (! $db_is_system_schema) {
  287. list($drop_query, $drop_message)
  288. = PMA_getTableDropQueryAndMessage($table_is_view, $current_table);
  289. }
  290. if ($num_columns > 0
  291. && $num_tables > $num_columns
  292. && ($row_count % $num_columns) == 0
  293. ) {
  294. $row_count = 1;
  295. $odd_row = true;
  296. $response->addHTML(
  297. '</tr></tbody></table>'
  298. );
  299. $response->addHTML(PMA_tableHeader(false, $server_slave_status));
  300. }
  301. list($do, $ignored) = PMA_getServerSlaveStatus(
  302. $server_slave_status, $truename
  303. );
  304. // Handle favorite table list. ----START----
  305. $already_favorite = PMA_checkFavoriteTable($db, $current_table['TABLE_NAME']);
  306. if (isset($_REQUEST['remove_favorite'])) {
  307. if ($already_favorite) {
  308. // If already in favorite list, remove it.
  309. $favorite_table = $_REQUEST['favorite_table'];
  310. $fav_instance->remove($db, $favorite_table);
  311. }
  312. }
  313. if (isset($_REQUEST['add_favorite'])) {
  314. if (!$already_favorite) {
  315. // Otherwise add to favorite list.
  316. $favorite_table = $_REQUEST['favorite_table'];
  317. $fav_instance->add($db, $favorite_table);
  318. }
  319. } // Handle favorite table list. ----ENDS----
  320. list($html_output, $odd_row) = PMA_getHtmlForStructureTableRow(
  321. $i, $odd_row, $table_is_view, $current_table,
  322. $browse_table_label, $tracking_icon, $server_slave_status,
  323. $browse_table, $tbl_url_query, $search_table, $db_is_system_schema,
  324. $titles, $empty_table, $drop_query, $drop_message, $collation,
  325. $formatted_size, $unit, $overhead,
  326. (isset ($create_time) ? $create_time : ''),
  327. (isset ($update_time) ? $update_time : ''),
  328. (isset ($check_time) ? $check_time : ''),
  329. $is_show_stats, $ignored, $do, $colspan_for_structure
  330. );
  331. $response->addHTML($html_output);
  332. } // end foreach
  333. // Show Summary
  334. $response->addHTML('</tbody>');
  335. $response->addHTML(
  336. PMA_getHtmlBodyForTableSummary(
  337. $num_tables, $server_slave_status, $db_is_system_schema, $sum_entries,
  338. $db_collation, $is_show_stats, $sum_size, $overhead_size, $create_time_all,
  339. $update_time_all, $check_time_all, $sum_row_count_pre
  340. )
  341. );
  342. $response->addHTML('</table>');
  343. //check all
  344. $response->addHTML(
  345. PMA_getHtmlForCheckAllTables(
  346. $pmaThemeImage, $text_dir, $overhead_check,
  347. $db_is_system_schema, $hidden_fields
  348. )
  349. );
  350. $response->addHTML('</form>'); //end of form
  351. // display again the table list navigator
  352. $response->addHTML(
  353. PMA_Util::getListNavigator(
  354. $total_num_tables, $pos, $_url_params, 'db_structure.php',
  355. 'frame_content', $GLOBALS['cfg']['MaxTableList']
  356. )
  357. );
  358. $response->addHTML('</div><hr />');
  359. /**
  360. * Work on the database
  361. */
  362. /* DATABASE WORK */
  363. /* Printable view of a table */
  364. $response->addHTML(
  365. PMA_getHtmlForTablePrintViewLink($url_query)
  366. . PMA_getHtmlForDataDictionaryLink($url_query)
  367. );
  368. if (empty($db_is_system_schema)) {
  369. ob_start();
  370. include 'libraries/display_create_table.lib.php';
  371. $content = ob_get_contents();
  372. ob_end_clean();
  373. $response->addHTML($content);
  374. } // end if (Create Table dialog)
  375. ?>