Change record status: 
Project: 
Introduced in branch: 
12.1.x
Introduced in version: 
12.1.0
Description: 

Two new exceptions have been added to the Drupal\Core\Database\Exception namespace:

- SchemaTableDoesNotExistException extends SchemaObjectDoesNotExistException.
- SchemaTableAlreadyExistsException extends SchemaObjectExistsException.

The MySQL, PostgreSQL and SQLite drivers throw them when a query fails because a table is missing or already exists. Core will later rely on these exceptions to create tables on demand.

ExceptionHandler has a new protected method, rethrowNormalizedException(). The base handleStatementException() and handleExecutionException() call it for every \PDOException. A driver maps its native error codes by overriding this method. For example, the PostgreSQL driver does this:

protected function rethrowNormalizedException(
  \Exception $exception,
  int|string $sqlState,
  ?int $errorCode,
  string $queryString,
  array $arguments,
  array $options = [],
): never {
  $info = new SqlExecutionInfo($queryString, $arguments, $options);
  $message = $info->appendToMessage($exception->getMessage());
  match ($sqlState) {
    '42P01' => throw new SchemaTableDoesNotExistException($message, (int) $sqlState, $exception, $info),
    '42P07' => throw new SchemaTableAlreadyExistsException($message, (int) $sqlState, $exception, $info),
    default => parent::rethrowNormalizedException($exception, $sqlState, $errorCode, $queryString, $arguments, $options),
  };
}

DatabaseExceptionWrapper has a new optional fourth constructor argument, ?SqlExecutionInfo $info.

Impacts: 
Module developers