packages/ztd-query-mysqli-adapter/tests/Unit/Native/MysqliStatementPropertyReaderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Native;
6
7use Container\MySql80Container;
8use Container\MySql84Container;
9use mysqli;
10use mysqli_stmt;
11use PHPUnit\Framework\Attributes\CoversClass;
12use PHPUnit\Framework\Attributes\Large;
13use PHPUnit\Framework\TestCase;
14use Testcontainers\Testcontainers;
15use ZtdQuery\Adapter\Mysqli\Native\MysqliStatementPropertyReader;
16
17#[CoversClass(MysqliStatementPropertyReader::class)]
18#[Large]
19final class MysqliStatementPropertyReaderTest extends TestCase
20{
21 public function testReadPreservesPreparedMetadataAndBufferedRowCounts(): void
22 {
23 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
24 try {
25 $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
26 $connection->set_charset('utf8mb4');
27 $statement = $connection->prepare('SELECT ? AS value UNION ALL SELECT ?');
28 self::assertInstanceOf(mysqli_stmt::class, $statement);
29 $reader = new MysqliStatementPropertyReader();
30 self::assertSame(2, $reader->read($statement, 'param_count'));
31 self::assertSame(1, $reader->read($statement, 'field_count'));
32 self::assertSame($statement->id, $reader->read($statement, 'id'));
33 self::assertTrue($statement->execute([7, 8]));
34 self::assertTrue($statement->store_result());
35 self::assertSame(2, $reader->read($statement, 'num_rows'));
36 self::assertSame(2, $reader->read($statement, 'affected_rows'));
37 self::assertSame(0, $reader->read($statement, 'errno'));
38 self::assertSame('', $reader->read($statement, 'error'));
39 self::assertSame([], $reader->read($statement, 'error_list'));
40 self::assertSame('00000', $reader->read($statement, 'sqlstate'));
41 self::assertNull($reader->read($statement, 'unsupported'));
42 $statement->close();
43 $connection->close();
44 } finally {
45 $container->stop();
46 }
47 }
48
49 public function testReadPreservesGeneratedIdsAndWriteCounts(): void
50 {
51 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
52 try {
53 $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
54 $connection->set_charset('utf8mb4');
55 $connection->query('CREATE TABLE generated_rows (id INT AUTO_INCREMENT PRIMARY KEY, value INT)');
56 $statement = $connection->prepare('INSERT INTO generated_rows (value) VALUES (?), (?)');
57 self::assertInstanceOf(mysqli_stmt::class, $statement);
58 self::assertTrue($statement->execute([7, 8]));
59 $reader = new MysqliStatementPropertyReader();
60 self::assertSame(1, $reader->read($statement, 'insert_id'));
61 self::assertSame(2, $reader->read($statement, 'affected_rows'));
62 self::assertSame(0, $reader->read($statement, 'field_count'));
63 self::assertSame(0, $reader->read($statement, 'num_rows'));
64 $statement->close();
65 $connection->close();
66 } finally {
67 $container->stop();
68 }
69 }
70
71 public function testReadPreservesNativeFailureDetails(): void
72 {
73 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
74 try {
75 $connection = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
76 $connection->set_charset('utf8mb4');
77 $connection->query('CREATE TABLE unique_rows (id INT PRIMARY KEY)');
78 $statement = $connection->prepare('INSERT INTO unique_rows VALUES (?)');
79 self::assertInstanceOf(mysqli_stmt::class, $statement);
80 self::assertTrue($statement->execute([1]));
81 mysqli_report(MYSQLI_REPORT_OFF);
82 try {
83 self::assertFalse($statement->execute([1]));
84 $reader = new MysqliStatementPropertyReader();
85 self::assertSame(1062, $reader->read($statement, 'errno'));
86 self::assertSame('23000', $reader->read($statement, 'sqlstate'));
87 self::assertStringContainsString('Duplicate entry', $statement->error);
88 self::assertSame($statement->error, $reader->read($statement, 'error'));
89 self::assertSame([['errno' => 1062, 'sqlstate' => '23000', 'error' => $statement->error]], $reader->read($statement, 'error_list'));
90 } finally {
91 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
92 $statement->close();
93 $connection->close();
94 }
95 } finally {
96 $container->stop();
97 }
98 }
99}
100