From e2de1af91009ac8bbcf9ec369753d883b515203b Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Wed, 18 Dec 2024 22:46:57 +0000 Subject: [PATCH 01/16] Remove $GLOBALS['cached_affected_rows'] Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 6 ------ src/DatabaseInterface.php | 7 +++++-- src/Server/Status/Monitor.php | 4 +--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4c6e32e1b1..2c4fa66162 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6957,12 +6957,6 @@ parameters: count: 1 path: src/DatabaseInterface.php - - - message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:affectedRows\(\) should return int\|numeric\-string but returns mixed\.$#' - identifier: return.type - count: 1 - path: src/DatabaseInterface.php - - message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:getColumnNames\(\) should return list\ but returns array\\.$#' identifier: return.type diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index e018c8f74b..d1bad97428 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -137,6 +137,9 @@ class DatabaseInterface implements DbalInterface private ListDatabase|null $databaseList = null; private readonly Config $config; + /** @var int|numeric-string */ + private static int|string $cachedAffectedRows = -1; + /** @param DbiExtension $extension Object to be used for database queries */ public function __construct(private DbiExtension $extension) { @@ -199,7 +202,7 @@ class DatabaseInterface implements DbalInterface } if ($cacheAffectedRows) { - $GLOBALS['cached_affected_rows'] = $this->affectedRows($connectionType, false); + self::$cachedAffectedRows = $this->affectedRows($connectionType, false); } if ($this->config->config->debug->sql) { @@ -1785,7 +1788,7 @@ class DatabaseInterface implements DbalInterface } if ($getFromCache) { - return $GLOBALS['cached_affected_rows']; + return self::$cachedAffectedRows; } return $this->extension->affectedRows($this->connections[$connectionType->value]); diff --git a/src/Server/Status/Monitor.php b/src/Server/Status/Monitor.php index f4935f1be3..7f7fe62055 100644 --- a/src/Server/Status/Monitor.php +++ b/src/Server/Status/Monitor.php @@ -485,8 +485,6 @@ class Monitor string $database, string $query, ): array { - $GLOBALS['cached_affected_rows'] ??= null; - $return = []; if ($database !== '') { @@ -503,7 +501,7 @@ class Monitor $sqlQuery = preg_replace('/^(\s*SELECT)/i', '\\1 SQL_NO_CACHE', $query); $this->dbi->tryQuery($sqlQuery); - $return['affectedRows'] = $GLOBALS['cached_affected_rows']; + $return['affectedRows'] = $this->dbi->affectedRows(); $result = $this->dbi->tryQuery('EXPLAIN ' . $sqlQuery); if ($result !== false) { From 319ae0d2e3ce56775b903a3be12865d755ef27b1 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 01:06:55 +0000 Subject: [PATCH 02/16] Split off fetchResultSimple Signed-off-by: Kamil Tekiela --- psalm-baseline.xml | 12 +- src/Bookmarks/BookmarkRepository.php | 2 +- src/ConfigStorage/Relation.php | 2 +- .../MultiTableQuery/TablesController.php | 2 +- src/Database/CentralColumns.php | 12 +- src/Database/Designer/Common.php | 2 +- src/Database/Events.php | 2 +- src/Database/Routines.php | 10 +- src/DatabaseInterface.php | 45 ++++--- src/Dbal/DbalInterface.php | 8 +- src/ListDatabase.php | 2 +- src/Navigation/Nodes/Node.php | 6 +- src/Navigation/Nodes/NodeTable.php | 4 +- src/Navigation/Nodes/ObjectFetcher.php | 6 +- src/Normalization.php | 6 +- src/Operations.php | 2 +- src/Partitioning/Maintenance.php | 8 +- src/Partitioning/Partition.php | 8 +- src/Plugins/Export/ExportSql.php | 2 +- src/Plugins/Export/ExportXml.php | 4 +- src/Plugins/Import/ImportCsv.php | 2 +- src/Profiling.php | 2 +- src/Replication/Replication.php | 3 +- src/Replication/ReplicationGui.php | 10 +- src/Replication/ReplicationInfo.php | 10 +- src/Server/Privileges.php | 8 +- src/Table/Maintenance.php | 10 +- src/Table/Table.php | 2 +- src/Triggers/Triggers.php | 4 +- tests/unit/Database/CentralColumnsTest.php | 18 ++- tests/unit/Navigation/Nodes/NodeTest.php | 6 +- tests/unit/NormalizationTest.php | 2 +- tests/unit/Partitioning/PartitionTest.php | 2 +- tests/unit/Plugins/Export/ExportSqlTest.php | 2 +- tests/unit/Plugins/Export/ExportXmlTest.php | 114 ++++++++++-------- tests/unit/Table/TableTest.php | 57 +++++---- 36 files changed, 205 insertions(+), 192 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 9fe8f3e0f4..52d039744f 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -3825,7 +3825,7 @@ - dbi->fetchResult($query, null, null, ConnectionType::ControlUser)]]> + dbi->fetchResultSimple($query, null, ConnectionType::ControlUser)]]> @@ -4230,7 +4230,7 @@ - fetchResult($sql, null, 'Field', $connectionType)]]> + fetchResultSimple($sql, 'Field', $connectionType)]]> @@ -4281,7 +4281,7 @@ - fetchResult($sql, null, null, $connectionType)]]> + fetchResultSimple($sql, null, $connectionType)]]> - dbi->fetchResult($query)]]> - dbi->fetchResult($query)]]> - dbi->fetchResult($query)]]> + dbi->fetchResultSimple($query)]]> + dbi->fetchResultSimple($query)]]> + dbi->fetchResultSimple($query)]]> diff --git a/src/Bookmarks/BookmarkRepository.php b/src/Bookmarks/BookmarkRepository.php index f4f5c40151..35552ea865 100644 --- a/src/Bookmarks/BookmarkRepository.php +++ b/src/Bookmarks/BookmarkRepository.php @@ -95,7 +95,7 @@ final class BookmarkRepository $query .= ' ORDER BY label ASC'; - $result = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $result = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); $bookmarks = []; foreach ($result as $row) { diff --git a/src/ConfigStorage/Relation.php b/src/ConfigStorage/Relation.php index f0570b84bb..3d1ba90c46 100644 --- a/src/ConfigStorage/Relation.php +++ b/src/ConfigStorage/Relation.php @@ -693,7 +693,7 @@ class Relation WHERE `username` = ' . $this->dbi->quoteString($username) . ' ORDER BY `id` DESC'; - return $this->dbi->fetchResult($histQuery, null, null, ConnectionType::ControlUser); + return $this->dbi->fetchResultSimple($histQuery, null, ConnectionType::ControlUser); } /** diff --git a/src/Controllers/Database/MultiTableQuery/TablesController.php b/src/Controllers/Database/MultiTableQuery/TablesController.php index 09dd98196e..6da9db31d4 100644 --- a/src/Controllers/Database/MultiTableQuery/TablesController.php +++ b/src/Controllers/Database/MultiTableQuery/TablesController.php @@ -29,7 +29,7 @@ final class TablesController implements InvocableController $tablesListForQuery = array_map($this->dbi->quoteString(...), $tables); - $constrains = $this->dbi->fetchResult( + $constrains = $this->dbi->fetchResultSimple( QueryGenerator::getInformationSchemaForeignKeyConstraintsRequest( $this->dbi->quoteString($db), implode(',', $tablesListForQuery), diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index c5139452f7..e2ad273be3 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -122,7 +122,7 @@ class CentralColumns . 'LIMIT ' . $from . ', ' . $num . ';'; } - $hasList = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $hasList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); $this->handleColumnExtra($hasList); return $hasList; @@ -147,7 +147,7 @@ class CentralColumns $query = 'SELECT count(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' ' . 'WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ';'; - $res = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $res = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); if (isset($res[0])) { return (int) $res[0]; } @@ -180,7 +180,7 @@ class CentralColumns . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; - return $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + return $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); } /** @@ -207,7 +207,7 @@ class CentralColumns $query = 'SELECT * FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; - $hasList = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $hasList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); $this->handleColumnExtra($hasList); return $hasList; @@ -692,7 +692,7 @@ class CentralColumns $query .= ';'; } - $columnsList = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $columnsList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); $this->handleColumnExtra($columnsList); return $columnsList; @@ -771,7 +771,7 @@ class CentralColumns $query = 'SELECT COUNT(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ($num === 0 ? '' : 'LIMIT ' . $from . ', ' . $num) . ';'; - $result = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $result = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); if (isset($result[0])) { return (int) $result[0]; diff --git a/src/Database/Designer/Common.php b/src/Database/Designer/Common.php index 8e05a8dd93..4da0ca7c23 100644 --- a/src/Database/Designer/Common.php +++ b/src/Database/Designer/Common.php @@ -330,7 +330,7 @@ class Common . ' FROM ' . Util::backquote($pdfFeature->database) . '.' . Util::backquote($pdfFeature->pdfPages) . ' WHERE `page_descr` = ' . $this->dbi->quoteString($pg, ConnectionType::ControlUser); - $pageNos = $this->dbi->fetchResult($query, null, null, ConnectionType::ControlUser); + $pageNos = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); return $pageNos !== []; } diff --git a/src/Database/Events.php b/src/Database/Events.php index ca7f732c44..475a040338 100644 --- a/src/Database/Events.php +++ b/src/Database/Events.php @@ -367,7 +367,7 @@ class Events } $result = []; - $events = $this->dbi->fetchResult($query); + $events = $this->dbi->fetchResultSimple($query); /** @var string[] $event */ foreach ($events as $event) { diff --git a/src/Database/Routines.php b/src/Database/Routines.php index 655ec85884..de33394658 100644 --- a/src/Database/Routines.php +++ b/src/Database/Routines.php @@ -1256,7 +1256,7 @@ class Routines in_array($which, ['FUNCTION', 'PROCEDURE'], true) ? $which : null, $name === '' ? null : $dbi->quoteString($name), ); - $routines = $dbi->fetchResult($query); + $routines = $dbi->fetchResultSimple($query); } else { $routines = []; @@ -1266,7 +1266,7 @@ class Routines $query .= ' AND `Name` = ' . $dbi->quoteString($name); } - $routines = $dbi->fetchResult($query); + $routines = $dbi->fetchResultSimple($query); } if ($which === 'PROCEDURE' || $which == null) { @@ -1275,7 +1275,7 @@ class Routines $query .= ' AND `Name` = ' . $dbi->quoteString($name); } - $routines = array_merge($routines, $dbi->fetchResult($query)); + $routines = array_merge($routines, $dbi->fetchResultSimple($query)); } } @@ -1319,7 +1319,7 @@ class Routines public static function getFunctionNames(DatabaseInterface $dbi, string $db): array { /** @psalm-var list $functions */ - $functions = $dbi->fetchResult('SHOW FUNCTION STATUS;'); + $functions = $dbi->fetchResultSimple('SHOW FUNCTION STATUS;'); $names = []; foreach ($functions as $function) { if ($function['Db'] !== $db || $function['Type'] !== 'FUNCTION' || $function['Name'] === '') { @@ -1339,7 +1339,7 @@ class Routines public static function getProcedureNames(DatabaseInterface $dbi, string $db): array { /** @psalm-var list $procedures */ - $procedures = $dbi->fetchResult('SHOW PROCEDURE STATUS;'); + $procedures = $dbi->fetchResultSimple('SHOW PROCEDURE STATUS;'); $names = []; foreach ($procedures as $procedure) { if ($procedure['Db'] !== $db || $procedure['Type'] !== 'PROCEDURE' || $procedure['Name'] === '') { diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index d1bad97428..4ee8ce5138 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -304,9 +304,8 @@ class DatabaseInterface implements DbalInterface } /** @var array $tables */ - $tables = $this->fetchResult( + $tables = $this->fetchResultSimple( 'SHOW TABLES FROM ' . Util::backquote($database) . ';', - null, 0, $connectionType, ); @@ -984,7 +983,7 @@ class DatabaseInterface implements DbalInterface $sql = QueryGenerator::getColumnsSql($database, $table); // We only need the 'Field' column which contains the table's column names - return $this->fetchResult($sql, null, 'Field', $connectionType); + return $this->fetchResultSimple($sql, 'Field', $connectionType); } /** @@ -1020,7 +1019,7 @@ class DatabaseInterface implements DbalInterface ): array { $sql = QueryGenerator::getTableIndexesSql($database, $table); - return $this->fetchResult($sql, null, null, $connectionType); + return $this->fetchResultSimple($sql, null, $connectionType); } /** @@ -1281,17 +1280,17 @@ class DatabaseInterface implements DbalInterface * // $users['admin']['John Doe'] = '123' * * - * @param string $query query to execute - * @param string|int|mixed[]|null $key field-name or offset + * @param string $query query to execute + * @param string|int|mixed[] $key field-name or offset * used as key for array * or array of those - * @param string|int|null $value value-name or offset used as value for array + * @param string|int|null $value value-name or offset used as value for array * * @return mixed[] resultrows or values indexed by $key */ public function fetchResult( string $query, - string|int|array|null $key = null, + string|int|array $key, string|int|null $value = null, ConnectionType $connectionType = ConnectionType::User, ): array { @@ -1304,15 +1303,6 @@ class DatabaseInterface implements DbalInterface return []; } - if ($key === null) { - // no nested array if only one field is in result - if ($value === 0 || $result->numFields() === 1) { - return $result->fetchAllColumn(); - } - - return $value === null ? $result->fetchAllAssoc() : array_column($result->fetchAllAssoc(), $value); - } - if (is_array($key)) { while ($row = $result->fetchAssoc()) { $resultTarget =& $resultRows; @@ -1349,6 +1339,25 @@ class DatabaseInterface implements DbalInterface return $resultRows; } + /** @return array */ + public function fetchResultSimple( + string $query, + string|int|null $value = null, + ConnectionType $connectionType = ConnectionType::User, + ): array { + $result = $this->tryQuery($query, $connectionType, cacheAffectedRows: false); + + if ($result === false) { + return []; + } + + if ($value === 0 || $result->numFields() === 1) { + return $result->fetchAllColumn(); + } + + return $value === null ? $result->fetchAllAssoc() : array_column($result->fetchAllAssoc(), $value); + } + /** * Get supported SQL compatibility modes * @@ -1565,7 +1574,7 @@ class DatabaseInterface implements DbalInterface private function getCurrentUserGrants(): array { /** @var string[] $grants */ - $grants = $this->fetchResult('SHOW GRANTS FOR CURRENT_USER();'); + $grants = $this->fetchResultSimple('SHOW GRANTS FOR CURRENT_USER();'); return $grants; } diff --git a/src/Dbal/DbalInterface.php b/src/Dbal/DbalInterface.php index 4e6776a204..d93278417e 100644 --- a/src/Dbal/DbalInterface.php +++ b/src/Dbal/DbalInterface.php @@ -352,15 +352,15 @@ interface DbalInterface * // $users['admin']['John Doe'] = '123' * * - * @param string $query query to execute - * @param string|int|mixed[]|null $key field-name or offset used as key for array or array of those - * @param string|int|null $value value-name or offset used as value for array + * @param string $query query to execute + * @param string|int|mixed[] $key field-name or offset used as key for array or array of those + * @param string|int|null $value value-name or offset used as value for array * * @return mixed[] resultrows or values indexed by $key */ public function fetchResult( string $query, - string|int|array|null $key = null, + string|int|array $key, string|int|null $value = null, ConnectionType $connectionType = ConnectionType::User, ): array; diff --git a/src/ListDatabase.php b/src/ListDatabase.php index 6c43d72ef7..00af6b8402 100644 --- a/src/ListDatabase.php +++ b/src/ListDatabase.php @@ -100,7 +100,7 @@ class ListDatabase extends ArrayObject } if ($command !== '') { - $databaseList = $this->dbi->fetchResult($command); + $databaseList = $this->dbi->fetchResultSimple($command); } if ($this->config->settings['NaturalOrder']) { diff --git a/src/Navigation/Nodes/Node.php b/src/Navigation/Nodes/Node.php index 746a266a8e..29c3ab95b6 100644 --- a/src/Navigation/Nodes/Node.php +++ b/src/Navigation/Nodes/Node.php @@ -626,7 +626,7 @@ class Node $maxItems, ); - return $dbi->fetchResult($query); + return $dbi->fetchResultSimple($query); } $dbSeparator = $this->config->settings['NavigationTreeDbSeparator']; @@ -643,7 +643,7 @@ class Node $maxItems, ); - return $dbi->fetchResult($query); + return $dbi->fetchResultSimple($query); } /** @@ -725,7 +725,7 @@ class Node implode('OR', $subClauses), ); - return $dbi->fetchResult($query); + return $dbi->fetchResultSimple($query); } /** diff --git a/src/Navigation/Nodes/NodeTable.php b/src/Navigation/Nodes/NodeTable.php index 43fc7009c6..afcf296d2a 100644 --- a/src/Navigation/Nodes/NodeTable.php +++ b/src/Navigation/Nodes/NodeTable.php @@ -164,7 +164,7 @@ class NodeTable extends NodeDatabaseChild $query .= 'AND `TABLE_SCHEMA`=' . $dbi->quoteString($db) . ' '; $query .= 'ORDER BY `COLUMN_NAME` ASC '; $query .= 'LIMIT ' . $pos . ', ' . $maxItems; - $retval = $dbi->fetchResult($query); + $retval = $dbi->fetchResultSimple($query); break; } @@ -229,7 +229,7 @@ class NodeTable extends NodeDatabaseChild . Util::getCollateForIS() . '=' . $dbi->quoteString($table) . ' '; $query .= 'ORDER BY `TRIGGER_NAME` ASC '; $query .= 'LIMIT ' . $pos . ', ' . $maxItems; - $retval = $dbi->fetchResult($query); + $retval = $dbi->fetchResultSimple($query); break; } diff --git a/src/Navigation/Nodes/ObjectFetcher.php b/src/Navigation/Nodes/ObjectFetcher.php index c2d8f0789b..291cd7a79b 100644 --- a/src/Navigation/Nodes/ObjectFetcher.php +++ b/src/Navigation/Nodes/ObjectFetcher.php @@ -121,7 +121,7 @@ class ObjectFetcher $query .= ' ORDER BY `EVENT_NAME` ASC'; - return $this->dbi->fetchResult($query); + return $this->dbi->fetchResultSimple($query); } $query = 'SHOW EVENTS FROM ' . Util::backquote($realName); @@ -181,7 +181,7 @@ class ObjectFetcher $query .= ' ORDER BY `TABLE_NAME` ASC'; - return $this->dbi->fetchResult($query); + return $this->dbi->fetchResultSimple($query); } $query = 'SHOW FULL TABLES FROM '; @@ -225,7 +225,7 @@ class ObjectFetcher $query .= ' ORDER BY `ROUTINE_NAME` ASC'; - return $this->dbi->fetchResult($query); + return $this->dbi->fetchResultSimple($query); } $query = 'SHOW ' . $routineType . ' STATUS WHERE `Db`=' . $this->dbi->quoteString($realName); diff --git a/src/Normalization.php b/src/Normalization.php index 3258195045..b567690b30 100644 --- a/src/Normalization.php +++ b/src/Normalization.php @@ -899,7 +899,7 @@ class Normalization $columns[] = Util::backquote($column); } - $totalRowsRes = $this->dbi->fetchResult( + $totalRowsRes = $this->dbi->fetchResultSimple( 'SELECT COUNT(*) FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;', ); @@ -988,7 +988,7 @@ class Normalization . 'COUNT(DISTINCT ' . $partialKey . ',' . $column . ') as pkColCnt ' . 'FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;'; - $res = $this->dbi->fetchResult($query); + $res = $this->dbi->fetchResultSimple($query); $pkColCnt = $res[0]; if ($pkCnt !== 0 && $pkCnt === $colCnt && $colCnt == $pkColCnt) { return true; @@ -1023,7 +1023,7 @@ class Normalization $query = trim($query, ', '); $query .= ' FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;'; - $res = $this->dbi->fetchResult($query); + $res = $this->dbi->fetchResultSimple($query); foreach ($columns as $column) { if ($column === '') { continue; diff --git a/src/Operations.php b/src/Operations.php index 249a6fea93..4072b9b447 100644 --- a/src/Operations.php +++ b/src/Operations.php @@ -247,7 +247,7 @@ class Operations public function runEventDefinitionsForDb(string $db, DatabaseName $newDatabaseName): void { /** @var string[] $eventNames */ - $eventNames = $this->dbi->fetchResult( + $eventNames = $this->dbi->fetchResultSimple( 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= ' . $this->dbi->quoteString($db) . ';', ); diff --git a/src/Partitioning/Maintenance.php b/src/Partitioning/Maintenance.php index 9ebb2a7b4f..87b23c30e3 100644 --- a/src/Partitioning/Maintenance.php +++ b/src/Partitioning/Maintenance.php @@ -29,7 +29,7 @@ final class Maintenance ); $this->dbi->selectDb($db); - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -49,7 +49,7 @@ final class Maintenance ); $this->dbi->selectDb($db); - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -84,7 +84,7 @@ final class Maintenance ); $this->dbi->selectDb($db); - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -122,7 +122,7 @@ final class Maintenance ); $this->dbi->selectDb($db); - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { diff --git a/src/Partitioning/Partition.php b/src/Partitioning/Partition.php index edf0f181c3..c575c79e4b 100644 --- a/src/Partitioning/Partition.php +++ b/src/Partitioning/Partition.php @@ -143,7 +143,7 @@ class Partition extends SubPartition { if (self::havePartitioning()) { $dbi = DatabaseInterface::getInstance(); - $result = $dbi->fetchResult( + $result = $dbi->fetchResultSimple( 'SELECT * FROM `information_schema`.`PARTITIONS`' . ' WHERE `TABLE_SCHEMA` = ' . $dbi->quoteString($db) . ' AND `TABLE_NAME` = ' . $dbi->quoteString($table), @@ -186,7 +186,7 @@ class Partition extends SubPartition if (self::havePartitioning()) { $dbi = DatabaseInterface::getInstance(); - return $dbi->fetchResult( + return $dbi->fetchResultSimple( 'SELECT DISTINCT `PARTITION_NAME` FROM `information_schema`.`PARTITIONS`' . ' WHERE `TABLE_SCHEMA` = ' . $dbi->quoteString($db) . ' AND `TABLE_NAME` = ' . $dbi->quoteString($table), @@ -208,7 +208,7 @@ class Partition extends SubPartition { if (self::havePartitioning()) { $dbi = DatabaseInterface::getInstance(); - $partitionMethod = $dbi->fetchResult( + $partitionMethod = $dbi->fetchResultSimple( 'SELECT `PARTITION_METHOD` FROM `information_schema`.`PARTITIONS`' . ' WHERE `TABLE_SCHEMA` = ' . $dbi->quoteString($db) . ' AND `TABLE_NAME` = ' . $dbi->quoteString($table) @@ -237,7 +237,7 @@ class Partition extends SubPartition self::$havePartitioning = true; } else { // see https://dev.mysql.com/doc/refman/5.6/en/partitioning.html - $plugins = $dbi->fetchResult('SHOW PLUGINS'); + $plugins = $dbi->fetchResultSimple('SHOW PLUGINS'); foreach ($plugins as $value) { if ($value['Name'] === 'partition') { self::$havePartitioning = true; diff --git a/src/Plugins/Export/ExportSql.php b/src/Plugins/Export/ExportSql.php index 034d55ad82..55aa4f648b 100644 --- a/src/Plugins/Export/ExportSql.php +++ b/src/Plugins/Export/ExportSql.php @@ -980,7 +980,7 @@ class ExportSql extends ExportPlugin $delimiter = '$$'; $dbi = DatabaseInterface::getInstance(); - $eventNames = $dbi->fetchResult( + $eventNames = $dbi->fetchResultSimple( 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE' . ' EVENT_SCHEMA= ' . $dbi->quoteString($db), ); diff --git a/src/Plugins/Export/ExportXml.php b/src/Plugins/Export/ExportXml.php index 3b1c92c485..75c4438b54 100644 --- a/src/Plugins/Export/ExportXml.php +++ b/src/Plugins/Export/ExportXml.php @@ -222,7 +222,7 @@ class ExportXml extends ExportPlugin . '>' . "\n"; if ($exportStruct) { - $result = $dbi->fetchResult( + $result = $dbi->fetchResultSimple( 'SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`' . ' FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME`' . ' = ' . $dbi->quoteString(Current::$database) . ' LIMIT 1', @@ -320,7 +320,7 @@ class ExportXml extends ExportPlugin if ($this->exportEvents) { // Export events - $events = $dbi->fetchResult( + $events = $dbi->fetchResultSimple( 'SELECT EVENT_NAME FROM information_schema.EVENTS ' . 'WHERE EVENT_SCHEMA=' . $dbi->quoteString(Current::$database), ); diff --git a/src/Plugins/Import/ImportCsv.php b/src/Plugins/Import/ImportCsv.php index 6c10822122..a4a8a40962 100644 --- a/src/Plugins/Import/ImportCsv.php +++ b/src/Plugins/Import/ImportCsv.php @@ -587,7 +587,7 @@ class ImportCsv extends AbstractImportCsv if ($this->newDatabaseName !== '') { $newDb = $this->newDatabaseName; } else { - $result = $dbi->fetchResult('SHOW DATABASES'); + $result = $dbi->fetchResultSimple('SHOW DATABASES'); $newDb = 'CSV_DB ' . (count($result) + 1); } diff --git a/src/Profiling.php b/src/Profiling.php index 6aa20807f9..83a7ad86cc 100644 --- a/src/Profiling.php +++ b/src/Profiling.php @@ -50,7 +50,7 @@ final class Profiling } /** @psalm-var list $profile */ - $profile = $dbi->fetchResult('SHOW PROFILE;'); + $profile = $dbi->fetchResultSimple('SHOW PROFILE;'); return $profile; } diff --git a/src/Replication/Replication.php b/src/Replication/Replication.php index d1b5fb3bb3..278c78f252 100644 --- a/src/Replication/Replication.php +++ b/src/Replication/Replication.php @@ -175,10 +175,9 @@ class Replication */ public function replicaBinLogPrimary(ConnectionType $connectionType): array { - $data = $this->dbi->fetchResult( + $data = $this->dbi->fetchResultSimple( Compatibility::getShowBinLogStatusStmt($this->dbi), null, - null, $connectionType, ); $output = []; diff --git a/src/Replication/ReplicationGui.php b/src/Replication/ReplicationGui.php index 811a994a90..e9de9a52ab 100644 --- a/src/Replication/ReplicationGui.php +++ b/src/Replication/ReplicationGui.php @@ -77,11 +77,11 @@ class ReplicationGui $primaryStatusTable = $this->getHtmlForReplicationStatusTable($connection, 'primary', true, false); $dbi = DatabaseInterface::getInstance(); if ($dbi->isMySql() && $dbi->getVersion() >= 80022) { - $replicas = $dbi->fetchResult('SHOW REPLICAS', null, null); + $replicas = $dbi->fetchResultSimple('SHOW REPLICAS'); } elseif ($dbi->isMariaDB() && $dbi->getVersion() >= 100501) { - $replicas = $dbi->fetchResult('SHOW REPLICA HOSTS', null, null); + $replicas = $dbi->fetchResultSimple('SHOW REPLICA HOSTS'); } else { - $replicas = $dbi->fetchResult('SHOW SLAVE HOSTS'); + $replicas = $dbi->fetchResultSimple('SHOW SLAVE HOSTS'); } $urlParams = UrlParams::$params; @@ -138,9 +138,9 @@ class ReplicationGui $serverReplicaMultiReplication = []; if ($dbi->isMariaDB() && $dbi->getVersion() >= 100501) { - $serverReplicaMultiReplication = $dbi->fetchResult('SHOW ALL REPLICAS STATUS'); + $serverReplicaMultiReplication = $dbi->fetchResultSimple('SHOW ALL REPLICAS STATUS'); } elseif ($dbi->isMariaDB()) { - $serverReplicaMultiReplication = $dbi->fetchResult('SHOW ALL SLAVES STATUS'); + $serverReplicaMultiReplication = $dbi->fetchResultSimple('SHOW ALL SLAVES STATUS'); } $isReplicaIoRunning = false; diff --git a/src/Replication/ReplicationInfo.php b/src/Replication/ReplicationInfo.php index 3777d0a74e..7122aad4c6 100644 --- a/src/Replication/ReplicationInfo.php +++ b/src/Replication/ReplicationInfo.php @@ -109,7 +109,7 @@ final class ReplicationInfo private function setPrimaryStatus(): void { - $this->primaryStatus = $this->dbi->fetchResult(Compatibility::getShowBinLogStatusStmt($this->dbi)); + $this->primaryStatus = $this->dbi->fetchResultSimple(Compatibility::getShowBinLogStatusStmt($this->dbi)); } /** @return mixed[] */ @@ -124,9 +124,9 @@ final class ReplicationInfo $this->dbi->isMySql() && $this->dbi->getVersion() >= 80022 || $this->dbi->isMariaDB() && $this->dbi->getVersion() >= 100501 ) { - $this->replicaStatus = $this->dbi->fetchResult('SHOW REPLICA STATUS'); + $this->replicaStatus = $this->dbi->fetchResultSimple('SHOW REPLICA STATUS'); } else { - $this->replicaStatus = $this->dbi->fetchResult('SHOW SLAVE STATUS'); + $this->replicaStatus = $this->dbi->fetchResultSimple('SHOW SLAVE STATUS'); } } @@ -140,9 +140,9 @@ final class ReplicationInfo { $this->multiPrimaryStatus = []; if ($this->dbi->isMariaDB() && $this->dbi->getVersion() >= 100501) { - $this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL REPLICAS STATUS'); + $this->multiPrimaryStatus = $this->dbi->fetchResultSimple('SHOW ALL REPLICAS STATUS'); } elseif ($this->dbi->isMariaDB()) { - $this->multiPrimaryStatus = $this->dbi->fetchResult('SHOW ALL SLAVES STATUS'); + $this->multiPrimaryStatus = $this->dbi->fetchResultSimple('SHOW ALL SLAVES STATUS'); } } diff --git a/src/Server/Privileges.php b/src/Server/Privileges.php index af695d116a..20d0d5feac 100644 --- a/src/Server/Privileges.php +++ b/src/Server/Privileges.php @@ -668,7 +668,7 @@ class Privileges $hostnameLength = 41; /* Try to get real lengths from the database */ - $fieldsInfo = $this->dbi->fetchResult( + $fieldsInfo = $this->dbi->fetchResultSimple( 'SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH ' . 'FROM information_schema.columns ' . "WHERE table_schema = 'mysql' AND table_name = 'user' " @@ -734,7 +734,7 @@ class Privileges */ public function getGrants(string $user, string $host): string { - $grants = $this->dbi->fetchResult( + $grants = $this->dbi->fetchResultSimple( 'SHOW GRANTS FOR ' . $this->dbi->quoteString($user) . '@' . $this->dbi->quoteString($host), @@ -1456,7 +1456,7 @@ class Privileges } // we also want privileges for this user not in table `db` but in other table - $tables = $this->dbi->fetchResult('SHOW TABLES FROM `mysql`;'); + $tables = $this->dbi->fetchResultSimple('SHOW TABLES FROM `mysql`;'); $dbRightsSqls = []; foreach ($tablesToSearchForUsers as $tableSearchIn) { @@ -1848,7 +1848,7 @@ class Privileges public function getDbRightsForUserOverview(string|null $initial): array { // we also want users not in table `user` but in other table - $mysqlTables = $this->dbi->fetchResult('SHOW TABLES FROM `mysql`'); + $mysqlTables = $this->dbi->fetchResultSimple('SHOW TABLES FROM `mysql`'); $userTables = ['user', 'db', 'tables_priv', 'columns_priv', 'procs_priv']; $whereUser = $this->rangeOfUsers($initial); $sqls = []; diff --git a/src/Table/Maintenance.php b/src/Table/Maintenance.php index f4388adcd0..69859239af 100644 --- a/src/Table/Maintenance.php +++ b/src/Table/Maintenance.php @@ -39,7 +39,7 @@ final class Maintenance $this->dbi->selectDb($db); /** @var array> $result */ - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -67,7 +67,7 @@ final class Maintenance $this->dbi->selectDb($db); /** @var array> $result */ - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -95,7 +95,7 @@ final class Maintenance $this->dbi->selectDb($db); /** @var array> $rows */ - $rows = $this->dbi->fetchResult($query); + $rows = $this->dbi->fetchResultSimple($query); $warnings = $this->dbi->getWarnings(); return [$rows, $query, $warnings]; @@ -137,7 +137,7 @@ final class Maintenance $this->dbi->selectDb($db); /** @var array> $result */ - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { @@ -165,7 +165,7 @@ final class Maintenance $this->dbi->selectDb($db); /** @var array> $result */ - $result = $this->dbi->fetchResult($query); + $result = $this->dbi->fetchResultSimple($query); $rows = []; foreach ($result as $row) { diff --git a/src/Table/Table.php b/src/Table/Table.php index b74b109b2a..38b2b7a241 100644 --- a/src/Table/Table.php +++ b/src/Table/Table.php @@ -1030,7 +1030,7 @@ class Table implements Stringable $columnsMetaQuery = 'SHOW COLUMNS FROM ' . $this->getFullName(true); $ret = []; - $columnsMetaQueryResult = $this->dbi->fetchResult($columnsMetaQuery); + $columnsMetaQueryResult = $this->dbi->fetchResultSimple($columnsMetaQuery); foreach ($columnsMetaQueryResult as $column) { $value = $column['Field']; diff --git a/src/Triggers/Triggers.php b/src/Triggers/Triggers.php index 1756d8868d..27f07e69f5 100644 --- a/src/Triggers/Triggers.php +++ b/src/Triggers/Triggers.php @@ -58,7 +58,7 @@ class Triggers } /** @var mixed[][] $triggers */ - $triggers = $dbi->fetchResult($query); + $triggers = $dbi->fetchResultSimple($query); return $triggers; } @@ -270,7 +270,7 @@ class Triggers . " AND `TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')", $this->dbi->quoteString($db), ); - $tables = $this->dbi->fetchResult($query); + $tables = $this->dbi->fetchResultSimple($query); Assert::allStringNotEmpty($tables); Assert::isList($tables); diff --git a/tests/unit/Database/CentralColumnsTest.php b/tests/unit/Database/CentralColumnsTest.php index 7a4a33e8ce..07eef7f148 100644 --- a/tests/unit/Database/CentralColumnsTest.php +++ b/tests/unit/Database/CentralColumnsTest.php @@ -175,7 +175,7 @@ class CentralColumnsTest extends AbstractTestCase public function testGetColumnsList(): void { $this->dbi->expects(self::exactly(2)) - ->method('fetchResult') + ->method('fetchResultSimple') ->willReturnOnConsecutiveCalls( self::COLUMN_DATA, array_slice(self::COLUMN_DATA, 1, 2), @@ -197,11 +197,10 @@ class CentralColumnsTest extends AbstractTestCase public function testGetCount(): void { $this->dbi->expects(self::once()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with( 'SELECT count(db_name) FROM `phpmyadmin`.`pma_central_columns` WHERE db_name = \'phpmyadmin\';', null, - null, ConnectionType::ControlUser, ) ->willReturn([3]); @@ -305,12 +304,11 @@ class CentralColumnsTest extends AbstractTestCase public function testGetHtmlForEditingPage(): void { $this->dbi->expects(self::any()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with( 'SELECT * FROM `phpmyadmin`.`pma_central_columns` ' . "WHERE db_name = 'phpmyadmin' AND col_name IN ('col1','col2');", null, - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -336,11 +334,10 @@ class CentralColumnsTest extends AbstractTestCase public function testGetListRaw(): void { $this->dbi->expects(self::once()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with( 'SELECT * FROM `phpmyadmin`.`pma_central_columns` WHERE db_name = \'phpmyadmin\';', null, - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -359,13 +356,12 @@ class CentralColumnsTest extends AbstractTestCase public function testGetListRawWithTable(): void { $this->dbi->expects(self::once()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with( 'SELECT * FROM `phpmyadmin`.`pma_central_columns` ' . "WHERE db_name = 'phpmyadmin' AND col_name " . "NOT IN ('id','col1','col2');", null, - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -386,8 +382,8 @@ class CentralColumnsTest extends AbstractTestCase $expectedQuery = 'SELECT * FROM `phpmyadmin`.`pma_central_columns`' . ' WHERE db_name = \'phpmyadmin\' AND col_name IN (\'col1\');'; $this->dbi->expects(self::once()) - ->method('fetchResult') - ->with($expectedQuery, null, null, ConnectionType::ControlUser) + ->method('fetchResultSimple') + ->with($expectedQuery, null, ConnectionType::ControlUser) ->willReturn(array_slice(self::COLUMN_DATA, 1, 1)); self::assertSame( array_slice(self::MODIFIED_COLUMN_DATA, 1, 1), diff --git a/tests/unit/Navigation/Nodes/NodeTest.php b/tests/unit/Navigation/Nodes/NodeTest.php index bf1654fcd1..b6864eebd9 100644 --- a/tests/unit/Navigation/Nodes/NodeTest.php +++ b/tests/unit/Navigation/Nodes/NodeTest.php @@ -357,7 +357,7 @@ final class NodeTest extends AbstractTestCase $node = new Node($config, 'node'); $dbi = self::createMock(DatabaseInterface::class); - $dbi->expects(self::once())->method('fetchResult')->with($expectedSql); + $dbi->expects(self::once())->method('fetchResultSimple')->with($expectedSql); $dbi->expects(self::any())->method('quoteString') ->willReturnCallback(static fn (string $string): string => "'" . $string . "'"); DatabaseInterface::$instance = $dbi; @@ -389,7 +389,7 @@ final class NodeTest extends AbstractTestCase $node = new Node($config, 'node'); $dbi = self::createMock(DatabaseInterface::class); - $dbi->expects(self::once())->method('fetchResult')->with($expectedSql); + $dbi->expects(self::once())->method('fetchResultSimple')->with($expectedSql); DatabaseInterface::$instance = $dbi; $node->getData(new UserPrivileges(), $relationParameters, '', 10); @@ -426,7 +426,7 @@ final class NodeTest extends AbstractTestCase ->willReturn(['0' => 'db'], ['0' => 'aa_db'], []); $dbi->expects(self::once()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with( "SHOW DATABASES WHERE TRUE AND `Database` LIKE '%db%' AND (" . " LOCATE('db_', CONCAT(`Database`, '_')) = 1" diff --git a/tests/unit/NormalizationTest.php b/tests/unit/NormalizationTest.php index 74f9b5aeb2..d23b8c5b6e 100644 --- a/tests/unit/NormalizationTest.php +++ b/tests/unit/NormalizationTest.php @@ -94,7 +94,7 @@ class NormalizationTest extends AbstractTestCase ->method('tryQuery') ->willReturn(self::createStub(DummyResult::class)); $dbi->expects(self::any()) - ->method('fetchResult') + ->method('fetchResultSimple') ->willReturn([0]); $this->normalization = new Normalization($dbi, new Relation($dbi), new Transformations(), new Template()); diff --git a/tests/unit/Partitioning/PartitionTest.php b/tests/unit/Partitioning/PartitionTest.php index 7cb76ebf52..10e33d7ac1 100644 --- a/tests/unit/Partitioning/PartitionTest.php +++ b/tests/unit/Partitioning/PartitionTest.php @@ -43,7 +43,7 @@ class PartitionTest extends AbstractTestCase $mock = self::createStub(DatabaseInterface::class); $mock->method('getVersion')->willReturn($version); $mock->method('fetchValue')->willReturn($varValue); - $mock->method('fetchResult')->willReturn($pluginValue); + $mock->method('fetchResultSimple')->willReturn($pluginValue); DatabaseInterface::$instance = $mock; self::assertSame($expected, Partition::havePartitioning()); } diff --git a/tests/unit/Plugins/Export/ExportSqlTest.php b/tests/unit/Plugins/Export/ExportSqlTest.php index 010c5904b7..65d6a0ad01 100644 --- a/tests/unit/Plugins/Export/ExportSqlTest.php +++ b/tests/unit/Plugins/Export/ExportSqlTest.php @@ -592,7 +592,7 @@ class ExportSqlTest extends AbstractTestCase ->getMock(); $dbi->expects(self::once()) - ->method('fetchResult') + ->method('fetchResultSimple') ->with('SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \'db\'') ->willReturn(['f1', 'f2']); diff --git a/tests/unit/Plugins/Export/ExportXmlTest.php b/tests/unit/Plugins/Export/ExportXmlTest.php index c649bbb540..135fa48ea6 100644 --- a/tests/unit/Plugins/Export/ExportXmlTest.php +++ b/tests/unit/Plugins/Export/ExportXmlTest.php @@ -18,7 +18,6 @@ use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup; use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem; use PhpMyAdmin\Properties\Options\Items\HiddenPropertyItem; use PhpMyAdmin\Properties\Plugins\ExportPluginProperties; -use PhpMyAdmin\Table\Table; use PhpMyAdmin\Tests\AbstractTestCase; use PhpMyAdmin\Transformations; use PHPUnit\Framework\Attributes\CoversClass; @@ -180,40 +179,55 @@ class ExportXmlTest extends AbstractTestCase $config->selectedServer['DisableIS'] = false; Current::$database = 'd<"b'; - $result = [ - 0 => ['DEFAULT_COLLATION_NAME' => 'utf8_general_ci', 'DEFAULT_CHARACTER_SET_NAME' => 'utf-8'], - 'table' => [null, '"tbl"'], - ]; - $dbi = $this->getMockBuilder(DatabaseInterface::class) - ->disableOriginalConstructor() - ->getMock(); + $functions = [['d<"b', 'fn', 'FUNCTION']]; + $procedures = [['d<"b', 'pr', 'PROCEDURE']]; - $triggers = [ + $dbiDummy = $this->createDbiDummy(); + $dbi = $this->createDatabaseInterface($dbiDummy); + + $dbiDummy->addResult( + 'SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`' + . " FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME` = 'd<\\\"b' LIMIT 1", + [['utf-8', 'utf8_general_ci']], + ['DEFAULT_CHARACTER_SET_NAME', 'DEFAULT_COLLATION_NAME'], + ); + $dbiDummy->addResult('SHOW FUNCTION STATUS;', $functions, ['Db', 'Name', 'Type']); + $dbiDummy->addResult('SHOW PROCEDURE STATUS;', $procedures, ['Db', 'Name', 'Type']); + $dbiDummy->addResult('SHOW CREATE TABLE `d<"b`.`table`', [['table', '"tbl"']]); + $dbiDummy->addResult( + 'SELECT 1 FROM information_schema.VIEWS WHERE TABLE_SCHEMA = \'d<\"b\' AND TABLE_NAME = \'table\'', + [], + ); + $dbiDummy->addResult( + 'SELECT TRIGGER_SCHEMA, TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE,' + . ' ACTION_TIMING, ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER FROM' + . ' information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= \'d<\"b\' AND' + . ' EVENT_OBJECT_TABLE COLLATE utf8_bin = \'table\';', [ - 'TRIGGER_SCHEMA' => 'd<"b', - 'TRIGGER_NAME' => 'trname', - 'EVENT_MANIPULATION' => 'INSERT', - 'EVENT_OBJECT_TABLE' => 'table', - 'ACTION_TIMING' => 'AFTER', - 'ACTION_STATEMENT' => 'BEGIN END', - 'EVENT_OBJECT_SCHEMA' => 'd<"b', - 'DEFINER' => 'test_user@localhost', + [ + 'd<"b', + 'trname', + 'INSERT', + 'table', + 'AFTER', + 'BEGIN END', + 'd<"b', + 'test_user@localhost', + ], ], - ]; - $functions = [['Db' => 'd<"b', 'Name' => 'fn', 'Type' => 'FUNCTION']]; - $procedures = [['Db' => 'd<"b', 'Name' => 'pr', 'Type' => 'PROCEDURE']]; - - $dbi->expects(self::exactly(5)) - ->method('fetchResult') - ->willReturn($result, $result, $triggers, $functions, $procedures); - - $dbi->expects(self::exactly(3)) - ->method('fetchValue') - ->willReturn(false, 'fndef', 'prdef'); - - $dbi->expects(self::once()) - ->method('getTable') - ->willReturn(new Table('table', 'd<"b', $dbi)); + [ + 'TRIGGER_SCHEMA', + 'TRIGGER_NAME', + 'EVENT_MANIPULATION', + 'EVENT_OBJECT_TABLE', + 'ACTION_TIMING', + 'ACTION_STATEMENT', + 'EVENT_OBJECT_SCHEMA', + 'DEFINER', + ], + ); + $dbiDummy->addResult('SHOW CREATE FUNCTION `d<"b`.`fn`', [['fn', 'fndef']], ['name', 'Create Function']); + $dbiDummy->addResult('SHOW CREATE PROCEDURE `d<"b`.`pr`', [['pr', 'prdef']], ['name', 'Create Procedure']); DatabaseInterface::$instance = $dbi; @@ -271,26 +285,22 @@ class ExportXmlTest extends AbstractTestCase $GLOBALS['output_charset_conversion'] = 0; - $dbi = $this->getMockBuilder(DatabaseInterface::class) - ->disableOriginalConstructor() - ->getMock(); - - $result1 = [['DEFAULT_COLLATION_NAME' => 'utf8_general_ci', 'DEFAULT_CHARACTER_SET_NAME' => 'utf-8']]; - $result2 = ['t1' => [null, '"tbl"']]; - - $result3 = ['t2' => [null, '"tbl"']]; - - $dbi->expects(self::exactly(3)) - ->method('fetchResult') - ->willReturn($result1, $result2, $result3); - - $dbi->expects(self::exactly(2)) - ->method('fetchValue') - ->willReturn('table', false); - - $dbi->expects(self::any()) - ->method('getTable') - ->willReturn(new Table('table', 'd<"b', $dbi)); + $dbiDummy->addResult( + 'SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`' + . " FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME` = 'd<\\\"b' LIMIT 1", + [['utf-8', 'utf8_general_ci']], + ['DEFAULT_CHARACTER_SET_NAME', 'DEFAULT_COLLATION_NAME'], + ); + $dbiDummy->addResult('SHOW CREATE TABLE `d<"b`.`t1`', [['t1', '"tbl"']]); + $dbiDummy->addResult( + 'SELECT 1 FROM information_schema.VIEWS WHERE TABLE_SCHEMA = \'d<\"b\' AND TABLE_NAME = \'t1\'', + [], + ); + $dbiDummy->addResult('SHOW CREATE TABLE `d<"b`.`t2`', [['t2', '"tbl"']]); + $dbiDummy->addResult( + 'SELECT 1 FROM information_schema.VIEWS WHERE TABLE_SCHEMA = \'d<\"b\' AND TABLE_NAME = \'t2\'', + [], + ); DatabaseInterface::$instance = $dbi; diff --git a/tests/unit/Table/TableTest.php b/tests/unit/Table/TableTest.php index 0d12870fb4..44db15d761 100644 --- a/tests/unit/Table/TableTest.php +++ b/tests/unit/Table/TableTest.php @@ -85,38 +85,15 @@ class TableTest extends AbstractTestCase $getUniqueColumnsSql = 'SHOW INDEXES FROM `PMA`.`PMA_BookMark`'; - $fetchResult = [ + $fetchResultSimple = [ [ $sqlAnalyzeStructureTrue, null, - null, ConnectionType::User, [['COLUMN_NAME' => 'COLUMN_NAME', 'DATA_TYPE' => 'DATA_TYPE']], ], - [ - $getUniqueColumnsSql . ' WHERE (Non_unique = 0)', - ['Key_name', null], - 'Column_name', - ConnectionType::User, - [['index1'], ['index3'], ['index5']], - ], - [ - $getUniqueColumnsSql, - 'Column_name', - 'Column_name', - ConnectionType::User, - ['column1', 'column3', 'column5', 'ACCESSIBLE', 'ADD', 'ALL'], - ], [ 'SHOW COLUMNS FROM `PMA`.`PMA_BookMark`', - 'Field', - 'Field', - ConnectionType::User, - ['column1', 'column3', 'column5', 'ACCESSIBLE', 'ADD', 'ALL'], - ], - [ - 'SHOW COLUMNS FROM `PMA`.`PMA_BookMark`', - null, null, ConnectionType::User, [ @@ -141,7 +118,6 @@ class TableTest extends AbstractTestCase [ 'SHOW TRIGGERS FROM `PMA` LIKE \'PMA_BookMark\';', null, - null, ConnectionType::User, [ [ @@ -173,7 +149,6 @@ class TableTest extends AbstractTestCase [ 'SHOW TRIGGERS FROM `PMA` LIKE \'PMA_.BookMark\';', null, - null, ConnectionType::User, [ [ @@ -208,7 +183,6 @@ class TableTest extends AbstractTestCase . "information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'PMA' " . "AND EVENT_OBJECT_TABLE COLLATE utf8_bin = 'PMA_BookMark';", null, - null, ConnectionType::User, [ [], @@ -220,7 +194,6 @@ class TableTest extends AbstractTestCase . "information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'aa' " . "AND EVENT_OBJECT_TABLE COLLATE utf8_bin = 'ad';", null, - null, ConnectionType::User, [ [], @@ -229,12 +202,35 @@ class TableTest extends AbstractTestCase [ 'SHOW COLUMNS FROM `aa`.`ad`', null, - null, ConnectionType::User, [], ], ]; + $fetchResult = [ + [ + $getUniqueColumnsSql . ' WHERE (Non_unique = 0)', + ['Key_name', null], + 'Column_name', + ConnectionType::User, + [['index1'], ['index3'], ['index5']], + ], + [ + $getUniqueColumnsSql, + 'Column_name', + 'Column_name', + ConnectionType::User, + ['column1', 'column3', 'column5', 'ACCESSIBLE', 'ADD', 'ALL'], + ], + [ + 'SHOW COLUMNS FROM `PMA`.`PMA_BookMark`', + 'Field', + 'Field', + ConnectionType::User, + ['column1', 'column3', 'column5', 'ACCESSIBLE', 'ADD', 'ALL'], + ], + ]; + $fetchValue = [ [$sqlIsViewTrue, 0, ConnectionType::User, 'PMA_BookMark'], [$sqlCopyData, 0, ConnectionType::User, false], @@ -268,6 +264,9 @@ class TableTest extends AbstractTestCase $dbi->expects(self::any())->method('fetchResult') ->willReturnMap($fetchResult); + $dbi->expects(self::any())->method('fetchResultSimple') + ->willReturnMap($fetchResultSimple); + $dbi->expects(self::any())->method('fetchValue') ->willReturnMap($fetchValue); From c4f4a1ee9e602204f9d8a7fa4115fb3935b1b104 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 01:34:46 +0000 Subject: [PATCH 03/16] Refactor getTables() Signed-off-by: Kamil Tekiela --- src/DatabaseInterface.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index 4ee8ce5138..1ff6868e07 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -303,12 +303,19 @@ class DatabaseInterface implements DbalInterface return []; } - /** @var array $tables */ - $tables = $this->fetchResultSimple( + $result = $this->tryQuery( 'SHOW TABLES FROM ' . Util::backquote($database) . ';', - 0, $connectionType, + cacheAffectedRows: false, ); + + if ($result === false) { + return []; + } + + /** @var list $tables */ + $tables = $result->fetchAllColumn(); + if ($this->config->settings['NaturalOrder']) { usort($tables, strnatcasecmp(...)); } From 94f70f8b68dd9c395ca023910f8ae357dbc545e4 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 01:43:03 +0000 Subject: [PATCH 04/16] Refactor getColumnNames() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 2 +- psalm-baseline.xml | 8 ++------ src/DatabaseInterface.php | 8 +++++++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 2c4fa66162..6747eaf1ef 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6958,7 +6958,7 @@ parameters: path: src/DatabaseInterface.php - - message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:getColumnNames\(\) should return list\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:getColumnNames\(\) should return list\ but returns list\\.$#' identifier: return.type count: 1 path: src/DatabaseInterface.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 52d039744f..0a9864e7c7 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -4229,9 +4229,6 @@ - - fetchResultSimple($sql, 'Field', $connectionType)]]> - @@ -4300,10 +4297,9 @@ * Visible?: string, * Expression?: string|null * }>]]> - - + fetchAllAssoc(), 'Field')]]> ]]> - + diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index 1ff6868e07..acd8a4e598 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -989,8 +989,14 @@ class DatabaseInterface implements DbalInterface ): array { $sql = QueryGenerator::getColumnsSql($database, $table); + $result = $this->tryQuery($sql, $connectionType, cacheAffectedRows: false); + + if ($result === false) { + return []; + } + // We only need the 'Field' column which contains the table's column names - return $this->fetchResultSimple($sql, 'Field', $connectionType); + return array_column($result->fetchAllAssoc(), 'Field'); } /** From 18493d01bafa6c9f6f8122b99b4b390a2bf65ce8 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 01:51:18 +0000 Subject: [PATCH 05/16] Drop $value param from fetchResultSimple Signed-off-by: Kamil Tekiela --- psalm-baseline.xml | 4 ++-- src/Bookmarks/BookmarkRepository.php | 2 +- src/ConfigStorage/Relation.php | 2 +- src/Database/CentralColumns.php | 12 ++++++------ src/Database/Designer/Common.php | 2 +- src/DatabaseInterface.php | 7 +++---- src/Replication/Replication.php | 1 - tests/unit/Database/CentralColumnsTest.php | 6 +----- tests/unit/Table/TableTest.php | 7 ------- 9 files changed, 15 insertions(+), 28 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 0a9864e7c7..bff31f9076 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -3825,7 +3825,7 @@ - dbi->fetchResultSimple($query, null, ConnectionType::ControlUser)]]> + dbi->fetchResultSimple($query, ConnectionType::ControlUser)]]> @@ -4278,7 +4278,7 @@ - fetchResultSimple($sql, null, $connectionType)]]> + fetchResultSimple($sql, $connectionType)]]> dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $result = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); $bookmarks = []; foreach ($result as $row) { diff --git a/src/ConfigStorage/Relation.php b/src/ConfigStorage/Relation.php index 3d1ba90c46..5ca1769deb 100644 --- a/src/ConfigStorage/Relation.php +++ b/src/ConfigStorage/Relation.php @@ -693,7 +693,7 @@ class Relation WHERE `username` = ' . $this->dbi->quoteString($username) . ' ORDER BY `id` DESC'; - return $this->dbi->fetchResultSimple($histQuery, null, ConnectionType::ControlUser); + return $this->dbi->fetchResultSimple($histQuery, ConnectionType::ControlUser); } /** diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index e2ad273be3..4a41ce74c2 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -122,7 +122,7 @@ class CentralColumns . 'LIMIT ' . $from . ', ' . $num . ';'; } - $hasList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $hasList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); $this->handleColumnExtra($hasList); return $hasList; @@ -147,7 +147,7 @@ class CentralColumns $query = 'SELECT count(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' ' . 'WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ';'; - $res = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $res = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); if (isset($res[0])) { return (int) $res[0]; } @@ -180,7 +180,7 @@ class CentralColumns . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; - return $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + return $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); } /** @@ -207,7 +207,7 @@ class CentralColumns $query = 'SELECT * FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; - $hasList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $hasList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); $this->handleColumnExtra($hasList); return $hasList; @@ -692,7 +692,7 @@ class CentralColumns $query .= ';'; } - $columnsList = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $columnsList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); $this->handleColumnExtra($columnsList); return $columnsList; @@ -771,7 +771,7 @@ class CentralColumns $query = 'SELECT COUNT(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ($num === 0 ? '' : 'LIMIT ' . $from . ', ' . $num) . ';'; - $result = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $result = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); if (isset($result[0])) { return (int) $result[0]; diff --git a/src/Database/Designer/Common.php b/src/Database/Designer/Common.php index 4da0ca7c23..cf91495e4d 100644 --- a/src/Database/Designer/Common.php +++ b/src/Database/Designer/Common.php @@ -330,7 +330,7 @@ class Common . ' FROM ' . Util::backquote($pdfFeature->database) . '.' . Util::backquote($pdfFeature->pdfPages) . ' WHERE `page_descr` = ' . $this->dbi->quoteString($pg, ConnectionType::ControlUser); - $pageNos = $this->dbi->fetchResultSimple($query, null, ConnectionType::ControlUser); + $pageNos = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); return $pageNos !== []; } diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index acd8a4e598..af0cb37de3 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -1032,7 +1032,7 @@ class DatabaseInterface implements DbalInterface ): array { $sql = QueryGenerator::getTableIndexesSql($database, $table); - return $this->fetchResultSimple($sql, null, $connectionType); + return $this->fetchResultSimple($sql, $connectionType); } /** @@ -1355,7 +1355,6 @@ class DatabaseInterface implements DbalInterface /** @return array */ public function fetchResultSimple( string $query, - string|int|null $value = null, ConnectionType $connectionType = ConnectionType::User, ): array { $result = $this->tryQuery($query, $connectionType, cacheAffectedRows: false); @@ -1364,11 +1363,11 @@ class DatabaseInterface implements DbalInterface return []; } - if ($value === 0 || $result->numFields() === 1) { + if ($result->numFields() === 1) { return $result->fetchAllColumn(); } - return $value === null ? $result->fetchAllAssoc() : array_column($result->fetchAllAssoc(), $value); + return $result->fetchAllAssoc(); } /** diff --git a/src/Replication/Replication.php b/src/Replication/Replication.php index 278c78f252..007383e3f8 100644 --- a/src/Replication/Replication.php +++ b/src/Replication/Replication.php @@ -177,7 +177,6 @@ class Replication { $data = $this->dbi->fetchResultSimple( Compatibility::getShowBinLogStatusStmt($this->dbi), - null, $connectionType, ); $output = []; diff --git a/tests/unit/Database/CentralColumnsTest.php b/tests/unit/Database/CentralColumnsTest.php index 07eef7f148..58387433be 100644 --- a/tests/unit/Database/CentralColumnsTest.php +++ b/tests/unit/Database/CentralColumnsTest.php @@ -200,7 +200,6 @@ class CentralColumnsTest extends AbstractTestCase ->method('fetchResultSimple') ->with( 'SELECT count(db_name) FROM `phpmyadmin`.`pma_central_columns` WHERE db_name = \'phpmyadmin\';', - null, ConnectionType::ControlUser, ) ->willReturn([3]); @@ -308,7 +307,6 @@ class CentralColumnsTest extends AbstractTestCase ->with( 'SELECT * FROM `phpmyadmin`.`pma_central_columns` ' . "WHERE db_name = 'phpmyadmin' AND col_name IN ('col1','col2');", - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -337,7 +335,6 @@ class CentralColumnsTest extends AbstractTestCase ->method('fetchResultSimple') ->with( 'SELECT * FROM `phpmyadmin`.`pma_central_columns` WHERE db_name = \'phpmyadmin\';', - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -361,7 +358,6 @@ class CentralColumnsTest extends AbstractTestCase 'SELECT * FROM `phpmyadmin`.`pma_central_columns` ' . "WHERE db_name = 'phpmyadmin' AND col_name " . "NOT IN ('id','col1','col2');", - null, ConnectionType::ControlUser, ) ->willReturn(self::COLUMN_DATA); @@ -383,7 +379,7 @@ class CentralColumnsTest extends AbstractTestCase . ' WHERE db_name = \'phpmyadmin\' AND col_name IN (\'col1\');'; $this->dbi->expects(self::once()) ->method('fetchResultSimple') - ->with($expectedQuery, null, ConnectionType::ControlUser) + ->with($expectedQuery, ConnectionType::ControlUser) ->willReturn(array_slice(self::COLUMN_DATA, 1, 1)); self::assertSame( array_slice(self::MODIFIED_COLUMN_DATA, 1, 1), diff --git a/tests/unit/Table/TableTest.php b/tests/unit/Table/TableTest.php index 44db15d761..974a952568 100644 --- a/tests/unit/Table/TableTest.php +++ b/tests/unit/Table/TableTest.php @@ -88,13 +88,11 @@ class TableTest extends AbstractTestCase $fetchResultSimple = [ [ $sqlAnalyzeStructureTrue, - null, ConnectionType::User, [['COLUMN_NAME' => 'COLUMN_NAME', 'DATA_TYPE' => 'DATA_TYPE']], ], [ 'SHOW COLUMNS FROM `PMA`.`PMA_BookMark`', - null, ConnectionType::User, [ [ @@ -117,7 +115,6 @@ class TableTest extends AbstractTestCase ], [ 'SHOW TRIGGERS FROM `PMA` LIKE \'PMA_BookMark\';', - null, ConnectionType::User, [ [ @@ -148,7 +145,6 @@ class TableTest extends AbstractTestCase ], [ 'SHOW TRIGGERS FROM `PMA` LIKE \'PMA_.BookMark\';', - null, ConnectionType::User, [ [ @@ -182,7 +178,6 @@ class TableTest extends AbstractTestCase . 'ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER FROM ' . "information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'PMA' " . "AND EVENT_OBJECT_TABLE COLLATE utf8_bin = 'PMA_BookMark';", - null, ConnectionType::User, [ [], @@ -193,7 +188,6 @@ class TableTest extends AbstractTestCase . 'ACTION_STATEMENT, EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, DEFINER FROM ' . "information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA COLLATE utf8_bin= 'aa' " . "AND EVENT_OBJECT_TABLE COLLATE utf8_bin = 'ad';", - null, ConnectionType::User, [ [], @@ -201,7 +195,6 @@ class TableTest extends AbstractTestCase ], [ 'SHOW COLUMNS FROM `aa`.`ad`', - null, ConnectionType::User, [], ], From 0b4a52919314d3f18987355313dbcd147c994ddd Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:02:27 +0000 Subject: [PATCH 06/16] Fix return type of getHistory() Signed-off-by: Kamil Tekiela --- src/ConfigStorage/Relation.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ConfigStorage/Relation.php b/src/ConfigStorage/Relation.php index 5ca1769deb..fa04966c09 100644 --- a/src/ConfigStorage/Relation.php +++ b/src/ConfigStorage/Relation.php @@ -662,9 +662,9 @@ class Relation * * @param string $username the username * - * @return mixed[]|bool list of history items + * @return mixed[]|false list of history items */ - public function getHistory(string $username): array|bool + public function getHistory(string $username): array|false { $sqlHistoryFeature = $this->getRelationParameters()->sqlHistoryFeature; if ($sqlHistoryFeature === null) { From b09e20d6c1495494927a068e34a6c1b1f3baa4e3 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:07:14 +0000 Subject: [PATCH 07/16] Refactor CentralColumns::getCount Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 2 +- src/Database/CentralColumns.php | 6 +----- tests/unit/Database/CentralColumnsTest.php | 5 +++-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6747eaf1ef..9518c35b63 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6186,7 +6186,7 @@ parameters: - message: '#^Cannot cast mixed to int\.$#' identifier: cast.int - count: 2 + count: 1 path: src/Database/CentralColumns.php - diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index 4a41ce74c2..aadafb3439 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -147,12 +147,8 @@ class CentralColumns $query = 'SELECT count(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' ' . 'WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ';'; - $res = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); - if (isset($res[0])) { - return (int) $res[0]; - } - return 0; + return (int) $this->dbi->fetchValue($query, 0, ConnectionType::ControlUser); } /** diff --git a/tests/unit/Database/CentralColumnsTest.php b/tests/unit/Database/CentralColumnsTest.php index 58387433be..47c191bda5 100644 --- a/tests/unit/Database/CentralColumnsTest.php +++ b/tests/unit/Database/CentralColumnsTest.php @@ -197,12 +197,13 @@ class CentralColumnsTest extends AbstractTestCase public function testGetCount(): void { $this->dbi->expects(self::once()) - ->method('fetchResultSimple') + ->method('fetchValue') ->with( 'SELECT count(db_name) FROM `phpmyadmin`.`pma_central_columns` WHERE db_name = \'phpmyadmin\';', + 0, ConnectionType::ControlUser, ) - ->willReturn([3]); + ->willReturn('3'); self::assertSame( 3, From 1d509b96325fcdbf62a03d43960d1d679b592883 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:12:14 +0000 Subject: [PATCH 08/16] Refactor getColumnsCount() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 6 ------ src/Database/CentralColumns.php | 7 ++++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 9518c35b63..e406046675 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6183,12 +6183,6 @@ parameters: count: 11 path: src/Database/CentralColumns.php - - - message: '#^Cannot cast mixed to int\.$#' - identifier: cast.int - count: 1 - path: src/Database/CentralColumns.php - - message: '#^Cannot cast mixed to string\.$#' identifier: cast.string diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index aadafb3439..d09a22b29c 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -31,6 +31,7 @@ use function implode; use function in_array; use function is_array; use function is_bool; +use function is_string; use function mb_strtoupper; use function sprintf; use function trim; @@ -767,10 +768,10 @@ class CentralColumns $query = 'SELECT COUNT(db_name) FROM ' . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ($num === 0 ? '' : 'LIMIT ' . $from . ', ' . $num) . ';'; - $result = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); + $result = $this->dbi->fetchValue($query, 0, ConnectionType::ControlUser); - if (isset($result[0])) { - return (int) $result[0]; + if (is_string($result)) { + return (int) $result; } return -1; From b687a6f62bbeb3c7c7c5f2c5afb55040eaefc2e1 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:38:52 +0000 Subject: [PATCH 09/16] Split off fetchSingleColumn() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 40 +++++++++++++------- psalm-baseline.xml | 41 ++++++++++++++------- src/Database/CentralColumns.php | 2 +- src/DatabaseInterface.php | 16 +++++++- src/ListDatabase.php | 3 +- src/Navigation/Nodes/Node.php | 6 +-- src/Navigation/Nodes/NodeTable.php | 2 +- src/Navigation/Nodes/ObjectFetcher.php | 4 +- src/Operations.php | 2 +- src/Partitioning/Partition.php | 3 +- src/Plugins/Export/ExportSql.php | 2 +- src/Plugins/Export/ExportXml.php | 2 +- src/Plugins/Import/ImportCsv.php | 2 +- src/Server/Privileges.php | 6 +-- src/Triggers/Triggers.php | 3 +- tests/unit/Navigation/Nodes/NodeTest.php | 6 +-- tests/unit/Plugins/Export/ExportSqlTest.php | 2 +- 17 files changed, 90 insertions(+), 52 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e406046675..6bd9e76da3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -6196,7 +6196,7 @@ parameters: path: src/Database/CentralColumns.php - - message: '#^Method PhpMyAdmin\\Database\\CentralColumns\:\:findExistingColNames\(\) should return array\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\Database\\CentralColumns\:\:findExistingColNames\(\) should return array\ but returns list\\.$#' identifier: return.type count: 1 path: src/Database/CentralColumns.php @@ -10681,13 +10681,13 @@ parameters: path: src/Navigation/Nodes/NodeTable.php - - message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getEventsFromDb\(\) should return array\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getEventsFromDb\(\) should return array\ but returns list\\.$#' identifier: return.type count: 1 path: src/Navigation/Nodes/ObjectFetcher.php - - message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getRoutines\(\) should return array\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getRoutines\(\) should return array\ but returns list\\.$#' identifier: return.type count: 1 path: src/Navigation/Nodes/ObjectFetcher.php @@ -11094,6 +11094,18 @@ parameters: count: 1 path: src/Partitioning/Partition.php + - + message: '#^Cannot access offset ''PARTITION_NAME'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 2 + path: src/Partitioning/Partition.php + + - + message: '#^Cannot access offset ''SUBPARTITION_NAME'' on mixed\.$#' + identifier: offsetAccess.nonOffsetAccessible + count: 1 + path: src/Partitioning/Partition.php + - message: '#^Cannot cast mixed to int\.$#' identifier: cast.int @@ -11119,8 +11131,14 @@ parameters: path: src/Partitioning/Partition.php - - message: '#^PHPDoc tag @var for variable \$row has no value type specified in iterable type array\.$#' - identifier: missingType.iterableValue + message: '#^Parameter \#1 \$row of class PhpMyAdmin\\Partitioning\\Partition constructor expects array\, mixed given\.$#' + identifier: argument.type + count: 1 + path: src/Partitioning/Partition.php + + - + message: '#^Parameter \#1 \$row of class PhpMyAdmin\\Partitioning\\SubPartition constructor expects array\, mixed given\.$#' + identifier: argument.type count: 1 path: src/Partitioning/Partition.php @@ -12606,7 +12624,7 @@ parameters: - message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#' identifier: argument.type - count: 3 + count: 2 path: src/Plugins/Export/ExportSql.php - @@ -12634,7 +12652,7 @@ parameters: path: src/Plugins/Export/ExportSql.php - - message: '#^Parameter \#3 \$name of static method PhpMyAdmin\\Database\\Events\:\:getDefinition\(\) expects string, mixed given\.$#' + message: '#^Parameter \#3 \$name of static method PhpMyAdmin\\Database\\Events\:\:getDefinition\(\) expects string, string\|null given\.$#' identifier: argument.type count: 1 path: src/Plugins/Export/ExportSql.php @@ -12823,7 +12841,7 @@ parameters: path: src/Plugins/Export/ExportXml.php - - message: '#^Parameter \#3 \$names of method PhpMyAdmin\\Plugins\\Export\\ExportXml\:\:exportDefinitions\(\) expects array\, array\ given\.$#' + message: '#^Parameter \#3 \$names of method PhpMyAdmin\\Plugins\\Export\\ExportXml\:\:exportDefinitions\(\) expects array\, list\ given\.$#' identifier: argument.type count: 1 path: src/Plugins/Export/ExportXml.php @@ -15534,12 +15552,6 @@ parameters: count: 1 path: src/Server/Privileges.php - - - message: '#^Binary operation "\." between mixed and ";\\n\\n" results in an error\.$#' - identifier: binaryOp.invalid - count: 1 - path: src/Server/Privileges.php - - message: '#^Binary operation "\." between mixed and ''&\#27;'' results in an error\.$#' identifier: binaryOp.invalid diff --git a/psalm-baseline.xml b/psalm-baseline.xml index bff31f9076..07ee639c3c 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -3771,6 +3771,12 @@ + + dbi->fetchSingleColumn($query, ConnectionType::ControlUser)]]> + + + + @@ -3825,9 +3831,7 @@ - dbi->fetchResultSimple($query, ConnectionType::ControlUser)]]> - @@ -6184,13 +6188,17 @@ + + dbi->fetchSingleColumn($query)]]> + dbi->fetchSingleColumn($query)]]> + + + + + - dbi->fetchResultSimple($query)]]> - dbi->fetchResultSimple($query)]]> dbi->fetchResultSimple($query)]]> - - @@ -6469,7 +6477,12 @@ + + + + + @@ -6490,6 +6503,9 @@ + + + @@ -7173,8 +7189,6 @@ - - @@ -7196,7 +7210,6 @@ - name]]> references->table->table]]> @@ -7220,6 +7233,7 @@ + @@ -7321,14 +7335,14 @@ + + + - - - @@ -9073,7 +9087,6 @@ - @@ -9089,7 +9102,6 @@ - @@ -9189,6 +9201,7 @@ + diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index d09a22b29c..bbd189e100 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -177,7 +177,7 @@ class CentralColumns . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; - return $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); + return $this->dbi->fetchSingleColumn($query, ConnectionType::ControlUser); } /** diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index af0cb37de3..838d3a763d 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -1370,6 +1370,20 @@ class DatabaseInterface implements DbalInterface return $result->fetchAllAssoc(); } + /** @return list */ + public function fetchSingleColumn( + string $query, + ConnectionType $connectionType = ConnectionType::User, + ): array { + $result = $this->tryQuery($query, $connectionType, cacheAffectedRows: false); + + if ($result === false) { + return []; + } + + return $result->fetchAllColumn(); + } + /** * Get supported SQL compatibility modes * @@ -1586,7 +1600,7 @@ class DatabaseInterface implements DbalInterface private function getCurrentUserGrants(): array { /** @var string[] $grants */ - $grants = $this->fetchResultSimple('SHOW GRANTS FOR CURRENT_USER();'); + $grants = $this->fetchSingleColumn('SHOW GRANTS FOR CURRENT_USER();'); return $grants; } diff --git a/src/ListDatabase.php b/src/ListDatabase.php index 00af6b8402..4ace28377e 100644 --- a/src/ListDatabase.php +++ b/src/ListDatabase.php @@ -100,7 +100,8 @@ class ListDatabase extends ArrayObject } if ($command !== '') { - $databaseList = $this->dbi->fetchResultSimple($command); + /** @var string[] $databaseList */ + $databaseList = $this->dbi->fetchSingleColumn($command); } if ($this->config->settings['NaturalOrder']) { diff --git a/src/Navigation/Nodes/Node.php b/src/Navigation/Nodes/Node.php index 29c3ab95b6..a04056a420 100644 --- a/src/Navigation/Nodes/Node.php +++ b/src/Navigation/Nodes/Node.php @@ -626,7 +626,7 @@ class Node $maxItems, ); - return $dbi->fetchResultSimple($query); + return $dbi->fetchSingleColumn($query); } $dbSeparator = $this->config->settings['NavigationTreeDbSeparator']; @@ -643,7 +643,7 @@ class Node $maxItems, ); - return $dbi->fetchResultSimple($query); + return $dbi->fetchSingleColumn($query); } /** @@ -725,7 +725,7 @@ class Node implode('OR', $subClauses), ); - return $dbi->fetchResultSimple($query); + return $dbi->fetchSingleColumn($query); } /** diff --git a/src/Navigation/Nodes/NodeTable.php b/src/Navigation/Nodes/NodeTable.php index afcf296d2a..6e92dd1e2f 100644 --- a/src/Navigation/Nodes/NodeTable.php +++ b/src/Navigation/Nodes/NodeTable.php @@ -229,7 +229,7 @@ class NodeTable extends NodeDatabaseChild . Util::getCollateForIS() . '=' . $dbi->quoteString($table) . ' '; $query .= 'ORDER BY `TRIGGER_NAME` ASC '; $query .= 'LIMIT ' . $pos . ', ' . $maxItems; - $retval = $dbi->fetchResultSimple($query); + $retval = $dbi->fetchSingleColumn($query); break; } diff --git a/src/Navigation/Nodes/ObjectFetcher.php b/src/Navigation/Nodes/ObjectFetcher.php index 291cd7a79b..84f2c21a4d 100644 --- a/src/Navigation/Nodes/ObjectFetcher.php +++ b/src/Navigation/Nodes/ObjectFetcher.php @@ -121,7 +121,7 @@ class ObjectFetcher $query .= ' ORDER BY `EVENT_NAME` ASC'; - return $this->dbi->fetchResultSimple($query); + return $this->dbi->fetchSingleColumn($query); } $query = 'SHOW EVENTS FROM ' . Util::backquote($realName); @@ -225,7 +225,7 @@ class ObjectFetcher $query .= ' ORDER BY `ROUTINE_NAME` ASC'; - return $this->dbi->fetchResultSimple($query); + return $this->dbi->fetchSingleColumn($query); } $query = 'SHOW ' . $routineType . ' STATUS WHERE `Db`=' . $this->dbi->quoteString($realName); diff --git a/src/Operations.php b/src/Operations.php index 4072b9b447..abcc6dcad7 100644 --- a/src/Operations.php +++ b/src/Operations.php @@ -247,7 +247,7 @@ class Operations public function runEventDefinitionsForDb(string $db, DatabaseName $newDatabaseName): void { /** @var string[] $eventNames */ - $eventNames = $this->dbi->fetchResultSimple( + $eventNames = $this->dbi->fetchSingleColumn( 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= ' . $this->dbi->quoteString($db) . ';', ); diff --git a/src/Partitioning/Partition.php b/src/Partitioning/Partition.php index c575c79e4b..9de31667db 100644 --- a/src/Partitioning/Partition.php +++ b/src/Partitioning/Partition.php @@ -150,7 +150,6 @@ class Partition extends SubPartition ); if ($result !== []) { $partitionMap = []; - /** @var array $row */ foreach ($result as $row) { if (isset($partitionMap[$row['PARTITION_NAME']])) { $partition = $partitionMap[$row['PARTITION_NAME']]; @@ -186,7 +185,7 @@ class Partition extends SubPartition if (self::havePartitioning()) { $dbi = DatabaseInterface::getInstance(); - return $dbi->fetchResultSimple( + return $dbi->fetchSingleColumn( 'SELECT DISTINCT `PARTITION_NAME` FROM `information_schema`.`PARTITIONS`' . ' WHERE `TABLE_SCHEMA` = ' . $dbi->quoteString($db) . ' AND `TABLE_NAME` = ' . $dbi->quoteString($table), diff --git a/src/Plugins/Export/ExportSql.php b/src/Plugins/Export/ExportSql.php index 55aa4f648b..1e6e5f6dd0 100644 --- a/src/Plugins/Export/ExportSql.php +++ b/src/Plugins/Export/ExportSql.php @@ -980,7 +980,7 @@ class ExportSql extends ExportPlugin $delimiter = '$$'; $dbi = DatabaseInterface::getInstance(); - $eventNames = $dbi->fetchResultSimple( + $eventNames = $dbi->fetchSingleColumn( 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE' . ' EVENT_SCHEMA= ' . $dbi->quoteString($db), ); diff --git a/src/Plugins/Export/ExportXml.php b/src/Plugins/Export/ExportXml.php index 75c4438b54..8eafa7826f 100644 --- a/src/Plugins/Export/ExportXml.php +++ b/src/Plugins/Export/ExportXml.php @@ -320,7 +320,7 @@ class ExportXml extends ExportPlugin if ($this->exportEvents) { // Export events - $events = $dbi->fetchResultSimple( + $events = $dbi->fetchSingleColumn( 'SELECT EVENT_NAME FROM information_schema.EVENTS ' . 'WHERE EVENT_SCHEMA=' . $dbi->quoteString(Current::$database), ); diff --git a/src/Plugins/Import/ImportCsv.php b/src/Plugins/Import/ImportCsv.php index a4a8a40962..11f9792118 100644 --- a/src/Plugins/Import/ImportCsv.php +++ b/src/Plugins/Import/ImportCsv.php @@ -587,7 +587,7 @@ class ImportCsv extends AbstractImportCsv if ($this->newDatabaseName !== '') { $newDb = $this->newDatabaseName; } else { - $result = $dbi->fetchResultSimple('SHOW DATABASES'); + $result = $dbi->fetchSingleColumn('SHOW DATABASES'); $newDb = 'CSV_DB ' . (count($result) + 1); } diff --git a/src/Server/Privileges.php b/src/Server/Privileges.php index 20d0d5feac..07fcfca78d 100644 --- a/src/Server/Privileges.php +++ b/src/Server/Privileges.php @@ -734,7 +734,7 @@ class Privileges */ public function getGrants(string $user, string $host): string { - $grants = $this->dbi->fetchResultSimple( + $grants = $this->dbi->fetchSingleColumn( 'SHOW GRANTS FOR ' . $this->dbi->quoteString($user) . '@' . $this->dbi->quoteString($host), @@ -1456,7 +1456,7 @@ class Privileges } // we also want privileges for this user not in table `db` but in other table - $tables = $this->dbi->fetchResultSimple('SHOW TABLES FROM `mysql`;'); + $tables = $this->dbi->fetchSingleColumn('SHOW TABLES FROM `mysql`;'); $dbRightsSqls = []; foreach ($tablesToSearchForUsers as $tableSearchIn) { @@ -1848,7 +1848,7 @@ class Privileges public function getDbRightsForUserOverview(string|null $initial): array { // we also want users not in table `user` but in other table - $mysqlTables = $this->dbi->fetchResultSimple('SHOW TABLES FROM `mysql`'); + $mysqlTables = $this->dbi->fetchSingleColumn('SHOW TABLES FROM `mysql`'); $userTables = ['user', 'db', 'tables_priv', 'columns_priv', 'procs_priv']; $whereUser = $this->rangeOfUsers($initial); $sqls = []; diff --git a/src/Triggers/Triggers.php b/src/Triggers/Triggers.php index 27f07e69f5..2c73d908cf 100644 --- a/src/Triggers/Triggers.php +++ b/src/Triggers/Triggers.php @@ -270,9 +270,8 @@ class Triggers . " AND `TABLE_TYPE` IN ('BASE TABLE', 'SYSTEM VERSIONED')", $this->dbi->quoteString($db), ); - $tables = $this->dbi->fetchResultSimple($query); + $tables = $this->dbi->fetchSingleColumn($query); Assert::allStringNotEmpty($tables); - Assert::isList($tables); return $tables; } diff --git a/tests/unit/Navigation/Nodes/NodeTest.php b/tests/unit/Navigation/Nodes/NodeTest.php index b6864eebd9..f2b9b4386a 100644 --- a/tests/unit/Navigation/Nodes/NodeTest.php +++ b/tests/unit/Navigation/Nodes/NodeTest.php @@ -357,7 +357,7 @@ final class NodeTest extends AbstractTestCase $node = new Node($config, 'node'); $dbi = self::createMock(DatabaseInterface::class); - $dbi->expects(self::once())->method('fetchResultSimple')->with($expectedSql); + $dbi->expects(self::once())->method('fetchSingleColumn')->with($expectedSql); $dbi->expects(self::any())->method('quoteString') ->willReturnCallback(static fn (string $string): string => "'" . $string . "'"); DatabaseInterface::$instance = $dbi; @@ -389,7 +389,7 @@ final class NodeTest extends AbstractTestCase $node = new Node($config, 'node'); $dbi = self::createMock(DatabaseInterface::class); - $dbi->expects(self::once())->method('fetchResultSimple')->with($expectedSql); + $dbi->expects(self::once())->method('fetchSingleColumn')->with($expectedSql); DatabaseInterface::$instance = $dbi; $node->getData(new UserPrivileges(), $relationParameters, '', 10); @@ -426,7 +426,7 @@ final class NodeTest extends AbstractTestCase ->willReturn(['0' => 'db'], ['0' => 'aa_db'], []); $dbi->expects(self::once()) - ->method('fetchResultSimple') + ->method('fetchSingleColumn') ->with( "SHOW DATABASES WHERE TRUE AND `Database` LIKE '%db%' AND (" . " LOCATE('db_', CONCAT(`Database`, '_')) = 1" diff --git a/tests/unit/Plugins/Export/ExportSqlTest.php b/tests/unit/Plugins/Export/ExportSqlTest.php index 65d6a0ad01..d570e85757 100644 --- a/tests/unit/Plugins/Export/ExportSqlTest.php +++ b/tests/unit/Plugins/Export/ExportSqlTest.php @@ -592,7 +592,7 @@ class ExportSqlTest extends AbstractTestCase ->getMock(); $dbi->expects(self::once()) - ->method('fetchResultSimple') + ->method('fetchSingleColumn') ->with('SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \'db\'') ->willReturn(['f1', 'f2']); From e41782c403fbd43fcf6600bfb858f2157d1ce652 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:47:10 +0000 Subject: [PATCH 10/16] Refactor getPartitionMethod() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 6 ------ psalm-baseline.xml | 6 ------ src/Partitioning/Partition.php | 6 +++--- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 6bd9e76da3..b1e0f735bc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -11118,12 +11118,6 @@ parameters: count: 2 path: src/Partitioning/Partition.php - - - message: '#^Method PhpMyAdmin\\Partitioning\\Partition\:\:getPartitionMethod\(\) should return string\|null but returns mixed\.$#' - identifier: return.type - count: 1 - path: src/Partitioning/Partition.php - - message: '#^Only booleans are allowed in an if condition, string\|false\|null given\.$#' identifier: if.condNotBoolean diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 07ee639c3c..eeed9a2888 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6497,12 +6497,6 @@ name]]> - - - - - - diff --git a/src/Partitioning/Partition.php b/src/Partitioning/Partition.php index 9de31667db..674aa72d2b 100644 --- a/src/Partitioning/Partition.php +++ b/src/Partitioning/Partition.php @@ -207,14 +207,14 @@ class Partition extends SubPartition { if (self::havePartitioning()) { $dbi = DatabaseInterface::getInstance(); - $partitionMethod = $dbi->fetchResultSimple( + $partitionMethod = $dbi->fetchValue( 'SELECT `PARTITION_METHOD` FROM `information_schema`.`PARTITIONS`' . ' WHERE `TABLE_SCHEMA` = ' . $dbi->quoteString($db) . ' AND `TABLE_NAME` = ' . $dbi->quoteString($table) . ' LIMIT 1', ); - if ($partitionMethod !== []) { - return $partitionMethod[0]; + if ($partitionMethod !== false) { + return $partitionMethod; } } From 0842106ca49e6e75c04a47f674744566fb36207a Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:50:44 +0000 Subject: [PATCH 11/16] Refactor findDistinctValuesCount() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 12 ------------ psalm-baseline.xml | 1 - src/Normalization.php | 7 +++---- tests/unit/NormalizationTest.php | 3 +++ 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index b1e0f735bc..82af7606e2 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -10737,18 +10737,6 @@ parameters: count: 2 path: src/Normalization.php - - - message: '#^Cannot access offset non\-falsy\-string on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Normalization.php - - - - message: '#^Cannot cast mixed to int\.$#' - identifier: cast.int - count: 1 - path: src/Normalization.php - - message: '#^Casting to int something that''s already int\<1, max\>\.$#' identifier: cast.useless diff --git a/psalm-baseline.xml b/psalm-baseline.xml index eeed9a2888..fa7fcd61d1 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6268,7 +6268,6 @@ - diff --git a/src/Normalization.php b/src/Normalization.php index b567690b30..32db2f83fd 100644 --- a/src/Normalization.php +++ b/src/Normalization.php @@ -1016,20 +1016,19 @@ class Normalization } //each column is already backquoted - $query .= 'COUNT(DISTINCT ' . $column . ') as \'' - . $column . '_cnt\', '; + $query .= 'COUNT(DISTINCT ' . $column . ') as \'' . $column . '_cnt\', '; } $query = trim($query, ', '); $query .= ' FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;'; - $res = $this->dbi->fetchResultSimple($query); + $res = $this->dbi->fetchSingleRow($query) ?? []; foreach ($columns as $column) { if ($column === '') { continue; } - $result[$column] = (int) ($res[0][$column . '_cnt'] ?? null); + $result[$column] = (int) $res[$column . '_cnt']; } return $result; diff --git a/tests/unit/NormalizationTest.php b/tests/unit/NormalizationTest.php index d23b8c5b6e..29c83af1c7 100644 --- a/tests/unit/NormalizationTest.php +++ b/tests/unit/NormalizationTest.php @@ -96,6 +96,9 @@ class NormalizationTest extends AbstractTestCase $dbi->expects(self::any()) ->method('fetchResultSimple') ->willReturn([0]); + $dbi->expects(self::any()) + ->method('fetchSingleRow') + ->willReturn(['`id`_cnt' => 0, '`col1`_cnt' => 0, '`col2`_cnt' => 0]); $this->normalization = new Normalization($dbi, new Relation($dbi), new Transformations(), new Template()); } From 1cc7e5aa3437392ac076fddfcd5f2ef2c02ade56 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:56:55 +0000 Subject: [PATCH 12/16] Refactor checkPartialDependency() Signed-off-by: Kamil Tekiela --- psalm-baseline.xml | 1 - src/Normalization.php | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index fa7fcd61d1..2f44338d2e 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6280,7 +6280,6 @@ - diff --git a/src/Normalization.php b/src/Normalization.php index 32db2f83fd..c03cc4e5ae 100644 --- a/src/Normalization.php +++ b/src/Normalization.php @@ -988,8 +988,7 @@ class Normalization . 'COUNT(DISTINCT ' . $partialKey . ',' . $column . ') as pkColCnt ' . 'FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;'; - $res = $this->dbi->fetchResultSimple($query); - $pkColCnt = $res[0]; + $pkColCnt = $this->dbi->fetchValue($query); if ($pkCnt !== 0 && $pkCnt === $colCnt && $colCnt == $pkColCnt) { return true; } From bab961a5a8e320d515d3197c0d39ea31c41fb2e8 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 02:58:45 +0000 Subject: [PATCH 13/16] Refactor findPartialDependencies() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 6 ------ psalm-baseline.xml | 2 -- src/Normalization.php | 3 +-- tests/unit/NormalizationTest.php | 3 --- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 82af7606e2..f76e067a42 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -10887,12 +10887,6 @@ parameters: count: 2 path: src/Normalization.php - - - message: '#^Parameter \#6 \$totalRows of method PhpMyAdmin\\Normalization\:\:checkPartialDependency\(\) expects int, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Normalization.php - - message: '#^Variable property access on object\.$#' identifier: property.dynamicName diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 2f44338d2e..bd1cd1db95 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -6247,7 +6247,6 @@ $key]]> $key]]> - @@ -6283,7 +6282,6 @@ - diff --git a/src/Normalization.php b/src/Normalization.php index c03cc4e5ae..a1deb8c5fc 100644 --- a/src/Normalization.php +++ b/src/Normalization.php @@ -899,11 +899,10 @@ class Normalization $columns[] = Util::backquote($column); } - $totalRowsRes = $this->dbi->fetchResultSimple( + $totalRows = (int) $this->dbi->fetchValue( 'SELECT COUNT(*) FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;', ); - $totalRows = $totalRowsRes[0]; $primary = Index::getPrimary($this->dbi, $table, $db); $primarycols = $primary === null ? [] : $primary->getColumns(); $pk = []; diff --git a/tests/unit/NormalizationTest.php b/tests/unit/NormalizationTest.php index 29c83af1c7..e1af278153 100644 --- a/tests/unit/NormalizationTest.php +++ b/tests/unit/NormalizationTest.php @@ -93,9 +93,6 @@ class NormalizationTest extends AbstractTestCase $dbi->expects(self::any()) ->method('tryQuery') ->willReturn(self::createStub(DummyResult::class)); - $dbi->expects(self::any()) - ->method('fetchResultSimple') - ->willReturn([0]); $dbi->expects(self::any()) ->method('fetchSingleRow') ->willReturn(['`id`_cnt' => 0, '`col1`_cnt' => 0, '`col2`_cnt' => 0]); From 678329497294201699bfceb6039a49b10ba117fd Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 03:06:02 +0000 Subject: [PATCH 14/16] Specialize fetchResultSimple() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 110 ++++++-------------------------------- psalm-baseline.xml | 109 +++++++++---------------------------- src/DatabaseInterface.php | 6 +-- 3 files changed, 42 insertions(+), 183 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index f76e067a42..70733d6819 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -312,13 +312,7 @@ parameters: - message: '#^Parameter \#1 \$row of method PhpMyAdmin\\Bookmarks\\BookmarkRepository\:\:createFromRow\(\) expects array\, array\ given\.$#' identifier: argument.type - count: 2 - path: src/Bookmarks/BookmarkRepository.php - - - - message: '#^Parameter \#1 \$row of method PhpMyAdmin\\Bookmarks\\BookmarkRepository\:\:createFromRow\(\) expects array\, mixed given\.$#' - identifier: argument.type - count: 1 + count: 3 path: src/Bookmarks/BookmarkRepository.php - @@ -6982,7 +6976,7 @@ parameters: path: src/DatabaseInterface.php - - message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:getTableIndexes\(\) should return array\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\DatabaseInterface\:\:getTableIndexes\(\) should return array\ but returns list\\>\.$#' identifier: return.type count: 1 path: src/DatabaseInterface.php @@ -10693,7 +10687,7 @@ parameters: path: src/Navigation/Nodes/ObjectFetcher.php - - message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getTablesAndViews\(\) should return array\ but returns array\\.$#' + message: '#^Method PhpMyAdmin\\Navigation\\Nodes\\ObjectFetcher\:\:getTablesAndViews\(\) should return array\ but returns list\\>\.$#' identifier: return.type count: 1 path: src/Navigation/Nodes/ObjectFetcher.php @@ -11055,12 +11049,6 @@ parameters: count: 1 path: src/Operations.php - - - message: '#^Cannot access offset ''Table'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 4 - path: src/Partitioning/Maintenance.php - - message: ''' #^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\DatabaseInterface\: @@ -11070,24 +11058,6 @@ parameters: count: 4 path: src/Partitioning/Partition.php - - - message: '#^Cannot access offset ''Name'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Partitioning/Partition.php - - - - message: '#^Cannot access offset ''PARTITION_NAME'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 2 - path: src/Partitioning/Partition.php - - - - message: '#^Cannot access offset ''SUBPARTITION_NAME'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Partitioning/Partition.php - - message: '#^Cannot cast mixed to int\.$#' identifier: cast.int @@ -11106,18 +11076,6 @@ parameters: count: 1 path: src/Partitioning/Partition.php - - - message: '#^Parameter \#1 \$row of class PhpMyAdmin\\Partitioning\\Partition constructor expects array\, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Partitioning/Partition.php - - - - message: '#^Parameter \#1 \$row of class PhpMyAdmin\\Partitioning\\SubPartition constructor expects array\, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Partitioning/Partition.php - - message: '#^PhpMyAdmin\\Partitioning\\Partition\:\:__construct\(\) does not call parent constructor from PhpMyAdmin\\Partitioning\\SubPartition\.$#' identifier: constructor.missingParentCall @@ -12744,18 +12702,6 @@ parameters: count: 3 path: src/Plugins/Export/ExportXml.php - - - message: '#^Cannot access offset ''DEFAULT_CHARACTER_SET_NAME'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Plugins/Export/ExportXml.php - - - - message: '#^Cannot access offset ''DEFAULT_COLLATION_NAME'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Plugins/Export/ExportXml.php - - message: '#^Cannot access offset ''columns'' on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -12807,13 +12753,13 @@ parameters: - message: '#^Parameter \#1 \$string of function htmlspecialchars expects string, mixed given\.$#' identifier: argument.type - count: 3 + count: 1 path: src/Plugins/Export/ExportXml.php - message: '#^Parameter \#1 \$string of function htmlspecialchars expects string, string\|null given\.$#' identifier: argument.type - count: 2 + count: 4 path: src/Plugins/Export/ExportXml.php - @@ -15129,18 +15075,6 @@ parameters: count: 2 path: src/Replication/Replication.php - - - message: '#^Cannot access offset ''File'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Replication/Replication.php - - - - message: '#^Cannot access offset ''Position'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Replication/Replication.php - - message: '#^Loose comparison via "\!\=" is not allowed\.$#' identifier: notEqual.notAllowed @@ -15148,7 +15082,7 @@ parameters: path: src/Replication/Replication.php - - message: '#^Method PhpMyAdmin\\Replication\\Replication\:\:replicaBinLogPrimary\(\) should return array\{File\?\: string, Position\?\: string\} but returns array\{\}\|array\{File\: mixed, Position\: mixed\}\.$#' + message: '#^Method PhpMyAdmin\\Replication\\Replication\:\:replicaBinLogPrimary\(\) should return array\{File\?\: string, Position\?\: string\} but returns array\{\}\|array\{File\: string\|null, Position\: string\|null\}\.$#' identifier: return.type count: 1 path: src/Replication/Replication.php @@ -15555,18 +15489,6 @@ parameters: count: 2 path: src/Server/Privileges.php - - - message: '#^Cannot access offset ''CHARACTER_MAXIMUM_LENGTH'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 2 - path: src/Server/Privileges.php - - - - message: '#^Cannot access offset ''COLUMN_NAME'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Server/Privileges.php - - message: '#^Cannot access offset ''Column_priv'' on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -17085,16 +17007,10 @@ parameters: count: 2 path: src/Table/Table.php - - - message: '#^Cannot access offset ''Extra'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 3 - path: src/Table/Table.php - - message: '#^Cannot access offset ''Field'' on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible - count: 3 + count: 2 path: src/Table/Table.php - @@ -17194,7 +17110,7 @@ parameters: path: src/Table/Table.php - - message: '#^Method PhpMyAdmin\\Table\\Table\:\:getNonGeneratedColumns\(\) should return array\ but returns list\\.$#' + message: '#^Method PhpMyAdmin\\Table\\Table\:\:getNonGeneratedColumns\(\) should return array\ but returns list\\.$#' identifier: return.type count: 1 path: src/Table/Table.php @@ -17230,7 +17146,7 @@ parameters: path: src/Table/Table.php - - message: '#^Parameter \#1 \$haystack of function str_contains expects string, mixed given\.$#' + message: '#^Parameter \#1 \$haystack of function str_contains expects string, string\|null given\.$#' identifier: argument.type count: 3 path: src/Table/Table.php @@ -17238,7 +17154,7 @@ parameters: - message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#' identifier: argument.type - count: 2 + count: 1 path: src/Table/Table.php - @@ -17730,6 +17646,12 @@ parameters: count: 4 path: src/Triggers/Triggers.php + - + message: '#^PHPDoc tag @var with type array\\> is not subtype of type list\\>\.$#' + identifier: varTag.type + count: 1 + path: src/Triggers/Triggers.php + - message: '#^Parameter \#1 \$haystack of function str_contains expects string, mixed given\.$#' identifier: argument.type diff --git a/psalm-baseline.xml b/psalm-baseline.xml index bd1cd1db95..ca3b5b8bf5 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -64,13 +64,8 @@ + - - - - - - bookmarkFeature]]> @@ -6189,17 +6184,15 @@ + dbi->fetchResultSimple($query)]]> dbi->fetchSingleColumn($query)]]> dbi->fetchSingleColumn($query)]]> + - - dbi->fetchResultSimple($query)]]> - - @@ -6443,28 +6436,12 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + @@ -6473,29 +6450,16 @@ - - - - - - - - - - - - - description]]> expression]]> method]]> name]]> - - - - + + + + @@ -6503,6 +6467,7 @@ fetchValue('SELECT @@have_partitioning;')]]> + @@ -7330,20 +7295,16 @@ - - - - - - + + @@ -8842,26 +8803,20 @@ + + + - - - - - - - - - - + - + @@ -9054,10 +9009,6 @@ - - - - @@ -9073,7 +9024,6 @@ - @@ -9088,8 +9038,6 @@ - - @@ -9832,6 +9780,7 @@ + getStatusInfo('TABLE_COLLATION') ?? '']]> getStatusInfo('TABLE_COMMENT') ?? '']]> @@ -9840,11 +9789,10 @@ + - - @@ -9852,7 +9800,6 @@ uiprefs[$property->value]]]> uiprefs[$property->value]]]> - @@ -9860,9 +9807,6 @@ dbName][$this->name]]]> - - - @@ -9886,12 +9830,9 @@ - - - @@ -9904,9 +9845,7 @@ - ]]> - @@ -9920,6 +9859,8 @@ + + refDbName]]> refTableName]]> diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index 838d3a763d..0abf9fe274 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -1352,7 +1352,7 @@ class DatabaseInterface implements DbalInterface return $resultRows; } - /** @return array */ + /** @return list> */ public function fetchResultSimple( string $query, ConnectionType $connectionType = ConnectionType::User, @@ -1363,10 +1363,6 @@ class DatabaseInterface implements DbalInterface return []; } - if ($result->numFields() === 1) { - return $result->fetchAllColumn(); - } - return $result->fetchAllAssoc(); } From 5a8f01c5959cb72121e775f3c3ca5d92c4cd1872 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 03:26:17 +0000 Subject: [PATCH 15/16] Refactor fetchSingleRow() Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 30 ---------------------- psalm-baseline.xml | 10 -------- src/Bookmarks/BookmarkRepository.php | 4 +-- src/ConfigStorage/Relation.php | 2 +- src/Controllers/Table/SearchController.php | 4 +-- src/Database/Designer.php | 3 +-- src/Database/Designer/Common.php | 2 +- src/Database/Events.php | 2 +- src/Database/Routines.php | 2 +- src/DatabaseInterface.php | 10 ++++---- src/Dbal/DbalInterface.php | 4 +-- src/Normalization.php | 8 ++++-- src/Server/Privileges.php | 4 +-- src/Sql.php | 2 +- src/StorageEngine.php | 11 +++----- src/Table/Table.php | 2 +- src/UserPreferences.php | 4 +-- tests/unit/DatabaseInterfaceTest.php | 2 +- 18 files changed, 33 insertions(+), 73 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 70733d6819..139c55c6d6 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3906,18 +3906,6 @@ parameters: count: 1 path: src/Controllers/Server/UserGroupsFormController.php - - - message: '#^Offset 1 might not exist on array\\|null\.$#' - identifier: offsetAccess.notFound - count: 2 - path: src/Controllers/Server/Variables/GetVariableController.php - - - - message: '#^Offset 1 might not exist on array\\|null\.$#' - identifier: offsetAccess.notFound - count: 1 - path: src/Controllers/Server/Variables/SetVariableController.php - - message: '#^Parameter \#1 \$string of function htmlspecialchars expects string, int\|string given\.$#' identifier: argument.type @@ -7071,12 +7059,6 @@ parameters: count: 1 path: src/DatabaseInterface.php - - - message: '#^Short ternary operator is not allowed\. Use null coalesce operator if applicable or consider using long ternary\.$#' - identifier: ternary.shortNotAllowed - count: 1 - path: src/DatabaseInterface.php - - message: '#^Variable \$roleHost on left side of \?\? always exists and is not nullable\.$#' identifier: nullCoalesce.variable @@ -15615,18 +15597,6 @@ parameters: count: 1 path: src/Server/Privileges.php - - - message: '#^Offset ''@@old_passwords'' might not exist on array\\|null\.$#' - identifier: offsetAccess.notFound - count: 1 - path: src/Server/Privileges.php - - - - message: '#^Offset ''Type'' might not exist on array\\|null\.$#' - identifier: offsetAccess.notFound - count: 4 - path: src/Server/Privileges.php - - message: '#^Only booleans are allowed in &&, mixed given on the right side\.$#' identifier: booleanAnd.rightNotBoolean diff --git a/psalm-baseline.xml b/psalm-baseline.xml index ca3b5b8bf5..b2b254ca8b 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -2309,9 +2309,6 @@ - - - @@ -2323,9 +2320,6 @@ - - - @@ -9118,10 +9112,6 @@ - - - - diff --git a/src/Bookmarks/BookmarkRepository.php b/src/Bookmarks/BookmarkRepository.php index f274006a22..9d68f99221 100644 --- a/src/Bookmarks/BookmarkRepository.php +++ b/src/Bookmarks/BookmarkRepository.php @@ -134,7 +134,7 @@ final class BookmarkRepository $query .= ' LIMIT 1'; $result = $this->dbi->fetchSingleRow($query, DatabaseInterface::FETCH_ASSOC, ConnectionType::ControlUser); - if ($result !== null) { + if ($result !== []) { return $this->createFromRow($result); } @@ -162,7 +162,7 @@ final class BookmarkRepository . ' LIMIT 1'; $result = $this->dbi->fetchSingleRow($query, DatabaseInterface::FETCH_ASSOC, ConnectionType::ControlUser); - if ($result !== null) { + if ($result !== []) { return $this->createFromRow($result); } diff --git a/src/ConfigStorage/Relation.php b/src/ConfigStorage/Relation.php index fa04966c09..ec98f98a81 100644 --- a/src/ConfigStorage/Relation.php +++ b/src/ConfigStorage/Relation.php @@ -478,7 +478,7 @@ class Relation . ' AND `table_name` = ' . $this->dbi->quoteString($table); $row = $this->dbi->fetchSingleRow($dispQuery, DatabaseInterface::FETCH_ASSOC, ConnectionType::ControlUser); - if (isset($row['display_field'])) { + if ($row['display_field'] !== null) { return $row['display_field']; } } diff --git a/src/Controllers/Table/SearchController.php b/src/Controllers/Table/SearchController.php index 96dcdefa44..2dcbc82505 100644 --- a/src/Controllers/Table/SearchController.php +++ b/src/Controllers/Table/SearchController.php @@ -304,9 +304,9 @@ final class SearchController implements InvocableController * * @param string $column Column name * - * @return mixed[]|null + * @return array */ - private function getColumnMinMax(string $column): array|null + private function getColumnMinMax(string $column): array { $sqlQuery = 'SELECT MIN(' . Util::backquote($column) . ') AS `min`, ' . 'MAX(' . Util::backquote($column) . ') AS `max` ' diff --git a/src/Database/Designer.php b/src/Database/Designer.php index 3e0d261c72..54462d8964 100644 --- a/src/Database/Designer.php +++ b/src/Database/Designer.php @@ -17,7 +17,6 @@ use PhpMyAdmin\Util; use stdClass; use function __; -use function is_array; use function json_decode; use function str_contains; @@ -146,7 +145,7 @@ class Designer . ';'; $result = $this->dbi->fetchSingleRow($query); - if (is_array($result)) { + if ($result !== []) { $params = json_decode((string) $result['settings_data'], true); } } diff --git a/src/Database/Designer/Common.php b/src/Database/Designer/Common.php index cf91495e4d..b56ccdb77e 100644 --- a/src/Database/Designer/Common.php +++ b/src/Database/Designer/Common.php @@ -669,7 +669,7 @@ class Common ConnectionType::ControlUser, ); - if ($origData !== null && $origData !== []) { + if ($origData !== []) { $origData = json_decode($origData['settings_data'], true); $origData[$index] = $value; $origData = json_encode($origData); diff --git a/src/Database/Events.php b/src/Database/Events.php index 475a040338..bfacccc5a9 100644 --- a/src/Database/Events.php +++ b/src/Database/Events.php @@ -223,7 +223,7 @@ class Events . ' AND EVENT_NAME=' . $this->dbi->quoteString($name); $query = 'SELECT ' . $columns . ' FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE ' . $where . ';'; $item = $this->dbi->fetchSingleRow($query); - if ($item === null || $item === []) { + if ($item === []) { return null; } diff --git a/src/Database/Routines.php b/src/Database/Routines.php index de33394658..348b4f91ef 100644 --- a/src/Database/Routines.php +++ b/src/Database/Routines.php @@ -432,7 +432,7 @@ class Routines $routine = $this->dbi->fetchSingleRow($query); - if ($routine === null || $routine === []) { + if ($routine === []) { return null; } diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index 0abf9fe274..75795d855a 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -1095,7 +1095,7 @@ class DatabaseInterface implements DbalInterface { $version = $this->fetchSingleRow('SELECT @@version, @@version_comment'); - if (is_array($version)) { + if ($version !== []) { $this->setVersion($version); } @@ -1211,19 +1211,19 @@ class DatabaseInterface implements DbalInterface * @param string $type NUM|ASSOC|BOTH returned array should either numeric associative or both * @psalm-param DatabaseInterface::FETCH_NUM|DatabaseInterface::FETCH_ASSOC $type * - * @return array|null + * @return array */ public function fetchSingleRow( string $query, string $type = DbalInterface::FETCH_ASSOC, ConnectionType $connectionType = ConnectionType::User, - ): array|null { + ): array { $result = $this->tryQuery($query, $connectionType, cacheAffectedRows: false); if ($result === false) { - return null; + return []; } - return $this->fetchByMode($result, $type) ?: null; + return $this->fetchByMode($result, $type); } /** diff --git a/src/Dbal/DbalInterface.php b/src/Dbal/DbalInterface.php index d93278417e..dd818ec85d 100644 --- a/src/Dbal/DbalInterface.php +++ b/src/Dbal/DbalInterface.php @@ -302,13 +302,13 @@ interface DbalInterface * @param string $type NUM|ASSOC returned array should either numeric associative or both * @psalm-param self::FETCH_NUM|self::FETCH_ASSOC $type * - * @return array|null + * @return array */ public function fetchSingleRow( string $query, string $type = DbalInterface::FETCH_ASSOC, ConnectionType $connectionType = ConnectionType::User, - ): array|null; + ): array; /** * returns all rows in the resultset in one array diff --git a/src/Normalization.php b/src/Normalization.php index a1deb8c5fc..7b578eae22 100644 --- a/src/Normalization.php +++ b/src/Normalization.php @@ -1006,7 +1006,6 @@ class Normalization */ private function findDistinctValuesCount(array $columns, string $table): array { - $result = []; $query = 'SELECT '; foreach ($columns as $column) { if ($column === '') { @@ -1020,7 +1019,12 @@ class Normalization $query = trim($query, ', '); $query .= ' FROM (SELECT * FROM ' . Util::backquote($table) . ' LIMIT 500) as dt;'; - $res = $this->dbi->fetchSingleRow($query) ?? []; + $res = $this->dbi->fetchSingleRow($query); + if ($res === []) { + return []; + } + + $result = []; foreach ($columns as $column) { if ($column === '') { continue; diff --git a/src/Server/Privileges.php b/src/Server/Privileges.php index 07fcfca78d..383b570c12 100644 --- a/src/Server/Privileges.php +++ b/src/Server/Privileges.php @@ -473,7 +473,7 @@ class Privileges $row = $this->dbi->fetchSingleRow($sqlQuery); } - if ($row === null || $row === []) { + if ($row === []) { if ($table === '*' && $this->dbi->isSuperUser()) { $row = []; $sqlQuery = 'SHOW COLUMNS FROM `mysql`.' . ($db === '*' ? '`user`' : '`db`') . ';'; @@ -2057,7 +2057,7 @@ class Privileges if (isset($_POST['change_copy'])) { $userHostCondition = $this->getUserHostCondition($oldUsername, $oldHostname); $row = $this->dbi->fetchSingleRow('SELECT * FROM `mysql`.`user` ' . $userHostCondition . ';'); - if ($row === null || $row === []) { + if ($row === []) { $response = ResponseRenderer::getInstance(); $response->addHTML( Message::notice(__('No user found.'))->getDisplay(), diff --git a/src/Sql.php b/src/Sql.php index 728db4a4a1..da19e8c81f 100644 --- a/src/Sql.php +++ b/src/Sql.php @@ -315,7 +315,7 @@ class Sql $whereClause, )); - if ($row === null) { + if ($row === []) { return ''; } diff --git a/src/StorageEngine.php b/src/StorageEngine.php index 8c8e5e4de3..9d05717901 100644 --- a/src/StorageEngine.php +++ b/src/StorageEngine.php @@ -157,8 +157,8 @@ class StorageEngine $dbi->selectDb($dbName);// Needed for mroonga_command calls if (! Cache::has($cacheKey)) { - $result = $dbi->fetchSingleRow('SELECT mroonga_command(\'object_list\');', DatabaseInterface::FETCH_NUM); - $objectList = (array) json_decode($result[0] ?? '', true); + $result = $dbi->fetchValue('SELECT mroonga_command(\'object_list\');', 0); + $objectList = (array) json_decode((string) $result, true); foreach ($objectList as $mroongaName => $mroongaData) { /** * We only need the objects of table or column types, more info: @@ -187,11 +187,8 @@ class StorageEngine continue; } - $result = $dbi->fetchSingleRow( - 'SELECT mroonga_command(\'object_inspect ' . $mroongaName . '\');', - DatabaseInterface::FETCH_NUM, - ); - $decodedData = json_decode($result[0] ?? '', true); + $result = $dbi->fetchValue('SELECT mroonga_command(\'object_inspect ' . $mroongaName . '\');', 0); + $decodedData = json_decode((string) $result, true); if ($decodedData === null) { // Invalid for some strange reason, maybe query failed continue; diff --git a/src/Table/Table.php b/src/Table/Table.php index 38b2b7a241..4cdfd41b77 100644 --- a/src/Table/Table.php +++ b/src/Table/Table.php @@ -1756,7 +1756,7 @@ class Table implements Stringable ), ); - if (! is_array($result)) { + if ($result === []) { return null; } diff --git a/src/UserPreferences.php b/src/UserPreferences.php index 161d94190f..64c03046a6 100644 --- a/src/UserPreferences.php +++ b/src/UserPreferences.php @@ -93,7 +93,7 @@ class UserPreferences . ' WHERE `username` = ' . $this->dbi->quoteString((string) $relationParameters->user); $row = $this->dbi->fetchSingleRow($query, DatabaseInterface::FETCH_ASSOC, ConnectionType::ControlUser); - if (! is_array($row) || ! isset($row['config_data']) || ! isset($row['ts'])) { + if ($row === [] || ! isset($row['config_data']) || ! isset($row['ts'])) { return ['config_data' => [], 'mtime' => time(), 'type' => 'db']; } @@ -189,7 +189,7 @@ class UserPreferences ); } - return (bool) $this->dbi->fetchSingleRow($query, 'ASSOC', ConnectionType::ControlUser); + return $this->dbi->fetchSingleRow($query, 'ASSOC', ConnectionType::ControlUser) !== []; } /** diff --git a/tests/unit/DatabaseInterfaceTest.php b/tests/unit/DatabaseInterfaceTest.php index e04e07961f..540fa09367 100644 --- a/tests/unit/DatabaseInterfaceTest.php +++ b/tests/unit/DatabaseInterfaceTest.php @@ -185,7 +185,7 @@ class DatabaseInterfaceTest extends AbstractTestCase $mock->expects(self::once()) ->method('fetchSingleRow') - ->willReturn(null); + ->willReturn([]); $mock->expects(self::never())->method('setVersion'); From a07292ecc16ac9f0cbecfd8022209eebfbba36ec Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Thu, 19 Dec 2024 03:32:26 +0000 Subject: [PATCH 16/16] Small changes Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 94 +------------------------------- psalm-baseline.xml | 38 +------------ src/Database/CentralColumns.php | 21 +++---- src/Navigation/Nodes/Node.php | 6 +- src/Partitioning/Maintenance.php | 20 +++---- src/Partitioning/Partition.php | 2 +- src/Plugins/Export/ExportXml.php | 8 +-- src/Server/Privileges.php | 2 +- src/Table/Table.php | 1 + src/Triggers/Triggers.php | 7 +-- 10 files changed, 32 insertions(+), 167 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 139c55c6d6..6e1ac2f400 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -4581,42 +4581,6 @@ parameters: count: 1 path: src/Controllers/Table/Maintenance/RepairController.php - - - message: '#^Parameter \#2 \$sqlQuery of static method PhpMyAdmin\\Html\\Generator\:\:getMessage\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Controllers/Table/Partition/AnalyzeController.php - - - - message: '#^Parameter \#2 \$sqlQuery of static method PhpMyAdmin\\Html\\Generator\:\:getMessage\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Controllers/Table/Partition/CheckController.php - - - - message: '#^Only booleans are allowed in an if condition, mixed given\.$#' - identifier: if.condNotBoolean - count: 1 - path: src/Controllers/Table/Partition/DropController.php - - - - message: '#^Parameter \#2 \$sqlQuery of static method PhpMyAdmin\\Html\\Generator\:\:getMessage\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 2 - path: src/Controllers/Table/Partition/DropController.php - - - - message: '#^Parameter \#2 \$sqlQuery of static method PhpMyAdmin\\Html\\Generator\:\:getMessage\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Controllers/Table/Partition/OptimizeController.php - - - - message: '#^Parameter \#2 \$sqlQuery of static method PhpMyAdmin\\Html\\Generator\:\:getMessage\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Controllers/Table/Partition/RepairController.php - - message: ''' #^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\Config\: @@ -6135,30 +6099,6 @@ parameters: count: 1 path: src/Database/CentralColumns.php - - - message: '#^Cannot access offset ''col_attribute'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 5 - path: src/Database/CentralColumns.php - - - - message: '#^Cannot access offset ''col_default'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Database/CentralColumns.php - - - - message: '#^Cannot access offset ''col_extra'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 2 - path: src/Database/CentralColumns.php - - - - message: '#^Cannot access offset ''col_type'' on mixed\.$#' - identifier: offsetAccess.nonOffsetAccessible - count: 1 - path: src/Database/CentralColumns.php - - message: '#^Cannot access offset int\<0, max\> on mixed\.$#' identifier: offsetAccess.nonOffsetAccessible @@ -6168,7 +6108,7 @@ parameters: - message: '#^Cannot cast mixed to string\.$#' identifier: cast.string - count: 2 + count: 1 path: src/Database/CentralColumns.php - @@ -6183,12 +6123,6 @@ parameters: count: 1 path: src/Database/CentralColumns.php - - - message: '#^Method PhpMyAdmin\\Database\\CentralColumns\:\:findExistingColumns\(\) should return array\\> but returns array\\.$#' - identifier: return.type - count: 1 - path: src/Database/CentralColumns.php - - message: '#^Only booleans are allowed in a negated boolean, PhpMyAdmin\\Dbal\\ResultInterface\|false given\.$#' identifier: booleanNot.exprNotBoolean @@ -6207,12 +6141,6 @@ parameters: count: 3 path: src/Database/CentralColumns.php - - - message: '#^Parameter \#1 \$bitDefaultValue of static method PhpMyAdmin\\Util\:\:convertBitDefaultValue\(\) expects string\|null, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Database/CentralColumns.php - - message: '#^Parameter \#1 \$db of method PhpMyAdmin\\Database\\CentralColumns\:\:updateOneColumn\(\) expects string, mixed given\.$#' identifier: argument.type @@ -6231,12 +6159,6 @@ parameters: count: 1 path: src/Database/CentralColumns.php - - - message: '#^Parameter \#1 \$string of function bin2hex expects string, mixed given\.$#' - identifier: argument.type - count: 1 - path: src/Database/CentralColumns.php - - message: '#^Parameter \#1 \$string of function trim expects string, mixed given\.$#' identifier: argument.type @@ -6262,7 +6184,7 @@ parameters: path: src/Database/CentralColumns.php - - message: '#^Parameter \#2 \$string of function explode expects string, mixed given\.$#' + message: '#^Parameter \#2 \$string of function explode expects string, string\|null given\.$#' identifier: argument.type count: 1 path: src/Database/CentralColumns.php @@ -17079,12 +17001,6 @@ parameters: count: 1 path: src/Table/Table.php - - - message: '#^Method PhpMyAdmin\\Table\\Table\:\:getNonGeneratedColumns\(\) should return array\ but returns list\\.$#' - identifier: return.type - count: 1 - path: src/Table/Table.php - - message: '#^Method PhpMyAdmin\\Table\\Table\:\:getUiPrefsFromDb\(\) should return array\ but returns mixed\.$#' identifier: return.type @@ -17616,12 +17532,6 @@ parameters: count: 4 path: src/Triggers/Triggers.php - - - message: '#^PHPDoc tag @var with type array\\> is not subtype of type list\\>\.$#' - identifier: varTag.type - count: 1 - path: src/Triggers/Triggers.php - - message: '#^Parameter \#1 \$haystack of function str_contains expects string, mixed given\.$#' identifier: argument.type diff --git a/psalm-baseline.xml b/psalm-baseline.xml index b2b254ca8b..4d8f427cc9 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -2867,34 +2867,21 @@ - - - - - - - - - - - - - @@ -2905,9 +2892,6 @@ - - - @@ -3778,9 +3762,6 @@ - - - @@ -3794,40 +3775,25 @@ - - - - - - - - - - - - - - - - + @@ -9770,7 +9736,6 @@ - getStatusInfo('TABLE_COLLATION') ?? '']]> getStatusInfo('TABLE_COMMENT') ?? '']]> @@ -9779,7 +9744,6 @@ - diff --git a/src/Database/CentralColumns.php b/src/Database/CentralColumns.php index bbd189e100..9fcd94e2d6 100644 --- a/src/Database/CentralColumns.php +++ b/src/Database/CentralColumns.php @@ -101,7 +101,7 @@ class CentralColumns * @param int $from starting offset of first result * @param int $num maximum number of results to return * - * @return mixed[] list of $num columns present in central columns list + * @return list> list of $num columns present in central columns list * starting at offset $from for the given database */ public function getColumnsList(string $db, int $from = 0, int $num = 25): array @@ -124,9 +124,8 @@ class CentralColumns } $hasList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); - $this->handleColumnExtra($hasList); - return $hasList; + return $this->handleColumnExtra($hasList); } /** @@ -205,9 +204,8 @@ class CentralColumns . Util::backquote($pmadb) . '.' . Util::backquote($centralListTable) . ' WHERE db_name = ' . $this->dbi->quoteString($db, ConnectionType::ControlUser) . ' AND col_name IN (' . $cols . ');'; $hasList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); - $this->handleColumnExtra($hasList); - return $hasList; + return $this->handleColumnExtra($hasList); } /** @@ -664,7 +662,7 @@ class CentralColumns * @param string $db selected database * @param string $table current table name * - * @return mixed[] encoded list of columns present in central list for the given database + * @return list> encoded list of columns present in central list for the given database */ public function getListRaw(string $db, string $table): array { @@ -690,18 +688,19 @@ class CentralColumns } $columnsList = $this->dbi->fetchResultSimple($query, ConnectionType::ControlUser); - $this->handleColumnExtra($columnsList); - return $columnsList; + return $this->handleColumnExtra($columnsList); } /** * Column `col_extra` is used to store both extra and attributes for a column. * This method separates them. * - * @param mixed[] $columnsList columns list + * @param list> $columnsList columns list + * + * @return list> */ - private function handleColumnExtra(array &$columnsList): void + private function handleColumnExtra(array $columnsList): array { foreach ($columnsList as &$row) { $vals = explode(',', $row['col_extra']); @@ -720,6 +719,8 @@ class CentralColumns $row['col_extra'] = in_array('auto_increment', $vals, true) ? 'auto_increment' : ''; } + + return $columnsList; } /** diff --git a/src/Navigation/Nodes/Node.php b/src/Navigation/Nodes/Node.php index a04056a420..2170141069 100644 --- a/src/Navigation/Nodes/Node.php +++ b/src/Navigation/Nodes/Node.php @@ -609,7 +609,7 @@ class Node * @param int $pos The offset of the list within the results. * @param string $searchClause A string used to filter the results of the query. * - * @return mixed[] + * @return list */ private function getDataFromInfoSchema(int $pos, string $searchClause): array { @@ -650,7 +650,7 @@ class Node * @param int $pos The offset of the list within the results. * @param string $searchClause A string used to filter the results of the query. * - * @return mixed[] + * @return list */ private function getDataFromShowDatabases(int $pos, string $searchClause): array { @@ -732,7 +732,7 @@ class Node * @param int $pos The offset of the list within the results. * @param string $searchClause A string used to filter the results of the query. * - * @return mixed[] + * @return list */ private function getDataFromShowDatabasesLike(UserPrivileges $userPrivileges, int $pos, string $searchClause): array { diff --git a/src/Partitioning/Maintenance.php b/src/Partitioning/Maintenance.php index 87b23c30e3..f83a8b58ac 100644 --- a/src/Partitioning/Maintenance.php +++ b/src/Partitioning/Maintenance.php @@ -19,7 +19,7 @@ final class Maintenance { } - /** @return mixed[] */ + /** @return array{array>>, string} */ public function analyze(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -39,7 +39,7 @@ final class Maintenance return [$rows, $query]; } - /** @return mixed[] */ + /** @return array{array>>, string} */ public function check(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -59,7 +59,7 @@ final class Maintenance return [$rows, $query]; } - /** @return mixed[] */ + /** @return array{bool, string} */ public function drop(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -74,7 +74,7 @@ final class Maintenance return [(bool) $result, $query]; } - /** @return mixed[] */ + /** @return array{array>>, string} */ public function optimize(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -94,10 +94,7 @@ final class Maintenance return [$rows, $query]; } - /** - * @return array - * @psalm-return array{bool, string} - */ + /** @return array{bool, string} */ public function rebuild(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -112,7 +109,7 @@ final class Maintenance return [(bool) $result, $query]; } - /** @return mixed[] */ + /** @return array{array>>, string} */ public function repair(DatabaseName $db, TableName $table, string $partition): array { $query = sprintf( @@ -132,10 +129,7 @@ final class Maintenance return [$rows, $query]; } - /** - * @return array - * @psalm-return array{bool, string} - */ + /** @return array{bool, string} */ public function truncate(DatabaseName $db, TableName $table, string $partition): array { if (Table::get($table->getName(), $db->getName(), $this->dbi)->isView()) { diff --git a/src/Partitioning/Partition.php b/src/Partitioning/Partition.php index 674aa72d2b..1440b83073 100644 --- a/src/Partitioning/Partition.php +++ b/src/Partitioning/Partition.php @@ -178,7 +178,7 @@ class Partition extends SubPartition * @param string $db database name * @param string $table table name * - * @return mixed[] of partition names + * @return list of partition names */ public static function getPartitionNames(string $db, string $table): array { diff --git a/src/Plugins/Export/ExportXml.php b/src/Plugins/Export/ExportXml.php index 8eafa7826f..b401613eb8 100644 --- a/src/Plugins/Export/ExportXml.php +++ b/src/Plugins/Export/ExportXml.php @@ -222,13 +222,13 @@ class ExportXml extends ExportPlugin . '>' . "\n"; if ($exportStruct) { - $result = $dbi->fetchResultSimple( + $result = $dbi->fetchSingleRow( 'SELECT `DEFAULT_CHARACTER_SET_NAME`, `DEFAULT_COLLATION_NAME`' . ' FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME`' . ' = ' . $dbi->quoteString(Current::$database) . ' LIMIT 1', ); - $dbCollation = $result[0]['DEFAULT_COLLATION_NAME']; - $dbCharset = $result[0]['DEFAULT_CHARACTER_SET_NAME']; + $dbCollation = $result['DEFAULT_COLLATION_NAME']; + $dbCharset = $result['DEFAULT_CHARACTER_SET_NAME']; $head .= '