From 8eee35b5b02da9987e259dc516c9799a8da541ef Mon Sep 17 00:00:00 2001 From: Alexander Melekhovets Date: Thu, 13 Jul 2023 01:54:35 +0300 Subject: [PATCH] Fix blob binding overwrite on DB2 On DB2 when binding more than 1 blob in the same statement each subsequent blob overwrites previous one. So instead of [1, 2, 3] we get [2, 3, 3] This happens because of reference between loop variable `$value` and the item in `$this->parameters[]`, which remains after iteration, see `bindLobs` and `bind` methods in `\Doctrine\DBAL\Driver\IBMDB2\Statement` --- src/Driver/IBMDB2/Statement.php | 2 ++ tests/Functional/BlobTest.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/Driver/IBMDB2/Statement.php b/src/Driver/IBMDB2/Statement.php index 15c3fdb588a..699e236d715 100644 --- a/src/Driver/IBMDB2/Statement.php +++ b/src/Driver/IBMDB2/Statement.php @@ -182,6 +182,8 @@ private function bindLobs(): array } else { $this->bind($param, $value, DB2_PARAM_IN, DB2_CHAR); } + + unset($value); } return $handles; diff --git a/tests/Functional/BlobTest.php b/tests/Functional/BlobTest.php index ec346406561..619b5c50fe0 100644 --- a/tests/Functional/BlobTest.php +++ b/tests/Functional/BlobTest.php @@ -169,6 +169,34 @@ public function testBindParamProcessesStream(): void $this->assertBlobContains('test'); } + public function testBlobBindingDoesNotOverwritePrevious(): void + { + $table = new Table('blob_table'); + $table->addColumn('id', 'integer'); + $table->addColumn('blobcolumn1', 'blob', ['notnull' => false]); + $table->addColumn('blobcolumn2', 'blob', ['notnull' => false]); + $table->setPrimaryKey(['id']); + $this->dropAndCreateTable($table); + + $params = ['test1', 'test2']; + $this->connection->executeStatement( + 'INSERT INTO blob_table(id, blobcolumn1, blobcolumn2) VALUES (1, ?, ?)', + $params, + [ParameterType::LARGE_OBJECT, ParameterType::LARGE_OBJECT], + ); + + $blobs = $this->connection->fetchNumeric('SELECT blobcolumn1, blobcolumn2 FROM blob_table'); + self::assertIsArray($blobs); + + $actual = []; + foreach ($blobs as $blob) { + $blob = Type::getType('blob')->convertToPHPValue($blob, $this->connection->getDatabasePlatform()); + $actual[] = stream_get_contents($blob); + } + + self::assertEquals(['test1', 'test2'], $actual); + } + private function assertBlobContains(string $text): void { [, $blobValue] = $this->fetchRow();