mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-22 13:12:41 +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:
parent
2b7a236147
commit
eeb1818bb5
8 changed files with 54 additions and 31 deletions
|
@ -23,6 +23,7 @@ abstract class AbstractException extends \Exception {
|
|||
"Db/Exception.fileCorrupt" => 10207,
|
||||
"Db/Exception.paramTypeInvalid" => 10401,
|
||||
"Db/Exception.paramTypeUnknown" => 10402,
|
||||
"Db/Exception.paramTypeMissing" => 10403,
|
||||
"Db/Update/Exception.tooNew" => 10211,
|
||||
"Db/Update/Exception.fileMissing" => 10212,
|
||||
"Db/Update/Exception.fileUnusable" => 10213,
|
||||
|
|
|
@ -291,7 +291,10 @@ class Database {
|
|||
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,
|
||||
$feed->title,
|
||||
// Grab the favicon for the Goodfeed; returns an empty string if it cannot find one.
|
||||
|
|
|
@ -38,7 +38,7 @@ class DriverSQLite3 extends AbstractDriver {
|
|||
|
||||
|
||||
static public function driverName(): string {
|
||||
return "SQLite 3";
|
||||
return Lang::msg("Driver.Db.$name.Name");
|
||||
}
|
||||
|
||||
public function schemaVersion(): int {
|
||||
|
|
|
@ -26,7 +26,7 @@ class StatementSQLite3 extends AbstractStatement {
|
|||
}
|
||||
|
||||
public function __destruct() {
|
||||
$this->st->close();
|
||||
try {$this->st->close();} catch(\Throwable $e) {}
|
||||
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]);
|
||||
$type = self::BINDINGS[$this->types[$a]];
|
||||
} else {
|
||||
$type = \SQLITE3_TEXT;
|
||||
throw new Exception("paramTypeMissing", $a+1);
|
||||
}
|
||||
// cast value if necessary
|
||||
$values[$a] = $this->cast($values[$a], $this->types[$a]);
|
||||
// re-adjust for null casts
|
||||
if($values[$a]===null) $type = \SQLITE3_NULL;
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use \Webmozart\Glob\Glob;
|
|||
class Lang {
|
||||
const DEFAULT = "en"; // fallback locale
|
||||
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/Lang/Exception.defaultFileMissing' => 'Default language file "{0}" missing',
|
||||
'Exception.JKingWeb/NewsSync/Lang/Exception.fileMissing' => 'Language file "{0}" is not available',
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
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!)
|
||||
'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
|
||||
'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.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.paramTypeMissing' => 'Prepared statement parameter type for parameter #{0} was not specified',
|
||||
|
||||
'Exception.JKingWeb/NewsSync/Db/Update/Exception.manual' =>
|
||||
'{from_version, select,
|
||||
|
|
|
@ -1,32 +1,66 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace JKingWeb\NewsSync;
|
||||
use JKingWeb\NewsSync\Db\Statement;
|
||||
|
||||
|
||||
class TestDbStatementSQLite3 extends \PHPUnit\Framework\TestCase {
|
||||
use Test\Tools, Test\Db\BindingTests;
|
||||
|
||||
protected $c;
|
||||
protected $s;
|
||||
static protected $imp = Db\StatementSQLite3::class;
|
||||
|
||||
function setUp() {
|
||||
date_default_timezone_set("UTC");
|
||||
$c = new \SQLite3(":memory:");
|
||||
$c->enableExceptions(true);
|
||||
$s = $c->prepare("SELECT ? as value");
|
||||
$this->c = $c;
|
||||
$this->s = $s;
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
try {$this->s->close();} catch(\Exception $e) {}
|
||||
$this->c->close();
|
||||
unset($this->s);
|
||||
unset($this->c);
|
||||
}
|
||||
|
||||
function testConstructStatement() {
|
||||
$this->assertInstanceOf(Db\StatementSQLite3::class, new Db\StatementSQLite3($this->c, $this->s));
|
||||
protected function checkBinding($input, array $expectations) {
|
||||
$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();
|
||||
}
|
||||
}
|
|
@ -4,13 +4,6 @@ namespace JKingWeb\NewsSync\Test\Db;
|
|||
use JKingWeb\NewsSync\Db\Statement;
|
||||
|
||||
trait BindingTests {
|
||||
|
||||
function testBindMissingValue() {
|
||||
$s = new self::$imp($this->c, $this->s);
|
||||
$val = $s->runArray()->get()['value'];
|
||||
$this->assertSame(null, $val);
|
||||
}
|
||||
|
||||
function testBindNull() {
|
||||
$input = null;
|
||||
$exp = [
|
||||
|
@ -226,14 +219,4 @@ trait BindingTests {
|
|||
function testBindImmutableDateObject() {
|
||||
$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.");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue