diff --git a/src/Context.php b/src/Context.php index 42c393244..9de1b5aea 100644 --- a/src/Context.php +++ b/src/Context.php @@ -10,6 +10,7 @@ use function intval; use function is_int; use function is_numeric; +use function preg_match; use function str_replace; use function str_starts_with; use function strlen; @@ -675,7 +676,11 @@ private static function getModeFromString(string $mode): int */ public static function escape(string $str, string $quote = '`') { - if ((static::$mode & self::SQL_MODE_NO_ENCLOSING_QUOTES) && (! static::isKeyword($str, true))) { + if ( + (static::$mode & self::SQL_MODE_NO_ENCLOSING_QUOTES) && ! ( + static::isKeyword($str, true) || static::doesIdentifierRequireQuoting($str) + ) + ) { return $str; } @@ -727,4 +732,9 @@ public static function hasMode(int|null $flag = null): bool return (self::$mode & $flag) === $flag; } + + public static function doesIdentifierRequireQuoting(string $identifier): bool + { + return preg_match('/^[$]|^\d+$|[^0-9a-zA-Z$_\x80-\xffff]/', $identifier) === 1; + } } diff --git a/tests/Lexer/ContextTest.php b/tests/Lexer/ContextTest.php index b02d1180c..95ba7b57f 100644 --- a/tests/Lexer/ContextTest.php +++ b/tests/Lexer/ContextTest.php @@ -217,6 +217,10 @@ public function testEscape(): void { Context::setMode(Context::SQL_MODE_NO_ENCLOSING_QUOTES); $this->assertEquals('test', Context::escape('test')); + $this->assertEquals('`123`', Context::escape('123')); + $this->assertEquals('`$test`', Context::escape('$test')); + $this->assertEquals('`te st`', Context::escape('te st')); + $this->assertEquals('`te.st`', Context::escape('te.st')); Context::setMode(Context::SQL_MODE_ANSI_QUOTES); $this->assertEquals('"test"', Context::escape('test'));