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