packages/sql-faker/tests/Unit/MySql/Generation/Rewrite/Expression/QuantifiedComparisonRuleTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\SqlFaker\MySql\Generation\Rewrite\Expression;
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\Generation\Token\ProductionOccurrence;
13use SqlFaker\Generation\Token\TerminalOccurrence;
14use SqlFaker\Generation\Token\TerminalSequence;
15use SqlFaker\Grammar\Model\NonTerminal;
16use SqlFaker\Grammar\Model\Production;
17use SqlFaker\Grammar\Model\Terminal;
18use SqlFaker\MySql\Generation\Rewrite\Expression\QuantifiedComparisonRule;
19
20#[CoversClass(QuantifiedComparisonRule::class)]
21#[UsesClass(DerivationTrace::class)]
22#[UsesClass(ProductionOccurrence::class)]
23#[UsesClass(TerminalOccurrence::class)]
24#[UsesClass(TerminalSequence::class)]
25#[UsesClass(NonTerminal::class)]
26#[UsesClass(Production::class)]
27#[UsesClass(Terminal::class)]
28final class QuantifiedComparisonRuleTest extends TestCase
29{
30 #[DataProvider('providerComparisons')]
31 public function testRewriteRestrictsNullSafeEqualityToScalarComparisons(string $scope, string $context, string $operator, string $quantifier, string $expected): void
32 {
33 $trace = new DerivationTrace($scope);
34 $trace->expand(0, new Production([new Terminal('LEFT'), new NonTerminal('comp_op'), new NonTerminal($context), new Terminal('RIGHT')]), 0);
35 $trace->expand(1, new Production([new Terminal($operator)]), 0);
36 $trace->expand(2, new Production([new Terminal($quantifier)]), 0);
37 $input = $trace->terminals();
38 $rule = new QuantifiedComparisonRule();
39 $result = $rule->rewrite($input);
40 self::assertSame(['LEFT', $expected, $quantifier, 'RIGHT'], $result->names());
41 self::assertSame($input->terminals[1]->id, $result->terminals[1]->id);
42 self::assertSame($input->terminals[1]->ancestors, $result->terminals[1]->ancestors);
43 self::assertSame($input->original, $result->original);
44 self::assertSame($input->productions, $result->productions);
45 self::assertSame($result, $rule->rewrite($result));
46 }
47
48 /**
49 * @return iterable<array{string, string, string, string, string}>
50 */
51 public static function providerComparisons(): iterable
52 {
53 foreach (['ALL', 'ANY_SYM'] as $quantifier) {
54 yield ['bool_pri', 'all_or_any', 'EQUAL_SYM', $quantifier, 'EQ'];
55 yield ['bool_pri', 'predicate', 'EQUAL_SYM', $quantifier, 'EQUAL_SYM'];
56 yield ['ordinary', 'all_or_any', 'EQUAL_SYM', $quantifier, 'EQUAL_SYM'];
57 foreach (['EQ', 'GE', 'GT_SYM', 'LE', 'LT', 'NE'] as $operator) {
58 yield ['bool_pri', 'all_or_any', $operator, $quantifier, $operator];
59 }
60 }
61 }
62
63 public function testRewritePreservesAnEmptyOrAbsentOperator(): void
64 {
65 $input = new TerminalSequence([], [], [], [
66 new ProductionOccurrence(0, null, 'bool_pri', 0),
67 new ProductionOccurrence(1, 0, 'all_or_any', 0),
68 new ProductionOccurrence(2, 0, 'comp_op', 0),
69 new ProductionOccurrence(3, null, 'bool_pri', 0),
70 new ProductionOccurrence(4, 3, 'all_or_any', 0),
71 ]);
72 self::assertSame($input, (new QuantifiedComparisonRule())->rewrite($input));
73 }
74}
75