packages/sql-parser/tests/Unit/PostgreSql/Lexer/OperatorScannerTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\PostgreSql\Lexer;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Small;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlParser\Lexer\Cursor;
12use SqlParser\Lexer\Lexeme;
13use SqlParser\Lexer\LexicalException;
14use SqlParser\PostgreSql\Lexer\KeywordTable;
15use SqlParser\PostgreSql\Lexer\OperatorScanner;
16use SqlParser\PostgreSql\Lexer\Scan;
17
18#[CoversClass(OperatorScanner::class)]
19#[UsesClass(Cursor::class)]
20#[UsesClass(Lexeme::class)]
21#[UsesClass(LexicalException::class)]
22#[UsesClass(KeywordTable::class)]
23#[UsesClass(Scan::class)]
24#[UsesClass(\SqlParser\Lexer\SourcePosition::class)]
25#[UsesClass(\SqlParser\Lexer\SourceException::class)]
26#[Small]
27final class OperatorScannerTest extends TestCase
28{
29 public function testScan(): void
30 {
31 $scanner = new OperatorScanner();
32 $scan = static fn (string $sql): Scan => new Scan(new Cursor($sql), new KeywordTable([]));
33
34 self::assertSame('TYPECAST', $scanner->scan($scan('::int'))->name);
35 self::assertSame('DOT_DOT', $scanner->scan($scan('..'))->name);
36 self::assertSame('COLON_EQUALS', $scanner->scan($scan(':='))->name);
37 self::assertSame('EQUALS_GREATER', $scanner->scan($scan('=>'))->name);
38 self::assertSame('NOT_EQUALS', $scanner->scan($scan('<>'))->name);
39 self::assertSame('NOT_EQUALS', $scanner->scan($scan('!='))->name);
40 self::assertSame('LESS_EQUALS', $scanner->scan($scan('<='))->name);
41 self::assertSame('+', $scanner->scan($scan('+ 1'))->name);
42 self::assertSame('Op', $scanner->scan($scan('~'))->name);
43 self::assertSame('<=>', $scanner->scan($scan('<=> 1'))->text);
44 self::assertSame('<', $scanner->scan($scan('<-1'))->text);
45 self::assertSame('@-', $scanner->scan($scan('@-1'))->text);
46 self::assertSame('-', $scanner->scan($scan('--'))->text);
47 self::assertSame('Op', $scanner->scan($scan('!=='))->name);
48 }
49
50 public function testScanRejectsAForeignCharacter(): void
51 {
52 $this->expectException(LexicalException::class);
53
54 (new OperatorScanner())->scan(new Scan(new Cursor('{'), new KeywordTable([])));
55 }
56
57 public function testScanRejectsAnOverlongOperator(): void
58 {
59 $this->expectException(LexicalException::class);
60
61 (new OperatorScanner())->scan(new Scan(new Cursor(str_repeat('~', 64)), new KeywordTable([])));
62 }
63
64 public function testOperatorRun(): void
65 {
66 $scanner = new OperatorScanner();
67
68 self::assertSame('<@', $scanner->operatorRun('<@/* c */', 0));
69 self::assertSame('+', $scanner->operatorRun('+--', 0));
70 self::assertSame('*', $scanner->operatorRun('*+-', 0));
71 self::assertSame('+', $scanner->operatorRun('++', 0));
72 self::assertSame('?-', $scanner->operatorRun('?-', 0));
73 self::assertNull($scanner->operatorRun('a+', 0));
74 }
75}
76