Merge PR #19686 Use native MySQL paging
Closes https://github.com/phpmyadmin/phpmyadmin/pull/19686 Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
commit
34710cf9d1
@ -5205,7 +5205,7 @@ parameters:
|
||||
Use dependency injection instead\.$#
|
||||
'''
|
||||
identifier: staticMethod.deprecated
|
||||
count: 3
|
||||
count: 2
|
||||
path: src/Database/Routines.php
|
||||
|
||||
-
|
||||
@ -5271,7 +5271,7 @@ parameters:
|
||||
-
|
||||
message: '#^Loose comparison via "\=\=" is not allowed\.$#'
|
||||
identifier: equal.notAllowed
|
||||
count: 3
|
||||
count: 1
|
||||
path: src/Database/Routines.php
|
||||
|
||||
-
|
||||
|
||||
@ -3467,7 +3467,6 @@
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[Config::getInstance()]]></code>
|
||||
<code><![CDATA[Config::getInstance()]]></code>
|
||||
<code><![CDATA[Config::getInstance()]]></code>
|
||||
</DeprecatedMethod>
|
||||
<InvalidArgument>
|
||||
<code><![CDATA[$itemParamDir]]></code>
|
||||
|
||||
@ -25,8 +25,6 @@ use PhpMyAdmin\UserPrivilegesFactory;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function array_slice;
|
||||
use function count;
|
||||
use function htmlentities;
|
||||
use function htmlspecialchars;
|
||||
use function in_array;
|
||||
@ -457,8 +455,7 @@ final readonly class RoutinesController implements InvocableController
|
||||
$type = null;
|
||||
}
|
||||
|
||||
$items = Routines::getDetails($this->dbi, Current::$database, $type);
|
||||
$totalNumRoutines = count($items);
|
||||
$totalNumRoutines = Routines::getRoutineCount($this->dbi, Current::$database, $type);
|
||||
$pageSize = $this->config->settings['MaxRoutineList'];
|
||||
$pos = (int) $request->getParam('pos');
|
||||
|
||||
@ -481,7 +478,7 @@ final readonly class RoutinesController implements InvocableController
|
||||
return $this->response->response();
|
||||
}
|
||||
|
||||
$items = array_slice($items, $pos, $pageSize);
|
||||
$items = Routines::getDetails($this->dbi, Current::$database, $type, limit: $pageSize, offset: $pos);
|
||||
|
||||
$isAjax = $request->isAjax() && empty($_REQUEST['ajax_page_request']);
|
||||
|
||||
|
||||
@ -20,9 +20,7 @@ use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function _ngettext;
|
||||
use function array_column;
|
||||
use function array_merge;
|
||||
use function array_multisort;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function htmlentities;
|
||||
@ -42,7 +40,6 @@ use function str_starts_with;
|
||||
use function stripos;
|
||||
|
||||
use const ENT_QUOTES;
|
||||
use const SORT_ASC;
|
||||
|
||||
/**
|
||||
* Functions for routine management.
|
||||
@ -1203,35 +1200,17 @@ class Routines
|
||||
string $db,
|
||||
string|null $which = null,
|
||||
string $name = '',
|
||||
int $limit = 0,
|
||||
int $offset = 0,
|
||||
): array {
|
||||
if (! Config::getInstance()->selectedServer['DisableIS']) {
|
||||
$query = QueryGenerator::getInformationSchemaRoutinesRequest(
|
||||
$dbi->quoteString($db),
|
||||
in_array($which, ['FUNCTION', 'PROCEDURE'], true) ? $which : null,
|
||||
$name === '' ? null : $dbi->quoteString($name),
|
||||
);
|
||||
$routines = $dbi->fetchResultSimple($query);
|
||||
} else {
|
||||
$routines = [];
|
||||
|
||||
if ($which === 'FUNCTION' || $which == null) {
|
||||
$query = 'SHOW FUNCTION STATUS WHERE `Db` = ' . $dbi->quoteString($db);
|
||||
if ($name !== '') {
|
||||
$query .= ' AND `Name` = ' . $dbi->quoteString($name);
|
||||
}
|
||||
|
||||
$routines = $dbi->fetchResultSimple($query);
|
||||
}
|
||||
|
||||
if ($which === 'PROCEDURE' || $which == null) {
|
||||
$query = 'SHOW PROCEDURE STATUS WHERE `Db` = ' . $dbi->quoteString($db);
|
||||
if ($name !== '') {
|
||||
$query .= ' AND `Name` = ' . $dbi->quoteString($name);
|
||||
}
|
||||
|
||||
$routines = array_merge($routines, $dbi->fetchResultSimple($query));
|
||||
}
|
||||
}
|
||||
$query = QueryGenerator::getInformationSchemaRoutinesRequest(
|
||||
$dbi->quoteString($db),
|
||||
in_array($which, ['FUNCTION', 'PROCEDURE'], true) ? $which : null,
|
||||
$name === '' ? null : $dbi->quoteString($name),
|
||||
$limit,
|
||||
$offset,
|
||||
);
|
||||
$routines = $dbi->fetchResultSimple($query);
|
||||
|
||||
$ret = [];
|
||||
/** @var array{Name:string, Type:string, Definer:string, DTD_IDENTIFIER:string|null} $routine */
|
||||
@ -1244,13 +1223,19 @@ class Routines
|
||||
);
|
||||
}
|
||||
|
||||
// Sort results by name
|
||||
$name = array_column($ret, 'name');
|
||||
array_multisort($name, SORT_ASC, $ret);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public static function getRoutineCount(DatabaseInterface $dbi, string $db, string|null $which = null): int
|
||||
{
|
||||
$query = QueryGenerator::getInformationSchemaRoutinesCountRequest(
|
||||
$dbi->quoteString($db),
|
||||
in_array($which, ['FUNCTION', 'PROCEDURE'], true) ? $which : null,
|
||||
);
|
||||
|
||||
return (int) $dbi->fetchValue($query);
|
||||
}
|
||||
|
||||
public static function getFunctionDefinition(DatabaseInterface $dbi, string $db, string $name): string|null
|
||||
{
|
||||
$result = $dbi->fetchValue(
|
||||
|
||||
@ -177,19 +177,13 @@ class Generator
|
||||
string $quotedDbName,
|
||||
string|null $routineType,
|
||||
string|null $quotedRoutineName,
|
||||
int $limit = 0,
|
||||
int $offset = 0,
|
||||
): string {
|
||||
$query = 'SELECT'
|
||||
. ' `ROUTINE_SCHEMA` AS `Db`,'
|
||||
. ' `SPECIFIC_NAME` AS `Name`,'
|
||||
. ' `ROUTINE_TYPE` AS `Type`,'
|
||||
. ' `DEFINER` AS `Definer`,'
|
||||
. ' `LAST_ALTERED` AS `Modified`,'
|
||||
. ' `CREATED` AS `Created`,'
|
||||
. ' `SECURITY_TYPE` AS `Security_type`,'
|
||||
. ' `ROUTINE_COMMENT` AS `Comment`,'
|
||||
. ' `CHARACTER_SET_CLIENT` AS `character_set_client`,'
|
||||
. ' `COLLATION_CONNECTION` AS `collation_connection`,'
|
||||
. ' `DATABASE_COLLATION` AS `Database Collation`,'
|
||||
. ' `DTD_IDENTIFIER`'
|
||||
. ' FROM `information_schema`.`ROUTINES`'
|
||||
. ' WHERE `ROUTINE_SCHEMA` ' . Util::getCollateForIS()
|
||||
@ -202,6 +196,36 @@ class Generator
|
||||
$query .= ' AND `SPECIFIC_NAME` = ' . $quotedRoutineName;
|
||||
}
|
||||
|
||||
$query .= ' ORDER BY `SPECIFIC_NAME`';
|
||||
|
||||
if ($limit > 0) {
|
||||
$query .= ' LIMIT ' . $limit;
|
||||
}
|
||||
|
||||
if ($offset > 0) {
|
||||
$query .= ' OFFSET ' . $offset;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public static function getInformationSchemaRoutinesCountRequest(
|
||||
string $quotedDbName,
|
||||
string|null $routineType,
|
||||
string|null $quotedRoutineName = null,
|
||||
): string {
|
||||
$query = 'SELECT COUNT(*) AS `count`'
|
||||
. ' FROM `information_schema`.`ROUTINES`'
|
||||
. ' WHERE `ROUTINE_SCHEMA` ' . Util::getCollateForIS()
|
||||
. ' = ' . $quotedDbName;
|
||||
if ($routineType !== null) {
|
||||
$query .= " AND `ROUTINE_TYPE` = '" . $routineType . "'";
|
||||
}
|
||||
|
||||
if ($quotedRoutineName !== null) {
|
||||
$query .= ' AND `SPECIFIC_NAME` = ' . $quotedRoutineName;
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
@ -39,20 +39,20 @@ final class RoutinesControllerTest extends AbstractTestCase
|
||||
['Grants for definer@localhost'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
'SHOW FUNCTION STATUS WHERE `Db` = \'test_db\'',
|
||||
[['test_db', 'test_func', 'FUNCTION', 'definer@localhost']],
|
||||
['Db', 'Name', 'Type', 'Definer'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
'SHOW PROCEDURE STATUS WHERE `Db` = \'test_db\'',
|
||||
[['test_db', 'test_proc', 'PROCEDURE', 'definer@localhost']],
|
||||
['Db', 'Name', 'Type', 'Definer'],
|
||||
"SELECT `SPECIFIC_NAME` AS `Name`, `ROUTINE_TYPE` AS `Type`, `DEFINER` AS `Definer`, `DTD_IDENTIFIER` FROM `information_schema`.`ROUTINES` WHERE `ROUTINE_SCHEMA` COLLATE utf8_bin = 'test_db' ORDER BY `SPECIFIC_NAME` LIMIT 250",
|
||||
[['test_db', 'test_func', 'FUNCTION', 'definer@localhost', null], ['test_db', 'test_proc', 'PROCEDURE', 'definer@localhost', null]],
|
||||
['Db', 'Name', 'Type', 'Definer', 'DTD_IDENTIFIER'],
|
||||
);
|
||||
$dummyDbi->addResult('SELECT @@lower_case_table_names', []);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `DEFINER` FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA COLLATE utf8_bin='test_db' AND SPECIFIC_NAME='test_func' AND ROUTINE_TYPE='FUNCTION';",
|
||||
[['definer@localhost']],
|
||||
['DEFINER'],
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='CREATE ROUTINE'",
|
||||
[['CREATE ROUTINE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='EXECUTE'",
|
||||
[['EXECUTE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='CREATE ROUTINE'",
|
||||
@ -64,35 +64,15 @@ final class RoutinesControllerTest extends AbstractTestCase
|
||||
[['EXECUTE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
'SHOW CREATE FUNCTION `test_db`.`test_func`',
|
||||
[['test_func', 'CREATE FUNCTION `test_func` (p INT) RETURNS int(11) BEGIN END']],
|
||||
['Function', 'Create Function'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `DEFINER` FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA COLLATE utf8_bin='test_db' AND SPECIFIC_NAME='test_proc' AND ROUTINE_TYPE='PROCEDURE';",
|
||||
[['definer@localhost']],
|
||||
['DEFINER'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='CREATE ROUTINE'",
|
||||
[['CREATE ROUTINE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='EXECUTE'",
|
||||
[['EXECUTE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
'SHOW CREATE PROCEDURE `test_db`.`test_proc`',
|
||||
[['test_proc2', 'CREATE PROCEDURE `test_proc2` (p INT) BEGIN END']],
|
||||
['Procedure', 'Create Procedure'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='CREATE ROUTINE'",
|
||||
[['CREATE ROUTINE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
"SELECT COUNT(*) AS `count` FROM `information_schema`.`ROUTINES` WHERE `ROUTINE_SCHEMA` COLLATE utf8_bin = 'test_db'",
|
||||
[[2]],
|
||||
['count'],
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
@ -293,6 +273,8 @@ HTML;
|
||||
// phpcs:enable
|
||||
|
||||
self::assertSame($expected, $actual);
|
||||
$dummyDbi->assertAllQueriesConsumed();
|
||||
$dummyDbi->assertAllSelectsConsumed();
|
||||
}
|
||||
|
||||
public function testWithoutRoutines(): void
|
||||
@ -312,13 +294,22 @@ HTML;
|
||||
[['GRANT ALL PRIVILEGES ON *.* TO `definer`@`localhost`']],
|
||||
['Grants for definer@localhost'],
|
||||
);
|
||||
$dummyDbi->addResult('SHOW FUNCTION STATUS WHERE `Db` = \'test_db\'', [], ['Db', 'Name', 'Type', 'Definer']);
|
||||
$dummyDbi->addResult('SHOW PROCEDURE STATUS WHERE `Db` = \'test_db\'', [], ['Db', 'Name', 'Type', 'Definer']);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `PRIVILEGE_TYPE` FROM `INFORMATION_SCHEMA`.`USER_PRIVILEGES` WHERE GRANTEE='''definer''@''localhost''' AND PRIVILEGE_TYPE='CREATE ROUTINE'",
|
||||
[['CREATE ROUTINE']],
|
||||
['PRIVILEGE_TYPE'],
|
||||
);
|
||||
$dummyDbi->addResult('SELECT @@lower_case_table_names', []);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT COUNT(*) AS `count` FROM `information_schema`.`ROUTINES` WHERE `ROUTINE_SCHEMA` COLLATE utf8_bin = 'test_db'",
|
||||
[[1]],
|
||||
['count'],
|
||||
);
|
||||
$dummyDbi->addResult(
|
||||
"SELECT `SPECIFIC_NAME` AS `Name`, `ROUTINE_TYPE` AS `Type`, `DEFINER` AS `Definer`, `DTD_IDENTIFIER` FROM `information_schema`.`ROUTINES` WHERE `ROUTINE_SCHEMA` COLLATE utf8_bin = 'test_db' ORDER BY `SPECIFIC_NAME` LIMIT 250",
|
||||
[],
|
||||
['Db', 'Name', 'Type', 'Definer', 'DTD_IDENTIFIER'],
|
||||
);
|
||||
// phpcs:enable
|
||||
|
||||
$dbi = $this->createDatabaseInterface($dummyDbi);
|
||||
@ -438,5 +429,7 @@ HTML;
|
||||
// phpcs:enable
|
||||
|
||||
self::assertSame($expected, $actual);
|
||||
$dummyDbi->assertAllQueriesConsumed();
|
||||
$dummyDbi->assertAllSelectsConsumed();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user