Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions js/src/sql.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ AJAX.registerTeardown('sql.js', function () {
$(document).off('submit', '.maxRowsForm');
$(document).off('click', '#view_as');
$(document).off('click', '#sqlquery');

$('#simulateDmlModal').modal('hide');
});

/**
Expand Down
50 changes: 33 additions & 17 deletions libraries/classes/Import/SimulateDml.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ public function getMatchedRows(Parser $parser, Statement $statement): array
}

// Execute the query and get the number of matched rows.
$matchedRows = $this->executeMatchedRowQuery($matchedRowsQuery);
$matchedRows = $this->executeMatchedRowQuery($matchedRowsQuery['count']);
$selectQuery = $matchedRowsQuery['select'];
$matchedRowsUrl = Url::getFromRoute('/sql', [
'db' => $GLOBALS['db'],
'sql_query' => $matchedRowsQuery,
'sql_signature' => Core::signSqlQuery($matchedRowsQuery),
'sql_query' => $selectQuery,
'sql_signature' => Core::signSqlQuery($selectQuery),
]);

return [
Expand All @@ -78,20 +79,20 @@ public function getMatchedRows(Parser $parser, Statement $statement): array
private function executeMatchedRowQuery(string $matchedRowQuery): int
{
$this->dbi->selectDb($GLOBALS['db']);
$result = $this->dbi->tryQuery($matchedRowQuery);
if (! $result) {
$count = $this->dbi->fetchValue($matchedRowQuery);
if ($count === false) {
return 0;
}

return (int) $result->numRows();
return (int) $count;
}

/**
* Transforms a DELETE query into SELECT statement.
*
* @return string SQL query
* @psalm-return array{select: string, count: string} SQL queries
*/
private function getSimulatedDeleteQuery(Parser $parser, DeleteStatement $statement): string
private function getSimulatedDeleteQuery(Parser $parser, DeleteStatement $statement): array
{
$tableReferences = Query::getTables($statement);
Assert::count($tableReferences, 1, 'No joins allowed in simulation query');
Expand All @@ -104,15 +105,22 @@ private function getSimulatedDeleteQuery(Parser $parser, DeleteStatement $statem
: ' ORDER BY ' . Query::getClause($statement, $parser->list, 'ORDER BY');
$limit = $statement->limit === null ? '' : ' LIMIT ' . Query::getClause($statement, $parser->list, 'LIMIT');

return 'SELECT * FROM ' . $tableReferences[0] . $where . $order . $limit;
return [
'select' => 'SELECT * FROM (' .
'SELECT * FROM ' . $tableReferences[0] . $where . $order . $limit .
') AS pma_tmp',
'count' => 'SELECT COUNT(*) FROM (' .
'SELECT 1 FROM ' . $tableReferences[0] . $where . $order . $limit .
') AS pma_tmp',
];
}

/**
* Transforms a UPDATE query into SELECT statement.
*
* @return string SQL query
* @psalm-return array{select: string, count: string} SQL queies
*/
private function getSimulatedUpdateQuery(Parser $parser, UpdateStatement $statement): string
private function getSimulatedUpdateQuery(Parser $parser, UpdateStatement $statement): array
{
$tableReferences = Query::getTables($statement);
Assert::count($tableReferences, 1, 'No joins allowed in simulation query');
Expand All @@ -129,7 +137,7 @@ private function getSimulatedUpdateQuery(Parser $parser, UpdateStatement $statem
}

$oldColumns[] = Util::backquote($column);
$values[$column] = $set->value . ' AS ' . ($newColumns[] = Util::backquote($column . ' `new`'));
$values[$column] = $set->value . ' AS ' . ($newColumns[] = Util::backquote($column . ' *new*'));
}

$condition = Query::getClause($statement, $parser->list, 'WHERE');
Expand All @@ -139,10 +147,18 @@ private function getSimulatedUpdateQuery(Parser $parser, UpdateStatement $statem
: ' ORDER BY ' . Query::getClause($statement, $parser->list, 'ORDER BY');
$limit = $statement->limit === null ? '' : ' LIMIT ' . Query::getClause($statement, $parser->list, 'LIMIT');

return 'SELECT *' .
' FROM (' .
'SELECT *, ' . implode(', ', $values) . ' FROM ' . $tableReferences[0] . $where . $order . $limit .
') AS `pma_tmp`' .
' WHERE NOT (' . implode(', ', $oldColumns) . ') <=> (' . implode(', ', $newColumns) . ')';
return [
'select' => 'SELECT *' .
' FROM (' .
'SELECT *, ' . implode(', ', $values) . ' FROM ' . $tableReferences[0] . $where . $order . $limit .
') AS `pma_tmp`' .
' WHERE NOT (' . implode(', ', $oldColumns) . ') <=> (' . implode(', ', $newColumns) . ')',
'count' => 'SELECT COUNT(*)' .
' FROM (' .
'SELECT ' . implode(', ', $oldColumns) . ', ' . implode(', ', $values) .
' FROM ' . $tableReferences[0] . $where . $order . $limit .
') AS `pma_tmp`' .
' WHERE NOT (' . implode(', ', $oldColumns) . ') <=> (' . implode(', ', $newColumns) . ')',
];
}
}
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -20755,11 +20755,6 @@ parameters:
count: 1
path: libraries/classes/Import/Ajax.php

-
message: "#^Only booleans are allowed in a negated boolean, PhpMyAdmin\\\\Dbal\\\\ResultInterface\\|false given\\.$#"
count: 1
path: libraries/classes/Import/SimulateDml.php

-
message: "#^Parameter \\#1 \\$dbname of method PhpMyAdmin\\\\DatabaseInterface\\:\\:selectDb\\(\\) expects PhpMyAdmin\\\\Dbal\\\\DatabaseName\\|string, mixed given\\.$#"
count: 1
Expand Down
Loading
Loading