packages/ztd-query-sqlite/src/Rewrite/GeneratedColumn/SqliteGeneratedColumnProjector.php

1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Platform\Sqlite\Rewrite\GeneratedColumn;
6
7use ZtdQuery\Platform\IdentifierQuoter;
8
9/**
10 * Recomputes database-generated columns from a complete base-row projection.
11 */
12final class SqliteGeneratedColumnProjector
13{
14    private const SOURCE_ALIAS = '__ztd_generated_source';
15
16    private readonly IdentifierQuoter $quoter;
17
18    /**
19     * Binds the dependencies used by this operation.
20     */
21    public function __construct()
22    {
23        $this->quoter = new \ZtdQuery\Platform\Sqlite\Sql\SqliteIdentifierQuoter();
24    }
25
26    /**
27     * @param array<int, string> $columns
28     * @param array<string, string> $generatedExpressions
29     */
30    public function project(string $sourceSql, array $columns, array $generatedExpressions): string
31    {
32        if ($generatedExpressions === []) {
33            return $sourceSql;
34        }
35
36        $sourceAlias = $this->quoter->quote(self::SOURCE_ALIAS);
37        $selects = [];
38        foreach ($columns as $column) {
39            $quotedColumn = $this->quoter->quote($column);
40            $expression = $generatedExpressions[$column] ?? null;
41            $selects[] = $expression === null
42                ? "$sourceAlias.$quotedColumn AS $quotedColumn"
43                : "$expression AS $quotedColumn";
44        }
45
46        return 'SELECT ' . implode(', ', $selects) . " FROM ($sourceSql) AS $sourceAlias";
47    }
48}
49