diff --git a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php index db78c7178ef..faf6b751124 100644 --- a/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php +++ b/lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php @@ -39,6 +39,7 @@ class MysqliStatement implements \IteratorAggregate, Statement */ protected static $_paramTypeMap = [ ParameterType::STRING => 's', + ParameterType::BINARY => 's', ParameterType::BOOLEAN => 'i', ParameterType::NULL => 's', ParameterType::INTEGER => 'i', diff --git a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php index 1d771007fda..0df45fc1b99 100644 --- a/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php +++ b/lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php @@ -25,6 +25,7 @@ use Doctrine\DBAL\ParameterType; use IteratorAggregate; use const OCI_ASSOC; +use const OCI_B_BIN; use const OCI_B_BLOB; use const OCI_BOTH; use const OCI_D_LOB; @@ -35,6 +36,7 @@ use const OCI_RETURN_NULLS; use const OCI_TEMP_BLOB; use const PREG_OFFSET_CAPTURE; +use const SQLT_CHR; use function array_key_exists; use function count; use function implode; @@ -301,18 +303,35 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l $lob = oci_new_descriptor($this->_dbh, OCI_D_LOB); $lob->writeTemporary($variable, OCI_TEMP_BLOB); - $this->boundValues[$column] =& $lob; - - return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB); - } elseif ($length !== null) { - $this->boundValues[$column] =& $variable; - - return oci_bind_by_name($this->_sth, $column, $variable, $length); + $variable =& $lob; } $this->boundValues[$column] =& $variable; - return oci_bind_by_name($this->_sth, $column, $variable); + return oci_bind_by_name( + $this->_sth, + $column, + $variable, + $length ?? -1, + $this->convertParameterType($type) + ); + } + + /** + * Converts DBAL parameter type to oci8 parameter type + */ + private function convertParameterType(int $type) : int + { + switch ($type) { + case ParameterType::BINARY: + return OCI_B_BIN; + + case ParameterType::LARGE_OBJECT: + return OCI_B_BLOB; + + default: + return SQLT_CHR; + } } /** diff --git a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php index 82e2c3e3565..3704003425f 100644 --- a/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php +++ b/lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php @@ -33,7 +33,9 @@ class Statement extends PDOStatement */ public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) { - if ($type === ParameterType::LARGE_OBJECT && $driverOptions === null) { + if (($type === ParameterType::LARGE_OBJECT || $type === ParameterType::BINARY) + && $driverOptions === null + ) { $driverOptions = PDO::SQLSRV_ENCODING_BINARY; } diff --git a/lib/Doctrine/DBAL/Driver/PDOStatement.php b/lib/Doctrine/DBAL/Driver/PDOStatement.php index ca07596b677..7b292639353 100644 --- a/lib/Doctrine/DBAL/Driver/PDOStatement.php +++ b/lib/Doctrine/DBAL/Driver/PDOStatement.php @@ -41,6 +41,7 @@ class PDOStatement extends \PDOStatement implements Statement ParameterType::NULL => PDO::PARAM_NULL, ParameterType::INTEGER => PDO::PARAM_INT, ParameterType::STRING => PDO::PARAM_STR, + ParameterType::BINARY => PDO::PARAM_LOB, ParameterType::LARGE_OBJECT => PDO::PARAM_LOB, ParameterType::BOOLEAN => PDO::PARAM_BOOL, ]; diff --git a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php index 5605e525ff2..365b1536df9 100644 --- a/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -132,6 +132,7 @@ public function bindParam($column, &$variable, $type = ParameterType::STRING, $l case ParameterType::NULL: case ParameterType::STRING: + case ParameterType::BINARY: $type = 's'; break; diff --git a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php index f4d450177a8..ecb521623df 100644 --- a/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php +++ b/lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php @@ -44,6 +44,7 @@ use function sqlsrv_next_result; use function sqlsrv_num_fields; use function SQLSRV_PHPTYPE_STREAM; +use function SQLSRV_PHPTYPE_STRING; use function sqlsrv_prepare; use function sqlsrv_rows_affected; use function SQLSRV_SQLTYPE_VARBINARY; @@ -283,15 +284,27 @@ private function prepare() $params = []; foreach ($this->variables as $column => &$variable) { - if ($this->types[$column] === ParameterType::LARGE_OBJECT) { - $params[$column - 1] = [ - &$variable, - SQLSRV_PARAM_IN, - SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), - SQLSRV_SQLTYPE_VARBINARY('max'), - ]; - } else { - $params[$column - 1] =& $variable; + switch ($this->types[$column]) { + case ParameterType::LARGE_OBJECT: + $params[$column - 1] = [ + &$variable, + SQLSRV_PARAM_IN, + SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), + SQLSRV_SQLTYPE_VARBINARY('max'), + ]; + break; + + case ParameterType::BINARY: + $params[$column - 1] = [ + &$variable, + SQLSRV_PARAM_IN, + SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), + ]; + break; + + default: + $params[$column - 1] =& $variable; + break; } } diff --git a/lib/Doctrine/DBAL/ParameterType.php b/lib/Doctrine/DBAL/ParameterType.php index 362a0514d23..be5413e61bb 100644 --- a/lib/Doctrine/DBAL/ParameterType.php +++ b/lib/Doctrine/DBAL/ParameterType.php @@ -42,6 +42,11 @@ final class ParameterType */ public const BOOLEAN = \PDO::PARAM_BOOL; + /** + * Represents a binary string data type. + */ + public const BINARY = 16; + /** * This class cannot be instantiated. */ diff --git a/lib/Doctrine/DBAL/Types/BinaryType.php b/lib/Doctrine/DBAL/Types/BinaryType.php index 08dd7f74169..57f0bbf0f8f 100644 --- a/lib/Doctrine/DBAL/Types/BinaryType.php +++ b/lib/Doctrine/DBAL/Types/BinaryType.php @@ -79,6 +79,6 @@ public function getName() */ public function getBindingType() { - return ParameterType::LARGE_OBJECT; + return ParameterType::BINARY; } } diff --git a/tests/Doctrine/Tests/DBAL/Functional/Types/BinaryTest.php b/tests/Doctrine/Tests/DBAL/Functional/Types/BinaryTest.php index 936b98c85c3..f4e6ff1a84d 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Types/BinaryTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Types/BinaryTest.php @@ -5,7 +5,6 @@ namespace Doctrine\Tests\DBAL\Functional\Types; use Doctrine\DBAL\Driver\IBMDB2\DB2Driver; -use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; use Doctrine\Tests\DbalFunctionalTestCase; @@ -20,11 +19,6 @@ protected function setUp() { parent::setUp(); - /** @see https://github.com/doctrine/dbal/issues/2787 */ - if ($this->_conn->getDriver() instanceof OCI8Driver) { - $this->markTestSkipped('Filtering by binary fields is currently not supported on Oracle'); - } - $table = new Table('binary_table'); $table->addColumn('id', 'binary', [ 'length' => 16, @@ -64,8 +58,8 @@ private function insert(string $id, string $value) : void 'id' => $id, 'val' => $value, ], [ - ParameterType::LARGE_OBJECT, - ParameterType::LARGE_OBJECT, + ParameterType::BINARY, + ParameterType::BINARY, ]); self::assertSame(1, $result); @@ -77,7 +71,7 @@ private function select(string $id) 'SELECT val FROM binary_table WHERE id = ?', [$id], 0, - [ParameterType::LARGE_OBJECT] + [ParameterType::BINARY] ); // Currently, `BinaryType` mistakenly converts string values fetched from the DB to a stream. diff --git a/tests/Doctrine/Tests/DBAL/Types/BinaryTest.php b/tests/Doctrine/Tests/DBAL/Types/BinaryTest.php index 88daec0bd96..9881c897960 100644 --- a/tests/Doctrine/Tests/DBAL/Types/BinaryTest.php +++ b/tests/Doctrine/Tests/DBAL/Types/BinaryTest.php @@ -32,7 +32,7 @@ protected function setUp() public function testReturnsBindingType() { - self::assertSame(ParameterType::LARGE_OBJECT, $this->type->getBindingType()); + self::assertSame(ParameterType::BINARY, $this->type->getBindingType()); } public function testReturnsName()