Skip to content

bug: modifying an existing Contstraint when allow_drop_extra_constraints is False #11

@brian-pond

Description

@brian-pond

Summary

When allow_drop_extra_constraints=False, dbconform can emit ADD CONSTRAINT for a CHECK constraint that already exists under the same name, causing PostgreSQL DuplicateObjectError instead of a clear skip or error.

Environment

  • dbconform: 1.0.5
  • PostgreSQL (asyncpg)
  • SQLAlchemy Enum(..., create_constraint=True, native_enum=False) CHECK constraints

Steps to reproduce

  1. Create a table with a SQLAlchemy string enum column (non-native enum), e.g. run_status with CHECK constraint named runstatus.
  2. Change the Python enum allowed values (add/remove members).
  3. Run dbconform compare/apply with allow_drop_extra_constraints=False (the default in some consumers).

Expected behavior

One of:

  • Skip the ADD step and report that the constraint cannot be updated without dropping it first, or
  • Treat same-name CHECK with different expression as a modify and emit DROP + ADD atomically only when drops are allowed, or
  • Fail with an actionable message before executing DDL.

Actual behavior

Compare treats the change as removed check + added check (different (name, expression) keys). With allow_drop_extra_constraints=False:

  1. DROP is skipped (correct).
  2. ADD still runs → DuplicateObjectError: constraint "runstatus" for relation "..." already exists.

Example failing SQL:

ALTER TABLE "public"."task_run_attempts" ADD CONSTRAINT "runstatus"
  CHECK (run_status IN ('pending', 'in_progress', ..., 'execution_timeout', ...));

Suggested fix

In ConformPlanBuilder.build(), when processing added_checks, if a check with the same name already exists on the table (from removed_checks or reflected schema) and allow_drop_extra_constraints=False, do not emit ADD; add a SkippedStep with reason e.g. "Check constraint update blocked: allow_drop_extra_constraints=False".

Alternatively, diff same-name checks by name only into modified_checks and handle modify as drop-then-add when drops are allowed.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions