Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accept the underlying statement as an oci8 statement constructor argument #4957

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/Driver/OCI8/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,23 @@

namespace Doctrine\DBAL\Driver\OCI8;

use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\OCI8\Exception\Error;
use Doctrine\DBAL\Driver\OCI8\Exception\SequenceDoesNotExist;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\SQL\Parser;
use Doctrine\Deprecations\Deprecation;

use function addcslashes;
use function assert;
use function is_float;
use function is_int;
use function is_resource;
use function oci_commit;
use function oci_parse;
use function oci_rollback;
use function oci_server_version;
use function preg_match;
Expand All @@ -23,7 +27,10 @@
final class Connection implements ServerInfoAwareConnection
{
/** @var resource */
protected $connection;
private $connection;

/** @var Parser */
private $parser;

/** @var ExecutionMode */
private $executionMode;
Expand All @@ -36,6 +43,7 @@ final class Connection implements ServerInfoAwareConnection
public function __construct($connection)
{
$this->connection = $connection;
$this->parser = new Parser(false);
$this->executionMode = new ExecutionMode();
}

Expand All @@ -55,11 +63,25 @@ public function getServerVersion()
return $matches[1];
}

/**
* @throws Parser\Exception
*/
public function prepare(string $sql): DriverStatement
{
return new Statement($this->connection, $sql, $this->executionMode);
$visitor = new ConvertPositionalToNamedPlaceholders();

$this->parser->parse($sql, $visitor);

$statement = oci_parse($this->connection, $visitor->getSQL());
assert(is_resource($statement));

return new Statement($this->connection, $statement, $visitor->getParameterMap(), $this->executionMode);
}

/**
* @throws Exception
* @throws Parser\Exception
*/
public function query(string $sql): ResultInterface
{
return $this->prepare($sql)->execute();
Expand All @@ -79,6 +101,10 @@ public function quote($value, $type = ParameterType::STRING)
return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
}

/**
* @throws Exception
* @throws Parser\Exception
*/
public function exec(string $sql): int
{
return $this->prepare($sql)->execute()->rowCount();
Expand All @@ -90,6 +116,8 @@ public function exec(string $sql): int
* @param string|null $name
*
* @return int|false
*
* @throws Parser\Exception
*/
public function lastInsertId($name = null)
{
Expand Down
67 changes: 20 additions & 47 deletions src/Driver/OCI8/Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,16 @@

namespace Doctrine\DBAL\Driver\OCI8;

use Doctrine\DBAL\Driver\Exception;
use Doctrine\DBAL\Driver\OCI8\Exception\Error;
use Doctrine\DBAL\Driver\OCI8\Exception\UnknownParameterIndex;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\SQL\Parser;

use function assert;
use function is_int;
use function is_resource;
use function oci_bind_by_name;
use function oci_execute;
use function oci_new_descriptor;
use function oci_parse;

use const OCI_B_BIN;
use const OCI_B_BLOB;
Expand All @@ -29,49 +24,29 @@
final class Statement implements StatementInterface
{
/** @var resource */
protected $_dbh;
private $connection;

/** @var resource */
protected $_sth;
private $statement;

/** @var array<int,string> */
private $parameterMap;

/** @var ExecutionMode */
private $executionMode;

/** @var string[] */
protected $_paramMap = [];

/**
* Holds references to bound parameter values.
*
* This is a new requirement for PHP7's oci8 extension that prevents bound values from being garbage collected.
*
* @var mixed[]
*/
private $boundValues = [];

/**
* Creates a new OCI8Statement that uses the given connection handle and SQL statement.
*
* @internal The statement can be only instantiated by its driver connection.
*
* @param resource $dbh The connection handle.
* @param string $query The SQL query.
*
* @throws Exception
* @param resource $connection
* @param resource $statement
* @param array<int,string> $parameterMap
*/
public function __construct($dbh, $query, ExecutionMode $executionMode)
public function __construct($connection, $statement, array $parameterMap, ExecutionMode $executionMode)
{
$parser = new Parser(false);
$visitor = new ConvertPositionalToNamedPlaceholders();

$parser->parse($query, $visitor);

$stmt = oci_parse($dbh, $visitor->getSQL());
assert(is_resource($stmt));

$this->_sth = $stmt;
$this->_dbh = $dbh;
$this->_paramMap = $visitor->getParameterMap();
$this->connection = $connection;
$this->statement = $statement;
$this->parameterMap = $parameterMap;
$this->executionMode = $executionMode;
}

Expand All @@ -80,7 +55,7 @@ public function __construct($dbh, $query, ExecutionMode $executionMode)
*/
public function bindValue($param, $value, $type = ParameterType::STRING)
{
return $this->bindParam($param, $value, $type, null);
return $this->bindParam($param, $value, $type);
}

/**
Expand All @@ -89,24 +64,22 @@ public function bindValue($param, $value, $type = ParameterType::STRING)
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null)
{
if (is_int($param)) {
if (! isset($this->_paramMap[$param])) {
if (! isset($this->parameterMap[$param])) {
throw UnknownParameterIndex::new($param);
}

$param = $this->_paramMap[$param];
$param = $this->parameterMap[$param];
}

if ($type === ParameterType::LARGE_OBJECT) {
$lob = oci_new_descriptor($this->_dbh, OCI_D_LOB);
$lob = oci_new_descriptor($this->connection, OCI_D_LOB);
$lob->writeTemporary($variable, OCI_TEMP_BLOB);

$variable =& $lob;
}

$this->boundValues[$param] =& $variable;

return oci_bind_by_name(
$this->_sth,
$this->statement,
$param,
$variable,
$length ?? -1,
Expand Down Expand Up @@ -152,11 +125,11 @@ public function execute($params = null): ResultInterface
$mode = OCI_NO_AUTO_COMMIT;
}

$ret = @oci_execute($this->_sth, $mode);
$ret = @oci_execute($this->statement, $mode);
if (! $ret) {
throw Error::new($this->_sth);
throw Error::new($this->statement);
}

return new Result($this->_sth);
return new Result($this->statement);
}
}