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