Skip to content

Commit

Permalink
Introduced binary binding type to support binary parameters on Oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
morozov committed May 19, 2018
1 parent 7021bdf commit 2ec1743
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 29 deletions.
1 change: 1 addition & 0 deletions lib/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
35 changes: 27 additions & 8 deletions lib/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
}

/**
Expand Down
4 changes: 3 additions & 1 deletion lib/Doctrine/DBAL/Driver/PDOSqlsrv/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
1 change: 1 addition & 0 deletions lib/Doctrine/DBAL/Driver/PDOStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
31 changes: 22 additions & 9 deletions lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/Doctrine/DBAL/ParameterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/DBAL/Types/BinaryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ public function getName()
*/
public function getBindingType()
{
return ParameterType::LARGE_OBJECT;
return ParameterType::BINARY;
}
}
12 changes: 3 additions & 9 deletions tests/Doctrine/Tests/DBAL/Functional/Types/BinaryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/DBAL/Types/BinaryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 2ec1743

Please sign in to comment.