packages/ztd-query-core/tests/Unit/Sql/Reader/SqlParameterReaderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql\Reader;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use Tests\Fake\FakeSqlLexerProfiles;
11use ZtdQuery\Sql\LexicalDelimiters;
12use ZtdQuery\Sql\LexicalPattern;
13use ZtdQuery\Sql\Profile\SqlCommentProfile;
14use ZtdQuery\Sql\Profile\SqlParameterProfile;
15use ZtdQuery\Sql\Profile\SqlQuoteProfile;
16use ZtdQuery\Sql\Profile\SqlSymbolProfile;
17use ZtdQuery\Sql\Reader\SqlLexeme;
18use ZtdQuery\Sql\Reader\SqlParameterReader;
19use ZtdQuery\Sql\SqlLexerProfile;
20use ZtdQuery\Sql\SqlTokenKind;
21
22#[CoversClass(SqlParameterReader::class)]
23#[UsesClass(SqlLexeme::class)]
24#[UsesClass(SqlLexerProfile::class)]
25#[UsesClass(LexicalDelimiters::class)]
26#[UsesClass(LexicalPattern::class)]
27#[UsesClass(SqlCommentProfile::class)]
28#[UsesClass(SqlParameterProfile::class)]
29#[UsesClass(SqlQuoteProfile::class)]
30#[UsesClass(SqlSymbolProfile::class)]
31final class SqlParameterReaderTest extends TestCase
32{
33 public function testReadAtAnswersNothingWhereNoPlaceholderBegins(): void
34 {
35 self::assertNull((new SqlParameterReader())->readAt('a', 0, FakeSqlLexerProfiles::allCapabilities()));
36 }
37
38 public function testReadAtReadsAPlaceholderWrittenByPositionAsFarAsTheDialectSpellsIt(): void
39 {
40 $lexeme = (new SqlParameterReader())->readAt('$12,', 0, FakeSqlLexerProfiles::allCapabilities());
41
42 self::assertSame([SqlTokenKind::Parameter, 3], [$lexeme?->kind, $lexeme?->end]);
43 }
44
45 public function testReadAtAnswersNothingForAPrefixThatNoNameFollows(): void
46 {
47 self::assertNull((new SqlParameterReader())->readAt(': ', 0, FakeSqlLexerProfiles::allCapabilities()));
48 }
49
50 public function testReadAtReadsAPlaceholderWrittenByName(): void
51 {
52 $lexeme = (new SqlParameterReader())->readAt(':name,', 0, FakeSqlLexerProfiles::allCapabilities());
53
54 self::assertSame([SqlTokenKind::Parameter, 5], [$lexeme?->kind, $lexeme?->end]);
55 }
56
57 public function testReadAtReadsAPlaceholderNameSpelledInPartsAsOneLexeme(): void
58 {
59 $lexeme = (new SqlParameterReader())->readAt(':a::b,', 0, FakeSqlLexerProfiles::allCapabilities());
60
61 self::assertSame([SqlTokenKind::Parameter, 5], [$lexeme?->kind, $lexeme?->end]);
62 }
63
64 public function testReadAtReadsTheSuffixTheDialectAllowsAPlaceholderToCarry(): void
65 {
66 $lexeme = (new SqlParameterReader())->readAt(':a(1),', 0, FakeSqlLexerProfiles::allCapabilities());
67
68 self::assertSame([SqlTokenKind::Parameter, 5], [$lexeme?->kind, $lexeme?->end]);
69 }
70
71 public function testEndOfNameStopsAtASeparatorNoFurtherNameFollows(): void
72 {
73 $profile = FakeSqlLexerProfiles::allCapabilities();
74
75 self::assertSame(2, (new SqlParameterReader())->endOfName(':a::', 1, ':', $profile));
76 }
77
78 public function testEndOfNameStopsAtTheEndOfTheStatement(): void
79 {
80 $profile = FakeSqlLexerProfiles::allCapabilities();
81
82 self::assertSame(3, (new SqlParameterReader())->endOfName(':ab', 1, ':', $profile));
83 }
84}
85