packages/ztd-query-core/tests/Unit/Shadow/Mutation/DataMutationTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation;
6
7use PHPUnit\Framework\Attributes\CoversNothing;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Schema\Key\ForeignKeyDefinition;
11use ZtdQuery\Schema\Key\ReferentialAction;
12use ZtdQuery\Schema\TableDefinition;
13use ZtdQuery\Schema\TableDefinitionRegistry;
14use ZtdQuery\Shadow\Mutation\Row\DeleteMutation;
15use ZtdQuery\Shadow\Mutation\Row\InsertMutation;
16use ZtdQuery\Shadow\Mutation\Row\MultiDeleteMutation;
17use ZtdQuery\Shadow\Mutation\Row\MultiUpdateMutation;
18use ZtdQuery\Shadow\Mutation\Row\ReplaceMutation;
19use ZtdQuery\Shadow\Mutation\Row\UpdateMutation;
20use ZtdQuery\Shadow\Mutation\ShadowMutation;
21use ZtdQuery\Shadow\Mutation\Table\CreateTableMutation;
22use ZtdQuery\Shadow\Mutation\Table\MultiTruncateMutation;
23use ZtdQuery\Shadow\Mutation\Table\SynchronizeMutation;
24use ZtdQuery\Shadow\Mutation\Table\TruncateMutation;
25use ZtdQuery\Shadow\Mutation\UpsertMutation;
26use ZtdQuery\Shadow\ReferentialIntegrityEnforcer;
27use ZtdQuery\Shadow\ShadowStore;
28
29#[CoversNothing]
30final class DataMutationTest extends TestCase
31{
32 #[DataProvider('providerRowChangingMutation')]
33 public function testAMutationThatChangesRowsCarriesItsConsequencesToTheChildren(
34 ShadowMutation $mutation,
35 ): void {
36 $registry = new TableDefinitionRegistry();
37 $registry->register('parents', new TableDefinition(['id'], [], ['id'], [], []));
38 $registry->register('children', new TableDefinition(['id', 'parent_id'], [], ['id'], [], [], foreignKeys: [
39 'fk' => new ForeignKeyDefinition(['parent_id'], 'parents', ['id'], ReferentialAction::Cascade),
40 ]));
41 $before = new ShadowStore();
42 $before->set('parents', [['id' => 1]]);
43 $before->set('children', [['id' => 10, 'parent_id' => 1]]);
44 $after = $before->snapshot();
45 $after->set('parents', []);
46
47 (new ReferentialIntegrityEnforcer($registry))->synchronize($before, $after, $mutation, [], 'SQL');
48
49 self::assertSame([], $after->get('children'));
50 }
51
52 /**
53 * @return iterable<string, array{ShadowMutation}>
54 */
55 public static function providerRowChangingMutation(): iterable
56 {
57 yield 'insert' => [new InsertMutation('parents')];
58 yield 'update' => [new UpdateMutation('parents', ['id'])];
59 yield 'delete' => [new DeleteMutation('parents', ['id'])];
60 yield 'replace' => [new ReplaceMutation('parents')];
61 yield 'upsert' => [new UpsertMutation('parents', ['id'])];
62 yield 'truncate' => [new TruncateMutation('parents')];
63 yield 'multi update' => [new MultiUpdateMutation([])];
64 yield 'multi delete' => [new MultiDeleteMutation([])];
65 yield 'multi truncate' => [new MultiTruncateMutation([])];
66 yield 'synchronize' => [new SynchronizeMutation('parents')];
67 }
68
69 public function testAMutationThatChangesNoRowsCarriesNothingToTheChildren(): void
70 {
71 $registry = new TableDefinitionRegistry();
72 $registry->register('parents', new TableDefinition(['id'], [], ['id'], [], []));
73 $registry->register('children', new TableDefinition(['id', 'parent_id'], [], ['id'], [], [], foreignKeys: [
74 'fk' => new ForeignKeyDefinition(['parent_id'], 'parents', ['id'], ReferentialAction::Cascade),
75 ]));
76 $before = new ShadowStore();
77 $before->set('parents', [['id' => 1]]);
78 $before->set('children', [['id' => 10, 'parent_id' => 1]]);
79 $after = $before->snapshot();
80 $after->set('parents', []);
81 $mutation = new CreateTableMutation(
82 'extra',
83 new TableDefinition(['id'], [], ['id'], [], []),
84 $registry,
85 'CREATE TABLE extra (id INT)',
86 );
87
88 (new ReferentialIntegrityEnforcer($registry))->synchronize($before, $after, $mutation, [], 'SQL');
89
90 self::assertSame([['id' => 10, 'parent_id' => 1]], $after->get('children'));
91 }
92}
93