packages/sql-faker/tests/Unit/Sqlite/Generation/Rewrite/WithoutRowidRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\Sqlite\Generation\Rewrite;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Derivation\DerivationTrace;
11use SqlFaker\Generation\Token\TerminalSequence;
12use SqlFaker\Grammar\Model\NonTerminal;
13use SqlFaker\Grammar\Model\Production;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\Sqlite\Generation\Rewrite\WithoutRowidRule;
16
17#[CoversClass(WithoutRowidRule::class)]
18#[UsesClass(DerivationTrace::class)]
19#[UsesClass(NonTerminal::class)]
20#[UsesClass(Production::class)]
21#[UsesClass(Terminal::class)]
22#[UsesClass(TerminalSequence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
24#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
25final class WithoutRowidRuleTest extends TestCase
26{
27    public function testRewriteCompletesAKeyOnlyForWithoutRowidAndRetainsTheOriginalTrace(): void
28    {
29        $trace = new DerivationTrace('create_table_args');
30        $trace->expand(0, new Production([new NonTerminal('column'), new Terminal('ROWID_TABLE_OPTION')]), 0);
31        $trace->expand(0, new Production([new NonTerminal('columnname'), new NonTerminal('carglist')]), 0);
32        $trace->expand(0, new Production([new Terminal('ID')]), 0);
33        $trace->expand(1, new Production([]), 0);
34        $input = $trace->terminals();
35        $result = (new WithoutRowidRule())->rewrite($input);
36        self::assertSame(['ID', 'PRIMARY', 'KEY', 'ROWID_TABLE_OPTION'], $result->names());
37        self::assertSame(['create_table_args', 'column', 'carglist'], $result->terminals[1]->rules);
38        self::assertSame($input->original, $result->original);
39        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
40        self::assertSame($input->productions, $result->productions);
41    }
42
43    public function testRewriteRemovesAutoincrementAndPreservesAnExistingPrimaryKey(): void
44    {
45        $trace = new DerivationTrace('create_table_args');
46        $trace->expand(0, new Production([new Terminal('ID'), new Terminal('PRIMARY'), new Terminal('KEY'), new NonTerminal('autoinc'), new Terminal('ROWID_TABLE_OPTION')]), 0);
47        $trace->expand(3, new Production([new Terminal('AUTOINCR')]), 1);
48        self::assertSame(['ID', 'PRIMARY', 'KEY', 'ROWID_TABLE_OPTION'], (new WithoutRowidRule())->rewrite($trace->terminals())->names());
49    }
50
51    public function testPrimaryKeyLeavesASequenceWithoutAColumnUntouched(): void
52    {
53        $input = TerminalSequence::fromNames(['ID']);
54        self::assertSame($input, (new WithoutRowidRule())->primaryKey($input, 9));
55        self::assertSame($input, (new WithoutRowidRule())->rewrite($input));
56    }
57}
58