1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-23 09:02:41 +00:00
Arsse/lib/Db/PostgreSQL/Statement.php
J. King c21ae3eca9 Correctly send binary data to PostgreSQL
This finally brings PostgreSQL to parity with SQLite and MySQL.
Two tests casting binary data to text were removed since behaviour here
should in fact be undefined

Accountinf for any encoding when retrieving data will be addressed by
a later commit
2020-11-02 15:21:04 -05:00

72 lines
2.3 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\PostgreSQL;
class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
use Dispatch;
protected const BINDINGS = [
self::T_INTEGER => "bigint",
self::T_FLOAT => "decimal",
self::T_DATETIME => "timestamp(0) without time zone",
self::T_BINARY => "bytea",
self::T_STRING => "text",
self::T_BOOLEAN => "smallint", // FIXME: using boolean leads to incompatibilities with versions of SQLite bundled prior to PHP 7.3
];
protected $db;
protected $in = [];
protected $query;
protected $qMunged;
protected $bindings;
public function __construct($db, string $query, array $bindings = []) {
$this->db = $db;
$this->query = $query;
$this->retypeArray($bindings);
}
public function runArray(array $values = []): \JKingWeb\Arsse\Db\Result {
$this->in = [];
$this->bindValues($values);
$r = $this->dispatchQuery($this->qMunged, $this->in);
$this->in = [];
if (is_resource($r)) {
return new Result($this->db, $r);
} else {
[$excClass, $excMsg, $excData] = $r;
throw new $excClass($excMsg, $excData);
}
}
protected function bindValue($value, int $type, int $position): bool {
if ($value !== null && ($this->types[$position - 1] % self::T_NOT_NULL) === self::T_BINARY) {
$value = "\\x".bin2hex($value);
}
$this->in[] = $value;
return true;
}
public static function mungeQuery(string $q, array $types, ...$extraData): string {
$mungeParamMarkers = (bool) ($extraData[0] ?? true);
$q = explode("?", $q);
$out = "";
for ($b = 1; $b < sizeof($q); $b++) {
$a = $b - 1;
$mark = $mungeParamMarkers ? "\$$b" : "?";
$type = isset($types[$a]) ? "::".self::BINDINGS[$types[$a] % self::T_NOT_NULL] : "";
$out .= $q[$a].$mark.$type;
}
$out .= array_pop($q);
return $out;
}
protected function prepare(string $query): bool {
$this->qMunged = $query;
return true;
}
}