packages/ztd-query-mysqli-adapter/tests/Unit/Driver/MysqliResultStatementTest.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\Attributes\UsesClass;
14use PHPUnit\Framework\TestCase;
15use Testcontainers\Testcontainers;
16use ZtdQuery\Adapter\Mysqli\Driver\MysqliResultColumnExtractor;
17use ZtdQuery\Adapter\Mysqli\Driver\MysqliResultStatement;
18use ZtdQuery\Platform\ResultColumnTypeResolver;
19use ZtdQuery\Schema\ColumnType;
20use ZtdQuery\Schema\ColumnTypeFamily;
21
22#[CoversClass(MysqliResultStatement::class)]
23#[Large]
24#[UsesClass(MysqliResultColumnExtractor::class)]
25final class MysqliResultStatementTest extends TestCase
26{
27    public function testExecuteRepresentsAWriteWithoutAResultSet(): void
28    {
29        $statement = new MysqliResultStatement(null, 2);
30        self::assertTrue($statement->execute());
31        self::assertTrue($statement->execute([1, 2]));
32        self::assertSame([], $statement->fetchAll());
33        self::assertSame(2, $statement->rowCount());
34        self::assertSame([], $statement->resultColumns(self::createStub(ResultColumnTypeResolver::class)));
35    }
36
37    public function testRowCountRetainsZeroAndLargeAffectedRowCounts(): void
38    {
39        self::assertSame(0, (new MysqliResultStatement(null, 0))->rowCount());
40        self::assertSame(PHP_INT_MAX, (new MysqliResultStatement(null, '999999999999999999999999999999'))->rowCount());
41    }
42
43    public function testFetchAllReadsNativeRowsWithoutLosingColumnNames(): void
44    {
45        $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
46        try {
47            $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
48            $connection->set_charset('utf8mb4');
49            $result = $connection->query("SELECT 1 AS id, 'Alice' AS name UNION ALL SELECT 2, 'Bob'");
50            self::assertInstanceOf(mysqli_result::class, $result);
51            $statement = new MysqliResultStatement($result, 2);
52            self::assertSame([['id' => '1', 'name' => 'Alice'], ['id' => '2', 'name' => 'Bob']], $statement->fetchAll());
53            self::assertSame(2, $statement->rowCount());
54            $connection->close();
55        } finally {
56            $container->stop();
57        }
58    }
59
60    public function testResultColumnsResolvesResultColumnTypes(): void
61    {
62        $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
63        try {
64            $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
65            $connection->set_charset('utf8mb4');
66            $result = $connection->query("SELECT 1 AS id, 'Alice' AS name");
67            self::assertInstanceOf(mysqli_result::class, $result);
68            $resolver = self::createStub(ResultColumnTypeResolver::class);
69            $resolver->method('resolve')->willReturnCallback(static fn (array $metadata): ColumnType =>
70                $metadata['name'] === 'id' ? new ColumnType(ColumnTypeFamily::INTEGER, 'INT') : new ColumnType(ColumnTypeFamily::STRING, 'VARCHAR'));
71            $columns = (new MysqliResultStatement($result, 1))->resultColumns($resolver);
72            self::assertSame(['id', 'name'], array_column($columns, 'name'));
73            self::assertSame(ColumnTypeFamily::INTEGER, $columns[0]->type->family);
74            self::assertSame(ColumnTypeFamily::STRING, $columns[1]->type->family);
75            $connection->close();
76        } finally {
77            $container->stop();
78        }
79    }
80
81}
82