packages/sql-faker/tests/Unit/Sqlite/Generation/Rewrite/JoinRuleTest.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\Grammar\Model\NonTerminal;
12use SqlFaker\Grammar\Model\Production;
13use SqlFaker\Grammar\Model\Terminal;
14use SqlFaker\Sqlite\Generation\Rewrite\JoinRule;
15
16#[CoversClass(JoinRule::class)]
17#[UsesClass(DerivationTrace::class)]
18#[UsesClass(NonTerminal::class)]
19#[UsesClass(Production::class)]
20#[UsesClass(Terminal::class)]
21#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
22#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
24final class JoinRuleTest extends TestCase
25{
26    public function testRewriteMarksOnlyDirectModifierNames(): void
27    {
28        $trace = new DerivationTrace('root');
29        $trace->expand(0, new Production([new NonTerminal('joinop'), new NonTerminal('nm')]), 0);
30        $trace->expand(0, new Production([new Terminal('JOIN_KW'), new NonTerminal('nm'), new Terminal('JOIN')]), 2);
31        $trace->expand(1, new Production([new Terminal('ID')]), 0);
32        $trace->expand(3, new Production([new Terminal('ID')]), 0);
33        $input = $trace->terminals();
34        $result = (new JoinRule())->rewrite($input);
35        self::assertSame(['JOIN_KW', 'JOIN_MODIFIER', 'JOIN', 'ID'], $result->names());
36        self::assertSame($input->terminals[3], $result->terminals[3]);
37    }
38
39    public function testRewriteRemovesConditionsOnlyWhenTheCorrespondingPrefixIsEmpty(): void
40    {
41        $trace = new DerivationTrace('seltablist');
42        $trace->expand(0, new Production([new NonTerminal('stl_prefix'), new Terminal('ID'), new NonTerminal('on_using')]), 0);
43        $trace->expand(0, new Production([]), 0);
44        $trace->expand(1, new Production([new Terminal('ON'), new Terminal('INTEGER')]), 1);
45        $input = $trace->terminals();
46        $result = (new JoinRule())->rewrite($input);
47        self::assertSame(['ID'], $result->names());
48        self::assertSame($input->productions, $result->productions);
49        self::assertSame($input->original, $result->original);
50        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
51    }
52
53    public function testRewriteKeepsConditionsOfAJoinedTable(): void
54    {
55        $trace = new DerivationTrace('seltablist');
56        $trace->expand(0, new Production([new NonTerminal('stl_prefix'), new Terminal('ID'), new NonTerminal('on_using')]), 0);
57        $trace->expand(0, new Production([new Terminal('ID'), new Terminal('JOIN')]), 1);
58        $trace->expand(3, new Production([new Terminal('ON'), new Terminal('INTEGER')]), 1);
59        $input = $trace->terminals();
60        self::assertSame($input, (new JoinRule())->rewrite($input));
61    }
62}
63