packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/Query/JoinGroupingRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite\Query;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use SqlFaker\Generation\Token\ProductionOccurrence;
11use SqlFaker\Generation\Token\TerminalOccurrence;
12use SqlFaker\Generation\Token\TerminalSequence;
13use SqlFaker\MySql\Generation\Rewrite\Query\JoinGroupingRule;
14
15#[CoversClass(JoinGroupingRule::class)]
16#[UsesClass(ProductionOccurrence::class)]
17#[UsesClass(TerminalOccurrence::class)]
18#[UsesClass(TerminalSequence::class)]
19final class JoinGroupingRuleTest extends TestCase
20{
21 public function testRewriteKeepsNestedJoinConditionsWithTheirOwnOperands(): void
22 {
23 $a = new TerminalOccurrence('A', 10, [0], ['joined_table']);
24 $outer = new TerminalOccurrence('LEFT', 11, [0], ['joined_table']);
25 $b = new TerminalOccurrence('B', 12, [0, 1], ['joined_table', 'joined_table']);
26 $inner = new TerminalOccurrence('JOIN_SYM', 13, [0, 1], ['joined_table', 'joined_table']);
27 $c = new TerminalOccurrence('C', 14, [0, 1], ['joined_table', 'joined_table']);
28 $using = new TerminalOccurrence('USING', 15, [0], ['joined_table']);
29 $tokens = [$a, $outer, $b, $inner, $c, $using];
30 $input = new TerminalSequence($tokens, $tokens, [], [new ProductionOccurrence(0, null, 'joined_table', 3), new ProductionOccurrence(1, 0, 'joined_table', 4), new ProductionOccurrence(9, null, 'joined_table', 0)]);
31 $rule = new JoinGroupingRule();
32 $result = $rule->rewrite($input);
33 self::assertSame(['(', 'A', 'LEFT', '(', 'B', 'JOIN_SYM', 'C', ')', 'USING', ')'], $result->names());
34 self::assertSame($input->original, $result->original);
35 self::assertSame($input->productions, $result->productions);
36 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
37 self::assertSame($result, $rule->rewrite($result));
38 }
39
40 public function testRewriteGroupsAnOuterJoinEvenWhenItsLeftChildIsAlreadyGrouped(): void
41 {
42 $a = new TerminalOccurrence('A', 10, [0, 1], ['joined_table', 'joined_table']);
43 $b = new TerminalOccurrence('B', 11, [0], ['joined_table']);
44 $input = new TerminalSequence([$a, $b], [$a, $b], [], [new ProductionOccurrence(0, null, 'joined_table', 0), new ProductionOccurrence(1, 0, 'joined_table', 0)]);
45 $rule = new JoinGroupingRule();
46 $result = $rule->rewrite($input);
47 self::assertSame(['(', '(', 'A', ')', 'B', ')'], $result->names());
48 self::assertSame($result, $rule->rewrite($result));
49 self::assertCount(count($result->terminals), array_unique(array_map(static fn ($terminal): int => $terminal->id, $result->terminals)));
50 }
51
52 public function testRewritePreservesTokensWithoutJoinProductions(): void
53 {
54 $input = TerminalSequence::fromNames(['A', 'JOIN_SYM', 'B']);
55 self::assertSame($input, (new JoinGroupingRule())->rewrite($input));
56 }
57}
58