Unverified Commit f4f987d7 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #3149 from morozov/issues/2787

Introduced binary binding type to support binary parameters on Oracle
parents 997b1938 2ec1743e
...@@ -39,6 +39,7 @@ class MysqliStatement implements \IteratorAggregate, Statement ...@@ -39,6 +39,7 @@ class MysqliStatement implements \IteratorAggregate, Statement
*/ */
protected static $_paramTypeMap = [ protected static $_paramTypeMap = [
ParameterType::STRING => 's', ParameterType::STRING => 's',
ParameterType::BINARY => 's',
ParameterType::BOOLEAN => 'i', ParameterType::BOOLEAN => 'i',
ParameterType::NULL => 's', ParameterType::NULL => 's',
ParameterType::INTEGER => 'i', ParameterType::INTEGER => 'i',
......
...@@ -25,6 +25,7 @@ use Doctrine\DBAL\FetchMode; ...@@ -25,6 +25,7 @@ use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use IteratorAggregate; use IteratorAggregate;
use const OCI_ASSOC; use const OCI_ASSOC;
use const OCI_B_BIN;
use const OCI_B_BLOB; use const OCI_B_BLOB;
use const OCI_BOTH; use const OCI_BOTH;
use const OCI_D_LOB; use const OCI_D_LOB;
...@@ -35,6 +36,7 @@ use const OCI_RETURN_LOBS; ...@@ -35,6 +36,7 @@ use const OCI_RETURN_LOBS;
use const OCI_RETURN_NULLS; use const OCI_RETURN_NULLS;
use const OCI_TEMP_BLOB; use const OCI_TEMP_BLOB;
use const PREG_OFFSET_CAPTURE; use const PREG_OFFSET_CAPTURE;
use const SQLT_CHR;
use function array_key_exists; use function array_key_exists;
use function count; use function count;
use function implode; use function implode;
...@@ -301,18 +303,35 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -301,18 +303,35 @@ class OCI8Statement implements IteratorAggregate, Statement
$lob = oci_new_descriptor($this->_dbh, OCI_D_LOB); $lob = oci_new_descriptor($this->_dbh, OCI_D_LOB);
$lob->writeTemporary($variable, OCI_TEMP_BLOB); $lob->writeTemporary($variable, OCI_TEMP_BLOB);
$this->boundValues[$column] =& $lob; $variable =& $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);
} }
$this->boundValues[$column] =& $variable; $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;
}
} }
/** /**
......
...@@ -33,7 +33,9 @@ class Statement extends PDOStatement ...@@ -33,7 +33,9 @@ class Statement extends PDOStatement
*/ */
public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null) 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; $driverOptions = PDO::SQLSRV_ENCODING_BINARY;
} }
......
...@@ -41,6 +41,7 @@ class PDOStatement extends \PDOStatement implements Statement ...@@ -41,6 +41,7 @@ class PDOStatement extends \PDOStatement implements Statement
ParameterType::NULL => PDO::PARAM_NULL, ParameterType::NULL => PDO::PARAM_NULL,
ParameterType::INTEGER => PDO::PARAM_INT, ParameterType::INTEGER => PDO::PARAM_INT,
ParameterType::STRING => PDO::PARAM_STR, ParameterType::STRING => PDO::PARAM_STR,
ParameterType::BINARY => PDO::PARAM_LOB,
ParameterType::LARGE_OBJECT => PDO::PARAM_LOB, ParameterType::LARGE_OBJECT => PDO::PARAM_LOB,
ParameterType::BOOLEAN => PDO::PARAM_BOOL, ParameterType::BOOLEAN => PDO::PARAM_BOOL,
]; ];
......
...@@ -132,6 +132,7 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -132,6 +132,7 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
case ParameterType::NULL: case ParameterType::NULL:
case ParameterType::STRING: case ParameterType::STRING:
case ParameterType::BINARY:
$type = 's'; $type = 's';
break; break;
......
...@@ -44,6 +44,7 @@ use function sqlsrv_get_field; ...@@ -44,6 +44,7 @@ use function sqlsrv_get_field;
use function sqlsrv_next_result; use function sqlsrv_next_result;
use function sqlsrv_num_fields; use function sqlsrv_num_fields;
use function SQLSRV_PHPTYPE_STREAM; use function SQLSRV_PHPTYPE_STREAM;
use function SQLSRV_PHPTYPE_STRING;
use function sqlsrv_prepare; use function sqlsrv_prepare;
use function sqlsrv_rows_affected; use function sqlsrv_rows_affected;
use function SQLSRV_SQLTYPE_VARBINARY; use function SQLSRV_SQLTYPE_VARBINARY;
...@@ -283,15 +284,27 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -283,15 +284,27 @@ class SQLSrvStatement implements IteratorAggregate, Statement
$params = []; $params = [];
foreach ($this->variables as $column => &$variable) { foreach ($this->variables as $column => &$variable) {
if ($this->types[$column] === ParameterType::LARGE_OBJECT) { switch ($this->types[$column]) {
$params[$column - 1] = [ case ParameterType::LARGE_OBJECT:
&$variable, $params[$column - 1] = [
SQLSRV_PARAM_IN, &$variable,
SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), SQLSRV_PARAM_IN,
SQLSRV_SQLTYPE_VARBINARY('max'), SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY),
]; SQLSRV_SQLTYPE_VARBINARY('max'),
} else { ];
$params[$column - 1] =& $variable; break;
case ParameterType::BINARY:
$params[$column - 1] = [
&$variable,
SQLSRV_PARAM_IN,
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY),
];
break;
default:
$params[$column - 1] =& $variable;
break;
} }
} }
......
...@@ -42,6 +42,11 @@ final class ParameterType ...@@ -42,6 +42,11 @@ final class ParameterType
*/ */
public const BOOLEAN = \PDO::PARAM_BOOL; public const BOOLEAN = \PDO::PARAM_BOOL;
/**
* Represents a binary string data type.
*/
public const BINARY = 16;
/** /**
* This class cannot be instantiated. * This class cannot be instantiated.
*/ */
......
...@@ -79,6 +79,6 @@ class BinaryType extends Type ...@@ -79,6 +79,6 @@ class BinaryType extends Type
*/ */
public function getBindingType() public function getBindingType()
{ {
return ParameterType::LARGE_OBJECT; return ParameterType::BINARY;
} }
} }
...@@ -5,7 +5,6 @@ declare(strict_types=1); ...@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Functional\Types; namespace Doctrine\Tests\DBAL\Functional\Types;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver; use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Table;
use Doctrine\Tests\DbalFunctionalTestCase; use Doctrine\Tests\DbalFunctionalTestCase;
...@@ -20,11 +19,6 @@ class BinaryTest extends DbalFunctionalTestCase ...@@ -20,11 +19,6 @@ class BinaryTest extends DbalFunctionalTestCase
{ {
parent::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 = new Table('binary_table');
$table->addColumn('id', 'binary', [ $table->addColumn('id', 'binary', [
'length' => 16, 'length' => 16,
...@@ -64,8 +58,8 @@ class BinaryTest extends DbalFunctionalTestCase ...@@ -64,8 +58,8 @@ class BinaryTest extends DbalFunctionalTestCase
'id' => $id, 'id' => $id,
'val' => $value, 'val' => $value,
], [ ], [
ParameterType::LARGE_OBJECT, ParameterType::BINARY,
ParameterType::LARGE_OBJECT, ParameterType::BINARY,
]); ]);
self::assertSame(1, $result); self::assertSame(1, $result);
...@@ -77,7 +71,7 @@ class BinaryTest extends DbalFunctionalTestCase ...@@ -77,7 +71,7 @@ class BinaryTest extends DbalFunctionalTestCase
'SELECT val FROM binary_table WHERE id = ?', 'SELECT val FROM binary_table WHERE id = ?',
[$id], [$id],
0, 0,
[ParameterType::LARGE_OBJECT] [ParameterType::BINARY]
); );
// Currently, `BinaryType` mistakenly converts string values fetched from the DB to a stream. // Currently, `BinaryType` mistakenly converts string values fetched from the DB to a stream.
......
...@@ -32,7 +32,7 @@ class BinaryTest extends \Doctrine\Tests\DbalTestCase ...@@ -32,7 +32,7 @@ class BinaryTest extends \Doctrine\Tests\DbalTestCase
public function testReturnsBindingType() public function testReturnsBindingType()
{ {
self::assertSame(ParameterType::LARGE_OBJECT, $this->type->getBindingType()); self::assertSame(ParameterType::BINARY, $this->type->getBindingType());
} }
public function testReturnsName() public function testReturnsName()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment