Skip to content

Commit 75dbc4e

Browse files
authored
Merge branch 'master' into improvement-skipping-current
2 parents 43eba85 + a6da770 commit 75dbc4e

280 files changed

Lines changed: 11880 additions & 6645 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
* Fixed differentiating between `ANALYZE` and `EXPLAIN` statements (#386)
1414
* Added "NOT" to the select options (#374)
1515
* Implement the `EXPLAIN` Parser (#389)
16-
* Context: Updated contexts to contain `multipoint` and `multipolygon` data types. (#393)
16+
* Context: Updated contexts to contain `multipoint` and `multipolygon` data types (#393)
17+
* Support more keywords on `Expression` component (#399)
1718
* Performance improvement to use less the `nextToken()` function (#397)
1819

1920
## [5.5.0] - 2021-12-08

src/Components/Expression.php

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use function implode;
1515
use function is_array;
16+
use function rtrim;
1617
use function strlen;
1718
use function trim;
1819

@@ -31,19 +32,22 @@ class Expression extends Component
3132
* @var array<string, int>
3233
*/
3334
private static $ALLOWED_KEYWORDS = [
35+
'AND' => 1,
3436
'AS' => 1,
35-
'DUAL' => 1,
36-
'NULL' => 1,
37-
'REGEXP' => 1,
37+
'BETWEEN' => 1,
3838
'CASE' => 1,
39+
'DUAL' => 1,
3940
'DIV' => 1,
40-
'AND' => 1,
41+
'IS' => 1,
42+
'MOD' => 1,
43+
'NOT' => 1,
44+
'NOT NULL' => 1,
45+
'NULL' => 1,
4146
'OR' => 1,
47+
'OVER' => 1,
48+
'REGEXP' => 1,
49+
'RLIKE' => 1,
4250
'XOR' => 1,
43-
'NOT' => 1,
44-
'MOD' => 1,
45-
46-
'OVER' => 2,
4751
];
4852

4953
/**
@@ -371,6 +375,23 @@ public static function parse(Parser $parser, TokensList $list, array $options =
371375

372376
$ret->alias = $prev[1]->value;
373377
} else {
378+
$currIdx = $list->idx;
379+
--$list->idx;
380+
$beforeToken = $list->getPrevious();
381+
$list->idx = $currIdx;
382+
// columns names tokens are of type NONE, or SYMBOL (`col`), and the columns options
383+
// would start with a token of type KEYWORD, in that case, we want to have a space
384+
// between the tokens.
385+
if (
386+
$ret->expr !== null &&
387+
$beforeToken &&
388+
($beforeToken->type === Token::TYPE_NONE ||
389+
$beforeToken->type === Token::TYPE_SYMBOL || $beforeToken->type === Token::TYPE_STRING) &&
390+
$token->type === Token::TYPE_KEYWORD
391+
) {
392+
$ret->expr = rtrim($ret->expr, ' ') . ' ';
393+
}
394+
374395
$ret->expr .= $token->token;
375396
}
376397
} elseif (! $isExpr) {

src/Utils/Formatter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public function __construct(array $options = [])
9292
*
9393
* @return array<string, bool|string|array<int, array<string, int|string>>>
9494
*/
95-
private function getMergedOptions(array $options)
95+
protected function getMergedOptions(array $options)
9696
{
9797
$options = array_merge(
9898
$this->getDefaultOptions(),

tests/Builder/SelectStatementTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,31 @@ public function testBuilder(): void
2222
. 'ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)',
2323
$stmt->build()
2424
);
25+
26+
$parser = new Parser('SELECT NULL IS NULL');
27+
$stmt = $parser->statements[0];
28+
29+
$this->assertEquals('SELECT NULL IS NULL', $stmt->build());
30+
31+
$parser = new Parser('SELECT NOT 1');
32+
$stmt = $parser->statements[0];
33+
34+
$this->assertEquals('SELECT NOT 1', $stmt->build());
35+
36+
$parser = new Parser('SELECT 1 BETWEEN 0 AND 2');
37+
$stmt = $parser->statements[0];
38+
39+
$this->assertEquals('SELECT 1 BETWEEN 0 AND 2', $stmt->build());
40+
41+
$parser = new Parser("SELECT 'a' NOT REGEXP '^[a-d]'");
42+
$stmt = $parser->statements[0];
43+
44+
$this->assertEquals("SELECT 'a' NOT REGEXP '^[a-d]'", $stmt->build());
45+
46+
$parser = new Parser("SELECT 'a' RLIKE 'a'");
47+
$stmt = $parser->statements[0];
48+
49+
$this->assertEquals("SELECT 'a' RLIKE 'a'", $stmt->build());
2550
}
2651

2752
public function testBuilderUnion(): void
@@ -35,6 +60,34 @@ public function testBuilderUnion(): void
3560
);
3661
}
3762

63+
public function testBuilderWithIsNull(): void
64+
{
65+
$parser = new Parser('SELECT `test3`.`t1` is not null AS `is_not_null` FROM `test3` ;');
66+
$stmt = $parser->statements[0];
67+
68+
$this->assertEquals('SELECT `test3`.`t1` is not null AS `is_not_null` FROM `test3`', $stmt->build());
69+
70+
$parser = new Parser('SELECT test3.t1 is null AS `col1` FROM test3');
71+
$stmt = $parser->statements[0];
72+
73+
$this->assertEquals('SELECT test3.t1 is null AS `col1` FROM test3', $stmt->build());
74+
}
75+
76+
public function testBuilderOrderByNull(): void
77+
{
78+
$query = 'SELECT * FROM some_table ORDER BY some_col IS NULL DESC;';
79+
$parser = new Parser($query);
80+
$stmt = $parser->statements[0];
81+
82+
$this->assertEquals('SELECT * FROM some_table ORDER BY some_col IS NULL DESC', $stmt->build());
83+
84+
$query = 'SELECT * FROM some_table ORDER BY some_col IS NOT NULL;';
85+
$parser = new Parser($query);
86+
$stmt = $parser->statements[0];
87+
88+
$this->assertEquals('SELECT * FROM some_table ORDER BY some_col IS NOT NULL ASC', $stmt->build());
89+
}
90+
3891
public function testBuilderAlias(): void
3992
{
4093
$parser = new Parser(

tests/Parser/CreateStatementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public function createProvider(): array
6060
['parser/parseCreateView2'],
6161
['parser/parseCreateView3'],
6262
['parser/parseCreateView4'],
63+
['parser/parseCreateView5'],
6364
['parser/parseCreateViewMultiple'],
6465
['parser/parseCreateViewWithoutQuotes'],
6566
['parser/parseCreateViewWithQuotes'],

tests/Parser/SelectStatementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public function selectProvider(): array
8989
['parser/parseSelectWhere'],
9090
['parser/parseSelectIndexHint1'],
9191
['parser/parseSelectIndexHint2'],
92+
['parser/parseSelectOrderByIsNull'],
9293
['parser/parseSelectIndexHintErr1'],
9394
['parser/parseSelectIndexHintErr2'],
9495
['parser/parseSelectIndexHintErr3'],

tests/data/bugs/gh14.out

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -599,18 +599,22 @@
599599
"table": {
600600
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
601601
"ALLOWED_KEYWORDS": {
602+
"AND": 1,
602603
"AS": 1,
603-
"DUAL": 1,
604-
"NULL": 1,
605-
"REGEXP": 1,
604+
"BETWEEN": 1,
606605
"CASE": 1,
606+
"DUAL": 1,
607607
"DIV": 1,
608-
"AND": 1,
609-
"OR": 1,
610-
"XOR": 1,
611-
"NOT": 1,
608+
"IS": 1,
612609
"MOD": 1,
613-
"OVER": 2
610+
"NOT": 1,
611+
"NOT NULL": 1,
612+
"NULL": 1,
613+
"OR": 1,
614+
"OVER": 1,
615+
"REGEXP": 1,
616+
"RLIKE": 1,
617+
"XOR": 1
614618
},
615619
"database": null,
616620
"table": "actor",
@@ -762,18 +766,22 @@
762766
"field": {
763767
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
764768
"ALLOWED_KEYWORDS": {
769+
"AND": 1,
765770
"AS": 1,
766-
"DUAL": 1,
767-
"NULL": 1,
768-
"REGEXP": 1,
771+
"BETWEEN": 1,
769772
"CASE": 1,
773+
"DUAL": 1,
770774
"DIV": 1,
771-
"AND": 1,
772-
"OR": 1,
773-
"XOR": 1,
774-
"NOT": 1,
775+
"IS": 1,
775776
"MOD": 1,
776-
"OVER": 2
777+
"NOT": 1,
778+
"NOT NULL": 1,
779+
"NULL": 1,
780+
"OR": 1,
781+
"OVER": 1,
782+
"REGEXP": 1,
783+
"RLIKE": 1,
784+
"XOR": 1
777785
},
778786
"database": null,
779787
"table": null,

0 commit comments

Comments
 (0)