packages/ztd-query-postgres/tests/Unit/Sql/PgSqlLexerProfileTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\Postgres\Sql\PgSqlLexerProfile;
10use ZtdQuery\Sql\SqlToken;
11use ZtdQuery\Sql\SqlTokenKind;
12use ZtdQuery\Sql\SqlTokenStream;
13
14#[CoversClass(PgSqlLexerProfile::class)]
15final class PgSqlLexerProfileTest extends TestCase
16{
17 public function testCreateSelectsPostgreSqlLexicalCapabilities(): void
18 {
19 $profile = PgSqlLexerProfile::create();
20 $tokens = SqlTokenStream::tokenize(
21 'SELECT `plain`, "quoted", $$body;still-string$$, $1',
22 $profile,
23 )->significantTokens();
24
25 self::assertSame(
26 [
27 SqlTokenKind::Word,
28 SqlTokenKind::Symbol,
29 SqlTokenKind::Word,
30 SqlTokenKind::Symbol,
31 SqlTokenKind::Symbol,
32 SqlTokenKind::QuotedIdentifier,
33 SqlTokenKind::Symbol,
34 SqlTokenKind::String,
35 SqlTokenKind::Symbol,
36 SqlTokenKind::Parameter,
37 ],
38 array_map(static fn (SqlToken $token): SqlTokenKind => $token->kind, $tokens),
39 );
40 self::assertSame(
41 ["'a\\'", 'tail'],
42 array_map(
43 static fn (SqlToken $token): string => $token->text,
44 SqlTokenStream::tokenize("'a\\' tail", $profile)->significantTokens(),
45 ),
46 );
47 self::assertSame(
48 ['E', "'a\\'b'", 'tail'],
49 array_map(
50 static fn (SqlToken $token): string => $token->text,
51 SqlTokenStream::tokenize("E'a\\'b' tail", $profile)->significantTokens(),
52 ),
53 );
54 self::assertTrue($profile->startsLineComment('-- comment', 0));
55 self::assertSame(['/*', '*/'], $profile->blockCommentAt('/* comment */', 0));
56 self::assertTrue($profile->isBracketOpening('['));
57 self::assertTrue($profile->isBracketClosing(']'));
58 self::assertTrue($profile->isNestingOpening('('));
59 self::assertTrue($profile->isNestingClosing(')'));
60 self::assertTrue($profile->supportsNestedBlockComments());
61 self::assertSame(2, $profile->positionalParameterLengthAt('$1', 0));
62 self::assertSame(1, $profile->positionalParameterLengthAt('?1', 0));
63 }
64
65 public function testRecognizesRadixNumbersAndDoesNotMisclassifyCastOperator(): void
66 {
67 $tokens = SqlTokenStream::tokenize(
68 '0xCA_FE 0o_755 0b10_01 1_000.25_5 value::text :bound',
69 PgSqlLexerProfile::create(),
70 )->significantTokens();
71
72 self::assertSame(
73 ['0xCA_FE', '0o_755', '0b10_01', '1_000.25_5'],
74 array_map(static fn (SqlToken $token): string => $token->text, array_slice($tokens, 0, 4)),
75 );
76 self::assertSame(
77 [SqlTokenKind::Word, SqlTokenKind::Symbol, SqlTokenKind::Symbol, SqlTokenKind::Word, SqlTokenKind::Parameter],
78 array_map(static fn (SqlToken $token): SqlTokenKind => $token->kind, array_slice($tokens, 4)),
79 );
80 self::assertSame(':bound', $tokens[8]->text);
81 }
82}
83