Skip to content

Commit 16c93f1

Browse files
committed
Add dollar-quoting support to MySQL multi-query parser
1 parent c14813e commit 16c93f1

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/MySqlMultiQueryParser.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ private function getQueryPattern(string $delimiter): string
5252
| \" (*PRUNE) (?: \\\\. | [^\"] )*+ \"
5353
| \` (*PRUNE) (?: [^\`]++ | \`\` )*+ \`
5454
| /\\* (*PRUNE) (?: [^*]++ | \\*(?!/) )*+ \\*/
55+
| (\\$(?:[a-zA-Z_\\x80-\\xFF][\\w\\x80-\\xFF]*+)?\\$) (*PRUNE) (?: [^$]++ | (?!\\g{-1})\\$ )*+ \\g{-1}
5556
| --[^\\n]*+(?:\\n|\\z)
5657
| \\#[^\\n]*+(?:\\n|\\z)
5758
| (?!$delimiterPattern) .

tests/cases/MySqlMultiQueryParserTest.phpt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
2929

3030
protected function getExpectedFileQueryCount(): int
3131
{
32-
return 60;
32+
return 61;
3333
}
3434

3535

@@ -242,6 +242,21 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
242242

243243
// Escaped backticks (doubled) inside backtick identifiers
244244
["SELECT `col``name` FROM t;", ["SELECT `col``name` FROM t"]],
245+
246+
// Dollar-quoted strings in JavaScript stored programs
247+
[
248+
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$;',
249+
['CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$'],
250+
],
251+
[
252+
'CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$;',
253+
['CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$'],
254+
],
255+
// Nested dollar-quoted strings with different tags
256+
[
257+
'CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$;',
258+
['CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$'],
259+
],
245260
];
246261
}
247262

@@ -297,6 +312,11 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
297312
["SELECT `col;na", "me` FROM t;"],
298313
["SELECT `col;name` FROM t"],
299314
],
315+
// Dollar-quoted string spanning chunks
316+
[
317+
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1;', ' return x; $mle$;'],
318+
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1; return x; $mle$'],
319+
],
300320
];
301321
}
302322
}

tests/data/mysql.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,21 @@ INSERT INTO contents (id, type, thread_id, replied_at) VALUES (1, 'thread', NULL
225225
INSERT INTO contents (id, type, thread_id, replied_at) VALUES (2, 'comment', 1, '2020-01-01 12:00:00');
226226
INSERT INTO contents (id, type, thread_id, replied_at) VALUES (3, 'comment', 1, '2020-01-02 12:00:00');
227227

228+
CREATE FUNCTION gcd(a INT, b INT)
229+
RETURNS INT
230+
NO SQL
231+
LANGUAGE JAVASCRIPT AS
232+
$mle$
233+
let x = Math.abs(a);
234+
let y = Math.abs(b);
235+
while (y) {
236+
var t = y;
237+
y = x % y;
238+
x = t;
239+
}
240+
return x;
241+
$mle$;
242+
228243
# Hash comment with semicolons; should be ignored; entirely
229244
SELECT `backtick;identifier` FROM authors WHERE name = 'test';
230245
# Another hash comment

0 commit comments

Comments
 (0)