diff --git a/lib/Doctrine/DBAL/Connection.php b/lib/Doctrine/DBAL/Connection.php index f71fbecb5f2..67ffe820341 100644 --- a/lib/Doctrine/DBAL/Connection.php +++ b/lib/Doctrine/DBAL/Connection.php @@ -1370,11 +1370,7 @@ public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp) */ private function ensureForwardCompatibilityStatement(ResultStatement $stmt) { - if ($stmt instanceof ForwardCompatibility\Result) { - return $stmt; - } - - return new ForwardCompatibility\Result($stmt); + return ForwardCompatibility\Result::ensure($stmt); } /** diff --git a/lib/Doctrine/DBAL/ForwardCompatibility/Result.php b/lib/Doctrine/DBAL/ForwardCompatibility/Result.php index a8c22644153..c1dde99b214 100644 --- a/lib/Doctrine/DBAL/ForwardCompatibility/Result.php +++ b/lib/Doctrine/DBAL/ForwardCompatibility/Result.php @@ -23,6 +23,15 @@ class Result implements IteratorAggregate, DriverStatement, DriverResultStatemen /** @var Driver\ResultStatement */ private $stmt; + public static function ensure(Driver\ResultStatement $stmt): Result + { + if ($stmt instanceof Result) { + return $stmt; + } + + return new Result($stmt); + } + public function __construct(Driver\ResultStatement $stmt) { $this->stmt = $stmt; diff --git a/lib/Doctrine/DBAL/Query/QueryBuilder.php b/lib/Doctrine/DBAL/Query/QueryBuilder.php index 205bb37a175..419937d3586 100644 --- a/lib/Doctrine/DBAL/Query/QueryBuilder.php +++ b/lib/Doctrine/DBAL/Query/QueryBuilder.php @@ -201,14 +201,16 @@ public function getState() /** * Executes this query using the bound parameters and their types. * - * @return ForwardCompatibility\DriverStatement|ForwardCompatibility\DriverResultStatement|int + * @return ForwardCompatibility\DriverStatement|int * * @throws Exception */ public function execute() { if ($this->type === self::SELECT) { - return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); + return ForwardCompatibility\Result::ensure( + $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes) + ); } return $this->connection->executeStatement($this->getSQL(), $this->params, $this->paramTypes); diff --git a/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php b/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php index b0a8acb697e..0798c7dbd3d 100644 --- a/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php +++ b/tests/Doctrine/Tests/DBAL/ForwardCompatibility/ResultTest.php @@ -41,6 +41,24 @@ public function setUp(): void ); } + public function testEnsureWithResult(): void + { + $instance = Result::ensure($this->instance); + $this->assertSame($this->instance, $instance, 'Result is not wrapped twice'); + } + + public function testEnsureWithResultStatement(): void + { + $instance = Result::ensure($this->createMock(Driver\ResultStatement::class)); + $this->assertInstanceOf(Result::class, $instance); + } + + public function testEnsureWithStatement(): void + { + $instance = Result::ensure($this->createMock(Driver\Statement::class)); + $this->assertInstanceOf(Result::class, $instance); + } + public function testIsTraversable(): void { $this->instance->setFetchMode(PDO::FETCH_ASSOC); diff --git a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php index a83362ed588..63969855009 100644 --- a/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php +++ b/tests/Doctrine/Tests/DBAL/Query/QueryBuilderTest.php @@ -3,15 +3,18 @@ namespace Doctrine\Tests\DBAL\Query; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver; use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Query\QueryException; +use Doctrine\DBAL\Result; use Doctrine\Tests\DbalTestCase; +use PHPUnit\Framework\MockObject\MockObject; class QueryBuilderTest extends DbalTestCase { - /** @var Connection */ + /** @var Connection&MockObject */ protected $conn; protected function setUp(): void @@ -1075,4 +1078,22 @@ public function testOrHavingEmptyStringStartingWithNonEmptyExpression(): void self::assertSame('SELECT id FROM foo HAVING (a = b) OR (c = d)', $qb->getSQL()); } + + public function testExecuteSelect(): void + { + $qb = new QueryBuilder($this->conn); + + $this->conn + ->expects($this->any()) + ->method('executeQuery') + ->willReturn($this->createMock(Driver\Statement::class)); + + $result = $qb + ->select('id') + ->from('foo') + ->execute(); + + self::assertInstanceOf(Driver\Statement::class, $result); + self::assertInstanceOf(Result::class, $result); + } }