Skip to content

Commit 0cd9386

Browse files
Ryujiyasuclaude
andcommitted
Fix parsing of backtick-enclosed table options
MariaDB encloses some table options in backticks by default (e.g. `PAGE_COMPRESSED`=1). The option name lookup in OptionsArrays::parse() used $token->token which includes the backticks, causing the match against the options array to fail. This adds a targeted check: when a backtick-enclosed symbol is followed by '=', its unquoted value is used for the lookup. A lookahead for '=' prevents regular quoted identifiers (such as table or column names) from being mistaken for options. Fixes #643 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 960cc8e commit 0cd9386

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

src/Parsers/OptionsArrays.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PhpMyAdmin\SqlParser\Components\OptionsArray;
88
use PhpMyAdmin\SqlParser\Parseable;
99
use PhpMyAdmin\SqlParser\Parser;
10+
use PhpMyAdmin\SqlParser\Token;
1011
use PhpMyAdmin\SqlParser\TokensList;
1112
use PhpMyAdmin\SqlParser\TokenType;
1213
use PhpMyAdmin\SqlParser\Translator;
@@ -86,7 +87,24 @@ public static function parse(Parser $parser, TokensList $list, array $options =
8687
}
8788

8889
if ($lastOption === null) {
89-
$upper = strtoupper($token->token);
90+
// Backtick-enclosed option names (e.g. `PAGE_COMPRESSED`=1) are
91+
// produced by MariaDB. We accept them only when followed by '='
92+
// so that regular quoted identifiers are not mistaken for options.
93+
if ($token->type === TokenType::Symbol && $token->flags === Token::FLAG_SYMBOL_BACKTICK) {
94+
$nextIdx = $list->idx + 1;
95+
while ($nextIdx < $list->count && $list->tokens[$nextIdx]->type === TokenType::Whitespace) {
96+
++$nextIdx;
97+
}
98+
99+
if ($nextIdx >= $list->count || $list->tokens[$nextIdx]->token !== '=') {
100+
break;
101+
}
102+
103+
$upper = strtoupper((string) $token->value);
104+
} else {
105+
$upper = strtoupper($token->token);
106+
}
107+
90108
if (! isset($options[$upper])) {
91109
// There is no option to be processed.
92110
break;

tests/Builder/CreateStatementTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ public function testBuilderCompressed(): void
9797
);
9898
}
9999

100+
public function testBuilderCompressedBackticks(): void
101+
{
102+
$parser = new Parser(
103+
'CREATE TABLE users ( user_id int ) `PAGE_COMPRESSED`=1 `PAGE_COMPRESSION_LEVEL`=9;',
104+
);
105+
$stmt = $parser->statements[0];
106+
$this->assertEquals(
107+
"CREATE TABLE users (\n `user_id` int\n) PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9",
108+
$stmt->build(),
109+
);
110+
}
111+
100112
public function testBuilderCollate(): void
101113
{
102114
$parser = new Parser(

0 commit comments

Comments
 (0)