Deprecation: #96972 - Deprecate QueryBuilder::execute()

See forge#96972

Description

doctrine/dbal deprecated the union return-type method QueryBuilder->execute() in favour of single return-typed QueryBuilder->executeQuery() and QueryBuilder->executeStatement() in doctrine/dbal v3.1.x. This makes it more obvious which return type is expected and further helps static code analyzer tools like phpstan to recognize return types properly. TYPO3 already provides a facade class around the doctrine/dbal QueryBuilder, which has been changed to provide the new methods in the core facade class with a corresponding backport.

Thus QueryBuilder->execute() is marked as deprecated in TYPO3 v12 and will be removed in v13 to encourage extension developers to use the cleaner methods and decrease issues with static code analysers.

Impact

The Method execute() is also used for extbase query execution and as Upgrade Wizard method, thus the extension scanner is not configured to scan for this method to avoid a lot of noisy weak matches.

QueryBuilder->execute() will raise a deprecation level log entry when called.

Affected Installations

In general, instances with extensions that uses the deprecated QueryBuilder->execute() method.

Migration

Extensions should use the proper methods QueryBuilder->executeQuery() and QueryBuilder->executeStatement() instead of the generic QueryBuilder->execute(). Through the backport to TYPO3 v11 extensions can change to deprecation less code but keep supporting two major core version at the same time.

  • QueryBuilder::executeStatement(): use this for INSERT, DELETE or UPDATE queries (expecting int as return value).

  • QueryBuilder::executeQuery(): use this for SELECT and COUNT queries (expecting ResultSet as return value).

As a thumb rule you can say that queries which expects a result set should use QueryBuilder::executeQuery(). Queries which return the number of affected rows should use QueryBuilder::executeStatement().

For example, following select query:

$rows = $queryBuilder
  ->select(...)
  ->from(...)
  ->execute()
  ->fetchAllAssociative();

should be replaced with:

$rows = $queryBuilder
  ->select(...)
  ->from(...)
  ->executeQuery()
  ->fetchAllAssociative();

As another example, given delete query:

$deletedRows = $queryBuilder
  ->delete(...)
  ->execute();

should be replaced with:

$deletedRows = $queryBuilder
  ->delete(...)
  ->executeStatement();