packages/ztd-query-pdo-adapter/tests/Integration/Sqlite/SelectSubqueryTest.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 SelectSubqueryTest extends TestCase
21{
22 public function testSubqueryInWhere(): 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)');
29 $rawPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
30 $rawPdo->exec('CREATE TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, amount INTEGER NOT NULL)');
31 $rawPdo->exec('INSERT INTO orders (id, user_id, amount) VALUES (1, 1, 100), (2, 1, 200), (3, 2, 150)');
32
33 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
34 $ztdPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
35 $ztdPdo->exec('INSERT INTO orders (id, user_id, amount) VALUES (1, 1, 100), (2, 1, 200), (3, 2, 150)');
36
37 $sql = 'SELECT * FROM users WHERE id IN (SELECT user_id FROM orders) ORDER BY id';
38
39 $stmt = $rawPdo->query($sql);
40 self::assertNotFalse($stmt);
41 /** @var list<Row> $rawRows */
42 $rawRows = $stmt->fetchAll();
43 $stmt = $ztdPdo->query($sql);
44 self::assertNotFalse($stmt);
45 /** @var list<Row> $ztdRows */
46 $ztdRows = $stmt->fetchAll();
47
48 self::assertSame($rawRows, $ztdRows);
49 }
50
51 public function testScalarSubquery(): void
52 {
53 $rawPdo = new PDO('sqlite::memory:', null, null, [
54 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
55 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
56 ]);
57 $rawPdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
58 $rawPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
59 $rawPdo->exec('CREATE TABLE orders (id INTEGER PRIMARY KEY, user_id INTEGER NOT NULL, amount INTEGER NOT NULL)');
60 $rawPdo->exec('INSERT INTO orders (id, user_id, amount) VALUES (1, 1, 100), (2, 1, 200), (3, 2, 150)');
61
62 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
63 $ztdPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
64 $ztdPdo->exec('INSERT INTO orders (id, user_id, amount) VALUES (1, 1, 100), (2, 1, 200), (3, 2, 150)');
65
66 $sql = 'SELECT name, (SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) AS order_count FROM users ORDER BY id';
67
68 $stmt = $rawPdo->query($sql);
69 self::assertNotFalse($stmt);
70 /** @var list<Row> $rawRows */
71 $rawRows = $stmt->fetchAll();
72 $stmt = $ztdPdo->query($sql);
73 self::assertNotFalse($stmt);
74 /** @var list<Row> $ztdRows */
75 $ztdRows = $stmt->fetchAll();
76
77 self::assertSame($rawRows, $ztdRows);
78 }
79
80 public function testSubqueryInFrom(): void
81 {
82 $rawPdo = new PDO('sqlite::memory:', null, null, [
83 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
84 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
85 ]);
86 $rawPdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
87 $rawPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
88
89 $ztdPdo = ZtdPdo::fromPdo($rawPdo);
90 $ztdPdo->exec("INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie')");
91
92 $sql = 'SELECT sub.name FROM (SELECT name FROM users WHERE id <= 2) AS sub ORDER BY sub.name';
93
94 $stmt = $rawPdo->query($sql);
95 self::assertNotFalse($stmt);
96 /** @var list<Row> $rawRows */
97 $rawRows = $stmt->fetchAll();
98 $stmt = $ztdPdo->query($sql);
99 self::assertNotFalse($stmt);
100 /** @var list<Row> $ztdRows */
101 $ztdRows = $stmt->fetchAll();
102
103 self::assertSame($rawRows, $ztdRows);
104 }
105}
106