Skip to content

Commit 8399efa

Browse files
committed
Merge #432 - Fix #430 - ALTER TABLE … RENAME COLUMN … TO … is not understood by the parser/linter
Pull-request: #432 Fixes: #430 Signed-off-by: William Desportes <williamdes@wdes.fr>
2 parents 1ac927f + 8b30047 commit 8399efa

File tree

7 files changed

+944
-2
lines changed

7 files changed

+944
-2
lines changed

src/Components/AlterOperation.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use function in_array;
1414
use function is_numeric;
1515
use function is_string;
16+
use function trim;
1617

1718
/**
1819
* Parses an alter operation.
@@ -381,6 +382,13 @@ public static function parse(Parser $parser, TokensList $list, array $options =
381382
--$list->idx;
382383
}
383384

385+
// If the operation is a RENAME COLUMN, now we have detected the field to rename, we need to parse
386+
// again the options to get the new name of the column.
387+
if ($ret->options->has('RENAME') && $ret->options->has('COLUMN')) {
388+
$nextOptions = OptionsArray::parse($parser, $list, $options);
389+
$ret->options->merge($nextOptions);
390+
}
391+
384392
$state = 2;
385393
} elseif ($state === 2) {
386394
if (is_string($token->value) || is_numeric($token->value)) {
@@ -485,18 +493,27 @@ public static function parse(Parser $parser, TokensList $list, array $options =
485493
*/
486494
public static function build($component, array $options = [])
487495
{
496+
// Specific case of RENAME COLUMN that insert the field between 2 options.
497+
$afterFieldsOptions = new OptionsArray();
498+
if ($component->options->has('RENAME') && $component->options->has('COLUMN')) {
499+
$afterFieldsOptions = clone $component->options;
500+
$afterFieldsOptions->remove('RENAME');
501+
$afterFieldsOptions->remove('COLUMN');
502+
$component->options->remove('TO');
503+
}
504+
488505
$ret = $component->options . ' ';
489506
if (isset($component->field) && ($component->field !== '')) {
490507
$ret .= $component->field . ' ';
491508
}
492509

493-
$ret .= TokensList::build($component->unknown);
510+
$ret .= $afterFieldsOptions . TokensList::build($component->unknown);
494511

495512
if (isset($component->partitions)) {
496513
$ret .= PartitionDefinition::build($component->partitions);
497514
}
498515

499-
return $ret;
516+
return trim($ret);
500517
}
501518

502519
/**

tests/Builder/AlterStatementTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace PhpMyAdmin\SqlParser\Tests\Builder;
66

7+
use Generator;
78
use PhpMyAdmin\SqlParser\Parser;
89
use PhpMyAdmin\SqlParser\Tests\TestCase;
910

@@ -113,4 +114,44 @@ public function testBuilderEventWithDefiner(): void
113114
$stmt = $parser->statements[0];
114115
$this->assertEquals($query, $stmt->build());
115116
}
117+
118+
/**
119+
* @return Generator<string, array{string}>
120+
*/
121+
public static function provideBuilderForRenameColumn(): Generator
122+
{
123+
$query = 'ALTER TABLE myTable RENAME COLUMN a TO b';
124+
125+
yield 'Single RENAME COLUMN' => [$query];
126+
127+
$query = 'ALTER TABLE myTable RENAME COLUMN a TO b, RENAME COLUMN b TO a';
128+
129+
yield 'Multiple RENAME COLUMN' => [$query];
130+
131+
$query = 'ALTER TABLE myTable ' .
132+
'RENAME COLUMN a TO b, ' .
133+
'RENAME COLUMN b TO a, ' .
134+
'RENAME INDEX oldIndex TO newIndex, ' .
135+
'RENAME TO newTable';
136+
137+
yield 'Mixed RENAME COLUMN + RENAME INDEX + RENAME table' => [$query];
138+
139+
$query = 'ALTER TABLE myTable ' .
140+
'RENAME TO newTable, ' .
141+
'RENAME INDEX oldIndex TO newIndex, ' .
142+
'RENAME COLUMN b TO a, ' .
143+
'RENAME COLUMN a TO b';
144+
145+
yield 'Mixed RENAME table + RENAME INDEX + RENAME COLUMNS' => [$query];
146+
}
147+
148+
/**
149+
* @dataProvider provideBuilderForRenameColumn
150+
*/
151+
public function testBuilderRenameColumn(string $query): void
152+
{
153+
$parser = new Parser($query);
154+
$stmt = $parser->statements[0];
155+
$this->assertEquals($query, $stmt->build());
156+
}
116157
}

tests/Parser/AlterStatementTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public function alterProvider(): array
7979
['parser/parseAlterEventOnScheduleEvery6'],
8080
['parser/parseAlterEventWithDefiner'],
8181
['parser/parseAlterEventWithOtherDefiners'],
82+
['parser/parseAlterRenameColumn'],
83+
['parser/parseAlterRenameColumns'],
8284
];
8385
}
8486
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE myTable RENAME COLUMN foo TO bar;
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
{
2+
"query": "ALTER TABLE myTable RENAME COLUMN foo TO bar;\n",
3+
"lexer": {
4+
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
5+
"str": "ALTER TABLE myTable RENAME COLUMN foo TO bar;\n",
6+
"len": 46,
7+
"last": 46,
8+
"list": {
9+
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
10+
"tokens": [
11+
{
12+
"@type": "PhpMyAdmin\\SqlParser\\Token",
13+
"token": "ALTER",
14+
"value": "ALTER",
15+
"keyword": "ALTER",
16+
"type": 1,
17+
"flags": 3,
18+
"position": 0
19+
},
20+
{
21+
"@type": "PhpMyAdmin\\SqlParser\\Token",
22+
"token": " ",
23+
"value": " ",
24+
"keyword": null,
25+
"type": 3,
26+
"flags": 0,
27+
"position": 5
28+
},
29+
{
30+
"@type": "PhpMyAdmin\\SqlParser\\Token",
31+
"token": "TABLE",
32+
"value": "TABLE",
33+
"keyword": "TABLE",
34+
"type": 1,
35+
"flags": 3,
36+
"position": 6
37+
},
38+
{
39+
"@type": "PhpMyAdmin\\SqlParser\\Token",
40+
"token": " ",
41+
"value": " ",
42+
"keyword": null,
43+
"type": 3,
44+
"flags": 0,
45+
"position": 11
46+
},
47+
{
48+
"@type": "PhpMyAdmin\\SqlParser\\Token",
49+
"token": "myTable",
50+
"value": "myTable",
51+
"keyword": null,
52+
"type": 0,
53+
"flags": 0,
54+
"position": 12
55+
},
56+
{
57+
"@type": "PhpMyAdmin\\SqlParser\\Token",
58+
"token": " ",
59+
"value": " ",
60+
"keyword": null,
61+
"type": 3,
62+
"flags": 0,
63+
"position": 19
64+
},
65+
{
66+
"@type": "PhpMyAdmin\\SqlParser\\Token",
67+
"token": "RENAME",
68+
"value": "RENAME",
69+
"keyword": "RENAME",
70+
"type": 1,
71+
"flags": 3,
72+
"position": 20
73+
},
74+
{
75+
"@type": "PhpMyAdmin\\SqlParser\\Token",
76+
"token": " ",
77+
"value": " ",
78+
"keyword": null,
79+
"type": 3,
80+
"flags": 0,
81+
"position": 26
82+
},
83+
{
84+
"@type": "PhpMyAdmin\\SqlParser\\Token",
85+
"token": "COLUMN",
86+
"value": "COLUMN",
87+
"keyword": "COLUMN",
88+
"type": 1,
89+
"flags": 3,
90+
"position": 27
91+
},
92+
{
93+
"@type": "PhpMyAdmin\\SqlParser\\Token",
94+
"token": " ",
95+
"value": " ",
96+
"keyword": null,
97+
"type": 3,
98+
"flags": 0,
99+
"position": 33
100+
},
101+
{
102+
"@type": "PhpMyAdmin\\SqlParser\\Token",
103+
"token": "foo",
104+
"value": "foo",
105+
"keyword": null,
106+
"type": 0,
107+
"flags": 0,
108+
"position": 34
109+
},
110+
{
111+
"@type": "PhpMyAdmin\\SqlParser\\Token",
112+
"token": " ",
113+
"value": " ",
114+
"keyword": null,
115+
"type": 3,
116+
"flags": 0,
117+
"position": 37
118+
},
119+
{
120+
"@type": "PhpMyAdmin\\SqlParser\\Token",
121+
"token": "TO",
122+
"value": "TO",
123+
"keyword": "TO",
124+
"type": 1,
125+
"flags": 3,
126+
"position": 38
127+
},
128+
{
129+
"@type": "PhpMyAdmin\\SqlParser\\Token",
130+
"token": " ",
131+
"value": " ",
132+
"keyword": null,
133+
"type": 3,
134+
"flags": 0,
135+
"position": 40
136+
},
137+
{
138+
"@type": "PhpMyAdmin\\SqlParser\\Token",
139+
"token": "bar",
140+
"value": "bar",
141+
"keyword": null,
142+
"type": 0,
143+
"flags": 0,
144+
"position": 41
145+
},
146+
{
147+
"@type": "PhpMyAdmin\\SqlParser\\Token",
148+
"token": ";",
149+
"value": ";",
150+
"keyword": null,
151+
"type": 9,
152+
"flags": 0,
153+
"position": 44
154+
},
155+
{
156+
"@type": "PhpMyAdmin\\SqlParser\\Token",
157+
"token": "\n",
158+
"value": " ",
159+
"keyword": null,
160+
"type": 3,
161+
"flags": 0,
162+
"position": 45
163+
},
164+
{
165+
"@type": "PhpMyAdmin\\SqlParser\\Token",
166+
"token": null,
167+
"value": null,
168+
"keyword": null,
169+
"type": 9,
170+
"flags": 0,
171+
"position": null
172+
}
173+
],
174+
"count": 18,
175+
"idx": 18
176+
},
177+
"delimiter": ";",
178+
"delimiterLen": 1,
179+
"strict": false,
180+
"errors": []
181+
},
182+
"parser": {
183+
"@type": "PhpMyAdmin\\SqlParser\\Parser",
184+
"list": {
185+
"@type": "@1"
186+
},
187+
"statements": [
188+
{
189+
"@type": "PhpMyAdmin\\SqlParser\\Statements\\AlterStatement",
190+
"table": {
191+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
192+
"database": null,
193+
"table": "myTable",
194+
"column": null,
195+
"expr": "myTable",
196+
"alias": null,
197+
"function": null,
198+
"subquery": null
199+
},
200+
"altered": [
201+
{
202+
"@type": "PhpMyAdmin\\SqlParser\\Components\\AlterOperation",
203+
"options": {
204+
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
205+
"options": [
206+
"RENAME",
207+
"COLUMN",
208+
{
209+
"name": "TO",
210+
"equals": false,
211+
"expr": "bar",
212+
"value": "bar"
213+
}
214+
]
215+
},
216+
"field": {
217+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
218+
"database": null,
219+
"table": null,
220+
"column": "foo",
221+
"expr": "foo",
222+
"alias": null,
223+
"function": null,
224+
"subquery": null
225+
},
226+
"partitions": null,
227+
"unknown": []
228+
}
229+
],
230+
"options": {
231+
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
232+
"options": {
233+
"3": "TABLE"
234+
}
235+
},
236+
"first": 0,
237+
"last": 15
238+
}
239+
],
240+
"brackets": 0,
241+
"strict": false,
242+
"errors": []
243+
},
244+
"errors": {
245+
"lexer": [],
246+
"parser": []
247+
}
248+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ALTER TABLE myTable RENAME COLUMN a TO b,
2+
RENAME COLUMN b TO c,
3+
RENAME COLUMN c TO d,
4+
RENAME COLUMN d TO a;

0 commit comments

Comments
 (0)