Merge pull request #17360 from mauriciofauth/issue-17359

Fix bug when renaming tables with config storage enabled
This commit is contained in:
Maurício Meneghini Fauth 2022-02-09 15:07:26 -03:00 committed by GitHub
commit d853d0dcc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 106 additions and 12 deletions

View File

@ -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,

View File

@ -1807,4 +1807,90 @@ class RelationTest extends AbstractTestCase
$this->assertAllQueriesConsumed();
}
/**
* @param array<string, bool|string> $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<int, array<int, array<int|string, bool|string>>>
* @psalm-return list<array{array<string, bool|string>, 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();
}
}