Skip to content

Commit 0b16f44

Browse files
committed
Implement missing "EXCEPT" and "INTERSECT" operators in the grammar
1 parent ed15ffa commit 0b16f44

File tree

6 files changed

+118
-200
lines changed

6 files changed

+118
-200
lines changed

custom-parser/grammar-factoring/MySQLParser-factored-versioned.json

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7218,49 +7218,104 @@
72187218
"name": "queryExpressionBody",
72197219
"bnf": [
72207220
[
7221-
"%queryExpressionBody00",
7221+
"queryTerm",
72227222
"%queryExpressionBody01_zero_or_more"
72237223
]
72247224
]
72257225
},
72267226
{
7227-
"name": "%queryExpressionBody0013",
7227+
"versions": "serverVersion >= 80031",
7228+
"name": "%queryExpressionBody010010",
72287229
"bnf": [
72297230
[
7230-
"queryPrimary"
7231+
"EXCEPT_SYMBOL"
7232+
]
7233+
]
7234+
},
7235+
{
7236+
"name": "%queryExpressionBody0100",
7237+
"bnf": [
7238+
[
7239+
"UNION_SYMBOL"
72317240
],
72327241
[
7233-
"queryExpressionParens"
7242+
"%queryExpressionBody010010"
7243+
]
7244+
]
7245+
},
7246+
{
7247+
"name": "setOperationOption_zero_or_one",
7248+
"bnf": [
7249+
[
7250+
"setOperationOption"
7251+
],
7252+
[
7253+
"\u03b5"
7254+
]
7255+
]
7256+
},
7257+
{
7258+
"name": "%queryExpressionBody01_zero_or_more",
7259+
"bnf": [
7260+
[
7261+
"%queryExpressionBody01",
7262+
"%queryExpressionBody01_zero_or_more"
7263+
],
7264+
[
7265+
"%queryExpressionBody01"
7266+
],
7267+
[
7268+
"\u03b5"
7269+
]
7270+
]
7271+
},
7272+
{
7273+
"name": "%queryExpressionBody01",
7274+
"bnf": [
7275+
[
7276+
"%queryExpressionBody0100",
7277+
"setOperationOption_zero_or_one",
7278+
"queryTerm"
72347279
]
72357280
]
72367281
},
72377282
{
7238-
"name": "unionOption_zero_or_one",
7283+
"name": "%queryTerm01_zero_or_more",
72397284
"bnf": [
72407285
[
7241-
"unionOption"
7286+
"%queryTerm01",
7287+
"%queryTerm01_zero_or_more"
7288+
],
7289+
[
7290+
"%queryTerm01"
72427291
],
72437292
[
72447293
"\u03b5"
72457294
]
72467295
]
72477296
},
72487297
{
7249-
"name": "%queryExpressionBody00",
7298+
"name": "queryTerm",
7299+
"bnf": [
7300+
[
7301+
"%queryTerm00",
7302+
"%queryTerm01_zero_or_more"
7303+
]
7304+
]
7305+
},
7306+
{
7307+
"name": "%queryTerm00",
72507308
"bnf": [
72517309
[
72527310
"queryPrimary"
72537311
],
72547312
[
7255-
"queryExpressionParens",
7256-
"UNION_SYMBOL",
7257-
"unionOption_zero_or_one",
7258-
"%queryExpressionBody0013"
7313+
"queryExpressionParens"
72597314
]
72607315
]
72617316
},
72627317
{
7263-
"name": "%queryExpressionBody0102",
7318+
"name": "%queryTerm01002",
72647319
"bnf": [
72657320
[
72667321
"queryPrimary"
@@ -7271,38 +7326,47 @@
72717326
]
72727327
},
72737328
{
7274-
"name": "unionOption_zero_or_one",
7329+
"name": "setOperationOption_zero_or_one",
72757330
"bnf": [
72767331
[
7277-
"unionOption"
7332+
"setOperationOption"
72787333
],
72797334
[
72807335
"\u03b5"
72817336
]
72827337
]
72837338
},
72847339
{
7285-
"name": "%queryExpressionBody01_zero_or_more",
7340+
"versions": "serverVersion >= 80031",
7341+
"name": "%queryTerm0100",
72867342
"bnf": [
72877343
[
7288-
"%queryExpressionBody01",
7289-
"%queryExpressionBody01_zero_or_more"
7344+
"INTERSECT_SYMBOL",
7345+
"setOperationOption_zero_or_one",
7346+
"%queryTerm01002"
7347+
]
7348+
]
7349+
},
7350+
{
7351+
"name": "%queryTerm01_zero_or_more",
7352+
"bnf": [
7353+
[
7354+
"%queryTerm01",
7355+
"%queryTerm01_zero_or_more"
72907356
],
72917357
[
7292-
"%queryExpressionBody01"
7358+
"%queryTerm01"
72937359
],
72947360
[
72957361
"\u03b5"
72967362
]
72977363
]
72987364
},
72997365
{
7300-
"name": "%queryExpressionBody01",
7366+
"name": "%queryTerm01",
73017367
"bnf": [
73027368
[
7303-
"UNION_SYMBOL",
7304-
"unionOption_zero_or_one",
7305-
"%queryExpressionBody0102"
7369+
"%queryTerm0100"
73067370
]
73077371
]
73087372
},
@@ -9568,7 +9632,7 @@
95689632
]
95699633
},
95709634
{
9571-
"name": "unionOption",
9635+
"name": "setOperationOption",
95729636
"bnf": [
95739637
[
95749638
"DISTINCT_SYMBOL"

custom-parser/grammar-factoring/MySQLParser.g4

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,14 +1086,29 @@ queryExpression:
10861086
) ({serverVersion < 80000}? procedureAnalyseClause)?
10871087
;
10881088

1089-
queryExpressionBody:
1089+
/*queryExpressionBody:
10901090
(
10911091
queryPrimary
10921092
| queryExpressionParens UNION_SYMBOL unionOption? (
10931093
queryPrimary
10941094
| queryExpressionParens
10951095
)
10961096
) (UNION_SYMBOL unionOption? ( queryPrimary | queryExpressionParens))*
1097+
;*/
1098+
1099+
/*
1100+
* @FIX:
1101+
* Implement missing "EXCEPT" and "INTERSECT" operators in the grammar.
1102+
* Note that "INTERSECT" must have a higher precedence than "UNION" and "EXCEPT",
1103+
* and is therefore evaluated first via "queryTerm" as per:
1104+
* https://dev.mysql.com/doc/refman/8.0/en/set-operations.html
1105+
*/
1106+
queryExpressionBody:
1107+
queryTerm ((UNION_SYMBOL | {serverVersion >= 80031}? EXCEPT_SYMBOL) setOperationOption? queryTerm)*
1108+
;
1109+
1110+
queryTerm:
1111+
(queryPrimary | queryExpressionParens) ({serverVersion >= 80031}? INTERSECT_SYMBOL setOperationOption? (queryPrimary | queryExpressionParens))*
10971112
;
10981113

10991114
queryExpressionParens:
@@ -1444,7 +1459,16 @@ jtOnResponse:
14441459
| DEFAULT_SYMBOL textStringLiteral
14451460
;
14461461

1447-
unionOption:
1462+
/*unionOption:
1463+
DISTINCT_SYMBOL
1464+
| ALL_SYMBOL
1465+
;*/
1466+
1467+
/*
1468+
* @FIX:
1469+
* Renamed "unionOption" to "setOperationOption" as this is now used also for EXCEPT and INTERSECT.
1470+
*/
1471+
setOperationOption:
14481472
DISTINCT_SYMBOL
14491473
| ALL_SYMBOL
14501474
;

custom-parser/parser/MySQLLexer.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,7 @@ class MySQLLexer {
890890
const SQL_TSI_SECOND_SYMBOL = 808;
891891
const SQL_TSI_WEEK_SYMBOL = 809;
892892
const SQL_TSI_YEAR_SYMBOL = 810;
893+
const INTERSECT_SYMBOL = 811; // missing in MySQLLexer.g4
893894

894895
// Special tokens
895896
const EOF = -1;
@@ -1597,6 +1598,7 @@ class MySQLLexer {
15971598
'HISTOGRAM' => self::HISTOGRAM_SYMBOL,
15981599
'HISTORY' => self::HISTORY_SYMBOL,
15991600
'INACTIVE' => self::INACTIVE_SYMBOL,
1601+
'INTERSECT' => self::INTERSECT_SYMBOL,
16001602
'INVISIBLE' => self::INVISIBLE_SYMBOL,
16011603
'JSON_ARRAYAGG' => self::JSON_ARRAYAGG_SYMBOL,
16021604
'JSON_OBJECTAGG' => self::JSON_OBJECTAGG_SYMBOL,
@@ -1840,6 +1842,7 @@ class MySQLLexer {
18401842
self::HISTOGRAM_SYMBOL => 80000,
18411843
self::HISTORY_SYMBOL => 80000,
18421844
self::INACTIVE_SYMBOL => 80014,
1845+
self::INTERSECT_SYMBOL => 80031,
18431846
self::INVISIBLE_SYMBOL => 80000,
18441847
self::JSON_ARRAYAGG_SYMBOL => 80000,
18451848
self::JSON_OBJECTAGG_SYMBOL => 80000,

custom-parser/parser/grammar.php

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)