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\Endpoint;
8use Container\MySqlRelease;
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(MySqlRelease::fromEnvironment());
27        $endpoint = $container->getData(Endpoint::class);
28        try {
29            $connection = new mysqli($endpoint->host, $endpoint->username, $endpoint->password, $endpoint->database, $endpoint->port);
30            $connection->set_charset('utf8mb4');
31            $result = $connection->query('SELECT CAST(7 AS SIGNED) AS value');
32            self::assertInstanceOf(mysqli_result::class, $result);
33            $resolver = self::createMock(ResultColumnTypeResolver::class);
34            $resolver->expects(self::once())->method('resolve')->with(self::callback(
35                static fn (array $metadata): bool => $metadata['name'] === 'value'
36                    && $metadata['type'] === MYSQLI_TYPE_LONGLONG && $metadata['charsetnr'] === 63,
37            ))->willReturn(new ColumnType(ColumnTypeFamily::INTEGER, 'BIGINT'));
38            $columns = MysqliResultColumnExtractor::extract($result, $resolver);
39            self::assertSame('value', $columns[0]->name);
40            self::assertSame(ColumnTypeFamily::INTEGER, $columns[0]->type->family);
41            $connection->close();
42        } finally {
43            $container->stop();
44        }
45    }
46
47    public function testExtractPreservesEveryColumnAndItsOrder(): void
48    {
49        $container = Testcontainers::run(MySqlRelease::fromEnvironment());
50        $endpoint = $container->getData(Endpoint::class);
51        try {
52            $connection = new mysqli($endpoint->host, $endpoint->username, $endpoint->password, $endpoint->database, $endpoint->port);
53            $connection->set_charset('utf8mb4');
54            $result = $connection->query("SELECT 1 AS id, 'Alice' AS name");
55            self::assertInstanceOf(mysqli_result::class, $result);
56            $resolver = self::createStub(ResultColumnTypeResolver::class);
57            $resolver->method('resolve')->willReturn(new ColumnType(ColumnTypeFamily::STRING, 'TEXT'));
58            $columns = MysqliResultColumnExtractor::extract($result, $resolver);
59            self::assertSame(['id', 'name'], array_column($columns, 'name'));
60            $connection->close();
61        } finally {
62            $container->stop();
63        }
64    }
65
66}
67