diff --git a/UPGRADE.md b/UPGRADE.md index 0cb2ad18500..4c4b3fc0eda 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,13 @@ # Upgrade to 3.0 +## BC BREAK: Dropped support for `FetchMode::CUSTOM_OBJECT` and `::STANDARD_OBJECT` + +Instead of fetching an object, fetch an array and map it to an object of the desired class. + +## BC BREAK: Dropped support for the `$columnIndex` argument in `ResultStatement::fetchColumn()`, other `ResultStatement::fetch*()` methods invoked with `FetchMode::COLUMN` and `Connection::fetchColumn()`. + +In order to fetch a column with an index other than `0`, use `FetchMode::NUMERIC` and the array element with the corresponding index. + ## BC BREAK: Removed `EchoSQLLogger` `EchoSQLLogger` is no longer available as part of the package. diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 867cc3bdc29..bd006f20217 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -98,12 +98,6 @@ parameters: - %currentWorkingDirectory%/src/Query/QueryBuilder.php - %currentWorkingDirectory%/src/Schema/*SchemaManager.php - # FetchMode::CUSTOM_OBJECT requires variable property access - - - message: '~^Variable property access on object\.~' - paths: - - %currentWorkingDirectory%/src/Driver/*/*Statement.php - # Some APIs use variable method calls internally - message: '~^Variable method call on .*~' diff --git a/src/Cache/ArrayStatement.php b/src/Cache/ArrayStatement.php index 38e337e800a..29c76cd3fe7 100644 --- a/src/Cache/ArrayStatement.php +++ b/src/Cache/ArrayStatement.php @@ -60,12 +60,8 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { - if (count($args) > 0) { - throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode()'); - } - $this->defaultFetchMode = $fetchMode; return true; @@ -84,7 +80,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { if (! isset($this->data[$this->num])) { return false; @@ -115,10 +111,10 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $rows = []; - while ($row = $this->fetch($fetchMode, ...$args)) { + while ($row = $this->fetch($fetchMode)) { $rows[] = $row; } @@ -128,11 +124,11 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); // TODO: verify that return false is the correct behavior - return $row[$columnIndex] ?? false; + return $row[0] ?? false; } } diff --git a/src/Cache/ResultCacheStatement.php b/src/Cache/ResultCacheStatement.php index 36f01880423..58178ce6db6 100644 --- a/src/Cache/ResultCacheStatement.php +++ b/src/Cache/ResultCacheStatement.php @@ -104,7 +104,7 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; @@ -124,7 +124,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { if ($this->data === null) { $this->data = []; @@ -164,9 +164,9 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { - $data = $this->statement->fetchAll($fetchMode, ...$args); + $data = $this->statement->fetchAll($fetchMode); if ($fetchMode === FetchMode::COLUMN) { foreach ($data as $key => $value) { @@ -183,12 +183,12 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); // TODO: verify that return false is the correct behavior - return $row[$columnIndex] ?? false; + return $row[0] ?? false; } /** diff --git a/src/Connection.php b/src/Connection.php index cca1716625f..bb0625b9de1 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -570,16 +570,15 @@ public function fetchArray($statement, array $params = [], array $types = []) * * @param string $statement The SQL query to be executed. * @param mixed[] $params The prepared statement params. - * @param int $column The 0-indexed column number to retrieve. * @param int[]|string[] $types The query parameter types. * * @return mixed|false False is returned if no rows are found. * * @throws DBALException */ - public function fetchColumn($statement, array $params = [], $column = 0, array $types = []) + public function fetchColumn($statement, array $params = [], array $types = []) { - return $this->executeQuery($statement, $params, $types)->fetchColumn($column); + return $this->executeQuery($statement, $params, $types)->fetchColumn(); } /** diff --git a/src/Driver/IBMDB2/DB2Statement.php b/src/Driver/IBMDB2/DB2Statement.php index 6c8c5cb3b7e..49282e0bb0e 100644 --- a/src/Driver/IBMDB2/DB2Statement.php +++ b/src/Driver/IBMDB2/DB2Statement.php @@ -7,25 +7,17 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use ReflectionClass; -use ReflectionObject; -use ReflectionProperty; -use stdClass; -use const CASE_LOWER; use const DB2_BINARY; use const DB2_CHAR; use const DB2_LONG; use const DB2_PARAM_FILE; use const DB2_PARAM_IN; -use function array_change_key_case; use function assert; -use function count; use function db2_bind_param; use function db2_execute; use function db2_fetch_array; use function db2_fetch_assoc; use function db2_fetch_both; -use function db2_fetch_object; use function db2_free_result; use function db2_num_fields; use function db2_num_rows; @@ -34,16 +26,11 @@ use function error_get_last; use function fclose; use function fwrite; -use function gettype; use function is_int; -use function is_object; use function is_resource; -use function is_string; use function ksort; -use function sprintf; use function stream_copy_to_stream; use function stream_get_meta_data; -use function strtolower; use function tmpfile; class DB2Statement implements IteratorAggregate, Statement @@ -62,12 +49,6 @@ class DB2Statement implements IteratorAggregate, Statement */ private $lobs = []; - /** @var string Name of the default class to instantiate when fetching class instances. */ - private $defaultFetchClass = '\stdClass'; - - /** @var mixed[] Constructor arguments for the default class to instantiate when fetching class instances. */ - private $defaultFetchClassCtorArgs = []; - /** @var int */ private $defaultFetchMode = FetchMode::MIXED; @@ -237,18 +218,10 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; - if (isset($args[0])) { - $this->defaultFetchClass = $args[0]; - } - - if (isset($args[1])) { - $this->defaultFetchClassCtorArgs = (array) $args[1]; - } - return true; } @@ -263,7 +236,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -282,29 +255,9 @@ public function fetch($fetchMode = null, ...$args) case FetchMode::ASSOCIATIVE: return db2_fetch_assoc($this->stmt); - case FetchMode::CUSTOM_OBJECT: - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (count($args) > 0) { - $className = $args[0]; - $ctorArgs = $args[1] ?? []; - } - - $result = db2_fetch_object($this->stmt); - - if ($result instanceof stdClass) { - $result = $this->castObject($result, $className, $ctorArgs); - } - - return $result; - case FetchMode::NUMERIC: return db2_fetch_array($this->stmt); - case FetchMode::STANDARD_OBJECT: - return db2_fetch_object($this->stmt); - default: throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.'); } @@ -313,16 +266,11 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $rows = []; switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch($fetchMode, ...$args)) !== false) { - $rows[] = $row; - } - break; case FetchMode::COLUMN: while (($row = $this->fetchColumn()) !== false) { $rows[] = $row; @@ -340,7 +288,7 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); @@ -348,7 +296,7 @@ public function fetchColumn($columnIndex = 0) return false; } - return $row[$columnIndex] ?? null; + return $row[0] ?? null; } /** @@ -359,71 +307,6 @@ public function rowCount() : int return @db2_num_rows($this->stmt); } - /** - * Casts a stdClass object to the given class name mapping its' properties. - * - * @param stdClass $sourceObject Object to cast from. - * @param string|object $destinationClass Name of the class or class instance to cast to. - * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. - * - * @return object - * - * @throws DB2Exception - */ - private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) - { - if (! is_string($destinationClass)) { - if (! is_object($destinationClass)) { - throw new DB2Exception(sprintf( - 'Destination class has to be of type string or object, %s given.', - gettype($destinationClass) - )); - } - } else { - $destinationClass = new ReflectionClass($destinationClass); - $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); - } - - $sourceReflection = new ReflectionObject($sourceObject); - $destinationClassReflection = new ReflectionObject($destinationClass); - /** @var ReflectionProperty[] $destinationProperties */ - $destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), CASE_LOWER); - - foreach ($sourceReflection->getProperties() as $sourceProperty) { - $sourceProperty->setAccessible(true); - - $name = $sourceProperty->getName(); - $value = $sourceProperty->getValue($sourceObject); - - // Try to find a case-matching property. - if ($destinationClassReflection->hasProperty($name)) { - $destinationProperty = $destinationClassReflection->getProperty($name); - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - - continue; - } - - $name = strtolower($name); - - // Try to find a property without matching case. - // Fallback for the driver returning either all uppercase or all lowercase column names. - if (isset($destinationProperties[$name])) { - $destinationProperty = $destinationProperties[$name]; - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - - continue; - } - - $destinationClass->$name = $value; - } - - return $destinationClass; - } - /** * @return resource * diff --git a/src/Driver/Mysqli/MysqliStatement.php b/src/Driver/Mysqli/MysqliStatement.php index f16025847a2..4795b291753 100644 --- a/src/Driver/Mysqli/MysqliStatement.php +++ b/src/Driver/Mysqli/MysqliStatement.php @@ -306,7 +306,7 @@ private function _fetch() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -345,9 +345,6 @@ public function fetch($fetchMode = null, ...$args) case FetchMode::MIXED: return $assoc + $values; - case FetchMode::STANDARD_OBJECT: - return (object) $assoc; - default: throw new MysqliException(sprintf("Unknown fetch type '%s'", $fetchMode)); } @@ -356,7 +353,7 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $fetchMode = $fetchMode ?? $this->_defaultFetchMode; @@ -378,7 +375,7 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); @@ -386,7 +383,7 @@ public function fetchColumn($columnIndex = 0) return false; } - return $row[$columnIndex] ?? null; + return $row[0] ?? null; } /** @@ -439,7 +436,7 @@ public function columnCount() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->_defaultFetchMode = $fetchMode; diff --git a/src/Driver/OCI8/OCI8Statement.php b/src/Driver/OCI8/OCI8Statement.php index f8a030395ff..d74fb3a8a85 100644 --- a/src/Driver/OCI8/OCI8Statement.php +++ b/src/Driver/OCI8/OCI8Statement.php @@ -33,7 +33,6 @@ use function oci_execute; use function oci_fetch_all; use function oci_fetch_array; -use function oci_fetch_object; use function oci_new_descriptor; use function oci_num_fields; use function oci_num_rows; @@ -411,7 +410,7 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->_defaultFetchMode = $fetchMode; @@ -429,7 +428,7 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -443,10 +442,6 @@ public function fetch($fetchMode = null, ...$args) return $this->fetchColumn(); } - if ($fetchMode === FetchMode::STANDARD_OBJECT) { - return oci_fetch_object($this->_sth); - } - if (! isset(self::$fetchModeMap[$fetchMode])) { throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); } @@ -460,20 +455,12 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $fetchMode = $fetchMode ?? $this->_defaultFetchMode; $result = []; - if ($fetchMode === FetchMode::STANDARD_OBJECT) { - while ($row = $this->fetch($fetchMode)) { - $result[] = $row; - } - - return $result; - } - if (! isset(self::$fetchModeMap[$fetchMode])) { throw new InvalidArgumentException('Invalid fetch style: ' . $fetchMode); } @@ -514,7 +501,7 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -528,7 +515,7 @@ public function fetchColumn($columnIndex = 0) return false; } - return $row[$columnIndex] ?? null; + return $row[0] ?? null; } /** diff --git a/src/Driver/PDOStatement.php b/src/Driver/PDOStatement.php index 876f74106eb..9dae60bdbaa 100644 --- a/src/Driver/PDOStatement.php +++ b/src/Driver/PDOStatement.php @@ -28,12 +28,10 @@ class PDOStatement implements IteratorAggregate, Statement ]; private const FETCH_MODE_MAP = [ - FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC, - FetchMode::NUMERIC => PDO::FETCH_NUM, - FetchMode::MIXED => PDO::FETCH_BOTH, - FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ, - FetchMode::COLUMN => PDO::FETCH_COLUMN, - FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS, + FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC, + FetchMode::NUMERIC => PDO::FETCH_NUM, + FetchMode::MIXED => PDO::FETCH_BOTH, + FetchMode::COLUMN => PDO::FETCH_COLUMN, ]; /** @var \PDOStatement */ @@ -47,12 +45,12 @@ public function __construct(\PDOStatement $stmt) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $fetchMode = $this->convertFetchMode($fetchMode); try { - return $this->stmt->setFetchMode($fetchMode, ...$args); + return $this->stmt->setFetchMode($fetchMode); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -141,7 +139,7 @@ public function rowCount() : int /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { try { if ($fetchMode === null) { @@ -149,8 +147,7 @@ public function fetch($fetchMode = null, ...$args) } return $this->stmt->fetch( - $this->convertFetchMode($fetchMode), - ...$args + $this->convertFetchMode($fetchMode) ); } catch (\PDOException $exception) { throw new PDOException($exception); @@ -160,15 +157,14 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { try { if ($fetchMode === null) { $data = $this->stmt->fetchAll(); } else { $data = $this->stmt->fetchAll( - $this->convertFetchMode($fetchMode), - ...$args + $this->convertFetchMode($fetchMode) ); } } catch (\PDOException $exception) { @@ -183,10 +179,10 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { try { - return $this->stmt->fetchColumn($columnIndex); + return $this->stmt->fetchColumn(); } catch (\PDOException $exception) { throw new PDOException($exception); } diff --git a/src/Driver/ResultStatement.php b/src/Driver/ResultStatement.php index 8cbd2688a21..9de8dae02aa 100644 --- a/src/Driver/ResultStatement.php +++ b/src/Driver/ResultStatement.php @@ -28,13 +28,12 @@ public function columnCount(); /** * Sets the fetch mode to use while iterating this statement. * - * @param int $fetchMode Controls how the next row will be returned to the caller. - * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants. - * @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}). + * @param int $fetchMode Controls how the next row will be returned to the caller. + * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants. * * @return bool */ - public function setFetchMode($fetchMode, ...$args); + public function setFetchMode($fetchMode); /** * Returns the next row of a result set. @@ -42,12 +41,11 @@ public function setFetchMode($fetchMode, ...$args); * @param int|null $fetchMode Controls how the next row will be returned to the caller. * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. - * @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}). * * @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is * returned on failure. */ - public function fetch($fetchMode = null, ...$args); + public function fetch($fetchMode = null); /** * Returns an array containing all of the result set rows. @@ -55,24 +53,15 @@ public function fetch($fetchMode = null, ...$args); * @param int|null $fetchMode Controls how the next row will be returned to the caller. * The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants, * defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}. - * @param mixed ...$args Optional mode-specific arguments. Supported modes: - * * {@link \Doctrine\DBAL\FetchMode::COLUMN} - * 1. The 0-indexed column to be returned. - * * {@link \Doctrine\DBAL\FetchMode::CUSTOM_OBJECT} - * 1. The class name of the object to be created, - * 2. Array of constructor arguments * * @return mixed[] */ - public function fetchAll($fetchMode = null, ...$args); + public function fetchAll($fetchMode = null); /** * Returns a single column from the next row of a result set or FALSE if there are no more rows. * - * @param int $columnIndex 0-indexed number of the column you wish to retrieve from the row. - * If no value is supplied, fetches the first column. - * * @return mixed|false A single column in the next row of a result set, or FALSE if there are no more rows. */ - public function fetchColumn($columnIndex = 0); + public function fetchColumn(); } diff --git a/src/Driver/SQLAnywhere/SQLAnywhereStatement.php b/src/Driver/SQLAnywhere/SQLAnywhereStatement.php index 0667617426a..444f41d1bdb 100644 --- a/src/Driver/SQLAnywhere/SQLAnywhereStatement.php +++ b/src/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -7,21 +7,13 @@ use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use IteratorAggregate; -use ReflectionClass; -use ReflectionObject; -use stdClass; use const SASQL_BOTH; use function array_key_exists; use function assert; -use function count; -use function gettype; use function is_int; -use function is_object; use function is_resource; -use function is_string; use function sasql_fetch_array; use function sasql_fetch_assoc; -use function sasql_fetch_object; use function sasql_fetch_row; use function sasql_prepare; use function sasql_stmt_affected_rows; @@ -32,7 +24,6 @@ use function sasql_stmt_field_count; use function sasql_stmt_reset; use function sasql_stmt_result_metadata; -use function sprintf; /** * SAP SQL Anywhere implementation of the Statement interface. @@ -42,12 +33,6 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement /** @var resource The connection resource. */ private $conn; - /** @var string Name of the default class to instantiate when fetching class instances. */ - private $defaultFetchClass = '\stdClass'; - - /** @var mixed[] Constructor arguments for the default class to instantiate when fetching class instances. */ - private $defaultFetchClassCtorArgs = []; - /** @var int Default fetch mode to use. */ private $defaultFetchMode = FetchMode::MIXED; @@ -199,7 +184,7 @@ public function execute($params = null) * * @throws SQLAnywhereException */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { if (! is_resource($this->result)) { return false; @@ -217,29 +202,9 @@ public function fetch($fetchMode = null, ...$args) case FetchMode::MIXED: return sasql_fetch_array($this->result, SASQL_BOTH); - case FetchMode::CUSTOM_OBJECT: - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (count($args) > 0) { - $className = $args[0]; - $ctorArgs = $args[1] ?? []; - } - - $result = sasql_fetch_object($this->result); - - if ($result instanceof stdClass) { - $result = $this->castObject($result, $className, $ctorArgs); - } - - return $result; - case FetchMode::NUMERIC: return sasql_fetch_row($this->result); - case FetchMode::STANDARD_OBJECT: - return sasql_fetch_object($this->result); - default: throw new SQLAnywhereException('Fetch mode is not supported: ' . $fetchMode); } @@ -248,17 +213,11 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $rows = []; switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch($fetchMode, ...$args)) !== false) { - $rows[] = $row; - } - break; - case FetchMode::COLUMN: while (($row = $this->fetchColumn()) !== false) { $rows[] = $row; @@ -277,7 +236,7 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); @@ -285,7 +244,7 @@ public function fetchColumn($columnIndex = 0) return false; } - return $row[$columnIndex] ?? null; + return $row[0] ?? null; } /** @@ -307,65 +266,10 @@ public function rowCount() : int /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; - if (isset($args[0])) { - $this->defaultFetchClass = $args[0]; - } - - if (isset($args[1])) { - $this->defaultFetchClassCtorArgs = (array) $args[1]; - } - return true; } - - /** - * Casts a stdClass object to the given class name mapping its' properties. - * - * @param stdClass $sourceObject Object to cast from. - * @param string|object $destinationClass Name of the class or class instance to cast to. - * @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance. - * - * @return object - * - * @throws SQLAnywhereException - */ - private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) - { - if (! is_string($destinationClass)) { - if (! is_object($destinationClass)) { - throw new SQLAnywhereException(sprintf( - 'Destination class has to be of type string or object, %s given.', - gettype($destinationClass) - )); - } - } else { - $destinationClass = new ReflectionClass($destinationClass); - $destinationClass = $destinationClass->newInstanceArgs($ctorArgs); - } - - $sourceReflection = new ReflectionObject($sourceObject); - $destinationClassReflection = new ReflectionObject($destinationClass); - - foreach ($sourceReflection->getProperties() as $sourceProperty) { - $sourceProperty->setAccessible(true); - - $name = $sourceProperty->getName(); - $value = $sourceProperty->getValue($sourceObject); - - if ($destinationClassReflection->hasProperty($name)) { - $destinationProperty = $destinationClassReflection->getProperty($name); - - $destinationProperty->setAccessible(true); - $destinationProperty->setValue($destinationClass, $value); - } else { - $destinationClass->$name = $value; - } - } - - return $destinationClass; - } } diff --git a/src/Driver/SQLSrv/SQLSrvStatement.php b/src/Driver/SQLSrv/SQLSrvStatement.php index 6ba0bbd1e53..92aa3f759a3 100644 --- a/src/Driver/SQLSrv/SQLSrvStatement.php +++ b/src/Driver/SQLSrv/SQLSrvStatement.php @@ -14,15 +14,12 @@ use const SQLSRV_FETCH_NUMERIC; use const SQLSRV_PARAM_IN; use function array_key_exists; -use function count; -use function in_array; use function is_int; use function is_numeric; use function sqlsrv_errors; use function sqlsrv_execute; use function sqlsrv_fetch; use function sqlsrv_fetch_array; -use function sqlsrv_fetch_object; use function sqlsrv_get_field; use function sqlsrv_next_result; use function sqlsrv_num_fields; @@ -84,20 +81,6 @@ class SQLSrvStatement implements IteratorAggregate, Statement FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC, ]; - /** - * The name of the default class to instantiate when fetching class instances. - * - * @var string - */ - private $defaultFetchClass = '\stdClass'; - - /** - * The constructor arguments for the default class to instantiate when fetching class instances. - * - * @var mixed[] - */ - private $defaultFetchClassCtorArgs = []; - /** * The fetch style. * @@ -322,18 +305,10 @@ private function prepare() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; - if (isset($args[0])) { - $this->defaultFetchClass = $args[0]; - } - - if (isset($args[1])) { - $this->defaultFetchClassCtorArgs = (array) $args[1]; - } - return true; } @@ -350,7 +325,7 @@ public function getIterator() * * @throws SQLSrvException */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { // do not try fetching from the statement if it's not expected to contain result // in order to prevent exceptional situation @@ -368,35 +343,17 @@ public function fetch($fetchMode = null, ...$args) return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?? false; } - if (in_array($fetchMode, [FetchMode::STANDARD_OBJECT, FetchMode::CUSTOM_OBJECT], true)) { - $className = $this->defaultFetchClass; - $ctorArgs = $this->defaultFetchClassCtorArgs; - - if (count($args) > 0) { - $className = $args[0]; - $ctorArgs = $args[1] ?? []; - } - - return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?? false; - } - throw new SQLSrvException('Fetch mode is not supported!'); } /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $rows = []; switch ($fetchMode) { - case FetchMode::CUSTOM_OBJECT: - while (($row = $this->fetch($fetchMode, ...$args)) !== false) { - $rows[] = $row; - } - break; - case FetchMode::COLUMN: while (($row = $this->fetchColumn()) !== false) { $rows[] = $row; @@ -415,7 +372,7 @@ public function fetchAll($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { $row = $this->fetch(FetchMode::NUMERIC); @@ -423,7 +380,7 @@ public function fetchColumn($columnIndex = 0) return false; } - return $row[$columnIndex] ?? null; + return $row[0] ?? null; } /** diff --git a/src/FetchMode.php b/src/FetchMode.php index 65af014f1e0..b5dbab11667 100644 --- a/src/FetchMode.php +++ b/src/FetchMode.php @@ -35,15 +35,6 @@ final class FetchMode */ public const MIXED = 4; - /** - * Specifies that the fetch method shall return each row as an object with - * property names that correspond to the column names returned in the result - * set. - * - * @see \PDO::FETCH_OBJ - */ - public const STANDARD_OBJECT = 5; - /** * Specifies that the fetch method shall return only a single requested * column from the next row in the result set. @@ -52,14 +43,6 @@ final class FetchMode */ public const COLUMN = 7; - /** - * Specifies that the fetch method shall return a new instance of the - * requested class, mapping the columns to named properties in the class. - * - * @see \PDO::FETCH_CLASS - */ - public const CUSTOM_OBJECT = 8; - /** * This class cannot be instantiated. */ diff --git a/src/Portability/Statement.php b/src/Portability/Statement.php index 397f96c5954..d1369dfa2f9 100644 --- a/src/Portability/Statement.php +++ b/src/Portability/Statement.php @@ -111,11 +111,11 @@ public function execute($params = null) /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { $this->defaultFetchMode = $fetchMode; - return $this->stmt->setFetchMode($fetchMode, ...$args); + return $this->stmt->setFetchMode($fetchMode); } /** @@ -129,11 +129,11 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { $fetchMode = $fetchMode ?? $this->defaultFetchMode; - $row = $this->stmt->fetch($fetchMode, ...$args); + $row = $this->stmt->fetch($fetchMode); $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; $fixCase = $this->case !== null @@ -148,11 +148,11 @@ public function fetch($fetchMode = null, ...$args) /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { $fetchMode = $fetchMode ?? $this->defaultFetchMode; - $rows = $this->stmt->fetchAll($fetchMode, ...$args); + $rows = $this->stmt->fetchAll($fetchMode); $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; $fixCase = $this->case !== null @@ -215,9 +215,9 @@ protected function fixRow($row, $iterateRow, $fixCase) /** * {@inheritdoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { - $value = $this->stmt->fetchColumn($columnIndex); + $value = $this->stmt->fetchColumn(); if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') { $value = null; diff --git a/src/Statement.php b/src/Statement.php index ab848b3dc42..93201d29a5d 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -211,9 +211,9 @@ public function errorInfo() /** * {@inheritdoc} */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode($fetchMode) { - return $this->stmt->setFetchMode($fetchMode, ...$args); + return $this->stmt->setFetchMode($fetchMode); } /** @@ -229,25 +229,25 @@ public function getIterator() /** * {@inheritdoc} */ - public function fetch($fetchMode = null, ...$args) + public function fetch($fetchMode = null) { - return $this->stmt->fetch($fetchMode, ...$args); + return $this->stmt->fetch($fetchMode); } /** * {@inheritdoc} */ - public function fetchAll($fetchMode = null, ...$args) + public function fetchAll($fetchMode = null) { - return $this->stmt->fetchAll($fetchMode, ...$args); + return $this->stmt->fetchAll($fetchMode); } /** * {@inheritDoc} */ - public function fetchColumn($columnIndex = 0) + public function fetchColumn() { - return $this->stmt->fetchColumn($columnIndex); + return $this->stmt->fetchColumn(); } /** diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index ef14ea66ff8..6e2545b75f3 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -627,7 +627,6 @@ public function testFetchColumn() : void $statement = 'SELECT * FROM foo WHERE bar = ?'; $params = [666]; $types = [ParameterType::INTEGER]; - $column = 0; $result = []; $driverMock = $this->createMock(Driver::class); @@ -642,7 +641,6 @@ public function testFetchColumn() : void $driverStatementMock->expects(self::once()) ->method('fetchColumn') - ->with($column) ->will(self::returnValue($result)); /** @var Connection|MockObject $conn */ @@ -656,7 +654,7 @@ public function testFetchColumn() : void ->with($statement, $params, $types) ->will(self::returnValue($driverStatementMock)); - self::assertSame($result, $conn->fetchColumn($statement, $params, $column, $types)); + self::assertSame($result, $conn->fetchColumn($statement, $params, $types)); } public function testFetchAll() : void diff --git a/tests/Functional/DataAccessTest.php b/tests/Functional/DataAccessTest.php index 2706f3b3176..b73eeea39c2 100644 --- a/tests/Functional/DataAccessTest.php +++ b/tests/Functional/DataAccessTest.php @@ -6,9 +6,6 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver; -use Doctrine\DBAL\Driver\OCI8\Driver as Oci8Driver; -use Doctrine\DBAL\Driver\PDOConnection; -use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver; use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver; use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; @@ -18,7 +15,6 @@ use Doctrine\DBAL\Statement; use Doctrine\DBAL\Tests\FunctionalTestCase; use Doctrine\DBAL\Types\Types; -use PDO; use const CASE_LOWER; use function array_change_key_case; use function array_filter; @@ -27,7 +23,6 @@ use function date; use function is_numeric; use function json_encode; -use function property_exists; use function sprintf; use function strtotime; @@ -376,13 +371,13 @@ public function testFetchArrayWithMissingTypes() : void public function testFetchColumn() : void { - $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $testInt = $this->connection->fetchColumn($sql, [1, 'foo'], 0); + $sql = 'SELECT test_int FROM fetch_table WHERE test_int = ? AND test_string = ?'; + $testInt = $this->connection->fetchColumn($sql, [1, 'foo']); self::assertEquals(1, $testInt); - $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $testString = $this->connection->fetchColumn($sql, [1, 'foo'], 1); + $sql = 'SELECT test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; + $testString = $this->connection->fetchColumn($sql, [1, 'foo']); self::assertEquals('foo', $testString); } @@ -392,15 +387,14 @@ public function testFetchColumnWithTypes() : void $datetimeString = '2010-01-01 10:10:10'; $datetime = new DateTime($datetimeString); - $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; + $sql = 'SELECT test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; $column = $this->connection->fetchColumn( $sql, [1, $datetime], - 1, [ParameterType::STRING, Types::DATETIME_MUTABLE] ); - self::assertNotFalse($column); + self::assertIsString($column); self::assertStringStartsWith($datetimeString, $column); } @@ -418,7 +412,7 @@ public function testFetchColumnWithMissingTypes() : void $this->expectException(DBALException::class); - $this->connection->fetchColumn($sql, [1, $datetime], 1); + $this->connection->fetchColumn($sql, [1, $datetime]); } /** @@ -635,7 +629,7 @@ public function testSqliteDateArithmeticWithDynamicInterval() : void $sql = 'SELECT COUNT(*) FROM fetch_table_date_math WHERE '; $sql .= $platform->getDateSubDaysExpression('test_date', 'test_days') . " < '2010-05-12'"; - $rowCount = $this->connection->fetchColumn($sql, [], 0); + $rowCount = $this->connection->fetchColumn($sql); self::assertEquals(1, $rowCount); } @@ -738,62 +732,6 @@ public function testSetDefaultFetchMode() : void }), 'should be no non-numerical elements in the result.'); } - /** - * @group DBAL-1091 - */ - public function testFetchAllStyleObject() : void - { - $this->setupFixture(); - - $sql = 'SELECT test_int, test_string, test_datetime FROM fetch_table'; - $stmt = $this->connection->prepare($sql); - - $stmt->execute(); - - $results = $stmt->fetchAll(FetchMode::STANDARD_OBJECT); - - self::assertCount(1, $results); - self::assertInstanceOf('stdClass', $results[0]); - - self::assertEquals( - 1, - property_exists($results[0], 'test_int') ? $results[0]->test_int : $results[0]->TEST_INT - ); - self::assertEquals( - 'foo', - property_exists($results[0], 'test_string') ? $results[0]->test_string : $results[0]->TEST_STRING - ); - self::assertStringStartsWith( - '2010-01-01 10:10:10', - property_exists($results[0], 'test_datetime') ? $results[0]->test_datetime : $results[0]->TEST_DATETIME - ); - } - - /** - * @group DBAL-196 - */ - public function testFetchAllSupportFetchClass() : void - { - $this->beforeFetchClassTest(); - $this->setupFixture(); - - $sql = 'SELECT test_int, test_string, test_datetime FROM fetch_table'; - $stmt = $this->connection->prepare($sql); - $stmt->execute(); - - $results = $stmt->fetchAll( - FetchMode::CUSTOM_OBJECT, - MyFetchClass::class - ); - - self::assertCount(1, $results); - self::assertInstanceOf(MyFetchClass::class, $results[0]); - - self::assertEquals(1, $results[0]->test_int); - self::assertEquals('foo', $results[0]->test_string); - self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime); - } - /** * @group DBAL-241 */ @@ -811,53 +749,6 @@ public function testFetchAllStyleColumn() : void self::assertEquals([1, 10], $rows); } - /** - * @group DBAL-214 - */ - public function testSetFetchModeClassFetchAll() : void - { - $this->beforeFetchClassTest(); - $this->setupFixture(); - - $sql = 'SELECT * FROM fetch_table'; - $stmt = $this->connection->query($sql); - $stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, MyFetchClass::class); - - $results = $stmt->fetchAll(); - - self::assertCount(1, $results); - self::assertInstanceOf(MyFetchClass::class, $results[0]); - - self::assertEquals(1, $results[0]->test_int); - self::assertEquals('foo', $results[0]->test_string); - self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime); - } - - /** - * @group DBAL-214 - */ - public function testSetFetchModeClassFetch() : void - { - $this->beforeFetchClassTest(); - $this->setupFixture(); - - $sql = 'SELECT * FROM fetch_table'; - $stmt = $this->connection->query($sql); - $stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, MyFetchClass::class); - - $results = []; - while ($row = $stmt->fetch()) { - $results[] = $row; - } - - self::assertCount(1, $results); - self::assertInstanceOf(MyFetchClass::class, $results[0]); - - self::assertEquals(1, $results[0]->test_int); - self::assertEquals('foo', $results[0]->test_string); - self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime); - } - /** * @group DBAL-257 */ @@ -898,21 +789,6 @@ public function testEmptyParameters() : void self::assertEquals([], $rows); } - /** - * @group DBAL-1028 - */ - public function testFetchColumnNullValue() : void - { - $this->connection->executeUpdate( - 'INSERT INTO fetch_table (test_int, test_string) VALUES (?, ?)', - [2, 'foo'] - ); - - self::assertNull( - $this->connection->fetchColumn('SELECT test_datetime FROM fetch_table WHERE test_int = ?', [2]) - ); - } - /** * @group DBAL-1028 */ @@ -922,48 +798,4 @@ public function testFetchColumnNoResult() : void $this->connection->fetchColumn('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1]) ); } - - private function setupFixture() : void - { - $this->connection->exec('DELETE FROM fetch_table'); - $this->connection->insert('fetch_table', [ - 'test_int' => 1, - 'test_string' => 'foo', - 'test_datetime' => '2010-01-01 10:10:10', - ]); - } - - private function beforeFetchClassTest() : void - { - $driver = $this->connection->getDriver(); - - if ($driver instanceof Oci8Driver) { - self::markTestSkipped('Not supported by OCI8'); - } - - if ($driver instanceof MySQLiDriver) { - self::markTestSkipped('Mysqli driver dont support this feature.'); - } - - if (! $driver instanceof PDOOracleDriver) { - return; - } - - /** @var PDOConnection $connection */ - $connection = $this->connection - ->getWrappedConnection(); - $connection->getWrappedConnection()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); - } -} - -class MyFetchClass -{ - /** @var int */ - public $test_int; - - /** @var string */ - public $test_string; - - /** @var string */ - public $test_datetime; } diff --git a/tests/Functional/Types/BinaryTest.php b/tests/Functional/Types/BinaryTest.php index 8491dff877e..04225239fe7 100644 --- a/tests/Functional/Types/BinaryTest.php +++ b/tests/Functional/Types/BinaryTest.php @@ -78,7 +78,6 @@ private function select(string $id) $value = $this->connection->fetchColumn( 'SELECT val FROM binary_table WHERE id = ?', [$id], - 0, [ParameterType::BINARY] ); diff --git a/tests/Portability/StatementTest.php b/tests/Portability/StatementTest.php index 087c5d063f6..4213b232814 100644 --- a/tests/Portability/StatementTest.php +++ b/tests/Portability/StatementTest.php @@ -3,13 +3,11 @@ namespace Doctrine\DBAL\Tests\Portability; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Portability\Connection; use Doctrine\DBAL\Portability\Statement; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use ReflectionProperty; use function iterator_to_array; class StatementTest extends TestCase @@ -122,25 +120,6 @@ public function testExecute() : void self::assertTrue($this->stmt->execute($params)); } - public function testSetFetchMode() : void - { - $fetchMode = FetchMode::CUSTOM_OBJECT; - $arg1 = 'MyClass'; - $arg2 = [1, 2]; - - $this->wrappedStmt->expects(self::once()) - ->method('setFetchMode') - ->with($fetchMode, $arg1, $arg2) - ->will(self::returnValue(true)); - - $re = new ReflectionProperty($this->stmt, 'defaultFetchMode'); - $re->setAccessible(true); - - self::assertSame(FetchMode::MIXED, $re->getValue($this->stmt)); - self::assertTrue($this->stmt->setFetchMode($fetchMode, $arg1, $arg2)); - self::assertSame($fetchMode, $re->getValue($this->stmt)); - } - public function testGetIterator() : void { $this->wrappedStmt->expects(self::exactly(3)) diff --git a/tests/StatementTest.php b/tests/StatementTest.php index 9af45c91d15..2c2a1f79b60 100644 --- a/tests/StatementTest.php +++ b/tests/StatementTest.php @@ -8,7 +8,6 @@ use Doctrine\DBAL\Driver; use Doctrine\DBAL\Driver\Connection as DriverConnection; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Logging\SQLLogger; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Statement; @@ -149,15 +148,4 @@ public function testExecuteCallsLoggerStopQueryOnException() : void $statement->execute(); } - - public function testPDOCustomClassConstructorArgs() : void - { - $statement = new Statement('', $this->conn); - - $this->driverStatement->expects(self::once()) - ->method('fetchAll') - ->with(self::equalTo(FetchMode::CUSTOM_OBJECT), self::equalTo('Example'), self::equalTo(['arg1'])); - - $statement->fetchAll(FetchMode::CUSTOM_OBJECT, 'Example', ['arg1']); - } }