packages/ztd-query-sqlite/tests/Unit/Shadow/Mutation/Upsert/ArithmeticExpressionParserTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Upsert;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\ArithmeticExpressionParser;
11use ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\ExpressionCursor;
12use ZtdQuery\Platform\Sqlite\Sql\SqliteLexerProfile;
13use ZtdQuery\Sql\SqlTokenStream;
14
15#[CoversClass(ArithmeticExpressionParser::class)]
16#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\ComparisonExpressionParser::class)]
17#[UsesClass(ExpressionCursor::class)]
18#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\ExpressionTokenDecoder::class)]
19#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\LogicalExpressionParser::class)]
20#[UsesClass(\ZtdQuery\Platform\Sqlite\Shadow\Mutation\Upsert\PrimaryExpressionParser::class)]
21#[UsesClass(SqliteLexerProfile::class)]
22final class ArithmeticExpressionParserTest extends TestCase
23{
24 public function testParseAdditiveHonorsMultiplicationPrecedence(): void
25 {
26 $sql = 'count + EXCLUDED.count * 2 - 1';
27 $cursor = new ExpressionCursor($sql, 'users', SqlTokenStream::tokenize($sql, SqliteLexerProfile::create())->significantTokens());
28 $result = (new ArithmeticExpressionParser($cursor))->parseAdditive();
29 self::assertSame(9, $result->evaluate(['count' => 4], ['count' => 3], 'users'));
30 self::assertCount($cursor->index, $cursor->tokens);
31 }
32
33 public function testParseMultiplicativeConsumesDivisionAndRemainder(): void
34 {
35 $sql = '24 / 2 % 5';
36 $cursor = new ExpressionCursor($sql, 'users', SqlTokenStream::tokenize($sql, SqliteLexerProfile::create())->significantTokens());
37 $result = (new ArithmeticExpressionParser($cursor))->parseMultiplicative();
38 self::assertSame(2, $result->evaluate(['count' => 4], ['count' => 3], 'users'));
39 self::assertCount($cursor->index, $cursor->tokens);
40 }
41
42 public function testParseUnaryConsumesNestedSigns(): void
43 {
44 $sql = '- - + 4';
45 $cursor = new ExpressionCursor($sql, 'users', SqlTokenStream::tokenize($sql, SqliteLexerProfile::create())->significantTokens());
46 $result = (new ArithmeticExpressionParser($cursor))->parseUnary();
47 self::assertSame(4, $result->evaluate(['count' => 4], ['count' => 3], 'users'));
48 self::assertCount($cursor->index, $cursor->tokens);
49 }
50
51 public function testParseUnaryNotUsesSqlTruth(): void
52 {
53 $sql = 'NOT FALSE';
54 $cursor = new ExpressionCursor($sql, 'users', SqlTokenStream::tokenize($sql, SqliteLexerProfile::create())->significantTokens());
55 $result = (new ArithmeticExpressionParser($cursor))->parseUnary();
56 self::assertSame(true, $result->evaluate(['count' => 4], ['count' => 3], 'users'));
57 self::assertCount($cursor->index, $cursor->tokens);
58 }
59
60}
61