packages/ztd-query-pdo-adapter/tests/Integration/Sqlite/SelectCteTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Integration\Sqlite;
6
7use PDO;
8use PHPUnit\Framework\Attributes\CoversNothing;
9use PHPUnit\Framework\Attributes\Large;
10use PHPUnit\Framework\TestCase;
11use ZtdQuery\Adapter\Pdo\ZtdPdo;
12
13/**
14 * @requires extension pdo_sqlite
15 *
16 * @phpstan-type Row array<string, mixed>
17 */
18#[CoversNothing]
19#[Large]
20final class SelectCteTest extends TestCase
21{
22 public function testSimpleCte(): void
23 {
24 $rawPdo = new PDO('sqlite::memory:', null, null, [
25 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
26 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
27 ]);
28 $rawPdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL)');
29 $rawPdo->exec("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Charlie', 35)");
30
31 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
32 $ztdPdo->exec("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Charlie', 35)");
33
34 $sql = 'WITH seniors AS (SELECT * FROM users WHERE age >= 30) SELECT * FROM seniors ORDER BY id';
35
36 $stmt = $rawPdo->query($sql);
37 self::assertNotFalse($stmt);
38 /** @var list<Row> $rawRows */
39 $rawRows = $stmt->fetchAll();
40 $stmt = $ztdPdo->query($sql);
41 self::assertNotFalse($stmt);
42 /** @var list<Row> $ztdRows */
43 $ztdRows = $stmt->fetchAll();
44
45 self::assertSame($rawRows, $ztdRows);
46 }
47
48 public function testMultipleCtesAreSupported(): void
49 {
50 $rawPdo = new PDO('sqlite::memory:', null, null, [
51 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
52 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
53 ]);
54 $rawPdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL)');
55 $rawPdo->exec("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Charlie', 35)");
56
57 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
58 $ztdPdo->exec("INSERT INTO users (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Charlie', 35)");
59
60 $sql = 'WITH young AS (SELECT * FROM users WHERE age < 30), old AS (SELECT * FROM users WHERE age >= 30) SELECT * FROM young UNION ALL SELECT * FROM old ORDER BY id';
61
62 $stmt = $ztdPdo->query($sql);
63 self::assertNotFalse($stmt);
64 /** @var list<Row> $ztdRows */
65 $ztdRows = $stmt->fetchAll();
66 self::assertNotEmpty($ztdRows);
67 }
68
69 public function testUserCteMayOwnTheSameNameAsAPhysicalTable(): void
70 {
71 $rawPdo = new PDO('sqlite::memory:', null, null, [
72 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
73 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
74 ]);
75 $rawPdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER NOT NULL)');
76 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
77 $ztdPdo->exec("INSERT INTO users VALUES (1, 'shadow', 30)");
78
79 $statement = $ztdPdo->query("WITH users AS (SELECT 9 AS id, 'cte' AS name, 99 AS age) SELECT * FROM users");
80 self::assertNotFalse($statement);
81 self::assertSame([['id' => 9, 'name' => 'cte', 'age' => 99]], $statement->fetchAll());
82 }
83}
84