packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/LimitOffsetRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\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\PostgreSql\Generation\Rewrite\LimitOffsetRule;
15
16#[CoversClass(LimitOffsetRule::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 LimitOffsetRuleTest extends TestCase
25{
26    public function testRewriteChangesOnlyTheDiagnosticComma(): void
27    {
28        $trace = new DerivationTrace('limit_clause');
29        $trace->expand(0, new Production([new Terminal('LIMIT'), new Terminal('ICONST'), new Terminal(','), new NonTerminal('select_offset_value')]), 1);
30        $trace->expand(3, new Production([new Terminal('ICONST')]), 0);
31        $input = $trace->terminals();
32        $result = (new LimitOffsetRule())->rewrite($input);
33        self::assertSame(['LIMIT', 'ICONST', 'OFFSET', 'ICONST'], $result->names());
34        self::assertSame($input->terminals[3], $result->terminals[3]);
35        self::assertSame($input->original, $result->original);
36        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
37    }
38
39    public function testRewriteRetainsAnExistingSeparateOffset(): void
40    {
41        $trace = new DerivationTrace('select_limit');
42        $trace->expand(0, new Production([new NonTerminal('limit_clause'), new NonTerminal('offset_clause')]), 0);
43        $trace->expand(0, new Production([new Terminal('LIMIT'), new Terminal('ALL'), new Terminal(','), new NonTerminal('select_offset_value')]), 1);
44        $trace->expand(3, new Production([new Terminal('REMOVED')]), 0);
45        $trace->expand(4, new Production([new Terminal('OFFSET'), new Terminal('KEPT')]), 0);
46        self::assertSame(['LIMIT', 'ALL', 'OFFSET', 'KEPT'], (new LimitOffsetRule())->rewrite($trace->terminals())->names());
47    }
48}
49