packages/ztd-query-mysql/tests/Unit/Shadow/Mutation/Upsert/ExpressionReaderTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Upsert;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\MySql\Shadow\Mutation\Upsert\ExpressionReader;
10
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Shadow\Mutation\Upsert\LiteralReader::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Shadow\Mutation\Upsert\StringLiteral::class)]
14#[CoversClass(ExpressionReader::class)]
15final class ExpressionReaderTest extends TestCase
16{
17    public function testParseOrEvaluatesTheConsumedExpression(): void
18    {
19        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('1 OR 0', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
20        $index = 0;
21        $expression = (new ExpressionReader())->parseOr('1 OR 0', 'users', null, $tokens, $index);
22        self::assertSame(true, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
23        self::assertSame(count($tokens), $index);
24    }
25
26    public function testParseAndEvaluatesTheConsumedExpression(): void
27    {
28        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('1 AND 0', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
29        $index = 0;
30        $expression = (new ExpressionReader())->parseAnd('1 AND 0', 'users', null, $tokens, $index);
31        self::assertSame(false, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
32        self::assertSame(count($tokens), $index);
33    }
34
35    public function testParseComparisonEvaluatesTheConsumedExpression(): void
36    {
37        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('1 < 2', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
38        $index = 0;
39        $expression = (new ExpressionReader())->parseComparison('1 < 2', 'users', null, $tokens, $index);
40        self::assertSame(true, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
41        self::assertSame(count($tokens), $index);
42    }
43
44    public function testParseAdditiveEvaluatesTheConsumedExpression(): void
45    {
46        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('1 + 2 * 3', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
47        $index = 0;
48        $expression = (new ExpressionReader())->parseAdditive('1 + 2 * 3', 'users', null, $tokens, $index);
49        self::assertSame(7, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
50        self::assertSame(count($tokens), $index);
51    }
52
53    public function testParseMultiplicativeEvaluatesTheConsumedExpression(): void
54    {
55        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('3 * 2', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
56        $index = 0;
57        $expression = (new ExpressionReader())->parseMultiplicative('3 * 2', 'users', null, $tokens, $index);
58        self::assertSame(6, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
59        self::assertSame(count($tokens), $index);
60    }
61
62    public function testParseUnaryEvaluatesTheConsumedExpression(): void
63    {
64        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('-2', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
65        $index = 0;
66        $expression = (new ExpressionReader())->parseUnary('-2', 'users', null, $tokens, $index);
67        self::assertSame(-2, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
68        self::assertSame(count($tokens), $index);
69    }
70
71    public function testParsePrimaryEvaluatesTheConsumedExpression(): void
72    {
73        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize("'a''b'", \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
74        $index = 0;
75        $expression = (new ExpressionReader())->parsePrimary("'a''b'", 'users', null, $tokens, $index);
76        self::assertSame("a'b", $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
77        self::assertSame(count($tokens), $index);
78    }
79
80    public function testParseColumnReferenceEvaluatesTheConsumedExpression(): void
81    {
82        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('users.score', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
83        $index = 0;
84        $expression = (new ExpressionReader())->parseColumnReference('users.score', 'users', null, $tokens, $index);
85        self::assertSame(7, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
86        self::assertSame(count($tokens), $index);
87    }
88
89    public function testParseValuesReferenceReadsIncomingColumn(): void
90    {
91        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('(score)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
92        $index = 0;
93        $expression = (new ExpressionReader())->parseValuesReference('(score)', $tokens, $index);
94        self::assertSame(9, $expression->evaluate(['score' => 7], ['score' => 9], 'users'));
95        self::assertSame(3, $index);
96    }
97
98    public function testColumnSourceDistinguishesIncomingAlias(): void
99    {
100        $reader = new ExpressionReader();
101        self::assertSame(\ZtdQuery\Shadow\Mutation\UpsertColumnSource::Existing, $reader->columnSource('users.score', 'users', 'users', 'incoming'));
102        self::assertSame(\ZtdQuery\Shadow\Mutation\UpsertColumnSource::Incoming, $reader->columnSource('incoming.score', 'incoming', 'users', 'incoming'));
103    }
104
105    public function testComparisonOperatorConsumesCompositeSymbols(): void
106    {
107        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('!=', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
108        $index = 0;
109        self::assertSame(\ZtdQuery\Shadow\Mutation\UpsertExpressionKind::NotEqual, (new ExpressionReader())->comparisonOperator('!=', $tokens, $index));
110        self::assertSame(2, $index);
111    }
112
113}
114