Skip to content

Commit db9d464

Browse files
committed
fix: recognize MariaDB executable comments
1 parent 357fc03 commit db9d464

3 files changed

Lines changed: 23 additions & 4 deletions

File tree

include/sql_parser/tokenizer.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ class Tokenizer {
160160
}
161161
} else {
162162
// MySQL: no nesting
163-
const bool executable = cursor_ < end_ && *cursor_ == '!';
163+
const bool executable = cursor_ < end_ &&
164+
(*cursor_ == '!' ||
165+
(cursor_ + 1 < end_ && cursor_[0] == 'M' && cursor_[1] == '!'));
164166
bool has_user_variable_marker = false;
165167
bool closed = false;
166168
while (cursor_ < end_) {
@@ -176,9 +178,9 @@ class Tokenizer {
176178
flag_fatal_error_at(StringRef{comment_start,
177179
static_cast<uint32_t>(end_ - comment_start)});
178180
}
179-
// Versioned comments execute as SQL on MySQL. Until their
180-
// contents are parsed exactly, preserve any possible user
181-
// variable use and force conservative classification.
181+
// MySQL and MariaDB executable comments run as SQL. Until
182+
// their contents are parsed exactly, preserve any possible
183+
// user variable use and force conservative classification.
182184
if (executable && has_user_variable_marker) {
183185
has_user_variables_ = true;
184186
flag_fatal_error_at(StringRef{comment_start,

tests/test_tokenizer.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,19 @@ TEST_F(MySQLTokenizerTest, UnterminatedBlockCommentIsAnError) {
213213
EXPECT_TRUE(tok.has_error());
214214
}
215215

216+
TEST_F(MySQLTokenizerTest, MariaDBExecutableCommentsExposeUserVariables) {
217+
const char* cases[] = {
218+
"/*M!100100 SET @x=1 */",
219+
"/*M! SET @x=1 */",
220+
};
221+
for (const char* sql : cases) {
222+
SCOPED_TRACE(sql);
223+
tok.reset(sql, strlen(sql));
224+
while (tok.next_token().type != TokenType::TK_EOF) {}
225+
EXPECT_TRUE(tok.has_user_variables());
226+
}
227+
}
228+
216229
TEST_F(MySQLTokenizerTest, Placeholder) {
217230
const char* sql = "?";
218231
tok.reset(sql, strlen(sql));

tests/test_user_variable.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ TEST(MySQLUserVariableUsage, HandlesMySQLCommentBoundariesConservatively) {
6363
EXPECT_EQ(classify("SELECT 1--@x"), UserVariableUsage::READ_ONLY);
6464
EXPECT_EQ(classify("/*!40101 SET @x=1 */"),
6565
UserVariableUsage::UNSAFE_OR_UNKNOWN);
66+
EXPECT_EQ(classify("/*M!100100 SET @x=1 */"),
67+
UserVariableUsage::UNSAFE_OR_UNKNOWN);
68+
EXPECT_EQ(classify("/*M! SET @x=1 */"),
69+
UserVariableUsage::UNSAFE_OR_UNKNOWN);
6670
EXPECT_EQ(classify("SELECT @x /* unterminated"),
6771
UserVariableUsage::UNSAFE_OR_UNKNOWN);
6872
EXPECT_EQ(classify("SET @x=1 /* unterminated"),

0 commit comments

Comments
 (0)