packages/sql-faker/tests/Unit/PostgreSql/Generation/Rewrite/Routine/TableFunctionRuleTest.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\Derivation\DerivationTrace;
12use SqlFaker\Grammar\Model\NonTerminal;
13use SqlFaker\Grammar\Model\Production;
14use SqlFaker\Grammar\Model\Terminal;
15use SqlFaker\PostgreSql\Generation\Rewrite\Routine\TableFunctionRule;
16
17#[CoversClass(TableFunctionRule::class)]
18#[UsesClass(DerivationTrace::class)]
19#[UsesClass(NonTerminal::class)]
20#[UsesClass(Production::class)]
21#[UsesClass(Terminal::class)]
22#[UsesClass(\SqlFaker\Generation\Token\ProductionOccurrence::class)]
23#[UsesClass(\SqlFaker\Generation\Token\TerminalOccurrence::class)]
24#[UsesClass(\SqlFaker\Generation\Token\TerminalSequence::class)]
25final class TableFunctionRuleTest extends TestCase
26{
27 /**
28 * @param list<string> $mode
29 * @param list<string> $expected
30 */
31 #[DataProvider('providerModes')]
32 public function testRewriteRestrictsOnlyInputArgumentsOfTableFunctions(array $mode, array $expected, bool $table, string $parameters): void
33 {
34 $trace = new DerivationTrace('CreateFunctionStmt');
35 $trace->expand(0, new Production([new NonTerminal($parameters), new NonTerminal($table ? 'table_func_column_list' : 'func_return')]), 0);
36 $trace->expand(0, new Production([new Terminal('('), new NonTerminal('func_arg'), new Terminal(')')]), 0);
37 $trace->expand(1, new Production([new NonTerminal('arg_class'), new Terminal('IDENT'), new Terminal('INT_P')]), 0);
38 $trace->expand(1, new Production(array_map(static fn (string $name): Terminal => new Terminal($name), $mode)), 0);
39 $trace->expand(count($mode) + 4, new Production([new Terminal('INT_P')]), 0);
40 $input = $trace->terminals();
41 $rule = new TableFunctionRule();
42 $result = $rule->rewrite($input);
43 self::assertSame(['(', ...$expected, 'IDENT', 'INT_P', ')', 'INT_P'], $result->names());
44 self::assertSame($input->original, $result->original);
45 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
46 self::assertSame($result, $rule->rewrite($result));
47 }
48
49 /**
50 * @return iterable<array{list<string>, list<string>, bool, string}>
51 */
52 public static function providerModes(): iterable
53 {
54 foreach ([['OUT_P'], ['INOUT'], ['IN_P', 'OUT_P']] as $mode) {
55 yield [$mode, ['IN_P'], true, 'func_args_with_defaults'];
56 yield [$mode, $mode, false, 'func_args_with_defaults'];
57 yield [$mode, $mode, true, 'func_args'];
58 }
59 foreach ([[], ['IN_P'], ['VARIADIC']] as $mode) {
60 yield [$mode, $mode, true, 'func_args_with_defaults'];
61 }
62 }
63}
64