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

Merge pull request #3590 from jwage/final-classes

Make classes final where applicable.
parents 69cd77e0 5bcd3563
......@@ -44,6 +44,39 @@ If you are using any of the legacy versions, you have to upgrade to newer MariaD
Table columns are no longer indexed by column name. Use the `name` attribute of the column instead.
## BC BREAK: Classes made final
- Class constant `SQLSrvStatement::LAST_INSERT_ID_SQL` was changed from public to private.
- Class `Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser` was made final.
- Class `Doctrine\DBAL\Sharding\SQLAzure\Schema\MultiTenantVisitor` was made final.
- Class `Doctrine\DBAL\Sharding\SQLAzure\SQLAzureFederationsSynchronizer` was made final.
- Class `Doctrine\DBAL\Sharding\PoolingShardManager` was made final.
- Class `Doctrine\DBAL\Id\TableGeneratorSchemaVisitor` was made final.
- Class `Doctrine\DBAL\Driver\OCI8\Driver` was made final.
- Class `Doctrine\DBAL\Driver\Mysqli\Driver` was made final.
- Class `Doctrine\DBAL\Driver\Mysqli\MysqliStatement` was made final.
- Class `Doctrine\DBAL\Driver\PDOSqlsrv\Driver` was made final.
- Class `Doctrine\DBAL\Driver\PDOSqlsrv\Statement` was made final.
- Class `Doctrine\DBAL\Driver\PDOMySql\Driver` was made final.
- Class `Doctrine\DBAL\Driver\IBMDB2\DB2Connection` was made final.
- Class `Doctrine\DBAL\Driver\IBMDB2\DB2Statement` was made final.
- Class `Doctrine\DBAL\Driver\IBMDB2\DB2Driver` was made final.
- Class `Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement` was made final.
- Class `Doctrine\DBAL\Driver\SQLSrv\Driver` was made final.
- Class `Doctrine\DBAL\Driver\SQLSrv\SQLSrvConnection` was made final.
- Class `Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereConnection` was made final.
- Class `Doctrine\DBAL\Driver\SQLAnywhere\Driver` was made final.
- Class `Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereStatement` was made final.
- Class `Doctrine\DBAL\Driver\PDOPgSql\Driver` was made final.
- Class `Doctrine\DBAL\Driver\PDOOracle\Driver` was made final.
- Class `Doctrine\DBAL\Driver\PDOSqlite\Driver` was made final.
- Class `Doctrine\DBAL\Driver\StatementIterator` was made final.
- Class `Doctrine\DBAL\Cache\ResultCacheStatement` was made final.
- Class `Doctrine\DBAL\Cache\ArrayStatement` was made final.
- Class `Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer` was made final.
- Class `Doctrine\DBAL\Schema\Visitor\RemoveNamespacedAssets` was made final.
- Class `Doctrine\DBAL\Portability\Statement` was made final.
## BC BREAK: Changes in the `Doctrine\DBAL\Schema` API
- Column precision no longer defaults to 10. The default value is NULL.
......
......@@ -17,7 +17,7 @@ use function count;
use function reset;
use function sprintf;
class ArrayStatement implements IteratorAggregate, ResultStatement
final class ArrayStatement implements IteratorAggregate, ResultStatement
{
/** @var mixed[] */
private $data;
......
......@@ -30,7 +30,7 @@ use function reset;
* Also you have to realize that the cache will load the whole result into memory at once to ensure 2.
* This means that the memory usage for cached results might increase by using this feature.
*/
class ResultCacheStatement implements IteratorAggregate, ResultStatement
final class ResultCacheStatement implements IteratorAggregate, ResultStatement
{
/** @var Cache */
private $resultCache;
......
......@@ -22,10 +22,10 @@ use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
class DB2Connection implements ServerInfoAwareConnection
final class DB2Connection implements ServerInfoAwareConnection
{
/** @var resource */
private $conn = null;
private $conn;
/**
* @param array<string, mixed> $params
......
......@@ -14,7 +14,7 @@ use function sprintf;
/**
* IBM DB2 Driver.
*/
class DB2Driver extends AbstractDB2Driver
final class DB2Driver extends AbstractDB2Driver
{
/**
* {@inheritdoc}
......
......@@ -48,7 +48,7 @@ use function stream_get_meta_data;
use function strtolower;
use function tmpfile;
class DB2Statement implements IteratorAggregate, Statement
final class DB2Statement implements IteratorAggregate, Statement
{
/** @var resource */
private $stmt;
......@@ -128,21 +128,6 @@ class DB2Statement implements IteratorAggregate, Statement
}
}
/**
* @param int $position Parameter position
* @param mixed $variable
*
* @throws DB2Exception
*/
private function bind(int $position, &$variable, int $parameterType, int $dataType) : void
{
$this->bindParam[$position] =& $variable;
if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) {
throw DB2Exception::fromStatementError($this->stmt);
}
}
/**
* {@inheritdoc}
*/
......@@ -336,6 +321,21 @@ class DB2Statement implements IteratorAggregate, Statement
return @db2_num_rows($this->stmt) ? : 0;
}
/**
* @param int $position Parameter position
* @param mixed $variable
*
* @throws DB2Exception
*/
private function bind(int $position, &$variable, int $parameterType, int $dataType) : void
{
$this->bindParam[$position] =& $variable;
if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) {
throw DB2Exception::fromStatementError($this->stmt);
}
}
/**
* Casts a stdClass object to the given class name mapping its' properties.
*
......
......@@ -8,7 +8,7 @@ use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractMySQLDriver;
use Doctrine\DBAL\Driver\Connection;
class Driver extends AbstractMySQLDriver
final class Driver extends AbstractMySQLDriver
{
/**
* {@inheritdoc}
......
......@@ -32,10 +32,10 @@ use function is_int;
use function is_resource;
use function str_repeat;
class MysqliStatement implements IteratorAggregate, Statement
final class MysqliStatement implements IteratorAggregate, Statement
{
/** @var string[] */
protected static $_paramTypeMap = [
private static $paramTypeMap = [
ParameterType::STRING => 's',
ParameterType::BINARY => 's',
ParameterType::BOOLEAN => 'i',
......@@ -45,32 +45,32 @@ class MysqliStatement implements IteratorAggregate, Statement
];
/** @var mysqli */
protected $_conn;
private $conn;
/** @var mysqli_stmt */
protected $_stmt;
private $stmt;
/** @var string[]|false|null */
protected $_columnNames;
private $columnNames;
/** @var mixed[] */
protected $_rowBindedValues = [];
private $rowBoundValues = [];
/** @var mixed[] */
protected $_bindedValues = [];
private $boundValues = [];
/** @var string */
protected $types;
private $types;
/**
* Contains ref values for bindValue().
*
* @var mixed[]
*/
protected $_values = [];
private $values = [];
/** @var int */
protected $_defaultFetchMode = FetchMode::MIXED;
private $defaultFetchMode = FetchMode::MIXED;
/**
* Indicates whether the statement is in the state when fetching results is possible
......@@ -84,23 +84,23 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function __construct(mysqli $conn, string $sql)
{
$this->_conn = $conn;
$this->conn = $conn;
$stmt = $conn->prepare($sql);
if ($stmt === false) {
throw ConnectionError::new($this->_conn);
throw ConnectionError::new($this->conn);
}
$this->_stmt = $stmt;
$this->stmt = $stmt;
$paramCount = $this->_stmt->param_count;
$paramCount = $this->stmt->param_count;
if (0 >= $paramCount) {
return;
}
$this->types = str_repeat('s', $paramCount);
$this->_bindedValues = array_fill(1, $paramCount, null);
$this->boundValues = array_fill(1, $paramCount, null);
}
/**
......@@ -110,12 +110,12 @@ class MysqliStatement implements IteratorAggregate, Statement
{
assert(is_int($param));
if (! isset(self::$_paramTypeMap[$type])) {
if (! isset(self::$paramTypeMap[$type])) {
throw UnknownType::new($type);
}
$this->_bindedValues[$param] =& $variable;
$this->types[$param - 1] = self::$_paramTypeMap[$type];
$this->boundValues[$param] =& $variable;
$this->types[$param - 1] = self::$paramTypeMap[$type];
}
/**
......@@ -125,13 +125,13 @@ class MysqliStatement implements IteratorAggregate, Statement
{
assert(is_int($param));
if (! isset(self::$_paramTypeMap[$type])) {
if (! isset(self::$paramTypeMap[$type])) {
throw UnknownType::new($type);
}
$this->_values[$param] = $value;
$this->_bindedValues[$param] =& $this->_values[$param];
$this->types[$param - 1] = self::$_paramTypeMap[$type];
$this->values[$param] = $value;
$this->boundValues[$param] =& $this->values[$param];
$this->types[$param - 1] = self::$paramTypeMap[$type];
}
/**
......@@ -141,18 +141,18 @@ class MysqliStatement implements IteratorAggregate, Statement
{
if ($params !== null && count($params) > 0) {
if (! $this->bindUntypedValues($params)) {
throw StatementError::new($this->_stmt);
throw StatementError::new($this->stmt);
}
} else {
$this->bindTypedParameters();
}
if (! $this->_stmt->execute()) {
throw StatementError::new($this->_stmt);
if (! $this->stmt->execute()) {
throw StatementError::new($this->stmt);
}
if ($this->_columnNames === null) {
$meta = $this->_stmt->result_metadata();
if ($this->columnNames === null) {
$meta = $this->stmt->result_metadata();
if ($meta !== false) {
$fields = $meta->fetch_fields();
assert(is_array($fields));
......@@ -164,17 +164,17 @@ class MysqliStatement implements IteratorAggregate, Statement
$meta->free();
$this->_columnNames = $columnNames;
$this->columnNames = $columnNames;
} else {
$this->_columnNames = false;
$this->columnNames = false;
}
}
if ($this->_columnNames !== false) {
if ($this->columnNames !== false) {
// Store result of every execution which has it. Otherwise it will be impossible
// to execute a new statement in case if the previous one has non-fetched rows
// @link http://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html
$this->_stmt->store_result();
$this->stmt->store_result();
// Bind row values _after_ storing the result. Otherwise, if mysqli is compiled with libmysql,
// it will have to allocate as much memory as it may be needed for the given column type
......@@ -187,15 +187,15 @@ class MysqliStatement implements IteratorAggregate, Statement
// It's also important that row values are bound after _each_ call to store_result(). Otherwise,
// if mysqli is compiled with libmysql, subsequently fetched string values will get truncated
// to the length of the ones fetched during the previous execution.
$this->_rowBindedValues = array_fill(0, count($this->_columnNames), null);
$this->rowBoundValues = array_fill(0, count($this->columnNames), null);
$refs = [];
foreach ($this->_rowBindedValues as $key => &$value) {
foreach ($this->rowBoundValues as $key => &$value) {
$refs[$key] =& $value;
}
if (! $this->_stmt->bind_result(...$refs)) {
throw StatementError::new($this->_stmt);
if (! $this->stmt->bind_result(...$refs)) {
throw StatementError::new($this->stmt);
}
}
......@@ -212,12 +212,12 @@ class MysqliStatement implements IteratorAggregate, Statement
$streams = $values = [];
$types = $this->types;
foreach ($this->_bindedValues as $parameter => $value) {
foreach ($this->boundValues as $parameter => $value) {
if (! isset($types[$parameter - 1])) {
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
$types[$parameter - 1] = self::$paramTypeMap[ParameterType::STRING];
}
if ($types[$parameter - 1] === static::$_paramTypeMap[ParameterType::LARGE_OBJECT]) {
if ($types[$parameter - 1] === self::$paramTypeMap[ParameterType::LARGE_OBJECT]) {
if (is_resource($value)) {
if (get_resource_type($value) !== 'stream') {
throw new InvalidArgumentException('Resources passed with the LARGE_OBJECT parameter type must be stream resources.');
......@@ -227,14 +227,14 @@ class MysqliStatement implements IteratorAggregate, Statement
continue;
}
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
$types[$parameter - 1] = self::$paramTypeMap[ParameterType::STRING];
}
$values[$parameter] = $value;
}
if (count($values) > 0 && ! $this->_stmt->bind_param($types, ...$values)) {
throw StatementError::new($this->_stmt);
if (count($values) > 0 && ! $this->stmt->bind_param($types, ...$values)) {
throw StatementError::new($this->stmt);
}
$this->sendLongData($streams);
......@@ -257,8 +257,8 @@ class MysqliStatement implements IteratorAggregate, Statement
throw FailedReadingStreamOffset::new($paramNr);
}
if (! $this->_stmt->send_long_data($paramNr - 1, $chunk)) {
throw StatementError::new($this->_stmt);
if (! $this->stmt->send_long_data($paramNr - 1, $chunk)) {
throw StatementError::new($this->stmt);
}
}
}
......@@ -278,7 +278,7 @@ class MysqliStatement implements IteratorAggregate, Statement
$params[] =& $v;
}
return $this->_stmt->bind_param($types, ...$params);
return $this->stmt->bind_param($types, ...$params);
}
/**
......@@ -286,11 +286,11 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
private function _fetch()
{
$ret = $this->_stmt->fetch();
$ret = $this->stmt->fetch();
if ($ret === true) {
$values = [];
foreach ($this->_rowBindedValues as $v) {
foreach ($this->rowBoundValues as $v) {
$values[] = $v;
}
......@@ -311,7 +311,7 @@ class MysqliStatement implements IteratorAggregate, Statement
return false;
}
$fetchMode = $fetchMode ?: $this->_defaultFetchMode;
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
if ($fetchMode === FetchMode::COLUMN) {
return $this->fetchColumn();
......@@ -324,15 +324,15 @@ class MysqliStatement implements IteratorAggregate, Statement
}
if ($values === false) {
throw StatementError::new($this->_stmt);
throw StatementError::new($this->stmt);
}
if ($fetchMode === FetchMode::NUMERIC) {
return $values;
}
assert(is_array($this->_columnNames));
$assoc = array_combine($this->_columnNames, $values);
assert(is_array($this->columnNames));
$assoc = array_combine($this->columnNames, $values);
assert(is_array($assoc));
switch ($fetchMode) {
......@@ -355,7 +355,7 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
{
$fetchMode = $fetchMode ?: $this->_defaultFetchMode;
$fetchMode = $fetchMode ?: $this->defaultFetchMode;
$rows = [];
......@@ -395,7 +395,7 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function closeCursor() : void
{
$this->_stmt->free_result();
$this->stmt->free_result();
$this->result = false;
}
......@@ -404,11 +404,11 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function rowCount() : int
{
if ($this->_columnNames === false) {
return $this->_stmt->affected_rows;
if ($this->columnNames === false) {
return $this->stmt->affected_rows;
}
return $this->_stmt->num_rows;
return $this->stmt->num_rows;
}
/**
......@@ -416,7 +416,7 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function columnCount() : int
{
return $this->_stmt->field_count;
return $this->stmt->field_count;
}
/**
......@@ -424,7 +424,7 @@ class MysqliStatement implements IteratorAggregate, Statement
*/
public function setFetchMode(int $fetchMode, ...$args) : void
{
$this->_defaultFetchMode = $fetchMode;
$this->defaultFetchMode = $fetchMode;
}
/**
......
......@@ -12,7 +12,7 @@ use const OCI_DEFAULT;
/**
* A Doctrine DBAL driver for the Oracle OCI8 PHP extensions.
*/
class Driver extends AbstractOracleDriver
final class Driver extends AbstractOracleDriver
{
/**
* {@inheritdoc}
......@@ -27,7 +27,7 @@ class Driver extends AbstractOracleDriver
return new OCI8Connection(
$username,
$password,
$this->_constructDsn($params),
$this->constructDsn($params),
$params['charset'] ?? '',
$params['sessionMode'] ?? OCI_DEFAULT,
$params['persistent'] ?? false
......@@ -44,7 +44,7 @@ class Driver extends AbstractOracleDriver
*
* @return string The DSN.
*/
protected function _constructDsn(array $params) : string
private function constructDsn(array $params) : string
{
return $this->getEasyConnectString($params);
}
......
......@@ -14,7 +14,7 @@ use PDO;
/**
* PDO MySql driver.
*/
class Driver extends AbstractMySQLDriver
final class Driver extends AbstractMySQLDriver
{
/**
* {@inheritdoc}
......@@ -50,7 +50,7 @@ class Driver extends AbstractMySQLDriver
*
* @return string The DSN.
*/
protected function constructPdoDsn(array $params) : string
private function constructPdoDsn(array $params) : string
{
$dsn = 'mysql:';
if (isset($params['host']) && $params['host'] !== '') {
......
......@@ -19,7 +19,7 @@ use PDO;
* which leads us to the recommendation to use the "oci8" driver to connect
* to Oracle instead.
*/
class Driver extends AbstractOracleDriver
final class Driver extends AbstractOracleDriver
{
/**
* {@inheritdoc}
......
......@@ -15,7 +15,7 @@ use function defined;
/**
* Driver that connects through pdo_pgsql.
*/
class Driver extends AbstractPostgreSQLDriver
final class Driver extends AbstractPostgreSQLDriver
{
/**
* {@inheritdoc}
......@@ -32,7 +32,7 @@ class Driver extends AbstractPostgreSQLDriver
try {
$connection = new PDOConnection(
$this->_constructPdoDsn($params),
$this->constructPdoDsn($params),
$username,
$password,
$driverOptions
......@@ -67,7 +67,7 @@ class Driver extends AbstractPostgreSQLDriver
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params) : string
private function constructPdoDsn(array $params) : string
{
$dsn = 'pgsql:';
......
......@@ -15,10 +15,10 @@ use function array_merge;
/**
* The PDO Sqlite driver.
*/
class Driver extends AbstractSQLiteDriver
final class Driver extends AbstractSQLiteDriver
{
/** @var mixed[] */
protected $_userDefinedFunctions = [
private $userDefinedFunctions = [
'sqrt' => ['callback' => [SqlitePlatform::class, 'udfSqrt'], 'numArgs' => 1],
'mod' => ['callback' => [SqlitePlatform::class, 'udfMod'], 'numArgs' => 2],
'locate' => ['callback' => [SqlitePlatform::class, 'udfLocate'], 'numArgs' => -1],
......@@ -34,8 +34,8 @@ class Driver extends AbstractSQLiteDriver
array $driverOptions = []
) : Connection {
if (isset($driverOptions['userDefinedFunctions'])) {
$this->_userDefinedFunctions = array_merge(
$this->_userDefinedFunctions,
$this->userDefinedFunctions = array_merge(
$this->userDefinedFunctions,
$driverOptions['userDefinedFunctions']
);
unset($driverOptions['userDefinedFunctions']);
......@@ -43,7 +43,7 @@ class Driver extends AbstractSQLiteDriver
try {
$connection = new PDOConnection(
$this->_constructPdoDsn($params),
$this->constructPdoDsn($params),
$username,
$password,
$driverOptions
......@@ -54,7 +54,7 @@ class Driver extends AbstractSQLiteDriver
$pdo = $connection->getWrappedConnection();
foreach ($this->_userDefinedFunctions as $fn => $data) {
foreach ($this->userDefinedFunctions as $fn => $data) {
$pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']);
}
......@@ -68,7 +68,7 @@ class Driver extends AbstractSQLiteDriver
*
* @return string The DSN.
*/
protected function _constructPdoDsn(array $params) : string
private function constructPdoDsn(array $params) : string
{
$dsn = 'sqlite:';
if (isset($params['path'])) {
......
......@@ -13,7 +13,7 @@ use function sprintf;
/**
* The PDO-based Sqlsrv driver.
*/
class Driver extends AbstractSQLServerDriver
final class Driver extends AbstractSQLServerDriver
{
/**
* {@inheritdoc}
......@@ -39,7 +39,7 @@ class Driver extends AbstractSQLServerDriver
}
return new Connection(
$this->_constructPdoDsn($params, $dsnOptions),
$this->constructPdoDsn($params, $dsnOptions),
$username,
$password,
$pdoOptions
......@@ -54,7 +54,7 @@ class Driver extends AbstractSQLServerDriver
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params, array $connectionOptions) : string
private function constructPdoDsn(array $params, array $connectionOptions) : string
{
$dsn = 'sqlsrv:server=';
......
......@@ -11,7 +11,7 @@ use PDO;
/**
* PDO SQL Server Statement
*/
class Statement extends PDOStatement
final class Statement extends PDOStatement
{
/**
* {@inheritdoc}
......
......@@ -16,7 +16,7 @@ use function sprintf;
/**
* A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension.
*/
class Driver extends AbstractSQLAnywhereDriver
final class Driver extends AbstractSQLAnywhereDriver
{
/**
* {@inheritdoc}
......
......@@ -23,7 +23,7 @@ use function sasql_set_option;
/**
* SAP Sybase SQL Anywhere implementation of the Connection interface.
*/
class SQLAnywhereConnection implements ServerInfoAwareConnection
final class SQLAnywhereConnection implements ServerInfoAwareConnection
{
/** @var resource The SQL Anywhere connection resource. */
private $connection;
......
......@@ -40,7 +40,7 @@ use function sprintf;
/**
* SAP SQL Anywhere implementation of the Statement interface.
*/
class SQLAnywhereStatement implements IteratorAggregate, Statement
final class SQLAnywhereStatement implements IteratorAggregate, Statement
{
/** @var resource The connection resource. */
private $conn;
......
......@@ -10,7 +10,7 @@ use Doctrine\DBAL\Driver\Connection;
/**
* Driver for ext/sqlsrv.
*/
class Driver extends AbstractSQLServerDriver
final class Driver extends AbstractSQLServerDriver
{
/**
* {@inheritdoc}
......
......@@ -20,13 +20,13 @@ use function str_replace;
/**
* SQL Server implementation for the Connection interface.
*/
class SQLSrvConnection implements ServerInfoAwareConnection
final class SQLSrvConnection implements ServerInfoAwareConnection
{
/** @var resource */
protected $conn;
private $conn;
/** @var LastInsertId */
protected $lastInsertId;
private $lastInsertId;
/**
* @param array<string, mixed> $connectionOptions
......
......@@ -37,7 +37,7 @@ use function stripos;
/**
* SQL Server Statement.
*/
class SQLSrvStatement implements IteratorAggregate, Statement
final class SQLSrvStatement implements IteratorAggregate, Statement
{
/**
* The SQLSRV Resource.
......@@ -232,51 +232,6 @@ class SQLSrvStatement implements IteratorAggregate, Statement
$this->result = true;
}
/**
* Prepares SQL Server statement resource
*
* @return resource
*
* @throws SQLSrvException
*/
private function prepare()
{
$params = [];
foreach ($this->variables as $column => &$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;
}
}
$stmt = sqlsrv_prepare($this->conn, $this->sql, $params);
if (! $stmt) {
throw SQLSrvException::fromSqlSrvErrors();
}
return $stmt;
}
/**
* {@inheritdoc}
*/
......@@ -399,4 +354,49 @@ class SQLSrvStatement implements IteratorAggregate, Statement
return sqlsrv_rows_affected($this->stmt) ?: 0;
}
/**
* Prepares SQL Server statement resource
*
* @return resource
*
* @throws SQLSrvException
*/
private function prepare()
{
$params = [];
foreach ($this->variables as $column => &$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;
}
}
$stmt = sqlsrv_prepare($this->conn, $this->sql, $params);
if (! $stmt) {
throw SQLSrvException::fromSqlSrvErrors();
}
return $stmt;
}
}
......@@ -6,7 +6,7 @@ namespace Doctrine\DBAL\Driver;
use IteratorAggregate;
class StatementIterator implements IteratorAggregate
final class StatementIterator implements IteratorAggregate
{
/** @var ResultStatement */
private $statement;
......
......@@ -12,7 +12,7 @@ use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Visitor\Visitor;
class TableGeneratorSchemaVisitor implements Visitor
final class TableGeneratorSchemaVisitor implements Visitor
{
/** @var string */
private $generatorTableName;
......
......@@ -18,7 +18,7 @@ use function rtrim;
/**
* Portability wrapper for a Statement.
*/
class Statement implements IteratorAggregate, DriverStatement
final class Statement implements IteratorAggregate, DriverStatement
{
/** @var int */
private $portability;
......@@ -164,34 +164,6 @@ class Statement implements IteratorAggregate, DriverStatement
return $rows;
}
/**
* @param mixed $row
*
* @return mixed
*/
protected function fixRow($row, bool $iterateRow, bool $fixCase)
{
if (! $row) {
return $row;
}
if ($fixCase) {
$row = array_change_key_case($row, $this->case);
}
if ($iterateRow) {
foreach ($row as $k => $v) {
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') {
$row[$k] = null;
} elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) {
$row[$k] = rtrim($v);
}
}
}
return $row;
}
/**
* {@inheritdoc}
*/
......@@ -219,4 +191,32 @@ class Statement implements IteratorAggregate, DriverStatement
return $this->stmt->rowCount();
}
/**
* @param mixed $row
*
* @return mixed
*/
private function fixRow($row, bool $iterateRow, bool $fixCase)
{
if (! $row) {
return $row;
}
if ($fixCase) {
$row = array_change_key_case($row, $this->case);
}
if ($iterateRow) {
foreach ($row as $k => $v) {
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') {
$row[$k] = null;
} elseif (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) {
$row[$k] = rtrim($v);
}
}
}
return $row;
}
}
......@@ -14,7 +14,7 @@ use function count;
/**
* Schema Synchronizer for Default DBAL Connection.
*/
class SingleDatabaseSynchronizer extends AbstractSchemaSynchronizer
final class SingleDatabaseSynchronizer extends AbstractSchemaSynchronizer
{
/** @var AbstractPlatform */
private $platform;
......
......@@ -20,7 +20,7 @@ use Doctrine\DBAL\Schema\Table;
* This visitor filters all these non-default namespaced tables and sequences
* and removes them from the SChema instance.
*/
class RemoveNamespacedAssets extends AbstractVisitor
final class RemoveNamespacedAssets extends AbstractVisitor
{
/** @var Schema */
private $schema;
......
......@@ -4,35 +4,14 @@ declare(strict_types=1);
namespace Doctrine\Tests\DBAL\Driver;
use Doctrine\DBAL\Driver\IBMDB2\DB2Statement;
use Doctrine\DBAL\Driver\Mysqli\MysqliStatement;
use Doctrine\DBAL\Driver\OCI8\OCI8Statement;
use Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereStatement;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Portability\Statement as PortabilityStatement;
use Doctrine\Tests\DbalTestCase;
use IteratorAggregate;
use PHPUnit\Framework\MockObject\MockObject;
use function extension_loaded;
use Traversable;
class StatementIteratorTest extends DbalTestCase
{
/**
* @dataProvider statementProvider()
*/
public function testGettingIteratorDoesNotCallFetch(string $class) : void
{
/** @var IteratorAggregate|MockObject $stmt */
$stmt = $this->createPartialMock($class, ['fetch', 'fetchAll', 'fetchColumn']);
$stmt->expects($this->never())->method('fetch');
$stmt->expects($this->never())->method('fetchAll');
$stmt->expects($this->never())->method('fetchColumn');
$stmt->getIterator();
}
public function testIteratorIterationCallsFetchOncePerStep() : void
{
$stmt = $this->createMock(Statement::class);
......@@ -45,20 +24,6 @@ class StatementIteratorTest extends DbalTestCase
$this->assertIterationCallsFetchOncePerStep($stmtIterator, $calls);
}
/**
* @dataProvider statementProvider()
*/
public function testStatementIterationCallsFetchOncePerStep(string $class) : void
{
/** @var iterable<int, mixed>|MockObject $stmt */
$stmt = $this->createPartialMock($class, ['fetch']);
$calls = 0;
$this->configureStatement($stmt, $calls);
$this->assertIterationCallsFetchOncePerStep($stmt, $calls);
}
private function configureStatement(MockObject $stmt, int &$calls) : void
{
$values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false, 'impossible'];
......@@ -74,33 +39,7 @@ class StatementIteratorTest extends DbalTestCase
});
}
/**
* @return string[][]
*/
public static function statementProvider() : iterable
{
if (extension_loaded('ibm_db2')) {
yield [DB2Statement::class];
}
yield [MysqliStatement::class];
if (extension_loaded('oci8')) {
yield [OCI8Statement::class];
}
yield [PortabilityStatement::class];
yield [SQLAnywhereStatement::class];
if (extension_loaded('sqlsrv')) {
yield [SQLSrvStatement::class];
}
}
/**
* @param iterable<int, mixed> $iterator
*/
private function assertIterationCallsFetchOncePerStep(iterable $iterator, int &$calls) : void
private function assertIterationCallsFetchOncePerStep(Traversable $iterator, int &$calls) : void
{
foreach ($iterator as $i => $_) {
$this->assertEquals($i + 1, $calls);
......
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