packages/ztd-query-core/tests/Unit/ResultSelectRunnerTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use stdClass;
11use Tests\Fake\FakeStatement;
12use ZtdQuery\Connection\ResultColumn;
13use ZtdQuery\Connection\ResultSet;
14use ZtdQuery\Platform\ResultColumnTypeResolver;
15use ZtdQuery\ResultSelectRunner;
16use ZtdQuery\Schema\ColumnDeclaration;
17use ZtdQuery\Schema\ColumnTypeFamily;
18
19#[CoversClass(ResultSelectRunner::class)]
20#[UsesClass(ColumnDeclaration::class)]
21#[UsesClass(ResultColumn::class)]
22#[UsesClass(ResultSet::class)]
23#[UsesClass(\ZtdQuery\Schema\RowSet::class)]
24final class ResultSelectRunnerTest extends TestCase
25{
26 public function testRunReturnsRowsFromExecutor(): void
27 {
28 $runner = new ResultSelectRunner();
29 $rows = [['id' => 1, 'name' => 'Alice']];
30
31 $resolver = self::createStub(ResultColumnTypeResolver::class);
32 $result = $runner->run('SELECT * FROM users', fn () => new FakeStatement($rows), $resolver);
33
34 self::assertSame($rows, $result);
35 }
36
37 public function testRunReturnsEmptyWhenExecutorReturnsFalse(): void
38 {
39 $runner = new ResultSelectRunner();
40
41 $resolver = self::createStub(ResultColumnTypeResolver::class);
42 $result = $runner->run('SELECT * FROM users', fn () => false, $resolver);
43
44 self::assertSame([], $result);
45 }
46
47 public function testRunPreservesSparseDriverRowsAndOpaqueValues(): void
48 {
49 $rows = [7 => ['id' => 1, 'payload' => new stdClass()], 12 => ['id' => 2, 'payload' => ['nested']]];
50 $resolver = self::createStub(ResultColumnTypeResolver::class);
51
52 $result = (new ResultSelectRunner())->run('SELECT * FROM users', fn () => new FakeStatement($rows), $resolver);
53
54 self::assertSame($rows, $result);
55 }
56
57 public function testRunStatementReturnsRows(): void
58 {
59 $runner = new ResultSelectRunner();
60 $rows = [['id' => 1]];
61 $statement = new FakeStatement($rows);
62
63 $resolver = self::createStub(ResultColumnTypeResolver::class);
64 $result = $runner->runStatement($statement, $resolver);
65
66 self::assertSame($rows, $result);
67 self::assertTrue($statement->isExecuted());
68 }
69
70 public function testRunResultSetRetainsColumnsWhenRowsAreEmpty(): void
71 {
72 $runner = new ResultSelectRunner();
73 $column = new ResultColumn('id', new ColumnDeclaration(ColumnTypeFamily::INTEGER, 'int4'));
74
75 $resolver = self::createStub(ResultColumnTypeResolver::class);
76 $result = $runner->runResultSet(
77 'SELECT id FROM users WHERE FALSE',
78 fn () => new FakeStatement([], [$column]),
79 $resolver,
80 );
81
82 self::assertSame([], $result->rows);
83 self::assertSame([$column], $result->columns);
84 }
85
86 public function testReadResultSetReadsMetadataBeforeRows(): void
87 {
88 $runner = new ResultSelectRunner();
89 $column = new ResultColumn('id', new ColumnDeclaration(ColumnTypeFamily::INTEGER, 'int4'));
90 $statement = new FakeStatement([['id' => 1]], [$column]);
91
92 $resolver = self::createStub(ResultColumnTypeResolver::class);
93 $result = $runner->readResultSet($statement, $resolver);
94
95 self::assertSame([['id' => 1]], $result->rows);
96 self::assertSame([$column], $result->columns);
97 }
98
99 public function testReadResultSetPassesPlatformTypeResolverToStatement(): void
100 {
101 $resolver = self::createStub(ResultColumnTypeResolver::class);
102 $statement = new FakeStatement();
103
104 (new ResultSelectRunner())->readResultSet($statement, $resolver);
105
106 self::assertSame([$resolver], $statement->typeResolversAsked());
107 }
108}
109