J. King
6 years ago
2 changed files with 271 additions and 536 deletions
@ -1,299 +0,0 @@ |
|||
<?php |
|||
/** @license MIT |
|||
* Copyright 2017 J. King, Dustin Wilson et al. |
|||
* See LICENSE and AUTHORS files for details */ |
|||
|
|||
declare(strict_types=1); |
|||
namespace JKingWeb\Arsse\TestCase\Db\SQLite3PDO; |
|||
|
|||
use JKingWeb\Arsse\Db\Statement; |
|||
use JKingWeb\Arsse\Db\PDOStatement; |
|||
use JKingWeb\Arsse\Db\SQLite3\PDODriver; |
|||
|
|||
/** |
|||
* @covers \JKingWeb\Arsse\Db\PDOStatement<extended> |
|||
* @covers \JKingWeb\Arsse\Db\PDOError */ |
|||
class TestStatement extends \JKingWeb\Arsse\Test\AbstractTest { |
|||
protected $c; |
|||
protected static $imp = \JKingWeb\Arsse\Db\PDOStatement::class; |
|||
|
|||
public function setUp() { |
|||
if (!PDODriver::requirementsMet()) { |
|||
$this->markTestSkipped("PDO-SQLite extension not loaded"); |
|||
} |
|||
$this->clearData(); |
|||
$c = new \PDO("sqlite::memory:", "", "", [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]); |
|||
$this->c = $c; |
|||
} |
|||
|
|||
public function tearDown() { |
|||
unset($this->c); |
|||
$this->clearData(); |
|||
} |
|||
|
|||
/** @dataProvider provideBindings */ |
|||
public function testBindATypedValue($value, $type, $exp) { |
|||
$typeStr = "'".str_replace("'", "''", $type)."'"; |
|||
$nativeStatement = $this->c->prepare( |
|||
"SELECT ( |
|||
(CASE WHEN substr($typeStr, 0, 7) <> 'strict ' then null else 1 end) is null |
|||
and ? is null |
|||
) or ( |
|||
$exp = ? |
|||
) as pass" |
|||
); |
|||
$s = new self::$imp($this->c, $nativeStatement); |
|||
$s->retype(...[$type, $type]); |
|||
$act = (bool) $s->run(...[$value, $value])->getRow()['pass']; |
|||
$this->assertTrue($act); |
|||
} |
|||
|
|||
public function provideBindings() { |
|||
$dateMutable = new \DateTime("Noon Today", new \DateTimezone("America/Toronto")); |
|||
$dateImmutable = new \DateTimeImmutable("Noon Today", new \DateTimezone("America/Toronto")); |
|||
$dateUTC = new \DateTime("@".$dateMutable->getTimestamp(), new \DateTimezone("UTC")); |
|||
return [ |
|||
/* input, type, expected binding as SQL fragment */ |
|||
[null, "integer", "null"], |
|||
[null, "float", "null"], |
|||
[null, "string", "null"], |
|||
[null, "binary", "null"], |
|||
[null, "datetime", "null"], |
|||
[null, "boolean", "null"], |
|||
[null, "strict integer", "0"], |
|||
[null, "strict float", "'0'"], |
|||
[null, "strict string", "''"], |
|||
[null, "strict binary", "x''"], |
|||
[null, "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[null, "strict boolean", "0"], |
|||
// true |
|||
[true, "integer", "1"], |
|||
[true, "float", "'1'"], |
|||
[true, "string", "'1'"], |
|||
[true, "binary", "x'31'"], |
|||
[true, "datetime", "null"], |
|||
[true, "boolean", "1"], |
|||
[true, "strict integer", "1"], |
|||
[true, "strict float", "'1'"], |
|||
[true, "strict string", "'1'"], |
|||
[true, "strict binary", "x'31'"], |
|||
[true, "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[true, "strict boolean", "1"], |
|||
// false |
|||
[false, "integer", "0"], |
|||
[false, "float", "'0'"], |
|||
[false, "string", "''"], |
|||
[false, "binary", "x''"], |
|||
[false, "datetime", "null"], |
|||
[false, "boolean", "0"], |
|||
[false, "strict integer", "0"], |
|||
[false, "strict float", "'0'"], |
|||
[false, "strict string", "''"], |
|||
[false, "strict binary", "x''"], |
|||
[false, "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[false, "strict boolean", "0"], |
|||
// integer |
|||
[2112, "integer", "2112"], |
|||
[2112, "float", "'2112'"], |
|||
[2112, "string", "'2112'"], |
|||
[2112, "binary", "x'32313132'"], |
|||
[2112, "datetime", "'1970-01-01 00:35:12'"], |
|||
[2112, "boolean", "1"], |
|||
[2112, "strict integer", "2112"], |
|||
[2112, "strict float", "'2112'"], |
|||
[2112, "strict string", "'2112'"], |
|||
[2112, "strict binary", "x'32313132'"], |
|||
[2112, "strict datetime", "'1970-01-01 00:35:12'"], |
|||
[2112, "strict boolean", "1"], |
|||
// integer zero |
|||
[0, "integer", "0"], |
|||
[0, "float", "'0'"], |
|||
[0, "string", "'0'"], |
|||
[0, "binary", "x'30'"], |
|||
[0, "datetime", "'1970-01-01 00:00:00'"], |
|||
[0, "boolean", "0"], |
|||
[0, "strict integer", "0"], |
|||
[0, "strict float", "'0'"], |
|||
[0, "strict string", "'0'"], |
|||
[0, "strict binary", "x'30'"], |
|||
[0, "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[0, "strict boolean", "0"], |
|||
// float |
|||
[2112.5, "integer", "2112"], |
|||
[2112.5, "float", "'2112.5'"], |
|||
[2112.5, "string", "'2112.5'"], |
|||
[2112.5, "binary", "x'323131322e35'"], |
|||
[2112.5, "datetime", "'1970-01-01 00:35:12'"], |
|||
[2112.5, "boolean", "1"], |
|||
[2112.5, "strict integer", "2112"], |
|||
[2112.5, "strict float", "'2112.5'"], |
|||
[2112.5, "strict string", "'2112.5'"], |
|||
[2112.5, "strict binary", "x'323131322e35'"], |
|||
[2112.5, "strict datetime", "'1970-01-01 00:35:12'"], |
|||
[2112.5, "strict boolean", "1"], |
|||
// float zero |
|||
[0.0, "integer", "0"], |
|||
[0.0, "float", "'0'"], |
|||
[0.0, "string", "'0'"], |
|||
[0.0, "binary", "x'30'"], |
|||
[0.0, "datetime", "'1970-01-01 00:00:00'"], |
|||
[0.0, "boolean", "0"], |
|||
[0.0, "strict integer", "0"], |
|||
[0.0, "strict float", "'0'"], |
|||
[0.0, "strict string", "'0'"], |
|||
[0.0, "strict binary", "x'30'"], |
|||
[0.0, "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[0.0, "strict boolean", "0"], |
|||
// ASCII string |
|||
["Random string", "integer", "0"], |
|||
["Random string", "float", "'0'"], |
|||
["Random string", "string", "'Random string'"], |
|||
["Random string", "binary", "x'52616e646f6d20737472696e67'"], |
|||
["Random string", "datetime", "null"], |
|||
["Random string", "boolean", "1"], |
|||
["Random string", "strict integer", "0"], |
|||
["Random string", "strict float", "'0'"], |
|||
["Random string", "strict string", "'Random string'"], |
|||
["Random string", "strict binary", "x'52616e646f6d20737472696e67'"], |
|||
["Random string", "strict datetime", "'1970-01-01 00:00:00'"], |
|||
["Random string", "strict boolean", "1"], |
|||
// UTF-8 string |
|||
["é", "integer", "0"], |
|||
["é", "float", "'0'"], |
|||
["é", "string", "char(233)"], |
|||
["é", "binary", "x'c3a9'"], |
|||
["é", "datetime", "null"], |
|||
["é", "boolean", "1"], |
|||
["é", "strict integer", "0"], |
|||
["é", "strict float", "'0'"], |
|||
["é", "strict string", "char(233)"], |
|||
["é", "strict binary", "x'c3a9'"], |
|||
["é", "strict datetime", "'1970-01-01 00:00:00'"], |
|||
["é", "strict boolean", "1"], |
|||
// binary string |
|||
[chr(233).chr(233), "integer", "0"], |
|||
[chr(233).chr(233), "float", "'0'"], |
|||
[chr(233).chr(233), "string", "'".chr(233).chr(233)."'"], |
|||
[chr(233).chr(233), "binary", "x'e9e9'"], |
|||
[chr(233).chr(233), "datetime", "null"], |
|||
[chr(233).chr(233), "boolean", "1"], |
|||
[chr(233).chr(233), "strict integer", "0"], |
|||
[chr(233).chr(233), "strict float", "'0'"], |
|||
[chr(233).chr(233), "strict string", "'".chr(233).chr(233)."'"], |
|||
[chr(233).chr(233), "strict binary", "x'e9e9'"], |
|||
[chr(233).chr(233), "strict datetime", "'1970-01-01 00:00:00'"], |
|||
[chr(233).chr(233), "strict boolean", "1"], |
|||
// ISO 8601 date string |
|||
["2017-01-09T13:11:17", "integer", "0"], |
|||
["2017-01-09T13:11:17", "float", "'0'"], |
|||
["2017-01-09T13:11:17", "string", "'2017-01-09T13:11:17'"], |
|||
["2017-01-09T13:11:17", "binary", "x'323031372d30312d30395431333a31313a3137'"], |
|||
["2017-01-09T13:11:17", "datetime", "'2017-01-09 13:11:17'"], |
|||
["2017-01-09T13:11:17", "boolean", "1"], |
|||
["2017-01-09T13:11:17", "strict integer", "0"], |
|||
["2017-01-09T13:11:17", "strict float", "'0'"], |
|||
["2017-01-09T13:11:17", "strict string", "'2017-01-09T13:11:17'"], |
|||
["2017-01-09T13:11:17", "strict binary", "x'323031372d30312d30395431333a31313a3137'"], |
|||
["2017-01-09T13:11:17", "strict datetime", "'2017-01-09 13:11:17'"], |
|||
["2017-01-09T13:11:17", "strict boolean", "1"], |
|||
// arbitrary date string |
|||
["Today", "integer", "0"], |
|||
["Today", "float", "'0'"], |
|||
["Today", "string", "'Today'"], |
|||
["Today", "binary", "x'546f646179'"], |
|||
["Today", "datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"], |
|||
["Today", "boolean", "1"], |
|||
["Today", "strict integer", "0"], |
|||
["Today", "strict float", "'0'"], |
|||
["Today", "strict string", "'Today'"], |
|||
["Today", "strict binary", "x'546f646179'"], |
|||
["Today", "strict datetime", "'".date_create("Today", new \DateTimezone("UTC"))->format("Y-m-d H:i:s")."'"], |
|||
["Today", "strict boolean", "1"], |
|||
// mutable date object |
|||
[$dateMutable, "integer", $dateUTC->getTimestamp()], |
|||
[$dateMutable, "float", "'".$dateUTC->getTimestamp()."'"], |
|||
[$dateMutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateMutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], |
|||
[$dateMutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateMutable, "boolean", "1"], |
|||
[$dateMutable, "strict integer", $dateUTC->getTimestamp()], |
|||
[$dateMutable, "strict float", "'".$dateUTC->getTimestamp()."'"], |
|||
[$dateMutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateMutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], |
|||
[$dateMutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateMutable, "strict boolean", "1"], |
|||
// immutable date object |
|||
[$dateImmutable, "integer", $dateUTC->getTimestamp()], |
|||
[$dateImmutable, "float", "'".$dateUTC->getTimestamp()."'"], |
|||
[$dateImmutable, "string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateImmutable, "binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], |
|||
[$dateImmutable, "datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateImmutable, "boolean", "1"], |
|||
[$dateImmutable, "strict integer", $dateUTC->getTimestamp()], |
|||
[$dateImmutable, "strict float", "'".$dateUTC->getTimestamp()."'"], |
|||
[$dateImmutable, "strict string", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateImmutable, "strict binary", "x'".bin2hex($dateUTC->format("Y-m-d H:i:s"))."'"], |
|||
[$dateImmutable, "strict datetime", "'".$dateUTC->format("Y-m-d H:i:s")."'"], |
|||
[$dateImmutable, "strict boolean", "1"], |
|||
]; |
|||
} |
|||
|
|||
public function testConstructStatement() { |
|||
$nativeStatement = $this->c->prepare("SELECT ? as value"); |
|||
$this->assertInstanceOf(Statement::class, new PDOStatement($this->c, $nativeStatement)); |
|||
} |
|||
|
|||
public function testBindMissingValue() { |
|||
$nativeStatement = $this->c->prepare("SELECT ? as value"); |
|||
$s = new self::$imp($this->c, $nativeStatement); |
|||
$val = $s->runArray()->getRow()['value']; |
|||
$this->assertSame(null, $val); |
|||
} |
|||
|
|||
public 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])->getRow(); |
|||
$this->assertSame($exp, $val); |
|||
} |
|||
|
|||
public function testBindRecursively() { |
|||
$exp = [ |
|||
'one' => "1", |
|||
'two' => "2", |
|||
'three' => "3", |
|||
'four' => "4", |
|||
]; |
|||
$nativeStatement = $this->c->prepare("SELECT ? as one, ? as two, ? as three, ? as four"); |
|||
$s = new self::$imp($this->c, $nativeStatement, ["int", ["int", "int"], "int"]); |
|||
$val = $s->runArray([1, [2, 3], 4])->getRow(); |
|||
$this->assertSame($exp, $val); |
|||
} |
|||
|
|||
public function testBindWithoutType() { |
|||
$nativeStatement = $this->c->prepare("SELECT ? as value"); |
|||
$this->assertException("paramTypeMissing", "Db"); |
|||
$s = new self::$imp($this->c, $nativeStatement, []); |
|||
$s->runArray([1]); |
|||
} |
|||
|
|||
public function testViolateConstraint() { |
|||
$this->c->exec("CREATE TABLE test(id integer not null)"); |
|||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)"); |
|||
$s = new self::$imp($this->c, $nativeStatement, ["int"]); |
|||
$this->assertException("constraintViolation", "Db", "ExceptionInput"); |
|||
$s->runArray([null]); |
|||
} |
|||
|
|||
public function testMismatchTypes() { |
|||
$this->c->exec("CREATE TABLE test(id integer primary key)"); |
|||
$nativeStatement = $this->c->prepare("INSERT INTO test(id) values(?)"); |
|||
$s = new self::$imp($this->c, $nativeStatement, ["str"]); |
|||
$this->assertException("typeViolation", "Db", "ExceptionInput"); |
|||
$s->runArray(['ook']); |
|||
} |
|||
} |
Loading…
Reference in new issue