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

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\PostgreSql\Generation\Rewrite\Routine;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlFaker\Generation\Token\ProductionOccurrence;
12use SqlFaker\Generation\Token\TerminalOccurrence;
13use SqlFaker\Generation\Token\TerminalSequence;
14use SqlFaker\PostgreSql\Generation\Rewrite\Routine\WithinGroupRule;
15
16#[CoversClass(WithinGroupRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class WithinGroupRuleTest extends TestCase
21{
22    #[DataProvider('providerClauses')]
23    public function testRewriteRetainsWithinGroupAndNestedFunctions(bool $within): void
24    {
25        $productions = [new ProductionOccurrence(0, null, 'func_expr', 0), new ProductionOccurrence(1, 0, 'func_application', 1), new ProductionOccurrence(2, 1, 'opt_sort_clause', 0), new ProductionOccurrence(3, 0, 'within_group_clause', 0), new ProductionOccurrence(4, 1, 'func_application', 2), new ProductionOccurrence(9, null, 'func_expr', 1)];
26        $tokens = [
27            new TerminalOccurrence('F', 10, [0, 1], ['func_expr', 'func_application']),
28            new TerminalOccurrence('DISTINCT', 11, [0, 1], ['func_expr', 'func_application']),
29            new TerminalOccurrence('VARIADIC', 12, [0, 1], ['func_expr', 'func_application']),
30            new TerminalOccurrence('DISTINCT', 13, [0, 1, 4], ['func_expr', 'func_application', 'func_application']),
31            new TerminalOccurrence('ORDER', 14, [0, 1, 2], ['func_expr', 'func_application', 'opt_sort_clause']),
32        ];
33        $clause = new TerminalOccurrence('WITHIN', 15, [0, 3], ['func_expr', 'within_group_clause']);
34        $tokens = [...$tokens, ...($within ? [$clause] : [])];
35        $input = new TerminalSequence($tokens, $tokens, [], $productions);
36        $rule = new WithinGroupRule();
37        $result = $rule->rewrite($input);
38        self::assertSame($within ? [$tokens[0], $tokens[3], $clause] : $tokens, $result->terminals);
39        self::assertSame($input->original, $result->original);
40        self::assertSame($input->productions, $result->productions);
41        self::assertSame($result->terminals, $rule->rewrite($result)->terminals);
42    }
43
44    /**
45     * @return list<array{bool}>
46     */
47    public static function providerClauses(): array
48    {
49        return [[true], [false]];
50    }
51
52    public function testRewriteKeepsFunctionsWithoutWithinGroupMetadata(): void
53    {
54        $input = TerminalSequence::fromNames(['DISTINCT', 'VARIADIC', 'ORDER']);
55        self::assertSame($input, (new WithinGroupRule())->rewrite($input));
56    }
57}
58