Refactor getFunctionNames & getProcedureNames

Signed-off-by: Kamil Tekiela <tekiela246@gmail.com>
This commit is contained in:
Kamil Tekiela 2025-04-30 21:17:16 +01:00
parent 88b759fbdb
commit 3c88ec1457
7 changed files with 58 additions and 73 deletions

View File

@ -1258,38 +1258,14 @@ class Routines
* @return array<int, string>
* @psalm-return list<non-empty-string>
*/
public static function getFunctionNames(DatabaseInterface $dbi, string $db): array
public static function getNames(DatabaseInterface $dbi, string $db, RoutineType $type): array
{
/** @psalm-var list<array{Db: string, Name: string, Type: string}> $functions */
$functions = $dbi->fetchResultSimple('SHOW FUNCTION STATUS;');
$names = [];
foreach ($functions as $function) {
if ($function['Db'] !== $db || $function['Type'] !== 'FUNCTION' || $function['Name'] === '') {
continue;
}
$names[] = $function['Name'];
}
return $names;
}
/**
* @return array<int, string>
* @psalm-return list<non-empty-string>
*/
public static function getProcedureNames(DatabaseInterface $dbi, string $db): array
{
/** @psalm-var list<array{Db: string, Name: string, Type: string}> $procedures */
$procedures = $dbi->fetchResultSimple('SHOW PROCEDURE STATUS;');
$names = [];
foreach ($procedures as $procedure) {
if ($procedure['Db'] !== $db || $procedure['Type'] !== 'PROCEDURE' || $procedure['Name'] === '') {
continue;
}
$names[] = $procedure['Name'];
}
/** @var list<non-empty-string> $names */
$names = $dbi->fetchSingleColumn(
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES'
. ' WHERE ROUTINE_SCHEMA = ' . $dbi->quoteString($db)
. " AND ROUTINE_TYPE = '" . $type->value . "' AND SPECIFIC_NAME != ''",
);
return $names;
}

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Database\Events;
use PhpMyAdmin\Database\Routines;
use PhpMyAdmin\Database\RoutineType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Engines\Innodb;
use PhpMyAdmin\Identifiers\DatabaseName;
@ -55,7 +56,7 @@ class Operations
*/
public function runProcedureAndFunctionDefinitions(string $db, DatabaseName $newDatabaseName): void
{
foreach (Routines::getProcedureNames($this->dbi, $db) as $procedureName) {
foreach (Routines::getNames($this->dbi, $db, RoutineType::Procedure) as $procedureName) {
$this->dbi->selectDb($db);
$query = Routines::getProcedureDefinition($this->dbi, $db, $procedureName);
if ($query === null) {
@ -68,7 +69,7 @@ class Operations
$this->dbi->query($query);
}
foreach (Routines::getFunctionNames($this->dbi, $db) as $functionName) {
foreach (Routines::getNames($this->dbi, $db, RoutineType::Function) as $functionName) {
$this->dbi->selectDb($db);
$query = Routines::getFunctionDefinition($this->dbi, $db, $functionName);
if ($query === null) {

View File

@ -13,6 +13,7 @@ use PhpMyAdmin\Config;
use PhpMyAdmin\Current;
use PhpMyAdmin\Database\Events;
use PhpMyAdmin\Database\Routines;
use PhpMyAdmin\Database\RoutineType;
use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Exceptions\ExportException;
@ -617,8 +618,8 @@ class ExportSql extends ExportPlugin
$delimiter = '$$';
$dbi = DatabaseInterface::getInstance();
$procedureNames = Routines::getProcedureNames($dbi, $db);
$functionNames = Routines::getFunctionNames($dbi, $db);
$procedureNames = Routines::getNames($dbi, $db, RoutineType::Procedure);
$functionNames = Routines::getNames($dbi, $db, RoutineType::Function);
if ($procedureNames || $functionNames) {
$text .= "\n"

View File

@ -9,6 +9,7 @@ use PhpMyAdmin\Config;
use PhpMyAdmin\Current;
use PhpMyAdmin\Database\Events;
use PhpMyAdmin\Database\Routines;
use PhpMyAdmin\Database\RoutineType;
use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Export\Export;
@ -307,7 +308,7 @@ class ExportXml extends ExportPlugin
$head .= $this->exportDefinitions(
Current::$database,
'function',
Routines::getFunctionNames($dbi, Current::$database),
Routines::getNames($dbi, Current::$database, RoutineType::Function),
);
}
@ -315,7 +316,7 @@ class ExportXml extends ExportPlugin
$head .= $this->exportDefinitions(
Current::$database,
'procedure',
Routines::getProcedureNames($dbi, Current::$database),
Routines::getNames($dbi, Current::$database, RoutineType::Procedure),
);
}

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Tests\Database;
use PhpMyAdmin\Config;
use PhpMyAdmin\Current;
use PhpMyAdmin\Database\Routines;
use PhpMyAdmin\Database\RoutineType;
use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Tests\AbstractTestCase;
@ -476,18 +477,16 @@ class RoutinesTest extends AbstractTestCase
{
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addResult(
'SHOW FUNCTION STATUS;',
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'FUNCTION' AND SPECIFIC_NAME != ''",
[
['db_test', 'test_func', 'FUNCTION'],
['test_db', 'test_func1', 'FUNCTION'],
['test_db', '', 'FUNCTION'],
['test_db', 'test_func2', 'FUNCTION'],
['test_db', 'test_func', 'PROCEDURE'],
['test_func1'],
['test_func2'],
],
['Db', 'Name', 'Type'],
['Name'],
);
$names = Routines::getFunctionNames($this->createDatabaseInterface($dbiDummy), 'test_db');
$names = Routines::getNames($this->createDatabaseInterface($dbiDummy), 'test_db', RoutineType::Function);
self::assertSame(['test_func1', 'test_func2'], $names);
$dbiDummy->assertAllQueriesConsumed();
@ -497,12 +496,13 @@ class RoutinesTest extends AbstractTestCase
{
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addResult(
'SHOW FUNCTION STATUS;',
[['db_test', 'test_func', 'FUNCTION'], ['test_db', '', 'FUNCTION'], ['test_db', 'test_func', 'PROCEDURE']],
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'FUNCTION' AND SPECIFIC_NAME != ''",
[],
['Db', 'Name', 'Type'],
);
$names = Routines::getFunctionNames($this->createDatabaseInterface($dbiDummy), 'test_db');
$names = Routines::getNames($this->createDatabaseInterface($dbiDummy), 'test_db', RoutineType::Function);
self::assertSame([], $names);
$dbiDummy->assertAllQueriesConsumed();
@ -512,18 +512,16 @@ class RoutinesTest extends AbstractTestCase
{
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addResult(
'SHOW PROCEDURE STATUS;',
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'PROCEDURE' AND SPECIFIC_NAME != ''",
[
['db_test', 'test_proc', 'PROCEDURE'],
['test_db', 'test_proc1', 'PROCEDURE'],
['test_db', '', 'PROCEDURE'],
['test_db', 'test_proc2', 'PROCEDURE'],
['test_db', 'test_proc', 'FUNCTION'],
['test_proc1', 'PROCEDURE'],
['test_proc2', 'PROCEDURE'],
],
['Db', 'Name', 'Type'],
['Name'],
);
$names = Routines::getProcedureNames($this->createDatabaseInterface($dbiDummy), 'test_db');
$names = Routines::getNames($this->createDatabaseInterface($dbiDummy), 'test_db', RoutineType::Procedure);
self::assertSame(['test_proc1', 'test_proc2'], $names);
$dbiDummy->assertAllQueriesConsumed();
@ -533,16 +531,13 @@ class RoutinesTest extends AbstractTestCase
{
$dbiDummy = $this->createDbiDummy();
$dbiDummy->addResult(
'SHOW PROCEDURE STATUS;',
[
['db_test', 'test_proc', 'PROCEDURE'],
['test_db', '', 'PROCEDURE'],
['test_db', 'test_proc', 'FUNCTION'],
],
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'PROCEDURE' AND SPECIFIC_NAME != ''",
[],
['Db', 'Name', 'Type'],
);
$names = Routines::getProcedureNames($this->createDatabaseInterface($dbiDummy), 'test_db');
$names = Routines::getNames($this->createDatabaseInterface($dbiDummy), 'test_db', RoutineType::Procedure);
self::assertSame([], $names);
$dbiDummy->assertAllQueriesConsumed();

View File

@ -179,8 +179,8 @@ class ExportXmlTest extends AbstractTestCase
$config->selectedServer['DisableIS'] = false;
Current::$database = 'd<"b';
$functions = [['d<"b', 'fn', 'FUNCTION']];
$procedures = [['d<"b', 'pr', 'PROCEDURE']];
$functions = [['fn']];
$procedures = [['pr']];
$dbiDummy = $this->createDbiDummy();
$dbi = $this->createDatabaseInterface($dbiDummy);
@ -191,8 +191,18 @@ class ExportXmlTest extends AbstractTestCase
[['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(
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'd<\\\"b' AND ROUTINE_TYPE = 'FUNCTION' AND SPECIFIC_NAME != ''",
$functions,
['Name'],
);
$dbiDummy->addResult(
'SELECT SPECIFIC_NAME FROM information_schema.ROUTINES '
. "WHERE ROUTINE_SCHEMA = 'd<\\\"b' AND ROUTINE_TYPE = 'PROCEDURE' AND SPECIFIC_NAME != ''",
$procedures,
['Name'],
);
$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\'',
@ -327,6 +337,7 @@ class ExportXmlTest extends AbstractTestCase
' &lt;/pma:structure_schemas&gt;',
$result,
);
$dbiDummy->assertAllQueriesConsumed();
}
public function testExportFooter(): void

View File

@ -1780,14 +1780,14 @@ class DbiDummy implements DbiExtension
],
],
[
'query' => 'SHOW PROCEDURE STATUS;',
'columns' => ['Db', 'Name', 'Type'],
'result' => [['test_db', 'test_proc1', 'PROCEDURE'], ['test_db', 'test_proc2', 'PROCEDURE']],
'query' => "SELECT SPECIFIC_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'PROCEDURE' AND SPECIFIC_NAME != ''",
'columns' => ['Name'],
'result' => [['test_proc1'], ['test_proc2']],
],
[
'query' => 'SHOW FUNCTION STATUS;',
'columns' => ['Db', 'Name', 'Type'],
'result' => [['test_db', 'test_func', 'FUNCTION']],
'query' => "SELECT SPECIFIC_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = 'test_db' AND ROUTINE_TYPE = 'FUNCTION' AND SPECIFIC_NAME != ''",
'columns' => ['Name'],
'result' => [['test_func']],
],
[
'query' => 'SHOW CREATE PROCEDURE `test_db`.`test_proc1`',