Skip to content

Commit e928bdc

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

3 files changed

Lines changed: 52 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+
| (?!$delimiterPattern) (\\$(?:[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: 36 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

@@ -148,6 +148,21 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
148148
"SELECT 1",
149149
],
150150
],
151+
// DELIMITER $$ with $mle$ dollar-quoted body
152+
[
153+
implode("\n", [
154+
'SELECT 1;',
155+
'DELIMITER $$',
156+
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$$$',
157+
'DELIMITER ;',
158+
'SELECT 2;',
159+
]),
160+
[
161+
'SELECT 1',
162+
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$',
163+
'SELECT 2',
164+
],
165+
],
151166
];
152167
}
153168

@@ -242,6 +257,21 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
242257

243258
// Escaped backticks (doubled) inside backtick identifiers
244259
["SELECT `col``name` FROM t;", ["SELECT `col``name` FROM t"]],
260+
261+
// Dollar-quoted strings in JavaScript stored programs
262+
[
263+
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$;',
264+
['CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$'],
265+
],
266+
[
267+
'CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$;',
268+
['CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$'],
269+
],
270+
// Nested dollar-quoted strings with different tags
271+
[
272+
'CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$;',
273+
['CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$'],
274+
],
245275
];
246276
}
247277

@@ -297,6 +327,11 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
297327
["SELECT `col;na", "me` FROM t;"],
298328
["SELECT `col;name` FROM t"],
299329
],
330+
// Dollar-quoted string spanning chunks
331+
[
332+
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1;', ' return x; $mle$;'],
333+
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1; return x; $mle$'],
334+
],
300335
];
301336
}
302337
}

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)