packages/ztd-query-mysqli-adapter/tests/Integration/MysqliSessionFactoryInjectionTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Integration;
6
7use Container\MySql80Container;
8use Container\MySql84Container;
9use mysqli;
10use mysqli_result;
11use PHPUnit\Framework\Attributes\Large;
12use PHPUnit\Framework\TestCase;
13use Testcontainers\Testcontainers;
14use ZtdQuery\Adapter\Mysqli\ZtdMysqli;
15use ZtdQuery\Platform\MySql\MySqlSessionFactory;
16
17#[\PHPUnit\Framework\Attributes\CoversClass(ZtdMysqli::class)]
18#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\ConnectionExecution::class)]
19#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\ZtdMysqliStatement::class)]
20#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\StatementExecution::class)]
21#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliConnection::class)]
22#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliResultStatement::class)]
23#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliResultColumnExtractor::class)]
24#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Native\MysqliStatementBindingBridge::class)]
25#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\ZtdMysqliException::class)]
26#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Native\MysqliPropertyReader::class)]
27#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\MysqliResultProcessor::class)]
28#[Large]
29final class MysqliSessionFactoryInjectionTest extends TestCase
30{
31 public function testExplicitMySqlSessionFactoryInjectionWorks(): void
32 {
33 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
34 try {
35 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
36 $rawMysqli->set_charset('utf8mb4');
37 $table = 'prefix_' . bin2hex(random_bytes(8));
38 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
39 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
40 $factory = new MySqlSessionFactory();
41 $ztd = ZtdMysqli::fromMysqli($rawMysqli, null, $factory);
42
43 $result = $ztd->query(sprintf('SELECT * FROM `%s`', $table));
44 self::assertNotFalse($result);
45 self::assertInstanceOf(mysqli_result::class, $result);
46
47 $rows = $result->fetch_all(MYSQLI_ASSOC);
48 self::assertCount(0, $rows);
49 } finally {
50 $container->stop();
51 }
52 }
53
54 public function testInjectedFactoryInsertIsVisibleViaSelect(): void
55 {
56 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
57 try {
58 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
59 $rawMysqli->set_charset('utf8mb4');
60 $table = 'prefix_' . bin2hex(random_bytes(8));
61 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
62 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
63 $factory = new MySqlSessionFactory();
64 $ztd = ZtdMysqli::fromMysqli($rawMysqli, null, $factory);
65
66 $ztd->query(sprintf(
67 "INSERT INTO `%s` (name) VALUES ('Charlie')",
68 $table
69 ));
70
71 $result = $ztd->query(sprintf('SELECT * FROM `%s` ORDER BY name', $table));
72 self::assertNotFalse($result);
73 self::assertInstanceOf(mysqli_result::class, $result);
74
75 $rows = $result->fetch_all(MYSQLI_ASSOC);
76 self::assertCount(1, $rows);
77 self::assertSame('Charlie', $rows[0]['name']);
78 } finally {
79 $container->stop();
80 }
81 }
82
83 public function testInjectedFactoryDoesNotModifyPhysicalDatabase(): void
84 {
85 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
86 try {
87 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
88 $rawMysqli->set_charset('utf8mb4');
89 $table = 'prefix_' . bin2hex(random_bytes(8));
90 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
91 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
92 $factory = new MySqlSessionFactory();
93 $ztd = ZtdMysqli::fromMysqli($rawMysqli, null, $factory);
94
95 $ztd->query(sprintf(
96 "INSERT INTO `%s` (name) VALUES ('Charlie')",
97 $table
98 ));
99
100 $result = $rawMysqli->query(sprintf('SELECT * FROM `%s` ORDER BY name', $table));
101 self::assertNotFalse($result);
102 self::assertInstanceOf(mysqli_result::class, $result);
103
104 $rows = $result->fetch_all(MYSQLI_ASSOC);
105 self::assertCount(2, $rows);
106 self::assertSame('Alice', $rows[0]['name']);
107 self::assertSame('Bob', $rows[1]['name']);
108 } finally {
109 $container->stop();
110 }
111 }
112
113 public function testInjectedFactoryPreparedStatementWorks(): void
114 {
115 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
116 try {
117 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
118 $rawMysqli->set_charset('utf8mb4');
119 $table = 'prefix_' . bin2hex(random_bytes(8));
120 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
121 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
122 $factory = new MySqlSessionFactory();
123 $ztd = ZtdMysqli::fromMysqli($rawMysqli, null, $factory);
124
125 $ztd->query(sprintf(
126 "INSERT INTO `%s` (name) VALUES ('Charlie')",
127 $table
128 ));
129
130 $stmt = $ztd->prepare(sprintf('SELECT * FROM `%s` WHERE name = ?', $table));
131 self::assertNotFalse($stmt);
132
133 $name = 'Charlie';
134 $stmt->bind_param('s', $name);
135 $stmt->execute();
136 $result = $stmt->get_result();
137 self::assertNotFalse($result);
138
139 $rows = $result->fetch_all(MYSQLI_ASSOC);
140 self::assertCount(1, $rows);
141 self::assertSame('Charlie', $rows[0]['name']);
142 } finally {
143 $container->stop();
144 }
145 }
146
147 public function testInjectedFactoryAffectedRowsTracking(): void
148 {
149 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
150 try {
151 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
152 $rawMysqli->set_charset('utf8mb4');
153 $table = 'prefix_' . bin2hex(random_bytes(8));
154 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
155 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
156 $factory = new MySqlSessionFactory();
157 $ztd = ZtdMysqli::fromMysqli($rawMysqli, null, $factory);
158
159 $ztd->query(sprintf(
160 "INSERT INTO `%s` (name) VALUES ('Charlie')",
161 $table
162 ));
163
164 self::assertSame(1, $ztd->lastAffectedRows());
165 } finally {
166 $container->stop();
167 }
168 }
169
170 public function testDefaultFactoryBehaviorMatchesExplicitInjection(): void
171 {
172 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
173 try {
174 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
175 $rawMysqli->set_charset('utf8mb4');
176 $table = 'prefix_' . bin2hex(random_bytes(8));
177 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL)', $table));
178 $rawMysqli->query(sprintf("INSERT INTO `%s` (name) VALUES ('Alice'), ('Bob')", $table));
179 $ztdDefault = ZtdMysqli::fromMysqli($rawMysqli);
180
181 $resultDefault = $ztdDefault->query(sprintf('SELECT * FROM `%s`', $table));
182 self::assertNotFalse($resultDefault);
183 self::assertInstanceOf(mysqli_result::class, $resultDefault);
184
185 $rowsDefault = $resultDefault->fetch_all(MYSQLI_ASSOC);
186 self::assertCount(0, $rowsDefault);
187 } finally {
188 $container->stop();
189 }
190 }
191}
192