Skip to content

Commit 2a4803a

Browse files
committed
Merge branch 'QA_5_2'
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
2 parents 0fa4ebd + 6b35829 commit 2a4803a

7 files changed

Lines changed: 118 additions & 55 deletions

File tree

ChangeLog

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ phpMyAdmin - ChangeLog
1212
- issue #17766 Allow to open in a new tab copy and edit row actions
1313
- issue #17599 Fix error when handling an user that is not in privileges table
1414
- issue #17364 Fix error when trying to import a status monitor chart arrangement
15+
- issue #18106 Fix renaming database with a view
16+
- issue #18120 Fix bug with numerical tables during renaming database
1517

1618
5.2.1 (2023-02-07)
1719
- issue #17522 Fix case where the routes cache file is invalid

libraries/classes/Controllers/Database/OperationsController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function __invoke(ServerRequest $request): void
111111
// go back to current db, just in case
112112
$this->dbi->selectDb($GLOBALS['db']);
113113

114-
$tablesFull = $this->dbi->getTablesFull($GLOBALS['db']);
114+
$tableNames = $this->dbi->getTables($GLOBALS['db']);
115115

116116
// remove all foreign key constraints, otherwise we can get errors
117117
$exportSqlPlugin = Plugins::getPlugin('export', 'sql', [
@@ -121,15 +121,15 @@ public function __invoke(ServerRequest $request): void
121121

122122
// create stand-in tables for views
123123
$views = $this->operations->getViewsAndCreateSqlViewStandIn(
124-
$tablesFull,
124+
$tableNames,
125125
$exportSqlPlugin,
126126
$GLOBALS['db'],
127127
$newDatabaseName
128128
);
129129

130130
// copy tables
131131
$sqlConstraints = $this->operations->copyTables(
132-
$tablesFull,
132+
$tableNames,
133133
$move,
134134
$GLOBALS['db'],
135135
$newDatabaseName

libraries/classes/Operations.php

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use PhpMyAdmin\Plugins\Export\ExportSql;
1515

1616
use function __;
17-
use function array_keys;
1817
use function array_merge;
1918
use function count;
2019
use function explode;
@@ -118,40 +117,40 @@ public function createDbBeforeCopy(DatabaseName $newDatabaseName): void
118117
/**
119118
* Get views as an array and create SQL view stand-in
120119
*
121-
* @param array $tablesFull array of all tables in given db or dbs
120+
* @param string[] $tables array of all tables in given db or dbs
122121
* @param ExportSql $exportSqlPlugin export plugin instance
123122
* @param string $db database name
124123
*
125124
* @return array
126125
*/
127126
public function getViewsAndCreateSqlViewStandIn(
128-
array $tablesFull,
127+
array $tables,
129128
$exportSqlPlugin,
130129
$db,
131130
DatabaseName $newDatabaseName
132131
) {
133132
$views = [];
134-
foreach (array_keys($tablesFull) as $tableName) {
133+
foreach ($tables as $table) {
135134
// to be able to rename a db containing views,
136135
// first all the views are collected and a stand-in is created
137136
// the real views are created after the tables
138-
if (! $this->dbi->getTable($db, (string) $tableName)->isView()) {
137+
if (! $this->dbi->getTable($db, $table)->isView()) {
139138
continue;
140139
}
141140

142141
// If view exists, and 'add drop view' is selected: Drop it!
143142
if ($_POST['what'] !== 'nocopy' && isset($_POST['drop_if_exists']) && $_POST['drop_if_exists'] === 'true') {
144143
$dropQuery = 'DROP VIEW IF EXISTS '
145144
. Util::backquote($newDatabaseName) . '.'
146-
. Util::backquote($tableName);
145+
. Util::backquote($table);
147146
$this->dbi->query($dropQuery);
148147

149148
$GLOBALS['sql_query'] .= "\n" . $dropQuery . ';';
150149
}
151150

152-
$views[] = $tableName;
151+
$views[] = $table;
153152
// Create stand-in definition to resolve view dependencies
154-
$sqlViewStandin = $exportSqlPlugin->getTableDefStandIn($db, $tableName);
153+
$sqlViewStandin = $exportSqlPlugin->getTableDefStandIn($db, $table);
155154
$this->dbi->selectDb($newDatabaseName);
156155
$this->dbi->query($sqlViewStandin);
157156
$GLOBALS['sql_query'] .= "\n" . $sqlViewStandin;
@@ -163,18 +162,18 @@ public function getViewsAndCreateSqlViewStandIn(
163162
/**
164163
* Get sql query for copy/rename table and boolean for whether copy/rename or not
165164
*
166-
* @param array $tablesFull array of all tables in given db or dbs
167-
* @param bool $move whether database name is empty or not
168-
* @param string $db database name
165+
* @param string[] $tables array of all tables in given db or dbs
166+
* @param bool $move whether database name is empty or not
167+
* @param string $db database name
169168
*
170169
* @return array SQL queries for the constraints
171170
*/
172-
public function copyTables(array $tablesFull, $move, $db, DatabaseName $newDatabaseName)
171+
public function copyTables(array $tables, $move, $db, DatabaseName $newDatabaseName)
173172
{
174173
$sqlContraints = [];
175-
foreach (array_keys($tablesFull) as $tableName) {
174+
foreach ($tables as $table) {
176175
// skip the views; we have created stand-in definitions
177-
if ($this->dbi->getTable($db, (string) $tableName)->isView()) {
176+
if ($this->dbi->getTable($db, $table)->isView()) {
178177
continue;
179178
}
180179

@@ -183,7 +182,7 @@ public function copyTables(array $tablesFull, $move, $db, DatabaseName $newDatab
183182

184183
// do not copy the data from a Merge table
185184
// note: on the calling FORM, 'data' means 'structure and data'
186-
if ($this->dbi->getTable($db, (string) $tableName)->isMerge()) {
185+
if ($this->dbi->getTable($db, $table)->isMerge()) {
187186
if ($copyMode === 'data') {
188187
$copyMode = 'structure';
189188
}
@@ -200,14 +199,14 @@ public function copyTables(array $tablesFull, $move, $db, DatabaseName $newDatab
200199
// keep the triggers from the original db+table
201200
// (third param is empty because delimiters are only intended
202201
// for importing via the mysql client or our Import feature)
203-
$triggers = Triggers::getDetails($this->dbi, $db, (string) $tableName, '');
202+
$triggers = Triggers::getDetails($this->dbi, $db, $table, '');
204203

205204
if (
206205
! Table::moveCopy(
207206
$db,
208-
$tableName,
207+
$table,
209208
$newDatabaseName->getName(),
210-
$tableName,
209+
$table,
211210
($copyMode ?? 'data'),
212211
$move,
213212
'db_copy',

libraries/classes/Table.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,10 +1015,11 @@ public static function moveCopy(
10151015
$GLOBALS['sql_auto_increment'] = $_POST['sql_auto_increment'];
10161016
}
10171017

1018+
$isView = (new Table($sourceTable, $sourceDb, $GLOBALS['dbi']))->isView();
10181019
/**
10191020
* The old structure of the table.
10201021
*/
1021-
$sqlStructure = $exportSqlPlugin->getTableDef($sourceDb, $sourceTable, false, false);
1022+
$sqlStructure = $exportSqlPlugin->getTableDef($sourceDb, $sourceTable, false, false, $isView);
10221023

10231024
unset($noConstraintsComments);
10241025

@@ -1045,7 +1046,7 @@ public static function moveCopy(
10451046
*/
10461047
$statement = new DropStatement();
10471048

1048-
$tbl = new Table($targetDb, $targetTable, $GLOBALS['dbi']);
1049+
$tbl = new Table($targetTable, $targetDb, $GLOBALS['dbi']);
10491050

10501051
$statement->options = new OptionsArray(
10511052
[

phpstan-baseline.neon

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5970,11 +5970,6 @@ parameters:
59705970
count: 1
59715971
path: libraries/classes/Operations.php
59725972

5973-
-
5974-
message: "#^Method PhpMyAdmin\\\\Operations\\:\\:copyTables\\(\\) has parameter \\$tablesFull with no value type specified in iterable type array\\.$#"
5975-
count: 1
5976-
path: libraries/classes/Operations.php
5977-
59785973
-
59795974
message: "#^Method PhpMyAdmin\\\\Operations\\:\\:copyTables\\(\\) return type has no value type specified in iterable type array\\.$#"
59805975
count: 1
@@ -6005,11 +6000,6 @@ parameters:
60056000
count: 1
60066001
path: libraries/classes/Operations.php
60076002

6008-
-
6009-
message: "#^Method PhpMyAdmin\\\\Operations\\:\\:getViewsAndCreateSqlViewStandIn\\(\\) has parameter \\$tablesFull with no value type specified in iterable type array\\.$#"
6010-
count: 1
6011-
path: libraries/classes/Operations.php
6012-
60136003
-
60146004
message: "#^Method PhpMyAdmin\\\\Operations\\:\\:getViewsAndCreateSqlViewStandIn\\(\\) return type has no value type specified in iterable type array\\.$#"
60156005
count: 1
@@ -6022,29 +6012,14 @@ parameters:
60226012

60236013
-
60246014
message: "#^Parameter \\#1 \\$identifier of static method PhpMyAdmin\\\\Util\\:\\:backquote\\(\\) expects string\\|Stringable\\|null, \\(int\\|string\\) given\\.$#"
6025-
count: 3
6015+
count: 2
60266016
path: libraries/classes/Operations.php
60276017

60286018
-
60296019
message: "#^Parameter \\#1 \\$query of method PhpMyAdmin\\\\DatabaseInterface\\:\\:query\\(\\) expects string, string\\|null given\\.$#"
60306020
count: 1
60316021
path: libraries/classes/Operations.php
60326022

6033-
-
6034-
message: "#^Parameter \\#2 \\$sourceTable of static method PhpMyAdmin\\\\Table\\:\\:moveCopy\\(\\) expects string, \\(int\\|string\\) given\\.$#"
6035-
count: 1
6036-
path: libraries/classes/Operations.php
6037-
6038-
-
6039-
message: "#^Parameter \\#2 \\$view of method PhpMyAdmin\\\\Plugins\\\\Export\\\\ExportSql\\:\\:getTableDefStandIn\\(\\) expects string, \\(int\\|string\\) given\\.$#"
6040-
count: 1
6041-
path: libraries/classes/Operations.php
6042-
6043-
-
6044-
message: "#^Parameter \\#4 \\$targetTable of static method PhpMyAdmin\\\\Table\\:\\:moveCopy\\(\\) expects string, \\(int\\|string\\) given\\.$#"
6045-
count: 1
6046-
path: libraries/classes/Operations.php
6047-
60486023
-
60496024
message: "#^Method PhpMyAdmin\\\\Partitioning\\\\Maintenance\\:\\:analyze\\(\\) return type has no value type specified in iterable type array\\.$#"
60506025
count: 1

psalm-baseline.xml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10229,10 +10229,6 @@
1022910229
<MixedArgumentTypeCoercion>
1023010230
<code>$master</code>
1023110231
<code>$master</code>
10232-
<code>$tableName</code>
10233-
<code>$tableName</code>
10234-
<code>$tableName</code>
10235-
<code>$tableName</code>
1023610232
</MixedArgumentTypeCoercion>
1023710233
<MixedArrayAccess>
1023810234
<code><![CDATA[$arr['foreign_db']]]></code>
@@ -18434,6 +18430,9 @@
1843418430
</UndefinedMethod>
1843518431
</file>
1843618432
<file src="test/classes/TableTest.php">
18433+
<InvalidArrayOffset>
18434+
<code><![CDATA[$GLOBALS['sql_drop_table']]]></code>
18435+
</InvalidArrayOffset>
1843718436
<MixedAssignment>
1843818437
<code>$is_define_property</code>
1843918438
<code>$sql</code>
@@ -18444,10 +18443,16 @@
1844418443
</MixedInferredReturnType>
1844518444
<MixedMethodCall>
1844618445
<code>method</code>
18446+
<code>method</code>
18447+
<code>method</code>
18448+
<code>will</code>
18449+
<code>will</code>
1844718450
<code>will</code>
1844818451
</MixedMethodCall>
1844918452
<UndefinedMethod>
1845018453
<code>expects</code>
18454+
<code>expects</code>
18455+
<code>expects</code>
1845118456
</UndefinedMethod>
1845218457
</file>
1845318458
<file src="test/classes/TemplateTest.php">

test/classes/TableTest.php

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,18 @@ protected function setUp(): void
249249
Connection::TYPE_USER,
250250
[],
251251
],
252+
[
253+
"SELECT 1 FROM information_schema.VIEWS WHERE TABLE_SCHEMA = 'aa' AND TABLE_NAME = 'ad'",
254+
0,
255+
Connection::TYPE_USER,
256+
['ad'],
257+
],
258+
[
259+
"SELECT 1 FROM information_schema.VIEWS WHERE TABLE_SCHEMA = 'bb' AND TABLE_NAME = 'ad'",
260+
0,
261+
Connection::TYPE_USER,
262+
[],
263+
],
252264
];
253265

254266
$resultStub = $this->createMock(DummyResult::class);
@@ -1408,9 +1420,18 @@ public function testCheckIfMinRecordsExist(): void
14081420
*/
14091421
public function testCountRecords(): void
14101422
{
1423+
$resultStub = $this->createMock(DummyResult::class);
1424+
$resultStub->expects($this->any())
1425+
->method('numRows')
1426+
->will($this->returnValue(20));
1427+
1428+
$dbi = clone $GLOBALS['dbi'];
1429+
$dbi->expects($this->any())->method('tryQuery')
1430+
->will($this->returnValue($resultStub));
1431+
14111432
$table = 'PMA_BookMark';
14121433
$db = 'PMA';
1413-
$tableObj = new Table($table, $db, $GLOBALS['dbi']);
1434+
$tableObj = new Table($table, $db, $dbi);
14141435

14151436
$this->assertEquals(
14161437
20,
@@ -1459,8 +1480,23 @@ public function testMoveCopy(): void
14591480
$move = true;
14601481
$mode = 'one_table';
14611482

1483+
unset($GLOBALS['sql_drop_table']);
1484+
1485+
$getTableMap = [
1486+
[
1487+
$target_db,
1488+
$target_table,
1489+
new Table($target_table, $target_db, $GLOBALS['dbi']),
1490+
],
1491+
[
1492+
'aa',
1493+
'ad',
1494+
new Table('ad', 'aa', $GLOBALS['dbi']),
1495+
],
1496+
];
1497+
14621498
$GLOBALS['dbi']->expects($this->any())->method('getTable')
1463-
->will($this->returnValue(new Table($target_table, $target_db, $GLOBALS['dbi'])));
1499+
->will($this->returnValueMap($getTableMap));
14641500

14651501
$return = Table::moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode, true);
14661502

@@ -1485,6 +1521,51 @@ public function testMoveCopy(): void
14851521
$this->assertStringContainsString($sql_query, $GLOBALS['sql_query']);
14861522
$sql_query = 'DROP VIEW `PMA`.`PMA_BookMark`';
14871523
$this->assertStringNotContainsString($sql_query, $GLOBALS['sql_query']);
1524+
1525+
// Renaming DB with a view bug
1526+
$resultStub = $this->createMock(DummyResult::class);
1527+
$GLOBALS['dbi']->expects($this->any())->method('tryQuery')
1528+
->will($this->returnValueMap([
1529+
[
1530+
'SHOW CREATE TABLE `aa`.`ad`',
1531+
Connection::TYPE_USER,
1532+
DatabaseInterface::QUERY_BUFFERED,
1533+
true,
1534+
$resultStub,
1535+
],
1536+
]));
1537+
$resultStub->expects($this->any())
1538+
->method('fetchRow')
1539+
->will($this->returnValue([
1540+
'ad',
1541+
'CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`' .
1542+
' SQL SECURITY DEFINER VIEW `ad` AS select `aa`.`bb`.`ac` AS `ac` from `bb`',
1543+
'utf8mb4',
1544+
'utf8mb4_unicode_ci',
1545+
]));
1546+
1547+
$this->loadContainerBuilder();
1548+
$this->loadDbiIntoContainerBuilder();
1549+
1550+
$GLOBALS['sql_query'] = '';
1551+
$return = Table::moveCopy(
1552+
'aa',
1553+
'ad',
1554+
'bb',
1555+
'ad',
1556+
'structure',
1557+
true,
1558+
'db_copy',
1559+
true
1560+
);
1561+
$this->assertEquals(true, $return);
1562+
$this->assertStringContainsString('DROP TABLE IF EXISTS `bb`.`ad`;', $GLOBALS['sql_query']);
1563+
$this->assertStringContainsString(
1564+
'CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`' .
1565+
' SQL SECURITY DEFINER VIEW `bb`.`ad` AS SELECT `bb`.`ac` AS `ac` FROM `bb` ;',
1566+
$GLOBALS['sql_query']
1567+
);
1568+
$this->assertStringContainsString('DROP VIEW `aa`.`ad`;', $GLOBALS['sql_query']);
14881569
}
14891570

14901571
/**

0 commit comments

Comments
 (0)