1 | <?php |
||||
2 | /* vim: set expandtab sw=4 ts=4 sts=4: */ |
||||
3 | /** |
||||
4 | * Holds the PhpMyAdmin\Controllers\Table\TableStructureController |
||||
5 | * |
||||
6 | * @package PhpMyAdmin\Controllers |
||||
7 | */ |
||||
8 | declare(strict_types=1); |
||||
9 | |||||
10 | namespace PhpMyAdmin\Controllers\Table; |
||||
11 | |||||
12 | use PhpMyAdmin\CentralColumns; |
||||
13 | use PhpMyAdmin\Config\PageSettings; |
||||
14 | use PhpMyAdmin\Controllers\TableController; |
||||
15 | use PhpMyAdmin\Core; |
||||
16 | use PhpMyAdmin\CreateAddField; |
||||
17 | use PhpMyAdmin\Index; |
||||
18 | use PhpMyAdmin\Message; |
||||
19 | use PhpMyAdmin\ParseAnalyze; |
||||
20 | use PhpMyAdmin\Partition; |
||||
21 | use PhpMyAdmin\Relation; |
||||
22 | use PhpMyAdmin\Sql; |
||||
23 | use PhpMyAdmin\SqlParser\Context; |
||||
24 | use PhpMyAdmin\SqlParser\Parser; |
||||
25 | use PhpMyAdmin\SqlParser\Statements\CreateStatement; |
||||
26 | use PhpMyAdmin\Table; |
||||
27 | use PhpMyAdmin\Template; |
||||
28 | use PhpMyAdmin\Tracker; |
||||
29 | use PhpMyAdmin\Transformations; |
||||
30 | use PhpMyAdmin\Url; |
||||
31 | use PhpMyAdmin\Util; |
||||
32 | |||||
33 | /** |
||||
34 | * Handles table structure logic |
||||
35 | * |
||||
36 | * @package PhpMyAdmin\Controllers |
||||
37 | */ |
||||
38 | class TableStructureController extends TableController |
||||
39 | { |
||||
40 | /** |
||||
41 | * @var Table The table object |
||||
42 | */ |
||||
43 | protected $table_obj; |
||||
44 | /** |
||||
45 | * @var string The URL query string |
||||
46 | */ |
||||
47 | protected $_url_query; |
||||
48 | /** |
||||
49 | * @var bool DB is information_schema |
||||
50 | */ |
||||
51 | protected $_db_is_system_schema; |
||||
52 | /** |
||||
53 | * @var bool Table is a view |
||||
54 | */ |
||||
55 | protected $_tbl_is_view; |
||||
56 | /** |
||||
57 | * @var string Table storage engine |
||||
58 | */ |
||||
59 | protected $_tbl_storage_engine; |
||||
60 | /** |
||||
61 | * @var int Number of rows |
||||
62 | */ |
||||
63 | protected $_table_info_num_rows; |
||||
64 | /** |
||||
65 | * @var string Table collation |
||||
66 | */ |
||||
67 | protected $_tbl_collation; |
||||
68 | /** |
||||
69 | * @var array Show table info |
||||
70 | */ |
||||
71 | protected $_showtable; |
||||
72 | |||||
73 | /** |
||||
74 | * @var CreateAddField |
||||
75 | */ |
||||
76 | private $createAddField; |
||||
77 | |||||
78 | /** |
||||
79 | * @var Relation |
||||
80 | */ |
||||
81 | private $relation; |
||||
82 | |||||
83 | /** |
||||
84 | * @var Transformations |
||||
85 | */ |
||||
86 | private $transformations; |
||||
87 | |||||
88 | /** |
||||
89 | * TableStructureController constructor |
||||
90 | * |
||||
91 | * @param \PhpMyAdmin\Response $response Response object |
||||
92 | * @param \PhpMyAdmin\DatabaseInterface $dbi DatabaseInterface object |
||||
93 | * @param string $db Database name |
||||
94 | * @param string $table Table name |
||||
95 | * @param string $type Indicate the db_structure or tbl_structure |
||||
96 | * @param int $num_tables Number of tables |
||||
97 | * @param int $pos Current position in the list |
||||
98 | * @param bool $db_is_system_schema DB is information_schema |
||||
99 | * @param int $total_num_tables Number of tables |
||||
100 | * @param array $tables Tables in the DB |
||||
101 | * @param bool $is_show_stats Whether stats show or not |
||||
102 | * @param bool $tbl_is_view Table is a view |
||||
103 | * @param string $tbl_storage_engine Table storage engine |
||||
104 | * @param int $table_info_num_rows Number of rows |
||||
105 | * @param string $tbl_collation Table collation |
||||
106 | * @param array $showtable Show table info |
||||
107 | */ |
||||
108 | public function __construct( |
||||
109 | $response, |
||||
110 | $dbi, |
||||
111 | $db, |
||||
112 | $table, |
||||
113 | $type, |
||||
114 | $num_tables, |
||||
115 | $pos, |
||||
116 | $db_is_system_schema, |
||||
117 | $total_num_tables, |
||||
118 | $tables, |
||||
119 | $is_show_stats, |
||||
120 | $tbl_is_view, |
||||
121 | $tbl_storage_engine, |
||||
122 | $table_info_num_rows, |
||||
123 | $tbl_collation, |
||||
124 | $showtable |
||||
125 | ) { |
||||
126 | parent::__construct($response, $dbi, $db, $table); |
||||
127 | |||||
128 | $this->_db_is_system_schema = $db_is_system_schema; |
||||
129 | $this->_url_query = Url::getCommonRaw(['db' => $db, 'table' => $table]); |
||||
130 | $this->_tbl_is_view = $tbl_is_view; |
||||
131 | $this->_tbl_storage_engine = $tbl_storage_engine; |
||||
132 | $this->_table_info_num_rows = $table_info_num_rows; |
||||
133 | $this->_tbl_collation = $tbl_collation; |
||||
134 | $this->_showtable = $showtable; |
||||
135 | $this->table_obj = $this->dbi->getTable($this->db, $this->table); |
||||
136 | |||||
137 | $this->createAddField = new CreateAddField($dbi); |
||||
138 | $this->relation = new Relation($dbi); |
||||
139 | $this->transformations = new Transformations(); |
||||
140 | } |
||||
141 | |||||
142 | /** |
||||
143 | * Index action |
||||
144 | * |
||||
145 | * @return void |
||||
146 | */ |
||||
147 | public function indexAction() |
||||
148 | { |
||||
149 | PageSettings::showGroup('TableStructure'); |
||||
150 | |||||
151 | /** |
||||
152 | * Function implementations for this script |
||||
153 | */ |
||||
154 | include_once 'libraries/check_user_privileges.inc.php'; |
||||
155 | |||||
156 | $this->response->getHeader()->getScripts()->addFiles( |
||||
157 | [ |
||||
158 | 'tbl_structure.js', |
||||
159 | 'indexes.js' |
||||
160 | ] |
||||
161 | ); |
||||
162 | |||||
163 | /** |
||||
164 | * Handle column moving |
||||
165 | */ |
||||
166 | if (isset($_REQUEST['move_columns']) |
||||
167 | && is_array($_REQUEST['move_columns']) |
||||
168 | && $this->response->isAjax() |
||||
169 | ) { |
||||
170 | $this->moveColumns(); |
||||
171 | return; |
||||
172 | } |
||||
173 | |||||
174 | /** |
||||
175 | * handle MySQL reserved words columns check |
||||
176 | */ |
||||
177 | if (isset($_REQUEST['reserved_word_check'])) { |
||||
178 | if ($GLOBALS['cfg']['ReservedWordDisableWarning'] === false) { |
||||
179 | $columns_names = $_REQUEST['field_name']; |
||||
180 | $reserved_keywords_names = []; |
||||
181 | foreach ($columns_names as $column) { |
||||
182 | if (Context::isKeyword(trim($column), true)) { |
||||
183 | $reserved_keywords_names[] = trim($column); |
||||
184 | } |
||||
185 | } |
||||
186 | if (Context::isKeyword(trim($this->table), true)) { |
||||
187 | $reserved_keywords_names[] = trim($this->table); |
||||
188 | } |
||||
189 | if (count($reserved_keywords_names) == 0) { |
||||
190 | $this->response->setRequestStatus(false); |
||||
191 | } |
||||
192 | $this->response->addJSON( |
||||
193 | 'message', |
||||
194 | sprintf( |
||||
195 | _ngettext( |
||||
196 | 'The name \'%s\' is a MySQL reserved keyword.', |
||||
197 | 'The names \'%s\' are MySQL reserved keywords.', |
||||
198 | count($reserved_keywords_names) |
||||
199 | ), |
||||
200 | implode(',', $reserved_keywords_names) |
||||
201 | ) |
||||
202 | ); |
||||
203 | } else { |
||||
204 | $this->response->setRequestStatus(false); |
||||
205 | } |
||||
206 | return; |
||||
207 | } |
||||
208 | /** |
||||
209 | * A click on Change has been made for one column |
||||
210 | */ |
||||
211 | if (isset($_REQUEST['change_column'])) { |
||||
212 | $this->displayHtmlForColumnChange(null, 'tbl_structure.php'); |
||||
213 | return; |
||||
214 | } |
||||
215 | |||||
216 | /** |
||||
217 | * Adding or editing partitioning of the table |
||||
218 | */ |
||||
219 | if (isset($_REQUEST['edit_partitioning']) |
||||
220 | && ! isset($_REQUEST['save_partitioning']) |
||||
221 | ) { |
||||
222 | $this->displayHtmlForPartitionChange(); |
||||
223 | return; |
||||
224 | } |
||||
225 | |||||
226 | /** |
||||
227 | * handle multiple field commands if required |
||||
228 | * |
||||
229 | * submit_mult_*_x comes from IE if <input type="img" ...> is used |
||||
230 | */ |
||||
231 | $submit_mult = $this->getMultipleFieldCommandType(); |
||||
232 | |||||
233 | if (! empty($submit_mult)) { |
||||
234 | if (isset($_REQUEST['selected_fld'])) { |
||||
235 | if ($submit_mult == 'browse') { |
||||
236 | // browsing the table displaying only selected columns |
||||
237 | $this->displayTableBrowseForSelectedColumns( |
||||
238 | $GLOBALS['goto'], |
||||
239 | $GLOBALS['pmaThemeImage'] |
||||
240 | ); |
||||
241 | } else { |
||||
242 | // handle multiple field commands |
||||
243 | // handle confirmation of deleting multiple columns |
||||
244 | $action = 'tbl_structure.php'; |
||||
245 | $GLOBALS['selected'] = $_REQUEST['selected_fld']; |
||||
246 | list( |
||||
247 | $what_ret, $query_type_ret, $is_unset_submit_mult, |
||||
248 | $mult_btn_ret, $centralColsError |
||||
249 | ) |
||||
250 | = $this->getDataForSubmitMult( |
||||
251 | $submit_mult, |
||||
252 | $_REQUEST['selected_fld'], |
||||
253 | $action |
||||
254 | ); |
||||
255 | //update the existing variables |
||||
256 | // todo: refactor mult_submits.inc.php such as |
||||
257 | // below globals are not needed anymore |
||||
258 | if (isset($what_ret)) { |
||||
259 | $GLOBALS['what'] = $what_ret; |
||||
260 | global $what; |
||||
261 | } |
||||
262 | if (isset($query_type_ret)) { |
||||
263 | $GLOBALS['query_type'] = $query_type_ret; |
||||
264 | global $query_type; |
||||
265 | } |
||||
266 | if ($is_unset_submit_mult) { |
||||
267 | unset($submit_mult); |
||||
268 | } |
||||
269 | if (isset($mult_btn_ret)) { |
||||
270 | $GLOBALS['mult_btn'] = $mult_btn_ret; |
||||
271 | global $mult_btn; |
||||
272 | } |
||||
273 | include 'libraries/mult_submits.inc.php'; |
||||
274 | /** |
||||
275 | * if $submit_mult == 'change', execution will have stopped |
||||
276 | * at this point |
||||
277 | */ |
||||
278 | if (empty($message)) { |
||||
279 | $message = Message::success(); |
||||
280 | } |
||||
281 | $this->response->addHTML( |
||||
282 | Util::getMessage($message, $sql_query) |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||||
283 | ); |
||||
284 | } |
||||
285 | } else { |
||||
286 | $this->response->setRequestStatus(false); |
||||
287 | $this->response->addJSON('message', __('No column selected.')); |
||||
288 | } |
||||
289 | } |
||||
290 | |||||
291 | /** |
||||
292 | * Modifications have been submitted -> updates the table |
||||
293 | */ |
||||
294 | if (isset($_REQUEST['do_save_data'])) { |
||||
295 | $regenerate = $this->updateColumns(); |
||||
296 | if ($regenerate) { |
||||
297 | // This happens when updating failed |
||||
298 | // @todo: do something appropriate |
||||
299 | } else { |
||||
300 | // continue to show the table's structure |
||||
301 | unset($_REQUEST['selected']); |
||||
302 | } |
||||
303 | } |
||||
304 | |||||
305 | /** |
||||
306 | * Modifications to the partitioning have been submitted -> updates the table |
||||
307 | */ |
||||
308 | if (isset($_REQUEST['save_partitioning'])) { |
||||
309 | $this->updatePartitioning(); |
||||
310 | } |
||||
311 | |||||
312 | /** |
||||
313 | * Adding indexes |
||||
314 | */ |
||||
315 | if (isset($_REQUEST['add_key']) |
||||
316 | || isset($_REQUEST['partition_maintenance']) |
||||
317 | ) { |
||||
318 | //todo: set some variables for sql.php include, to be eliminated |
||||
319 | //after refactoring sql.php |
||||
320 | $db = $this->db; |
||||
321 | $table = $this->table; |
||||
322 | $sql_query = $GLOBALS['sql_query']; |
||||
323 | $cfg = $GLOBALS['cfg']; |
||||
324 | $pmaThemeImage = $GLOBALS['pmaThemeImage']; |
||||
325 | include 'sql.php'; |
||||
326 | $GLOBALS['reload'] = true; |
||||
327 | } |
||||
328 | |||||
329 | /** |
||||
330 | * Gets the relation settings |
||||
331 | */ |
||||
332 | $cfgRelation = $this->relation->getRelationsParam(); |
||||
333 | |||||
334 | /** |
||||
335 | * Runs common work |
||||
336 | */ |
||||
337 | // set db, table references, for require_once that follows |
||||
338 | // got to be eliminated in long run |
||||
339 | $db = &$this->db; |
||||
340 | $table = &$this->table; |
||||
341 | $url_params = []; |
||||
342 | include_once 'libraries/tbl_common.inc.php'; |
||||
343 | $this->_db_is_system_schema = $db_is_system_schema; |
||||
344 | $this->_url_query = Url::getCommonRaw([ |
||||
345 | 'db' => $db, |
||||
346 | 'table' => $table, |
||||
347 | 'goto' => 'tbl_structure.php', |
||||
348 | 'back' => 'tbl_structure.php', |
||||
349 | ]); |
||||
350 | /* The url_params array is initialized in above include */ |
||||
351 | $url_params['goto'] = 'tbl_structure.php'; |
||||
352 | $url_params['back'] = 'tbl_structure.php'; |
||||
353 | |||||
354 | // 2. Gets table keys and retains them |
||||
355 | // @todo should be: $server->db($db)->table($table)->primary() |
||||
356 | $primary = Index::getPrimary($this->table, $this->db); |
||||
357 | $columns_with_index = $this->dbi |
||||
358 | ->getTable($this->db, $this->table) |
||||
359 | ->getColumnsWithIndex( |
||||
360 | Index::UNIQUE | Index::INDEX | Index::SPATIAL |
||||
361 | | Index::FULLTEXT |
||||
362 | ); |
||||
363 | $columns_with_unique_index = $this->dbi |
||||
364 | ->getTable($this->db, $this->table) |
||||
365 | ->getColumnsWithIndex(Index::UNIQUE); |
||||
366 | |||||
367 | // 3. Get fields |
||||
368 | $fields = (array)$this->dbi->getColumns( |
||||
369 | $this->db, |
||||
370 | $this->table, |
||||
371 | null, |
||||
372 | true |
||||
373 | ); |
||||
374 | |||||
375 | //display table structure |
||||
376 | $this->response->addHTML( |
||||
377 | $this->displayStructure( |
||||
378 | $cfgRelation, |
||||
379 | $columns_with_unique_index, |
||||
380 | $url_params, |
||||
381 | $primary, |
||||
382 | $fields, |
||||
383 | $columns_with_index |
||||
384 | ) |
||||
385 | ); |
||||
386 | } |
||||
387 | |||||
388 | /** |
||||
389 | * Moves columns in the table's structure based on $_REQUEST |
||||
390 | * |
||||
391 | * @return void |
||||
392 | */ |
||||
393 | protected function moveColumns() |
||||
394 | { |
||||
395 | $this->dbi->selectDb($this->db); |
||||
396 | |||||
397 | /* |
||||
398 | * load the definitions for all columns |
||||
399 | */ |
||||
400 | $columns = $this->dbi->getColumnsFull($this->db, $this->table); |
||||
401 | $column_names = array_keys($columns); |
||||
402 | $changes = []; |
||||
403 | |||||
404 | // move columns from first to last |
||||
405 | for ($i = 0, $l = count($_REQUEST['move_columns']); $i < $l; $i++) { |
||||
406 | $column = $_REQUEST['move_columns'][$i]; |
||||
407 | // is this column already correctly placed? |
||||
408 | if ($column_names[$i] == $column) { |
||||
409 | continue; |
||||
410 | } |
||||
411 | |||||
412 | // it is not, let's move it to index $i |
||||
413 | $data = $columns[$column]; |
||||
414 | $extracted_columnspec = Util::extractColumnSpec($data['Type']); |
||||
415 | if (isset($data['Extra']) |
||||
416 | && $data['Extra'] == 'on update CURRENT_TIMESTAMP' |
||||
417 | ) { |
||||
418 | $extracted_columnspec['attribute'] = $data['Extra']; |
||||
419 | unset($data['Extra']); |
||||
420 | } |
||||
421 | $current_timestamp = ($data['Type'] == 'timestamp' |
||||
422 | || $data['Type'] == 'datetime') |
||||
423 | && ($data['Default'] == 'CURRENT_TIMESTAMP' |
||||
424 | || $data['Default'] == 'current_timestamp()'); |
||||
425 | |||||
426 | if ($data['Null'] === 'YES' && $data['Default'] === null) { |
||||
427 | $default_type = 'NULL'; |
||||
428 | } elseif ($current_timestamp) { |
||||
429 | $default_type = 'CURRENT_TIMESTAMP'; |
||||
430 | } elseif ($data['Default'] === null) { |
||||
431 | $default_type = 'NONE'; |
||||
432 | } else { |
||||
433 | $default_type = 'USER_DEFINED'; |
||||
434 | } |
||||
435 | |||||
436 | $virtual = [ |
||||
437 | 'VIRTUAL', 'PERSISTENT', 'VIRTUAL GENERATED', 'STORED GENERATED' |
||||
438 | ]; |
||||
439 | $data['Virtuality'] = ''; |
||||
440 | $data['Expression'] = ''; |
||||
441 | if (isset($data['Extra']) && in_array($data['Extra'], $virtual)) { |
||||
442 | $data['Virtuality'] = str_replace(' GENERATED', '', $data['Extra']); |
||||
443 | $expressions = $this->table->getColumnGenerationExpression($column); |
||||
444 | $data['Expression'] = $expressions[$column]; |
||||
445 | } |
||||
446 | |||||
447 | $changes[] = 'CHANGE ' . Table::generateAlter( |
||||
448 | $column, |
||||
449 | $column, |
||||
450 | mb_strtoupper($extracted_columnspec['type']), |
||||
451 | $extracted_columnspec['spec_in_brackets'], |
||||
452 | $extracted_columnspec['attribute'], |
||||
453 | isset($data['Collation']) ? $data['Collation'] : '', |
||||
454 | $data['Null'] === 'YES' ? 'NULL' : 'NOT NULL', |
||||
455 | $default_type, |
||||
456 | $current_timestamp ? '' : $data['Default'], |
||||
457 | isset($data['Extra']) && $data['Extra'] !== '' ? $data['Extra'] |
||||
458 | : false, |
||||
459 | isset($data['COLUMN_COMMENT']) && $data['COLUMN_COMMENT'] !== '' |
||||
460 | ? $data['COLUMN_COMMENT'] : false, |
||||
461 | $data['Virtuality'], |
||||
462 | $data['Expression'], |
||||
463 | $i === 0 ? '-first' : $column_names[$i - 1] |
||||
464 | ); |
||||
465 | // update current column_names array, first delete old position |
||||
466 | for ($j = 0, $ll = count($column_names); $j < $ll; $j++) { |
||||
467 | if ($column_names[$j] == $column) { |
||||
468 | unset($column_names[$j]); |
||||
469 | } |
||||
470 | } |
||||
471 | // insert moved column |
||||
472 | array_splice($column_names, $i, 0, $column); |
||||
473 | } |
||||
474 | if (empty($changes) && !isset($_REQUEST['preview_sql'])) { // should never happen |
||||
475 | $this->response->setRequestStatus(false); |
||||
476 | return; |
||||
477 | } |
||||
478 | // query for moving the columns |
||||
479 | $sql_query = sprintf( |
||||
480 | 'ALTER TABLE %s %s', |
||||
481 | Util::backquote($this->table), |
||||
482 | implode(', ', $changes) |
||||
483 | ); |
||||
484 | |||||
485 | if (isset($_REQUEST['preview_sql'])) { // preview sql |
||||
486 | $this->response->addJSON( |
||||
487 | 'sql_data', |
||||
488 | $this->template->render('preview_sql', [ |
||||
489 | 'query_data' => $sql_query |
||||
490 | ]) |
||||
491 | ); |
||||
492 | } else { // move column |
||||
493 | $this->dbi->tryQuery($sql_query); |
||||
494 | $tmp_error = $this->dbi->getError(); |
||||
495 | if ($tmp_error) { |
||||
496 | $this->response->setRequestStatus(false); |
||||
497 | $this->response->addJSON('message', Message::error($tmp_error)); |
||||
498 | } else { |
||||
499 | $message = Message::success( |
||||
500 | __('The columns have been moved successfully.') |
||||
501 | ); |
||||
502 | $this->response->addJSON('message', $message); |
||||
503 | $this->response->addJSON('columns', $column_names); |
||||
504 | } |
||||
505 | } |
||||
506 | } |
||||
507 | |||||
508 | /** |
||||
509 | * Displays HTML for changing one or more columns |
||||
510 | * |
||||
511 | * @param array $selected the selected columns |
||||
512 | * @param string $action target script to call |
||||
513 | * |
||||
514 | * @return boolean true if error occurred |
||||
515 | * |
||||
516 | */ |
||||
517 | protected function displayHtmlForColumnChange($selected, $action) |
||||
518 | { |
||||
519 | // $selected comes from mult_submits.inc.php |
||||
520 | if (empty($selected)) { |
||||
521 | $selected[] = $_REQUEST['field']; |
||||
522 | $selected_cnt = 1; |
||||
523 | } else { // from a multiple submit |
||||
524 | $selected_cnt = count($selected); |
||||
525 | } |
||||
526 | |||||
527 | /** |
||||
528 | * @todo optimize in case of multiple fields to modify |
||||
529 | */ |
||||
530 | $fields_meta = []; |
||||
531 | for ($i = 0; $i < $selected_cnt; $i++) { |
||||
532 | $value = $this->dbi->getColumns( |
||||
533 | $this->db, |
||||
534 | $this->table, |
||||
535 | $selected[$i], |
||||
536 | true |
||||
537 | ); |
||||
538 | if (count($value) == 0) { |
||||
539 | $message = Message::error( |
||||
540 | __('Failed to get description of column %s!') |
||||
541 | ); |
||||
542 | $message->addParam($selected[$i]); |
||||
543 | $this->response->addHTML($message); |
||||
544 | } else { |
||||
545 | $fields_meta[] = $value; |
||||
546 | } |
||||
547 | } |
||||
548 | $num_fields = count($fields_meta); |
||||
549 | // set these globals because tbl_columns_definition_form.inc.php |
||||
550 | // verifies them |
||||
551 | // @todo: refactor tbl_columns_definition_form.inc.php so that it uses |
||||
552 | // protected function params |
||||
553 | $GLOBALS['action'] = $action; |
||||
554 | $GLOBALS['num_fields'] = $num_fields; |
||||
555 | |||||
556 | /** |
||||
557 | * Form for changing properties. |
||||
558 | */ |
||||
559 | include_once 'libraries/check_user_privileges.inc.php'; |
||||
560 | include 'libraries/tbl_columns_definition_form.inc.php'; |
||||
561 | } |
||||
562 | |||||
563 | /** |
||||
564 | * Displays HTML for partition change |
||||
565 | * |
||||
566 | * @return string HTML for partition change |
||||
567 | */ |
||||
568 | protected function displayHtmlForPartitionChange() |
||||
569 | { |
||||
570 | $partitionDetails = null; |
||||
571 | if (! isset($_REQUEST['partition_by'])) { |
||||
572 | $partitionDetails = $this->_extractPartitionDetails(); |
||||
573 | } |
||||
574 | |||||
575 | include 'libraries/tbl_partition_definition.inc.php'; |
||||
576 | $this->response->addHTML( |
||||
577 | $this->template->render('table/structure/partition_definition_form', [ |
||||
578 | 'db' => $this->db, |
||||
579 | 'table' => $this->table, |
||||
580 | 'partition_details' => $partitionDetails, |
||||
581 | ]) |
||||
582 | ); |
||||
583 | } |
||||
584 | |||||
585 | /** |
||||
586 | * Extracts partition details from CREATE TABLE statement |
||||
587 | * |
||||
588 | * @return array[] array of partition details |
||||
589 | */ |
||||
590 | private function _extractPartitionDetails() |
||||
591 | { |
||||
592 | $createTable = (new Table($this->table, $this->db))->showCreate(); |
||||
593 | if (! $createTable) { |
||||
594 | return null; |
||||
595 | } |
||||
596 | |||||
597 | $parser = new Parser($createTable); |
||||
598 | /** |
||||
599 | * @var CreateStatement $stmt |
||||
600 | */ |
||||
601 | $stmt = $parser->statements[0]; |
||||
602 | |||||
603 | $partitionDetails = []; |
||||
604 | |||||
605 | $partitionDetails['partition_by'] = ''; |
||||
606 | $partitionDetails['partition_expr'] = ''; |
||||
607 | $partitionDetails['partition_count'] = ''; |
||||
608 | |||||
609 | if (! empty($stmt->partitionBy)) { |
||||
610 | $openPos = strpos($stmt->partitionBy, "("); |
||||
611 | $closePos = strrpos($stmt->partitionBy, ")"); |
||||
612 | |||||
613 | $partitionDetails['partition_by'] |
||||
614 | = trim(substr($stmt->partitionBy, 0, $openPos)); |
||||
615 | $partitionDetails['partition_expr'] |
||||
616 | = trim(substr($stmt->partitionBy, $openPos + 1, $closePos - ($openPos + 1))); |
||||
617 | if (isset($stmt->partitionsNum)) { |
||||
618 | $count = $stmt->partitionsNum; |
||||
619 | } else { |
||||
620 | $count = count($stmt->partitions); |
||||
621 | } |
||||
622 | $partitionDetails['partition_count'] = $count; |
||||
623 | } |
||||
624 | |||||
625 | $partitionDetails['subpartition_by'] = ''; |
||||
626 | $partitionDetails['subpartition_expr'] = ''; |
||||
627 | $partitionDetails['subpartition_count'] = ''; |
||||
628 | |||||
629 | if (! empty($stmt->subpartitionBy)) { |
||||
630 | $openPos = strpos($stmt->subpartitionBy, "("); |
||||
631 | $closePos = strrpos($stmt->subpartitionBy, ")"); |
||||
632 | |||||
633 | $partitionDetails['subpartition_by'] |
||||
634 | = trim(substr($stmt->subpartitionBy, 0, $openPos)); |
||||
635 | $partitionDetails['subpartition_expr'] |
||||
636 | = trim(substr($stmt->subpartitionBy, $openPos + 1, $closePos - ($openPos + 1))); |
||||
637 | if (isset($stmt->subpartitionsNum)) { |
||||
638 | $count = $stmt->subpartitionsNum; |
||||
639 | } else { |
||||
640 | $count = count($stmt->partitions[0]->subpartitions); |
||||
641 | } |
||||
642 | $partitionDetails['subpartition_count'] = $count; |
||||
643 | } |
||||
644 | |||||
645 | // Only LIST and RANGE type parameters allow subpartitioning |
||||
646 | $partitionDetails['can_have_subpartitions'] |
||||
647 | = $partitionDetails['partition_count'] > 1 |
||||
648 | && ($partitionDetails['partition_by'] == 'RANGE' |
||||
649 | || $partitionDetails['partition_by'] == 'RANGE COLUMNS' |
||||
650 | || $partitionDetails['partition_by'] == 'LIST' |
||||
651 | || $partitionDetails['partition_by'] == 'LIST COLUMNS'); |
||||
652 | |||||
653 | // Values are specified only for LIST and RANGE type partitions |
||||
654 | $partitionDetails['value_enabled'] = isset($partitionDetails['partition_by']) |
||||
655 | && ($partitionDetails['partition_by'] == 'RANGE' |
||||
656 | || $partitionDetails['partition_by'] == 'RANGE COLUMNS' |
||||
657 | || $partitionDetails['partition_by'] == 'LIST' |
||||
658 | || $partitionDetails['partition_by'] == 'LIST COLUMNS'); |
||||
659 | |||||
660 | $partitionDetails['partitions'] = []; |
||||
661 | |||||
662 | for ($i = 0; $i < intval($partitionDetails['partition_count']); $i++) { |
||||
663 | if (! isset($stmt->partitions[$i])) { |
||||
664 | $partitionDetails['partitions'][$i] = [ |
||||
665 | 'name' => 'p' . $i, |
||||
666 | 'value_type' => '', |
||||
667 | 'value' => '', |
||||
668 | 'engine' => '', |
||||
669 | 'comment' => '', |
||||
670 | 'data_directory' => '', |
||||
671 | 'index_directory' => '', |
||||
672 | 'max_rows' => '', |
||||
673 | 'min_rows' => '', |
||||
674 | 'tablespace' => '', |
||||
675 | 'node_group' => '', |
||||
676 | ]; |
||||
677 | } else { |
||||
678 | $p = $stmt->partitions[$i]; |
||||
679 | $type = $p->type; |
||||
680 | $expr = trim((string) $p->expr, '()'); |
||||
681 | if ($expr == 'MAXVALUE') { |
||||
682 | $type .= ' MAXVALUE'; |
||||
683 | $expr = ''; |
||||
684 | } |
||||
685 | $partitionDetails['partitions'][$i] = [ |
||||
686 | 'name' => $p->name, |
||||
687 | 'value_type' => $type, |
||||
688 | 'value' => $expr, |
||||
689 | 'engine' => $p->options->has('ENGINE', true), |
||||
690 | 'comment' => trim((string) $p->options->has('COMMENT', true), "'"), |
||||
691 | 'data_directory' => trim((string) $p->options->has('DATA DIRECTORY', true), "'"), |
||||
692 | 'index_directory' => trim((string) $p->options->has('INDEX_DIRECTORY', true), "'"), |
||||
693 | 'max_rows' => $p->options->has('MAX_ROWS', true), |
||||
694 | 'min_rows' => $p->options->has('MIN_ROWS', true), |
||||
695 | 'tablespace' => $p->options->has('TABLESPACE', true), |
||||
696 | 'node_group' => $p->options->has('NODEGROUP', true), |
||||
697 | ]; |
||||
698 | } |
||||
699 | |||||
700 | $partition =& $partitionDetails['partitions'][$i]; |
||||
701 | $partition['prefix'] = 'partitions[' . $i . ']'; |
||||
702 | |||||
703 | if ($partitionDetails['subpartition_count'] > 1) { |
||||
704 | $partition['subpartition_count'] = $partitionDetails['subpartition_count']; |
||||
705 | $partition['subpartitions'] = []; |
||||
706 | |||||
707 | for ($j = 0; $j < intval($partitionDetails['subpartition_count']); $j++) { |
||||
708 | if (! isset($stmt->partitions[$i]->subpartitions[$j])) { |
||||
709 | $partition['subpartitions'][$j] = [ |
||||
710 | 'name' => $partition['name'] . '_s' . $j, |
||||
711 | 'engine' => '', |
||||
712 | 'comment' => '', |
||||
713 | 'data_directory' => '', |
||||
714 | 'index_directory' => '', |
||||
715 | 'max_rows' => '', |
||||
716 | 'min_rows' => '', |
||||
717 | 'tablespace' => '', |
||||
718 | 'node_group' => '', |
||||
719 | ]; |
||||
720 | } else { |
||||
721 | $sp = $stmt->partitions[$i]->subpartitions[$j]; |
||||
722 | $partition['subpartitions'][$j] = [ |
||||
723 | 'name' => $sp->name, |
||||
724 | 'engine' => $sp->options->has('ENGINE', true), |
||||
725 | 'comment' => trim($sp->options->has('COMMENT', true), "'"), |
||||
726 | 'data_directory' => trim($sp->options->has('DATA DIRECTORY', true), "'"), |
||||
727 | 'index_directory' => trim($sp->options->has('INDEX_DIRECTORY', true), "'"), |
||||
728 | 'max_rows' => $sp->options->has('MAX_ROWS', true), |
||||
729 | 'min_rows' => $sp->options->has('MIN_ROWS', true), |
||||
730 | 'tablespace' => $sp->options->has('TABLESPACE', true), |
||||
731 | 'node_group' => $sp->options->has('NODEGROUP', true), |
||||
732 | ]; |
||||
733 | } |
||||
734 | |||||
735 | $subpartition =& $partition['subpartitions'][$j]; |
||||
736 | $subpartition['prefix'] = 'partitions[' . $i . ']' |
||||
737 | . '[subpartitions][' . $j . ']'; |
||||
738 | } |
||||
739 | } |
||||
740 | } |
||||
741 | |||||
742 | return $partitionDetails; |
||||
743 | } |
||||
744 | |||||
745 | /** |
||||
746 | * Update the table's partitioning based on $_REQUEST |
||||
747 | * |
||||
748 | * @return void |
||||
749 | */ |
||||
750 | protected function updatePartitioning() |
||||
751 | { |
||||
752 | $sql_query = "ALTER TABLE " . Util::backquote($this->table) . " " |
||||
753 | . $this->createAddField->getPartitionsDefinition(); |
||||
754 | |||||
755 | // Execute alter query |
||||
756 | $result = $this->dbi->tryQuery($sql_query); |
||||
757 | |||||
758 | if ($result !== false) { |
||||
759 | $message = Message::success( |
||||
760 | __('Table %1$s has been altered successfully.') |
||||
761 | ); |
||||
762 | $message->addParam($this->table); |
||||
763 | $this->response->addHTML( |
||||
764 | Util::getMessage($message, $sql_query, 'success') |
||||
765 | ); |
||||
766 | } else { |
||||
767 | $this->response->setRequestStatus(false); |
||||
768 | $this->response->addJSON( |
||||
769 | 'message', |
||||
770 | Message::rawError( |
||||
771 | __('Query error') . ':<br />' . $this->dbi->getError() |
||||
772 | ) |
||||
773 | ); |
||||
774 | } |
||||
775 | } |
||||
776 | |||||
777 | /** |
||||
778 | * Function to get the type of command for multiple field handling |
||||
779 | * |
||||
780 | * @return string |
||||
781 | */ |
||||
782 | protected function getMultipleFieldCommandType() |
||||
783 | { |
||||
784 | $types = [ |
||||
785 | 'change', 'drop', 'primary', |
||||
786 | 'index', 'unique', 'spatial', |
||||
787 | 'fulltext', 'browse' |
||||
788 | ]; |
||||
789 | |||||
790 | foreach ($types as $type) { |
||||
791 | if (isset($_REQUEST['submit_mult_' . $type . '_x'])) { |
||||
792 | return $type; |
||||
793 | } |
||||
794 | } |
||||
795 | |||||
796 | if (isset($_REQUEST['submit_mult'])) { |
||||
797 | return $_REQUEST['submit_mult']; |
||||
798 | } elseif (isset($_REQUEST['mult_btn']) |
||||
799 | && $_REQUEST['mult_btn'] == __('Yes') |
||||
800 | ) { |
||||
801 | if (isset($_REQUEST['selected'])) { |
||||
802 | $_REQUEST['selected_fld'] = $_REQUEST['selected']; |
||||
803 | } |
||||
804 | return 'row_delete'; |
||||
805 | } |
||||
806 | |||||
807 | return null; |
||||
808 | } |
||||
809 | |||||
810 | /** |
||||
811 | * Function to display table browse for selected columns |
||||
812 | * |
||||
813 | * @param string $goto goto page url |
||||
814 | * @param string $pmaThemeImage URI of the pma theme image |
||||
815 | * |
||||
816 | * @return void |
||||
817 | */ |
||||
818 | protected function displayTableBrowseForSelectedColumns($goto, $pmaThemeImage) |
||||
819 | { |
||||
820 | $GLOBALS['active_page'] = 'sql.php'; |
||||
821 | $fields = []; |
||||
822 | foreach ($_REQUEST['selected_fld'] as $sval) { |
||||
823 | $fields[] = Util::backquote($sval); |
||||
824 | } |
||||
825 | $sql_query = sprintf( |
||||
826 | 'SELECT %s FROM %s.%s', |
||||
827 | implode(', ', $fields), |
||||
828 | Util::backquote($this->db), |
||||
829 | Util::backquote($this->table) |
||||
830 | ); |
||||
831 | |||||
832 | // Parse and analyze the query |
||||
833 | $db = &$this->db; |
||||
834 | list( |
||||
835 | $analyzed_sql_results, |
||||
836 | $db, |
||||
837 | ) = ParseAnalyze::sqlQuery($sql_query, $db); |
||||
838 | // @todo: possibly refactor |
||||
839 | extract($analyzed_sql_results); |
||||
840 | |||||
841 | $sql = new Sql(); |
||||
842 | $this->response->addHTML( |
||||
843 | $sql->executeQueryAndGetQueryResponse( |
||||
844 | isset($analyzed_sql_results) ? $analyzed_sql_results : '', |
||||
845 | false, // is_gotofile |
||||
846 | $this->db, // db |
||||
847 | $this->table, // table |
||||
848 | null, // find_real_end |
||||
849 | null, // sql_query_for_bookmark |
||||
850 | null, // extra_data |
||||
851 | null, // message_to_show |
||||
852 | null, // message |
||||
853 | null, // sql_data |
||||
854 | $goto, // goto |
||||
855 | $pmaThemeImage, // pmaThemeImage |
||||
856 | null, // disp_query |
||||
857 | null, // disp_message |
||||
858 | null, // query_type |
||||
859 | $sql_query, // sql_query |
||||
860 | null, // selectedTables |
||||
861 | null // complete_query |
||||
862 | ) |
||||
863 | ); |
||||
864 | } |
||||
865 | |||||
866 | /** |
||||
867 | * Update the table's structure based on $_REQUEST |
||||
868 | * |
||||
869 | * @return boolean true if error occurred |
||||
870 | * |
||||
871 | */ |
||||
872 | protected function updateColumns() |
||||
873 | { |
||||
874 | $err_url = 'tbl_structure.php' . Url::getCommon( |
||||
875 | [ |
||||
876 | 'db' => $this->db, 'table' => $this->table |
||||
877 | ] |
||||
878 | ); |
||||
879 | $regenerate = false; |
||||
880 | $field_cnt = count($_REQUEST['field_name']); |
||||
881 | $changes = []; |
||||
882 | $adjust_privileges = []; |
||||
883 | $columns_with_index = $this->dbi |
||||
884 | ->getTable($this->db, $this->table) |
||||
885 | ->getColumnsWithIndex( |
||||
886 | Index::PRIMARY | Index::UNIQUE |
||||
887 | ); |
||||
888 | for ($i = 0; $i < $field_cnt; $i++) { |
||||
889 | if (!$this->columnNeedsAlterTable($i)) { |
||||
890 | continue; |
||||
891 | } |
||||
892 | |||||
893 | $changes[] = 'CHANGE ' . Table::generateAlter( |
||||
894 | Util::getValueByKey($_REQUEST, "field_orig.${i}", ''), |
||||
895 | $_REQUEST['field_name'][$i], |
||||
896 | $_REQUEST['field_type'][$i], |
||||
897 | $_REQUEST['field_length'][$i], |
||||
898 | $_REQUEST['field_attribute'][$i], |
||||
899 | Util::getValueByKey($_REQUEST, "field_collation.${i}", ''), |
||||
900 | Util::getValueByKey($_REQUEST, "field_null.${i}", 'NOT NULL'), |
||||
901 | $_REQUEST['field_default_type'][$i], |
||||
902 | $_REQUEST['field_default_value'][$i], |
||||
903 | Util::getValueByKey($_REQUEST, "field_extra.${i}", false), |
||||
904 | Util::getValueByKey($_REQUEST, "field_comments.${i}", ''), |
||||
905 | Util::getValueByKey($_REQUEST, "field_virtuality.${i}", ''), |
||||
906 | Util::getValueByKey($_REQUEST, "field_expression.${i}", ''), |
||||
907 | Util::getValueByKey($_REQUEST, "field_move_to.${i}", ''), |
||||
908 | $columns_with_index |
||||
909 | ); |
||||
910 | |||||
911 | // find the remembered sort expression |
||||
912 | $sorted_col = $this->table_obj->getUiProp( |
||||
913 | Table::PROP_SORTED_COLUMN |
||||
914 | ); |
||||
915 | // if the old column name is part of the remembered sort expression |
||||
916 | if (mb_strpos( |
||||
917 | (string) $sorted_col, |
||||
918 | Util::backquote($_REQUEST['field_orig'][$i]) |
||||
0 ignored issues
–
show
It seems like
PhpMyAdmin\Util::backquo...UEST['field_orig'][$i]) can also be of type array ; however, parameter $needle of mb_strpos() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
919 | ) !== false) { |
||||
920 | // delete the whole remembered sort expression |
||||
921 | $this->table_obj->removeUiProp(Table::PROP_SORTED_COLUMN); |
||||
922 | } |
||||
923 | |||||
924 | if (isset($_REQUEST['field_adjust_privileges'][$i]) |
||||
925 | && ! empty($_REQUEST['field_adjust_privileges'][$i]) |
||||
926 | && $_REQUEST['field_orig'][$i] != $_REQUEST['field_name'][$i] |
||||
927 | ) { |
||||
928 | $adjust_privileges[$_REQUEST['field_orig'][$i]] |
||||
929 | = $_REQUEST['field_name'][$i]; |
||||
930 | } |
||||
931 | } // end for |
||||
932 | |||||
933 | if (count($changes) > 0 || isset($_REQUEST['preview_sql'])) { |
||||
934 | // Builds the primary keys statements and updates the table |
||||
935 | $key_query = ''; |
||||
936 | /** |
||||
937 | * this is a little bit more complex |
||||
938 | * |
||||
939 | * @todo if someone selects A_I when altering a column we need to check: |
||||
940 | * - no other column with A_I |
||||
941 | * - the column has an index, if not create one |
||||
942 | * |
||||
943 | */ |
||||
944 | |||||
945 | // To allow replication, we first select the db to use |
||||
946 | // and then run queries on this db. |
||||
947 | if (!$this->dbi->selectDb($this->db)) { |
||||
948 | Util::mysqlDie( |
||||
949 | $this->dbi->getError(), |
||||
950 | 'USE ' . Util::backquote($this->db) . ';', |
||||
951 | false, |
||||
952 | $err_url |
||||
953 | ); |
||||
954 | } |
||||
955 | $sql_query = 'ALTER TABLE ' . Util::backquote($this->table) . ' '; |
||||
956 | $sql_query .= implode(', ', $changes) . $key_query; |
||||
957 | $sql_query .= ';'; |
||||
958 | |||||
959 | // If there is a request for SQL previewing. |
||||
960 | if (isset($_REQUEST['preview_sql'])) { |
||||
961 | Core::previewSQL(count($changes) > 0 ? $sql_query : ''); |
||||
962 | } |
||||
963 | |||||
964 | $columns_with_index = $this->dbi |
||||
965 | ->getTable($this->db, $this->table) |
||||
966 | ->getColumnsWithIndex( |
||||
967 | Index::PRIMARY | Index::UNIQUE | Index::INDEX |
||||
968 | | Index::SPATIAL | Index::FULLTEXT |
||||
969 | ); |
||||
970 | |||||
971 | $changedToBlob = []; |
||||
972 | // While changing the Column Collation |
||||
973 | // First change to BLOB |
||||
974 | for ($i = 0; $i < $field_cnt; $i++) { |
||||
975 | if (isset($_REQUEST['field_collation'][$i]) |
||||
976 | && isset($_REQUEST['field_collation_orig'][$i]) |
||||
977 | && $_REQUEST['field_collation'][$i] !== $_REQUEST['field_collation_orig'][$i] |
||||
978 | && ! in_array($_REQUEST['field_orig'][$i], $columns_with_index) |
||||
979 | ) { |
||||
980 | $secondary_query = 'ALTER TABLE ' . Util::backquote( |
||||
981 | $this->table |
||||
982 | ) |
||||
983 | . ' CHANGE ' . Util::backquote( |
||||
0 ignored issues
–
show
Are you sure
PhpMyAdmin\Util::backquo...UEST['field_orig'][$i]) 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...
|
|||||
984 | $_REQUEST['field_orig'][$i] |
||||
985 | ) |
||||
986 | . ' ' . Util::backquote($_REQUEST['field_orig'][$i]) |
||||
987 | . ' BLOB;'; |
||||
988 | $this->dbi->query($secondary_query); |
||||
989 | $changedToBlob[$i] = true; |
||||
990 | } else { |
||||
991 | $changedToBlob[$i] = false; |
||||
992 | } |
||||
993 | } |
||||
994 | |||||
995 | // Then make the requested changes |
||||
996 | $result = $this->dbi->tryQuery($sql_query); |
||||
997 | |||||
998 | if ($result !== false) { |
||||
999 | $changed_privileges = $this->adjustColumnPrivileges( |
||||
1000 | $adjust_privileges |
||||
1001 | ); |
||||
1002 | |||||
1003 | if ($changed_privileges) { |
||||
1004 | $message = Message::success( |
||||
1005 | __( |
||||
1006 | 'Table %1$s has been altered successfully. Privileges ' . |
||||
1007 | 'have been adjusted.' |
||||
1008 | ) |
||||
1009 | ); |
||||
1010 | } else { |
||||
1011 | $message = Message::success( |
||||
1012 | __('Table %1$s has been altered successfully.') |
||||
1013 | ); |
||||
1014 | } |
||||
1015 | $message->addParam($this->table); |
||||
1016 | |||||
1017 | $this->response->addHTML( |
||||
1018 | Util::getMessage($message, $sql_query, 'success') |
||||
1019 | ); |
||||
1020 | } else { |
||||
1021 | // An error happened while inserting/updating a table definition |
||||
1022 | |||||
1023 | // Save the Original Error |
||||
1024 | $orig_error = $this->dbi->getError(); |
||||
1025 | $changes_revert = []; |
||||
1026 | |||||
1027 | // Change back to Original Collation and data type |
||||
1028 | for ($i = 0; $i < $field_cnt; $i++) { |
||||
1029 | if ($changedToBlob[$i]) { |
||||
1030 | $changes_revert[] = 'CHANGE ' . Table::generateAlter( |
||||
1031 | Util::getValueByKey($_REQUEST, "field_orig.${i}", ''), |
||||
1032 | $_REQUEST['field_name'][$i], |
||||
1033 | $_REQUEST['field_type_orig'][$i], |
||||
1034 | $_REQUEST['field_length_orig'][$i], |
||||
1035 | $_REQUEST['field_attribute_orig'][$i], |
||||
1036 | Util::getValueByKey($_REQUEST, "field_collation_orig.${i}", ''), |
||||
1037 | Util::getValueByKey($_REQUEST, "field_null_orig.${i}", 'NOT NULL'), |
||||
1038 | $_REQUEST['field_default_type_orig'][$i], |
||||
1039 | $_REQUEST['field_default_value_orig'][$i], |
||||
1040 | Util::getValueByKey($_REQUEST, "field_extra_orig.${i}", false), |
||||
1041 | Util::getValueByKey($_REQUEST, "field_comments_orig.${i}", ''), |
||||
1042 | Util::getValueByKey($_REQUEST, "field_virtuality_orig.${i}", ''), |
||||
1043 | Util::getValueByKey($_REQUEST, "field_expression_orig.${i}", ''), |
||||
1044 | Util::getValueByKey($_REQUEST, "field_move_to_orig.${i}", '') |
||||
1045 | ); |
||||
1046 | } |
||||
1047 | } |
||||
1048 | |||||
1049 | $revert_query = 'ALTER TABLE ' . Util::backquote($this->table) |
||||
1050 | . ' '; |
||||
1051 | $revert_query .= implode(', ', $changes_revert) . ''; |
||||
1052 | $revert_query .= ';'; |
||||
1053 | |||||
1054 | // Column reverted back to original |
||||
1055 | $this->dbi->query($revert_query); |
||||
1056 | |||||
1057 | $this->response->setRequestStatus(false); |
||||
1058 | $this->response->addJSON( |
||||
1059 | 'message', |
||||
1060 | Message::rawError( |
||||
1061 | __('Query error') . ':<br />' . $orig_error |
||||
1062 | ) |
||||
1063 | ); |
||||
1064 | $regenerate = true; |
||||
1065 | } |
||||
1066 | } |
||||
1067 | |||||
1068 | // update field names in relation |
||||
1069 | if (isset($_REQUEST['field_orig']) && is_array($_REQUEST['field_orig'])) { |
||||
1070 | foreach ($_REQUEST['field_orig'] as $fieldindex => $fieldcontent) { |
||||
1071 | if ($_REQUEST['field_name'][$fieldindex] != $fieldcontent) { |
||||
1072 | $this->relation->renameField( |
||||
1073 | $this->db, |
||||
1074 | $this->table, |
||||
1075 | $fieldcontent, |
||||
1076 | $_REQUEST['field_name'][$fieldindex] |
||||
1077 | ); |
||||
1078 | } |
||||
1079 | } |
||||
1080 | } |
||||
1081 | |||||
1082 | // update mime types |
||||
1083 | if (isset($_REQUEST['field_mimetype']) |
||||
1084 | && is_array($_REQUEST['field_mimetype']) |
||||
1085 | && $GLOBALS['cfg']['BrowseMIME'] |
||||
1086 | ) { |
||||
1087 | foreach ($_REQUEST['field_mimetype'] as $fieldindex => $mimetype) { |
||||
1088 | if (isset($_REQUEST['field_name'][$fieldindex]) |
||||
1089 | && strlen($_REQUEST['field_name'][$fieldindex]) > 0 |
||||
1090 | ) { |
||||
1091 | $this->transformations->setMime( |
||||
1092 | $this->db, |
||||
1093 | $this->table, |
||||
1094 | $_REQUEST['field_name'][$fieldindex], |
||||
1095 | $mimetype, |
||||
1096 | $_REQUEST['field_transformation'][$fieldindex], |
||||
1097 | $_REQUEST['field_transformation_options'][$fieldindex], |
||||
1098 | $_REQUEST['field_input_transformation'][$fieldindex], |
||||
1099 | $_REQUEST['field_input_transformation_options'][$fieldindex] |
||||
1100 | ); |
||||
1101 | } |
||||
1102 | } |
||||
1103 | } |
||||
1104 | return $regenerate; |
||||
1105 | } |
||||
1106 | |||||
1107 | /** |
||||
1108 | * Adjusts the Privileges for all the columns whose names have changed |
||||
1109 | * |
||||
1110 | * @param array $adjust_privileges assoc array of old col names mapped to new |
||||
1111 | * cols |
||||
1112 | * |
||||
1113 | * @return boolean boolean whether at least one column privileges |
||||
1114 | * adjusted |
||||
1115 | */ |
||||
1116 | protected function adjustColumnPrivileges(array $adjust_privileges) |
||||
1117 | { |
||||
1118 | $changed = false; |
||||
1119 | |||||
1120 | if (Util::getValueByKey($GLOBALS, 'col_priv', false) |
||||
1121 | && Util::getValueByKey($GLOBALS, 'is_reload_priv', false) |
||||
1122 | ) { |
||||
1123 | $this->dbi->selectDb('mysql'); |
||||
1124 | |||||
1125 | // For Column specific privileges |
||||
1126 | foreach ($adjust_privileges as $oldCol => $newCol) { |
||||
1127 | $this->dbi->query( |
||||
1128 | sprintf( |
||||
1129 | 'UPDATE %s SET Column_name = "%s" |
||||
1130 | WHERE Db = "%s" |
||||
1131 | AND Table_name = "%s" |
||||
1132 | AND Column_name = "%s";', |
||||
1133 | Util::backquote('columns_priv'), |
||||
1134 | $newCol, |
||||
1135 | $this->db, |
||||
1136 | $this->table, |
||||
1137 | $oldCol |
||||
1138 | ) |
||||
1139 | ); |
||||
1140 | |||||
1141 | // i.e. if atleast one column privileges adjusted |
||||
1142 | $changed = true; |
||||
1143 | } |
||||
1144 | |||||
1145 | if ($changed) { |
||||
1146 | // Finally FLUSH the new privileges |
||||
1147 | $this->dbi->query("FLUSH PRIVILEGES;"); |
||||
1148 | } |
||||
1149 | } |
||||
1150 | |||||
1151 | return $changed; |
||||
1152 | } |
||||
1153 | |||||
1154 | /** |
||||
1155 | * Verifies if some elements of a column have changed |
||||
1156 | * |
||||
1157 | * @param integer $i column index in the request |
||||
1158 | * |
||||
1159 | * @return boolean true if we need to generate ALTER TABLE |
||||
1160 | * |
||||
1161 | */ |
||||
1162 | protected function columnNeedsAlterTable($i) |
||||
1163 | { |
||||
1164 | // these two fields are checkboxes so might not be part of the |
||||
1165 | // request; therefore we define them to avoid notices below |
||||
1166 | if (! isset($_REQUEST['field_null'][$i])) { |
||||
1167 | $_REQUEST['field_null'][$i] = 'NO'; |
||||
1168 | } |
||||
1169 | if (! isset($_REQUEST['field_extra'][$i])) { |
||||
1170 | $_REQUEST['field_extra'][$i] = ''; |
||||
1171 | } |
||||
1172 | |||||
1173 | // field_name does not follow the convention (corresponds to field_orig) |
||||
1174 | if ($_REQUEST['field_name'][$i] != $_REQUEST['field_orig'][$i]) { |
||||
1175 | return true; |
||||
1176 | } |
||||
1177 | |||||
1178 | $fields = [ |
||||
1179 | 'field_attribute', 'field_collation', 'field_comments', |
||||
1180 | 'field_default_value', 'field_default_type', 'field_extra', |
||||
1181 | 'field_length', 'field_null', 'field_type' |
||||
1182 | ]; |
||||
1183 | foreach ($fields as $field) { |
||||
1184 | if ($_REQUEST[$field][$i] != $_REQUEST[$field . '_orig'][$i]) { |
||||
1185 | return true; |
||||
1186 | } |
||||
1187 | } |
||||
1188 | return !empty($_REQUEST['field_move_to'][$i]); |
||||
1189 | } |
||||
1190 | |||||
1191 | /** |
||||
1192 | * Displays the table structure ('show table' works correct since 3.23.03) |
||||
1193 | * |
||||
1194 | * @param array $cfgRelation current relation parameters |
||||
1195 | * @param array $columns_with_unique_index Columns with unique index |
||||
1196 | * @param mixed $url_params Contains an associative |
||||
1197 | * array with url params |
||||
1198 | * @param Index|false $primary_index primary index or false if |
||||
1199 | * no one exists |
||||
1200 | * @param array $fields Fields |
||||
1201 | * @param array $columns_with_index Columns with index |
||||
1202 | * |
||||
1203 | * @return string |
||||
1204 | */ |
||||
1205 | protected function displayStructure( |
||||
1206 | array $cfgRelation, |
||||
1207 | array $columns_with_unique_index, |
||||
1208 | $url_params, |
||||
1209 | $primary_index, |
||||
1210 | array $fields, |
||||
1211 | array $columns_with_index |
||||
1212 | ) { |
||||
1213 | // prepare comments |
||||
1214 | $comments_map = []; |
||||
1215 | $mime_map = []; |
||||
1216 | |||||
1217 | if ($GLOBALS['cfg']['ShowPropertyComments']) { |
||||
1218 | $comments_map = $this->relation->getComments($this->db, $this->table); |
||||
1219 | if ($cfgRelation['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { |
||||
1220 | $mime_map = $this->transformations->getMime($this->db, $this->table, true); |
||||
1221 | } |
||||
1222 | } |
||||
1223 | $centralColumns = new CentralColumns($this->dbi); |
||||
1224 | $central_list = $centralColumns->getFromTable( |
||||
1225 | $this->db, |
||||
1226 | $this->table |
||||
1227 | ); |
||||
1228 | $columns_list = []; |
||||
1229 | |||||
1230 | $titles = [ |
||||
1231 | 'Change' => Util::getIcon('b_edit', __('Change')), |
||||
1232 | 'Drop' => Util::getIcon('b_drop', __('Drop')), |
||||
1233 | 'NoDrop' => Util::getIcon('b_drop', __('Drop')), |
||||
1234 | 'Primary' => Util::getIcon('b_primary', __('Primary')), |
||||
1235 | 'Index' => Util::getIcon('b_index', __('Index')), |
||||
1236 | 'Unique' => Util::getIcon('b_unique', __('Unique')), |
||||
1237 | 'Spatial' => Util::getIcon('b_spatial', __('Spatial')), |
||||
1238 | 'IdxFulltext' => Util::getIcon('b_ftext', __('Fulltext')), |
||||
1239 | 'NoPrimary' => Util::getIcon('bd_primary', __('Primary')), |
||||
1240 | 'NoIndex' => Util::getIcon('bd_index', __('Index')), |
||||
1241 | 'NoUnique' => Util::getIcon('bd_unique', __('Unique')), |
||||
1242 | 'NoSpatial' => Util::getIcon('bd_spatial', __('Spatial')), |
||||
1243 | 'NoIdxFulltext' => Util::getIcon('bd_ftext', __('Fulltext')), |
||||
1244 | 'DistinctValues' => Util::getIcon('b_browse', __('Distinct values')), |
||||
1245 | ]; |
||||
1246 | |||||
1247 | /** |
||||
1248 | * Work on the table |
||||
1249 | */ |
||||
1250 | if ($this->_tbl_is_view && ! $this->_db_is_system_schema) { |
||||
1251 | $item = $this->dbi->fetchSingleRow( |
||||
1252 | sprintf( |
||||
1253 | "SELECT `VIEW_DEFINITION`, `CHECK_OPTION`, `DEFINER`, |
||||
1254 | `SECURITY_TYPE` |
||||
1255 | FROM `INFORMATION_SCHEMA`.`VIEWS` |
||||
1256 | WHERE TABLE_SCHEMA='%s' |
||||
1257 | AND TABLE_NAME='%s';", |
||||
1258 | $this->dbi->escapeString($this->db), |
||||
1259 | $this->dbi->escapeString($this->table) |
||||
1260 | ) |
||||
1261 | ); |
||||
1262 | |||||
1263 | $createView = $this->dbi->getTable($this->db, $this->table) |
||||
1264 | ->showCreate(); |
||||
1265 | // get algorithm from $createView of the form |
||||
1266 | // CREATE ALGORITHM=<ALGORITHM> DE... |
||||
1267 | $parts = explode(" ", substr($createView, 17)); |
||||
1268 | $item['ALGORITHM'] = $parts[0]; |
||||
1269 | |||||
1270 | $view = [ |
||||
1271 | 'operation' => 'alter', |
||||
1272 | 'definer' => $item['DEFINER'], |
||||
1273 | 'sql_security' => $item['SECURITY_TYPE'], |
||||
1274 | 'name' => $this->table, |
||||
1275 | 'as' => $item['VIEW_DEFINITION'], |
||||
1276 | 'with' => $item['CHECK_OPTION'], |
||||
1277 | 'algorithm' => $item['ALGORITHM'], |
||||
1278 | ]; |
||||
1279 | |||||
1280 | $edit_view_url = 'view_create.php' |
||||
1281 | . Url::getCommon($url_params) . '&' |
||||
1282 | . implode( |
||||
1283 | '&', |
||||
1284 | array_map( |
||||
1285 | function ($key, $val) { |
||||
1286 | return 'view[' . urlencode($key) . ']=' . urlencode( |
||||
1287 | $val |
||||
1288 | ); |
||||
1289 | }, |
||||
1290 | array_keys($view), |
||||
1291 | $view |
||||
1292 | ) |
||||
1293 | ); |
||||
1294 | } |
||||
1295 | |||||
1296 | /** |
||||
1297 | * Displays Space usage and row statistics |
||||
1298 | */ |
||||
1299 | // BEGIN - Calc Table Space |
||||
1300 | // Get valid statistics whatever is the table type |
||||
1301 | if ($GLOBALS['cfg']['ShowStats']) { |
||||
1302 | //get table stats in HTML format |
||||
1303 | $tablestats = $this->getTableStats(); |
||||
1304 | //returning the response in JSON format to be used by Ajax |
||||
1305 | $this->response->addJSON('tableStat', $tablestats); |
||||
1306 | } |
||||
1307 | // END - Calc Table Space |
||||
1308 | |||||
1309 | $hideStructureActions = false; |
||||
1310 | if ($GLOBALS['cfg']['HideStructureActions'] === true) { |
||||
1311 | $hideStructureActions = true; |
||||
1312 | } |
||||
1313 | |||||
1314 | // logic removed from Template |
||||
1315 | $rownum = 0; |
||||
1316 | $columns_list = []; |
||||
1317 | $attributes = []; |
||||
1318 | $displayed_fields = []; |
||||
1319 | $row_comments = []; |
||||
1320 | $extracted_columnspecs = []; |
||||
1321 | foreach ($fields as &$field) { |
||||
1322 | $rownum += 1; |
||||
1323 | $columns_list[] = $field['Field']; |
||||
1324 | |||||
1325 | $extracted_columnspecs[$rownum] = Util::extractColumnSpec($field['Type']); |
||||
1326 | $attributes[$rownum] = $extracted_columnspecs[$rownum]['attribute']; |
||||
1327 | if (strpos($field['Extra'], 'on update CURRENT_TIMESTAMP') !== false) { |
||||
1328 | $attributes[$rownum] = 'on update CURRENT_TIMESTAMP'; |
||||
1329 | } |
||||
1330 | |||||
1331 | $displayed_fields[$rownum] = new \stdClass(); |
||||
1332 | $displayed_fields[$rownum]->text = $field['Field']; |
||||
1333 | $displayed_fields[$rownum]->icon = ""; |
||||
1334 | $row_comments[$rownum] = ''; |
||||
1335 | |||||
1336 | if (isset($comments_map[$field['Field']])) { |
||||
1337 | $displayed_fields[$rownum]->comment = $comments_map[$field['Field']]; |
||||
1338 | $row_comments[$rownum] = $comments_map[$field['Field']]; |
||||
1339 | } |
||||
1340 | |||||
1341 | if ($primary_index && $primary_index->hasColumn($field['Field'])) { |
||||
1342 | $displayed_fields[$rownum]->icon .= |
||||
1343 | Util::getImage('b_primary', __('Primary')); |
||||
1344 | } |
||||
1345 | |||||
1346 | if (in_array($field['Field'], $columns_with_index)) { |
||||
1347 | $displayed_fields[$rownum]->icon .= |
||||
1348 | Util::getImage('bd_primary', __('Index')); |
||||
1349 | } |
||||
1350 | } |
||||
1351 | |||||
1352 | $engine = $this->table_obj->getStorageEngine(); |
||||
1353 | return $this->template->render('table/structure/display_structure', [ |
||||
1354 | 'url_params' => [ |
||||
1355 | 'db' => $this->db, |
||||
1356 | 'table' => $this->table, |
||||
1357 | ], |
||||
1358 | 'is_foreign_key_supported' => Util::isForeignKeySupported($engine), |
||||
1359 | 'displayIndexesHtml' => Index::getHtmlForDisplayIndexes(), |
||||
1360 | 'cfg_relation' => $this->relation->getRelationsParam(), |
||||
1361 | 'hide_structure_actions' => $hideStructureActions, |
||||
1362 | 'db' => $this->db, |
||||
1363 | 'table' => $this->table, |
||||
1364 | 'db_is_system_schema' => $this->_db_is_system_schema, |
||||
1365 | 'tbl_is_view' => $this->_tbl_is_view, |
||||
1366 | 'mime_map' => $mime_map, |
||||
1367 | 'url_query' => $this->_url_query, |
||||
1368 | 'titles' => $titles, |
||||
1369 | 'tbl_storage_engine' => $this->_tbl_storage_engine, |
||||
1370 | 'primary' => $primary_index, |
||||
1371 | 'columns_with_unique_index' => $columns_with_unique_index, |
||||
1372 | 'edit_view_url' => isset($edit_view_url) ? $edit_view_url : null, |
||||
1373 | 'columns_list' => $columns_list, |
||||
1374 | 'table_stats' => isset($tablestats) ? $tablestats : null, |
||||
1375 | 'fields' => $fields, |
||||
1376 | 'extracted_columnspecs' => $extracted_columnspecs, |
||||
1377 | 'columns_with_index' => $columns_with_index, |
||||
1378 | 'central_list' => $central_list, |
||||
1379 | 'comments_map' => $comments_map, |
||||
1380 | 'browse_mime' => $GLOBALS['cfg']['BrowseMIME'], |
||||
1381 | 'show_column_comments' => $GLOBALS['cfg']['ShowColumnComments'], |
||||
1382 | 'show_stats' => $GLOBALS['cfg']['ShowStats'], |
||||
1383 | 'relation_commwork' => $GLOBALS['cfgRelation']['commwork'], |
||||
1384 | 'relation_mimework' => $GLOBALS['cfgRelation']['mimework'], |
||||
1385 | 'central_columns_work' => $GLOBALS['cfgRelation']['centralcolumnswork'], |
||||
1386 | 'mysql_int_version' => $this->dbi->getVersion(), |
||||
1387 | 'pma_theme_image' => $GLOBALS['pmaThemeImage'], |
||||
1388 | 'text_dir' => $GLOBALS['text_dir'], |
||||
1389 | 'is_active' => Tracker::isActive(), |
||||
1390 | 'have_partitioning' => Partition::havePartitioning(), |
||||
1391 | 'partitions' => Partition::getPartitions($this->db, $this->table), |
||||
1392 | 'partition_names' => Partition::getPartitionNames($this->db, $this->table), |
||||
1393 | 'default_sliders_state' => $GLOBALS['cfg']['InitialSlidersState'], |
||||
1394 | 'attributes' => $attributes, |
||||
1395 | 'displayed_fields' => $displayed_fields, |
||||
1396 | 'row_comments' => $row_comments, |
||||
1397 | ]); |
||||
1398 | } |
||||
1399 | |||||
1400 | /** |
||||
1401 | * Get HTML snippet for display table statistics |
||||
1402 | * |
||||
1403 | * @return string |
||||
1404 | */ |
||||
1405 | protected function getTableStats() |
||||
1406 | { |
||||
1407 | if (empty($this->_showtable)) { |
||||
1408 | $this->_showtable = $this->dbi->getTable( |
||||
1409 | $this->db, |
||||
1410 | $this->table |
||||
1411 | )->getStatusInfo(null, true); |
||||
1412 | } |
||||
1413 | |||||
1414 | if (empty($this->_showtable['Data_length'])) { |
||||
1415 | $this->_showtable['Data_length'] = 0; |
||||
1416 | } |
||||
1417 | if (empty($this->_showtable['Index_length'])) { |
||||
1418 | $this->_showtable['Index_length'] = 0; |
||||
1419 | } |
||||
1420 | |||||
1421 | $is_innodb = (isset($this->_showtable['Type']) |
||||
1422 | && $this->_showtable['Type'] == 'InnoDB'); |
||||
1423 | |||||
1424 | $mergetable = $this->table_obj->isMerge(); |
||||
1425 | |||||
1426 | // this is to display for example 261.2 MiB instead of 268k KiB |
||||
1427 | $max_digits = 3; |
||||
1428 | $decimals = 1; |
||||
1429 | list($data_size, $data_unit) = Util::formatByteDown( |
||||
1430 | $this->_showtable['Data_length'], |
||||
1431 | $max_digits, |
||||
1432 | $decimals |
||||
1433 | ); |
||||
1434 | if ($mergetable == false) { |
||||
1435 | list($index_size, $index_unit) = Util::formatByteDown( |
||||
1436 | $this->_showtable['Index_length'], |
||||
1437 | $max_digits, |
||||
1438 | $decimals |
||||
1439 | ); |
||||
1440 | } |
||||
1441 | // InnoDB returns a huge value in Data_free, do not use it |
||||
1442 | if (! $is_innodb && isset($this->_showtable['Data_free']) |
||||
1443 | && $this->_showtable['Data_free'] > 0 |
||||
1444 | ) { |
||||
1445 | list($free_size, $free_unit) = Util::formatByteDown( |
||||
1446 | $this->_showtable['Data_free'], |
||||
1447 | $max_digits, |
||||
1448 | $decimals |
||||
1449 | ); |
||||
1450 | list($effect_size, $effect_unit) = Util::formatByteDown( |
||||
1451 | $this->_showtable['Data_length'] |
||||
1452 | + $this->_showtable['Index_length'] |
||||
1453 | - $this->_showtable['Data_free'], |
||||
1454 | $max_digits, |
||||
1455 | $decimals |
||||
1456 | ); |
||||
1457 | } else { |
||||
1458 | list($effect_size, $effect_unit) = Util::formatByteDown( |
||||
1459 | $this->_showtable['Data_length'] |
||||
1460 | + $this->_showtable['Index_length'], |
||||
1461 | $max_digits, |
||||
1462 | $decimals |
||||
1463 | ); |
||||
1464 | } |
||||
1465 | list($tot_size, $tot_unit) = Util::formatByteDown( |
||||
1466 | $this->_showtable['Data_length'] + $this->_showtable['Index_length'], |
||||
1467 | $max_digits, |
||||
1468 | $decimals |
||||
1469 | ); |
||||
1470 | if ($this->_table_info_num_rows > 0) { |
||||
1471 | list($avg_size, $avg_unit) = Util::formatByteDown( |
||||
1472 | ($this->_showtable['Data_length'] |
||||
1473 | + $this->_showtable['Index_length']) |
||||
1474 | / $this->_showtable['Rows'], |
||||
1475 | 6, |
||||
1476 | 1 |
||||
1477 | ); |
||||
1478 | } else { |
||||
1479 | $avg_size = $avg_unit = ''; |
||||
1480 | } |
||||
1481 | |||||
1482 | $engine = $this->dbi->getTable($this->db, $this->table)->getStorageEngine(); |
||||
1483 | return $this->template->render('table/structure/display_table_stats', [ |
||||
1484 | 'url_params' => [ |
||||
1485 | 'db' => $GLOBALS['db'], |
||||
1486 | 'table' => $GLOBALS['table'], |
||||
1487 | ], |
||||
1488 | 'is_foreign_key_supported' => Util::isForeignKeySupported($engine), |
||||
1489 | 'cfg_relation' => $this->relation->getRelationsParam(), |
||||
1490 | 'showtable' => $this->_showtable, |
||||
1491 | 'table_info_num_rows' => $this->_table_info_num_rows, |
||||
1492 | 'tbl_is_view' => $this->_tbl_is_view, |
||||
1493 | 'db_is_system_schema' => $this->_db_is_system_schema, |
||||
1494 | 'tbl_storage_engine' => $this->_tbl_storage_engine, |
||||
1495 | 'url_query' => $this->_url_query, |
||||
1496 | 'tbl_collation' => $this->_tbl_collation, |
||||
1497 | 'is_innodb' => $is_innodb, |
||||
1498 | 'mergetable' => $mergetable, |
||||
1499 | 'avg_size' => isset($avg_size) ? $avg_size : null, |
||||
1500 | 'avg_unit' => isset($avg_unit) ? $avg_unit : null, |
||||
1501 | 'data_size' => $data_size, |
||||
1502 | 'data_unit' => $data_unit, |
||||
1503 | 'index_size' => isset($index_size) ? $index_size : null, |
||||
1504 | 'index_unit' => isset($index_unit) ? $index_unit : null, |
||||
1505 | 'free_size' => isset($free_size) ? $free_size : null, |
||||
1506 | 'free_unit' => isset($free_unit) ? $free_unit : null, |
||||
1507 | 'effect_size' => $effect_size, |
||||
1508 | 'effect_unit' => $effect_unit, |
||||
1509 | 'tot_size' => $tot_size, |
||||
1510 | 'tot_unit' => $tot_unit, |
||||
1511 | 'table' => $GLOBALS['table'], |
||||
1512 | ]); |
||||
1513 | } |
||||
1514 | |||||
1515 | /** |
||||
1516 | * Gets table primary key |
||||
1517 | * |
||||
1518 | * @return string |
||||
1519 | */ |
||||
1520 | protected function getKeyForTablePrimary() |
||||
1521 | { |
||||
1522 | $this->dbi->selectDb($this->db); |
||||
1523 | $result = $this->dbi->query( |
||||
1524 | 'SHOW KEYS FROM ' . Util::backquote($this->table) . ';' |
||||
1525 | ); |
||||
1526 | $primary = ''; |
||||
1527 | while ($row = $this->dbi->fetchAssoc($result)) { |
||||
1528 | // Backups the list of primary keys |
||||
1529 | if ($row['Key_name'] == 'PRIMARY') { |
||||
1530 | $primary .= $row['Column_name'] . ', '; |
||||
1531 | } |
||||
1532 | } // end while |
||||
1533 | $this->dbi->freeResult($result); |
||||
1534 | |||||
1535 | return $primary; |
||||
1536 | } |
||||
1537 | |||||
1538 | /** |
||||
1539 | * Get List of information for Submit Mult |
||||
1540 | * |
||||
1541 | * @param string $submit_mult mult_submit type |
||||
1542 | * @param array $selected the selected columns |
||||
1543 | * @param string $action action type |
||||
1544 | * |
||||
1545 | * @return array |
||||
1546 | */ |
||||
1547 | protected function getDataForSubmitMult($submit_mult, $selected, $action) |
||||
1548 | { |
||||
1549 | $centralColumns = new CentralColumns($this->dbi); |
||||
1550 | $what = null; |
||||
1551 | $query_type = null; |
||||
1552 | $is_unset_submit_mult = false; |
||||
1553 | $mult_btn = null; |
||||
1554 | $centralColsError = null; |
||||
1555 | switch ($submit_mult) { |
||||
1556 | case 'drop': |
||||
1557 | $what = 'drop_fld'; |
||||
1558 | break; |
||||
1559 | case 'primary': |
||||
1560 | // Gets table primary key |
||||
1561 | $primary = $this->getKeyForTablePrimary(); |
||||
1562 | if (empty($primary)) { |
||||
1563 | // no primary key, so we can safely create new |
||||
1564 | $is_unset_submit_mult = true; |
||||
1565 | $query_type = 'primary_fld'; |
||||
1566 | $mult_btn = __('Yes'); |
||||
1567 | } else { |
||||
1568 | // primary key exists, so lets as user |
||||
1569 | $what = 'primary_fld'; |
||||
1570 | } |
||||
1571 | break; |
||||
1572 | case 'index': |
||||
1573 | $is_unset_submit_mult = true; |
||||
1574 | $query_type = 'index_fld'; |
||||
1575 | $mult_btn = __('Yes'); |
||||
1576 | break; |
||||
1577 | case 'unique': |
||||
1578 | $is_unset_submit_mult = true; |
||||
1579 | $query_type = 'unique_fld'; |
||||
1580 | $mult_btn = __('Yes'); |
||||
1581 | break; |
||||
1582 | case 'spatial': |
||||
1583 | $is_unset_submit_mult = true; |
||||
1584 | $query_type = 'spatial_fld'; |
||||
1585 | $mult_btn = __('Yes'); |
||||
1586 | break; |
||||
1587 | case 'ftext': |
||||
1588 | $is_unset_submit_mult = true; |
||||
1589 | $query_type = 'fulltext_fld'; |
||||
1590 | $mult_btn = __('Yes'); |
||||
1591 | break; |
||||
1592 | case 'add_to_central_columns': |
||||
1593 | $centralColsError = $centralColumns->syncUniqueColumns( |
||||
1594 | $selected, |
||||
1595 | false |
||||
1596 | ); |
||||
1597 | break; |
||||
1598 | case 'remove_from_central_columns': |
||||
1599 | $centralColsError = $centralColumns->deleteColumnsFromList( |
||||
1600 | $selected, |
||||
1601 | false |
||||
1602 | ); |
||||
1603 | break; |
||||
1604 | case 'change': |
||||
1605 | $this->displayHtmlForColumnChange($selected, $action); |
||||
1606 | // execution stops here but PhpMyAdmin\Response correctly finishes |
||||
1607 | // the rendering |
||||
1608 | exit; |
||||
1609 | case 'browse': |
||||
1610 | // this should already be handled by tbl_structure.php |
||||
1611 | } |
||||
1612 | |||||
1613 | return [ |
||||
1614 | $what, $query_type, $is_unset_submit_mult, $mult_btn, |
||||
1615 | $centralColsError |
||||
1616 | ]; |
||||
1617 | } |
||||
1618 | } |
||||
1619 |