packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/SubqueryContextRuleTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite;
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\MySql\Generation\Rewrite\SubqueryContextRule;
15
16#[CoversClass(SubqueryContextRule::class)]
17#[UsesClass(ProductionOccurrence::class)]
18#[UsesClass(TerminalOccurrence::class)]
19#[UsesClass(TerminalSequence::class)]
20final class SubqueryContextRuleTest extends TestCase
21{
22    #[DataProvider('providerScopes')]
23    public function testRewriteChangesOnlyTheForbiddenSubqueryOperand(string $statement, bool $replace): void
24    {
25        $left = new TerminalOccurrence('IDENT', 3, [0, 1], [$statement, 'bool_pri']);
26        $subquery = new TerminalOccurrence('SUBQUERY', 4, [0, 1, 2], [$statement, 'bool_pri', 'subquery']);
27        $other = new TerminalOccurrence('IDENT', 5, [0], [$statement]);
28        $input = new TerminalSequence([$left, $subquery, $other], [$left, $subquery, $other], [], [new ProductionOccurrence(0, null, $statement, 0), new ProductionOccurrence(1, 0, 'bool_pri', 0), new ProductionOccurrence(2, 1, 'subquery', 0), new ProductionOccurrence(6, 0, 'subquery', 0)]);
29        $rule = new SubqueryContextRule();
30        $result = $rule->rewrite($input);
31        self::assertSame($replace ? ['NUM', 'IDENT'] : ['IDENT', 'SUBQUERY', 'IDENT'], $result->names());
32        self::assertSame($input->original, $result->original);
33        self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
34        self::assertSame($result, $rule->rewrite($result));
35    }
36
37    /**
38     * @return list<array{string, bool}>
39     */
40    public static function providerScopes(): array
41    {
42        return [['handler_stmt', true], ['purge', true], ['install_stmt', true], ['part_type_def', true], ['opt_sub_part', true], ['select_stmt', false], ['create_table_stmt', false]];
43    }
44}
45