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