db_operations.php 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * handles miscellaneous db operations:
  5. * - move/rename
  6. * - copy
  7. * - changing collation
  8. * - changing comment
  9. * - adding tables
  10. * - viewing PDF schemas
  11. *
  12. * @package PhpMyAdmin
  13. */
  14. use PhpMyAdmin\DatabaseInterface;
  15. use PhpMyAdmin\Display\CreateTable;
  16. use PhpMyAdmin\Message;
  17. use PhpMyAdmin\Operations;
  18. use PhpMyAdmin\Plugins;
  19. use PhpMyAdmin\Plugins\Export\ExportSql;
  20. use PhpMyAdmin\Relation;
  21. use PhpMyAdmin\RelationCleanup;
  22. use PhpMyAdmin\Response;
  23. use PhpMyAdmin\Util;
  24. /**
  25. * requirements
  26. */
  27. require_once 'libraries/common.inc.php';
  28. /**
  29. * functions implementation for this script
  30. */
  31. require_once 'libraries/check_user_privileges.inc.php';
  32. // add a javascript file for jQuery functions to handle Ajax actions
  33. $response = Response::getInstance();
  34. $header = $response->getHeader();
  35. $scripts = $header->getScripts();
  36. $scripts->addFile('db_operations.js');
  37. $sql_query = '';
  38. $operations = new Operations();
  39. /**
  40. * Rename/move or copy database
  41. */
  42. if (strlen($GLOBALS['db']) > 0
  43. && (! empty($_POST['db_rename']) || ! empty($_POST['db_copy']))
  44. ) {
  45. if (! empty($_POST['db_rename'])) {
  46. $move = true;
  47. } else {
  48. $move = false;
  49. }
  50. if (! isset($_POST['newname']) || strlen($_POST['newname']) === 0) {
  51. $message = Message::error(__('The database name is empty!'));
  52. } else {
  53. // lower_case_table_names=1 `DB` becomes `db`
  54. if ($GLOBALS['dbi']->getLowerCaseNames() === '1') {
  55. $_POST['newname'] = mb_strtolower(
  56. $_POST['newname']
  57. );
  58. }
  59. if ($_POST['newname'] === $_REQUEST['db']) {
  60. $message = Message::error(
  61. __('Cannot copy database to the same name. Change the name and try again.')
  62. );
  63. } else {
  64. $_error = false;
  65. if ($move || ! empty($_POST['create_database_before_copying'])) {
  66. $operations->createDbBeforeCopy();
  67. }
  68. // here I don't use DELIMITER because it's not part of the
  69. // language; I have to send each statement one by one
  70. // to avoid selecting alternatively the current and new db
  71. // we would need to modify the CREATE definitions to qualify
  72. // the db name
  73. $operations->runProcedureAndFunctionDefinitions($GLOBALS['db']);
  74. // go back to current db, just in case
  75. $GLOBALS['dbi']->selectDb($GLOBALS['db']);
  76. $tables_full = $GLOBALS['dbi']->getTablesFull($GLOBALS['db']);
  77. // remove all foreign key constraints, otherwise we can get errors
  78. /* @var $export_sql_plugin ExportSql */
  79. $export_sql_plugin = Plugins::getPlugin(
  80. "export",
  81. "sql",
  82. 'libraries/classes/Plugins/Export/',
  83. array(
  84. 'single_table' => isset($single_table),
  85. 'export_type' => 'database'
  86. )
  87. );
  88. // create stand-in tables for views
  89. $views = $operations->getViewsAndCreateSqlViewStandIn(
  90. $tables_full, $export_sql_plugin, $GLOBALS['db']
  91. );
  92. // copy tables
  93. $sqlConstratints = $operations->copyTables(
  94. $tables_full, $move, $GLOBALS['db']
  95. );
  96. // handle the views
  97. if (! $_error) {
  98. $operations->handleTheViews($views, $move, $GLOBALS['db']);
  99. }
  100. unset($views);
  101. // now that all tables exist, create all the accumulated constraints
  102. if (! $_error && count($sqlConstratints) > 0) {
  103. $operations->createAllAccumulatedConstraints($sqlConstratints);
  104. }
  105. unset($sqlConstratints);
  106. if ($GLOBALS['dbi']->getVersion() >= 50100) {
  107. // here DELIMITER is not used because it's not part of the
  108. // language; each statement is sent one by one
  109. $operations->runEventDefinitionsForDb($GLOBALS['db']);
  110. }
  111. // go back to current db, just in case
  112. $GLOBALS['dbi']->selectDb($GLOBALS['db']);
  113. // Duplicate the bookmarks for this db (done once for each db)
  114. $operations->duplicateBookmarks($_error, $GLOBALS['db']);
  115. if (! $_error && $move) {
  116. if (isset($_POST['adjust_privileges'])
  117. && ! empty($_POST['adjust_privileges'])
  118. ) {
  119. $operations->adjustPrivilegesMoveDb($GLOBALS['db'], $_POST['newname']);
  120. }
  121. /**
  122. * cleanup pmadb stuff for this db
  123. */
  124. RelationCleanup::database($GLOBALS['db']);
  125. // if someday the RENAME DATABASE reappears, do not DROP
  126. $local_query = 'DROP DATABASE '
  127. . Util::backquote($GLOBALS['db']) . ';';
  128. $sql_query .= "\n" . $local_query;
  129. $GLOBALS['dbi']->query($local_query);
  130. $message = Message::success(
  131. __('Database %1$s has been renamed to %2$s.')
  132. );
  133. $message->addParam($GLOBALS['db']);
  134. $message->addParam($_POST['newname']);
  135. } elseif (! $_error) {
  136. if (isset($_POST['adjust_privileges'])
  137. && ! empty($_POST['adjust_privileges'])
  138. ) {
  139. $operations->adjustPrivilegesCopyDb($GLOBALS['db'], $_POST['newname']);
  140. }
  141. $message = Message::success(
  142. __('Database %1$s has been copied to %2$s.')
  143. );
  144. $message->addParam($GLOBALS['db']);
  145. $message->addParam($_POST['newname']);
  146. } else {
  147. $message = Message::error();
  148. }
  149. $reload = true;
  150. /* Change database to be used */
  151. if (! $_error && $move) {
  152. $GLOBALS['db'] = $_POST['newname'];
  153. } elseif (! $_error) {
  154. if (isset($_POST['switch_to_new'])
  155. && $_POST['switch_to_new'] == 'true'
  156. ) {
  157. $_SESSION['pma_switch_to_new'] = true;
  158. $GLOBALS['db'] = $_POST['newname'];
  159. } else {
  160. $_SESSION['pma_switch_to_new'] = false;
  161. }
  162. }
  163. }
  164. }
  165. /**
  166. * Database has been successfully renamed/moved. If in an Ajax request,
  167. * generate the output with {@link PhpMyAdmin\Response} and exit
  168. */
  169. if ($response->isAjax()) {
  170. $response->setRequestStatus($message->isSuccess());
  171. $response->addJSON('message', $message);
  172. $response->addJSON('newname', $_POST['newname']);
  173. $response->addJSON(
  174. 'sql_query',
  175. Util::getMessage(null, $sql_query)
  176. );
  177. $response->addJSON('db', $GLOBALS['db']);
  178. exit;
  179. }
  180. }
  181. /**
  182. * Settings for relations stuff
  183. */
  184. $relation = new Relation();
  185. $cfgRelation = $relation->getRelationsParam();
  186. /**
  187. * Check if comments were updated
  188. * (must be done before displaying the menu tabs)
  189. */
  190. if (isset($_POST['comment'])) {
  191. $relation->setDbComment($GLOBALS['db'], $_POST['comment']);
  192. }
  193. require 'libraries/db_common.inc.php';
  194. $url_query .= '&amp;goto=db_operations.php';
  195. // Gets the database structure
  196. $sub_part = '_structure';
  197. list(
  198. $tables,
  199. $num_tables,
  200. $total_num_tables,
  201. $sub_part,
  202. $is_show_stats,
  203. $db_is_system_schema,
  204. $tooltip_truename,
  205. $tooltip_aliasname,
  206. $pos
  207. ) = Util::getDbInfo($db, isset($sub_part) ? $sub_part : '');
  208. echo "\n";
  209. if (isset($message)) {
  210. echo Util::getMessage($message, $sql_query);
  211. unset($message);
  212. }
  213. $db_collation = $GLOBALS['dbi']->getDbCollation($GLOBALS['db']);
  214. $is_information_schema = $GLOBALS['dbi']->isSystemSchema($GLOBALS['db']);
  215. if (!$is_information_schema) {
  216. if ($cfgRelation['commwork']) {
  217. /**
  218. * database comment
  219. */
  220. $response->addHTML($operations->getHtmlForDatabaseComment($GLOBALS['db']));
  221. }
  222. $response->addHTML('<div>');
  223. $response->addHTML(CreateTable::getHtml($db));
  224. $response->addHTML('</div>');
  225. /**
  226. * rename database
  227. */
  228. if ($GLOBALS['db'] != 'mysql') {
  229. $response->addHTML($operations->getHtmlForRenameDatabase($GLOBALS['db'], $db_collation));
  230. }
  231. // Drop link if allowed
  232. // Don't even try to drop information_schema.
  233. // You won't be able to. Believe me. You won't.
  234. // Don't allow to easily drop mysql database, RFE #1327514.
  235. if (($GLOBALS['dbi']->isSuperuser() || $GLOBALS['cfg']['AllowUserDropDatabase'])
  236. && ! $db_is_system_schema
  237. && $GLOBALS['db'] != 'mysql'
  238. ) {
  239. $response->addHTML($operations->getHtmlForDropDatabaseLink($GLOBALS['db']));
  240. }
  241. /**
  242. * Copy database
  243. */
  244. $response->addHTML($operations->getHtmlForCopyDatabase($GLOBALS['db'], $db_collation));
  245. /**
  246. * Change database charset
  247. */
  248. $response->addHTML($operations->getHtmlForChangeDatabaseCharset($GLOBALS['db'], $db_collation));
  249. if (! $cfgRelation['allworks']
  250. && $cfg['PmaNoRelation_DisableWarning'] == false
  251. ) {
  252. $message = Message::notice(
  253. __(
  254. 'The phpMyAdmin configuration storage has been deactivated. ' .
  255. '%sFind out why%s.'
  256. )
  257. );
  258. $message->addParamHtml('<a href="./chk_rel.php" data-post="' . $url_query . '">');
  259. $message->addParamHtml('</a>');
  260. /* Show error if user has configured something, notice elsewhere */
  261. if (!empty($cfg['Servers'][$server]['pmadb'])) {
  262. $message->isError(true);
  263. }
  264. } // end if
  265. } // end if (!$is_information_schema)