diff --git a/src/Parsers/OptionsArrays.php b/src/Parsers/OptionsArrays.php index f3dea83c..39f8fc59 100644 --- a/src/Parsers/OptionsArrays.php +++ b/src/Parsers/OptionsArrays.php @@ -7,6 +7,7 @@ use PhpMyAdmin\SqlParser\Components\OptionsArray; use PhpMyAdmin\SqlParser\Parseable; use PhpMyAdmin\SqlParser\Parser; +use PhpMyAdmin\SqlParser\Token; use PhpMyAdmin\SqlParser\TokensList; use PhpMyAdmin\SqlParser\TokenType; use PhpMyAdmin\SqlParser\Translator; @@ -86,7 +87,24 @@ public static function parse(Parser $parser, TokensList $list, array $options = } if ($lastOption === null) { - $upper = strtoupper($token->token); + // Backtick-enclosed option names (e.g. `PAGE_COMPRESSED`=1) are + // produced by MariaDB. We accept them only when followed by '=' + // so that regular quoted identifiers are not mistaken for options. + if ($token->type === TokenType::Symbol && $token->flags === Token::FLAG_SYMBOL_BACKTICK) { + $nextIdx = $list->idx + 1; + while ($nextIdx < $list->count && $list->tokens[$nextIdx]->type === TokenType::Whitespace) { + ++$nextIdx; + } + + if ($nextIdx >= $list->count || $list->tokens[$nextIdx]->token !== '=') { + break; + } + + $upper = strtoupper((string) $token->value); + } else { + $upper = strtoupper($token->token); + } + if (! isset($options[$upper])) { // There is no option to be processed. break; diff --git a/tests/Builder/CreateStatementTest.php b/tests/Builder/CreateStatementTest.php index 3ba1c1c5..7ec9fcde 100644 --- a/tests/Builder/CreateStatementTest.php +++ b/tests/Builder/CreateStatementTest.php @@ -97,6 +97,18 @@ public function testBuilderCompressed(): void ); } + public function testBuilderCompressedBackticks(): void + { + $parser = new Parser( + 'CREATE TABLE users ( user_id int ) `PAGE_COMPRESSED`=1 `PAGE_COMPRESSION_LEVEL`=9;', + ); + $stmt = $parser->statements[0]; + $this->assertEquals( + "CREATE TABLE users (\n `user_id` int\n) PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=9", + $stmt->build(), + ); + } + public function testBuilderCollate(): void { $parser = new Parser(