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:
@@ -73,36 +73,18 @@ class Database
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDriver()
|
||||||
|
{
|
||||||
|
return $this->driver;
|
||||||
|
}
|
||||||
|
|
||||||
private function rewriteForSQLite($sql)
|
private function rewriteForSQLite($sql)
|
||||||
{
|
{
|
||||||
// REPLACE INTO → INSERT OR REPLACE INTO
|
// REPLACE INTO → INSERT OR REPLACE INTO
|
||||||
$sql = preg_replace('/\bREPLACE\s+INTO\b/i', 'INSERT OR REPLACE INTO', $sql);
|
$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
|
// INSERT IGNORE INTO → INSERT OR IGNORE INTO
|
||||||
$sql = preg_replace('/\bINSERT\s+IGNORE\s+INTO\b/i', 'INSERT OR IGNORE INTO', $sql);
|
$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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// LIMIT :offset, :limit → LIMIT :limit OFFSET :offset
|
// LIMIT :offset, :limit → LIMIT :limit OFFSET :offset
|
||||||
$sql = preg_replace(
|
$sql = preg_replace(
|
||||||
|
|||||||
@@ -122,10 +122,12 @@ class Tag
|
|||||||
|
|
||||||
public static function getAlbums($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
|
public static function getAlbums($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
|
||||||
{
|
{
|
||||||
|
$parent_clause = empty($id_parent) ? '(id_parent = :id_parent OR id_parent IS NULL)' : 'id_parent = :id_parent';
|
||||||
|
|
||||||
$rows = Registry::get('db')->queryAssocs('
|
$rows = Registry::get('db')->queryAssocs('
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM tags
|
FROM tags
|
||||||
WHERE id_parent = :id_parent AND kind = :kind
|
WHERE ' . $parent_clause . ' AND kind = :kind
|
||||||
ORDER BY tag ASC
|
ORDER BY tag ASC
|
||||||
LIMIT :offset, :limit',
|
LIMIT :offset, :limit',
|
||||||
[
|
[
|
||||||
@@ -163,10 +165,12 @@ class Tag
|
|||||||
|
|
||||||
public static function getPeople($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
|
public static function getPeople($id_parent = 0, $offset = 0, $limit = 24, $return_format = 'array')
|
||||||
{
|
{
|
||||||
|
$parent_clause = empty($id_parent) ? '(id_parent = :id_parent OR id_parent IS NULL)' : 'id_parent = :id_parent';
|
||||||
|
|
||||||
$rows = Registry::get('db')->queryAssocs('
|
$rows = Registry::get('db')->queryAssocs('
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM tags
|
FROM tags
|
||||||
WHERE id_parent = :id_parent AND kind = :kind
|
WHERE ' . $parent_clause . ' AND kind = :kind
|
||||||
ORDER BY tag ASC
|
ORDER BY tag ASC
|
||||||
LIMIT :offset, :limit',
|
LIMIT :offset, :limit',
|
||||||
[
|
[
|
||||||
@@ -249,7 +253,21 @@ class Tag
|
|||||||
|
|
||||||
public static function recount(array $id_tags = [])
|
public static function recount(array $id_tags = [])
|
||||||
{
|
{
|
||||||
return Registry::get('db')->query('
|
$db = Registry::get('db');
|
||||||
|
|
||||||
|
if ($db->getDriver() === 'sqlite')
|
||||||
|
{
|
||||||
|
return $db->query('
|
||||||
|
UPDATE tags SET count = (
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM `assets_tags` AS at
|
||||||
|
WHERE at.id_tag = tags.id_tag
|
||||||
|
)' . (!empty($id_tags) ? '
|
||||||
|
WHERE tags.id_tag IN(@id_tags)' : ''),
|
||||||
|
['id_tags' => $id_tags]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $db->query('
|
||||||
UPDATE tags AS t SET count = (
|
UPDATE tags AS t SET count = (
|
||||||
SELECT COUNT(*)
|
SELECT COUNT(*)
|
||||||
FROM `assets_tags` AS at
|
FROM `assets_tags` AS at
|
||||||
@@ -272,6 +290,18 @@ class Tag
|
|||||||
if (!isset($data['count']))
|
if (!isset($data['count']))
|
||||||
$data['count'] = 0;
|
$data['count'] = 0;
|
||||||
|
|
||||||
|
if ($db->getDriver() === 'sqlite')
|
||||||
|
{
|
||||||
|
$res = $db->query('
|
||||||
|
INSERT INTO tags
|
||||||
|
(id_parent, tag, slug, kind, description, count)
|
||||||
|
VALUES
|
||||||
|
(:id_parent, :tag, :slug, :kind, :description, :count)
|
||||||
|
ON CONFLICT(slug) DO UPDATE SET count = count + 1',
|
||||||
|
$data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
$res = $db->query('
|
$res = $db->query('
|
||||||
INSERT IGNORE INTO tags
|
INSERT IGNORE INTO tags
|
||||||
(id_parent, tag, slug, kind, description, count)
|
(id_parent, tag, slug, kind, description, count)
|
||||||
@@ -279,6 +309,7 @@ class Tag
|
|||||||
(:id_parent, :tag, :slug, :kind, :description, :count)
|
(:id_parent, :tag, :slug, :kind, :description, :count)
|
||||||
ON DUPLICATE KEY UPDATE count = count + 1',
|
ON DUPLICATE KEY UPDATE count = count + 1',
|
||||||
$data);
|
$data);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$res)
|
if (!$res)
|
||||||
throw new Exception('Could not create the requested tag.');
|
throw new Exception('Could not create the requested tag.');
|
||||||
|
|||||||
Reference in New Issue
Block a user