Skip to content

Commit 9793e66

Browse files
committed
Fix result set rows for DDL queries to be null, instead of empty array
The result set for DDL queries (INSERT, UPDATE, DELETE etc.) is empty, i.e. it does not contain any columns or rows. Columns and rows should thus be represented by a null value. In contrast, an empty result set from a SELECT query will always contain a non-empty array of columns and may contain any number of rows (possibly an empty array of rows).
1 parent d8f0d34 commit 9793e66

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

res/sqlite-worker.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,15 @@
172172
'error' => array('message' => $db->lastErrorMsg())
173173
));
174174
} else {
175-
$columns = array();
176-
for ($i = 0, $n = $result->numColumns(); $i < $n; ++$i) {
177-
$columns[] = $result->columnName($i);
178-
}
179-
180-
$rows = array();
181175
if ($result->numColumns() !== 0) {
182176
// Fetch all rows only if this result set has any columns.
183177
// INSERT/UPDATE/DELETE etc. do not return any columns, trying
184178
// to fetch the results here will issue the same query again.
179+
$rows = $columns = [];
180+
for ($i = 0, $n = $result->numColumns(); $i < $n; ++$i) {
181+
$columns[] = $result->columnName($i);
182+
}
183+
185184
while (($row = $result->fetchArray(\SQLITE3_ASSOC)) !== false) {
186185
// base64-encode any string that is not valid UTF-8 without control characters (BLOB)
187186
foreach ($row as &$value) {
@@ -193,6 +192,8 @@
193192
}
194193
$rows[] = $row;
195194
}
195+
} else {
196+
$rows = $columns = null;
196197
}
197198
$result->finalize();
198199

src/Io/ProcessIoDatabase.php

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,19 @@ public function query($sql, array $params = array())
9090
$result->changed = $data['changed'];
9191
$result->insertId = $data['insertId'];
9292
$result->columns = $data['columns'];
93+
$result->rows = $data['rows'];
9394

9495
// base64-decode string result values for BLOBS
95-
$result->rows = [];
96-
foreach ($data['rows'] as $row) {
97-
foreach ($row as &$value) {
98-
if (isset($value['base64'])) {
99-
$value = \base64_decode($value['base64']);
100-
} elseif (isset($value['float'])) {
101-
$value = (float)$value['float'];
96+
if ($result->rows !== null) {
97+
foreach ($result->rows as &$row) {
98+
foreach ($row as &$value) {
99+
if (isset($value['base64'])) {
100+
$value = \base64_decode($value['base64']);
101+
} elseif (isset($value['float'])) {
102+
$value = (float)$value['float'];
103+
}
102104
}
103105
}
104-
$result->rows[] = $row;
105106
}
106107

107108
return $result;

tests/FunctionalDatabaseTest.php

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ public function testExecRejectsWhenAlreadyClosed($flag)
658658
* @dataProvider provideSocketFlags
659659
* @param bool $flag
660660
*/
661-
public function testQueryInsertResolvesWithResultWithLastInsertIdAndRunsUntilQuit($flag)
661+
public function testQueryInsertResolvesWithEmptyResultSetWithLastInsertIdAndRunsUntilQuit($flag)
662662
{
663663
$loop = React\EventLoop\Factory::create();
664664
$factory = new Factory($loop);
@@ -673,15 +673,50 @@ public function testQueryInsertResolvesWithResultWithLastInsertIdAndRunsUntilQui
673673
$promise->then(function (DatabaseInterface $db) use (&$data){
674674
$db->exec('CREATE TABLE foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar STRING)');
675675
$db->query('INSERT INTO foo (bar) VALUES (?)', ['test'])->then(function (Result $result) use (&$data) {
676-
$data = $result->insertId;
677-
});
676+
$data = $result;
677+
}, 'printf');
678+
679+
$db->quit();
680+
});
681+
682+
$loop->run();
683+
684+
$this->assertInstanceOf('Clue\React\SQLite\Result', $data);
685+
$this->assertSame(1, $data->insertId);
686+
$this->assertNull($data->columns);
687+
$this->assertNull($data->rows);
688+
}
689+
690+
/**
691+
* @dataProvider provideSocketFlags
692+
* @param bool $flag
693+
*/
694+
public function testQuerySelectEmptyResolvesWithEmptyResultSetWithColumnsAndNoRowsAndRunsUntilQuit($flag)
695+
{
696+
$loop = React\EventLoop\Factory::create();
697+
$factory = new Factory($loop);
698+
699+
$ref = new ReflectionProperty($factory, 'useSocket');
700+
$ref->setAccessible(true);
701+
$ref->setValue($factory, $flag);
702+
703+
$promise = $factory->open(':memory:');
704+
705+
$data = null;
706+
$promise->then(function (DatabaseInterface $db) use (&$data){
707+
$db->exec('CREATE TABLE foo (id INTEGER PRIMARY KEY AUTOINCREMENT, bar STRING)');
708+
$db->query('SELECT * FROM foo LIMIT 0')->then(function (Result $result) use (&$data) {
709+
$data = $result;
710+
}, 'printf');
678711

679712
$db->quit();
680713
});
681714

682715
$loop->run();
683716

684-
$this->assertSame(1, $data);
717+
$this->assertInstanceOf('Clue\React\SQLite\Result', $data);
718+
$this->assertSame(['id', 'bar'], $data->columns);
719+
$this->assertSame([], $data->rows);
685720
}
686721

687722
protected function expectCallableNever()

0 commit comments

Comments
 (0)