packages/sql-parser/tests/Unit/MySql/Lexer/NumberScannerTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\MySql\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\MySql\Lexer\KeywordTable;
14use SqlParser\MySql\Lexer\LexerState;
15use SqlParser\MySql\Lexer\NumberScanner;
16use SqlParser\MySql\Lexer\Scan;
17use SqlParser\MySql\Lexer\WordScanner;
18use SqlParser\MySql\MySqlVersion;
19use SqlParser\MySql\SqlMode;
20
21#[CoversClass(NumberScanner::class)]
22#[UsesClass(Cursor::class)]
23#[UsesClass(Lexeme::class)]
24#[UsesClass(KeywordTable::class)]
25#[UsesClass(MySqlVersion::class)]
26#[UsesClass(Scan::class)]
27#[UsesClass(SqlMode::class)]
28#[UsesClass(WordScanner::class)]
29#[UsesClass(\SqlParser\Resource\SqlVersion::class)]
30#[UsesClass(\SqlParser\Resource\VersionRegistry::class)]
31#[Small]
32final class NumberScannerTest extends TestCase
33{
34 public function testScan(): void
35 {
36 $scanner = new NumberScanner();
37 $words = new WordScanner();
38 $version = MySqlVersion::resolve();
39 $scan = static fn (string $sql): Scan => new Scan(new Cursor($sql), new KeywordTable([], []), new SqlMode(), $version);
40
41 self::assertSame('NUM', $scanner->scan($scan('42 '), $words)?->name);
42 self::assertSame('HEX_NUM', $scanner->scan($scan('0x1F'), $words)?->name);
43 self::assertSame('BIN_NUM', $scanner->scan($scan('0b01 '), $words)?->name);
44 self::assertSame('IDENT', $scanner->scan($scan('0xZZ'), $words)?->name);
45 self::assertSame('DECIMAL_NUM', $scanner->scan($scan('1.5'), $words)?->name);
46 self::assertSame('DECIMAL_NUM', $scanner->scan($scan('.5'), $words)?->name);
47 self::assertSame('FLOAT_NUM', $scanner->scan($scan('1e5'), $words)?->name);
48 self::assertSame('FLOAT_NUM', $scanner->scan($scan('1.5E-3'), $words)?->name);
49 self::assertSame('IDENT', $scanner->scan($scan('1e'), $words)?->name);
50 self::assertSame('IDENT', $scanner->scan($scan('1abc'), $words)?->name);
51 self::assertNull($scanner->scan($scan('abc'), $words));
52 }
53
54 public function testScanNotesAQualifiedIdentifierThatStartsWithADigit(): void
55 {
56 $scan = new Scan(new Cursor('1a.b'), new KeywordTable([], []), new SqlMode(), MySqlVersion::resolve());
57
58 self::assertSame('1a', (new NumberScanner())->scan($scan, new WordScanner())?->text);
59 self::assertSame(LexerState::IdentifierSeparator, $scan->next);
60 }
61
62 public function testFraction(): void
63 {
64 $scan = new Scan(new Cursor('.25e2x'), new KeywordTable([], []), new SqlMode(), MySqlVersion::resolve());
65 $lexeme = (new NumberScanner())->fraction($scan, 0);
66
67 self::assertSame('FLOAT_NUM', $lexeme->name);
68 self::assertSame('.25e2', $lexeme->text);
69 }
70
71 public function testIntegerTerminal(): void
72 {
73 self::assertSame('NUM', NumberScanner::integerTerminal('0002147483647'));
74 self::assertSame('LONG_NUM', NumberScanner::integerTerminal('2147483648'));
75 self::assertSame('LONG_NUM', NumberScanner::integerTerminal('9223372036854775807'));
76 self::assertSame('ULONGLONG_NUM', NumberScanner::integerTerminal('9223372036854775808'));
77 self::assertSame('ULONGLONG_NUM', NumberScanner::integerTerminal('18446744073709551615'));
78 self::assertSame('DECIMAL_NUM', NumberScanner::integerTerminal('18446744073709551616'));
79 self::assertSame('NUM', NumberScanner::integerTerminal('000'));
80 }
81}
82