From 4297f5027011027529fdccfa3b1fbbb3090a7d25 Mon Sep 17 00:00:00 2001 From: Martin Dumoulin Date: Fri, 5 Mar 2021 12:43:51 +0100 Subject: [PATCH] Improve forward compatibility between 2.x and 3.0 Make Doctrine\DBAL\Connection executeQuery() & executeCachedQuery() return a result implementing the following v3.0 features : - fetchNumeric() - fetchAssociative() - fetchOne() - fetchAllNumeric() - fetchAllAssociative() - fetchAllKeyValue() - fetchAllAssociativeIndexed() - fetchFirstColumn() - iterateNumeric() - iterateAssociative() - iterateKeyValue() - iterateAssociativeIndexed() - iterateColumn() - rowCount() - columnCount() - free() --- lib/Doctrine/DBAL/Connection.php | 118 +++--- .../DBAL/ForwardCompatibility/Result.php | 274 ++++++++++++++ lib/Doctrine/DBAL/Portability/Connection.php | 3 +- lib/Doctrine/DBAL/Result.php | 52 +++ tests/Doctrine/Tests/DBAL/ConnectionTest.php | 10 +- .../DBAL/ForwardCompatibility/ResultTest.php | 349 ++++++++++++++++++ .../BackwardCompatibility/Connection.php | 5 +- .../Tests/DBAL/Functional/ResultCacheTest.php | 15 +- 8 files changed, 746 insertions(+), 80 deletions(-) create mode 100644 lib/Doctrine/DBAL/ForwardCompatibility/Result.php create mode 100644 lib/Doctrine/DBAL/Result.php create mode 100644 tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index c41e5ba90dc..a7136044a7d 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -4,7 +4,6 @@ use Closure; use Doctrine\Common\EventManager; -use Doctrine\DBAL\Abstraction\Result; use Doctrine\DBAL\Cache\ArrayStatement; use Doctrine\DBAL\Cache\CacheException; use Doctrine\DBAL\Cache\QueryCacheProfile; @@ -19,6 +18,7 @@ use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; +use Doctrine\DBAL\Result as BaseResult; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Doctrine\DBAL\Types\Type; use Throwable; @@ -616,13 +616,11 @@ public function fetchColumn($sql, array $params = [], $column = 0, array $types public function fetchAssociative(string $query, array $params = [], array $types = []) { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchAssociative(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetch(FetchMode::ASSOCIATIVE); + return $stmt->fetchAssociative(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -643,13 +641,11 @@ public function fetchAssociative(string $query, array $params = [], array $types public function fetchNumeric(string $query, array $params = [], array $types = []) { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchNumeric(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetch(FetchMode::NUMERIC); + return $stmt->fetchNumeric(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -670,13 +666,11 @@ public function fetchNumeric(string $query, array $params = [], array $types = [ public function fetchOne(string $query, array $params = [], array $types = []) { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchOne(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetch(FetchMode::COLUMN); + return $stmt->fetchOne(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -956,13 +950,11 @@ public function fetchAll($sql, array $params = [], $types = []) public function fetchAllNumeric(string $query, array $params = [], array $types = []): array { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchAllNumeric(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetchAll(FetchMode::NUMERIC); + return $stmt->fetchAllNumeric(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -982,13 +974,11 @@ public function fetchAllNumeric(string $query, array $params = [], array $types public function fetchAllAssociative(string $query, array $params = [], array $types = []): array { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchAllAssociative(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetchAll(FetchMode::ASSOCIATIVE); + return $stmt->fetchAllAssociative(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -1061,13 +1051,11 @@ public function fetchAllAssociativeIndexed(string $query, array $params = [], ar public function fetchFirstColumn(string $query, array $params = [], array $types = []): array { try { - $stmt = $this->executeQuery($query, $params, $types); - - if ($stmt instanceof Result) { - return $stmt->fetchFirstColumn(); - } + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - return $stmt->fetchAll(FetchMode::COLUMN); + return $stmt->fetchFirstColumn(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -1087,15 +1075,11 @@ public function fetchFirstColumn(string $query, array $params = [], array $types public function iterateNumeric(string $query, array $params = [], array $types = []): Traversable { try { - $stmt = $this->executeQuery($query, $params, $types); + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - if ($stmt instanceof Result) { - yield from $stmt->iterateNumeric(); - } else { - while (($row = $stmt->fetch(FetchMode::NUMERIC)) !== false) { - yield $row; - } - } + yield from $stmt->iterateNumeric(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -1116,15 +1100,11 @@ public function iterateNumeric(string $query, array $params = [], array $types = public function iterateAssociative(string $query, array $params = [], array $types = []): Traversable { try { - $stmt = $this->executeQuery($query, $params, $types); + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - if ($stmt instanceof Result) { - yield from $stmt->iterateAssociative(); - } else { - while (($row = $stmt->fetch(FetchMode::ASSOCIATIVE)) !== false) { - yield $row; - } - } + yield from $stmt->iterateAssociative(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -1189,15 +1169,11 @@ public function iterateAssociativeIndexed(string $query, array $params = [], arr public function iterateColumn(string $query, array $params = [], array $types = []): Traversable { try { - $stmt = $this->executeQuery($query, $params, $types); + $stmt = $this->ensureForwardCompatibilityStatement( + $this->executeQuery($query, $params, $types) + ); - if ($stmt instanceof Result) { - yield from $stmt->iterateColumn(); - } else { - while (($value = $stmt->fetch(FetchMode::COLUMN)) !== false) { - yield $value; - } - } + yield from $stmt->iterateColumn(); } catch (Throwable $e) { $this->handleExceptionDuringQuery($e, $query, $params, $types); } @@ -1235,7 +1211,7 @@ public function prepare($sql) * @param array|array $params Query parameters * @param array|array $types Parameter types * - * @return ResultStatement The executed statement. + * @return ResultStatement&BaseResult The executed statement. * * @throws Exception */ @@ -1281,7 +1257,7 @@ public function executeQuery($sql, array $params = [], $types = [], ?QueryCacheP $logger->stopQuery(); } - return $stmt; + return $this->ensureForwardCompatibilityStatement($stmt); } /** @@ -1291,7 +1267,7 @@ public function executeQuery($sql, array $params = [], $types = [], ?QueryCacheP * @param array|array $params Query parameters * @param array|array $types Parameter types * - * @return ResultStatement + * @return ResultStatement&BaseResult * * @throws CacheException */ @@ -1332,7 +1308,19 @@ public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp) $stmt->setFetchMode($this->defaultFetchMode); - return $stmt; + return $this->ensureForwardCompatibilityStatement($stmt); + } + + /** + * @return ResultStatement&BaseResult + */ + private function ensureForwardCompatibilityStatement(ResultStatement $stmt) + { + if ($stmt instanceof BaseResult) { + return $stmt; + } + + return new ForwardCompatibility\Result($stmt); } /** diff --git a/lib/Doctrine/DBAL/ForwardCompatibility/Result.php b/lib/Doctrine/DBAL/ForwardCompatibility/Result.php new file mode 100644 index 00000000000..c03cd3ac570 --- /dev/null +++ b/lib/Doctrine/DBAL/ForwardCompatibility/Result.php @@ -0,0 +1,274 @@ +stmt = $stmt; + } + + /** + * @return DriverResultStatement + */ + public function getIterator() + { + return $this->stmt; + } + + /** + * {@inheritDoc} + */ + public function closeCursor() + { + return $this->stmt->closeCursor(); + } + + /** + * {@inheritDoc} + */ + public function columnCount() + { + return $this->stmt->columnCount(); + } + + /** + * {@inheritDoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); + } + + /** + * {@inheritDoc} + */ + public function fetch($fetchMode = null, $cursorOrientation = PDO::FETCH_ORI_NEXT, $cursorOffset = 0) + { + return $this->stmt->fetch($fetchMode, $cursorOrientation, $cursorOffset); + } + + /** + * {@inheritDoc} + */ + public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null) + { + return $this->stmt->fetchAll($fetchMode, $fetchArgument, $ctorArgs); + } + + /** + * {@inheritDoc} + */ + public function fetchColumn($columnIndex = 0) + { + return $this->stmt->fetchColumn($columnIndex); + } + + /** + * {@inheritDoc} + */ + public function fetchNumeric() + { + return $this->stmt->fetch(PDO::FETCH_NUM); + } + + /** + * {@inheritDoc} + */ + public function fetchAssociative() + { + return $this->stmt->fetch(PDO::FETCH_ASSOC); + } + + /** + * {@inheritDoc} + */ + public function fetchOne() + { + $row = $this->fetchNumeric(); + + if ($row === false) { + return false; + } + + return $row[0]; + } + + /** + * {@inheritDoc} + */ + public function fetchAllNumeric(): array + { + $rows = []; + + while (($row = $this->fetchNumeric()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * {@inheritDoc} + */ + public function fetchAllAssociative(): array + { + $rows = []; + + while (($row = $this->fetchAssociative()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * {@inheritDoc} + */ + public function fetchAllKeyValue(): array + { + $this->ensureHasKeyValue(); + $data = []; + + foreach ($this->fetchAllNumeric() as [$key, $value]) { + $data[$key] = $value; + } + + return $data; + } + + /** + * {@inheritDoc} + */ + public function fetchAllAssociativeIndexed(): array + { + $data = []; + + foreach ($this->fetchAllAssociative() as $row) { + $data[array_shift($row)] = $row; + } + + return $data; + } + + /** + * {@inheritDoc} + */ + public function fetchFirstColumn(): array + { + $rows = []; + + while (($row = $this->fetchOne()) !== false) { + $rows[] = $row; + } + + return $rows; + } + + /** + * {@inheritdoc} + * + * @return Traversable> + */ + public function iterateNumeric(): Traversable + { + while (($row = $this->fetchNumeric()) !== false) { + yield $row; + } + } + + /** + * {@inheritDoc} + * + * @return Traversable> + */ + public function iterateAssociative(): Traversable + { + while (($row = $this->fetchAssociative()) !== false) { + yield $row; + } + } + + /** + * {@inheritDoc} + * + * @return Traversable + */ + public function iterateKeyValue(): Traversable + { + $this->ensureHasKeyValue(); + + foreach ($this->iterateNumeric() as [$key, $value]) { + yield $key => $value; + } + } + + /** + * {@inheritDoc} + * + * @return Traversable> + */ + public function iterateAssociativeIndexed(): Traversable + { + foreach ($this->iterateAssociative() as $row) { + yield array_shift($row) => $row; + } + } + + /** + * {@inheritDoc} + * + * @return Traversable + */ + public function iterateColumn(): Traversable + { + while (($value = $this->fetchOne()) !== false) { + yield $value; + } + } + + /** + * {@inheritDoc} + */ + public function rowCount() + { + if (method_exists($this->stmt, 'rowCount')) { + return $this->stmt->rowCount(); + } + + throw Exception::notSupported('rowCount'); + } + + public function free(): void + { + $this->closeCursor(); + } + + private function ensureHasKeyValue(): void + { + $columnCount = $this->columnCount(); + + if ($columnCount < 2) { + throw NoKeyValue::fromColumnCount($columnCount); + } + } +} diff --git a/lib/Doctrine/DBAL/Portability/Connection.php b/lib/Doctrine/DBAL/Portability/Connection.php index eb7af86be81..bf973830d35 100644 --- a/lib/Doctrine/DBAL/Portability/Connection.php +++ b/lib/Doctrine/DBAL/Portability/Connection.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\ColumnCase; use Doctrine\DBAL\Connection as BaseConnection; use Doctrine\DBAL\Driver\PDO\Connection as PDOConnection; +use Doctrine\DBAL\ForwardCompatibility; use PDO; use function func_get_args; @@ -96,7 +97,7 @@ public function executeQuery($sql, array $params = [], $types = [], ?QueryCacheP $stmt = new Statement(parent::executeQuery($sql, $params, $types, $qcp), $this); $stmt->setFetchMode($this->defaultFetchMode); - return $stmt; + return new ForwardCompatibility\Result($stmt); } /** diff --git a/lib/Doctrine/DBAL/Result.php b/lib/Doctrine/DBAL/Result.php new file mode 100644 index 00000000000..227310b3dbd --- /dev/null +++ b/lib/Doctrine/DBAL/Result.php @@ -0,0 +1,52 @@ + + * + * @throws Exception + */ + public function fetchAllKeyValue(): array; + + /** + * Returns an associative array with the keys mapped to the first column and the values being + * an associative array representing the rest of the columns and their values. + * + * @return array> + * + * @throws Exception + */ + public function fetchAllAssociativeIndexed(): array; + + /** + * Returns an iterator over the result set with the values of the first column of the result + * + * @return Traversable + * + * @throws Exception + */ + public function iterateKeyValue(): Traversable; + + /** + * Returns an iterator over the result set with the keys mapped to the first column and the values being + * an associative array representing the rest of the columns and their values. + * + * @return Traversable> + * + * @throws Exception + */ + public function iterateAssociativeIndexed(): Traversable; +} diff --git a/tests/Doctrine/Tests/DBAL/ConnectionTest.php b/tests/Doctrine/Tests/DBAL/ConnectionTest.php index 32129bf6c91..0716e97d94f 100644 --- a/tests/Doctrine/Tests/DBAL/ConnectionTest.php +++ b/tests/Doctrine/Tests/DBAL/ConnectionTest.php @@ -4,7 +4,6 @@ use Doctrine\Common\Cache\Cache; use Doctrine\Common\EventManager; -use Doctrine\DBAL\Cache\ArrayStatement; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; @@ -22,6 +21,7 @@ use Doctrine\DBAL\Logging\EchoSQLLogger; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Result; use Doctrine\Tests\DbalTestCase; use PHPUnit\Framework\MockObject\MockObject; use stdClass; @@ -778,11 +778,11 @@ public function testConnectionParamsArePassedToTheQueryCacheProfileInExecuteCach ->will($this->returnValue(['cacheKey', 'realKey'])); $driver = $this->createMock(Driver::class); + $result = (new Connection($this->params, $driver)) + ->executeCacheQuery($query, $params, $types, $queryCacheProfileMock); - self::assertInstanceOf( - ArrayStatement::class, - (new Connection($this->params, $driver))->executeCacheQuery($query, $params, $types, $queryCacheProfileMock) - ); + self::assertInstanceOf(Driver\ResultStatement::class, $result); + self::assertInstanceOf(Result::class, $result); } public function testShouldNotPassPlatformInParamsToTheQueryCacheProfileInExecuteCacheQuery(): void diff --git a/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php b/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php new file mode 100644 index 00000000000..a519e33c8c4 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php @@ -0,0 +1,349 @@ +instance = new Result( + new ArrayStatement([ + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + [ + 'row2col1' => 'row2col1value', + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + [ + 'row3col1' => 'row3col1value', + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ]) + ); + } + + public function testIsTraversable(): void + { + $this->instance->setFetchMode(PDO::FETCH_ASSOC); + + $data = []; + + foreach ($this->instance as $row) { + $data[] = $row; + } + + $this->assertInstanceOf(Traversable::class, $this->instance); + $this->assertSame( + [ + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + [ + 'row2col1' => 'row2col1value', + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + [ + 'row3col1' => 'row3col1value', + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + $data + ); + } + + public function testFetchWithPdoAssoc(): void + { + $this->assertSame( + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + $this->instance->fetch(PDO::FETCH_ASSOC) + ); + } + + public function testFetchAllWithPdoAssoc(): void + { + $this->assertSame( + [ + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + [ + 'row2col1' => 'row2col1value', + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + [ + 'row3col1' => 'row3col1value', + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + $this->instance->fetchAll(PDO::FETCH_ASSOC) + ); + } + + public function testFetchColumn(): void + { + $this->assertSame( + 'row1col2value', + $this->instance->fetchColumn(1) + ); + } + + public function testFetchNumeric(): void + { + $this->assertSame( + [ + 'row1col1value', + 'row1col2value', + 'row1col3value', + ], + $this->instance->fetchNumeric() + ); + } + + public function testFetchAssociative(): void + { + $this->assertSame( + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + $this->instance->fetchAssociative() + ); + } + + public function testFetchOne(): void + { + $this->assertSame( + 'row1col1value', + $this->instance->fetchOne() + ); + } + + public function testAllNumeric(): void + { + $this->assertSame( + [ + [ + 'row1col1value', + 'row1col2value', + 'row1col3value', + ], + [ + 'row2col1value', + 'row2col2value', + 'row2col3value', + ], + [ + 'row3col1value', + 'row3col2value', + 'row3col3value', + ], + ], + $this->instance->fetchAllNumeric() + ); + } + + public function testAllAssociative(): void + { + $this->assertSame( + [ + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + [ + 'row2col1' => 'row2col1value', + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + [ + 'row3col1' => 'row3col1value', + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + $this->instance->fetchAllAssociative() + ); + } + + public function testFetchAllKeyValue(): void + { + $this->assertSame( + [ + 'row1col1value' => 'row1col2value', + 'row2col1value' => 'row2col2value', + 'row3col1value' => 'row3col2value', + ], + $this->instance->fetchAllKeyValue() + ); + } + + public function testFetchAllAssociativeIndexed(): void + { + $this->assertSame( + [ + 'row1col1value' => [ + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + 'row2col1value' => [ + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + 'row3col1value' => [ + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + $this->instance->fetchAllAssociativeIndexed() + ); + } + + public function testFetchFirstColumn(): void + { + $this->assertSame( + [ + 'row1col1value', + 'row2col1value', + 'row3col1value', + ], + $this->instance->fetchFirstColumn() + ); + } + + public function testIterateNumeric(): void + { + $this->assertSame( + [ + [ + 0 => 'row1col1value', + 1 => 'row1col2value', + 2 => 'row1col3value', + ], + [ + 0 => 'row2col1value', + 1 => 'row2col2value', + 2 => 'row2col3value', + ], + [ + 0 => 'row3col1value', + 1 => 'row3col2value', + 2 => 'row3col3value', + ], + ], + iterator_to_array($this->instance->iterateNumeric()) + ); + } + + public function testIterateAssociative(): void + { + $this->assertSame( + [ + [ + 'row1col1' => 'row1col1value', + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + [ + 'row2col1' => 'row2col1value', + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + [ + 'row3col1' => 'row3col1value', + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + iterator_to_array($this->instance->iterateAssociative()) + ); + } + + public function testIterateKeyValue(): void + { + $this->assertSame( + [ + 'row1col1value' => 'row1col2value', + 'row2col1value' => 'row2col2value', + 'row3col1value' => 'row3col2value', + ], + iterator_to_array($this->instance->iterateKeyValue()) + ); + } + + public function testIterateAssociativeIndexed(): void + { + $this->assertSame( + [ + 'row1col1value' => [ + 'row1col2' => 'row1col2value', + 'row1col3' => 'row1col3value', + ], + 'row2col1value' => [ + 'row2col2' => 'row2col2value', + 'row2col3' => 'row2col3value', + ], + 'row3col1value' => [ + 'row3col2' => 'row3col2value', + 'row3col3' => 'row3col3value', + ], + ], + iterator_to_array($this->instance->iterateAssociativeIndexed()) + ); + } + + public function testIterateColumn(): void + { + $this->assertSame( + [ + 'row1col1value', + 'row2col1value', + 'row3col1value', + ], + iterator_to_array($this->instance->iterateColumn()) + ); + } + + public function testRowCountIsSupportedByWrappedStatement(): void + { + $this->assertSame(3, $this->instance->rowCount()); + } + + public function testRowCountIsNotSupportedByWrappedStatement(): void + { + $this->expectExceptionObject(Exception::notSupported('rowCount')); + $instance = new Result($this->createMock(DriverResultStatement::class)); + $instance->rowCount(); + } +} diff --git a/tests/Doctrine/Tests/DBAL/Functional/Connection/BackwardCompatibility/Connection.php b/tests/Doctrine/Tests/DBAL/Functional/Connection/BackwardCompatibility/Connection.php index b864a794236..aa0496fee89 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Connection/BackwardCompatibility/Connection.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Connection/BackwardCompatibility/Connection.php @@ -4,6 +4,7 @@ use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\DBAL\Connection as BaseConnection; +use Doctrine\DBAL\ForwardCompatibility; use function func_get_args; @@ -17,7 +18,9 @@ class Connection extends BaseConnection */ public function executeQuery($sql, array $params = [], $types = [], ?QueryCacheProfile $qcp = null) { - return new Statement(parent::executeQuery($sql, $params, $types, $qcp)); + return new ForwardCompatibility\Result( + new Statement(parent::executeQuery($sql, $params, $types, $qcp)) + ); } /** diff --git a/tests/Doctrine/Tests/DBAL/Functional/ResultCacheTest.php b/tests/Doctrine/Tests/DBAL/Functional/ResultCacheTest.php index 5336a1053ea..f2e12203343 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/ResultCacheTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/ResultCacheTest.php @@ -4,8 +4,7 @@ use Doctrine\Common\Cache\ArrayCache; use Doctrine\DBAL\Cache\QueryCacheProfile; -use Doctrine\DBAL\Cache\ResultCacheStatement; -use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Driver; use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\Logging\DebugStack; use Doctrine\DBAL\Schema\Table; @@ -238,25 +237,25 @@ public function testFetchingAllRowsSavesCache(callable $fetchAll): void public static function fetchAllProvider(): iterable { yield 'fetchAll' => [ - static function (ResultCacheStatement $statement): void { + static function (Driver\ResultStatement $statement): void { $statement->fetchAll(); }, ]; yield 'fetchAllAssociative' => [ - static function (ResultCacheStatement $statement): void { + static function (Driver\Result $statement): void { $statement->fetchAllAssociative(); }, ]; yield 'fetchAllNumeric' => [ - static function (ResultCacheStatement $statement): void { + static function (Driver\Result $statement): void { $statement->fetchAllNumeric(); }, ]; yield 'fetchFirstColumn' => [ - static function (ResultCacheStatement $result): void { + static function (Driver\Result $result): void { $result->fetchFirstColumn(); }, ]; @@ -358,7 +357,7 @@ public function testChangeCacheImpl(): void /** * @return array */ - private function hydrateStmt(ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE): array + private function hydrateStmt(Driver\ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE): array { $data = []; @@ -372,7 +371,7 @@ private function hydrateStmt(ResultStatement $stmt, int $fetchMode = FetchMode:: /** * @return array */ - private function hydrateStmtIterator(ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE): array + private function hydrateStmtIterator(Driver\ResultStatement $stmt, int $fetchMode = FetchMode::ASSOCIATIVE): array { $data = []; $stmt->setFetchMode($fetchMode);