Skip to content

Commit 3f7f94d

Browse files
committed
fix(bug-3): backtick-escape database and table names in data diff SQL
MySQL data diff queries in LocalTableData now use backtick-quoted `db`.`table` references instead of bare db.table. This prevents MySQL from interpreting hyphens in database names (e.g. 'my-db') as subtraction operators, which caused PDO syntax error 1064. Fixed in getOldNewDiff() (2 queries) and getChangeDiff() (1 query + key column references). Added unit test verifying MySQLDialect::quote() correctly handles hyphenated names, names with backticks, and names with spaces. Refs: bugs.md Bug #3, PR #92
1 parent 6a1ddff commit 3f7f94d

2 files changed

Lines changed: 40 additions & 7 deletions

File tree

src/DB/Data/LocalTableData.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,12 +333,12 @@ public function getOldNewDiff($table, $key) {
333333

334334
$this->setFetchMode(\PDO::FETCH_NAMED);
335335
$result1 = $this->source->select(
336-
"SELECT $columnsAUtf FROM {$db1}.{$table} as a
337-
LEFT JOIN {$db2}.{$table} as b ON $keyCols WHERE $keyNulls2
336+
"SELECT $columnsAUtf FROM `{$db1}`.`{$table}` as a
337+
LEFT JOIN `{$db2}`.`{$table}` as b ON $keyCols WHERE $keyNulls2
338338
");
339339
$result2 = $this->source->select(
340-
"SELECT $columnsBUtf FROM {$db2}.{$table} as b
341-
LEFT JOIN {$db1}.{$table} as a ON $keyCols WHERE $keyNulls1
340+
"SELECT $columnsBUtf FROM `{$db2}`.`{$table}` as b
341+
LEFT JOIN `{$db1}`.`{$table}` as a ON $keyCols WHERE $keyNulls1
342342
");
343343
$this->setFetchMode(\PDO::FETCH_ASSOC);
344344

@@ -392,15 +392,15 @@ public function getChangeDiff($table, $key) {
392392
$columnsB = implode(',', $wrapCast($columns2, 'b'));
393393

394394
$keyCols = implode(self::SQL_AND, array_map(function($el) {
395-
return "a.{$el} = b.{$el}";
395+
return "`a`.`{$el}` = `b`.`{$el}`";
396396
}, $key));
397397

398398
$this->setFetchMode(\PDO::FETCH_NAMED);
399399
$result = $this->source->select(
400400
"SELECT * FROM (
401401
SELECT $columnsAas, $columnsBas, SHA2(concat($columnsA), 256) AS hash1,
402-
SHA2(concat($columnsB), 256) AS hash2 FROM {$db1}.{$table} as a
403-
INNER JOIN {$db2}.{$table} as b
402+
SHA2(concat($columnsB), 256) AS hash2 FROM `{$db1}`.`{$table}` as a
403+
INNER JOIN `{$db2}`.`{$table}` as b
404404
ON $keyCols
405405
) t WHERE hash1 <> hash2");
406406
$this->setFetchMode(\PDO::FETCH_ASSOC);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace DBDiff\Tests\Unit;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use DBDiff\SQLGen\Dialect\MySQLDialect;
7+
8+
class MySQLDialectQuoteTest extends TestCase
9+
{
10+
public function testQuoteSimpleName(): void
11+
{
12+
$dialect = new MySQLDialect();
13+
$this->assertSame('`users`', $dialect->quote('users'));
14+
}
15+
16+
public function testQuoteHyphenatedName(): void
17+
{
18+
$dialect = new MySQLDialect();
19+
$this->assertSame('`my-database`', $dialect->quote('my-database'));
20+
}
21+
22+
public function testQuoteNameWithBacktick(): void
23+
{
24+
$dialect = new MySQLDialect();
25+
$this->assertSame('`name``with``ticks`', $dialect->quote('name`with`ticks'));
26+
}
27+
28+
public function testQuoteNameWithSpaces(): void
29+
{
30+
$dialect = new MySQLDialect();
31+
$this->assertSame('`table name`', $dialect->quote('table name'));
32+
}
33+
}

0 commit comments

Comments
 (0)