Skip to content

Commit e9debaf

Browse files
authored
Fix #434 - No error when using UPDATE ... SET (#577)
* Preparing tests about missing assignment in SET operation. * Fix empty SET operations now throw error. * Move the check about missing assignment in SET operation to focus UPDATE statements only. * Improve PHPDoc. * Fix linint issue with PHPDoc. * Fix linint issue with PHPDoc. Fixes #434 Closes #577
1 parent 99b9f38 commit e9debaf

File tree

5 files changed

+218
-0
lines changed

5 files changed

+218
-0
lines changed

src/Statements/UpdateStatement.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010
use PhpMyAdmin\SqlParser\Components\Limit;
1111
use PhpMyAdmin\SqlParser\Components\OrderKeyword;
1212
use PhpMyAdmin\SqlParser\Components\SetOperation;
13+
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
14+
use PhpMyAdmin\SqlParser\Parser;
1315
use PhpMyAdmin\SqlParser\Statement;
16+
use PhpMyAdmin\SqlParser\Token;
17+
use PhpMyAdmin\SqlParser\TokensList;
1418

1519
/**
1620
* `UPDATE` statement.
@@ -135,4 +139,25 @@ class UpdateStatement extends Statement
135139
* @var JoinKeyword[]|null
136140
*/
137141
public $join;
142+
143+
/**
144+
* Function called after the token was processed.
145+
* In the update statement, this is used to check that at least one assignment has been set to throw an error if a
146+
* query like `UPDATE acme SET WHERE 1;` is parsed.
147+
*
148+
* @return void
149+
*
150+
* @throws ParserException throws the exception, if strict mode is enabled.
151+
*/
152+
public function after(Parser $parser, TokensList $list, Token $token)
153+
{
154+
/** @psalm-var string $tokenValue */
155+
$tokenValue = $token->value;
156+
// Ensure we finished to parse the "SET" token, and if yes, ensure that assignments are defined.
157+
if ($this->set !== [] || (Parser::$KEYWORD_PARSERS[$tokenValue]['field'] ?? null) !== 'set') {
158+
return;
159+
}
160+
161+
$parser->error('Missing assignment in SET operation.', $list->tokens[$list->idx]);
162+
}
138163
}

tests/Parser/UpdateStatementTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static function updateProvider(): array
3030
['parser/parseUpdate6'],
3131
['parser/parseUpdate7'],
3232
['parser/parseUpdateErr'],
33+
['parser/parseUpdateEmptySet'],
3334
];
3435
}
3536
}

tests/data/parser/parseUpdate3.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@
243243
"@type": "@12"
244244
},
245245
0
246+
],
247+
[
248+
"Missing assignment in SET operation.",
249+
{
250+
"@type": "@11"
251+
},
252+
0
246253
]
247254
]
248255
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
UPDATE test SET WHERE 1;
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
{
2+
"query": "UPDATE test SET WHERE 1;\n",
3+
"lexer": {
4+
"@type": "PhpMyAdmin\\SqlParser\\Lexer",
5+
"str": "UPDATE test SET WHERE 1;\n",
6+
"len": 25,
7+
"last": 25,
8+
"list": {
9+
"@type": "PhpMyAdmin\\SqlParser\\TokensList",
10+
"tokens": [
11+
{
12+
"@type": "PhpMyAdmin\\SqlParser\\Token",
13+
"token": "UPDATE",
14+
"value": "UPDATE",
15+
"keyword": "UPDATE",
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": 6
28+
},
29+
{
30+
"@type": "PhpMyAdmin\\SqlParser\\Token",
31+
"token": "test",
32+
"value": "test",
33+
"keyword": null,
34+
"type": 0,
35+
"flags": 0,
36+
"position": 7
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": "SET",
50+
"value": "SET",
51+
"keyword": "SET",
52+
"type": 1,
53+
"flags": 11,
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": 15
64+
},
65+
{
66+
"@type": "PhpMyAdmin\\SqlParser\\Token",
67+
"token": "WHERE",
68+
"value": "WHERE",
69+
"keyword": "WHERE",
70+
"type": 1,
71+
"flags": 3,
72+
"position": 16
73+
},
74+
{
75+
"@type": "PhpMyAdmin\\SqlParser\\Token",
76+
"token": " ",
77+
"value": " ",
78+
"keyword": null,
79+
"type": 3,
80+
"flags": 0,
81+
"position": 21
82+
},
83+
{
84+
"@type": "PhpMyAdmin\\SqlParser\\Token",
85+
"token": "1",
86+
"value": 1,
87+
"keyword": null,
88+
"type": 6,
89+
"flags": 0,
90+
"position": 22
91+
},
92+
{
93+
"@type": "PhpMyAdmin\\SqlParser\\Token",
94+
"token": ";",
95+
"value": ";",
96+
"keyword": null,
97+
"type": 9,
98+
"flags": 0,
99+
"position": 23
100+
},
101+
{
102+
"@type": "PhpMyAdmin\\SqlParser\\Token",
103+
"token": "\n",
104+
"value": " ",
105+
"keyword": null,
106+
"type": 3,
107+
"flags": 0,
108+
"position": 24
109+
},
110+
{
111+
"@type": "PhpMyAdmin\\SqlParser\\Token",
112+
"token": null,
113+
"value": null,
114+
"keyword": null,
115+
"type": 9,
116+
"flags": 0,
117+
"position": null
118+
}
119+
],
120+
"count": 12,
121+
"idx": 12
122+
},
123+
"delimiter": ";",
124+
"delimiterLen": 1,
125+
"strict": false,
126+
"errors": []
127+
},
128+
"parser": {
129+
"@type": "PhpMyAdmin\\SqlParser\\Parser",
130+
"list": {
131+
"@type": "@1"
132+
},
133+
"statements": [
134+
{
135+
"@type": "PhpMyAdmin\\SqlParser\\Statements\\UpdateStatement",
136+
"tables": [
137+
{
138+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Expression",
139+
"database": null,
140+
"table": "test",
141+
"column": null,
142+
"expr": "test",
143+
"alias": null,
144+
"function": null,
145+
"subquery": null
146+
}
147+
],
148+
"set": [],
149+
"where": [
150+
{
151+
"@type": "PhpMyAdmin\\SqlParser\\Components\\Condition",
152+
"identifiers": [],
153+
"isOperator": false,
154+
"expr": "1"
155+
}
156+
],
157+
"order": null,
158+
"limit": null,
159+
"join": null,
160+
"options": {
161+
"@type": "PhpMyAdmin\\SqlParser\\Components\\OptionsArray",
162+
"options": []
163+
},
164+
"first": 0,
165+
"last": 8
166+
}
167+
],
168+
"brackets": 0,
169+
"strict": false,
170+
"errors": []
171+
},
172+
"errors": {
173+
"lexer": [],
174+
"parser": [
175+
[
176+
"Missing assignment in SET operation.",
177+
{
178+
"@type": "@7"
179+
},
180+
0
181+
]
182+
]
183+
}
184+
}

0 commit comments

Comments
 (0)