packages/ztd-query-core/tests/Unit/Rewrite/RewritePlanTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Rewrite;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use RuntimeException;
11use ZtdQuery\Exception\UnsupportedSqlException;
12use ZtdQuery\Rewrite\AffectedRowsMode;
13use ZtdQuery\Rewrite\QueryKind;
14use ZtdQuery\Rewrite\ReturningProjection;
15use ZtdQuery\Rewrite\RewritePlan;
16use ZtdQuery\Schema\Key\CandidateKeySet;
17use ZtdQuery\Shadow\Mutation\Row\InsertMutation;
18
19#[UsesClass(InsertMutation::class)]
20#[UsesClass(CandidateKeySet::class)]
21#[UsesClass(ReturningProjection::class)]
22#[CoversClass(RewritePlan::class)]
23#[UsesClass(UnsupportedSqlException::class)]
24#[UsesClass(\ZtdQuery\Shadow\Mutation\ConflictSearch::class)]
25#[UsesClass(\ZtdQuery\Shadow\Mutation\RowConstraints::class)]
26final class RewritePlanTest extends TestCase
27{
28 public function testKindSqlKindPlanHoldsSqlKindAndMutation(): void
29 {
30 $mutation = new InsertMutation('users');
31 $plan = new RewritePlan('SELECT 1', QueryKind::READ, $mutation);
32
33 self::assertSame('SELECT 1', $plan->sql());
34 self::assertSame(QueryKind::READ, $plan->kind());
35 self::assertSame($mutation, $plan->mutation());
36 }
37
38 public function testMutationPlanWithoutMutation(): void
39 {
40 $plan = new RewritePlan('SELECT 1', QueryKind::READ);
41
42 self::assertNull($plan->mutation());
43 }
44
45 public function testAffectedRowsModeReturningProjectionAffectedRowsModePlanCarriesReturningAndAffectedRowsMetadata(): void
46 {
47 $projection = ReturningProjection::fromItems([['source' => 'id', 'output' => null]]);
48 $plan = new RewritePlan(
49 'SELECT 1 AS id',
50 QueryKind::WRITE_SIMULATED,
51 new InsertMutation('users'),
52 $projection,
53 AffectedRowsMode::Matched,
54 );
55
56 self::assertSame($projection, $plan->returningProjection());
57 self::assertSame(AffectedRowsMode::Matched, $plan->affectedRowsMode());
58 }
59
60 public function testSqlKeepsTheStatementThePlanIsFor(): void
61 {
62 self::assertSame('SELECT 1', (new RewritePlan('SELECT 1', QueryKind::READ))->sql());
63 }
64
65 public function testReturningProjectionIsNothingWherePlanCarriesNone(): void
66 {
67 self::assertNull((new RewritePlan('SELECT 1', QueryKind::READ))->returningProjection());
68 }
69
70 public function testRequireMutationAnswersTheMutationTheWriteWasSimulatedAs(): void
71 {
72 $mutation = new InsertMutation('users');
73 $plan = new RewritePlan('SELECT 1', QueryKind::WRITE_SIMULATED, $mutation);
74
75 self::assertSame($mutation, $plan->requireMutation());
76 }
77
78 public function testRequireMutationRefusesAPlanThatCarriesNone(): void
79 {
80 $this->expectException(RuntimeException::class);
81
82 (new RewritePlan('SELECT 1', QueryKind::WRITE_SIMULATED))->requireMutation();
83 }
84}
85