diff --git a/UPGRADE.md b/UPGRADE.md index 0c1fba1e138..339f0eac900 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -36,6 +36,23 @@ Use `Connection::createSchemaManager()` instead. The usage of `Connection::$_expr` and `Connection::getExpressionBuilder()` is deprecated. Use `Connection::createExpressionBuilder()` instead. +## Deprecated `QueryBuilder::execute()` + +The usage of `QueryBuilder::execute()` is deprecated. Use either `QueryBuilder::executeQuery()` or +`QueryBuilder::executeStatement()`, depending on whether the queryBuilder is a query (SELECT) or a statement (INSERT, +UPDATE, DELETE). + +You might also consider the use of the new shortcut methods, such as: + +- `fetchAllAssociative()` +- `fetchAllAssociativeIndexed()` +- `fetchAllKeyValue()` +- `fetchAllNumeric()` +- `fetchAssociative()` +- `fetchFirstColumn()` +- `fetchNumeric()` +- `fetchOne()` + # Upgrade to 3.0 ## BC BREAK: leading colon in named parameter names not supported diff --git a/src/Query/QueryBuilder.php b/src/Query/QueryBuilder.php index 24f1706fa38..cfed4b0130e 100644 --- a/src/Query/QueryBuilder.php +++ b/src/Query/QueryBuilder.php @@ -300,9 +300,35 @@ public function fetchFirstColumn(): array return $this->connection->fetchFirstColumn($this->getSQL(), $this->params, $this->paramTypes); } + /** + * Executes an SQL query (SELECT) and returns a Result. + * + * @throws Exception + */ + public function executeQuery(): Result + { + return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); + } + + /** + * Executes an SQL statement and returns the number of affected rows. + * + * Should be used for INSERT, UPDATE and DELETE + * + * @return int The number of affected rows. + * + * @throws Exception + */ + public function executeStatement(): int + { + return $this->connection->executeStatement($this->getSQL(), $this->params, $this->paramTypes); + } + /** * Executes this query using the bound parameters and their types. * + * @deprecated Use {@link executeQuery()} or {@link executeStatement()} instead. + * * @return Result|int * * @throws Exception @@ -310,9 +336,21 @@ public function fetchFirstColumn(): array public function execute() { if ($this->type === self::SELECT) { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/4578', + 'QueryBuilder::execute() is deprecated, use QueryBuilder::executeQuery() for SQL queries instead.' + ); + return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); } + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/4578', + 'QueryBuilder::execute() is deprecated, use QueryBuilder::executeStatement() for SQL statements instead.' + ); + return $this->connection->executeStatement($this->getSQL(), $this->params, $this->paramTypes); } diff --git a/tests/Query/QueryBuilderTest.php b/tests/Query/QueryBuilderTest.php index 3313375cb16..4230baf0f31 100644 --- a/tests/Query/QueryBuilderTest.php +++ b/tests/Query/QueryBuilderTest.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder; use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Query\QueryException; +use Doctrine\DBAL\Result; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use PHPUnit\Framework\MockObject\MockObject; @@ -1302,4 +1303,72 @@ public static function fetchProvider(): iterable 'SELECT id, username FROM user WHERE password = :password AND username != :username AND id != :id', ]; } + + /** + * @param list|array $parameters + * @param array|array $parameterTypes + * + * @dataProvider fetchProvider + */ + public function testExecuteQuery( + string $select, + string $from, + string $where, + array $parameters, + array $parameterTypes, + string $expectedSql + ): void { + $qb = new QueryBuilder($this->conn); + $mockedResult = $this->createMock(Result::class); + + $this->conn->expects(self::once()) + ->method('executeQuery') + ->with($expectedSql, $parameters, $parameterTypes) + ->willReturn($mockedResult); + + $results = $qb->select($select) + ->from($from) + ->where($where) + ->setParameters($parameters, $parameterTypes) + ->executeQuery(); + + self::assertSame( + $mockedResult, + $results + ); + } + + public function testExecuteStatement(): void + { + $qb = new QueryBuilder($this->conn); + $mockedResult = 123; + $expectedSql = 'UPDATE users SET foo = ?, bar = ? WHERE bar = 1'; + + $parameters = [ + 'foo' => 'jwage', + 'bar' => false, + ]; + + $parameterTypes = [ + 'foo' => Types::STRING, + 'bar' => Types::BOOLEAN, + ]; + + $this->conn->expects(self::once()) + ->method('executeStatement') + ->with($expectedSql, $parameters, $parameterTypes) + ->willReturn($mockedResult); + + $results = $qb->update('users') + ->set('foo', '?') + ->set('bar', '?') + ->where('bar = 1') + ->setParameters($parameters, $parameterTypes) + ->executeStatement(); + + self::assertSame( + $mockedResult, + $results + ); + } }