1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Still more database changes

- Restructured tests
- Localized driver name for SQLite driver (fixes #37)
- Ensured that binding type definitions are required
This commit is contained in:
J. King 2017-03-03 13:20:26 -05:00
parent 2b7a236147
commit eeb1818bb5
8 changed files with 54 additions and 31 deletions

View file

@ -23,6 +23,7 @@ abstract class AbstractException extends \Exception {
"Db/Exception.fileCorrupt" => 10207, "Db/Exception.fileCorrupt" => 10207,
"Db/Exception.paramTypeInvalid" => 10401, "Db/Exception.paramTypeInvalid" => 10401,
"Db/Exception.paramTypeUnknown" => 10402, "Db/Exception.paramTypeUnknown" => 10402,
"Db/Exception.paramTypeMissing" => 10403,
"Db/Update/Exception.tooNew" => 10211, "Db/Update/Exception.tooNew" => 10211,
"Db/Update/Exception.fileMissing" => 10212, "Db/Update/Exception.fileMissing" => 10212,
"Db/Update/Exception.fileUnusable" => 10213, "Db/Update/Exception.fileUnusable" => 10213,

View file

@ -291,7 +291,10 @@ class Database {
throw new Feed\Exception($url, $e); throw new Feed\Exception($url, $e);
} }
$this->db->prepare("INSERT INTO newssync_feeds(url,title,favicon,source,updated,modified,etag,username,password) values(?,?,?,?,?,?,?,?,?)", "str", "str", "str", "str", "datetime", "datetime", "str", "str", "str")->run( $this->db->prepare(
"INSERT INTO newssync_feeds(url,title,favicon,source,updated,modified,etag,username,password) values(?,?,?,?,?,?,?,?,?)",
"str", "str", "str", "str", "datetime", "datetime", "str", "str", "str"
)->run(
$url, $url,
$feed->title, $feed->title,
// Grab the favicon for the Goodfeed; returns an empty string if it cannot find one. // Grab the favicon for the Goodfeed; returns an empty string if it cannot find one.

View file

@ -38,7 +38,7 @@ class DriverSQLite3 extends AbstractDriver {
static public function driverName(): string { static public function driverName(): string {
return "SQLite 3"; return Lang::msg("Driver.Db.$name.Name");
} }
public function schemaVersion(): int { public function schemaVersion(): int {

View file

@ -26,7 +26,7 @@ class StatementSQLite3 extends AbstractStatement {
} }
public function __destruct() { public function __destruct() {
$this->st->close(); try {$this->st->close();} catch(\Throwable $e) {}
unset($this->st); unset($this->st);
} }
@ -49,14 +49,14 @@ class StatementSQLite3 extends AbstractStatement {
if(!array_key_exists($this->types[$a], self::BINDINGS)) throw new Exception("paramTypeUnknown", $this->types[$a]); if(!array_key_exists($this->types[$a], self::BINDINGS)) throw new Exception("paramTypeUnknown", $this->types[$a]);
$type = self::BINDINGS[$this->types[$a]]; $type = self::BINDINGS[$this->types[$a]];
} else { } else {
$type = \SQLITE3_TEXT; throw new Exception("paramTypeMissing", $a+1);
} }
// cast value if necessary // cast value if necessary
$values[$a] = $this->cast($values[$a], $this->types[$a]); $values[$a] = $this->cast($values[$a], $this->types[$a]);
// re-adjust for null casts // re-adjust for null casts
if($values[$a]===null) $type = \SQLITE3_NULL; if($values[$a]===null) $type = \SQLITE3_NULL;
// perform binding // perform binding
$this->st->bindParam($a+1, $values[$a], $type); $this->st->bindValue($a+1, $values[$a], $type);
} }
return new ResultSQLite3($this->st->execute(), $this->db->changes(), $this); return new ResultSQLite3($this->st->execute(), $this->db->changes(), $this);
} }

View file

@ -6,7 +6,7 @@ use \Webmozart\Glob\Glob;
class Lang { class Lang {
const DEFAULT = "en"; // fallback locale const DEFAULT = "en"; // fallback locale
const REQUIRED = [ // collection of absolutely required strings to handle pathological errors const REQUIRED = [ // collection of absolutely required strings to handle pathological errors
'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in Exception.php', 'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred', 'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred',
'Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing', 'Exception.JKingWeb/NewsSync/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
'Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing' => 'Language file "{0}" is not available', 'Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',

View file

@ -1,9 +1,10 @@
<?php <?php
return [ return [
'Driver.User.Internal.Name' => 'Internal', 'Driver.User.Internal.Name' => 'Internal',
'Driver.Db.SQLite3.Name' => 'SQLite 3',
// this should only be encountered in testing (because tests should cover all exceptions!) // this should only be encountered in testing (because tests should cover all exceptions!)
'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in Exception.php', 'Exception.JKingWeb/NewsSync/Exception.uncoded' => 'The specified exception symbol {0} has no code specified in AbstractException.php',
// this should not usually be encountered // this should not usually be encountered
'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred', 'Exception.JKingWeb/NewsSync/Exception.unknown' => 'An unknown error has occurred',
@ -29,6 +30,7 @@ return [
'Exception.JKingWeb/NewsSync/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database', 'Exception.JKingWeb/NewsSync/Db/Exception.fileCorrupt' => 'Database file "{0}" is corrupt or not a valid database',
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid', 'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeInvalid' => 'Prepared statement parameter type "{0}" is invalid',
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented', 'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeUnknown' => 'Prepared statement parameter type "{0}" is valid, but not implemented',
'Exception.JKingWeb/NewsSync/Db/Exception.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
'Exception.JKingWeb/NewsSync/Db/Update/Exception.manual' => 'Exception.JKingWeb/NewsSync/Db/Update/Exception.manual' =>
'{from_version, select, '{from_version, select,

View file

@ -1,32 +1,66 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace JKingWeb\NewsSync; namespace JKingWeb\NewsSync;
use JKingWeb\NewsSync\Db\Statement;
class TestDbStatementSQLite3 extends \PHPUnit\Framework\TestCase { class TestDbStatementSQLite3 extends \PHPUnit\Framework\TestCase {
use Test\Tools, Test\Db\BindingTests; use Test\Tools, Test\Db\BindingTests;
protected $c; protected $c;
protected $s;
static protected $imp = Db\StatementSQLite3::class; static protected $imp = Db\StatementSQLite3::class;
function setUp() { function setUp() {
date_default_timezone_set("UTC"); date_default_timezone_set("UTC");
$c = new \SQLite3(":memory:"); $c = new \SQLite3(":memory:");
$c->enableExceptions(true); $c->enableExceptions(true);
$s = $c->prepare("SELECT ? as value");
$this->c = $c; $this->c = $c;
$this->s = $s;
} }
function tearDown() { function tearDown() {
try {$this->s->close();} catch(\Exception $e) {} try {$this->s->close();} catch(\Exception $e) {}
$this->c->close(); $this->c->close();
unset($this->s);
unset($this->c); unset($this->c);
} }
function testConstructStatement() { protected function checkBinding($input, array $expectations) {
$this->assertInstanceOf(Db\StatementSQLite3::class, new Db\StatementSQLite3($this->c, $this->s)); $nativeStatement = $this->c->prepare("SELECT ? as value");
$s = new self::$imp($this->c, $nativeStatement);
$types = array_unique(Statement::TYPES);
foreach($types as $type) {
$s->rebindArray([$type]);
$val = $s->runArray([$input])->get()['value'];
$this->assertSame($expectations[$type], $val, "Type $type failed comparison.");
}
} }
function testConstructStatement() {
$nativeStatement = $this->c->prepare("SELECT ? as value");
$this->assertInstanceOf(Db\StatementSQLite3::class, new Db\StatementSQLite3($this->c, $nativeStatement));
}
function testBindMissingValue() {
$nativeStatement = $this->c->prepare("SELECT ? as value");
$s = new self::$imp($this->c, $nativeStatement);
$val = $s->runArray()->get()['value'];
$this->assertSame(null, $val);
}
function testBindMultipleValues() {
$exp = [
'one' => 1,
'two' => 2,
];
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two");
$s = new self::$imp($this->c, $nativeStatement, ["int", "int"]);
$val = $s->runArray([1,2])->get();
$this->assertSame($exp, $val);
}
function testBindWithoutType() {
$this->assertException("paramTypeMissing", "Db");
$nativeStatement = $this->c->prepare("SELECT ? as value");
$s = new self::$imp($this->c, $nativeStatement, []);
$val = $s->runArray([1])->get();
}
} }

View file

@ -4,13 +4,6 @@ namespace JKingWeb\NewsSync\Test\Db;
use JKingWeb\NewsSync\Db\Statement; use JKingWeb\NewsSync\Db\Statement;
trait BindingTests { trait BindingTests {
function testBindMissingValue() {
$s = new self::$imp($this->c, $this->s);
$val = $s->runArray()->get()['value'];
$this->assertSame(null, $val);
}
function testBindNull() { function testBindNull() {
$input = null; $input = null;
$exp = [ $exp = [
@ -226,14 +219,4 @@ trait BindingTests {
function testBindImmutableDateObject() { function testBindImmutableDateObject() {
$this->testBindMutableDateObject('\DateTimeImmutable'); $this->testBindMutableDateObject('\DateTimeImmutable');
} }
protected function checkBinding($input, array $expectations) {
$s = new self::$imp($this->c, $this->s);
$types = array_unique(Statement::TYPES);
foreach($types as $type) {
$s->rebindArray([$type]);
$val = $s->runArray([$input])->get()['value'];
$this->assertSame($expectations[$type], $val, "Type $type failed comparison.");
}
}
} }