packages/ztd-query-mysql/tests/Unit/Rewrite/Transformer/Insert/ResultProjectionTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Rewrite\Transformer\Insert;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\ResultProjection;
10
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\Value\MySqlCastRenderer::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
14#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertRowRenderer::class)]
15#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertSelectRenderer::class)]
16#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\InsertTarget::class)]
17#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Transformer\MySqlSelectListAliaser::class)]
18#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Transformer\Select\ExpressionAliaser::class)]
19#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\Value\CastTypeResolver::class)]
20#[CoversClass(ResultProjection::class)]
21final class ResultProjectionTest extends TestCase
22{
23    public function testBuildInsertSelect(): void
24    {
25        $projection = new ResultProjection(new \ZtdQuery\Platform\MySql\Sql\Value\MySqlCastRenderer(), new \ZtdQuery\Rewrite\ShadowIdentityAllocator(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertRowRenderer());
26        $target = new \ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\InsertTarget('t', ['id', 'name'], ['name'], [], ['name' => "'default'"], ['id' => \ZtdQuery\Schema\Key\IdentityGenerationStrategy::MaxValue], [['id' => 7]], []);
27        $statement = (new \PhpMyAdmin\SqlParser\Parser("INSERT INTO t (name) VALUES ('a'), ('b')"))->statements[0];
28        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\InsertStatement::class, $statement);
29        self::assertSame("SELECT 8 AS `id`, 'a' AS `name` UNION ALL SELECT 9 AS `id`, 'b' AS `name`", $projection->buildInsertSelect($statement, $target, null));
30    }
31
32    public function testBuildInsertRowSelect(): void
33    {
34        $projection = new ResultProjection(new \ZtdQuery\Platform\MySql\Sql\Value\MySqlCastRenderer(), new \ZtdQuery\Rewrite\ShadowIdentityAllocator(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertRowRenderer());
35        $target = new \ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\InsertTarget('t', ['id', 'name'], ['name'], [], ['name' => "'default'"], ['id' => \ZtdQuery\Schema\Key\IdentityGenerationStrategy::MaxValue], [['id' => 7]], []);
36        $statement = (new \PhpMyAdmin\SqlParser\Parser('INSERT INTO t (name) VALUES (DEFAULT)'))->statements[0];
37        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\InsertStatement::class, $statement);
38        self::assertNotNull($statement->values);
39        self::assertSame("SELECT 8 AS `id`, 'default' AS `name`", $projection->buildInsertRowSelect($statement->values[0], $target));
40    }
41
42    public function testBuildInsertSetSelect(): void
43    {
44        $projection = new ResultProjection(new \ZtdQuery\Platform\MySql\Sql\Value\MySqlCastRenderer(), new \ZtdQuery\Rewrite\ShadowIdentityAllocator(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertRowRenderer());
45        $target = new \ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\InsertTarget('t', ['id', 'name'], ['name'], [], ['name' => "'default'"], ['id' => \ZtdQuery\Schema\Key\IdentityGenerationStrategy::MaxValue], [['id' => 7]], []);
46        $statement = (new \PhpMyAdmin\SqlParser\Parser("INSERT INTO t SET name = 'a'"))->statements[0];
47        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\InsertStatement::class, $statement);
48        self::assertNotNull($statement->set);
49        self::assertSame("SELECT 8 AS `id`, 'a' AS `name`", $projection->buildInsertSetSelect(array_values($statement->set), $target));
50    }
51
52    public function testBuildInsertSourceSelectCastsDestinationColumns(): void
53    {
54        $projection = new ResultProjection(new \ZtdQuery\Platform\MySql\Sql\Value\MySqlCastRenderer(), new \ZtdQuery\Rewrite\ShadowIdentityAllocator(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertSelectRenderer(), new \ZtdQuery\Platform\MySql\Rewrite\Transformer\InsertRowRenderer());
55        $target = new \ZtdQuery\Platform\MySql\Rewrite\Transformer\Insert\InsertTarget('years', ['year', 'note`tag'], [], ['year' => new \ZtdQuery\Schema\ColumnDeclaration(\ZtdQuery\Schema\ColumnTypeFamily::INTEGER, 'YEAR')], [], [], [], []);
56        $statement = (new \PhpMyAdmin\SqlParser\Parser("SELECT 93, 'ok'"))->statements[0];
57        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\SelectStatement::class, $statement);
58        self::assertStringStartsWith(
59            'SELECT CAST(CAST(_ztd_insert_cast.`year` AS YEAR) AS SIGNED) AS `year`, _ztd_insert_cast.`note``tag` AS `note``tag` FROM (',
60            $projection->buildInsertSourceSelect($statement, $target, null),
61        );
62    }
63
64    public function testOrderedValues(): void
65    {
66        self::assertSame(['first', 'second'], ResultProjection::orderedValues([8 => 'first', 2 => 'second']));
67        self::assertSame([], ResultProjection::orderedValues([]));
68    }
69
70}
71