Needs review
Project:
Drupal core
Version:
main
Component:
database system
Priority:
Critical
Category:
Task
Assigned:
Issue tags:
Reporter:
Created:
11 Sep 2026 at 20:30 UTC
Updated:
8 Oct 2026 at 21:54 UTC
Jump to comment: Most recent
Spin off from #3609986: Improve database exception messages.
Database exceptions' hierarchy is a bit messy, and couple of them are unused. Found out in #3609986: Improve database exception messages.
SqlExecutionInfo value object that carries the details of the SQL operation that failed.SqlExecutionInfo optionally.New hierarchy structure of the database exceptions after MR merge (AI assisted in drawing the tree):
DatabaseException [interface]
│
├── DatabaseExceptionWrapper
│ │
│ ├── DatabaseAccessDeniedException
│ ├── DatabaseConnectionRefusedException
│ ├── DatabaseNotFoundException
│ │
│ ├── IntegrityConstraintViolationException
│ │
│ ├── SchemaException
│ │ │
│ │ ├── SchemaObjectDoesNotExistException
│ │ │ └── SchemaTableDoesNotExistException
│ │ │
│ │ ├── SchemaObjectExistsException
│ │ │ └── SchemaTableAlreadyExistsException
│ │ │
│ │ ├── SchemaPrimaryKeyMustBeDroppedException
│ │ ├── SchemaTableColumnSizeTooLargeException
│ │ └── SchemaTableKeyTooLargeException
│ │
│ └── TransactionException
│ │
│ ├── TransactionCommitFailedException
│ ├── TransactionExplicitCommitNotAllowedException [deprecated]
│ ├── TransactionNameNonUniqueException
│ ├── TransactionNoActiveException [deprecated]
│ └── TransactionOutOfOrderException
│
├── ConnectionNotDefinedException
├── DriverNotSpecifiedException
├── InvalidQueryException
├── RowCountException
│
├── SchemaDefinitionException
│
├── Query\FieldsOverlapException
├── Query\InvalidMergeQueryException
├── Query\NoFieldsException
└── Query\NoUniqueFieldException
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
mondrakeComment #3
mondrakeComment #5
mondrakeComment #6
dcam commentedI think this is mostly OK, but I did find one issue. There's a docblock reference to the deprecated
TransactionNoActiveExceptionatTransationManagerInterface::rollback(), https://git.drupalcode.org/project/drupal/-/blob/main/core/lib/Drupal/Co.... As far as I can tell onlyTransationManagerBase::rollback()implements this function and it does not throwTransactionNoActiveException. Maybe it did at one time. I attempted a brief search through its Git history to see if I could find out. Eventually I decided it wasn't that important and stopped. Anyway, I'm not familiar enough with the database subsystem to know for certain, but it seems like we can just delete this@throwsannotation.Comment #7
mondrakeDone #6 (thanks), added draft CR, linked in deprecation messages, bumped deprecation version to 12.1.
Comment #8
dcam commentedThank you for taking care of the deprecation messages. I knew there was something that I was forgetting. I did this review over several days and it slipped my mind.
Anyway, that was all the feedback I had. I'll go ahead and RTBC it so we can see what a committer says.
Comment #9
daffie commentedThe code changes in the MR look good.
Just a single old deprecation that needs to be updated.
What I am missing in the IS and maybe the CR is information about the new class SqlExecutionInfo. Also why it is added. I am not saying that it wrong or anything. Just explain what is added and why it should be added.
The same for the other changes in the MR. I am getting the feeling that they should be in different issues.
A lot of exception are getting an extra parameter. Should that be documented. At least in the IS.
Comment #10
mondrakeIntroduce dedicated exceptions for table existence checks: SchemaTableDoesNotExistException and SchemaTableAlreadyExistsException, to help simplifying #2371709: Move the on-demand-table creation into the database API.
Comment #12
longwaveNormalized all exceptions across all drivers as some SQLite and Postgres cases were missing before. Also improved the formatter a bit.
Parts of these commits were assisted by GPT 6.
Comment #13
mondrakeCouple of comments inline. Man AI-built tests are hard to follow...
Comment #14
mondrakeAll drivers' ExceptionHandlers now implement the pattern
handleStatementException()->rethrowNormalizedException(), but the base class does not and is now dead code for core anyway.Can we deprecate calling the base class'
handleStatementException()on the basis that it will become abstract in 13? and implement a stubrethrowNormalizedException()in the base class too that just throws?Comment #15
daffie commentedThis issue has become a blocker for #2371709: Move the on-demand-table creation into the database API and that issue has the priority critical. Therefore this issue also gets the priority critical.
Comment #16
mondrakeFiled a follow up.
Comment #17
longwaveAll pipelines are green.
Addressed the feedback from #13 and #14:
query()on every driver.SchemaTableDoesNotExistException.#[TestWith].Comment #18
longwaveDid another self-review pass, removed a bunch of tests that were testing nothing useful or duplicates. Also removed
fromThrowable()andstripFromMessage()as nothing calls them - we can reintroduce them when we need them? Hopefully this addresses @daffie's concerns in #9.Comment #19
mondrakeLovely and neat. Thanks!
+1 for RTBC but I cannot mark.
Comment #20
longwaveAdded two CRs, one for database driver maintainers who need to add the new exceptions, and another for the message format changes and
SqlExceptionInfo.Comment #21
daffie commentedI was a bit worried about a possible BC break with all the changes to the exceptions. Only I could not find an exception change that would be a BC break.
All the code changes look good to me.
@longwave what to do a minor documentation change in the MR, which is fine by me.
After that is it RTBC for me.
Comment #22
longwaveRenamed the variable, updated some comments and the CR to match.
Comment #23
daffie commentedThe last changes from @longwave look good to me.
There is enough testing added.
All code changes look good to me.
For me it is RTBC.
Comment #24
mondrakefound a small inconsistency, will update soon
Comment #25
mondrakeWith this MR,
DatabaseExceptionWrapperbecomes the base exception class for any error that is thrown by the lower-level database driver client (PDO, mysqli, etc).Based on this, IMHO
DatabaseAccessDeniedException,DatabaseConnectionRefusedExceptionandDatabaseNotFoundExceptionshould be descendants ofDatabaseExceptionWrapper, since they are triggered after the client returns an error.SchemaDefinitionExceptionshould no longer be a descendent ofSchemaException, since that inherits fromDatabaseExceptionWrapperand is triggered when execution of DML fails. But errors from the schema definition have nothing to do with the client connection. So it could be a direct implementation of the interface instead.Made changes accordingly in the last commit.
Comment #26
mondrakeUpdated the inheritance tree in the IS (AI assisted generation)