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\Endpoint;
8use Container\MySqlRelease;
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(MySqlRelease::fromEnvironment());
46 $endpoint = $container->getData(Endpoint::class);
47 try {
48 $connection = new mysqli($endpoint->host, $endpoint->username, $endpoint->password, $endpoint->database, $endpoint->port);
49 $connection->set_charset('utf8mb4');
50 $result = $connection->query("SELECT 1 AS id, 'Alice' AS name UNION ALL SELECT 2, 'Bob'");
51 self::assertInstanceOf(mysqli_result::class, $result);
52 $statement = new MysqliResultStatement($result, 2);
53 self::assertSame([['id' => '1', 'name' => 'Alice'], ['id' => '2', 'name' => 'Bob']], $statement->fetchAll());
54 self::assertSame(2, $statement->rowCount());
55 $connection->close();
56 } finally {
57 $container->stop();
58 }
59 }
60
61 public function testResultColumnsResolvesResultColumnTypes(): void
62 {
63 $container = Testcontainers::run(MySqlRelease::fromEnvironment());
64 $endpoint = $container->getData(Endpoint::class);
65 try {
66 $connection = new mysqli($endpoint->host, $endpoint->username, $endpoint->password, $endpoint->database, $endpoint->port);
67 $connection->set_charset('utf8mb4');
68 $result = $connection->query("SELECT 1 AS id, 'Alice' AS name");
69 self::assertInstanceOf(mysqli_result::class, $result);
70 $resolver = self::createStub(ResultColumnTypeResolver::class);
71 $resolver->method('resolve')->willReturnCallback(static fn (array $metadata): ColumnType =>
72 $metadata['name'] === 'id' ? new ColumnType(ColumnTypeFamily::INTEGER, 'INT') : new ColumnType(ColumnTypeFamily::STRING, 'VARCHAR'));
73 $columns = (new MysqliResultStatement($result, 1))->resultColumns($resolver);
74 self::assertSame(['id', 'name'], array_column($columns, 'name'));
75 self::assertSame(ColumnTypeFamily::INTEGER, $columns[0]->type->family);
76 self::assertSame(ColumnTypeFamily::STRING, $columns[1]->type->family);
77 $connection->close();
78 } finally {
79 $container->stop();
80 }
81 }
82
83}
84