Browse Source

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
rpm
J. King 3 years ago
parent
commit
c21ae3eca9
  1. 3
      lib/Db/PostgreSQL/Statement.php
  2. 7
      tests/cases/Db/BaseStatement.php
  3. 5
      tests/cases/Db/PostgreSQL/TestStatement.php
  4. 5
      tests/cases/Db/PostgreSQLPDO/TestStatement.php

3
lib/Db/PostgreSQL/Statement.php

@ -44,6 +44,9 @@ class Statement extends \JKingWeb\Arsse\Db\AbstractStatement {
}
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;
}

7
tests/cases/Db/BaseStatement.php

@ -57,7 +57,6 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
} else {
$query = "SELECT ($exp = ?) as pass";
}
$typeStr = "'".str_replace("'", "''", $type)."'";
$s = new $this->statementClass(...$this->makeStatement($query));
$s->retype(...[$type]);
$act = $s->run(...[$value])->getValue();
@ -66,15 +65,11 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
/** @dataProvider provideBinaryBindings */
public function testHandleBinaryData($value, string $type, string $exp): void {
if (in_array(static::$implementation, ["PostgreSQL", "PDO PostgreSQL"])) {
$this->markTestIncomplete("Correct handling of binary data with PostgreSQL is not currently implemented");
}
if ($exp === "null") {
$query = "SELECT (? is null) as pass";
} else {
$query = "SELECT ($exp = ?) as pass";
}
$typeStr = "'".str_replace("'", "''", $type)."'";
$s = new $this->statementClass(...$this->makeStatement($query));
$s->retype(...[$type]);
$act = $s->run(...[$value])->getValue();
@ -297,13 +292,11 @@ abstract class BaseStatement extends \JKingWeb\Arsse\Test\AbstractTest {
'UTF-8 string as strict binary' => ["\u{e9}", "strict binary", "x'c3a9'"],
'Binary string as integer' => [chr(233).chr(233), "integer", "0"],
'Binary string as float' => [chr(233).chr(233), "float", "0.0"],
'Binary string as string' => [chr(233).chr(233), "string", "'".chr(233).chr(233)."'"],
'Binary string as binary' => [chr(233).chr(233), "binary", "x'e9e9'"],
'Binary string as datetime' => [chr(233).chr(233), "datetime", "null"],
'Binary string as boolean' => [chr(233).chr(233), "boolean", "1"],
'Binary string as strict integer' => [chr(233).chr(233), "strict integer", "0"],
'Binary string as strict float' => [chr(233).chr(233), "strict float", "0.0"],
'Binary string as strict string' => [chr(233).chr(233), "strict string", "'".chr(233).chr(233)."'"],
'Binary string as strict binary' => [chr(233).chr(233), "strict binary", "x'e9e9'"],
'Binary string as strict datetime' => [chr(233).chr(233), "strict datetime", "'0001-01-01 00:00:00'"],
'Binary string as strict boolean' => [chr(233).chr(233), "strict boolean", "1"],

5
tests/cases/Db/PostgreSQL/TestStatement.php

@ -27,6 +27,11 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";
}
return $value;
case "binary":
if ($value[0] === "x") {
return "'\\x".substr($value, 2)."::bytea";
}
// no break;
default:
return $value;
}

5
tests/cases/Db/PostgreSQLPDO/TestStatement.php

@ -27,6 +27,11 @@ class TestStatement extends \JKingWeb\Arsse\TestCase\Db\BaseStatement {
return "U&'\\+".str_pad(dechex((int) $match[1]), 6, "0", \STR_PAD_LEFT)."'";
}
return $value;
case "binary":
if ($value[0] === "x") {
return "'\\x".substr($value, 2)."::bytea";
}
// no break;
default:
return $value;
}

Loading…
Cancel
Save