Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions res/sqlite-worker.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,34 +132,38 @@
if ($data->params[1] === []) {
$result = @$db->query($data->params[0]);
} else {
$statement = $db->prepare($data->params[0]);
foreach ($data->params[1] as $index => $value) {
if ($value === null) {
$type = \SQLITE3_NULL;
} elseif ($value === true || $value === false) {
// explicitly cast bool to int because SQLite does not have a native boolean
$type = \SQLITE3_INTEGER;
$value = (int)$value;
} elseif (\is_int($value)) {
$type = \SQLITE3_INTEGER;
} elseif (isset($value->float)) {
$type = \SQLITE3_FLOAT;
$value = (float)$value->float;
} elseif (isset($value->base64)) {
// base64-decode string parameters as BLOB
$type = \SQLITE3_BLOB;
$value = \base64_decode($value->base64);
} else {
$type = \SQLITE3_TEXT;
}
$statement = @$db->prepare($data->params[0]);
if ($statement === false) {
$result = false;
} else {
foreach ($data->params[1] as $index => $value) {
if ($value === null) {
$type = \SQLITE3_NULL;
} elseif ($value === true || $value === false) {
// explicitly cast bool to int because SQLite does not have a native boolean
$type = \SQLITE3_INTEGER;
$value = (int)$value;
} elseif (\is_int($value)) {
$type = \SQLITE3_INTEGER;
} elseif (isset($value->float)) {
$type = \SQLITE3_FLOAT;
$value = (float)$value->float;
} elseif (isset($value->base64)) {
// base64-decode string parameters as BLOB
$type = \SQLITE3_BLOB;
$value = \base64_decode($value->base64);
} else {
$type = \SQLITE3_TEXT;
}

$statement->bindValue(
\is_int($index) ? $index + 1 : $index,
$value,
$type
);
$statement->bindValue(
\is_int($index) ? $index + 1 : $index,
$value,
$type
);
}
$result = @$statement->execute();
}
$result = @$statement->execute();
}

if ($result === false) {
Expand Down
6 changes: 3 additions & 3 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,11 @@ private function openProcessIo($filename, $flags = null)
}
// @codeCoverageIgnoreEnd

// launch process with default STDIO pipes
// launch process with default STDIO pipes, but inherit STDERR
$pipes = array(
array('pipe', 'r'),
array('pipe', 'w'),
array('pipe', 'w')
\defined('STDERR') ? \STDERR : \fopen('php://stderr', 'w')
);

// do not inherit open FDs by explicitly overwriting existing FDs with dummy files
Expand Down Expand Up @@ -253,7 +253,7 @@ private function openSocketIo($filename, $flags = null)
{
$command = \escapeshellarg($this->bin) . ' sqlite-worker.php';

// launch process without default STDIO pipes
// launch process without default STDIO pipes, but inherit STDERR
$null = \DIRECTORY_SEPARATOR === '\\' ? 'nul' : '/dev/null';
$pipes = array(
array('file', $null, 'r'),
Expand Down
58 changes: 58 additions & 0 deletions tests/FunctionalDatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,64 @@ public function testQueryStringResolvesWithResultWithTypeStringAndRunsUntilQuit(
$this->assertSame(array(array('value' => 'hellö')), $data);
}

/**
* @dataProvider provideSocketFlags
* @param bool $flag
*/
public function testQueryInvalidTableRejectsWithExceptionAndRunsUntilQuit($flag)
{
$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);

$ref = new ReflectionProperty($factory, 'useSocket');
$ref->setAccessible(true);
$ref->setValue($factory, $flag);

$promise = $factory->open(':memory:');

$data = null;
$promise->then(function (DatabaseInterface $db) use (&$data){
$db->query('SELECT 1 FROM foo')->then('var_dump', function (Exception $e) use (&$data) {
$data = $e->getMessage();
});

$db->quit();
});

$loop->run();

$this->assertSame('no such table: foo', $data);
}

/**
* @dataProvider provideSocketFlags
* @param bool $flag
*/
public function testQueryInvalidTableWithPlaceholderRejectsWithExceptionAndRunsUntilQuit($flag)
{
$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);

$ref = new ReflectionProperty($factory, 'useSocket');
$ref->setAccessible(true);
$ref->setValue($factory, $flag);

$promise = $factory->open(':memory:');

$data = null;
$promise->then(function (DatabaseInterface $db) use (&$data){
$db->query('SELECT ? FROM foo', [1])->then('var_dump', function (Exception $e) use (&$data) {
$data = $e->getMessage();
});

$db->quit();
});

$loop->run();

$this->assertSame('no such table: foo', $data);
}

public function provideSqlDataWillBeReturnedWithType()
{
return array_merge(
Expand Down