From 1faab7119d3eb9ffed32632042f5fbafe69c582e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Wed, 9 Feb 2022 13:58:35 -0300 Subject: [PATCH] Fix bug when renaming tables with config storage enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/phpmyadmin/phpmyadmin/issues/17359 Introduced by https://github.com/phpmyadmin/phpmyadmin/pull/17256 Signed-off-by: MaurĂ­cio Meneghini Fauth --- libraries/classes/ConfigStorage/Relation.php | 32 +++++--- test/classes/ConfigStorage/RelationTest.php | 86 ++++++++++++++++++++ 2 files changed, 106 insertions(+), 12 deletions(-) diff --git a/libraries/classes/ConfigStorage/Relation.php b/libraries/classes/ConfigStorage/Relation.php index 7efc7eae60..38e21d6182 100644 --- a/libraries/classes/ConfigStorage/Relation.php +++ b/libraries/classes/ConfigStorage/Relation.php @@ -6,6 +6,8 @@ namespace PhpMyAdmin\ConfigStorage; use PhpMyAdmin\ConfigStorage\Features\PdfFeature; use PhpMyAdmin\DatabaseInterface; +use PhpMyAdmin\Dbal\DatabaseName; +use PhpMyAdmin\Dbal\TableName; use PhpMyAdmin\InternalRelations; use PhpMyAdmin\RecentFavoriteTable; use PhpMyAdmin\SqlParser\Parser; @@ -1170,7 +1172,6 @@ class Relation /** * Performs SQL query used for renaming table. * - * @param string $table Relation table to use * @param string $source_db Source database name * @param string $target_db Target database name * @param string $source_table Source table name @@ -1179,7 +1180,8 @@ class Relation * @param string $table_field Name of table field */ public function renameSingleTable( - string $table, + DatabaseName $configStorageDatabase, + TableName $configStorageTable, string $source_db, string $target_db, string $source_table, @@ -1187,10 +1189,9 @@ class Relation string $db_field, string $table_field ): void { - $relationParameters = $this->getRelationParameters(); $query = 'UPDATE ' - . Util::backquote($relationParameters->db) . '.' - . Util::backquote((string) $relationParameters->{$table}) + . Util::backquote($configStorageDatabase) . '.' + . Util::backquote($configStorageTable) . ' SET ' . $db_field . ' = \'' . $this->dbi->escapeString($target_db) . '\', ' @@ -1221,7 +1222,8 @@ class Relation // Move old entries from PMA-DBs to new table if ($relationParameters->columnCommentsFeature !== null) { $this->renameSingleTable( - 'columnInfo', + $relationParameters->columnCommentsFeature->database, + $relationParameters->columnCommentsFeature->columnInfo, $source_db, $target_db, $source_table, @@ -1236,7 +1238,8 @@ class Relation if ($relationParameters->displayFeature !== null) { $this->renameSingleTable( - 'tableInfo', + $relationParameters->displayFeature->database, + $relationParameters->displayFeature->tableInfo, $source_db, $target_db, $source_table, @@ -1248,7 +1251,8 @@ class Relation if ($relationParameters->relationFeature !== null) { $this->renameSingleTable( - 'relation', + $relationParameters->relationFeature->database, + $relationParameters->relationFeature->relation, $source_db, $target_db, $source_table, @@ -1258,7 +1262,8 @@ class Relation ); $this->renameSingleTable( - 'relation', + $relationParameters->relationFeature->database, + $relationParameters->relationFeature->relation, $source_db, $target_db, $source_table, @@ -1272,7 +1277,8 @@ class Relation if ($source_db == $target_db) { // rename within the database can be handled $this->renameSingleTable( - 'tableCoords', + $relationParameters->pdfFeature->database, + $relationParameters->pdfFeature->tableCoords, $source_db, $target_db, $source_table, @@ -1295,7 +1301,8 @@ class Relation if ($relationParameters->uiPreferencesFeature !== null) { $this->renameSingleTable( - 'tableUiprefs', + $relationParameters->uiPreferencesFeature->database, + $relationParameters->uiPreferencesFeature->tableUiPrefs, $source_db, $target_db, $source_table, @@ -1311,7 +1318,8 @@ class Relation // update hidden items inside table $this->renameSingleTable( - 'navigationhiding', + $relationParameters->navigationItemsHidingFeature->database, + $relationParameters->navigationItemsHidingFeature->navigationHiding, $source_db, $target_db, $source_table, diff --git a/test/classes/ConfigStorage/RelationTest.php b/test/classes/ConfigStorage/RelationTest.php index 1e771eae5d..678fcb752f 100644 --- a/test/classes/ConfigStorage/RelationTest.php +++ b/test/classes/ConfigStorage/RelationTest.php @@ -1807,4 +1807,90 @@ class RelationTest extends AbstractTestCase $this->assertAllQueriesConsumed(); } + + /** + * @param array $params + * @param string[] $queries + * + * @dataProvider providerForTestRenameTable + */ + public function testRenameTable(array $params, array $queries): void + { + $GLOBALS['server'] = 1; + $_SESSION['relation'] = []; + $_SESSION['relation'][$GLOBALS['server']] = RelationParameters::fromArray($params)->toArray(); + + foreach ($queries as $query) { + $this->dummyDbi->addResult($query, []); + } + + $this->relation->renameTable('db_1', 'db_2', 'table_1', 'table_2'); + + $this->assertAllQueriesConsumed(); + } + + /** + * @return array>> + * @psalm-return list, string[]}> + */ + public function providerForTestRenameTable(): array + { + // phpcs:disable Generic.Files.LineLength.TooLong + return [ + [ + ['user' => 'user', 'db' => 'pmadb', 'commwork' => true, 'column_info' => 'column_info'], + ['UPDATE `pmadb`.`column_info` SET db_name = \'db_2\', table_name = \'table_2\' WHERE db_name = \'db_1\' AND table_name = \'table_1\''], + ], + [ + ['user' => 'user', 'db' => 'pmadb', 'displaywork' => true, 'relation' => 'relation', 'table_info' => 'table_info'], + ['UPDATE `pmadb`.`table_info` SET db_name = \'db_2\', table_name = \'table_2\' WHERE db_name = \'db_1\' AND table_name = \'table_1\''], + ], + [ + ['user' => 'user', 'db' => 'pmadb', 'relwork' => true, 'relation' => 'relation'], + [ + 'UPDATE `pmadb`.`relation` SET foreign_db = \'db_2\', foreign_table = \'table_2\' WHERE foreign_db = \'db_1\' AND foreign_table = \'table_1\'', + 'UPDATE `pmadb`.`relation` SET master_db = \'db_2\', master_table = \'table_2\' WHERE master_db = \'db_1\' AND master_table = \'table_1\'', + ], + ], + [ + ['user' => 'user', 'db' => 'pmadb', 'pdfwork' => true, 'pdf_pages' => 'pdf_pages', 'table_coords' => 'table_coords'], + ['DELETE FROM `pmadb`.`table_coords` WHERE db_name = \'db_1\' AND table_name = \'table_1\''], + ], + [ + ['user' => 'user', 'db' => 'pmadb', 'uiprefswork' => true, 'table_uiprefs' => 'table_uiprefs'], + ['UPDATE `pmadb`.`table_uiprefs` SET db_name = \'db_2\', table_name = \'table_2\' WHERE db_name = \'db_1\' AND table_name = \'table_1\''], + ], + [ + ['user' => 'user', 'db' => 'pmadb', 'navwork' => true, 'navigationhiding' => 'navigationhiding'], + [ + 'UPDATE `pmadb`.`navigationhiding` SET db_name = \'db_2\', table_name = \'table_2\' WHERE db_name = \'db_1\' AND table_name = \'table_1\'', + 'UPDATE `pmadb`.`navigationhiding` SET db_name = \'db_2\', item_name = \'table_2\' WHERE db_name = \'db_1\' AND item_name = \'table_1\' AND item_type = \'table\'', + ], + ], + ]; + // phpcs:enable + } + + public function testRenameTableEscaping(): void + { + $GLOBALS['server'] = 1; + $_SESSION['relation'] = []; + $_SESSION['relation'][$GLOBALS['server']] = RelationParameters::fromArray([ + 'user' => 'user', + 'db' => 'pma`db', + 'pdfwork' => true, + 'pdf_pages' => 'pdf_pages', + 'table_coords' => 'table`coords', + ])->toArray(); + + $this->dummyDbi->addResult( + 'UPDATE `pma``db`.`table``coords` SET db_name = \'db\\\'1\', table_name = \'table\\\'2\'' + . ' WHERE db_name = \'db\\\'1\' AND table_name = \'table\\\'1\'', + [] + ); + + $this->relation->renameTable('db\'1', 'db\'1', 'table\'1', 'table\'2'); + + $this->assertAllQueriesConsumed(); + } }