From 6a2b7ed8531cfac4604b5b5747416bf7fbc281dc Mon Sep 17 00:00:00 2001 From: Nicolas Giraud Date: Thu, 22 Jun 2023 13:39:38 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Add=20unit=20tests=20showing=20that=20SELEC?= =?UTF-8?q?T=E2=80=A6OVER=20fails.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Parser/SelectStatementTest.php | 1 + ...rseSelectAggregateWithPartitionAndAlias.in | 1 + ...seSelectAggregateWithPartitionAndAlias.out | 347 ++++++++++++++++++ 3 files changed, 349 insertions(+) create mode 100644 tests/data/parser/parseSelectAggregateWithPartitionAndAlias.in create mode 100644 tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out diff --git a/tests/Parser/SelectStatementTest.php b/tests/Parser/SelectStatementTest.php index 309a60926..c43fa0d36 100644 --- a/tests/Parser/SelectStatementTest.php +++ b/tests/Parser/SelectStatementTest.php @@ -46,6 +46,7 @@ public function selectProvider(): array ['parser/parseSelect14'], ['parser/parseSelect15'], ['parser/parseSelect16'], + ['parser/parseSelectAggregateWithPartitionAndAlias'], ['parser/parseSelectErr1'], ['parser/parseSelectErr2'], ['parser/parseSelectNested'], diff --git a/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.in b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.in new file mode 100644 index 000000000..56d4b5236 --- /dev/null +++ b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.in @@ -0,0 +1 @@ +SELECT *, COUNT(*) OVER(PARTITION BY `REGION`) AS "count(REGION)" FROM `world_borders` diff --git a/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out new file mode 100644 index 000000000..ec36edd07 --- /dev/null +++ b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out @@ -0,0 +1,347 @@ +{ + "query": "SELECT *, COUNT(*) OVER(PARTITION BY `REGION`) AS \"count(REGION)\" FROM `world_borders`\n", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "SELECT *, COUNT(*) OVER(PARTITION BY `REGION`) AS \"count(REGION)\" FROM `world_borders`\n", + "len": 87, + "last": 87, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "SELECT", + "value": "SELECT", + "keyword": "SELECT", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 6 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "*", + "value": "*", + "keyword": null, + "type": 2, + "flags": 16, + "position": 7 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ",", + "value": ",", + "keyword": null, + "type": 2, + "flags": 16, + "position": 8 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 9 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "COUNT", + "value": "COUNT", + "keyword": "COUNT", + "type": 1, + "flags": 33, + "position": 10 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "(", + "value": "(", + "keyword": null, + "type": 2, + "flags": 16, + "position": 15 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "*", + "value": "*", + "keyword": null, + "type": 2, + "flags": 16, + "position": 16 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ")", + "value": ")", + "keyword": null, + "type": 2, + "flags": 16, + "position": 17 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 18 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "OVER", + "value": "OVER", + "keyword": null, + "type": 0, + "flags": 0, + "position": 19 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "(", + "value": "(", + "keyword": null, + "type": 2, + "flags": 16, + "position": 23 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "PARTITION BY", + "value": "PARTITION BY", + "keyword": "PARTITION BY", + "type": 1, + "flags": 7, + "position": 24 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 36 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "`REGION`", + "value": "REGION", + "keyword": null, + "type": 8, + "flags": 2, + "position": 37 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ")", + "value": ")", + "keyword": null, + "type": 2, + "flags": 16, + "position": 45 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 46 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "AS", + "value": "AS", + "keyword": "AS", + "type": 1, + "flags": 3, + "position": 47 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 49 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "\"count(REGION)\"", + "value": "count(REGION)", + "keyword": null, + "type": 7, + "flags": 2, + "position": 50 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 65 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "FROM", + "value": "FROM", + "keyword": "FROM", + "type": 1, + "flags": 3, + "position": 66 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 70 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "`world_borders`", + "value": "world_borders", + "keyword": null, + "type": 8, + "flags": 2, + "position": 71 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "\n", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 86 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 26, + "idx": 26 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\SelectStatement", + "expr": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", + "database": null, + "table": null, + "column": null, + "expr": "*", + "alias": null, + "function": null, + "subquery": null + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", + "database": null, + "table": null, + "column": null, + "expr": "COUNT(*) (PARTITION BY `REGION`)", + "alias": "OVER", + "function": "COUNT", + "subquery": null + } + ], + "from": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", + "database": null, + "table": "world_borders", + "column": null, + "expr": "`world_borders`", + "alias": null, + "function": null, + "subquery": null + } + ], + "index_hints": null, + "partition": null, + "where": null, + "group": null, + "group_options": null, + "having": null, + "order": null, + "limit": null, + "procedure": null, + "into": null, + "join": null, + "union": [], + "end_options": null, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 0, + "last": 24 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [ + [ + "An alias was previously found.", + { + "@type": "@21" + }, + 0 + ], + [ + "An alias was expected.", + { + "@type": "@20" + }, + 0 + ], + [ + "Unexpected token.", + { + "@type": "@21" + }, + 0 + ] + ] + } +} \ No newline at end of file From bf03484b5175d1c9f9884819694a8b79fb239d7b Mon Sep 17 00:00:00 2001 From: Nicolas Giraud Date: Thu, 22 Jun 2023 13:44:41 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Fix=20bad=20alias=20recognition=20on=20SELE?= =?UTF-8?q?CT=E2=80=A6OVER=20statements.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Components/Expression.php | 3 +- ...seSelectAggregateWithPartitionAndAlias.out | 28 ++----------------- 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/Components/Expression.php b/src/Components/Expression.php index b0fd6b0cc..980f59724 100644 --- a/src/Components/Expression.php +++ b/src/Components/Expression.php @@ -367,7 +367,8 @@ public static function parse(Parser $parser, TokensList $list, array $options = && (($prev[1]->type === Token::TYPE_STRING) || ($prev[1]->type === Token::TYPE_SYMBOL && ! ($prev[1]->flags & Token::FLAG_SYMBOL_VARIABLE)) - || ($prev[1]->type === Token::TYPE_NONE)) + || ($prev[1]->type === Token::TYPE_NONE + && $prev[1]->token !== 'OVER')) ) { if (! empty($ret->alias)) { $parser->error('An alias was previously found.', $token); diff --git a/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out index ec36edd07..3fcc0454b 100644 --- a/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out +++ b/tests/data/parser/parseSelectAggregateWithPartitionAndAlias.out @@ -275,8 +275,8 @@ "database": null, "table": null, "column": null, - "expr": "COUNT(*) (PARTITION BY `REGION`)", - "alias": "OVER", + "expr": "COUNT(*) OVER(PARTITION BY `REGION`)", + "alias": "count(REGION)", "function": "COUNT", "subquery": null } @@ -320,28 +320,6 @@ }, "errors": { "lexer": [], - "parser": [ - [ - "An alias was previously found.", - { - "@type": "@21" - }, - 0 - ], - [ - "An alias was expected.", - { - "@type": "@20" - }, - 0 - ], - [ - "Unexpected token.", - { - "@type": "@21" - }, - 0 - ] - ] + "parser": [] } } \ No newline at end of file