From 16e3d9477434302da179f74603c515b9da4b5f03 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Wed, 31 May 2023 21:57:57 +0100 Subject: [PATCH 1/2] Fix Misc class Signed-off-by: Kamil Tekiela --- phpstan-baseline.neon | 10 ---------- psalm-baseline.xml | 12 ------------ src/Utils/Misc.php | 7 ++----- tests/Utils/MiscTest.php | 19 ++++++------------- 4 files changed, 8 insertions(+), 40 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 79f15b246..27d0e7ce3 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1185,16 +1185,6 @@ parameters: count: 1 path: tests/Parser/WithStatementTest.php - - - message: "#^Parameter \\#1 \\$statement of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Misc\\:\\:getAliases\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\Statements\\\\SelectStatement, PhpMyAdmin\\\\SqlParser\\\\Statement\\|null given\\.$#" - count: 1 - path: tests/Utils/MiscTest.php - - - - message: "#^Parameter \\#2 \\$database of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Misc\\:\\:getAliases\\(\\) expects string, string\\|null given\\.$#" - count: 1 - path: tests/Utils/MiscTest.php - - message: "#^Parameter \\#2 \\$list of static method PhpMyAdmin\\\\SqlParser\\\\Utils\\\\Query\\:\\:getClause\\(\\) expects PhpMyAdmin\\\\SqlParser\\\\TokensList, PhpMyAdmin\\\\SqlParser\\\\TokensList\\|null given\\.$#" count: 9 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 36ffe79a8..b21260e99 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -5420,9 +5420,6 @@ - - ! ($statement instanceof SelectStatement) - $tables[$thisDb] @@ -5735,15 +5732,6 @@ setAccessible - - - $statement - - - $db - $statement - - list]]> diff --git a/src/Utils/Misc.php b/src/Utils/Misc.php index f4e0bcd83..15576fa73 100644 --- a/src/Utils/Misc.php +++ b/src/Utils/Misc.php @@ -4,7 +4,6 @@ namespace PhpMyAdmin\SqlParser\Utils; -use PhpMyAdmin\SqlParser\Components\Expression; use PhpMyAdmin\SqlParser\Statements\SelectStatement; /** @@ -20,9 +19,9 @@ class Misc * * @return array|string|null>>|null>> */ - public static function getAliases($statement, $database) + public static function getAliases(SelectStatement $statement, string $database): array { - if (! ($statement instanceof SelectStatement) || empty($statement->expr) || empty($statement->from)) { + if (empty($statement->expr) || empty($statement->from)) { return []; } @@ -33,8 +32,6 @@ public static function getAliases($statement, $database) /** * Expressions that may contain aliases. * These are extracted from `FROM` and `JOIN` keywords. - * - * @var Expression[] */ $expressions = $statement->from; diff --git a/tests/Utils/MiscTest.php b/tests/Utils/MiscTest.php index 338628eb6..ed7d6929d 100644 --- a/tests/Utils/MiscTest.php +++ b/tests/Utils/MiscTest.php @@ -5,13 +5,13 @@ namespace PhpMyAdmin\SqlParser\Tests\Utils; use PhpMyAdmin\SqlParser\Parser; +use PhpMyAdmin\SqlParser\Statements\SelectStatement; use PhpMyAdmin\SqlParser\Tests\TestCase; use PhpMyAdmin\SqlParser\Utils\Misc; class MiscTest extends TestCase { /** - * @param mixed[] $expected * @psalm-param array}> @@ -19,17 +19,15 @@ class MiscTest extends TestCase * * @dataProvider getAliasesProvider */ - public function testGetAliases(string $query, string|null $db, array $expected): void + public function testGetAliases(string $query, string $db, array $expected): void { $parser = new Parser($query); - $statement = empty($parser->statements[0]) ? - null : $parser->statements[0]; - $this->assertEquals($expected, Misc::getAliases($statement, $db)); + $this->assertInstanceOf(SelectStatement::class, $parser->statements[0]); + $this->assertEquals($expected, Misc::getAliases($parser->statements[0], $db)); } /** - * @return array> - * @psalm-return list}> * }>}> @@ -107,14 +105,9 @@ public static function getAliasesProvider(): array 'sakila', [], ], - [ - '', - null, - [], - ], [ 'SELECT 1', - null, + '', [], ], [ From e47aef6f27488ee6b7436ffccf19ac0f584252fc Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Wed, 31 May 2023 22:09:11 +0100 Subject: [PATCH 2/2] Move getAliases to SelectStatement Signed-off-by: Kamil Tekiela --- psalm-baseline.xml | 8 +- src/Statements/SelectStatement.php | 81 ++++++++++++++++++ src/Utils/Misc.php | 95 --------------------- tests/Builder/StatementTest.php | 118 ++++++++++++++++++++++++++ tests/Utils/MiscTest.php | 130 ----------------------------- 5 files changed, 202 insertions(+), 230 deletions(-) delete mode 100644 src/Utils/Misc.php delete mode 100644 tests/Utils/MiscTest.php diff --git a/psalm-baseline.xml b/psalm-baseline.xml index b21260e99..c8719a292 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -5177,6 +5177,9 @@ + + $tables[$thisDb] + $endOptions $groupOptions @@ -5419,11 +5422,6 @@ type === Token::TYPE_KEYWORD]]> - - - $tables[$thisDb] - - int diff --git a/src/Statements/SelectStatement.php b/src/Statements/SelectStatement.php index 6aad579f8..cee5b3555 100644 --- a/src/Statements/SelectStatement.php +++ b/src/Statements/SelectStatement.php @@ -366,4 +366,85 @@ public function getClauses() return static::$clauses; } + + /** + * Gets a list of all aliases and their original names. + * + * @param string $database the name of the database + * + * @return array|string|null>>|null>> + */ + public function getAliases(string $database): array + { + if (empty($this->expr) || empty($this->from)) { + return []; + } + + $retval = []; + + $tables = []; + + /** + * Expressions that may contain aliases. + * These are extracted from `FROM` and `JOIN` keywords. + */ + $expressions = $this->from; + + // Adding expressions from JOIN. + if (! empty($this->join)) { + foreach ($this->join as $join) { + $expressions[] = $join->expr; + } + } + + foreach ($expressions as $expr) { + if (! isset($expr->table) || ($expr->table === '')) { + continue; + } + + $thisDb = isset($expr->database) && ($expr->database !== '') ? + $expr->database : $database; + + if (! isset($retval[$thisDb])) { + $retval[$thisDb] = [ + 'alias' => null, + 'tables' => [], + ]; + } + + if (! isset($retval[$thisDb]['tables'][$expr->table])) { + $retval[$thisDb]['tables'][$expr->table] = [ + 'alias' => isset($expr->alias) && ($expr->alias !== '') ? + $expr->alias : null, + 'columns' => [], + ]; + } + + if (! isset($tables[$thisDb])) { + $tables[$thisDb] = []; + } + + $tables[$thisDb][$expr->alias] = $expr->table; + } + + foreach ($this->expr as $expr) { + if (! isset($expr->column, $expr->alias) || ($expr->column === '') || ($expr->alias === '')) { + continue; + } + + $thisDb = isset($expr->database) && ($expr->database !== '') ? + $expr->database : $database; + + if (isset($expr->table) && ($expr->table !== '')) { + $thisTable = $tables[$thisDb][$expr->table] ?? $expr->table; + $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias; + } else { + foreach ($retval[$thisDb]['tables'] as &$table) { + $table['columns'][$expr->column] = $expr->alias; + } + } + } + + return $retval; + } } diff --git a/src/Utils/Misc.php b/src/Utils/Misc.php deleted file mode 100644 index 15576fa73..000000000 --- a/src/Utils/Misc.php +++ /dev/null @@ -1,95 +0,0 @@ -|string|null>>|null>> - */ - public static function getAliases(SelectStatement $statement, string $database): array - { - if (empty($statement->expr) || empty($statement->from)) { - return []; - } - - $retval = []; - - $tables = []; - - /** - * Expressions that may contain aliases. - * These are extracted from `FROM` and `JOIN` keywords. - */ - $expressions = $statement->from; - - // Adding expressions from JOIN. - if (! empty($statement->join)) { - foreach ($statement->join as $join) { - $expressions[] = $join->expr; - } - } - - foreach ($expressions as $expr) { - if (! isset($expr->table) || ($expr->table === '')) { - continue; - } - - $thisDb = isset($expr->database) && ($expr->database !== '') ? - $expr->database : $database; - - if (! isset($retval[$thisDb])) { - $retval[$thisDb] = [ - 'alias' => null, - 'tables' => [], - ]; - } - - if (! isset($retval[$thisDb]['tables'][$expr->table])) { - $retval[$thisDb]['tables'][$expr->table] = [ - 'alias' => isset($expr->alias) && ($expr->alias !== '') ? - $expr->alias : null, - 'columns' => [], - ]; - } - - if (! isset($tables[$thisDb])) { - $tables[$thisDb] = []; - } - - $tables[$thisDb][$expr->alias] = $expr->table; - } - - foreach ($statement->expr as $expr) { - if (! isset($expr->column, $expr->alias) || ($expr->column === '') || ($expr->alias === '')) { - continue; - } - - $thisDb = isset($expr->database) && ($expr->database !== '') ? - $expr->database : $database; - - if (isset($expr->table) && ($expr->table !== '')) { - $thisTable = $tables[$thisDb][$expr->table] ?? $expr->table; - $retval[$thisDb]['tables'][$thisTable]['columns'][$expr->column] = $expr->alias; - } else { - foreach ($retval[$thisDb]['tables'] as &$table) { - $table['columns'][$expr->column] = $expr->alias; - } - } - } - - return $retval; - } -} diff --git a/tests/Builder/StatementTest.php b/tests/Builder/StatementTest.php index ea483ccda..01a127c46 100644 --- a/tests/Builder/StatementTest.php +++ b/tests/Builder/StatementTest.php @@ -8,6 +8,7 @@ use PhpMyAdmin\SqlParser\Components\Expression; use PhpMyAdmin\SqlParser\Components\Limit; use PhpMyAdmin\SqlParser\Components\OptionsArray; +use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Statements\SelectStatement; use PhpMyAdmin\SqlParser\Tests\TestCase; @@ -39,4 +40,121 @@ public function testBuilder(): void (string) $stmt ); } + + /** + * @psalm-param array}> + * }> $expected + * + * @dataProvider getAliasesProvider + */ + public function testGetAliases(string $query, string $db, array $expected): void + { + $parser = new Parser($query); + $this->assertInstanceOf(SelectStatement::class, $parser->statements[0]); + $this->assertEquals($expected, $parser->statements[0]->getAliases($db)); + } + + /** + * @psalm-return list}> + * }>}> + */ + public static function getAliasesProvider(): array + { + return [ + [ + 'select * from (select 1) tbl', + 'mydb', + [], + ], + [ + 'select i.name as `n`,abcdef gh from qwerty i', + 'mydb', + [ + 'mydb' => [ + 'alias' => null, + 'tables' => [ + 'qwerty' => [ + 'alias' => 'i', + 'columns' => [ + 'name' => 'n', + 'abcdef' => 'gh', + ], + ], + ], + ], + ], + ], + [ + 'select film_id id,title from film', + 'sakila', + [ + 'sakila' => [ + 'alias' => null, + 'tables' => [ + 'film' => [ + 'alias' => null, + 'columns' => ['film_id' => 'id'], + ], + ], + ], + ], + ], + [ + 'select `sakila`.`A`.`actor_id` as aid,`F`.`film_id` `fid`,' + . 'last_update updated from `sakila`.actor A join `film_actor` as ' + . '`F` on F.actor_id = A.`actor_id`', + 'sakila', + [ + 'sakila' => [ + 'alias' => null, + 'tables' => [ + 'film_actor' => [ + 'alias' => 'F', + 'columns' => [ + 'film_id' => 'fid', + 'last_update' => 'updated', + ], + ], + 'actor' => [ + 'alias' => 'A', + 'columns' => [ + 'actor_id' => 'aid', + 'last_update' => 'updated', + ], + ], + ], + ], + ], + ], + [ + 'SELECT film_id FROM (SELECT * FROM film) as f;', + 'sakila', + [], + ], + [ + 'SELECT 1', + '', + [], + ], + [ + 'SELECT * FROM orders AS ord WHERE 1', + 'db', + [ + 'db' => [ + 'alias' => null, + 'tables' => [ + 'orders' => [ + 'alias' => 'ord', + 'columns' => [], + ], + ], + ], + ], + ], + ]; + } } diff --git a/tests/Utils/MiscTest.php b/tests/Utils/MiscTest.php deleted file mode 100644 index ed7d6929d..000000000 --- a/tests/Utils/MiscTest.php +++ /dev/null @@ -1,130 +0,0 @@ -}> - * }> $expected - * - * @dataProvider getAliasesProvider - */ - public function testGetAliases(string $query, string $db, array $expected): void - { - $parser = new Parser($query); - $this->assertInstanceOf(SelectStatement::class, $parser->statements[0]); - $this->assertEquals($expected, Misc::getAliases($parser->statements[0], $db)); - } - - /** - * @psalm-return list}> - * }>}> - */ - public static function getAliasesProvider(): array - { - return [ - [ - 'select * from (select 1) tbl', - 'mydb', - [], - ], - [ - 'select i.name as `n`,abcdef gh from qwerty i', - 'mydb', - [ - 'mydb' => [ - 'alias' => null, - 'tables' => [ - 'qwerty' => [ - 'alias' => 'i', - 'columns' => [ - 'name' => 'n', - 'abcdef' => 'gh', - ], - ], - ], - ], - ], - ], - [ - 'select film_id id,title from film', - 'sakila', - [ - 'sakila' => [ - 'alias' => null, - 'tables' => [ - 'film' => [ - 'alias' => null, - 'columns' => ['film_id' => 'id'], - ], - ], - ], - ], - ], - [ - 'select `sakila`.`A`.`actor_id` as aid,`F`.`film_id` `fid`,' - . 'last_update updated from `sakila`.actor A join `film_actor` as ' - . '`F` on F.actor_id = A.`actor_id`', - 'sakila', - [ - 'sakila' => [ - 'alias' => null, - 'tables' => [ - 'film_actor' => [ - 'alias' => 'F', - 'columns' => [ - 'film_id' => 'fid', - 'last_update' => 'updated', - ], - ], - 'actor' => [ - 'alias' => 'A', - 'columns' => [ - 'actor_id' => 'aid', - 'last_update' => 'updated', - ], - ], - ], - ], - ], - ], - [ - 'SELECT film_id FROM (SELECT * FROM film) as f;', - 'sakila', - [], - ], - [ - 'SELECT 1', - '', - [], - ], - [ - 'SELECT * FROM orders AS ord WHERE 1', - 'db', - [ - 'db' => [ - 'alias' => null, - 'tables' => [ - 'orders' => [ - 'alias' => 'ord', - 'columns' => [], - ], - ], - ], - ], - ], - ]; - } -}