diff --git a/src/Cache/ArrayStatement.php b/src/Cache/ArrayStatement.php index 8227c9fc2cf..f3201f390a3 100644 --- a/src/Cache/ArrayStatement.php +++ b/src/Cache/ArrayStatement.php @@ -4,18 +4,14 @@ namespace Doctrine\DBAL\Cache; -use ArrayIterator; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\ResultStatement; -use Doctrine\DBAL\FetchMode; -use InvalidArgumentException; -use IteratorAggregate; -use function array_merge; +use Traversable; use function array_values; use function count; use function reset; -use function sprintf; -final class ArrayStatement implements IteratorAggregate, ResultStatement +final class ArrayStatement implements ResultStatement { /** @var mixed[] */ private $data; @@ -57,69 +53,100 @@ public function rowCount() : int /** * {@inheritdoc} */ - public function getIterator() + public function fetchNumeric() { - $data = $this->fetchAll(); + $row = $this->fetch(); - return new ArrayIterator($data); + if ($row === false) { + return false; + } + + return array_values($row); } /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - if (! isset($this->data[$this->num])) { - return false; - } - - $row = $this->data[$this->num++]; + return $this->fetch(); + } - if ($fetchMode === FetchMode::ASSOCIATIVE) { - return $row; - } + /** + * {@inheritdoc} + */ + public function fetchOne() + { + $row = $this->fetch(); - if ($fetchMode === FetchMode::NUMERIC) { - return array_values($row); + if ($row === false) { + return false; } - if ($fetchMode === FetchMode::MIXED) { - return array_merge($row, array_values($row)); - } + return reset($row); + } - if ($fetchMode === FetchMode::COLUMN) { - return reset($row); - } + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return FetchUtils::fetchAllNumeric($this); + } - throw new InvalidArgumentException( - sprintf('Invalid fetch mode given for fetching result, %d given.', $fetchMode) - ); + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return FetchUtils::fetchAllAssociative($this); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchColumn() : array { - $rows = []; - while ($row = $this->fetch($fetchMode)) { - $rows[] = $row; + return FetchUtils::fetchColumn($this); + } + + /** + * @return Traversable> + */ + public function iterateNumeric() : Traversable + { + foreach ($this->data as $row) { + yield array_values($row); } + } - return $rows; + /** + * @return Traversable> + */ + public function iterateAssociative() : Traversable + { + yield from $this->data; } /** - * {@inheritdoc} + * @return Traversable */ - public function fetchColumn() + public function iterateColumn() : Traversable { - $row = $this->fetch(FetchMode::NUMERIC); + foreach ($this->data as $row) { + yield reset($row); + } + } - if ($row === false) { + /** + * @return mixed|false + */ + private function fetch() + { + if (! isset($this->data[$this->num])) { return false; } - return $row[0]; + return $this->data[$this->num++]; } } diff --git a/src/Cache/ResultCacheStatement.php b/src/Cache/ResultCacheStatement.php index bb36ab3f631..3a9cff262fa 100644 --- a/src/Cache/ResultCacheStatement.php +++ b/src/Cache/ResultCacheStatement.php @@ -4,15 +4,12 @@ namespace Doctrine\DBAL\Cache; -use ArrayIterator; use Doctrine\Common\Cache\Cache; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\ResultStatement; -use Doctrine\DBAL\FetchMode; -use InvalidArgumentException; -use IteratorAggregate; -use function array_merge; +use Traversable; use function array_values; -use function reset; /** * Cache statement for SQL results. @@ -27,7 +24,7 @@ * 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. */ -final class ResultCacheStatement implements IteratorAggregate, ResultStatement +final class ResultCacheStatement implements ResultStatement { /** @var Cache */ private $resultCache; @@ -51,7 +48,7 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement */ private $emptied = false; - /** @var mixed[] */ + /** @var array> */ private $data; public function __construct(ResultStatement $stmt, Cache $resultCache, string $cacheKey, string $realKey, int $lifetime) @@ -90,82 +87,94 @@ public function columnCount() : int /** * {@inheritdoc} */ - public function getIterator() + public function fetchNumeric() { - $data = $this->fetchAll(); + $row = $this->fetch(); - return new ArrayIterator($data); + if ($row === false) { + return false; + } + + return array_values($row); } /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - if ($this->data === null) { - $this->data = []; - } - - $row = $this->statement->fetch(FetchMode::ASSOCIATIVE); - - if ($row !== false) { - $this->data[] = $row; - - if ($fetchMode === FetchMode::ASSOCIATIVE) { - return $row; - } - - if ($fetchMode === FetchMode::NUMERIC) { - return array_values($row); - } - - if ($fetchMode === FetchMode::MIXED) { - return array_merge($row, array_values($row)); - } - - if ($fetchMode === FetchMode::COLUMN) { - return reset($row); - } - - throw new InvalidArgumentException('Invalid fetch-style given for caching result.'); - } - - $this->emptied = true; - - return false; + return $this->fetch(); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $data = $this->statement->fetchAll($fetchMode); - - if ($fetchMode === FetchMode::COLUMN) { - foreach ($data as $key => $value) { - $data[$key] = [$value]; - } - } + return FetchUtils::fetchOne($this); + } - $this->data = $data; - $this->emptied = true; + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return $this->store( + $this->statement->fetchAllAssociative(), + true + ); + } - return $this->data; + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return $this->store( + $this->statement->fetchAllAssociative(), + true + ); } /** * {@inheritdoc} */ - public function fetchColumn() + public function fetchColumn() : array { - $row = $this->fetch(FetchMode::NUMERIC); + return $this->store( + $this->statement->fetchAllAssociative(), + true + ); + } - if ($row === false) { - return false; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } - return $row[0]; + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } /** @@ -183,4 +192,47 @@ public function rowCount() : int { return $this->statement->rowCount(); } + + /** + * @return array|false + * + * @throws DriverException + */ + private function fetch() + { + if ($this->data === null) { + $this->data = []; + } + + $row = $this->statement->fetchAssociative(); + + if ($row !== false) { + $this->data[] = $row; + + return $row; + } + + $this->emptied = true; + + return false; + } + + /** + * @param array> $data + * + * @return array> + */ + private function store(array $data, bool $isArray) : array + { + if (! $isArray) { + foreach ($data as $key => $value) { + $data[$key] = [$value]; + } + } + + $this->data = $data; + $this->emptied = true; + + return $this->data; + } } diff --git a/src/Connection.php b/src/Connection.php index 0aed956b5d1..1dd20dfe6b4 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -31,6 +31,7 @@ use Doctrine\DBAL\Types\Type; use Exception; use Throwable; +use Traversable; use function array_key_exists; use function assert; use function count; @@ -215,7 +216,7 @@ public function getDatabase() : ?string { $platform = $this->getDatabasePlatform(); $query = $platform->getDummySelectSQL($platform->getCurrentDatabaseExpression()); - $database = $this->query($query)->fetchColumn(); + $database = $this->query($query)->fetchOne(); assert(is_string($database) || $database === null); @@ -455,9 +456,13 @@ public function setAutoCommit(bool $autoCommit) : void * * @throws DBALException */ - public function fetchAssoc(string $query, array $params = [], array $types = []) + public function fetchAssociative(string $query, array $params = [], array $types = []) { - return $this->executeQuery($query, $params, $types)->fetch(FetchMode::ASSOCIATIVE); + try { + return $this->executeQuery($query, $params, $types)->fetchAssociative(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } } /** @@ -472,9 +477,13 @@ public function fetchAssoc(string $query, array $params = [], array $types = []) * * @throws DBALException */ - public function fetchArray(string $query, array $params = [], array $types = []) + public function fetchNumeric(string $query, array $params = [], array $types = []) { - return $this->executeQuery($query, $params, $types)->fetch(FetchMode::NUMERIC); + try { + return $this->executeQuery($query, $params, $types)->fetchNumeric(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } } /** @@ -489,9 +498,13 @@ public function fetchArray(string $query, array $params = [], array $types = []) * * @throws DBALException */ - public function fetchColumn(string $query, array $params = [], array $types = []) + public function fetchOne(string $query, array $params = [], array $types = []) { - return $this->executeQuery($query, $params, $types)->fetchColumn(); + try { + return $this->executeQuery($query, $params, $types)->fetchOne(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } } /** @@ -726,17 +739,123 @@ public function quote(string $input) : string } /** - * Prepares and executes an SQL query and returns the result as an associative array. + * Prepares and executes an SQL query and returns the result as an array of numeric arrays. * * @param string $query The SQL query. * @param array|array $params The query parameters. * @param array|array $types The query parameter types. * - * @return array + * @return array> + * + * @throws DBALException */ - public function fetchAll(string $query, array $params = [], array $types = []) : array + public function fetchAllNumeric(string $query, array $params = [], array $types = []) : array { - return $this->executeQuery($query, $params, $types)->fetchAll(); + try { + return $this->executeQuery($query, $params, $types)->fetchAllNumeric(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } + } + + /** + * Prepares and executes an SQL query and returns the result as an array of associative arrays. + * + * @param string $query The SQL query. + * @param array|array $params The query parameters. + * @param array|array $types The query parameter types. + * + * @return array> + * + * @throws DBALException + */ + public function fetchAllAssociative(string $query, array $params = [], array $types = []) : array + { + try { + return $this->executeQuery($query, $params, $types)->fetchAllAssociative(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } + } + + /** + * Prepares and executes an SQL query and returns the result as an array of the first column values. + * + * @param string $query The SQL query. + * @param array|array $params The query parameters. + * @param array|array $types The query parameter types. + * + * @return array + * + * @throws DBALException + */ + public function fetchColumn(string $query, array $params = [], array $types = []) : array + { + try { + return $this->executeQuery($query, $params, $types)->fetchColumn(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } + } + + /** + * Prepares and executes an SQL query and returns the result as an iterator over rows represented as numeric arrays. + * + * @param string $query The SQL query. + * @param array|array $params The query parameters. + * @param array|array $types The query parameter types. + * + * @return Traversable> + * + * @throws DBALException + */ + public function iterateNumeric(string $query, array $params = [], array $types = []) : Traversable + { + try { + return $this->executeQuery($query, $params, $types)->iterateNumeric(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } + } + + /** + * Prepares and executes an SQL query and returns the result as an iterator over rows represented as associative arrays. + * + * @param string $query The SQL query. + * @param array|array $params The query parameters. + * @param array|array $types The query parameter types. + * + * @return Traversable> + * + * @throws DBALException + */ + public function iterateAssociative(string $query, array $params = [], array $types = []) : Traversable + { + try { + return $this->executeQuery($query, $params, $types)->iterateAssociative(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } + } + + /** + * Prepares and executes an SQL query and returns the result as an iterator over the first column values. + * + * @param string $query The SQL query. + * @param array|array $params The query parameters. + * @param array|array $types The query parameter types. + * + * @return Traversable + * + * @throws DBALException + */ + public function iterateColumn(string $query, array $params = [], array $types = []) : Traversable + { + try { + return $this->executeQuery($query, $params, $types)->iterateColumn(); + } catch (Throwable $e) { + throw DBALException::driverExceptionDuringQuery($this->_driver, $e, $query); + } } /** diff --git a/src/Driver/Exception/UnknownFetchMode.php b/src/Driver/Exception/UnknownFetchMode.php deleted file mode 100644 index f95ef4dd177..00000000000 --- a/src/Driver/Exception/UnknownFetchMode.php +++ /dev/null @@ -1,19 +0,0 @@ -fetchNumeric(); + + if ($row === false) { + return false; + } + + return $row[0]; + } + + /** + * @return array> + * + * @throws DriverException + */ + public static function fetchAllNumeric(ResultStatement $stmt) : array + { + $rows = []; + + while (($row = $stmt->fetchNumeric()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * @return array> + * + * @throws DriverException + */ + public static function fetchAllAssociative(ResultStatement $stmt) : array + { + $rows = []; + + while (($row = $stmt->fetchAssociative()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * @return array + * + * @throws DriverException + */ + public static function fetchColumn(ResultStatement $stmt) : array + { + $rows = []; + + while (($row = $stmt->fetchOne()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public static function iterateNumeric(ResultStatement $stmt) : Traversable + { + while (($row = $stmt->fetchNumeric()) !== false) { + yield $row; + } + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public static function iterateAssociative(ResultStatement $stmt) : Traversable + { + while (($row = $stmt->fetchAssociative()) !== false) { + yield $row; + } + } + + /** + * @return Traversable + * + * @throws DriverException + */ + public static function iterateColumn(ResultStatement $stmt) : Traversable + { + while (($row = $stmt->fetchOne()) !== false) { + yield $row; + } + } +} diff --git a/src/Driver/IBMDB2/DB2Statement.php b/src/Driver/IBMDB2/DB2Statement.php index 3e789f54f8e..7846fcc3c5f 100644 --- a/src/Driver/IBMDB2/DB2Statement.php +++ b/src/Driver/IBMDB2/DB2Statement.php @@ -4,17 +4,16 @@ namespace Doctrine\DBAL\Driver\IBMDB2; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\Statement; -use Doctrine\DBAL\Driver\StatementIterator; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use IteratorAggregate; +use Traversable; use function assert; 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_free_result; use function db2_num_fields; use function db2_num_rows; @@ -33,7 +32,7 @@ use const DB2_PARAM_FILE; use const DB2_PARAM_IN; -final class DB2Statement implements IteratorAggregate, Statement +final class DB2Statement implements Statement { /** @var resource */ private $stmt; @@ -169,78 +168,91 @@ public function execute(?array $params = null) : void } /** - * {@inheritdoc} + * {@inheritDoc} */ - public function getIterator() + public function fetchNumeric() { - return new StatementIterator($this); + if (! $this->result) { + return false; + } + + return db2_fetch_array($this->stmt); } /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - // do not try fetching from the statement if it's not expected to contain result + // do not try fetching from the statement if it's not expected to contain the result // in order to prevent exceptional situation if (! $this->result) { return false; } - switch ($fetchMode) { - case FetchMode::COLUMN: - return $this->fetchColumn(); - - case FetchMode::MIXED: - return db2_fetch_both($this->stmt); - - case FetchMode::ASSOCIATIVE: - return db2_fetch_assoc($this->stmt); - - case FetchMode::NUMERIC: - return db2_fetch_array($this->stmt); - - default: - throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.'); - } + return db2_fetch_assoc($this->stmt); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $rows = []; - - switch ($fetchMode) { - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - - break; + return FetchUtils::fetchOne($this); + } - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return FetchUtils::fetchAllNumeric($this); + } - return $rows; + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return FetchUtils::fetchAllAssociative($this); } /** * {@inheritdoc} */ - public function fetchColumn() + public function fetchColumn() : array { - $row = $this->fetch(FetchMode::NUMERIC); + return FetchUtils::fetchColumn($this); + } - if ($row === false) { - return false; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } - return $row[0]; + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } + + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } public function rowCount() : int diff --git a/src/Driver/Mysqli/Exception/UnknownFetchMode.php b/src/Driver/Mysqli/Exception/UnknownFetchMode.php deleted file mode 100644 index 3db453e77fa..00000000000 --- a/src/Driver/Mysqli/Exception/UnknownFetchMode.php +++ /dev/null @@ -1,19 +0,0 @@ -result) { return false; } - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - $values = $this->_fetch(); if ($values === null) { @@ -345,57 +339,86 @@ public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) throw StatementError::new($this->stmt); } - if ($fetchMode === FetchMode::NUMERIC) { - return $values; - } + return $values; + } - $assoc = array_combine($this->columnNames, $values); - assert(is_array($assoc)); + /** + * {@inheritDoc} + */ + public function fetchAssociative() + { + $values = $this->fetchNumeric(); - switch ($fetchMode) { - case FetchMode::ASSOCIATIVE: - return $assoc; + if ($values === false) { + return false; + } - case FetchMode::MIXED: - return $assoc + $values; + $row = array_combine($this->columnNames, $values); + assert(is_array($row)); - default: - throw UnknownFetchMode::new($fetchMode); - } + return $row; } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $rows = []; + return FetchUtils::fetchOne($this); + } - if ($fetchMode === FetchMode::COLUMN) { - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - } else { - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return FetchUtils::fetchAllNumeric($this); + } - return $rows; + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return FetchUtils::fetchAllAssociative($this); } /** * {@inheritdoc} */ - public function fetchColumn() + public function fetchColumn() : array { - $row = $this->fetch(FetchMode::NUMERIC); + return FetchUtils::fetchColumn($this); + } - if ($row === false) { - return false; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } - return $row[0]; + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } public function closeCursor() : void @@ -417,12 +440,4 @@ public function columnCount() : int { return $this->stmt->field_count; } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - return new StatementIterator($this); - } } diff --git a/src/Driver/OCI8/OCI8Connection.php b/src/Driver/OCI8/OCI8Connection.php index a65fe5c416d..13a419f4365 100644 --- a/src/Driver/OCI8/OCI8Connection.php +++ b/src/Driver/OCI8/OCI8Connection.php @@ -118,7 +118,7 @@ public function lastInsertId(?string $name = null) : string $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; $stmt = $this->query($sql); - $result = $stmt->fetchColumn(); + $result = $stmt->fetchOne(); if ($result === false) { throw new OCI8Exception('lastInsertId failed: Query was executed but no result was returned.'); diff --git a/src/Driver/OCI8/OCI8Statement.php b/src/Driver/OCI8/OCI8Statement.php index 36991502ab2..848ebf99972 100644 --- a/src/Driver/OCI8/OCI8Statement.php +++ b/src/Driver/OCI8/OCI8Statement.php @@ -4,12 +4,11 @@ namespace Doctrine\DBAL\Driver\OCI8; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\Statement; -use Doctrine\DBAL\Driver\StatementIterator; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use InvalidArgumentException; -use IteratorAggregate; +use Traversable; use function assert; use function is_int; use function is_resource; @@ -27,7 +26,6 @@ use const OCI_ASSOC; use const OCI_B_BIN; use const OCI_B_BLOB; -use const OCI_BOTH; use const OCI_COMMIT_ON_SUCCESS; use const OCI_D_LOB; use const OCI_FETCHSTATEMENT_BY_COLUMN; @@ -42,7 +40,7 @@ /** * The OCI8 implementation of the Statement interface. */ -final class OCI8Statement implements IteratorAggregate, Statement +final class OCI8Statement implements Statement { /** @var resource */ protected $_dbh; @@ -53,14 +51,6 @@ final class OCI8Statement implements IteratorAggregate, Statement /** @var ExecutionMode */ protected $executionMode; - /** @var int[] */ - protected static $fetchModeMap = [ - FetchMode::MIXED => OCI_BOTH, - FetchMode::ASSOCIATIVE => OCI_ASSOC, - FetchMode::NUMERIC => OCI_NUM, - FetchMode::COLUMN => OCI_NUM, - ]; - /** @var string[] */ protected $_paramMap = []; @@ -220,108 +210,128 @@ public function execute(?array $params = null) : void /** * {@inheritdoc} */ - public function getIterator() + public function fetchNumeric() { - return new StatementIterator($this); + return $this->fetch(OCI_NUM); } /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return false; - } - - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - - if (! isset(self::$fetchModeMap[$fetchMode])) { - throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode)); - } - - return oci_fetch_array( - $this->_sth, - self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS - ); + return $this->fetch(OCI_ASSOC); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $result = []; - - if (! isset(self::$fetchModeMap[$fetchMode])) { - throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode)); - } + return FetchUtils::fetchOne($this); + } - if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) { - while ($row = $this->fetch($fetchMode)) { - $result[] = $row; - } - } else { - $fetchStructure = OCI_FETCHSTATEMENT_BY_ROW; + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_ROW); + } - if ($fetchMode === FetchMode::COLUMN) { - $fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN; - } + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return $this->fetchAll(OCI_ASSOC, OCI_FETCHSTATEMENT_BY_ROW); + } - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if (! $this->result) { - return []; - } + /** + * {@inheritdoc} + */ + public function fetchColumn() : array + { + return $this->fetchAll(OCI_NUM, OCI_FETCHSTATEMENT_BY_COLUMN)[0]; + } - oci_fetch_all( - $this->_sth, - $result, - 0, - -1, - self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS - ); + public function rowCount() : int + { + $count = oci_num_rows($this->_sth); - if ($fetchMode === FetchMode::COLUMN) { - $result = $result[0]; - } + if ($count !== false) { + return $count; } - return $result; + return 0; } /** - * {@inheritdoc} + * @return mixed|false */ - public function fetchColumn() + private function fetch(int $mode) { - // do not try fetching from the statement if it's not expected to contain result + // do not try fetching from the statement if it's not expected to contain the result // in order to prevent exceptional situation if (! $this->result) { return false; } - $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); + return oci_fetch_array( + $this->_sth, + $mode | OCI_RETURN_NULLS | OCI_RETURN_LOBS + ); + } - if ($row === false) { - return false; + /** + * @return array + */ + private function fetchAll(int $mode, int $fetchStructure) : array + { + // do not try fetching from the statement if it's not expected to contain the result + // in order to prevent exceptional situation + if (! $this->result) { + return []; } - return $row[0]; + oci_fetch_all( + $this->_sth, + $result, + 0, + -1, + $mode | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS + ); + + return $result; } - public function rowCount() : int + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable { - $count = oci_num_rows($this->_sth); + return FetchUtils::iterateNumeric($this); + } - if ($count !== false) { - return $count; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } - return 0; + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } } diff --git a/src/Driver/PDOConnection.php b/src/Driver/PDOConnection.php index 023741330b5..fcfc7caf5ee 100644 --- a/src/Driver/PDOConnection.php +++ b/src/Driver/PDOConnection.php @@ -92,8 +92,6 @@ public function lastInsertId(?string $name = null) : string */ protected function createStatement(\PDOStatement $stmt) : PDOStatement { - $stmt->setFetchMode(PDO::FETCH_ASSOC); - return new PDOStatement($stmt); } diff --git a/src/Driver/PDOSqlsrv/Connection.php b/src/Driver/PDOSqlsrv/Connection.php index 77d3a58421b..4f1520732f8 100644 --- a/src/Driver/PDOSqlsrv/Connection.php +++ b/src/Driver/PDOSqlsrv/Connection.php @@ -23,7 +23,7 @@ public function lastInsertId(?string $name = null) : string $stmt = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?'); $stmt->execute([$name]); - return $stmt->fetchColumn(); + return $stmt->fetchOne(); } public function quote(string $input) : string diff --git a/src/Driver/PDOStatement.php b/src/Driver/PDOStatement.php index b9667f41dd6..b14dabf2a5b 100644 --- a/src/Driver/PDOStatement.php +++ b/src/Driver/PDOStatement.php @@ -4,12 +4,10 @@ namespace Doctrine\DBAL\Driver; -use Doctrine\DBAL\Driver\Exception\UnknownFetchMode; use Doctrine\DBAL\Driver\Exception\UnknownParamType; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use IteratorAggregate; use PDO; +use Traversable; use function array_slice; use function assert; use function count; @@ -20,7 +18,7 @@ * The PDO implementation of the Statement interface. * Used by all PDO-based drivers. */ -class PDOStatement implements IteratorAggregate, Statement +class PDOStatement implements Statement { private const PARAM_TYPE_MAP = [ ParameterType::NULL => PDO::PARAM_NULL, @@ -31,13 +29,6 @@ class PDOStatement implements IteratorAggregate, Statement ParameterType::BOOLEAN => PDO::PARAM_BOOL, ]; - private const FETCH_MODE_MAP = [ - FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC, - FetchMode::NUMERIC => PDO::FETCH_NUM, - FetchMode::MIXED => PDO::FETCH_BOTH, - FetchMode::COLUMN => PDO::FETCH_COLUMN, - ]; - /** @var \PDOStatement */ private $stmt; @@ -111,26 +102,104 @@ public function rowCount() : int /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchNumeric() + { + return $this->fetch(PDO::FETCH_NUM); + } + + /** + * {@inheritdoc} + */ + public function fetchAssociative() + { + return $this->fetch(PDO::FETCH_ASSOC); + } + + /** + * {@inheritdoc} + */ + public function fetchOne() + { + return $this->fetch(PDO::FETCH_COLUMN); + } + + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return $this->fetchAll(PDO::FETCH_NUM); + } + + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return $this->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * {@inheritdoc} + */ + public function fetchColumn() : array + { + return $this->fetchAll(PDO::FETCH_COLUMN); + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return $this->iterate(PDO::FETCH_NUM); + } + + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return $this->iterate(PDO::FETCH_ASSOC); + } + + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return $this->iterate(PDO::FETCH_COLUMN); + } + + /** + * @return mixed|false + * + * @throws PDOException + */ + private function fetch(int $mode) { try { - return $this->stmt->fetch( - $this->convertFetchMode($fetchMode) - ); + return $this->stmt->fetch($mode); } catch (\PDOException $exception) { throw new PDOException($exception); } } /** - * {@inheritdoc} + * @return array + * + * @throws PDOException */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + private function fetchAll(int $mode) : array { try { - $data = $this->stmt->fetchAll( - $this->convertFetchMode($fetchMode) - ); + $data = $this->stmt->fetchAll($mode); } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -141,12 +210,16 @@ public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array } /** - * {@inheritdoc} + * @return Traversable + * + * @throws PDOException */ - public function fetchColumn() + private function iterate(int $mode) : Traversable { + $this->stmt->setFetchMode($mode); + try { - return $this->stmt->fetchColumn(); + yield from $this->stmt; } catch (\PDOException $exception) { throw new PDOException($exception); } @@ -165,26 +238,4 @@ private function convertParamType(int $type) : int return self::PARAM_TYPE_MAP[$type]; } - - /** - * Converts DBAL fetch mode to PDO fetch mode - * - * @param int $fetchMode Fetch mode - */ - private function convertFetchMode(int $fetchMode) : int - { - if (! isset(self::FETCH_MODE_MAP[$fetchMode])) { - throw UnknownFetchMode::new($fetchMode); - } - - return self::FETCH_MODE_MAP[$fetchMode]; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - yield from $this->stmt; - } } diff --git a/src/Driver/ResultStatement.php b/src/Driver/ResultStatement.php index eb4ac70871f..a1e48317752 100644 --- a/src/Driver/ResultStatement.php +++ b/src/Driver/ResultStatement.php @@ -4,13 +4,12 @@ namespace Doctrine\DBAL\Driver; -use Doctrine\DBAL\FetchMode; use Traversable; /** * Interface for the reading part of a prepare statement only. */ -interface ResultStatement extends Traversable +interface ResultStatement { /** * Closes the cursor, enabling the statement to be executed again. @@ -38,30 +37,83 @@ public function columnCount() : int; public function rowCount() : int; /** - * Returns the next row of a result set. + * Returns the next row of a result set as a numeric array or FALSE if there are no more rows. * - * @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 array|false * - * @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is - * returned on failure. + * @throws DriverException */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE); + public function fetchNumeric(); /** - * Returns an array containing all of the result set rows. + * Returns the next row of a result set as an associative array or FALSE if there are no more rows. * - * @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 array|false * - * @return mixed[] + * @throws DriverException */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array; + public function fetchAssociative(); /** - * Returns a single column from the next row of a result set or FALSE if there are no more rows. + * Returns the first value of the next row of a result set or FALSE if there are no more rows. * - * @return mixed|false A single column in the next row of a result set, or FALSE if there are no more rows. + * @return mixed|false + * + * @throws DriverException + */ + public function fetchOne(); + + /** + * Returns an array containing all of the result set rows represented as numeric arrays. + * + * @return array> + * + * @throws DriverException + */ + public function fetchAllNumeric() : array; + + /** + * Returns an array containing all of the result set rows represented as associative arrays. + * + * @return array> + * + * @throws DriverException + */ + public function fetchAllAssociative() : array; + + /** + * Returns an array containing the values of the first column of the result set. + * + * @return array + * + * @throws DriverException + */ + public function fetchColumn() : array; + + /** + * Returns an iterator over the result set rows represented as numeric arrays. + * + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable; + + /** + * Returns an iterator over the result set rows represented as associative arrays. + * + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable; + + /** + * Returns an iterator over the values of the first column of the result set. + * + * @return Traversable + * + * @throws DriverException */ - public function fetchColumn(); + public function iterateColumn() : Traversable; } diff --git a/src/Driver/SQLAnywhere/SQLAnywhereConnection.php b/src/Driver/SQLAnywhere/SQLAnywhereConnection.php index e637bc092e0..43b7a5d4a7a 100644 --- a/src/Driver/SQLAnywhere/SQLAnywhereConnection.php +++ b/src/Driver/SQLAnywhere/SQLAnywhereConnection.php @@ -92,7 +92,7 @@ public function exec(string $statement) : int public function getServerVersion() : string { - $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchColumn(); + $version = $this->query("SELECT PROPERTY('ProductVersion')")->fetchOne(); assert(is_string($version)); @@ -105,7 +105,7 @@ public function lastInsertId(?string $name = null) : string return sasql_insert_id($this->connection); } - return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn(); + return $this->query('SELECT ' . $name . '.CURRVAL')->fetchOne(); } public function prepare(string $sql) : DriverStatement diff --git a/src/Driver/SQLAnywhere/SQLAnywhereStatement.php b/src/Driver/SQLAnywhere/SQLAnywhereStatement.php index 11553be7b42..bde4d782c71 100644 --- a/src/Driver/SQLAnywhere/SQLAnywhereStatement.php +++ b/src/Driver/SQLAnywhere/SQLAnywhereStatement.php @@ -4,17 +4,16 @@ namespace Doctrine\DBAL\Driver\SQLAnywhere; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\Statement; -use Doctrine\DBAL\Driver\StatementIterator; use Doctrine\DBAL\Exception\GetVariableType; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use IteratorAggregate; +use Traversable; use function array_key_exists; use function assert; use function is_int; use function is_resource; -use function sasql_fetch_array; use function sasql_fetch_assoc; use function sasql_fetch_row; use function sasql_prepare; @@ -25,12 +24,11 @@ use function sasql_stmt_reset; use function sasql_stmt_result_metadata; use function sprintf; -use const SASQL_BOTH; /** * SAP SQL Anywhere implementation of the Statement interface. */ -final class SQLAnywhereStatement implements IteratorAggregate, Statement +final class SQLAnywhereStatement implements Statement { /** @var resource The connection resource. */ private $conn; @@ -150,78 +148,97 @@ public function execute(?array $params = null) : void } /** - * {@inheritdoc} - * - * @throws SQLAnywhereException + * {@inheritDoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchNumeric() { if (! is_resource($this->result)) { return false; } - switch ($fetchMode) { - case FetchMode::COLUMN: - return $this->fetchColumn(); - - case FetchMode::ASSOCIATIVE: - return sasql_fetch_assoc($this->result); - - case FetchMode::MIXED: - return sasql_fetch_array($this->result, SASQL_BOTH); - - case FetchMode::NUMERIC: - return sasql_fetch_row($this->result); - - default: - throw new SQLAnywhereException(sprintf('Fetch mode is not supported %d.', $fetchMode)); - } + return sasql_fetch_row($this->result); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchAssociative() { - $rows = []; + if (! is_resource($this->result)) { + return false; + } - switch ($fetchMode) { - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } + return sasql_fetch_assoc($this->result); + } - break; + /** + * {@inheritdoc} + * + * @throws DriverException + */ + public function fetchOne() + { + return FetchUtils::fetchOne($this); + } - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } + /** + * @return array> + * + * @throws DriverException + */ + public function fetchAllNumeric() : array + { + return FetchUtils::fetchAllNumeric($this); + } - return $rows; + /** + * @return array> + * + * @throws DriverException + */ + public function fetchAllAssociative() : array + { + return FetchUtils::fetchAllAssociative($this); } /** - * {@inheritdoc} + * @return array + * + * @throws DriverException */ - public function fetchColumn() + public function fetchColumn() : array { - $row = $this->fetch(FetchMode::NUMERIC); + return FetchUtils::fetchColumn($this); + } - if ($row === false) { - return false; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } - return $row[0]; + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); } /** - * {@inheritdoc} + * @return Traversable + * + * @throws DriverException */ - public function getIterator() + public function iterateColumn() : Traversable { - return new StatementIterator($this); + return FetchUtils::iterateColumn($this); } public function rowCount() : int diff --git a/src/Driver/SQLSrv/SQLSrvConnection.php b/src/Driver/SQLSrv/SQLSrvConnection.php index b7e7ed58381..23615707c8e 100644 --- a/src/Driver/SQLSrv/SQLSrvConnection.php +++ b/src/Driver/SQLSrv/SQLSrvConnection.php @@ -100,7 +100,7 @@ public function lastInsertId(?string $name = null) : string $stmt = $this->query('SELECT @@IDENTITY'); } - return $stmt->fetchColumn(); + return $stmt->fetchOne(); } public function beginTransaction() : void diff --git a/src/Driver/SQLSrv/SQLSrvStatement.php b/src/Driver/SQLSrv/SQLSrvStatement.php index 3f5545ce668..bc1b8df0fdf 100644 --- a/src/Driver/SQLSrv/SQLSrvStatement.php +++ b/src/Driver/SQLSrv/SQLSrvStatement.php @@ -4,11 +4,11 @@ namespace Doctrine\DBAL\Driver\SQLSrv; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\Statement; -use Doctrine\DBAL\Driver\StatementIterator; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use IteratorAggregate; +use Traversable; use function assert; use function is_int; use function sqlsrv_execute; @@ -25,14 +25,13 @@ use function stripos; use const SQLSRV_ENC_BINARY; use const SQLSRV_FETCH_ASSOC; -use const SQLSRV_FETCH_BOTH; use const SQLSRV_FETCH_NUMERIC; use const SQLSRV_PARAM_IN; /** * SQL Server Statement. */ -final class SQLSrvStatement implements IteratorAggregate, Statement +final class SQLSrvStatement implements Statement { /** * The SQLSRV Resource. @@ -69,17 +68,6 @@ final class SQLSrvStatement implements IteratorAggregate, Statement */ private $types = []; - /** - * Translations. - * - * @var int[] - */ - private static $fetchMap = [ - FetchMode::MIXED => SQLSRV_FETCH_BOTH, - FetchMode::ASSOCIATIVE => SQLSRV_FETCH_ASSOC, - FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC, - ]; - /** * The last insert ID. * @@ -207,71 +195,79 @@ public function execute(?array $params = null) : void /** * {@inheritdoc} */ - public function getIterator() + public function fetchNumeric() { - return new StatementIterator($this); + return $this->fetch(SQLSRV_FETCH_NUMERIC); } /** * {@inheritdoc} - * - * @throws SQLSrvException */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - // do not try fetching from the statement if it's not expected to contain result - // in order to prevent exceptional situation - if ($this->stmt === null || ! $this->result) { - return false; - } - - if ($fetchMode === FetchMode::COLUMN) { - return $this->fetchColumn(); - } - - if (isset(self::$fetchMap[$fetchMode])) { - return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?? false; - } - - throw new SQLSrvException('Fetch mode is not supported.'); + return $this->fetch(SQLSRV_FETCH_ASSOC); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $rows = []; - - switch ($fetchMode) { - case FetchMode::COLUMN: - while (($row = $this->fetchColumn()) !== false) { - $rows[] = $row; - } - - break; + return FetchUtils::fetchOne($this); + } - default: - while (($row = $this->fetch($fetchMode)) !== false) { - $rows[] = $row; - } - } + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return FetchUtils::fetchAllNumeric($this); + } - return $rows; + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return FetchUtils::fetchAllAssociative($this); } /** * {@inheritdoc} */ - public function fetchColumn() + public function fetchColumn() : array { - $row = $this->fetch(FetchMode::NUMERIC); + return FetchUtils::fetchColumn($this); + } - if ($row === false) { - return false; - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } - return $row[0]; + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } + + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } public function rowCount() : int @@ -333,4 +329,18 @@ private function prepare() return $stmt; } + + /** + * @return mixed|false + */ + private function fetch(int $fetchType) + { + // do not try fetching from the statement if it's not expected to contain the result + // in order to prevent exceptional situation + if ($this->stmt === null || ! $this->result) { + return false; + } + + return sqlsrv_fetch_array($this->stmt, $fetchType) ?? false; + } } diff --git a/src/Driver/StatementIterator.php b/src/Driver/StatementIterator.php deleted file mode 100644 index 8cf5023d81e..00000000000 --- a/src/Driver/StatementIterator.php +++ /dev/null @@ -1,28 +0,0 @@ -statement = $statement; - } - - /** - * {@inheritdoc} - */ - public function getIterator() - { - while (($result = $this->statement->fetch()) !== false) { - yield $result; - } - } -} diff --git a/src/FetchMode.php b/src/FetchMode.php deleted file mode 100644 index 425aa7f38a6..00000000000 --- a/src/FetchMode.php +++ /dev/null @@ -1,54 +0,0 @@ -appendLockHint($this->generatorTableName, LockMode::PESSIMISTIC_WRITE) . ' WHERE sequence_name = ? ' . $platform->getWriteLockSQL(); $stmt = $this->conn->executeQuery($sql, [$sequenceName]); - $row = $stmt->fetch(FetchMode::ASSOCIATIVE); + $row = $stmt->fetchAssociative(); if ($row !== false) { $row = array_change_key_case($row, CASE_LOWER); diff --git a/src/Portability/Statement.php b/src/Portability/Statement.php index 2889eb2ce59..b64b79af614 100644 --- a/src/Portability/Statement.php +++ b/src/Portability/Statement.php @@ -4,12 +4,12 @@ namespace Doctrine\DBAL\Portability; +use Doctrine\DBAL\Driver\DriverException; +use Doctrine\DBAL\Driver\FetchUtils; use Doctrine\DBAL\Driver\ResultStatement; use Doctrine\DBAL\Driver\Statement as DriverStatement; -use Doctrine\DBAL\Driver\StatementIterator; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; -use IteratorAggregate; +use Traversable; use function array_change_key_case; use function assert; use function is_string; @@ -18,7 +18,7 @@ /** * Portability wrapper for a Statement. */ -final class Statement implements IteratorAggregate, DriverStatement +final class Statement implements DriverStatement { /** @var int */ private $portability; @@ -84,77 +84,105 @@ public function execute(?array $params = null) : void /** * {@inheritdoc} */ - public function getIterator() + public function fetchNumeric() { - return new StatementIterator($this); + return $this->fixResult( + $this->stmt->fetchAssociative(), + false + ); } /** * {@inheritdoc} */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAssociative() { - $row = $this->stmt->fetch($fetchMode); - - $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; - $fixCase = $this->case !== null - && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) - && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0; - - $row = $this->fixRow($row, $iterateRow, $fixCase); - - return $row; + return $this->fixResult( + $this->stmt->fetchAssociative(), + true + ); } /** * {@inheritdoc} */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchOne() { - $rows = $this->stmt->fetchAll($fetchMode); - - $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; - $fixCase = $this->case !== null - && ($fetchMode === FetchMode::ASSOCIATIVE || $fetchMode === FetchMode::MIXED) - && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0; - - if (! $iterateRow && ! $fixCase) { - return $rows; - } + $value = $this->stmt->fetchOne(); - if ($fetchMode === FetchMode::COLUMN) { - foreach ($rows as $num => $row) { - $rows[$num] = [$row]; - } + if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') { + $value = null; + } elseif (($this->portability & Connection::PORTABILITY_RTRIM) !== 0 && is_string($value)) { + $value = rtrim($value); } - foreach ($rows as $num => $row) { - $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); - } + return $value; + } - if ($fetchMode === FetchMode::COLUMN) { - foreach ($rows as $num => $row) { - $rows[$num] = $row[0]; - } - } + /** + * {@inheritdoc} + */ + public function fetchAllNumeric() : array + { + return $this->fixResultSet( + $this->stmt->fetchAllNumeric(), + false, + true + ); + } - return $rows; + /** + * {@inheritdoc} + */ + public function fetchAllAssociative() : array + { + return $this->fixResultSet( + $this->stmt->fetchAllAssociative(), + true, + true + ); } /** * {@inheritdoc} */ - public function fetchColumn() + public function fetchColumn() : array { - $value = $this->stmt->fetchColumn(); + return $this->fixResultSet( + $this->stmt->fetchColumn(), + true, + false + ); + } - if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') { - $value = null; - } elseif (($this->portability & Connection::PORTABILITY_RTRIM) !== 0 && is_string($value)) { - $value = rtrim($value); - } + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateNumeric() : Traversable + { + return FetchUtils::iterateNumeric($this); + } - return $value; + /** + * @return Traversable> + * + * @throws DriverException + */ + public function iterateAssociative() : Traversable + { + return FetchUtils::iterateAssociative($this); + } + + /** + * @return Traversable + * + * @throws DriverException + */ + public function iterateColumn() : Traversable + { + return FetchUtils::iterateColumn($this); } public function rowCount() : int @@ -164,6 +192,52 @@ public function rowCount() : int return $this->stmt->rowCount(); } + /** + * @param mixed $result + * + * @return mixed + */ + private function fixResult($result, bool $fixCase) + { + $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; + $fixCase = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0; + + return $this->fixRow($result, $iterateRow, $fixCase); + } + + /** + * @param array $resultSet + * + * @return array + */ + private function fixResultSet(array $resultSet, bool $fixCase, bool $isArray) : array + { + $iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0; + $fixCase = $fixCase && $this->case !== null && ($this->portability & Connection::PORTABILITY_FIX_CASE) !== 0; + + if (! $iterateRow && ! $fixCase) { + return $resultSet; + } + + if (! $isArray) { + foreach ($resultSet as $num => $value) { + $resultSet[$num] = [$value]; + } + } + + foreach ($resultSet as $num => $row) { + $resultSet[$num] = $this->fixRow($row, $iterateRow, $fixCase); + } + + if (! $isArray) { + foreach ($resultSet as $num => $row) { + $resultSet[$num] = $row[0]; + } + } + + return $resultSet; + } + /** * @param mixed $row * diff --git a/src/Schema/AbstractSchemaManager.php b/src/Schema/AbstractSchemaManager.php index bfe5831ddab..ef12d5ff24f 100644 --- a/src/Schema/AbstractSchemaManager.php +++ b/src/Schema/AbstractSchemaManager.php @@ -93,7 +93,7 @@ public function listDatabases() : array { $sql = $this->_platform->getListDatabasesSQL(); - $databases = $this->_conn->fetchAll($sql); + $databases = $this->_conn->fetchAllAssociative($sql); return $this->_getPortableDatabasesList($databases); } @@ -107,7 +107,7 @@ public function listNamespaceNames() : array { $sql = $this->_platform->getListNamespacesSQL(); - $namespaces = $this->_conn->fetchAll($sql); + $namespaces = $this->_conn->fetchAllAssociative($sql); return $this->getPortableNamespacesList($namespaces); } @@ -126,7 +126,7 @@ public function listSequences(?string $database = null) : array $sql = $this->_platform->getListSequencesSQL($database); - $sequences = $this->_conn->fetchAll($sql); + $sequences = $this->_conn->fetchAllAssociative($sql); return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); } @@ -152,7 +152,7 @@ public function listTableColumns(string $table, ?string $database = null) : arra $sql = $this->_platform->getListTableColumnsSQL($table, $database); - $tableColumns = $this->_conn->fetchAll($sql); + $tableColumns = $this->_conn->fetchAllAssociative($sql); return $this->_getPortableTableColumnList($table, $database, $tableColumns); } @@ -168,7 +168,7 @@ public function listTableIndexes(string $table) : array { $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); - $tableIndexes = $this->_conn->fetchAll($sql); + $tableIndexes = $this->_conn->fetchAllAssociative($sql); return $this->_getPortableTableIndexesList($tableIndexes, $table); } @@ -199,7 +199,7 @@ public function listTableNames() : array { $sql = $this->_platform->getListTablesSQL(); - $tables = $this->_conn->fetchAll($sql); + $tables = $this->_conn->fetchAllAssociative($sql); $tableNames = $this->_getPortableTablesList($tables); return $this->filterAssetNames($tableNames); @@ -267,7 +267,7 @@ public function listViews() : array ); $sql = $this->_platform->getListViewsSQL($database); - $views = $this->_conn->fetchAll($sql); + $views = $this->_conn->fetchAllAssociative($sql); return $this->_getPortableViewsList($views); } @@ -284,7 +284,7 @@ public function listTableForeignKeys(string $table, ?string $database = null) : } $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); - $tableForeignKeys = $this->_conn->fetchAll($sql); + $tableForeignKeys = $this->_conn->fetchAllAssociative($sql); return $this->_getPortableTableForeignKeysList($tableForeignKeys); } @@ -553,7 +553,7 @@ protected function _getPortableDatabasesList(array $databases) : array /** * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition. * - * @param array> $namespaces The list of namespace names in the native DBMS data definition. + * @param array> $namespaces The list of namespace names in the native DBMS data definition. * * @return array */ @@ -581,7 +581,7 @@ protected function _getPortableDatabaseDefinition(array $database) : string /** * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition. * - * @param array $namespace The native DBMS namespace definition. + * @param array $namespace The native DBMS namespace definition. */ protected function getPortableNamespaceDefinition(array $namespace) : string { diff --git a/src/Schema/DB2SchemaManager.php b/src/Schema/DB2SchemaManager.php index 7b48c1b2e36..cc4b595d4ad 100644 --- a/src/Schema/DB2SchemaManager.php +++ b/src/Schema/DB2SchemaManager.php @@ -30,7 +30,7 @@ public function listTableNames() : array { $sql = $this->_platform->getListTablesSQL() . ' AND CREATOR = CURRENT_USER'; - $tables = $this->_conn->fetchAll($sql); + $tables = $this->_conn->fetchAllAssociative($sql); return $this->filterAssetNames($this->_getPortableTablesList($tables)); } @@ -198,7 +198,7 @@ public function listTableDetails(string $tableName) : Table assert($platform instanceof DB2Platform); $sql = $platform->getListTableCommentsSQL($tableName); - $tableOptions = $this->_conn->fetchAssoc($sql); + $tableOptions = $this->_conn->fetchAssociative($sql); if ($tableOptions !== false) { $table->addOption('comment', $tableOptions['REMARKS']); diff --git a/src/Schema/MySqlSchemaManager.php b/src/Schema/MySqlSchemaManager.php index ee9a8a007c1..1862e0f6b1f 100644 --- a/src/Schema/MySqlSchemaManager.php +++ b/src/Schema/MySqlSchemaManager.php @@ -311,7 +311,7 @@ public function listTableDetails(string $tableName) : Table assert($platform instanceof MySqlPlatform); $sql = $platform->getListTableMetadataSQL($tableName); - $tableOptions = $this->_conn->fetchAssoc($sql); + $tableOptions = $this->_conn->fetchAssociative($sql); if ($tableOptions === false) { return $table; diff --git a/src/Schema/OracleSchemaManager.php b/src/Schema/OracleSchemaManager.php index 3250ce94c8f..dd36f9e9592 100644 --- a/src/Schema/OracleSchemaManager.php +++ b/src/Schema/OracleSchemaManager.php @@ -344,7 +344,7 @@ private function killUserSessions(string $user) : void AND p.addr(+) = s.paddr SQL; - $activeUserSessions = $this->_conn->fetchAll($sql, [strtoupper($user)]); + $activeUserSessions = $this->_conn->fetchAllAssociative($sql, [strtoupper($user)]); foreach ($activeUserSessions as $activeUserSession) { $activeUserSession = array_change_key_case($activeUserSession, CASE_LOWER); @@ -367,7 +367,7 @@ public function listTableDetails(string $tableName) : Table assert($platform instanceof OraclePlatform); $sql = $platform->getListTableCommentsSQL($tableName); - $tableOptions = $this->_conn->fetchAssoc($sql); + $tableOptions = $this->_conn->fetchAssociative($sql); if ($tableOptions !== false) { $table->addOption('comment', $tableOptions['COMMENTS']); diff --git a/src/Schema/PostgreSqlSchemaManager.php b/src/Schema/PostgreSqlSchemaManager.php index 1d52ee1c9ed..6e68790d4df 100644 --- a/src/Schema/PostgreSqlSchemaManager.php +++ b/src/Schema/PostgreSqlSchemaManager.php @@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\Exception\DriverException; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; @@ -44,7 +43,7 @@ public function getSchemaNames() : array { $statement = $this->_conn->executeQuery("SELECT nspname FROM pg_namespace WHERE nspname !~ '^pg_.*' AND nspname != 'information_schema'"); - return $statement->fetchAll(FetchMode::COLUMN); + return $statement->fetchColumn(); } /** @@ -57,7 +56,7 @@ public function getSchemaNames() : array public function getSchemaSearchPaths() : array { $params = $this->_conn->getParams(); - $schema = explode(',', $this->_conn->fetchColumn('SHOW search_path')); + $schema = explode(',', $this->_conn->fetchOne('SHOW search_path')); if (isset($params['user'])) { $schema = str_replace('"$user"', $params['user'], $schema); @@ -222,7 +221,7 @@ protected function _getPortableTableIndexesList(array $tableIndexRows, string $t ); $stmt = $this->_conn->executeQuery($columnNameSql); - $indexColumns = $stmt->fetchAll(); + $indexColumns = $stmt->fetchAllAssociative(); // required for getting the order of the columns right. foreach ($colNumbers as $colNum) { @@ -300,7 +299,7 @@ protected function _getPortableSequenceDefinition(array $sequence) : Sequence if (! isset($sequence['increment_by'], $sequence['min_value'])) { /** @var string[] $data */ - $data = $this->_conn->fetchAssoc('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName)); + $data = $this->_conn->fetchAssociative('SELECT min_value, increment_by FROM ' . $this->_platform->quoteIdentifier($sequenceName)); $sequence += $data; } @@ -518,7 +517,7 @@ public function listTableDetails(string $tableName) : Table assert($platform instanceof PostgreSQL94Platform); $sql = $platform->getListTableMetadataSQL($tableName); - $tableOptions = $this->_conn->fetchAssoc($sql); + $tableOptions = $this->_conn->fetchAssociative($sql); if ($tableOptions !== false) { $table->addOption('comment', $tableOptions['table_comment']); diff --git a/src/Schema/SQLServerSchemaManager.php b/src/Schema/SQLServerSchemaManager.php index 6751a379b48..4bb439536dd 100644 --- a/src/Schema/SQLServerSchemaManager.php +++ b/src/Schema/SQLServerSchemaManager.php @@ -261,7 +261,7 @@ public function listTableIndexes(string $table) : array $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); try { - $tableIndexes = $this->_conn->fetchAll($sql); + $tableIndexes = $this->_conn->fetchAllAssociative($sql); } catch (PDOException $e) { if ($e->getCode() === 'IMSSP') { return []; @@ -284,7 +284,7 @@ public function alterTable(TableDiff $tableDiff) : void if (count($tableDiff->removedColumns) > 0) { foreach ($tableDiff->removedColumns as $col) { $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); - foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { + foreach ($this->_conn->fetchAllAssociative($columnConstraintSql) as $constraint) { $this->_conn->exec( sprintf( 'ALTER TABLE %s DROP CONSTRAINT %s', @@ -338,7 +338,7 @@ public function listTableDetails(string $tableName) : Table assert($platform instanceof SQLServer2012Platform); $sql = $platform->getListTableMetadataSQL($tableName); - $tableOptions = $this->_conn->fetchAssoc($sql); + $tableOptions = $this->_conn->fetchAssociative($sql); if ($tableOptions !== false) { $table->addOption('comment', $tableOptions['table_comment']); diff --git a/src/Schema/SqliteSchemaManager.php b/src/Schema/SqliteSchemaManager.php index 8a8f62d309c..cb6692081d7 100644 --- a/src/Schema/SqliteSchemaManager.php +++ b/src/Schema/SqliteSchemaManager.php @@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Schema; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Types\StringType; use Doctrine\DBAL\Types\TextType; use Doctrine\DBAL\Types\Type; @@ -121,7 +120,7 @@ public function listTableForeignKeys(string $table, ?string $database = null) : } $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); - $tableForeignKeys = $this->_conn->fetchAll($sql); + $tableForeignKeys = $this->_conn->fetchAllAssociative($sql); if (! empty($tableForeignKeys)) { $createSql = $this->getCreateTableSQL($table); @@ -179,7 +178,7 @@ protected function _getPortableTableIndexesList(array $tableIndexRows, string $t 'PRAGMA TABLE_INFO (%s)', $this->_conn->quote($tableName) )); - $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + $indexArray = $stmt->fetchAllAssociative(); usort($indexArray, static function ($a, $b) { if ($a['pk'] === $b['pk']) { @@ -218,7 +217,7 @@ protected function _getPortableTableIndexesList(array $tableIndexRows, string $t 'PRAGMA INDEX_INFO (%s)', $this->_conn->quote($keyName) )); - $indexArray = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + $indexArray = $stmt->fetchAllAssociative(); foreach ($indexArray as $indexColumnRow) { $idx['column_name'] = $indexColumnRow['name']; @@ -481,7 +480,7 @@ private function parseColumnCommentFromSQL(string $column, string $sql) : string private function getCreateTableSQL(string $table) : string { - $sql = $this->_conn->fetchColumn( + $sql = $this->_conn->fetchOne( <<<'SQL' SELECT sql FROM ( diff --git a/src/Statement.php b/src/Statement.php index e794605ef36..3d768a93f24 100644 --- a/src/Statement.php +++ b/src/Statement.php @@ -8,15 +8,15 @@ use Doctrine\DBAL\Driver\Statement as DriverStatement; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\Type; -use IteratorAggregate; use Throwable; +use Traversable; use function is_string; /** * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support * for logging, DBAL mapping types, etc. */ -class Statement implements IteratorAggregate, DriverStatement +class Statement implements DriverStatement { /** * The SQL statement. @@ -181,37 +181,135 @@ public function columnCount() : int } /** - * Required by interface IteratorAggregate. + * {@inheritdoc} * + * @throws DBALException + */ + public function fetchNumeric() + { + try { + return $this->stmt->fetchNumeric(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } + } + + /** * {@inheritdoc} + * + * @throws DBALException */ - public function getIterator() + public function fetchAssociative() { - return $this->stmt; + try { + return $this->stmt->fetchAssociative(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } + } + + /** + * {@inheritDoc} + * + * @throws DBALException + */ + public function fetchOne() + { + try { + return $this->stmt->fetchOne(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } } /** * {@inheritdoc} + * + * @throws DBALException */ - public function fetch(int $fetchMode = FetchMode::ASSOCIATIVE) + public function fetchAllNumeric() : array { - return $this->stmt->fetch($fetchMode); + try { + return $this->stmt->fetchAllNumeric(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } } /** * {@inheritdoc} + * + * @throws DBALException */ - public function fetchAll(int $fetchMode = FetchMode::ASSOCIATIVE) : array + public function fetchAllAssociative() : array { - return $this->stmt->fetchAll($fetchMode); + try { + return $this->stmt->fetchAllAssociative(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } + } + + /** + * {@inheritdoc} + * + * @throws DBALException + */ + public function fetchColumn() : array + { + try { + return $this->stmt->fetchColumn(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } + } + + /** + * {@inheritDoc} + * + * @return Traversable> + * + * @throws DBALException + */ + public function iterateNumeric() : Traversable + { + try { + yield from $this->stmt->iterateNumeric(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } } /** * {@inheritDoc} + * + * @return Traversable> + * + * @throws DBALException */ - public function fetchColumn() + public function iterateAssociative() : Traversable { - return $this->stmt->fetchColumn(); + try { + yield from $this->stmt->iterateAssociative(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } + } + + /** + * {@inheritDoc} + * + * @return Traversable + * + * @throws DBALException + */ + public function iterateColumn() : Traversable + { + try { + yield from $this->stmt->iterateColumn(); + } catch (DriverException $e) { + throw DBALException::driverException($this->conn->getDriver(), $e); + } } /** diff --git a/src/Tools/Console/Command/RunSqlCommand.php b/src/Tools/Console/Command/RunSqlCommand.php index 4eb86837763..48a7cb74e32 100644 --- a/src/Tools/Console/Command/RunSqlCommand.php +++ b/src/Tools/Console/Command/RunSqlCommand.php @@ -65,7 +65,7 @@ protected function execute(InputInterface $input, OutputInterface $output) assert(is_bool($forceFetch)); if (stripos($sql, 'select') === 0 || $forceFetch) { - $resultSet = $conn->fetchAll($sql); + $resultSet = $conn->fetchAllAssociative($sql); } else { $resultSet = $conn->executeUpdate($sql); } diff --git a/tests/Cache/ArrayStatementTest.php b/tests/Cache/ArrayStatementTest.php index 70d7d73be71..f0d12a295e2 100644 --- a/tests/Cache/ArrayStatementTest.php +++ b/tests/Cache/ArrayStatementTest.php @@ -5,8 +5,6 @@ namespace Doctrine\DBAL\Tests\Cache; use Doctrine\DBAL\Cache\ArrayStatement; -use Doctrine\DBAL\FetchMode; -use InvalidArgumentException; use PHPUnit\Framework\TestCase; use function array_values; use function iterator_to_array; @@ -54,65 +52,43 @@ public function testGetIterator() : void { $statement = $this->createTestArrayStatement(); - self::assertSame($this->users, iterator_to_array($statement->getIterator())); + self::assertSame($this->users, iterator_to_array($statement->iterateAssociative())); } public function testFetchModeAssociative() : void { $statement = $this->createTestArrayStatement(); - self::assertSame($this->users[0], $statement->fetch(FetchMode::ASSOCIATIVE)); + self::assertSame($this->users[0], $statement->fetchAssociative()); } public function testFetchModeNumeric() : void { $statement = $this->createTestArrayStatement(); - self::assertSame(array_values($this->users[0]), $statement->fetch(FetchMode::NUMERIC)); - } - - public function testFetchModeMixed() : void - { - $statement = $this->createTestArrayStatement(); - - self::assertSame([ - 'username' => 'jwage', - 'active' => true, - 0 => 'jwage', - 1 => true, - ], $statement->fetch(FetchMode::MIXED)); + self::assertSame(array_values($this->users[0]), $statement->fetchNumeric()); } public function testFetchModeColumn() : void { $statement = $this->createTestArrayStatement(); - self::assertSame('jwage', $statement->fetch(FetchMode::COLUMN)); - } - - public function testFetchThrowsInvalidArgumentException() : void - { - $statement = $this->createTestArrayStatement(); - - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid fetch mode given for fetching result, 9999 given.'); - - $statement->fetch(9999); + self::assertSame('jwage', $statement->fetchOne()); } - public function testFetchAll() : void + public function testFetchAllAssociative() : void { $statement = $this->createTestArrayStatement(); - self::assertSame($this->users, $statement->fetchAll(FetchMode::ASSOCIATIVE)); + self::assertSame($this->users, $statement->fetchAllAssociative()); } - public function testFetchColumn() : void + public function testFetchOne() : void { $statement = $this->createTestArrayStatement(); - self::assertSame('jwage', $statement->fetchColumn()); - self::assertSame('romanb', $statement->fetchColumn()); + self::assertSame('jwage', $statement->fetchOne()); + self::assertSame('romanb', $statement->fetchOne()); } private function createTestArrayStatement() : ArrayStatement diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index a3f56240c4e..8489bacc49b 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -19,7 +19,6 @@ use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Events; use Doctrine\DBAL\Exception\InvalidArgumentException; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Logging\DebugStack; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; @@ -494,7 +493,7 @@ public function testDeleteWithIsNull() : void ); } - public function testFetchAssoc() : void + public function testFetchAssociative() : void { $statement = 'SELECT * FROM foo WHERE bar = ?'; $params = [666]; @@ -512,8 +511,7 @@ public function testFetchAssoc() : void $driverStatementMock = $this->createMock(Statement::class); $driverStatementMock->expects(self::once()) - ->method('fetch') - ->with(FetchMode::ASSOCIATIVE) + ->method('fetchAssociative') ->will(self::returnValue($result)); $conn = $this->getMockBuilder(Connection::class) @@ -526,10 +524,10 @@ public function testFetchAssoc() : void ->with($statement, $params, $types) ->will(self::returnValue($driverStatementMock)); - self::assertSame($result, $conn->fetchAssoc($statement, $params, $types)); + self::assertSame($result, $conn->fetchAssociative($statement, $params, $types)); } - public function testFetchArray() : void + public function testFetchNumeric() : void { $statement = 'SELECT * FROM foo WHERE bar = ?'; $params = [666]; @@ -547,8 +545,7 @@ public function testFetchArray() : void $driverStatementMock = $this->createMock(Statement::class); $driverStatementMock->expects(self::once()) - ->method('fetch') - ->with(FetchMode::NUMERIC) + ->method('fetchNumeric') ->will(self::returnValue($result)); $conn = $this->getMockBuilder(Connection::class) @@ -561,10 +558,10 @@ public function testFetchArray() : void ->with($statement, $params, $types) ->will(self::returnValue($driverStatementMock)); - self::assertSame($result, $conn->fetchArray($statement, $params, $types)); + self::assertSame($result, $conn->fetchNumeric($statement, $params, $types)); } - public function testFetchColumn() : void + public function testFetchOne() : void { $statement = 'SELECT * FROM foo WHERE bar = ?'; $params = [666]; @@ -582,7 +579,7 @@ public function testFetchColumn() : void $driverStatementMock = $this->createMock(Statement::class); $driverStatementMock->expects(self::once()) - ->method('fetchColumn') + ->method('fetchOne') ->will(self::returnValue($result)); $conn = $this->getMockBuilder(Connection::class) @@ -595,10 +592,10 @@ public function testFetchColumn() : void ->with($statement, $params, $types) ->will(self::returnValue($driverStatementMock)); - self::assertSame($result, $conn->fetchColumn($statement, $params, $types)); + self::assertSame($result, $conn->fetchOne($statement, $params, $types)); } - public function testFetchAll() : void + public function testFetchAllAssociative() : void { $statement = 'SELECT * FROM foo WHERE bar = ?'; $params = [666]; @@ -616,7 +613,7 @@ public function testFetchAll() : void $driverStatementMock = $this->createMock(Statement::class); $driverStatementMock->expects(self::once()) - ->method('fetchAll') + ->method('fetchAllAssociative') ->will(self::returnValue($result)); $conn = $this->getMockBuilder(Connection::class) @@ -629,7 +626,7 @@ public function testFetchAll() : void ->with($statement, $params, $types) ->will(self::returnValue($driverStatementMock)); - self::assertSame($result, $conn->fetchAll($statement, $params, $types)); + self::assertSame($result, $conn->fetchAllAssociative($statement, $params, $types)); } public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void diff --git a/tests/Driver/StatementIteratorTest.php b/tests/Driver/StatementIteratorTest.php deleted file mode 100644 index a968322804c..00000000000 --- a/tests/Driver/StatementIteratorTest.php +++ /dev/null @@ -1,51 +0,0 @@ -createMock(Statement::class); - - $calls = 0; - $this->configureStatement($stmt, $calls); - - $stmtIterator = new StatementIterator($stmt); - - $this->assertIterationCallsFetchOncePerStep($stmtIterator, $calls); - } - - private function configureStatement(MockObject $stmt, int &$calls) : void - { - $values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false, 'impossible']; - $calls = 0; - - $stmt->expects(self::exactly(10)) - ->method('fetch') - ->willReturnCallback(static function () use ($values, &$calls) { - $value = $values[$calls]; - $calls++; - - return $value; - }); - } - - /** - * @param Traversable $iterator - */ - private function assertIterationCallsFetchOncePerStep(Traversable $iterator, int &$calls) : void - { - foreach ($iterator as $i => $_) { - self::assertEquals($i + 1, $calls); - } - } -} diff --git a/tests/Functional/BlobTest.php b/tests/Functional/BlobTest.php index 0d2c3ad1e6b..e8ea0c61ba7 100644 --- a/tests/Functional/BlobTest.php +++ b/tests/Functional/BlobTest.php @@ -6,7 +6,6 @@ use Doctrine\DBAL\Driver\OCI8\Driver as OCI8Driver; use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; @@ -160,7 +159,7 @@ public function testBindParamProcessesStream() : void private function assertBlobContains(string $text) : void { - $rows = $this->connection->query('SELECT blobfield FROM blob_table')->fetchAll(FetchMode::COLUMN); + $rows = $this->connection->query('SELECT blobfield FROM blob_table')->fetchColumn(); self::assertCount(1, $rows); diff --git a/tests/Functional/ConnectionTest.php b/tests/Functional/ConnectionTest.php index 5fa05ae07dd..f37c7f31854 100644 --- a/tests/Functional/ConnectionTest.php +++ b/tests/Functional/ConnectionTest.php @@ -107,7 +107,7 @@ public function testTransactionNestingLevelIsResetOnReconnect() : void $connection->executeQuery('insert into test_nesting values (33)'); $connection->rollBack(); - self::assertEquals(0, $connection->fetchColumn('select count(*) from test_nesting')); + self::assertEquals(0, $connection->fetchOne('select count(*) from test_nesting')); } public function testTransactionNestingBehaviorWithSavepoints() : void diff --git a/tests/Functional/DataAccessTest.php b/tests/Functional/DataAccessTest.php index ffcf662873a..5b83112c0a4 100644 --- a/tests/Functional/DataAccessTest.php +++ b/tests/Functional/DataAccessTest.php @@ -9,7 +9,6 @@ use Doctrine\DBAL\DBALException; use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver; use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\SqlitePlatform; @@ -65,7 +64,8 @@ public function testPrepareWithBindValue() : void $stmt->bindValue(2, 'foo'); $stmt->execute(); - $row = $stmt->fetch(FetchMode::ASSOCIATIVE); + $row = $stmt->fetchAssociative(); + self::assertIsArray($row); $row = array_change_key_case($row, CASE_LOWER); self::assertEquals(['test_int' => 1, 'test_string' => 'foo'], $row); } @@ -83,12 +83,13 @@ public function testPrepareWithBindParam() : void $stmt->bindParam(2, $paramStr); $stmt->execute(); - $row = $stmt->fetch(FetchMode::ASSOCIATIVE); + $row = $stmt->fetchAssociative(); + self::assertIsArray($row); $row = array_change_key_case($row, CASE_LOWER); self::assertEquals(['test_int' => 1, 'test_string' => 'foo'], $row); } - public function testPrepareWithFetchAll() : void + public function testPrepareWithFetchAllAssociative() : void { $paramInt = 1; $paramStr = 'foo'; @@ -101,33 +102,12 @@ public function testPrepareWithFetchAll() : void $stmt->bindParam(2, $paramStr); $stmt->execute(); - $rows = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + $rows = $stmt->fetchAllAssociative(); $rows[0] = array_change_key_case($rows[0], CASE_LOWER); self::assertEquals(['test_int' => 1, 'test_string' => 'foo'], $rows[0]); } - /** - * @group DBAL-228 - */ - public function testPrepareWithFetchAllBoth() : void - { - $paramInt = 1; - $paramStr = 'foo'; - - $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $stmt = $this->connection->prepare($sql); - self::assertInstanceOf(Statement::class, $stmt); - - $stmt->bindParam(1, $paramInt); - $stmt->bindParam(2, $paramStr); - $stmt->execute(); - - $rows = $stmt->fetchAll(FetchMode::MIXED); - $rows[0] = array_change_key_case($rows[0], CASE_LOWER); - self::assertEquals(['test_int' => 1, 'test_string' => 'foo', 0 => 1, 1 => 'foo'], $rows[0]); - } - - public function testPrepareWithFetchColumn() : void + public function testPrepareWithFetchOne() : void { $paramInt = 1; $paramStr = 'foo'; @@ -140,7 +120,7 @@ public function testPrepareWithFetchColumn() : void $stmt->bindParam(2, $paramStr); $stmt->execute(); - $column = $stmt->fetchColumn(); + $column = $stmt->fetchOne(); self::assertEquals(1, $column); } @@ -159,7 +139,7 @@ public function testPrepareWithIterator() : void $rows = []; - foreach ($stmt as $row) { + foreach ($stmt->iterateAssociative() as $row) { $rows[] = array_change_key_case($row, CASE_LOWER); } @@ -191,16 +171,16 @@ public function testPrepareWithExecuteParams() : void self::assertInstanceOf(Statement::class, $stmt); $stmt->execute([$paramInt, $paramStr]); - $row = $stmt->fetch(FetchMode::ASSOCIATIVE); + $row = $stmt->fetchAssociative(); self::assertNotFalse($row); $row = array_change_key_case($row, CASE_LOWER); self::assertEquals(['test_int' => 1, 'test_string' => 'foo'], $row); } - public function testFetchAll() : void + public function testFetchAllAssociative() : void { $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $data = $this->connection->fetchAll($sql, [1, 'foo']); + $data = $this->connection->fetchAllAssociative($sql, [1, 'foo']); self::assertCount(1, $data); @@ -221,7 +201,7 @@ public function testFetchAllWithTypes() : void $datetime = new DateTime($datetimeString); $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; - $data = $this->connection->fetchAll( + $data = $this->connection->fetchAllAssociative( $sql, [1, $datetime], [ParameterType::STRING, Types::DATETIME_MUTABLE] @@ -253,35 +233,20 @@ public function testFetchAllWithMissingTypes() : void $this->expectException(DBALException::class); - $this->connection->fetchAll($sql, [1, $datetime]); - } - - public function testFetchBoth() : void - { - $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $row = $this->connection->executeQuery($sql, [1, 'foo'])->fetch(FetchMode::MIXED); - - self::assertNotFalse($row); - - $row = array_change_key_case($row, CASE_LOWER); - - self::assertEquals(1, $row['test_int']); - self::assertEquals('foo', $row['test_string']); - self::assertEquals(1, $row[0]); - self::assertEquals('foo', $row[1]); + $this->connection->fetchAllAssociative($sql, [1, $datetime]); } public function testFetchNoResult() : void { self::assertFalse( - $this->connection->executeQuery('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1])->fetch() + $this->connection->executeQuery('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1])->fetchAssociative() ); } - public function testFetchAssoc() : void + public function testFetchAssociative() : void { $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $row = $this->connection->fetchAssoc($sql, [1, 'foo']); + $row = $this->connection->fetchAssociative($sql, [1, 'foo']); self::assertNotFalse($row); @@ -297,7 +262,7 @@ public function testFetchAssocWithTypes() : void $datetime = new DateTime($datetimeString); $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; - $row = $this->connection->fetchAssoc( + $row = $this->connection->fetchAssociative( $sql, [1, $datetime], [ParameterType::STRING, Types::DATETIME_MUTABLE] @@ -324,13 +289,13 @@ public function testFetchAssocWithMissingTypes() : void $this->expectException(DBALException::class); - $this->connection->fetchAssoc($sql, [1, $datetime]); + $this->connection->fetchAssociative($sql, [1, $datetime]); } public function testFetchArray() : void { $sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $row = $this->connection->fetchArray($sql, [1, 'foo']); + $row = $this->connection->fetchNumeric($sql, [1, 'foo']); self::assertIsArray($row); self::assertEquals(1, $row[0]); @@ -343,7 +308,7 @@ public function testFetchArrayWithTypes() : void $datetime = new DateTime($datetimeString); $sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; - $row = $this->connection->fetchArray( + $row = $this->connection->fetchNumeric( $sql, [1, $datetime], [ParameterType::STRING, Types::DATETIME_MUTABLE] @@ -370,29 +335,29 @@ public function testFetchArrayWithMissingTypes() : void $this->expectException(DBALException::class); - $this->connection->fetchArray($sql, [1, $datetime]); + $this->connection->fetchNumeric($sql, [1, $datetime]); } - public function testFetchColumn() : void + public function testFetchOne() : void { $sql = 'SELECT test_int FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $testInt = $this->connection->fetchColumn($sql, [1, 'foo']); + $testInt = $this->connection->fetchOne($sql, [1, 'foo']); self::assertEquals(1, $testInt); $sql = 'SELECT test_string FROM fetch_table WHERE test_int = ? AND test_string = ?'; - $testString = $this->connection->fetchColumn($sql, [1, 'foo']); + $testString = $this->connection->fetchOne($sql, [1, 'foo']); self::assertEquals('foo', $testString); } - public function testFetchColumnWithTypes() : void + public function testFetchOneWithTypes() : void { $datetimeString = '2010-01-01 10:10:10'; $datetime = new DateTime($datetimeString); $sql = 'SELECT test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?'; - $column = $this->connection->fetchColumn( + $column = $this->connection->fetchOne( $sql, [1, $datetime], [ParameterType::STRING, Types::DATETIME_MUTABLE] @@ -403,7 +368,7 @@ public function testFetchColumnWithTypes() : void self::assertStringStartsWith($datetimeString, $column); } - public function testFetchColumnWithMissingTypes() : void + public function testFetchOneWithMissingTypes() : void { if ($this->connection->getDriver() instanceof MySQLiDriver || $this->connection->getDriver() instanceof SQLSrvDriver) { @@ -416,7 +381,7 @@ public function testFetchColumnWithMissingTypes() : void $this->expectException(DBALException::class); - $this->connection->fetchColumn($sql, [1, $datetime]); + $this->connection->fetchOne($sql, [1, $datetime]); } /** @@ -431,7 +396,7 @@ public function testExecuteQueryBindDateTimeType() : void [1 => Types::DATETIME_MUTABLE] ); - self::assertEquals(1, $stmt->fetchColumn()); + self::assertEquals(1, $stmt->fetchOne()); } /** @@ -457,7 +422,7 @@ public function testExecuteUpdateBindDateTimeType() : void 'SELECT count(*) AS c FROM fetch_table WHERE test_datetime = ?', [1 => $datetime], [1 => Types::DATETIME_MUTABLE] - )->fetchColumn()); + )->fetchOne()); } /** @@ -470,7 +435,7 @@ public function testPrepareQueryBindValueDateTimeType() : void $stmt->bindValue(1, new DateTime('2010-01-01 10:10:10'), Types::DATETIME_MUTABLE); $stmt->execute(); - self::assertEquals(1, $stmt->fetchColumn()); + self::assertEquals(1, $stmt->fetchOne()); } /** @@ -488,7 +453,7 @@ public function testNativeArrayListSupport() : void [Connection::PARAM_INT_ARRAY] ); - $data = $stmt->fetchAll(FetchMode::NUMERIC); + $data = $stmt->fetchAllNumeric(); self::assertCount(5, $data); self::assertEquals([[100], [101], [102], [103], [104]], $data); @@ -498,7 +463,7 @@ public function testNativeArrayListSupport() : void [Connection::PARAM_STR_ARRAY] ); - $data = $stmt->fetchAll(FetchMode::NUMERIC); + $data = $stmt->fetchAllNumeric(); self::assertCount(5, $data); self::assertEquals([[100], [101], [102], [103], [104]], $data); } @@ -512,7 +477,7 @@ public function testTrimExpression(string $value, int $position, ?string $char, $this->connection->getDatabasePlatform()->getTrimExpression($value, $position, $char) . ' AS trimmed ' . 'FROM fetch_table'; - $row = $this->connection->fetchAssoc($sql); + $row = $this->connection->fetchAssociative($sql); self::assertIsArray($row); $row = array_change_key_case($row, CASE_LOWER); @@ -845,7 +810,7 @@ private function assertDateExpression(callable $buildQuery, callable $bindParams $stmt->execute(); - $date = $stmt->fetchColumn(); + $date = $stmt->fetchOne(); self::assertEquals($expected, date('Y-m-d H:i:s', strtotime($date))); } @@ -903,7 +868,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); + $rowCount = $this->connection->fetchOne($sql); self::assertEquals(1, $rowCount); } @@ -924,7 +889,7 @@ public function testLocateExpression() : void $sql .= $platform->getLocateExpression('test_string', "'oo'", '3') . ' AS locate9 '; $sql .= 'FROM fetch_table'; - $row = $this->connection->fetchAssoc($sql); + $row = $this->connection->fetchAssociative($sql); assert(is_array($row)); $row = array_change_key_case($row, CASE_LOWER); @@ -951,7 +916,7 @@ public function testSubstringExpression(string $string, string $start, ?string $ $platform->getSubstringExpression($string, $start, $length) ); - self::assertEquals($expected, $this->connection->fetchColumn($query)); + self::assertEquals($expected, $this->connection->fetchOne($query)); } /** @@ -984,7 +949,7 @@ public static function substringExpressionProvider() : iterable public function testQuoteSQLInjection() : void { $sql = 'SELECT * FROM fetch_table WHERE test_string = ' . $this->connection->quote("bar' OR '1'='1"); - $rows = $this->connection->fetchAll($sql); + $rows = $this->connection->fetchAllAssociative($sql); self::assertCount(0, $rows, 'no result should be returned, otherwise SQL injection is possible'); } @@ -1016,7 +981,7 @@ public function testBitComparisonExpressionSupport() : void . ' FROM fetch_table'; $stmt = $this->connection->executeQuery($sql); - $data = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + $data = $stmt->fetchAllAssociative(); self::assertCount(4, $data); self::assertEquals(count($bitmap), count($data)); @@ -1050,7 +1015,7 @@ public function testFetchAllStyleColumn() : void $this->connection->insert('fetch_table', ['test_int' => 10, 'test_string' => 'foo']); $sql = 'SELECT test_int FROM fetch_table'; - $rows = $this->connection->query($sql)->fetchAll(FetchMode::COLUMN); + $rows = $this->connection->query($sql)->fetchColumn(); self::assertEquals([1, 10], $rows); } @@ -1058,12 +1023,12 @@ public function testFetchAllStyleColumn() : void /** * @group DBAL-257 */ - public function testEmptyFetchColumnReturnsFalse() : void + public function testEmptyFetchOneReturnsFalse() : void { $this->connection->beginTransaction(); $this->connection->exec('DELETE FROM fetch_table'); - self::assertFalse($this->connection->fetchColumn('SELECT test_int FROM fetch_table')); - self::assertFalse($this->connection->query('SELECT test_int FROM fetch_table')->fetchColumn()); + self::assertFalse($this->connection->fetchOne('SELECT test_int FROM fetch_table')); + self::assertFalse($this->connection->query('SELECT test_int FROM fetch_table')->fetchOne()); $this->connection->rollBack(); } @@ -1074,7 +1039,7 @@ public function testEmptyParameters() : void { $sql = 'SELECT * FROM fetch_table WHERE test_int IN (?)'; $stmt = $this->connection->executeQuery($sql, [[]], [Connection::PARAM_INT_ARRAY]); - $rows = $stmt->fetchAll(); + $rows = $stmt->fetchAllAssociative(); self::assertEquals([], $rows); } @@ -1082,10 +1047,10 @@ public function testEmptyParameters() : void /** * @group DBAL-1028 */ - public function testFetchColumnNoResult() : void + public function testFetchOneNoResult() : void { self::assertFalse( - $this->connection->fetchColumn('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1]) + $this->connection->fetchOne('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1]) ); } } diff --git a/tests/Functional/Driver/OCI8/StatementTest.php b/tests/Functional/Driver/OCI8/StatementTest.php index 0c7c62dddf5..10cda1f33af 100644 --- a/tests/Functional/Driver/OCI8/StatementTest.php +++ b/tests/Functional/Driver/OCI8/StatementTest.php @@ -35,7 +35,7 @@ public function testQueryConversion(string $query, array $params, array $expecte { self::assertEquals( $expected, - $this->connection->executeQuery($query, $params)->fetch() + $this->connection->executeQuery($query, $params)->fetchAssociative() ); } @@ -54,7 +54,7 @@ public function testStatementBindParameters(string $query, array $params, array self::assertEquals( $expected, - $stmt->fetch() + $stmt->fetchAssociative() ); } diff --git a/tests/Functional/Driver/PDOPgSql/DriverTest.php b/tests/Functional/Driver/PDOPgSql/DriverTest.php index df1dd10b234..f32d89774dc 100644 --- a/tests/Functional/Driver/PDOPgSql/DriverTest.php +++ b/tests/Functional/Driver/PDOPgSql/DriverTest.php @@ -87,7 +87,7 @@ public function testConnectsWithApplicationNameParameter() : void $hash = microtime(true); // required to identify the record in the results uniquely $sql = sprintf('SELECT * FROM pg_stat_activity WHERE %d = %d', $hash, $hash); $statement = $connection->query($sql); - $records = $statement->fetchAll(); + $records = $statement->fetchAllAssociative(); foreach ($records as $record) { // The query column is named "current_query" on PostgreSQL < 9.2 diff --git a/tests/Functional/Driver/PDOPgsqlConnectionTest.php b/tests/Functional/Driver/PDOPgsqlConnectionTest.php index 467d43dc193..069735131f0 100644 --- a/tests/Functional/Driver/PDOPgsqlConnectionTest.php +++ b/tests/Functional/Driver/PDOPgsqlConnectionTest.php @@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Tests\Functional\Driver; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Platforms\PostgreSQL94Platform; use Doctrine\DBAL\Tests\FunctionalTestCase; use function extension_loaded; @@ -46,7 +45,7 @@ public function testConnectsWithValidCharsetOption(string $charset) : void self::assertEquals( $charset, $connection->query('SHOW client_encoding') - ->fetch(FetchMode::COLUMN) + ->fetchOne() ); } diff --git a/tests/Functional/Driver/PDOSqlsrv/DriverTest.php b/tests/Functional/Driver/PDOSqlsrv/DriverTest.php index a0900e26f5c..a8149547f07 100644 --- a/tests/Functional/Driver/PDOSqlsrv/DriverTest.php +++ b/tests/Functional/Driver/PDOSqlsrv/DriverTest.php @@ -59,7 +59,7 @@ protected function getConnection(array $driverOptions) : Connection public function testConnectionOptions() : void { $connection = $this->getConnection(['APP' => 'APP_NAME']); - $result = $connection->query('SELECT APP_NAME()')->fetchColumn(); + $result = $connection->query('SELECT APP_NAME()')->fetchOne(); self::assertSame('APP_NAME', $result); } diff --git a/tests/Functional/LikeWildcardsEscapingTest.php b/tests/Functional/LikeWildcardsEscapingTest.php index 9d0103bf54c..e47a36e880a 100644 --- a/tests/Functional/LikeWildcardsEscapingTest.php +++ b/tests/Functional/LikeWildcardsEscapingTest.php @@ -25,6 +25,6 @@ public function testFetchLikeExpressionResult() : void ) ); $stmt->execute(); - self::assertTrue((bool) $stmt->fetchColumn()); + self::assertTrue((bool) $stmt->fetchOne()); } } diff --git a/tests/Functional/MasterSlaveConnectionTest.php b/tests/Functional/MasterSlaveConnectionTest.php index 3ae1a702fed..4cd948832aa 100644 --- a/tests/Functional/MasterSlaveConnectionTest.php +++ b/tests/Functional/MasterSlaveConnectionTest.php @@ -95,7 +95,7 @@ public function testInheritCharsetFromMaster() : void self::assertFalse($conn->isConnectedToMaster()); - $clientCharset = $conn->fetchColumn('select @@character_set_client as c'); + $clientCharset = $conn->fetchOne('select @@character_set_client as c'); self::assertSame( $charset, @@ -120,7 +120,7 @@ public function testNoMasterOnExecuteQuery() : void $conn = $this->createMasterSlaveConnection(); $sql = 'SELECT count(*) as num FROM master_slave_table'; - $data = $conn->fetchAll($sql); + $data = $conn->fetchAllAssociative($sql); $data[0] = array_change_key_case($data[0], CASE_LOWER); self::assertEquals(1, $data[0]['num']); @@ -135,7 +135,7 @@ public function testMasterOnWriteOperation() : void self::assertTrue($conn->isConnectedToMaster()); $sql = 'SELECT count(*) as num FROM master_slave_table'; - $data = $conn->fetchAll($sql); + $data = $conn->fetchAllAssociative($sql); $data[0] = array_change_key_case($data[0], CASE_LOWER); self::assertEquals(2, $data[0]['num']); @@ -208,9 +208,8 @@ public function testQueryOnMaster() : void //Query must be executed only on Master self::assertTrue($conn->isConnectedToMaster()); - $data = $statement->fetchAll(); + $data = $statement->fetchAllAssociative(); - //Default fetchmode is FetchMode::ASSOCIATIVE self::assertArrayHasKey(0, $data); self::assertArrayHasKey('num', $data[0]); @@ -233,9 +232,8 @@ public function testQueryOnSlave() : void //Query must be executed only on Master, even when we connect to the slave self::assertTrue($conn->isConnectedToMaster()); - $data = $statement->fetchAll(); + $data = $statement->fetchAllAssociative(); - //Default fetchmode is FetchMode::ASSOCIATIVE self::assertArrayHasKey(0, $data); self::assertArrayHasKey('num', $data[0]); diff --git a/tests/Functional/ModifyLimitQueryTest.php b/tests/Functional/ModifyLimitQueryTest.php index 667eb6fb51b..c4242f8a827 100644 --- a/tests/Functional/ModifyLimitQueryTest.php +++ b/tests/Functional/ModifyLimitQueryTest.php @@ -171,7 +171,7 @@ private function assertLimitResult(array $expectedResults, string $sql, ?int $li { $p = $this->connection->getDatabasePlatform(); $data = []; - foreach ($this->connection->fetchAll($p->modifyLimitQuery($sql, $limit, $offset)) as $row) { + foreach ($this->connection->fetchAllAssociative($p->modifyLimitQuery($sql, $limit, $offset)) as $row) { $row = array_change_key_case($row, CASE_LOWER); $data[] = $row['test_int']; } diff --git a/tests/Functional/NamedParametersTest.php b/tests/Functional/NamedParametersTest.php index 33e9af6a683..67c6ded15ec 100644 --- a/tests/Functional/NamedParametersTest.php +++ b/tests/Functional/NamedParametersTest.php @@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Tests\Functional; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; @@ -215,7 +214,7 @@ protected function setUp() : void public function testTicket(string $query, array $params, array $types, array $expected) : void { $stmt = $this->connection->executeQuery($query, $params, $types); - $result = $stmt->fetchAll(FetchMode::ASSOCIATIVE); + $result = $stmt->fetchAllAssociative(); foreach ($result as $k => $v) { $result[$k] = array_change_key_case($v, CASE_LOWER); diff --git a/tests/Functional/Platform/ColumnTest.php b/tests/Functional/Platform/ColumnTest.php index 598670137dc..0d33e79a7eb 100644 --- a/tests/Functional/Platform/ColumnTest.php +++ b/tests/Functional/Platform/ColumnTest.php @@ -113,7 +113,7 @@ protected function assertColumn(string $type, array $column, string $value, int self::assertSame(1, $this->connection->insert('column_test', ['val' => $value], [$bindType])); self::assertSame($value, Type::getType($type)->convertToPHPValue( - $this->connection->fetchColumn('SELECT val FROM column_test'), + $this->connection->fetchOne('SELECT val FROM column_test'), $this->connection->getDatabasePlatform() )); } diff --git a/tests/Functional/Platform/DateExpressionTest.php b/tests/Functional/Platform/DateExpressionTest.php index c57f7555f1e..7a6f37a0870 100644 --- a/tests/Functional/Platform/DateExpressionTest.php +++ b/tests/Functional/Platform/DateExpressionTest.php @@ -28,7 +28,7 @@ public function testDifference(string $date1, string $date2, int $expected) : vo $platform = $this->connection->getDatabasePlatform(); $sql = sprintf('SELECT %s FROM date_expr_test', $platform->getDateDiffExpression('date1', 'date2')); - $diff = $this->connection->query($sql)->fetchColumn(); + $diff = $this->connection->query($sql)->fetchOne(); self::assertEquals($expected, $diff); } diff --git a/tests/Functional/Platform/DefaultExpressionTest.php b/tests/Functional/Platform/DefaultExpressionTest.php index dd735898c34..65624b0757d 100644 --- a/tests/Functional/Platform/DefaultExpressionTest.php +++ b/tests/Functional/Platform/DefaultExpressionTest.php @@ -4,7 +4,6 @@ namespace Doctrine\DBAL\Tests\Functional\Platform; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Platforms\OraclePlatform; @@ -71,7 +70,7 @@ private function assertDefaultExpression(string $type, callable $expression) : v [$actualValue, $defaultValue] = $this->connection->query( 'SELECT default_value, actual_value FROM default_expr_test' - )->fetch(FetchMode::NUMERIC); + )->fetchNumeric(); self::assertEquals($actualValue, $defaultValue); } diff --git a/tests/Functional/Platform/QuotingTest.php b/tests/Functional/Platform/QuotingTest.php index 5657315e348..af843c19e2b 100644 --- a/tests/Functional/Platform/QuotingTest.php +++ b/tests/Functional/Platform/QuotingTest.php @@ -18,7 +18,7 @@ public function testQuoteStringLiteral(string $string) : void $platform->quoteStringLiteral($string) ); - self::assertSame($string, $this->connection->fetchColumn($query)); + self::assertSame($string, $this->connection->fetchOne($query)); } /** diff --git a/tests/Functional/PortabilityTest.php b/tests/Functional/PortabilityTest.php index 89aca6edbf7..ccd3888cea7 100644 --- a/tests/Functional/PortabilityTest.php +++ b/tests/Functional/PortabilityTest.php @@ -7,7 +7,6 @@ use Doctrine\DBAL\ColumnCase; use Doctrine\DBAL\Connection; use Doctrine\DBAL\DriverManager; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Portability\Connection as ConnectionPortability; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; @@ -78,47 +77,47 @@ private function getPortableConnection( public function testFullFetchMode() : void { - $rows = $this->portableConnection->fetchAll('SELECT * FROM portability_table'); + $rows = $this->portableConnection->fetchAllAssociative('SELECT * FROM portability_table'); $this->assertFetchResultRows($rows); $stmt = $this->portableConnection->query('SELECT * FROM portability_table'); - foreach ($stmt as $row) { + foreach ($stmt->iterateAssociative() as $row) { $this->assertFetchResultRow($row); } $stmt = $this->portableConnection->query('SELECT * FROM portability_table'); - while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE))) { + while (($row = $stmt->fetchAssociative())) { $this->assertFetchResultRow($row); } $stmt = $this->portableConnection->prepare('SELECT * FROM portability_table'); $stmt->execute(); - while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE))) { + while (($row = $stmt->fetchAssociative())) { $this->assertFetchResultRow($row); } } public function testConnFetchMode() : void { - $rows = $this->portableConnection->fetchAll('SELECT * FROM portability_table'); + $rows = $this->portableConnection->fetchAllAssociative('SELECT * FROM portability_table'); $this->assertFetchResultRows($rows); $stmt = $this->portableConnection->query('SELECT * FROM portability_table'); - foreach ($stmt as $row) { + foreach ($stmt->iterateAssociative() as $row) { $this->assertFetchResultRow($row); } $stmt = $this->portableConnection->query('SELECT * FROM portability_table'); - while (($row = $stmt->fetch())) { + while (($row = $stmt->fetchAssociative())) { $this->assertFetchResultRow($row); } $stmt = $this->portableConnection->prepare('SELECT * FROM portability_table'); $stmt->execute(); - while (($row = $stmt->fetch())) { + while (($row = $stmt->fetchAssociative())) { $this->assertFetchResultRow($row); } } @@ -153,20 +152,20 @@ public function assertFetchResultRow(array $row) : void /** * @param mixed[] $expected * - * @dataProvider fetchAllColumnProvider + * @dataProvider fetchColumnProvider */ - public function testFetchAllColumn(string $field, array $expected) : void + public function testfetchColumn(string $field, array $expected) : void { $stmt = $this->portableConnection->query('SELECT ' . $field . ' FROM portability_table'); - $column = $stmt->fetchAll(FetchMode::COLUMN); + $column = $stmt->fetchColumn(); self::assertEquals($expected, $column); } /** * @return iterable> */ - public static function fetchAllColumnProvider() : iterable + public static function fetchColumnProvider() : iterable { return [ 'int' => [ @@ -184,7 +183,7 @@ public function testFetchAllNullColumn() : void { $stmt = $this->portableConnection->query('SELECT Test_Null FROM portability_table'); - $column = $stmt->fetchAll(FetchMode::COLUMN); + $column = $stmt->fetchColumn(); self::assertSame([null, null], $column); } } diff --git a/tests/Functional/ResultCacheTest.php b/tests/Functional/ResultCacheTest.php index e27bab43d0a..6c242e8339a 100644 --- a/tests/Functional/ResultCacheTest.php +++ b/tests/Functional/ResultCacheTest.php @@ -7,12 +7,10 @@ use Doctrine\Common\Cache\ArrayCache; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Driver\ResultStatement; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Logging\DebugStack; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; use function array_change_key_case; -use function array_merge; use function array_shift; use function array_values; use function is_array; @@ -55,42 +53,44 @@ protected function setUp() : void $config->setResultCacheImpl($cache); } - public function testCacheFetchAssoc() : void + public function testCacheFetchAssociative() : void { $this->assertCacheNonCacheSelectSameFetchModeAreEqual( $this->expectedResult, - FetchMode::ASSOCIATIVE + static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + } ); } - public function testFetchNum() : void + public function testFetchNumeric() : void { $expectedResult = []; foreach ($this->expectedResult as $v) { $expectedResult[] = array_values($v); } - $this->assertCacheNonCacheSelectSameFetchModeAreEqual($expectedResult, FetchMode::NUMERIC); - } - - public function testFetchBoth() : void - { - $expectedResult = []; - foreach ($this->expectedResult as $v) { - $expectedResult[] = array_merge($v, array_values($v)); - } - - $this->assertCacheNonCacheSelectSameFetchModeAreEqual($expectedResult, FetchMode::MIXED); + $this->assertCacheNonCacheSelectSameFetchModeAreEqual( + $expectedResult, + static function (ResultStatement $stmt) { + return $stmt->fetchNumeric(); + } + ); } - public function testFetchColumn() : void + public function testFetchOne() : void { $expectedResult = []; foreach ($this->expectedResult as $v) { $expectedResult[] = array_shift($v); } - $this->assertCacheNonCacheSelectSameFetchModeAreEqual($expectedResult, FetchMode::COLUMN); + $this->assertCacheNonCacheSelectSameFetchModeAreEqual( + $expectedResult, + static function (ResultStatement $stmt) { + return $stmt->fetchOne(); + } + ); } public function testMixingFetch() : void @@ -102,25 +102,25 @@ public function testMixingFetch() : void $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); - $data = $this->hydrateStmt($stmt, FetchMode::ASSOCIATIVE); + $data = $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }); self::assertEquals($this->expectedResult, $data); $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); - $data = $this->hydrateStmt($stmt, FetchMode::NUMERIC); + $data = $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchNumeric(); + }); self::assertEquals($numExpectedResult, $data); } - public function testIteratorFetch() : void - { - self::assertStandardAndIteratorFetchAreEqual(FetchMode::MIXED); - self::assertStandardAndIteratorFetchAreEqual(FetchMode::ASSOCIATIVE); - self::assertStandardAndIteratorFetchAreEqual(FetchMode::NUMERIC); - } - - private function assertStandardAndIteratorFetchAreEqual(int $fetchMode) : void + /** + * @dataProvider fetchModeProvider + */ + public function testIteratorFetch(callable $fetchMode) : void { $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); $data = $this->hydrateStmt($stmt, $fetchMode); @@ -137,7 +137,7 @@ public function testDontCloseNoCache() : void $data = []; - while ($row = $stmt->fetch(FetchMode::ASSOCIATIVE)) { + while (($row = $stmt->fetchAssociative()) !== false) { $data[] = $row; } @@ -145,7 +145,7 @@ public function testDontCloseNoCache() : void $data = []; - while ($row = $stmt->fetch(FetchMode::NUMERIC)) { + while (($row = $stmt->fetchNumeric()) !== false) { $data[] = $row; } @@ -156,12 +156,14 @@ public function testDontFinishNoCache() : void { $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); - $stmt->fetch(FetchMode::ASSOCIATIVE); + $stmt->fetchAssociative(); $stmt->closeCursor(); $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); - $this->hydrateStmt($stmt, FetchMode::NUMERIC); + $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchNumeric(); + }); self::assertCount(2, $this->sqlLogger->queries); } @@ -170,13 +172,13 @@ public function testFetchAllAndFinishSavesCache() : void { $layerCache = new ArrayCache(); $stmt = $this->connection->executeQuery('SELECT * FROM caching WHERE test_int > 500', [], [], new QueryCacheProfile(10, 'testcachekey', $layerCache)); - $stmt->fetchAll(); + $stmt->fetchAllAssociative(); $stmt->closeCursor(); self::assertCount(1, $layerCache->fetch('testcachekey')); } - public function testFetchAllColumn() : void + public function testfetchColumn() : void { $query = $this->connection->getDatabasePlatform() ->getDummySelectSQL('1'); @@ -184,18 +186,18 @@ public function testFetchAllColumn() : void $qcp = new QueryCacheProfile(0, null, new ArrayCache()); $stmt = $this->connection->executeCacheQuery($query, [], [], $qcp); - $stmt->fetchAll(FetchMode::COLUMN); + $stmt->fetchColumn(); $stmt->closeCursor(); $stmt = $this->connection->executeCacheQuery($query, [], [], $qcp); - self::assertEquals([1], $stmt->fetchAll(FetchMode::COLUMN)); + self::assertEquals([1], $stmt->fetchColumn()); } /** * @param array $expectedResult */ - private function assertCacheNonCacheSelectSameFetchModeAreEqual(array $expectedResult, int $fetchMode) : void + private function assertCacheNonCacheSelectSameFetchModeAreEqual(array $expectedResult, callable $fetchMode) : void { $stmt = $this->connection->executeQuery('SELECT * FROM caching ORDER BY test_int ASC', [], [], new QueryCacheProfile(10, 'testcachekey')); @@ -214,10 +216,14 @@ private function assertCacheNonCacheSelectSameFetchModeAreEqual(array $expectedR public function testEmptyResultCache() : void { $stmt = $this->connection->executeQuery('SELECT * FROM caching WHERE test_int > 500', [], [], new QueryCacheProfile(10, 'emptycachekey')); - $this->hydrateStmt($stmt); + $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }); $stmt = $this->connection->executeQuery('SELECT * FROM caching WHERE test_int > 500', [], [], new QueryCacheProfile(10, 'emptycachekey')); - $this->hydrateStmt($stmt); + $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }); self::assertCount(1, $this->sqlLogger->queries, 'just one dbal hit'); } @@ -225,23 +231,45 @@ public function testEmptyResultCache() : void public function testChangeCacheImpl() : void { $stmt = $this->connection->executeQuery('SELECT * FROM caching WHERE test_int > 500', [], [], new QueryCacheProfile(10, 'emptycachekey')); - $this->hydrateStmt($stmt); + $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }); $secondCache = new ArrayCache(); $stmt = $this->connection->executeQuery('SELECT * FROM caching WHERE test_int > 500', [], [], new QueryCacheProfile(10, 'emptycachekey', $secondCache)); - $this->hydrateStmt($stmt); + $this->hydrateStmt($stmt, static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }); self::assertCount(2, $this->sqlLogger->queries, 'two hits'); self::assertCount(1, $secondCache->fetch('emptycachekey')); } + /** + * @return iterable> + */ + public static function fetchModeProvider() : iterable + { + yield 'associative' => [ + static function (ResultStatement $stmt) { + return $stmt->fetchAssociative(); + }, + ]; + + yield 'numeric' => [ + static function (ResultStatement $stmt) { + return $stmt->fetchNumeric(); + }, + ]; + } + /** * @return array */ - private function hydrateStmt(ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE) : array + private function hydrateStmt(ResultStatement $stmt, callable $fetchMode) : array { $data = []; - while ($row = $stmt->fetch($fetchMode)) { + while (($row = $fetchMode($stmt)) !== false) { $data[] = is_array($row) ? array_change_key_case($row, CASE_LOWER) : $row; } @@ -253,11 +281,11 @@ private function hydrateStmt(ResultStatement $stmt, int $fetchMode = FetchMode:: /** * @return array */ - private function hydrateStmtIterator(ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE) : array + private function hydrateStmtIterator(ResultStatement $stmt, callable $fetchMode) : array { $data = []; - while (($row = $stmt->fetch($fetchMode)) !== false) { + while (($row = $fetchMode($stmt)) !== false) { $data[] = is_array($row) ? array_change_key_case($row, CASE_LOWER) : $row; } diff --git a/tests/Functional/Schema/DefaultValueTest.php b/tests/Functional/Schema/DefaultValueTest.php index 064ea14fbb3..fce082a4c08 100644 --- a/tests/Functional/Schema/DefaultValueTest.php +++ b/tests/Functional/Schema/DefaultValueTest.php @@ -60,7 +60,7 @@ public function testEscapedDefaultValueCanBeIntrospected(string $name, ?string $ */ public function testEscapedDefaultValueCanBeInserted(string $name, ?string $expectedDefault) : void { - $value = $this->connection->fetchColumn( + $value = $this->connection->fetchOne( sprintf('SELECT %s FROM default_value', $name) ); diff --git a/tests/Functional/Schema/MySqlSchemaManagerTest.php b/tests/Functional/Schema/MySqlSchemaManagerTest.php index 19a9eebc055..c52c045c63b 100644 --- a/tests/Functional/Schema/MySqlSchemaManagerTest.php +++ b/tests/Functional/Schema/MySqlSchemaManagerTest.php @@ -468,7 +468,7 @@ public function testColumnDefaultsAreValid() : void 'INSERT INTO test_column_defaults_are_valid () VALUES()' ); - $row = $this->connection->fetchAssoc( + $row = $this->connection->fetchAssociative( 'SELECT *, DATEDIFF(CURRENT_TIMESTAMP(), col_datetime) as diff_seconds FROM test_column_defaults_are_valid' ); diff --git a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php index 58cd734ed6a..1f3744d6b30 100644 --- a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php +++ b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php @@ -1236,7 +1236,7 @@ public function testPrimaryKeyAutoIncrement() : void assert($query instanceof Statement); $query->execute(); - $lastUsedIdBeforeDelete = (int) $query->fetchColumn(); + $lastUsedIdBeforeDelete = (int) $query->fetchOne(); $this->connection->query('DELETE FROM test_pk_auto_increment'); @@ -1246,7 +1246,7 @@ public function testPrimaryKeyAutoIncrement() : void assert($query instanceof Statement); $query->execute(); - $lastUsedIdAfterDelete = (int) $query->fetchColumn(); + $lastUsedIdAfterDelete = (int) $query->fetchOne(); self::assertGreaterThan($lastUsedIdBeforeDelete, $lastUsedIdAfterDelete); } diff --git a/tests/Functional/Schema/SqliteSchemaManagerTest.php b/tests/Functional/Schema/SqliteSchemaManagerTest.php index d68a1e99fa0..c272d1d77a2 100644 --- a/tests/Functional/Schema/SqliteSchemaManagerTest.php +++ b/tests/Functional/Schema/SqliteSchemaManagerTest.php @@ -279,7 +279,7 @@ public function testPrimaryKeyNoAutoIncrement() : void assert($query instanceof Statement); $query->execute(); - $lastUsedIdAfterDelete = (int) $query->fetchColumn(); + $lastUsedIdAfterDelete = (int) $query->fetchOne(); // with an empty table, non autoincrement rowid is always 1 self::assertEquals(1, $lastUsedIdAfterDelete); diff --git a/tests/Functional/StatementTest.php b/tests/Functional/StatementTest.php index ceffa2141f9..0c309f8f796 100644 --- a/tests/Functional/StatementTest.php +++ b/tests/Functional/StatementTest.php @@ -11,7 +11,6 @@ use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSRVDriver; use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSRVDriver; use Doctrine\DBAL\Driver\Statement; -use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Tests\FunctionalTestCase; @@ -46,15 +45,15 @@ public function testStatementIsReusableAfterClosingCursor() : void $stmt->execute(); - $id = $stmt->fetchColumn(); + $id = $stmt->fetchOne(); self::assertEquals(1, $id); $stmt->closeCursor(); $stmt->execute(); - $id = $stmt->fetchColumn(); + $id = $stmt->fetchOne(); self::assertEquals(1, $id); - $id = $stmt->fetchColumn(); + $id = $stmt->fetchOne(); self::assertEquals(2, $id); } @@ -80,7 +79,7 @@ public function testReuseStatementWithLongerResults() : void $stmt->execute(); self::assertEquals([ ['param1', 'X'], - ], $stmt->fetchAll(FetchMode::NUMERIC)); + ], $stmt->fetchAllNumeric()); $row2 = [ 'param' => 'param2', @@ -92,7 +91,7 @@ public function testReuseStatementWithLongerResults() : void self::assertEquals([ ['param1', 'X'], ['param2', 'A bit longer value'], - ], $stmt->fetchAll(FetchMode::NUMERIC)); + ], $stmt->fetchAllNumeric()); } public function testFetchLongBlob() : void @@ -136,7 +135,7 @@ public function testFetchLongBlob() : void $stream = Type::getType('blob') ->convertToPHPValue( - $stmt->fetchColumn(), + $stmt->fetchOne(), $this->connection->getDatabasePlatform() ); @@ -150,14 +149,14 @@ public function testIncompletelyFetchedStatementDoesNotBlockConnection() : void $stmt1 = $this->connection->prepare('SELECT id FROM stmt_test'); $stmt1->execute(); - $stmt1->fetch(); + $stmt1->fetchAssociative(); $stmt1->execute(); // fetching only one record out of two - $stmt1->fetch(); + $stmt1->fetchAssociative(); $stmt2 = $this->connection->prepare('SELECT id FROM stmt_test WHERE id = ?'); $stmt2->execute([1]); - self::assertEquals(1, $stmt2->fetchColumn()); + self::assertEquals(1, $stmt2->fetchOne()); } public function testReuseStatementAfterClosingCursor() : void @@ -172,13 +171,13 @@ public function testReuseStatementAfterClosingCursor() : void $stmt = $this->connection->prepare('SELECT id FROM stmt_test WHERE id = ?'); $stmt->execute([1]); - $id = $stmt->fetchColumn(); + $id = $stmt->fetchOne(); self::assertEquals(1, $id); $stmt->closeCursor(); $stmt->execute([2]); - $id = $stmt->fetchColumn(); + $id = $stmt->fetchOne(); self::assertEquals(2, $id); } @@ -192,11 +191,11 @@ public function testReuseStatementWithParameterBoundByReference() : void $id = 1; $stmt->execute(); - self::assertEquals(1, $stmt->fetchColumn()); + self::assertEquals(1, $stmt->fetchOne()); $id = 2; $stmt->execute(); - self::assertEquals(2, $stmt->fetchColumn()); + self::assertEquals(2, $stmt->fetchOne()); } public function testReuseStatementWithReboundValue() : void @@ -208,11 +207,11 @@ public function testReuseStatementWithReboundValue() : void $stmt->bindValue(1, 1); $stmt->execute(); - self::assertEquals(1, $stmt->fetchColumn()); + self::assertEquals(1, $stmt->fetchOne()); $stmt->bindValue(1, 2); $stmt->execute(); - self::assertEquals(2, $stmt->fetchColumn()); + self::assertEquals(2, $stmt->fetchOne()); } public function testReuseStatementWithReboundParam() : void @@ -225,12 +224,12 @@ public function testReuseStatementWithReboundParam() : void $x = 1; $stmt->bindParam(1, $x); $stmt->execute(); - self::assertEquals(1, $stmt->fetchColumn()); + self::assertEquals(1, $stmt->fetchOne()); $y = 2; $stmt->bindParam(1, $y); $stmt->execute(); - self::assertEquals(2, $stmt->fetchColumn()); + self::assertEquals(2, $stmt->fetchOne()); } /** @@ -264,7 +263,7 @@ public function testCloseCursorAfterCursorEnd() : void $stmt = $this->connection->prepare('SELECT name FROM stmt_test'); $stmt->execute(); - $stmt->fetch(); + $stmt->fetchAssociative(); $stmt->closeCursor(); } @@ -315,19 +314,19 @@ public static function emptyFetchProvider() : iterable return [ 'fetch' => [ static function (Statement $stmt) { - return $stmt->fetch(); + return $stmt->fetchAssociative(); }, false, ], 'fetch-column' => [ static function (Statement $stmt) { - return $stmt->fetchColumn(); + return $stmt->fetchOne(); }, false, ], 'fetch-all' => [ static function (Statement $stmt) : array { - return $stmt->fetchAll(); + return $stmt->fetchAllAssociative(); }, [], ], @@ -338,7 +337,7 @@ public function testFetchInColumnMode() : void { $platform = $this->connection->getDatabasePlatform(); $query = $platform->getDummySelectSQL(); - $result = $this->connection->executeQuery($query)->fetch(FetchMode::COLUMN); + $result = $this->connection->executeQuery($query)->fetchOne(); self::assertEquals(1, $result); } diff --git a/tests/Functional/TemporaryTableTest.php b/tests/Functional/TemporaryTableTest.php index b406caedb24..f0cc6327316 100644 --- a/tests/Functional/TemporaryTableTest.php +++ b/tests/Functional/TemporaryTableTest.php @@ -69,7 +69,7 @@ public function testDropTemporaryTableNotAutoCommitTransaction() : void $this->connection->rollBack(); - $rows = $this->connection->fetchAll('SELECT * FROM nontemporary'); + $rows = $this->connection->fetchAllAssociative('SELECT * FROM nontemporary'); self::assertEquals([], $rows, 'In an event of an error this result has one row, because of an implicit commit.'); } @@ -116,7 +116,7 @@ public function testCreateTemporaryTableNotAutoCommitTransaction() : void } catch (Throwable $e) { } - $rows = $this->connection->fetchAll('SELECT * FROM nontemporary'); + $rows = $this->connection->fetchAllAssociative('SELECT * FROM nontemporary'); self::assertEquals([], $rows, 'In an event of an error this result has one row, because of an implicit commit.'); } } diff --git a/tests/Functional/Ticket/DBAL202Test.php b/tests/Functional/Ticket/DBAL202Test.php index 577f58239e1..ff96646d9c7 100644 --- a/tests/Functional/Ticket/DBAL202Test.php +++ b/tests/Functional/Ticket/DBAL202Test.php @@ -38,7 +38,7 @@ public function testStatementRollback() : void $stmt->execute(); $this->connection->rollBack(); - self::assertEquals(0, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchColumn()); + self::assertEquals(0, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchOne()); } public function testStatementCommit() : void @@ -48,6 +48,6 @@ public function testStatementCommit() : void $stmt->execute(); $this->connection->commit(); - self::assertEquals(1, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchColumn()); + self::assertEquals(1, $this->connection->query('SELECT COUNT(1) FROM DBAL202')->fetchOne()); } } diff --git a/tests/Functional/Ticket/DBAL630Test.php b/tests/Functional/Ticket/DBAL630Test.php index efc731aff92..b585a3e3252 100644 --- a/tests/Functional/Ticket/DBAL630Test.php +++ b/tests/Functional/Ticket/DBAL630Test.php @@ -54,7 +54,7 @@ public function testBooleanConversionSqlLiteral() : void $id = $this->connection->lastInsertId('dbal630_id_seq'); self::assertNotEmpty($id); - $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); + $row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); self::assertIsArray($row); self::assertFalse($row['bool_col']); @@ -70,7 +70,7 @@ public function testBooleanConversionBoolParamRealPrepares() : void $id = $this->connection->lastInsertId('dbal630_id_seq'); self::assertNotEmpty($id); - $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); + $row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); self::assertIsArray($row); self::assertFalse($row['bool_col']); @@ -91,7 +91,7 @@ public function testBooleanConversionBoolParamEmulatedPrepares() : void self::assertNotEmpty($id); - $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); + $row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630 WHERE id = ?', [$id]); self::assertIsArray($row); self::assertFalse($row['bool_col']); @@ -117,7 +117,7 @@ public function testBooleanConversionNullParamEmulatedPrepares( self::assertNotEmpty($id); - $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]); + $row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]); self::assertIsArray($row); self::assertSame($databaseConvertedValue, $row['bool_col']); @@ -147,7 +147,7 @@ public function testBooleanConversionNullParamEmulatedPreparesWithBooleanTypeInB self::assertNotEmpty($id); - $row = $this->connection->fetchAssoc('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]); + $row = $this->connection->fetchAssociative('SELECT bool_col FROM dbal630_allow_nulls WHERE id = ?', [$id]); self::assertIsArray($row); self::assertSame($databaseConvertedValue, $row['bool_col']); diff --git a/tests/Functional/TypeConversionTest.php b/tests/Functional/TypeConversionTest.php index 414aaaa5c79..ddb40b84a08 100644 --- a/tests/Functional/TypeConversionTest.php +++ b/tests/Functional/TypeConversionTest.php @@ -249,7 +249,7 @@ private function processValue(string $type, $originalValue) $sql = 'SELECT ' . $columnName . ' FROM type_conversion WHERE id = ' . self::$typeCounter; return $typeInstance->convertToPHPValue( - $this->connection->fetchColumn($sql), + $this->connection->fetchOne($sql), $this->connection->getDatabasePlatform() ); } diff --git a/tests/Functional/Types/BinaryTest.php b/tests/Functional/Types/BinaryTest.php index b251b4b2899..82f8e72c804 100644 --- a/tests/Functional/Types/BinaryTest.php +++ b/tests/Functional/Types/BinaryTest.php @@ -74,7 +74,7 @@ private function insert(string $id, string $value) : void */ private function select(string $id) { - $value = $this->connection->fetchColumn( + $value = $this->connection->fetchOne( 'SELECT val FROM binary_table WHERE id = ?', [$id], [ParameterType::BINARY] diff --git a/tests/Functional/WriteTest.php b/tests/Functional/WriteTest.php index 265fba23962..bfe36085f87 100644 --- a/tests/Functional/WriteTest.php +++ b/tests/Functional/WriteTest.php @@ -118,10 +118,10 @@ public function testDelete() : void $this->insertRows(); self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 2])); - self::assertCount(1, $this->connection->fetchAll('SELECT * FROM write_table')); + self::assertCount(1, $this->connection->fetchAllAssociative('SELECT * FROM write_table')); self::assertEquals(1, $this->connection->delete('write_table', ['test_int' => 1])); - self::assertCount(0, $this->connection->fetchAll('SELECT * FROM write_table')); + self::assertCount(0, $this->connection->fetchAllAssociative('SELECT * FROM write_table')); } public function testUpdate() : void @@ -163,7 +163,7 @@ public function testLastInsertIdSequence() : void })); $stmt = $this->connection->query($this->connection->getDatabasePlatform()->getSequenceNextValSQL('write_table_id_seq')); - $nextSequenceVal = $stmt->fetchColumn(); + $nextSequenceVal = $stmt->fetchOne(); $lastInsertId = $this->lastInsertId('write_table_id_seq'); @@ -194,7 +194,7 @@ public function testInsertWithKeyValueTypes() : void ['test_string' => 'datetime', 'test_int' => 'integer'] ); - $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30'); self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data); } @@ -221,7 +221,7 @@ public function testUpdateWithKeyValueTypes() : void ['test_string' => 'datetime', 'test_int' => 'integer'] ); - $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30'); self::assertEquals($testString->format($this->connection->getDatabasePlatform()->getDateTimeFormatString()), $data); } @@ -240,7 +240,7 @@ public function testDeleteWithKeyValueTypes() : void $this->connection->delete('write_table', ['test_int' => 30, 'test_string' => $val], ['test_string' => 'datetime', 'test_int' => 'integer']); - $data = $this->connection->fetchColumn('SELECT test_string FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchOne('SELECT test_string FROM write_table WHERE test_int = 30'); self::assertFalse($data); } @@ -296,13 +296,13 @@ public function testUpdateWhereIsNull() : void ['test_string' => 'string', 'test_int' => 'integer'] ); - $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30'); self::assertCount(1, $data); $this->connection->update('write_table', ['test_int' => 10], ['test_string' => null], ['test_string' => 'string', 'test_int' => 'integer']); - $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30'); self::assertCount(0, $data); } @@ -315,13 +315,13 @@ public function testDeleteWhereIsNull() : void ['test_string' => 'string', 'test_int' => 'integer'] ); - $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30'); self::assertCount(1, $data); $this->connection->delete('write_table', ['test_string' => null], ['test_string' => 'string']); - $data = $this->connection->fetchAll('SELECT * FROM write_table WHERE test_int = 30'); + $data = $this->connection->fetchAllAssociative('SELECT * FROM write_table WHERE test_int = 30'); self::assertCount(0, $data); } diff --git a/tests/Portability/StatementTest.php b/tests/Portability/StatementTest.php index 3d12339d3e5..acb34fa3cb4 100644 --- a/tests/Portability/StatementTest.php +++ b/tests/Portability/StatementTest.php @@ -10,7 +10,6 @@ use Doctrine\DBAL\Portability\Statement; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; -use function iterator_to_array; class StatementTest extends TestCase { @@ -93,15 +92,6 @@ public function testExecute() : void $this->stmt->execute($params); } - public function testGetIterator() : void - { - $this->wrappedStmt->expects(self::exactly(3)) - ->method('fetch') - ->willReturnOnConsecutiveCalls('foo', 'bar', false); - - self::assertSame(['foo', 'bar'], iterator_to_array($this->stmt->getIterator())); - } - public function testRowCount() : void { $rowCount = 666; diff --git a/tests/Schema/DB2SchemaManagerTest.php b/tests/Schema/DB2SchemaManagerTest.php index 2a50a49a21a..3a782d583dc 100644 --- a/tests/Schema/DB2SchemaManagerTest.php +++ b/tests/Schema/DB2SchemaManagerTest.php @@ -33,7 +33,7 @@ protected function setUp() : void $platform = $this->createMock(DB2Platform::class); $this->conn = $this ->getMockBuilder(Connection::class) - ->onlyMethods(['fetchAll']) + ->onlyMethods(['fetchAllAssociative']) ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) ->getMock(); @@ -50,7 +50,7 @@ public function testListTableNamesFiltersAssetNamesCorrectly() : void $this->conn->getConfiguration()->setSchemaAssetsFilter(static function (string $name) : bool { return preg_match('/^(?!T_)/', $name) === 1; }); - $this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue([ + $this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue([ ['name' => 'FOO'], ['name' => 'T_FOO'], ['name' => 'BAR'], @@ -73,7 +73,7 @@ public function testListTableNamesFiltersAssetNamesCorrectlyWithCallable() : voi return in_array($assetName, $accepted, true); }); - $this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue([ + $this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue([ ['name' => 'FOO'], ['name' => 'T_FOO'], ['name' => 'BAR'], diff --git a/tests/Schema/MySqlSchemaManagerTest.php b/tests/Schema/MySqlSchemaManagerTest.php index 632c49b707e..962997816c1 100644 --- a/tests/Schema/MySqlSchemaManagerTest.php +++ b/tests/Schema/MySqlSchemaManagerTest.php @@ -29,7 +29,7 @@ protected function setUp() : void $driverMock = $this->createMock(Driver::class); $platform = $this->createMock(MySqlPlatform::class); $this->conn = $this->getMockBuilder(Connection::class) - ->onlyMethods(['fetchAll']) + ->onlyMethods(['fetchAllAssociative']) ->setConstructorArgs([['platform' => $platform], $driverMock, new Configuration(), $eventManager]) ->getMock(); $this->manager = new MySqlSchemaManager($this->conn); @@ -37,7 +37,7 @@ protected function setUp() : void public function testCompositeForeignKeys() : void { - $this->conn->expects(self::once())->method('fetchAll')->will(self::returnValue($this->getFKDefinition())); + $this->conn->expects(self::once())->method('fetchAllAssociative')->will(self::returnValue($this->getFKDefinition())); $fkeys = $this->manager->listTableForeignKeys('dummy'); self::assertCount(1, $fkeys, 'Table has to have one foreign key.'); diff --git a/tests/Tools/Console/RunSqlCommandTest.php b/tests/Tools/Console/RunSqlCommandTest.php index 39a87f8467c..aec2e5d1a35 100644 --- a/tests/Tools/Console/RunSqlCommandTest.php +++ b/tests/Tools/Console/RunSqlCommandTest.php @@ -33,7 +33,7 @@ protected function setUp() : void $this->commandTester = new CommandTester($this->command); $this->connectionMock = $this->createMock(Connection::class); - $this->connectionMock->method('fetchAll') + $this->connectionMock->method('fetchAllAssociative') ->willReturn([[1]]); $this->connectionMock->method('executeUpdate') ->willReturn(42); @@ -67,7 +67,7 @@ public function testIncorrectDepthOption() : void public function testSelectStatementsPrintsResult() : void { - $this->expectConnectionFetchAll(); + $this->expectConnectionFetchAllAssociative(); $exitCode = $this->commandTester->execute([ 'command' => $this->command->getName(), @@ -99,22 +99,22 @@ private function expectConnectionExecuteUpdate() : void ->method('executeUpdate'); $this->connectionMock ->expects(self::exactly(0)) - ->method('fetchAll'); + ->method('fetchAllAssociative'); } - private function expectConnectionFetchAll() : void + private function expectConnectionFetchAllAssociative() : void { $this->connectionMock ->expects(self::exactly(0)) ->method('executeUpdate'); $this->connectionMock ->expects(self::exactly(1)) - ->method('fetchAll'); + ->method('fetchAllAssociative'); } public function testStatementsWithFetchResultPrintsResult() : void { - $this->expectConnectionFetchAll(); + $this->expectConnectionFetchAllAssociative(); $this->commandTester->execute([ 'command' => $this->command->getName(),