Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/MySqlMultiQueryParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ private function getQueryPattern(string $delimiter): string
| \" (*PRUNE) (?: \\\\. | [^\"] )*+ \"
| \` (*PRUNE) (?: [^\`]++ | \`\` )*+ \`
| /\\* (*PRUNE) (?: [^*]++ | \\*(?!/) )*+ \\*/
| (?!$delimiterPattern) (\\$(?:[a-zA-Z_\\x80-\\xFF][\\w\\x80-\\xFF]*+)?\\$) (*PRUNE) (?: [^$]++ | (?!\\g{-1})\\$ )*+ \\g{-1}
| --[^\\n]*+(?:\\n|\\z)
| \\#[^\\n]*+(?:\\n|\\z)
| (?!$delimiterPattern) .
Expand Down
37 changes: 36 additions & 1 deletion tests/cases/MySqlMultiQueryParserTest.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase

protected function getExpectedFileQueryCount(): int
{
return 60;
return 61;
}


Expand Down Expand Up @@ -148,6 +148,21 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
"SELECT 1",
],
],
// DELIMITER $$ with $mle$ dollar-quoted body
[
implode("\n", [
'SELECT 1;',
'DELIMITER $$',
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$$$',
'DELIMITER ;',
'SELECT 2;',
]),
[
'SELECT 1',
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$',
'SELECT 2',
],
],
];
}

Expand Down Expand Up @@ -242,6 +257,21 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase

// Escaped backticks (doubled) inside backtick identifiers
["SELECT `col``name` FROM t;", ["SELECT `col``name` FROM t"]],

// Dollar-quoted strings in JavaScript stored programs
[
'CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$;',
['CREATE FUNCTION gcd(a INT, b INT) RETURNS INT NO SQL LANGUAGE JAVASCRIPT AS $mle$ let x = a; let y = b; $mle$'],
],
[
'CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$;',
['CREATE FUNCTION js_add(a INT, b INT) RETURNS INT LANGUAGE JAVASCRIPT AS $$ return a + b; $$'],
],
// Nested dollar-quoted strings with different tags
[
'CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$;',
['CREATE FUNCTION nested() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let s = $inner$;$inner$; return 1; $mle$'],
],
];
}

Expand Down Expand Up @@ -297,6 +327,11 @@ class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
["SELECT `col;na", "me` FROM t;"],
["SELECT `col;name` FROM t"],
],
// Dollar-quoted string spanning chunks
[
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1;', ' return x; $mle$;'],
['CREATE FUNCTION f() RETURNS INT LANGUAGE JAVASCRIPT AS $mle$ let x = 1; return x; $mle$'],
],
];
}
}
Expand Down
15 changes: 15 additions & 0 deletions tests/data/mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,21 @@ INSERT INTO contents (id, type, thread_id, replied_at) VALUES (1, 'thread', NULL
INSERT INTO contents (id, type, thread_id, replied_at) VALUES (2, 'comment', 1, '2020-01-01 12:00:00');
INSERT INTO contents (id, type, thread_id, replied_at) VALUES (3, 'comment', 1, '2020-01-02 12:00:00');

CREATE FUNCTION gcd(a INT, b INT)
RETURNS INT
NO SQL
LANGUAGE JAVASCRIPT AS
$mle$
let x = Math.abs(a);
let y = Math.abs(b);
while (y) {
var t = y;
y = x % y;
x = t;
}
return x;
$mle$;

# Hash comment with semicolons; should be ignored; entirely
SELECT `backtick;identifier` FROM authors WHERE name = 'test';
# Another hash comment
Expand Down