Refactor fragile SQLite regex rewrites into driver-aware query methods

Move the ON DUPLICATE KEY UPDATE and UPDATE...AS alias SQL rewrites out
of Database::rewriteForSQLite() and into Tag::createNew() and
Tag::recount() as driver-aware branches via a new Database::getDriver()
method. This keeps dialect-specific SQL explicit at the call site rather
than buried in fragile regex transforms.

Also fix Tag::getAlbums() and Tag::getPeople() failing on SQLite when
id_parent is NULL by adding an IS NULL fallback for root-level queries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 15:40:46 +01:00
parent a4d453792d
commit d788391f4a
2 changed files with 48 additions and 35 deletions

View File

@@ -73,36 +73,18 @@ class Database
}, 0);
}
public function getDriver()
{
return $this->driver;
}
private function rewriteForSQLite($sql)
{
// REPLACE INTO → INSERT OR REPLACE INTO
$sql = preg_replace('/\bREPLACE\s+INTO\b/i', 'INSERT OR REPLACE INTO', $sql);
// ON DUPLICATE KEY UPDATE → ON CONFLICT(slug) DO UPDATE SET
// When present, strip INSERT IGNORE down to INSERT (OR IGNORE conflicts with ON CONFLICT).
if (preg_match('/\bON\s+DUPLICATE\s+KEY\s+UPDATE\b/i', $sql))
{
$sql = preg_replace('/\bINSERT\s+IGNORE\s+INTO\b/i', 'INSERT INTO', $sql);
$sql = preg_replace(
'/\bON\s+DUPLICATE\s+KEY\s+UPDATE\s+(.+)/i',
'ON CONFLICT(slug) DO UPDATE SET $1',
$sql
);
}
else
{
// INSERT IGNORE INTO → INSERT OR IGNORE INTO
$sql = preg_replace('/\bINSERT\s+IGNORE\s+INTO\b/i', 'INSERT OR IGNORE INTO', $sql);
}
// UPDATE table AS alias SET ... → UPDATE table SET ... (with alias replaced by table name)
if (preg_match('/\bUPDATE\s+(\w+)\s+AS\s+(\w+)\s+SET\b/i', $sql, $m))
{
$table = $m[1];
$alias = $m[2];
$sql = preg_replace('/\bUPDATE\s+\w+\s+AS\s+\w+\s+SET\b/i', "UPDATE $table SET", $sql);
$sql = preg_replace('/\b' . preg_quote($alias, '/') . '\.(\w+)\b/', "$table.$1", $sql);
}
// INSERT IGNORE INTO → INSERT OR IGNORE INTO
$sql = preg_replace('/\bINSERT\s+IGNORE\s+INTO\b/i', 'INSERT OR IGNORE INTO', $sql);
// LIMIT :offset, :limit → LIMIT :limit OFFSET :offset
$sql = preg_replace(