packages/ztd-query-mysql/tests/Unit/Schema/Key/DefinitionReaderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Schema\Key;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\MySql\Schema\Key\DefinitionReader;
10
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Schema\Key\TokenReader::class)]
13#[CoversClass(DefinitionReader::class)]
14final class DefinitionReaderTest extends TestCase
15{
16 public function testTableBody(): void
17 {
18 $reader = new DefinitionReader();
19 $profile = \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create();
20 self::assertSame('id INT, FOREIGN KEY (id) REFERENCES p (id)', $reader->tableBody('CREATE TABLE c (id INT, FOREIGN KEY (id) REFERENCES p (id))', $profile));
21 self::assertNull($reader->tableBody('SELECT 1', $profile));
22 self::assertNull($reader->tableBody('CREATE TABLE c', $profile));
23 }
24
25 public function testParseEntry(): void
26 {
27 $stream = \ZtdQuery\Sql\SqlTokenStream::tokenize('CONSTRAINT fk FOREIGN KEY (pid) REFERENCES p (id) ON DELETE CASCADE ON UPDATE SET NULL', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
28 $entry = (new DefinitionReader())->parseEntry($stream, 'default', null);
29 self::assertNotNull($entry);
30 self::assertSame('fk', $entry['name']);
31 self::assertSame(['pid'], $entry['foreignKey']->columns);
32 self::assertSame('p', $entry['foreignKey']->referencedTable);
33 self::assertSame(['id'], $entry['foreignKey']->referencedColumns);
34 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::Cascade, $entry['foreignKey']->onDelete);
35 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::SetNull, $entry['foreignKey']->onUpdate);
36 }
37
38 public function testForeignKeyColumns(): void
39 {
40 $stream = \ZtdQuery\Sql\SqlTokenStream::tokenize('FOREIGN KEY (a, b) REFERENCES p (x, y)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
41 self::assertSame(['a', 'b'], (new DefinitionReader())->foreignKeyColumns($stream, $stream->significantTokens(), 8));
42 }
43
44 public function testReferencedRelation(): void
45 {
46 $stream = \ZtdQuery\Sql\SqlTokenStream::tokenize('db.`parent` (id, code)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
47 self::assertSame(['table' => 'parent', 'columns' => ['id', 'code']], (new DefinitionReader())->referencedRelation($stream, $stream->significantTokens(), 0));
48 }
49
50 public function testIdentifierList(): void
51 {
52 $stream = \ZtdQuery\Sql\SqlTokenStream::tokenize('(`a`, b)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
53 self::assertSame(['a', 'b'], (new DefinitionReader())->identifierList($stream, $stream->significantTokens(), 0));
54 }
55
56 public function testActionCase1(): void
57 {
58 $reader = new DefinitionReader();
59 $sql = 'CASCADE';
60 $expected = \ZtdQuery\Schema\Key\ReferentialAction::Cascade;
61 self::assertSame($expected, $reader->action(\ZtdQuery\Sql\SqlTokenStream::tokenize('ON DELETE ' . $sql, \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 'DELETE'));
62 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::NoAction, $reader->action([], 'DELETE'));
63 }
64
65 public function testActionCase2(): void
66 {
67 $reader = new DefinitionReader();
68 $sql = 'RESTRICT';
69 $expected = \ZtdQuery\Schema\Key\ReferentialAction::Restrict;
70 self::assertSame($expected, $reader->action(\ZtdQuery\Sql\SqlTokenStream::tokenize('ON DELETE ' . $sql, \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 'DELETE'));
71 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::NoAction, $reader->action([], 'DELETE'));
72 }
73
74 public function testActionCase3(): void
75 {
76 $reader = new DefinitionReader();
77 $sql = 'SET NULL';
78 $expected = \ZtdQuery\Schema\Key\ReferentialAction::SetNull;
79 self::assertSame($expected, $reader->action(\ZtdQuery\Sql\SqlTokenStream::tokenize('ON DELETE ' . $sql, \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 'DELETE'));
80 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::NoAction, $reader->action([], 'DELETE'));
81 }
82
83 public function testActionCase4(): void
84 {
85 $reader = new DefinitionReader();
86 $sql = 'SET DEFAULT';
87 $expected = \ZtdQuery\Schema\Key\ReferentialAction::SetDefault;
88 self::assertSame($expected, $reader->action(\ZtdQuery\Sql\SqlTokenStream::tokenize('ON DELETE ' . $sql, \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 'DELETE'));
89 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::NoAction, $reader->action([], 'DELETE'));
90 }
91
92 public function testActionCase5(): void
93 {
94 $reader = new DefinitionReader();
95 $sql = 'NO ACTION';
96 $expected = \ZtdQuery\Schema\Key\ReferentialAction::NoAction;
97 self::assertSame($expected, $reader->action(\ZtdQuery\Sql\SqlTokenStream::tokenize('ON DELETE ' . $sql, \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 'DELETE'));
98 self::assertSame(\ZtdQuery\Schema\Key\ReferentialAction::NoAction, $reader->action([], 'DELETE'));
99 }
100
101 public function testKeywordIndex(): void
102 {
103 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('FOREIGN KEY (a) REFERENCES p (id)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
104 self::assertSame(5, DefinitionReader::keywordIndex($tokens, 'REFERENCES'));
105 self::assertNull(DefinitionReader::keywordIndex($tokens, 'DELETE'));
106 }
107
108 public function testSymbolIndex(): void
109 {
110 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('(a) REFERENCES p (id)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
111 self::assertSame(5, DefinitionReader::symbolIndex($tokens, '(', 1));
112 self::assertNull(DefinitionReader::symbolIndex($tokens, ',', 0));
113 }
114
115}
116