Skip to content

Commit 6b42052

Browse files
committed
Merge #287 - Fix #285 - Fixing conflict in lexer when '*/*' was in a query.
Pull-request: #287 Fixes: #285 Signed-off-by: William Desportes <[email protected]>
2 parents 7148669 + 101e0b0 commit 6b42052

File tree

5 files changed

+167
-6
lines changed

5 files changed

+167
-6
lines changed

src/Context.php

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,28 @@ public static function isComment($str, $end = false)
336336
if ($len === 0) {
337337
return null;
338338
}
339+
340+
// If comment is Bash style (#):
339341
if ($str[0] === '#') {
340342
return Token::FLAG_COMMENT_BASH;
341-
} elseif (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
342-
return (($len > 2) && ($str[2] === '!')) ?
343+
}
344+
// If comment is opening C style (/*), warning, it could be a MySQL command (/*!)
345+
if (($len > 1) && ($str[0] === '/') && ($str[1] === '*')) {
346+
return ($len > 2) && ($str[2] === '!') ?
343347
Token::FLAG_COMMENT_MYSQL_CMD : Token::FLAG_COMMENT_C;
344-
} elseif (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
348+
}
349+
// If comment is closing C style (*/), warning, it could conflicts with wildcard and a real opening C style.
350+
// It would looks like the following valid SQL statement: "SELECT */* comment */ FROM...".
351+
if (($len > 1) && ($str[0] === '*') && ($str[1] === '/')) {
345352
return Token::FLAG_COMMENT_C;
346-
} elseif (($len > 2) && ($str[0] === '-')
353+
}
354+
// If comment is SQL style (--\s?):
355+
if (($len > 2) && ($str[0] === '-')
347356
&& ($str[1] === '-') && static::isWhitespace($str[2])
348357
) {
349358
return Token::FLAG_COMMENT_SQL;
350-
} elseif (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
359+
}
360+
if (($len === 2) && $end && ($str[0] === '-') && ($str[1] === '-')) {
351361
return Token::FLAG_COMMENT_SQL;
352362
}
353363

src/Lexer.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,19 @@ public function parseComment()
559559
if (++$this->last < $this->len) {
560560
$token .= $this->str[$this->last];
561561
if (Context::isComment($token)) {
562+
// There might be a conflict with "*" operator here, when string is "*/*".
563+
// This can occurs in the following statements:
564+
// - "SELECT */* comment */ FROM ..."
565+
// - "SELECT 2*/* comment */3 AS `six`;"
566+
$next = $this->last+1;
567+
if (($next < $this->len) && $this->str[$next] === '*') {
568+
// Conflict in "*/*": first "*" was not for ending a comment.
569+
// Stop here and let other parsing method define the true behavior of that first star.
570+
$this->last = $iBak;
571+
572+
return null;
573+
}
574+
562575
$flags = Token::FLAG_COMMENT_C;
563576

564577
// This comment already ended. It may be a part of a

tests/Lexer/LexerTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ public function lexProvider()
8484
array('lexer/lexWhitespace'),
8585
array('lexer/lexLabel1'),
8686
array('lexer/lexLabel2'),
87-
array('lexer/lexNoLabel')
87+
array('lexer/lexNoLabel'),
88+
array('lexer/lexWildcardThenComment')
8889
);
8990
}
9091
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
SELECT */* comment */
2+
3+
SELECT /* comment */*
4+
5+
SELECT 2*/* comment */3
6+
7+
SELECT 2/* comment */*3
8+
9+
SELECT */*
10+
comment
11+
on
12+
multiple
13+
lines
14+
*/FROM
15+
16+
DELETE foo.*/* foo */ USING
17+
18+
DELETE foo.*/* foo */,bar.*/*bar*/ USING
19+
20+
SELECT `*`/*with comment*/ AS star_field
21+
22+
SELECT `*`,*/*with comment*/
23+
24+
DELETE a.*/*multi
25+
line /* with C open tag
26+
comment inside */ USING
27+
28+
SELECT 2*/* operator */3 + 3/* operator */*2,/* start wildcard */*/* end wildcard */
29+
30+
SELECT `*`/*a*/*/*b*/`*`
31+
32+
-- invalid queries
33+
/* SELECT */*

0 commit comments

Comments
 (0)