packages/ztd-query-postgres/tests/Unit/Shadow/Mutation/Upsert/Expression/PrimaryParserTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Shadow\Mutation\Upsert\Expression;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9
10#[CoversClass(\ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrimaryParser::class)]
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ComparisonOperator::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionCursor::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionLexeme::class)]
14#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrecedenceParser::class)]
15#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::class)]
16final class PrimaryParserTest extends TestCase
17{
18    public function testParsePrimaryEvaluatesAParenthesizedExpression(): void
19    {
20        $sql = '(2 + 3)';
21        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize($sql, \ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::create())->significantTokens();
22        $cursor = new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionCursor($sql, 'users', $tokens);
23        $expression = (new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrimaryParser($cursor))->parsePrimary();
24        self::assertSame(5, $expression->evaluate([], [], 'users'));
25        self::assertSame(count($tokens), $cursor->index);
26    }
27
28    public function testColumnSourceResolvesIncomingAndExistingQualifiers(): void
29    {
30        $sql = 'id';
31        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize($sql, \ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::create())->significantTokens();
32        $cursor = new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionCursor($sql, 'users', $tokens);
33        $parser = new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrimaryParser($cursor);
34        self::assertSame(\ZtdQuery\Shadow\Mutation\UpsertColumnSource::Incoming, $parser->columnSource('excluded'));
35        self::assertSame(\ZtdQuery\Shadow\Mutation\UpsertColumnSource::Existing, $parser->columnSource('USERS'));
36    }
37
38    public function testColumnReadsTheIncomingRow(): void
39    {
40        $sql = 'EXCLUDED.name';
41        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize($sql, \ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::create())->significantTokens();
42        $cursor = new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionCursor($sql, 'users', $tokens);
43        $expression = (new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrimaryParser($cursor))->column($tokens[0]);
44        self::assertSame('incoming', $expression->evaluate(['name' => 'existing'], ['name' => 'incoming'], 'users'));
45        self::assertSame(count($tokens), $cursor->index);
46    }
47
48    public function testColumnSourceRejectsUnknownQualifiers(): void
49    {
50        $sql = 'other.id';
51        $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize($sql, \ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile::create())->significantTokens();
52        $cursor = new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\ExpressionCursor($sql, 'users', $tokens);
53        $this->expectException(\ZtdQuery\Exception\UnsupportedSqlException::class);
54        (new \ZtdQuery\Platform\Postgres\Shadow\Mutation\Upsert\Expression\PrimaryParser($cursor))->columnSource('other');
55    }
56}
57