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