diff --git a/CHANGELOG.md b/CHANGELOG.md index 3af0daf3b..137af005f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ## 1.1.2 under development - Bug #751: Fix collected debug actions (@xepozz) +- Enh #756: Refactor `Quoter` (@Tigrov) +- Bug #756: Fix `quoteSql()` for SQL containing table with prefix (@Tigrov) +- Bug #756: Fix `getTableNameParts()` for cases when different quotes for tables and columns (@Tigrov) +- Bug #756: Fix `quoteTableName()` for sub-query with alias (@Tigrov) ## 1.1.1 August 16, 2023 diff --git a/src/Schema/Quoter.php b/src/Schema/Quoter.php index 10a559222..1f8aef970 100644 --- a/src/Schema/Quoter.php +++ b/src/Schema/Quoter.php @@ -8,9 +8,13 @@ use Yiisoft\Db\Expression\ExpressionInterface; use function addcslashes; +use function array_slice; +use function count; use function explode; use function implode; use function is_string; +use function preg_match; +use function preg_replace; use function preg_replace_callback; use function str_contains; use function str_replace; @@ -44,7 +48,7 @@ public function cleanUpTableNames(array $tableNames): array { $cleanedUpTableNames = []; $pattern = << $tableNames */ @@ -104,7 +108,7 @@ public function ensureColumnName(string $name): string $name = $parts[count($parts) - 1]; } - return preg_replace('|^\[\[([_\w\-. ]+)\]\]$|', '\1', $name); + return preg_replace('|^\[\[([\w\-. ]+)]]$|', '\1', $name); } public function quoteColumnName(string $name): string @@ -135,8 +139,9 @@ public function quoteSimpleColumnName(string $name): string [$startingCharacter, $endingCharacter] = $this->columnQuoteCharacter; } - return $name === '*' || str_contains($name, $startingCharacter) ? $name : $startingCharacter . $name - . $endingCharacter; + return $name === '*' || str_starts_with($name, $startingCharacter) + ? $name + : $startingCharacter . $name . $endingCharacter; } public function quoteSimpleTableName(string $name): string @@ -147,13 +152,15 @@ public function quoteSimpleTableName(string $name): string [$startingCharacter, $endingCharacter] = $this->tableQuoteCharacter; } - return str_contains($name, $startingCharacter) ? $name : $startingCharacter . $name . $endingCharacter; + return str_starts_with($name, $startingCharacter) + ? $name + : $startingCharacter . $name . $endingCharacter; } public function quoteSql(string $sql): string { return preg_replace_callback( - '/({{(%?[\w\-. ]+%?)}}|\\[\\[([\w\-. ]+)]])/', + '/({{(%?[\w\-. ]+)%?}}|\\[\\[([\w\-. ]+)]])/', function ($matches) { if (isset($matches[3])) { return $this->quoteColumnName($matches[3]); @@ -167,7 +174,7 @@ function ($matches) { public function quoteTableName(string $name): string { - if (str_starts_with($name, '(') && str_ends_with($name, ')')) { + if (str_starts_with($name, '(')) { return $name; } @@ -194,7 +201,7 @@ public function quoteValue(mixed $value): mixed return $value; } - return '\'' . str_replace('\'', '\'\'', addcslashes($value, "\000\032")) . '\''; + return "'" . str_replace("'", "''", addcslashes($value, "\000\032")) . "'"; } public function unquoteSimpleColumnName(string $name): string @@ -205,7 +212,9 @@ public function unquoteSimpleColumnName(string $name): string $startingCharacter = $this->columnQuoteCharacter[0]; } - return !str_contains($name, $startingCharacter) ? $name : substr($name, 1, -1); + return !str_starts_with($name, $startingCharacter) + ? $name + : substr($name, 1, -1); } public function unquoteSimpleTableName(string $name): string @@ -216,7 +225,9 @@ public function unquoteSimpleTableName(string $name): string $startingCharacter = $this->tableQuoteCharacter[0]; } - return !str_contains($name, $startingCharacter) ? $name : substr($name, 1, -1); + return !str_starts_with($name, $startingCharacter) + ? $name + : substr($name, 1, -1); } /** @@ -229,7 +240,7 @@ protected function unquoteParts(array $parts, bool $withColumn): array $lastKey = count($parts) - 1; foreach ($parts as $k => &$part) { - $part = ($withColumn || $lastKey === $k) ? + $part = ($withColumn && $lastKey === $k) ? $this->unquoteSimpleColumnName($part) : $this->unquoteSimpleTableName($part); } diff --git a/tests/Db/Schema/QuoterTest.php b/tests/Db/Schema/QuoterTest.php index 0841dca80..3d7bd8599 100644 --- a/tests/Db/Schema/QuoterTest.php +++ b/tests/Db/Schema/QuoterTest.php @@ -87,4 +87,27 @@ public function testCleanUpTableNamesWithCastException(): void ['tableAlias' => 123], ); } + + public function testGetTableNamePartsWithDifferentQuotes(): void + { + $quoter = new Quoter('`', '"'); + + $this->assertSame(['schema', 'table'], $quoter->getTableNameParts('"schema"."table"')); + } + + public function testQuoteSqlWithTablePrefix(): void + { + $quoter = new Quoter('`', '`', 'prefix_'); + $sql = 'SELECT * FROM {{%table%}}'; + + $this->assertSame('SELECT * FROM `prefix_table`', $quoter->quoteSql($sql)); + } + + public function testQuoteTableNameWithQueryAlias() + { + $quoter = new Quoter('`', '`'); + $name = '(SELECT * FROM table) alias'; + + $this->assertSame($name, $quoter->quoteTableName($name)); + } }