From c21ae3eca990269d41f1d5e6117e7a32dcc32cf7 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Mon, 2 Nov 2020 15:21:04 -0500 Subject: [PATCH] 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 --- lib/Db/PostgreSQL/Statement.php | 3 +++ tests/cases/Db/BaseStatement.php | 7 ------- tests/cases/Db/PostgreSQL/TestStatement.php | 5 +++++ tests/cases/Db/PostgreSQLPDO/TestStatement.php | 5 +++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/lib/Db/PostgreSQL/Statement.php b/lib/Db/PostgreSQL/Statement.php index 8c89053..4472e8e 100644 --- a/lib/Db/PostgreSQL/Statement.php +++ b/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; } diff --git a/tests/cases/Db/BaseStatement.php b/tests/cases/Db/BaseStatement.php index 206aed7..ba86269 100644 --- a/tests/cases/Db/BaseStatement.php +++ b/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"], diff --git a/tests/cases/Db/PostgreSQL/TestStatement.php b/tests/cases/Db/PostgreSQL/TestStatement.php index 7b44ec1..a7f776a 100644 --- a/tests/cases/Db/PostgreSQL/TestStatement.php +++ b/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; } diff --git a/tests/cases/Db/PostgreSQLPDO/TestStatement.php b/tests/cases/Db/PostgreSQLPDO/TestStatement.php index 926df76..8878d42 100644 --- a/tests/cases/Db/PostgreSQLPDO/TestStatement.php +++ b/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; }