Prepare for 5.0.4-dev
[phpmyadmin.git] / db_operations.php
blobc31418cb7bc49d9ebc58563cfddd4f299194c909
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
12 * @package PhpMyAdmin
14 declare(strict_types=1);
16 use PhpMyAdmin\CheckUserPrivileges;
17 use PhpMyAdmin\DatabaseInterface;
18 use PhpMyAdmin\Display\CreateTable;
19 use PhpMyAdmin\Message;
20 use PhpMyAdmin\Operations;
21 use PhpMyAdmin\Plugins;
22 use PhpMyAdmin\Plugins\Export\ExportSql;
23 use PhpMyAdmin\Relation;
24 use PhpMyAdmin\RelationCleanup;
25 use PhpMyAdmin\Response;
26 use PhpMyAdmin\Util;
28 if (! defined('ROOT_PATH')) {
29 define('ROOT_PATH', __DIR__ . DIRECTORY_SEPARATOR);
32 global $cfg, $db, $server, $url_query;
34 require_once ROOT_PATH . 'libraries/common.inc.php';
36 /** @var Response $response */
37 $response = $containerBuilder->get(Response::class);
39 /** @var DatabaseInterface $dbi */
40 $dbi = $containerBuilder->get(DatabaseInterface::class);
42 $checkUserPrivileges = new CheckUserPrivileges($dbi);
43 $checkUserPrivileges->getPrivileges();
45 $header = $response->getHeader();
46 $scripts = $header->getScripts();
47 $scripts->addFile('database/operations.js');
49 $sql_query = '';
51 /** @var Relation $relation */
52 $relation = $containerBuilder->get('relation');
53 $operations = new Operations($dbi, $relation);
54 $relationCleanup = new RelationCleanup($dbi, $relation);
56 /**
57 * Rename/move or copy database
59 if (strlen($db) > 0
60 && (! empty($_POST['db_rename']) || ! empty($_POST['db_copy']))
61 ) {
62 if (! empty($_POST['db_rename'])) {
63 $move = true;
64 } else {
65 $move = false;
68 if (! isset($_POST['newname']) || strlen($_POST['newname']) === 0) {
69 $message = Message::error(__('The database name is empty!'));
70 } else {
71 // lower_case_table_names=1 `DB` becomes `db`
72 if ($dbi->getLowerCaseNames() === '1') {
73 $_POST['newname'] = mb_strtolower(
74 $_POST['newname']
78 if ($_POST['newname'] === $_REQUEST['db']) {
79 $message = Message::error(
80 __('Cannot copy database to the same name. Change the name and try again.')
82 } else {
83 $_error = false;
84 if ($move || ! empty($_POST['create_database_before_copying'])) {
85 $operations->createDbBeforeCopy();
88 // here I don't use DELIMITER because it's not part of the
89 // language; I have to send each statement one by one
91 // to avoid selecting alternatively the current and new db
92 // we would need to modify the CREATE definitions to qualify
93 // the db name
94 $operations->runProcedureAndFunctionDefinitions($db);
96 // go back to current db, just in case
97 $dbi->selectDb($db);
99 $tables_full = $dbi->getTablesFull($db);
101 // remove all foreign key constraints, otherwise we can get errors
102 /** @var ExportSql $export_sql_plugin */
103 $export_sql_plugin = Plugins::getPlugin(
104 "export",
105 "sql",
106 'libraries/classes/Plugins/Export/',
108 'single_table' => isset($single_table),
109 'export_type' => 'database',
113 // create stand-in tables for views
114 $views = $operations->getViewsAndCreateSqlViewStandIn(
115 $tables_full,
116 $export_sql_plugin,
120 // copy tables
121 $sqlConstratints = $operations->copyTables(
122 $tables_full,
123 $move,
127 // handle the views
128 if (! $_error) {
129 $operations->handleTheViews($views, $move, $db);
131 unset($views);
133 // now that all tables exist, create all the accumulated constraints
134 if (! $_error && count($sqlConstratints) > 0) {
135 $operations->createAllAccumulatedConstraints($sqlConstratints);
137 unset($sqlConstratints);
139 if ($dbi->getVersion() >= 50100) {
140 // here DELIMITER is not used because it's not part of the
141 // language; each statement is sent one by one
143 $operations->runEventDefinitionsForDb($db);
146 // go back to current db, just in case
147 $dbi->selectDb($db);
149 // Duplicate the bookmarks for this db (done once for each db)
150 $operations->duplicateBookmarks($_error, $db);
152 if (! $_error && $move) {
153 if (isset($_POST['adjust_privileges'])
154 && ! empty($_POST['adjust_privileges'])
156 $operations->adjustPrivilegesMoveDb($db, $_POST['newname']);
160 * cleanup pmadb stuff for this db
162 $relationCleanup->database($db);
164 // if someday the RENAME DATABASE reappears, do not DROP
165 $local_query = 'DROP DATABASE '
166 . Util::backquote($db) . ';';
167 $sql_query .= "\n" . $local_query;
168 $dbi->query($local_query);
170 $message = Message::success(
171 __('Database %1$s has been renamed to %2$s.')
173 $message->addParam($db);
174 $message->addParam($_POST['newname']);
175 } elseif (! $_error) {
176 if (isset($_POST['adjust_privileges'])
177 && ! empty($_POST['adjust_privileges'])
179 $operations->adjustPrivilegesCopyDb($db, $_POST['newname']);
182 $message = Message::success(
183 __('Database %1$s has been copied to %2$s.')
185 $message->addParam($db);
186 $message->addParam($_POST['newname']);
187 } else {
188 $message = Message::error();
190 $reload = true;
192 /* Change database to be used */
193 if (! $_error && $move) {
194 $db = $_POST['newname'];
195 } elseif (! $_error) {
196 if (isset($_POST['switch_to_new'])
197 && $_POST['switch_to_new'] == 'true'
199 $_SESSION['pma_switch_to_new'] = true;
200 $db = $_POST['newname'];
201 } else {
202 $_SESSION['pma_switch_to_new'] = false;
209 * Database has been successfully renamed/moved. If in an Ajax request,
210 * generate the output with {@link PhpMyAdmin\Response} and exit
212 if ($response->isAjax()) {
213 $response->setRequestStatus($message->isSuccess());
214 $response->addJSON('message', $message);
215 $response->addJSON('newname', $_POST['newname']);
216 $response->addJSON(
217 'sql_query',
218 Util::getMessage(null, $sql_query)
220 $response->addJSON('db', $db);
221 exit;
226 * Settings for relations stuff
228 $cfgRelation = $relation->getRelationsParam();
231 * Check if comments were updated
232 * (must be done before displaying the menu tabs)
234 if (isset($_POST['comment'])) {
235 $relation->setDbComment($db, $_POST['comment']);
238 require ROOT_PATH . 'libraries/db_common.inc.php';
239 $url_query .= '&amp;goto=db_operations.php';
241 // Gets the database structure
242 $sub_part = '_structure';
244 list(
245 $tables,
246 $num_tables,
247 $total_num_tables,
248 $sub_part,
249 $is_show_stats,
250 $db_is_system_schema,
251 $tooltip_truename,
252 $tooltip_aliasname,
253 $pos
254 ) = Util::getDbInfo($db, $sub_part === null ? '' : $sub_part);
256 echo "\n";
258 if (isset($message)) {
259 echo Util::getMessage($message, $sql_query);
260 unset($message);
263 $db_collation = $dbi->getDbCollation($db);
264 $is_information_schema = $dbi->isSystemSchema($db);
266 if (! $is_information_schema) {
267 if ($cfgRelation['commwork']) {
269 * database comment
271 $response->addHTML($operations->getHtmlForDatabaseComment($db));
274 $response->addHTML('<div>');
275 $response->addHTML(CreateTable::getHtml($db));
276 $response->addHTML('</div>');
279 * rename database
281 if ($db != 'mysql') {
282 $response->addHTML($operations->getHtmlForRenameDatabase($db, $db_collation));
285 // Drop link if allowed
286 // Don't even try to drop information_schema.
287 // You won't be able to. Believe me. You won't.
288 // Don't allow to easily drop mysql database, RFE #1327514.
289 if (($dbi->isSuperuser() || $cfg['AllowUserDropDatabase'])
290 && ! $db_is_system_schema
291 && $db != 'mysql'
293 $response->addHTML($operations->getHtmlForDropDatabaseLink($db));
296 * Copy database
298 $response->addHTML($operations->getHtmlForCopyDatabase($db, $db_collation));
301 * Change database charset
303 $response->addHTML($operations->getHtmlForChangeDatabaseCharset($db, $db_collation));
305 if (! $cfgRelation['allworks']
306 && $cfg['PmaNoRelation_DisableWarning'] == false
308 $message = Message::notice(
310 'The phpMyAdmin configuration storage has been deactivated. ' .
311 '%sFind out why%s.'
314 $message->addParamHtml('<a href="./chk_rel.php" data-post="' . $url_query . '">');
315 $message->addParamHtml('</a>');
316 /* Show error if user has configured something, notice elsewhere */
317 if (! empty($cfg['Servers'][$server]['pmadb'])) {
318 $message->isError(true);
320 } // end if
321 } // end if (!$is_information_schema)