From ee6c7dad7e433c36f8a87ff1480692abcbc7f4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Biarda?= <1135380+michalbiarda@users.noreply.github.com> Date: Thu, 14 May 2026 09:46:40 +0200 Subject: [PATCH] fix(database-pgsql): JSON-encode array bindings before passing to PDO PDO silently casts PHP arrays to the string "Array" when bound as query parameters. For json/jsonb columns this causes an "invalid input syntax for type json" error at the database level. Co-Authored-By: Claude Sonnet 4.6 --- .../src/Connection/PgSqlConnection.php | 6 ++++ .../tests/Connection/PgSqlConnectionTest.php | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/packages/database-pgsql/src/Connection/PgSqlConnection.php b/packages/database-pgsql/src/Connection/PgSqlConnection.php index 2edb610d..9300b521 100644 --- a/packages/database-pgsql/src/Connection/PgSqlConnection.php +++ b/packages/database-pgsql/src/Connection/PgSqlConnection.php @@ -187,6 +187,12 @@ private function bindValues( ): void { foreach ($bindings as $key => $value) { $param = is_int($key) ? $key + 1 : $key; + + if (is_array($value)) { + $statement->bindValue($param, json_encode($value), PDO::PARAM_STR); + continue; + } + $type = match (true) { is_bool($value) => PDO::PARAM_BOOL, is_null($value) => PDO::PARAM_NULL, diff --git a/packages/database-pgsql/tests/Connection/PgSqlConnectionTest.php b/packages/database-pgsql/tests/Connection/PgSqlConnectionTest.php index 3ab8c1cd..c68a86fc 100644 --- a/packages/database-pgsql/tests/Connection/PgSqlConnectionTest.php +++ b/packages/database-pgsql/tests/Connection/PgSqlConnectionTest.php @@ -685,4 +685,33 @@ protected function createPdo( expect(fn () => $connection->beginTransaction()) ->toThrow(TransactionException::class, 'Nested transactions are not supported'); }); + + it('JSON-encodes array bindings instead of casting them to the string "Array"', function (): void { + $config = createTestPgSqlConfig(); + $connection = new class ($config) extends PgSqlConnection + { + protected function createPdo( + string $dsn, + string $username, + string $password, + array $options, + ): PDO { + $pdo = createSqliteMockPdo($options); + $pdo->exec('CREATE TABLE items (id INTEGER PRIMARY KEY, metadata TEXT)'); + + return $pdo; + } + }; + + $connection->execute( + 'INSERT INTO items (metadata) VALUES (?)', + [['key' => 'value', 'nested' => [1, 2, 3]]], + ); + + $rows = $connection->query('SELECT metadata FROM items'); + + expect($rows[0]['metadata']) + ->toBe('{"key":"value","nested":[1,2,3]}') + ->not->toBe('Array'); + }); });