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