packages/ztd-query-postgres/tests/Unit/Rewrite/Transformer/Merge/RowActionsTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Rewrite\Transformer\Merge;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9
10#[CoversClass(\ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\RowActions::class)]
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Cte\HeaderParser::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Cte\IdentifierReferences::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Cte\PrefixMerge::class)]
14#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Cte\ShadowDependencies::class)]
15#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\ActionClause::class)]
16#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\BranchTokens::class)]
17#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\RelationTarget::class)]
18#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\StatementParts::class)]
19#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Relation\FromClause::class)]
20#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Relation\RelationReference::class)]
21#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Cte\PgSqlCteShadowComposer::class)]
22#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\PgSqlIdentifierQuoter::class)]
23#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::class)]
24#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeActionKind::class)]
25#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeClause::class)]
26#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeMatchKind::class)]
27#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeParser::class)]
28#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeStatement::class)]
29#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\Relation\PgSqlSelectRelationParser::class)]
30#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertRowRenderer::class)]
31#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertSelectRenderer::class)]
32#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\MatchConditions::class)]
33final class RowActionsTest extends TestCase
34{
35    public function testUnchangedRows(): void
36    {
37        $sql = 'MERGE INTO users u USING incoming s ON u.id = s.id WHEN MATCHED AND s.active THEN UPDATE SET name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name)';
38        $statement = (new \ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeParser())->parse($sql);
39
40        self::assertSame('SELECT "u"."id" AS "id", "u"."name" AS "name" FROM users AS "u" WHERE NOT (EXISTS (SELECT 1 FROM incoming s WHERE (u.id = s.id) AND (s.active)))', (new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\RowActions(new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\Postgres\Sql\PgSqlIdentifierQuoter(), new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertRowRenderer()))->unchangedRows($statement, ['id', 'name'], ['s.active', 'TRUE']));
41    }
42
43    public function testUpdatedRows(): void
44    {
45        $sql = 'MERGE INTO users u USING incoming s ON u.id = s.id WHEN MATCHED AND s.active THEN UPDATE SET name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name)';
46        $statement = (new \ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeParser())->parse($sql);
47
48        self::assertSame('SELECT "u"."id" AS "id", s.name AS "name" FROM users AS "u" JOIN incoming s ON (u.id = s.id) WHERE s.active', (new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\RowActions(new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\Postgres\Sql\PgSqlIdentifierQuoter(), new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertRowRenderer()))->updatedRows($sql, $statement, $statement->clauses[0], ['id', 'name'], [], 's.active'));
49    }
50
51    public function testInsertedRows(): void
52    {
53        $sql = 'MERGE INTO users u USING incoming s ON u.id = s.id WHEN MATCHED AND s.active THEN UPDATE SET name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name)';
54        $statement = (new \ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeParser())->parse($sql);
55
56        self::assertSame('SELECT s.id AS "id", s.name AS "name" FROM incoming s WHERE NOT EXISTS (SELECT 1 FROM users AS "u" WHERE u.id = s.id) AND (TRUE)', (new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\RowActions(new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\Postgres\Sql\PgSqlIdentifierQuoter(), new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertRowRenderer()))->insertedRows($sql, $statement, $statement->clauses[1], ['id', 'name'], [], [], [], 'TRUE'));
57    }
58    public function testModifiedRowsProjectsBothActionKindsInOrder(): void
59    {
60        $sql = 'MERGE INTO users u USING source s ON u.id = s.id WHEN MATCHED THEN UPDATE SET name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name)';
61        $statement = (new \ZtdQuery\Platform\Postgres\Sql\Merge\PgSqlMergeParser())->parse($sql);
62        $conditions = (new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\MatchConditions())->effectiveConditions($statement);
63        $actions = new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\Merge\RowActions(new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\Postgres\Sql\PgSqlIdentifierQuoter(), new \ZtdQuery\Platform\Postgres\Rewrite\Transformer\InsertRowRenderer());
64        $rows = $actions->modifiedRows($sql, $statement, ['id', 'name'], [], [], [], $conditions);
65        self::assertCount(2, $rows);
66        self::assertStringContainsString('s.name AS "name"', $rows[0]);
67        self::assertStringContainsString('s.id AS "id"', $rows[1]);
68    }
69}
70