Skip to content

Commit 274fc3a

Browse files
committed
Merge #485 - Fix #478, Fix #234 - ALTER TABLE … MODIFY … ENUM('<reserved_keyword>') is being wrongly parsed
Pull-request: #485 Fixes: #478 Fixes: #234 Signed-off-by: William Desportes <[email protected]>
2 parents 5b4b5e2 + 9838a1c commit 274fc3a

10 files changed

+848
-19
lines changed

src/Components/AlterOperation.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -427,25 +427,32 @@ public static function parse(Parser $parser, TokensList $list, array $options =
427427
break;
428428
}
429429
} elseif (! self::checkIfTokenQuotedSymbol($token)) {
430-
if (! empty(Parser::$STATEMENT_PARSERS[$token->value])) {
430+
// If the current token is "SET" or "ENUM", we want to avoid the token between their parenthesis in
431+
// the unknown tokens.
432+
if (in_array($token->value, ['SET', 'ENUM'], true)) {
431433
$list->idx++; // Ignore the current token
432434
$nextToken = $list->getNext();
433435

434-
if ($token->value === 'SET' && $nextToken !== null && $nextToken->value === '(') {
435-
// To avoid adding the tokens between the SET() parentheses to the unknown tokens
436+
if ($nextToken !== null && $nextToken->value === '(') {
436437
$list->getNextOfTypeAndValue(Token::TYPE_OPERATOR, ')');
437-
} elseif ($token->value === 'SET' && $nextToken !== null && $nextToken->value === 'DEFAULT') {
438+
} elseif ($nextToken !== null && $nextToken->value === 'DEFAULT') {
438439
// to avoid adding the `DEFAULT` token to the unknown tokens.
439440
++$list->idx;
440441
} else {
441-
// We have reached the end of ALTER operation and suddenly found
442-
// a start to new statement, but have not find a delimiter between them
443442
$parser->error(
444443
'A new statement was found, but no delimiter between it and the previous one.',
445444
$token
446445
);
447446
break;
448447
}
448+
} elseif (! empty(Parser::$statementParsers[$token->value])) {
449+
// We have reached the end of ALTER operation and suddenly found
450+
// a start to new statement, but have not found a delimiter between them
451+
$parser->error(
452+
'A new statement was found, but no delimiter between it and the previous one.',
453+
$token
454+
);
455+
break;
449456
} elseif (
450457
(array_key_exists($arrayKey, self::$DB_OPTIONS)
451458
|| array_key_exists($arrayKey, self::$TABLE_OPTIONS))

tests/Parser/AlterStatementTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ public function alterProvider(): array
4949
['parser/parseAlterTableDropAddIndex1'],
5050
['parser/parseAlterTableDropColumn1'],
5151
['parser/parseAlterTableModifyColumn'],
52+
['parser/parseAlterTableModifyColumnEnum1'],
53+
['parser/parseAlterTableModifyColumnEnum2'],
54+
['parser/parseAlterTableModifyColumnEnum3'],
5255
['parser/parseAlterWithInvisible'],
5356
['parser/parseAlterTableCharacterSet1'],
5457
['parser/parseAlterTableCharacterSet2'],

tests/data/parser/parseAlter3.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@
554554
"lexer": [],
555555
"parser": [
556556
[
557-
"A new statement was found, but no delimiter between it and the previous one.",
557+
"Missing comma before start of a new alter operation.",
558558
{
559559
"@type": "@27"
560560
},

tests/data/parser/parseAlter9.out

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,6 @@
336336
{
337337
"@type": "@16"
338338
},
339-
{
340-
"@type": "@17"
341-
},
342-
{
343-
"@type": "@18"
344-
},
345-
{
346-
"@type": "@19"
347-
},
348-
{
349-
"@type": "@20"
350-
},
351339
{
352340
"@type": "@21"
353341
},
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- ENUM with a string that is a database option.
2+
ALTER TABLE `test_table` MODIFY `COL` ENUM("COLLATE") NULL;
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
{
2+
"query": "-- ENUM with a string that is a database option.\nALTER TABLE `test_table` MODIFY `COL` ENUM(\"COLLATE\") NULL;\n",
3+
"lexer": {
4+
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
5+
"str": "-- ENUM with a string that is a database option.\nALTER TABLE `test_table` MODIFY `COL` ENUM(\"COLLATE\") NULL;\n",
6+
"len": 109,
7+
"last": 109,
8+
"list": {
9+
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
10+
"tokens": [
11+
{
12+
"@type": "PhpMyAdmin\\SqlParser\\Token",
13+
"token": "-- ENUM with a string that is a database option.",
14+
"value": "-- ENUM with a string that is a database option.",
15+
"keyword": null,
16+
"type": 4,
17+
"flags": 4,
18+
"position": 0
19+
},
20+
{
21+
"@type": "PhpMyAdmin\\SqlParser\\Token",
22+
"token": "\n",
23+
"value": " ",
24+
"keyword": null,
25+
"type": 3,
26+
"flags": 0,
27+
"position": 48
28+
},
29+
{
30+
"@type": "PhpMyAdmin\\SqlParser\\Token",
31+
"token": "ALTER",
32+
"value": "ALTER",
33+
"keyword": "ALTER",
34+
"type": 1,
35+
"flags": 3,
36+
"position": 49
37+
},
38+
{
39+
"@type": "PhpMyAdmin\\SqlParser\\Token",
40+
"token": " ",
41+
"value": " ",
42+
"keyword": null,
43+
"type": 3,
44+
"flags": 0,
45+
"position": 54
46+
},
47+
{
48+
"@type": "PhpMyAdmin\\SqlParser\\Token",
49+
"token": "TABLE",
50+
"value": "TABLE",
51+
"keyword": "TABLE",
52+
"type": 1,
53+
"flags": 3,
54+
"position": 55
55+
},
56+
{
57+
"@type": "PhpMyAdmin\\SqlParser\\Token",
58+
"token": " ",
59+
"value": " ",
60+
"keyword": null,
61+
"type": 3,
62+
"flags": 0,
63+
"position": 60
64+
},
65+
{
66+
"@type": "PhpMyAdmin\\SqlParser\\Token",
67+
"token": "`test_table`",
68+
"value": "test_table",
69+
"keyword": null,
70+
"type": 8,
71+
"flags": 2,
72+
"position": 61
73+
},
74+
{
75+
"@type": "PhpMyAdmin\\SqlParser\\Token",
76+
"token": " ",
77+
"value": " ",
78+
"keyword": null,
79+
"type": 3,
80+
"flags": 0,
81+
"position": 73
82+
},
83+
{
84+
"@type": "PhpMyAdmin\\SqlParser\\Token",
85+
"token": "MODIFY",
86+
"value": "MODIFY",
87+
"keyword": "MODIFY",
88+
"type": 1,
89+
"flags": 1,
90+
"position": 74
91+
},
92+
{
93+
"@type": "PhpMyAdmin\\SqlParser\\Token",
94+
"token": " ",
95+
"value": " ",
96+
"keyword": null,
97+
"type": 3,
98+
"flags": 0,
99+
"position": 80
100+
},
101+
{
102+
"@type": "PhpMyAdmin\\SqlParser\\Token",
103+
"token": "`COL`",
104+
"value": "COL",
105+
"keyword": null,
106+
"type": 8,
107+
"flags": 2,
108+
"position": 81
109+
},
110+
{
111+
"@type": "PhpMyAdmin\\SqlParser\\Token",
112+
"token": " ",
113+
"value": " ",
114+
"keyword": null,
115+
"type": 3,
116+
"flags": 0,
117+
"position": 86
118+
},
119+
{
120+
"@type": "PhpMyAdmin\\SqlParser\\Token",
121+
"token": "ENUM",
122+
"value": "ENUM",
123+
"keyword": "ENUM",
124+
"type": 1,
125+
"flags": 9,
126+
"position": 87
127+
},
128+
{
129+
"@type": "PhpMyAdmin\\SqlParser\\Token",
130+
"token": "(",
131+
"value": "(",
132+
"keyword": null,
133+
"type": 2,
134+
"flags": 16,
135+
"position": 91
136+
},
137+
{
138+
"@type": "PhpMyAdmin\\SqlParser\\Token",
139+
"token": "\"COLLATE\"",
140+
"value": "COLLATE",
141+
"keyword": null,
142+
"type": 7,
143+
"flags": 2,
144+
"position": 92
145+
},
146+
{
147+
"@type": "PhpMyAdmin\\SqlParser\\Token",
148+
"token": ")",
149+
"value": ")",
150+
"keyword": null,
151+
"type": 2,
152+
"flags": 16,
153+
"position": 101
154+
},
155+
{
156+
"@type": "PhpMyAdmin\\SqlParser\\Token",
157+
"token": " ",
158+
"value": " ",
159+
"keyword": null,
160+
"type": 3,
161+
"flags": 0,
162+
"position": 102
163+
},
164+
{
165+
"@type": "PhpMyAdmin\\SqlParser\\Token",
166+
"token": "NULL",
167+
"value": "NULL",
168+
"keyword": "NULL",
169+
"type": 1,
170+
"flags": 3,
171+
"position": 103
172+
},
173+
{
174+
"@type": "PhpMyAdmin\\SqlParser\\Token",
175+
"token": ";",
176+
"value": ";",
177+
"keyword": null,
178+
"type": 9,
179+
"flags": 0,
180+
"position": 107
181+
},
182+
{
183+
"@type": "PhpMyAdmin\\SqlParser\\Token",
184+
"token": "\n",
185+
"value": " ",
186+
"keyword": null,
187+
"type": 3,
188+
"flags": 0,
189+
"position": 108
190+
},
191+
{
192+
"@type": "PhpMyAdmin\\SqlParser\\Token",
193+
"token": null,
194+
"value": null,
195+
"keyword": null,
196+
"type": 9,
197+
"flags": 0,
198+
"position": null
199+
}
200+
],
201+
"count": 21,
202+
"idx": 21
203+
},
204+
"delimiter": ";",
205+
"delimiterLen": 1,
206+
"strict": false,
207+
"errors": []
208+
},
209+
"parser": {
210+
"@type": "PhpMyAdmin\\SqlParser\\Parser",
211+
"list": {
212+
"@type": "@1"
213+
},
214+
"statements": [
215+
{
216+
"@type": "PhpMyAdmin\\SqlParser\\Statements\\AlterStatement",
217+
"table": {
218+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
219+
"database": null,
220+
"table": "test_table",
221+
"column": null,
222+
"expr": "`test_table`",
223+
"alias": null,
224+
"function": null,
225+
"subquery": null
226+
},
227+
"altered": [
228+
{
229+
"@type": "PhpMyAdmin\\SqlParser\\Components\\AlterOperation",
230+
"options": {
231+
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
232+
"options": {
233+
"1": "MODIFY"
234+
}
235+
},
236+
"field": {
237+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
238+
"database": null,
239+
"table": null,
240+
"column": "COL",
241+
"expr": "`COL`",
242+
"alias": null,
243+
"function": null,
244+
"subquery": null
245+
},
246+
"partitions": null,
247+
"unknown": [
248+
{
249+
"@type": "@14"
250+
},
251+
{
252+
"@type": "@19"
253+
}
254+
]
255+
}
256+
],
257+
"options": {
258+
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
259+
"options": {
260+
"3": "TABLE"
261+
}
262+
},
263+
"first": 0,
264+
"last": 18
265+
}
266+
],
267+
"brackets": 0,
268+
"strict": false,
269+
"errors": []
270+
},
271+
"errors": {
272+
"lexer": [],
273+
"parser": []
274+
}
275+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- ENUM with a string that is a table option.
2+
ALTER TABLE `test_table` MODIFY `COL` ENUM("LOCK") NULL;

0 commit comments

Comments
 (0)