packages/ztd-query-mysqli-adapter/tests/Unit/Driver/MysqliResultColumnExtractorTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Driver;
6
7use Container\MySql80Container;
8use Container\MySql84Container;
9use mysqli;
10use mysqli_result;
11use PHPUnit\Framework\Attributes\CoversClass;
12use PHPUnit\Framework\Attributes\Large;
13use PHPUnit\Framework\TestCase;
14use Testcontainers\Testcontainers;
15use ZtdQuery\Adapter\Mysqli\Driver\MysqliResultColumnExtractor;
16use ZtdQuery\Platform\ResultColumnTypeResolver;
17use ZtdQuery\Schema\ColumnType;
18use ZtdQuery\Schema\ColumnTypeFamily;
19
20#[CoversClass(MysqliResultColumnExtractor::class)]
21#[Large]
22final class MysqliResultColumnExtractorTest extends TestCase
23{
24    public function testExtractPassesNativeFieldMetadataToTheTypeResolver(): void
25    {
26        $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
27        try {
28            $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
29            $connection->set_charset('utf8mb4');
30            $result = $connection->query('SELECT CAST(7 AS SIGNED) AS value');
31            self::assertInstanceOf(mysqli_result::class, $result);
32            $resolver = self::createMock(ResultColumnTypeResolver::class);
33            $resolver->expects(self::once())->method('resolve')->with(self::callback(
34                static fn (array $metadata): bool => $metadata['name'] === 'value'
35                    && $metadata['type'] === MYSQLI_TYPE_LONGLONG && $metadata['charsetnr'] === 63,
36            ))->willReturn(new ColumnType(ColumnTypeFamily::INTEGER, 'BIGINT'));
37            $columns = MysqliResultColumnExtractor::extract($result, $resolver);
38            self::assertSame('value', $columns[0]->name);
39            self::assertSame(ColumnTypeFamily::INTEGER, $columns[0]->type->family);
40            $connection->close();
41        } finally {
42            $container->stop();
43        }
44    }
45
46    public function testExtractPreservesEveryColumnAndItsOrder(): void
47    {
48        $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
49        try {
50            $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
51            $connection->set_charset('utf8mb4');
52            $result = $connection->query("SELECT 1 AS id, 'Alice' AS name");
53            self::assertInstanceOf(mysqli_result::class, $result);
54            $resolver = self::createStub(ResultColumnTypeResolver::class);
55            $resolver->method('resolve')->willReturn(new ColumnType(ColumnTypeFamily::STRING, 'TEXT'));
56            $columns = MysqliResultColumnExtractor::extract($result, $resolver);
57            self::assertSame(['id', 'name'], array_column($columns, 'name'));
58            $connection->close();
59        } finally {
60            $container->stop();
61        }
62    }
63
64}
65