mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 08:34:56 +00:00
ba0aeab7ec
This sees the addition of a dateOutFormat parameter to ValueInfo::normalize(), as well as a general simplification of how parameter binding works. Some value type-casting results are slightly different, but this simply makes SQL statement objects consistent with the rest of the system.
93 lines
3.5 KiB
PHP
93 lines
3.5 KiB
PHP
<?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\Db;
|
|
|
|
use JKingWeb\Arsse\Misc\Date;
|
|
use JKingWeb\Arsse\Misc\ValueInfo;
|
|
|
|
abstract class AbstractStatement implements Statement {
|
|
protected $types = [];
|
|
protected $isNullable = [];
|
|
|
|
abstract public function runArray(array $values = []): Result;
|
|
abstract protected function bindValue($value, string $type, int $position): bool;
|
|
|
|
public function run(...$values): Result {
|
|
return $this->runArray($values);
|
|
}
|
|
|
|
public function retype(...$bindings): bool {
|
|
return $this->retypeArray($bindings);
|
|
}
|
|
|
|
public function retypeArray(array $bindings, bool $append = false): bool {
|
|
if (!$append) {
|
|
$this->types = [];
|
|
}
|
|
foreach ($bindings as $binding) {
|
|
if (is_array($binding)) {
|
|
// recursively flatten any arrays, which may be provided for SET or IN() clauses
|
|
$this->retypeArray($binding, true);
|
|
} else {
|
|
$binding = trim(strtolower($binding));
|
|
if (strpos($binding, "strict ")===0) {
|
|
// "strict" types' values may never be null; null values will later be cast to the type specified
|
|
$this->isNullable[] = false;
|
|
$binding = substr($binding, 7);
|
|
} else {
|
|
$this->isNullable[] = true;
|
|
}
|
|
if (!array_key_exists($binding, self::TYPES)) {
|
|
throw new Exception("paramTypeInvalid", $binding); // @codeCoverageIgnore
|
|
}
|
|
$this->types[] = self::TYPES[$binding];
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected function cast($v, string $t, bool $nullable) {
|
|
switch ($t) {
|
|
case "datetime":
|
|
$v = Date::transform($v, "sql");
|
|
if (is_null($v) && !$nullable) {
|
|
$v = 0;
|
|
$v = Date::transform($v, "sql");
|
|
}
|
|
return $v;
|
|
case "integer":
|
|
return ValueInfo::normalize($v, ValueInfo::T_INT | ($nullable ? ValueInfo::M_NULL : 0), null, "sql");
|
|
case "float":
|
|
return ValueInfo::normalize($v, ValueInfo::T_FLOAT | ($nullable ? ValueInfo::M_NULL : 0), null, "sql");
|
|
case "binary":
|
|
case "string":
|
|
return ValueInfo::normalize($v, ValueInfo::T_STRING | ($nullable ? ValueInfo::M_NULL : 0), null, "sql");
|
|
case "boolean":
|
|
$v = ValueInfo::normalize($v, ValueInfo::T_BOOL | ($nullable ? ValueInfo::M_NULL : 0), null, "sql");
|
|
return is_null($v) ? $v : (int) $v;
|
|
default:
|
|
throw new Exception("paramTypeUnknown", $type); // @codeCoverageIgnore
|
|
}
|
|
}
|
|
|
|
protected function bindValues(array $values, int $offset = 0): int {
|
|
$a = $offset;
|
|
foreach ($values as $value) {
|
|
if (is_array($value)) {
|
|
// recursively flatten any arrays, which may be provided for SET or IN() clauses
|
|
$a += $this->bindValues($value, $a);
|
|
} elseif (array_key_exists($a, $this->types)) {
|
|
$value = $this->cast($value, $this->types[$a], $this->isNullable[$a]);
|
|
$this->bindValue($value, $this->types[$a], $a+1);
|
|
$a++;
|
|
} else {
|
|
throw new Exception("paramTypeMissing", $a+1);
|
|
}
|
|
}
|
|
return $a - $offset;
|
|
}
|
|
}
|