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