packages/ztd-query-sqlite/tests/Unit/Shadow/Mutation/Table/Alter/RenameResolverTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Table\Alter;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Platform\Sqlite\Shadow\Mutation\Table\Alter\RenameResolver;
11use ZtdQuery\Platform\Sqlite\Shadow\Mutation\Table\AlterTableMutation;
12use ZtdQuery\Schema\Key\ForeignKeyDefinition;
13use ZtdQuery\Schema\Key\ReferentialAction;
14use ZtdQuery\Schema\TableDefinition;
15use ZtdQuery\Schema\TableDefinitionRegistry;
16use ZtdQuery\Shadow\ShadowStore;
17
18#[CoversClass(RenameResolver::class)]
19#[UsesClass(AlterTableMutation::class)]
20#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Table\Alter\AlteredTableProjection::class)]
21#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Table\Alter\ColumnDefinitionEditor::class)]
22#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Resolution\MutationTableLookup::class)]
23#[UsesClass(\ZtdQuery\Platform\Sqlite\Sql\Alter\AlterOperationParser::class)]
24#[UsesClass(\ZtdQuery\Platform\Sqlite\Sql\SqliteIdentifierQuoter::class)]
25#[UsesClass(\ZtdQuery\Platform\Sqlite\Sql\SqliteLexerProfile::class)]
26final class RenameResolverTest extends TestCase
27{
28 public function testResolveAlterRenameTableMovesSchemaAndRowsAtApply(): void
29 {
30 $registry = new TableDefinitionRegistry();
31 $definition = new TableDefinition(['id', 'name'], ['id' => 'INTEGER', 'name' => 'TEXT'], ['id'], ['id'], []);
32 $registry->register('users', $definition);
33 $store = new ShadowStore();
34 $store->set('users', [['id' => 1, 'name' => 'Alice']]);
35 $mutation = (new RenameResolver($registry))->resolveAlterRenameTable('ALTER TABLE users RENAME TO people', 'users', 'people');
36 self::assertInstanceOf(AlterTableMutation::class, $mutation);
37 self::assertSame('SELECT "id", "name" FROM "users"', $mutation->resultSelect());
38 $mutation->apply($store, [['id' => 1, 'name' => 'Alice']]);
39 self::assertFalse($registry->has('users'));
40 self::assertTrue($registry->has('people'));
41 self::assertFalse($store->has('users'));
42 self::assertSame([['id' => 1, 'name' => 'Alice']], $store->get('people'));
43 }
44
45 public function testResolveAlterRenameColumnProjectsNewName(): void
46 {
47 $registry = new TableDefinitionRegistry();
48 $definition = new TableDefinition(['id', 'name'], ['id' => 'INTEGER', 'name' => 'TEXT'], ['id'], ['id'], []);
49 $registry->register('users', $definition);
50 $store = new ShadowStore();
51 $store->set('users', [['id' => 1, 'name' => 'Alice']]);
52 $mutation = (new RenameResolver($registry))->resolveAlterRenameColumn('ALTER TABLE users RENAME COLUMN NAME TO label', 'users', 'NAME TO label');
53 self::assertInstanceOf(AlterTableMutation::class, $mutation);
54 self::assertSame('SELECT "id", "name" AS "label" FROM "users"', $mutation->resultSelect());
55 $mutation->apply($store, [['id' => 1, 'label' => 'Alice']]);
56 self::assertSame(['id', 'label'], $registry->get('users')?->columns);
57 }
58
59 public function testResolveAlterRenameColumnRejectsExistingTargetName(): void
60 {
61 $registry = new TableDefinitionRegistry();
62 $definition = new TableDefinition(['id', 'name'], ['id' => 'INTEGER', 'name' => 'TEXT'], ['id'], ['id'], []);
63 $registry->register('users', $definition);
64 $store = new ShadowStore();
65 $store->set('users', [['id' => 1, 'name' => 'Alice']]);
66 $this->expectException(\ZtdQuery\Exception\ColumnAlreadyExistsException::class);
67 (new RenameResolver($registry))->resolveAlterRenameColumn('ALTER TABLE users RENAME COLUMN name TO id', 'users', 'name TO id');
68 }
69
70 public function testDefinitionWithRenamedColumnUpdatesKeyAndValueMaps(): void
71 {
72 $definition = new TableDefinition(
73 ['parent', 'label'],
74 ['parent' => 'INTEGER', 'label' => 'TEXT'],
75 ['parent'],
76 ['parent'],
77 ['unique_parent' => ['parent']],
78 ['parent' => new \ZtdQuery\Schema\ColumnDeclaration(\ZtdQuery\Schema\ColumnTypeFamily::INTEGER, 'INTEGER')],
79 ['parent' => '0'],
80 ['parent' => \ZtdQuery\Schema\Key\IdentityGenerationStrategy::MaxValue],
81 ['parent' => '(1)'],
82 ['fk' => new ForeignKeyDefinition(['parent'], 'other', ['id'], ReferentialAction::Cascade, ReferentialAction::SetNull)],
83 );
84 $result = (new RenameResolver(new TableDefinitionRegistry()))->definitionWithRenamedColumn($definition, 'parent', 'parent_id');
85 self::assertSame(['parent_id', 'label'], $result->columns);
86 self::assertSame(['parent_id'], $result->primaryKeys);
87 self::assertSame(['parent_id'], $result->notNullColumns);
88 self::assertSame(['unique_parent' => ['parent_id']], $result->uniqueConstraints);
89 self::assertSame(['parent_id' => '0'], $result->columnDefaults);
90 self::assertSame(['parent_id' => '(1)'], $result->generatedExpressions);
91 self::assertSame(['parent_id'], array_keys($result->typedColumns));
92 self::assertSame(['parent_id'], array_keys($result->identityStrategies));
93 self::assertSame(['parent_id'], $result->foreignKeys['fk']->columns);
94 self::assertSame(['id'], $result->foreignKeys['fk']->referencedColumns);
95 self::assertSame(ReferentialAction::Cascade, $result->foreignKeys['fk']->onDelete);
96 }
97
98}
99