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