packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Routine/RangeFunctionOrdinalityRuleTest.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\RangeFunctionOrdinalityRule;
15
16#[CoversClass(RangeFunctionOrdinalityRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class RangeFunctionOrdinalityRuleTest extends TestCase
21{
22 #[DataProvider('providerScopes')]
23 public function testRewriteOnlyRemovesOrdinalityBesideItsOwnTypedColumnList(string $function, string $alias, string $columns, int $columnParent, bool $ordinality, bool $remove): void
24 {
25 $call = new TerminalOccurrence('IDENT', 10, [0, 1], ['table_ref', $function]);
26 $with = new TerminalOccurrence('WITH_LA', 11, [0, 1, 2], ['table_ref', $function, 'opt_ordinality']);
27 $ordinal = new TerminalOccurrence('ORDINALITY', 12, [0, 1, 2], ['table_ref', $function, 'opt_ordinality']);
28 $column = new TerminalOccurrence('IDENT', 13, [0, 3, 4], ['table_ref', $alias, $columns]);
29 $terminals = [$call, ...($ordinality ? [$with, $ordinal] : []), $column];
30 $input = new TerminalSequence($terminals, $terminals, [], [
31 new ProductionOccurrence(0, null, 'table_ref', 2),
32 new ProductionOccurrence(1, 0, $function, 0),
33 new ProductionOccurrence(2, 1, 'opt_ordinality', $ordinality ? 0 : 1),
34 new ProductionOccurrence(3, 0, $alias, 2),
35 new ProductionOccurrence(4, $columnParent, $columns, 0),
36 ]);
37 $rule = new RangeFunctionOrdinalityRule();
38 $result = $rule->rewrite($input);
39 self::assertSame($remove ? [$call, $column] : $terminals, $result->terminals);
40 self::assertSame($input->original, $result->original);
41 self::assertSame($input->productions, $result->productions);
42 self::assertSame($result, $rule->rewrite($result));
43 }
44
45 /**
46 * @return iterable<string, array{string, string, string, int, bool, bool}>
47 */
48 public static function providerScopes(): iterable
49 {
50 yield 'typed alias' => ['func_table', 'func_alias_clause', 'TableFuncElementList', 3, true, true];
51 yield 'no ordinality' => ['func_table', 'func_alias_clause', 'TableFuncElementList', 3, false, false];
52 yield 'plain relation' => ['relation_expr', 'func_alias_clause', 'TableFuncElementList', 3, true, false];
53 yield 'other alias scope' => ['func_table', 'opt_alias_clause', 'TableFuncElementList', 3, true, false];
54 yield 'column names only' => ['func_table', 'func_alias_clause', 'name_list', 3, true, false];
55 yield 'definitions inside rows from' => ['func_table', 'func_alias_clause', 'TableFuncElementList', 1, true, false];
56 }
57}
58