Treat PostgreSQL RESTRICT violations (SQLSTATE 23001) as ReferenceConstraintException - #103
Conversation
…straintException PostgreSQL 18 reports violations of ON DELETE/UPDATE RESTRICT foreign keys with SQLSTATE 23001 (restrict_violation) instead of 23503.
There was a problem hiding this comment.
🟢 Approval recommended
The classifier change is focused and covered by appropriate PostgreSQL 18 integration tests.
Pull request overview
Adds PostgreSQL 18 support for classifying SQLSTATE 23001 RESTRICT violations as reference constraint errors.
Changes:
- Recognizes
RestrictViolationalongside foreign-key violations. - Adds RESTRICT relationship integration tests using PostgreSQL 18.
- Skips unsupported SQLite cases.
File summaries
| File | Description |
|---|---|
PostgreSQLExceptionClassifier.cs |
Classifies SQLSTATE 23001. |
DemoContext.cs |
Adds the RESTRICT test relationship. |
DatabaseTests.cs |
Tests tracked and bulk deletions. |
PostgreSQLTests.cs |
Runs tests against PostgreSQL 18. |
SqliteTests.cs |
Skips SQLite-specific unsupported behavior. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
@zerox12311 How do other databases (SQL Server, Oracle, MySQL) treat |
|
As far as I know, PostgreSQL 18 is the only one affected. The new tests pass on SQL Server, MySQL and Oracle in this PR's CI run without any change to their classifiers, since those servers report a RESTRICT violation with the same error code as NO ACTION (SQL Server and Oracle don't even emit a RESTRICT clause; EF Core generates NO ACTION / no clause for them). That said, I only verified against the versions used in the test containers, and I can't rule out that other versions behave differently. So I kept this PR focused on the PostgreSQL 18 change. The one other case I ran into is SQLite: it reports RESTRICT violations with |
|
I'm not sure that SQLite needs any additional handling. If we report every |
|
Agreed, that would cause false positives. I'll leave SQLite as is and keep this PR to the PostgreSQL 18 change only. |
|
Thanks for the PR! |
Problem
PostgreSQL 18 reports a violation of an
ON DELETE/UPDATE RESTRICTforeign key with SQLSTATE23001(restrict_violation) instead of23503(foreign_key_violation). PostgreSQL 17 and earlier used23503for bothRESTRICTandNO ACTION;NO ACTIONstill reports23503on 18.The change is in
src/backend/utils/adt/ri_triggers.c(ri_ReportViolation, newis_restrictbranch usingERRCODE_RESTRICT_VIOLATION). It is not mentioned in the PostgreSQL 18 release notes.PostgreSQLExceptionClassifier.IsReferenceConstraintErroronly matchesPostgresErrorCodes.ForeignKeyViolation, so on PostgreSQL 18 an EF Core relationship configured withDeleteBehavior.Restrictsurfaces as a plainDbUpdateExceptioninstead ofReferenceConstraintException:Fix
Also match
PostgresErrorCodes.RestrictViolation(23001) inIsReferenceConstraintError.PostgresErrorCodes.RestrictViolationis aconst, and PostgreSQL 17 and earlier never emit23001, so behaviour on older servers is unchanged.Tests
ProductReviewentity toDemoContextwith anOnDelete(DeleteBehavior.Restrict)relationship toProduct.DeleteParentItemWithRestrictThrowsReferenceConstraintExceptionand...ThroughExecuteDeletetoDatabaseTests, mirroring the existingDeleteParentItem...tests, assertingReferenceConstraintExceptionis thrown.postgres:18(the Testcontainers default is 15.x, where23001is never emitted). Without the classifier change both new tests fail on PostgreSQL 18 with the23001error above; with it, the full PostgreSQL suite passes.RESTRICTviolations withSQLITE_CONSTRAINT_TRIGGER(1811) rather thanSQLITE_CONSTRAINT_FOREIGNKEY(787), soSqliteExceptionClassifierdoes not classify them either. That is a separate issue and is left out of this PR.