packages/ztd-query-core/tests/Unit/Shadow/Mutation/Table/CreateTableMutationTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Table;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Exception\TableAlreadyExistsException;
11use ZtdQuery\Schema\TableDefinition;
12use ZtdQuery\Schema\TableDefinitionRegistry;
13use ZtdQuery\Shadow\Mutation\Table\CreateTableMutation;
14use ZtdQuery\Shadow\ShadowStore;
15
16#[UsesClass(TableAlreadyExistsException::class)]
17#[UsesClass(TableDefinition::class)]
18#[UsesClass(TableDefinitionRegistry::class)]
19#[UsesClass(ShadowStore::class)]
20#[CoversClass(CreateTableMutation::class)]
21#[UsesClass(\ZtdQuery\Schema\RowSet::class)]
22final class CreateTableMutationTest extends TestCase
23{
24    public function testApplyRegistersTableInSchema(): void
25    {
26        $registry = new TableDefinitionRegistry();
27        $store = new ShadowStore();
28
29        $definition = new TableDefinition(
30            ['id', 'name'],
31            ['id' => 'INT', 'name' => 'VARCHAR(255)'],
32            ['id'],
33            ['id'],
34            [],
35        );
36        $mutation = new CreateTableMutation('users', $definition, $registry, 'fixture statement');
37        $mutation->apply($store, []);
38
39        self::assertNotNull($registry->get('users'));
40        self::assertSame(['id', 'name'], $registry->get('users')->columns);
41    }
42
43    public function testApplyEnsuresTableInShadowStore(): void
44    {
45        $registry = new TableDefinitionRegistry();
46        $store = new ShadowStore();
47
48        $definition = new TableDefinition(
49            ['id'],
50            ['id' => 'INT'],
51            ['id'],
52            ['id'],
53            [],
54        );
55        $mutation = new CreateTableMutation('users', $definition, $registry, 'fixture statement');
56        $mutation->apply($store, []);
57
58        self::assertSame([], $store->get('users'));
59    }
60
61    public function testTableNameReturnsTableName(): void
62    {
63        $registry = new TableDefinitionRegistry();
64        $definition = new TableDefinition(
65            ['id'],
66            ['id' => 'INT'],
67            ['id'],
68            ['id'],
69            [],
70        );
71        $mutation = new CreateTableMutation('users', $definition, $registry, 'fixture statement');
72
73        self::assertSame('users', $mutation->tableName());
74    }
75
76    public function testApplyThrowsExceptionWhenTableExists(): void
77    {
78        $registry = new TableDefinitionRegistry();
79        $existingDefinition = new TableDefinition(
80            ['id'],
81            ['id' => 'INT'],
82            ['id'],
83            ['id'],
84            [],
85        );
86        $registry->register('users', $existingDefinition);
87        $store = new ShadowStore();
88
89        $newDefinition = new TableDefinition(
90            ['id', 'name'],
91            ['id' => 'INT', 'name' => 'VARCHAR(255)'],
92            ['id'],
93            ['id'],
94            [],
95        );
96        $mutation = new CreateTableMutation('users', $newDefinition, $registry, 'fixture statement');
97
98        try {
99            $mutation->apply($store, []);
100            self::fail('Expected duplicate virtual table creation to fail.');
101        } catch (TableAlreadyExistsException $exception) {
102            self::assertSame("Table 'users' already exists.", $exception->getMessage());
103            self::assertSame('fixture statement', $exception->getSql());
104        }
105    }
106
107    public function testApplyWithIfNotExistsSkipsWhenTableExists(): void
108    {
109        $registry = new TableDefinitionRegistry();
110        $originalDefinition = new TableDefinition(
111            ['id'],
112            ['id' => 'INT'],
113            ['id'],
114            ['id'],
115            [],
116        );
117        $registry->register('users', $originalDefinition);
118        $store = new ShadowStore();
119
120        $newDefinition = new TableDefinition(
121            ['id', 'name'],
122            ['id' => 'INT', 'name' => 'VARCHAR(255)'],
123            ['id'],
124            ['id'],
125            [],
126        );
127        $mutation = new CreateTableMutation('users', $newDefinition, $registry, 'fixture statement', true);
128        $mutation->apply($store, []);
129
130        $def = $registry->get('users');
131        self::assertNotNull($def);
132        self::assertSame(['id'], $def->columns);
133    }
134
135    public function testApplyWithIfNotExistsCreatesWhenTableDoesNotExist(): void
136    {
137        $registry = new TableDefinitionRegistry();
138        $store = new ShadowStore();
139
140        $definition = new TableDefinition(
141            ['id'],
142            ['id' => 'INT'],
143            ['id'],
144            ['id'],
145            [],
146        );
147        $mutation = new CreateTableMutation('users', $definition, $registry, 'fixture statement', true);
148        $mutation->apply($store, []);
149
150        self::assertNotNull($registry->get('users'));
151        self::assertSame(['id'], $registry->get('users')->columns);
152    }
153}
154