packages/ztd-query-mysqli-adapter/tests/Integration/MysqliLoadDataTest.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;
15
16#[\PHPUnit\Framework\Attributes\CoversClass(ZtdMysqli::class)]
17#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\ConnectionExecution::class)]
18#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\ZtdMysqliStatement::class)]
19#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\StatementExecution::class)]
20#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliConnection::class)]
21#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliResultStatement::class)]
22#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Driver\MysqliResultColumnExtractor::class)]
23#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Native\MysqliStatementBindingBridge::class)]
24#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\ZtdMysqliException::class)]
25#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Native\MysqliPropertyReader::class)]
26#[\PHPUnit\Framework\Attributes\CoversClass(\ZtdQuery\Adapter\Mysqli\Session\MysqliResultProcessor::class)]
27#[Large]
28final class MysqliLoadDataTest extends TestCase
29{
30 public function testLocalInfileLoadsOnlyTheShadowTable(): void
31 {
32 $container = Testcontainers::run(getenv('MYSQL_VERSION') === '8.4.7' ? MySql84Container::class : MySql80Container::class);
33 try {
34 $rawMysqli = new mysqli(str_replace('localhost', '127.0.0.1', $container->getHost()), 'root', 'root', 'test', $container->getMappedPort(3306));
35 $rawMysqli->set_charset('utf8mb4');
36 $table = 'load_' . bin2hex(random_bytes(8));
37 $rawMysqli->query(sprintf('CREATE TABLE `%s` (id INT PRIMARY KEY, name VARCHAR(100))', $table));
38 $ztdMysqli = ZtdMysqli::fromMysqli($rawMysqli);
39
40 $stream = tmpfile();
41 self::assertIsResource($stream);
42 self::assertSame(14, fwrite($stream, "1\tAlice\n2\tBob\n"));
43 $metadata = stream_get_meta_data($stream);
44 $path = $metadata['uri'] ?? null;
45 self::assertIsString($path);
46
47 self::assertNotFalse($ztdMysqli->query(sprintf(
48 "LOAD DATA LOCAL INFILE '%s' INTO TABLE `%s`",
49 str_replace("'", "''", $path),
50 $table,
51 )));
52 self::assertSame(2, $ztdMysqli->lastAffectedRows());
53
54 $rows = $ztdMysqli->query(sprintf('SELECT id, name FROM `%s` ORDER BY id', $table));
55 self::assertInstanceOf(mysqli_result::class, $rows);
56 self::assertSame([
57 ['id' => 1, 'name' => 'Alice'],
58 ['id' => 2, 'name' => 'Bob'],
59 ], $rows->fetch_all(MYSQLI_ASSOC));
60
61 $physical = $rawMysqli->query(sprintf('SELECT COUNT(*) AS count FROM `%s`', $table));
62 self::assertInstanceOf(mysqli_result::class, $physical);
63 self::assertSame([['count' => '0']], $physical->fetch_all(MYSQLI_ASSOC));
64 } finally {
65 $container->stop();
66 }
67 }
68}
69