From afe9173c3eddab2ffce58dac56c3b342de53a281 Mon Sep 17 00:00:00 2001 From: Fawzi Abdulfattah Date: Wed, 10 Jul 2024 01:24:51 +0300 Subject: [PATCH] feat: Implementing and refactoring the KILL statement parser Signed-off-by: Fawzi Abdulfattah --- .gitignore | 1 + src/Parser.php | 4 - src/Statements/KillStatement.php | 171 ++++++++++++++++++-- tests/Parser/KillStatementTest.php | 36 +++-- tests/data/parser/parseKill.out | 15 +- tests/data/parser/parseKill2.in | 1 + tests/data/parser/parseKill2.out | 189 ++++++++++++++++++++++ tests/data/parser/parseKill3.in | 1 + tests/data/parser/parseKill3.out | 121 ++++++++++++++ tests/data/parser/parseKillConnection.out | 17 +- tests/data/parser/parseKillErr1.in | 1 + tests/data/parser/parseKillErr1.out | 130 +++++++++++++++ tests/data/parser/parseKillErr2.in | 1 + tests/data/parser/parseKillErr2.out | 80 +++++++++ tests/data/parser/parseKillErr3.in | 1 + tests/data/parser/parseKillErr3.out | 109 +++++++++++++ tests/data/parser/parseKillErr4.in | 1 + tests/data/parser/parseKillErr4.out | 140 ++++++++++++++++ tests/data/parser/parseKillQuery.out | 17 +- 19 files changed, 967 insertions(+), 69 deletions(-) create mode 100644 tests/data/parser/parseKill2.in create mode 100644 tests/data/parser/parseKill2.out create mode 100644 tests/data/parser/parseKill3.in create mode 100644 tests/data/parser/parseKill3.out create mode 100644 tests/data/parser/parseKillErr1.in create mode 100644 tests/data/parser/parseKillErr1.out create mode 100644 tests/data/parser/parseKillErr2.in create mode 100644 tests/data/parser/parseKillErr2.out create mode 100644 tests/data/parser/parseKillErr3.in create mode 100644 tests/data/parser/parseKillErr3.out create mode 100644 tests/data/parser/parseKillErr4.in create mode 100644 tests/data/parser/parseKillErr4.out diff --git a/.gitignore b/.gitignore index 9bc6509bf..81c367771 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ phpstan.neon # Infection infection.json infection.log +**/.DS_Store diff --git a/src/Parser.php b/src/Parser.php index 6168aff3a..526461dcf 100644 --- a/src/Parser.php +++ b/src/Parser.php @@ -211,10 +211,6 @@ class Parser extends Core 'class' => 'PhpMyAdmin\\SqlParser\\Components\\JoinKeyword', 'field' => 'join', ], - 'KILL' => [ - 'class' => 'PhpMyAdmin\\SqlParser\\Components\\Expression', - 'field' => 'processListId', - ], 'LEFT JOIN' => [ 'class' => 'PhpMyAdmin\\SqlParser\\Components\\JoinKeyword', 'field' => 'join', diff --git a/src/Statements/KillStatement.php b/src/Statements/KillStatement.php index 7040a0f3f..21f16eb26 100644 --- a/src/Statements/KillStatement.php +++ b/src/Statements/KillStatement.php @@ -4,16 +4,22 @@ namespace PhpMyAdmin\SqlParser\Statements; -use PhpMyAdmin\SqlParser\Components\Expression; use PhpMyAdmin\SqlParser\Components\OptionsArray; +use PhpMyAdmin\SqlParser\Exceptions\ParserException; +use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Statement; +use PhpMyAdmin\SqlParser\Token; +use PhpMyAdmin\SqlParser\TokensList; -use function trim; +use function array_slice; +use function count; +use function is_int; -/** - * `KILL` statement. - * - * KILL [CONNECTION | QUERY] processlist_id +/** KILL [HARD|SOFT] + * { + * {CONNECTION|QUERY} id | + * QUERY ID query_id | USER user_name + * } */ class KillStatement extends Statement { @@ -24,20 +30,153 @@ class KillStatement extends Statement * @psalm-var array 1, - 'QUERY' => 1, + 'HARD' => 1, + 'SOFT' => 1, + 'CONNECTION' => 2, + 'QUERY' => 2, + 'USER' => 2, ]; - /** @var Expression|null */ - public $processListId = null; + /** + * Holds the identifier if explicitly set + * + * @psalm-var Statement|int|null + */ + public $identifier = null; + + /** + * Whether MariaDB ID keyword is used or not. + * + * @psalm-var bool + */ + public $IDKeywordUsed = false; + + /** + * Whether parenthesis used around the identifier or not + * + * @psalm-var bool + */ + public $parenthesisUsed = false; + + /** @throws ParserException */ + public function parse(Parser $parser, TokensList $list): void + { + /** + * The state of the parser. + * + * Below are the states of the parser. + * + * 0 --------------------- [ OPTIONS PARSED ] --------------------------> 0 + * + * 0 -------------------- [ number ] -----------------------------------> 2 + * + * 0 -------------------- [ ( ] ----------------------------------------> 3 + * + * 0 -------------------- [ QUERY ID ] ---------------------------------> 0 + * + * 3 -------------------- [ number ] -----------------------------------> 3 + * + * 3 -------------------- [ SELECT STATEMENT ] -------------------------> 2 + * + * 3 -------------------- [ ) ] ----------------------------------------> 2 + * + * 2 ----------------------------------------------------------> Final state + */ + $state = 0; + + ++$list->idx; // Skipping `KILL`. + $this->options = OptionsArray::parse($parser, $list, static::$OPTIONS); + ++$list->idx; + for (; $list->idx < $list->count; ++$list->idx) { + $token = $list->tokens[$list->idx]; + + if ($token->type === Token::TYPE_WHITESPACE || $token->type === Token::TYPE_COMMENT) { + continue; + } - public function build(): string + switch ($state) { + case 0: + $currIdx = $list->idx; + $prev = $list->getPreviousOfType(Token::TYPE_KEYWORD); + $list->idx = $currIdx; + if ($token->type === Token::TYPE_NUMBER && is_int($token->value)) { + $this->identifier = $token->value; + $state = 2; + } elseif ($token->type === Token::TYPE_OPERATOR && $token->value === '(') { + $this->parenthesisUsed = true; + $state = 3; + } elseif ($prev && $token->value === 'ID' && $prev->value === 'QUERY') { + $this->IDKeywordUsed = true; + $state = 0; + } else { + $parser->error('Unexpected token.', $token); + break 2; + } + + break; + + case 3: + if ($token->type === Token::TYPE_KEYWORD && $token->value === 'SELECT') { + $subList = new TokensList(array_slice($list->tokens, $list->idx - 1)); + $subParser = new Parser($subList); + if (count($subParser->errors)) { + foreach ($subParser->errors as $error) { + $parser->errors[] = $error; + } + + break; + } + + $this->identifier = $subParser->statements[0]; + $state = 2; + } elseif ($token->type === Token::TYPE_OPERATOR && $token->value === ')') { + $state = 2; + } elseif ($token->type === Token::TYPE_NUMBER && is_int($token->value)) { + $this->identifier = $token->value; + $state = 3; + } else { + $parser->error('Unexpected token.', $token); + break 2; + } + + break; + } + } + + if ($state !== 2) { + $token = $list->tokens[$list->idx]; + $parser->error('Unexpected end of the KILL statement.', $token); + } + + --$list->idx; + } + + /** + * {@inheritdoc} + */ + public function build() { - $option = $this->options === null || $this->options->isEmpty() - ? '' - : ' ' . OptionsArray::build($this->options); - $expression = $this->processListId === null ? '' : ' ' . Expression::build($this->processListId); + $ret = 'KILL'; + + if ($this->options && count($this->options->options) > 0) { + $ret .= ' ' . OptionsArray::build($this->options); + } + + if ($this->IDKeywordUsed) { + $ret .= ' ID'; + } + + $builtIdentifier = (string) $this->identifier; + if ($this->identifier instanceof Statement) { + $builtIdentifier = $this->identifier->build(); + } + + if ($this->parenthesisUsed) { + $ret .= ' (' . $builtIdentifier . ')'; + } elseif ($this->identifier !== null) { + $ret .= ' ' . $builtIdentifier; + } - return trim('KILL' . $option . $expression); + return $ret; } } diff --git a/tests/Parser/KillStatementTest.php b/tests/Parser/KillStatementTest.php index 99b81f758..2a7c87e4f 100644 --- a/tests/Parser/KillStatementTest.php +++ b/tests/Parser/KillStatementTest.php @@ -10,29 +10,29 @@ class KillStatementTest extends TestCase { - /** - * @dataProvider killProvider - */ + /** @dataProvider killProvider */ public function testKill(string $test): void { $this->runParserTest($test); } - /** - * @return string[][] - */ - public function killProvider(): array + /** @return string[][] */ + public static function killProvider(): array { return [ ['parser/parseKill'], + ['parser/parseKill2'], + ['parser/parseKill3'], ['parser/parseKillConnection'], ['parser/parseKillQuery'], + ['parser/parseKillErr1'], + ['parser/parseKillErr2'], + ['parser/parseKillErr3'], + ['parser/parseKillErr4'], ]; } - /** - * @dataProvider buildKillProvider - */ + /** @dataProvider buildKillProvider */ public function testBuildKill(string $sql): void { $parser = new Parser($sql); @@ -47,13 +47,21 @@ public function testBuildKill(string $sql): void * @return array> * @psalm-return list> */ - public function buildKillProvider(): array + public static function buildKillProvider(): array { return [ ['KILL (SELECT 3 + 4)'], - ['KILL QUERY 3'], - ['KILL CONNECTION 3'], - ['KILL'], + ['KILL QUERY 4'], + ['KILL CONNECTION 5'], + ['KILL 6'], + ['KILL QUERY (SELECT 7)'], + ['KILL SOFT QUERY (SELECT 8)'], + ['KILL HARD 9'], + ['KILL USER 10'], + ['KILL SOFT (SELECT 1)'], + ['KILL (2)'], + ['KILL QUERY ID (2)'], + ['KILL QUERY ID (SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST LIMIT 0, 1)'], ]; } } diff --git a/tests/data/parser/parseKill.out b/tests/data/parser/parseKill.out index 33e63ed8e..537583096 100644 --- a/tests/data/parser/parseKill.out +++ b/tests/data/parser/parseKill.out @@ -61,22 +61,15 @@ "statements": [ { "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", - "processListId": { - "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", - "database": null, - "table": null, - "column": null, - "expr": "1", - "alias": null, - "function": null, - "subquery": null - }, + "identifier": 1, + "IDKeywordUsed": false, + "parenthesisUsed": false, "options": { "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", "options": [] }, "first": 0, - "last": 2 + "last": 3 } ], "brackets": 0, diff --git a/tests/data/parser/parseKill2.in b/tests/data/parser/parseKill2.in new file mode 100644 index 000000000..ff8653ef8 --- /dev/null +++ b/tests/data/parser/parseKill2.in @@ -0,0 +1 @@ +KILL (SELECT 3 + 4) \ No newline at end of file diff --git a/tests/data/parser/parseKill2.out b/tests/data/parser/parseKill2.out new file mode 100644 index 000000000..d079cb1eb --- /dev/null +++ b/tests/data/parser/parseKill2.out @@ -0,0 +1,189 @@ +{ + "query": "KILL (SELECT 3 + 4)", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL (SELECT 3 + 4)", + "len": 19, + "last": 19, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 4 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "(", + "value": "(", + "keyword": null, + "type": 2, + "flags": 16, + "position": 5 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "SELECT", + "value": "SELECT", + "keyword": "SELECT", + "type": 1, + "flags": 3, + "position": 6 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 12 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "3", + "value": 3, + "keyword": null, + "type": 6, + "flags": 0, + "position": 13 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 14 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "+", + "value": "+", + "keyword": null, + "type": 2, + "flags": 1, + "position": 15 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 16 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "4", + "value": 4, + "keyword": null, + "type": 6, + "flags": 0, + "position": 17 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ")", + "value": ")", + "keyword": null, + "type": 2, + "flags": 16, + "position": 18 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 12, + "idx": 12 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\SelectStatement", + "expr": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", + "database": null, + "table": null, + "column": null, + "expr": "3 + 4", + "alias": null, + "function": null, + "subquery": null + } + ], + "from": [], + "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": 8 + }, + "IDKeywordUsed": false, + "parenthesisUsed": true, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 0, + "last": 11 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKill3.in b/tests/data/parser/parseKill3.in new file mode 100644 index 000000000..dc834b146 --- /dev/null +++ b/tests/data/parser/parseKill3.in @@ -0,0 +1 @@ +KILL QUERY ID 10 \ No newline at end of file diff --git a/tests/data/parser/parseKill3.out b/tests/data/parser/parseKill3.out new file mode 100644 index 000000000..38be2010c --- /dev/null +++ b/tests/data/parser/parseKill3.out @@ -0,0 +1,121 @@ +{ + "query": "KILL QUERY ID 10", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL QUERY ID 10", + "len": 16, + "last": 16, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 4 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "QUERY", + "value": "QUERY", + "keyword": "QUERY", + "type": 1, + "flags": 1, + "position": 5 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 10 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "ID", + "value": "ID", + "keyword": null, + "type": 0, + "flags": 0, + "position": 11 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 13 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "10", + "value": 10, + "keyword": null, + "type": 6, + "flags": 0, + "position": 14 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 8, + "idx": 8 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": 10, + "IDKeywordUsed": true, + "parenthesisUsed": false, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": { + "2": "QUERY" + } + }, + "first": 0, + "last": 7 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKillConnection.out b/tests/data/parser/parseKillConnection.out index 8e45e1d1c..415c2c7f5 100644 --- a/tests/data/parser/parseKillConnection.out +++ b/tests/data/parser/parseKillConnection.out @@ -79,24 +79,17 @@ "statements": [ { "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", - "processListId": { - "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", - "database": null, - "table": null, - "column": null, - "expr": "1", - "alias": null, - "function": null, - "subquery": null - }, + "identifier": 1, + "IDKeywordUsed": false, + "parenthesisUsed": false, "options": { "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", "options": { - "1": "CONNECTION" + "2": "CONNECTION" } }, "first": 0, - "last": 4 + "last": 5 } ], "brackets": 0, diff --git a/tests/data/parser/parseKillErr1.in b/tests/data/parser/parseKillErr1.in new file mode 100644 index 000000000..79fae152d --- /dev/null +++ b/tests/data/parser/parseKillErr1.in @@ -0,0 +1 @@ +KILL CONNECTION QUERY 1 \ No newline at end of file diff --git a/tests/data/parser/parseKillErr1.out b/tests/data/parser/parseKillErr1.out new file mode 100644 index 000000000..ddf1d2a1c --- /dev/null +++ b/tests/data/parser/parseKillErr1.out @@ -0,0 +1,130 @@ +{ + "query": "KILL CONNECTION QUERY 1", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL CONNECTION QUERY 1", + "len": 23, + "last": 23, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 4 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "CONNECTION", + "value": "CONNECTION", + "keyword": "CONNECTION", + "type": 1, + "flags": 1, + "position": 5 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 15 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "QUERY", + "value": "QUERY", + "keyword": "QUERY", + "type": 1, + "flags": 1, + "position": 16 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 21 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "1", + "value": 1, + "keyword": null, + "type": 6, + "flags": 0, + "position": 22 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 8, + "idx": 8 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": 1, + "IDKeywordUsed": false, + "parenthesisUsed": false, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": { + "2": "CONNECTION", + "6": "QUERY" + } + }, + "first": 0, + "last": 7 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [ + [ + "This option conflicts with \"CONNECTION\".", + { + "@type": "@6" + }, + 0 + ] + ] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKillErr2.in b/tests/data/parser/parseKillErr2.in new file mode 100644 index 000000000..4551c2f17 --- /dev/null +++ b/tests/data/parser/parseKillErr2.in @@ -0,0 +1 @@ +KILL \ No newline at end of file diff --git a/tests/data/parser/parseKillErr2.out b/tests/data/parser/parseKillErr2.out new file mode 100644 index 000000000..7aeb1ec2c --- /dev/null +++ b/tests/data/parser/parseKillErr2.out @@ -0,0 +1,80 @@ +{ + "query": "KILL", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL", + "len": 4, + "last": 4, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 2, + "idx": 2 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": null, + "IDKeywordUsed": false, + "parenthesisUsed": false, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 0, + "last": 0 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [ + [ + "Unexpected token.", + { + "@type": "@3" + }, + 0 + ], + [ + "Unexpected end of the KILL statement.", + { + "@type": "@3" + }, + 0 + ] + ] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKillErr3.in b/tests/data/parser/parseKillErr3.in new file mode 100644 index 000000000..f2bdc0e22 --- /dev/null +++ b/tests/data/parser/parseKillErr3.in @@ -0,0 +1 @@ +KILL (SELECT) \ No newline at end of file diff --git a/tests/data/parser/parseKillErr3.out b/tests/data/parser/parseKillErr3.out new file mode 100644 index 000000000..fc03ef100 --- /dev/null +++ b/tests/data/parser/parseKillErr3.out @@ -0,0 +1,109 @@ +{ + "query": "KILL (SELECT)", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL (SELECT)", + "len": 13, + "last": 13, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 4 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "(", + "value": "(", + "keyword": null, + "type": 2, + "flags": 16, + "position": 5 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "SELECT", + "value": "SELECT", + "keyword": "SELECT", + "type": 1, + "flags": 3, + "position": 6 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ")", + "value": ")", + "keyword": null, + "type": 2, + "flags": 16, + "position": 12 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 6, + "idx": 6 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": null, + "IDKeywordUsed": false, + "parenthesisUsed": true, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 0, + "last": 5 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [ + [ + "An expression was expected.", + { + "@type": "@6" + }, + 0 + ] + ] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKillErr4.in b/tests/data/parser/parseKillErr4.in new file mode 100644 index 000000000..6ee8db58d --- /dev/null +++ b/tests/data/parser/parseKillErr4.in @@ -0,0 +1 @@ +KILL (INSERT) \ No newline at end of file diff --git a/tests/data/parser/parseKillErr4.out b/tests/data/parser/parseKillErr4.out new file mode 100644 index 000000000..ba52e332c --- /dev/null +++ b/tests/data/parser/parseKillErr4.out @@ -0,0 +1,140 @@ +{ + "query": "KILL (INSERT)", + "lexer": { + "@type": "PhpMyAdmin\\SqlParser\\Lexer", + "str": "KILL (INSERT)", + "len": 13, + "last": 13, + "list": { + "@type": "PhpMyAdmin\\SqlParser\\TokensList", + "tokens": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "KILL", + "value": "KILL", + "keyword": "KILL", + "type": 1, + "flags": 3, + "position": 0 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": " ", + "value": " ", + "keyword": null, + "type": 3, + "flags": 0, + "position": 4 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "(", + "value": "(", + "keyword": null, + "type": 2, + "flags": 16, + "position": 5 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": "INSERT", + "value": "INSERT", + "keyword": "INSERT", + "type": 1, + "flags": 35, + "position": 6 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": ")", + "value": ")", + "keyword": null, + "type": 2, + "flags": 16, + "position": 12 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Token", + "token": null, + "value": null, + "keyword": null, + "type": 9, + "flags": 0, + "position": null + } + ], + "count": 6, + "idx": 6 + }, + "delimiter": ";", + "delimiterLen": 1, + "strict": false, + "errors": [] + }, + "parser": { + "@type": "PhpMyAdmin\\SqlParser\\Parser", + "list": { + "@type": "@1" + }, + "statements": [ + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", + "identifier": null, + "IDKeywordUsed": false, + "parenthesisUsed": true, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 0, + "last": 2 + }, + { + "@type": "PhpMyAdmin\\SqlParser\\Statements\\InsertStatement", + "into": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\IntoKeyword", + "type": null, + "dest": null, + "columns": null, + "values": null, + "fields_options": null, + "fields_keyword": null, + "lines_options": null + }, + "values": null, + "set": null, + "select": null, + "with": null, + "onDuplicateSet": null, + "options": { + "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", + "options": [] + }, + "first": 3, + "last": 4 + } + ], + "brackets": 0, + "strict": false, + "errors": [] + }, + "errors": { + "lexer": [], + "parser": [ + [ + "Unexpected token.", + { + "@type": "@5" + }, + 0 + ], + [ + "Unexpected end of the KILL statement.", + { + "@type": "@5" + }, + 0 + ] + ] + } +} \ No newline at end of file diff --git a/tests/data/parser/parseKillQuery.out b/tests/data/parser/parseKillQuery.out index 2f95a3536..321c5a090 100644 --- a/tests/data/parser/parseKillQuery.out +++ b/tests/data/parser/parseKillQuery.out @@ -79,24 +79,17 @@ "statements": [ { "@type": "PhpMyAdmin\\SqlParser\\Statements\\KillStatement", - "processListId": { - "@type": "PhpMyAdmin\\SqlParser\\Components\\Expression", - "database": null, - "table": null, - "column": null, - "expr": "1", - "alias": null, - "function": null, - "subquery": null - }, + "identifier": 1, + "IDKeywordUsed": false, + "parenthesisUsed": false, "options": { "@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray", "options": { - "1": "QUERY" + "2": "QUERY" } }, "first": 0, - "last": 4 + "last": 5 } ], "brackets": 0,