packages/ztd-query-pdo-adapter/tests/Unit/Session/PreparedQueryTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Session;
6
7use PDO;
8use PDOStatement;
9use PHPUnit\Framework\Attributes\CoversClass;
10use PHPUnit\Framework\Attributes\UsesClass;
11use PHPUnit\Framework\TestCase;
12use ZtdQuery\Adapter\Pdo\Driver\PdoConnection;
13use ZtdQuery\Adapter\Pdo\Session\PreparedQuery;
14use ZtdQuery\Adapter\Pdo\ZtdPdoException;
15use ZtdQuery\Config\ZtdConfig;
16use ZtdQuery\Platform\Sqlite\SqliteSessionFactory;
17
18#[CoversClass(PreparedQuery::class)]
19#[UsesClass(ZtdPdoException::class)]
20#[UsesClass(\ZtdQuery\Adapter\Pdo\ZtdPdoStatement::class)]
21#[UsesClass(\ZtdQuery\Adapter\Pdo\ZtdPdo::class)]
22#[UsesClass(PdoConnection::class)]
23#[UsesClass(\ZtdQuery\Adapter\Pdo\Driver\PdoStatement::class)]
24#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\StatementExecution::class)]
25#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\Bindings::class)]
26#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\BufferedRow::class)]
27#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\DriverSessionFactory::class)]
28#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\ParameterKind::class)]
29#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\ParameterBinder::class)]
30#[\PHPUnit\Framework\Attributes\Medium]
31#[UsesClass(\ZtdQuery\Adapter\Pdo\Session\ConnectionExecution::class)]
32final class PreparedQueryTest extends TestCase
33{
34 public function testRewriteUsesTheCurrentShadowOnEveryExecution(): void
35 {
36 $native = new PDO('sqlite::memory:');
37 $native->exec('CREATE TABLE items (id INTEGER PRIMARY KEY, value TEXT)');
38 $session = (new SqliteSessionFactory())->create(new PdoConnection($native), ZtdConfig::default());
39 $query = new PreparedQuery($session, 'SELECT value FROM items WHERE id = ?', static fn (string $sql): PDOStatement|false => $native->prepare($sql));
40 $session->execStatement("INSERT INTO items VALUES (1, 'before')");
41 $before = $query->prepare($query->rewrite()->sql());
42 self::assertTrue($before->execute([1]));
43 self::assertSame('before', $before->fetchColumn());
44 $session->execStatement("UPDATE items SET value = 'after' WHERE id = 1");
45 $after = $query->prepare($query->rewrite()->sql());
46 self::assertTrue($after->execute([1]));
47 self::assertSame('after', $after->fetchColumn());
48 $result1 = $native->query('SELECT COUNT(*) FROM items');
49 self::assertNotFalse($result1);
50 self::assertSame(0, $result1->fetchColumn());
51 }
52
53 public function testPrepareReportsASilentDriverFailure(): void
54 {
55 $native = new PDO('sqlite::memory:', options: [PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT]);
56 $session = (new SqliteSessionFactory())->create(new PdoConnection($native), ZtdConfig::default());
57 $query = new PreparedQuery($session, 'SELECT 1', static fn (string $sql): PDOStatement|false => $native->prepare($sql));
58 $this->expectException(ZtdPdoException::class);
59 $this->expectExceptionMessage('PDO failed to prepare rewritten SQL.');
60 $query->prepare('SELECT * FROM missing_table');
61 }
62}
63