Skip to content

check on delete (expr) fires on INSERT #23

@aarashrestha

Description

@aarashrestha

check on delete (expr) fires on INSERT instead of being scoped to DELETE

Affected versions: confirmed in 2.9.0 and 3.1.1 (latest as of 2026-05-22)

Summary

A CHECK constraint declared with the on delete modifier — e.g.,
constraint X check on delete (false) — is evaluated against INSERT
rows, not just DELETE rows as the syntax declares.

Reproduction

declare schema main

{
    table T (
        Id int,
        primary key (),
        constraint NoDeleteEver check on delete (false)
    );
}

apply schema main;

insert into T (Id) values (1);

Expected: INSERT succeeds ((false) is scoped to DELETE ops only).

Actual: ConstraintError: CHECK constraint failed: NoDeleteEver.

Confirmation that the literal false is not special

constraint NoDeleteEither check on delete (1 = 0)

(semantically identical to (false)) reproduces the same failure on
INSERT, ruling out a special case in literal-false handling.

Root cause hypothesis

The parser correctly captures operations: ['delete'] in the AST
(dist/src/parser/parser.js:3261 / :3361). The schema manager converts
to bitmask RowOpFlag.DELETE = 4. The bug is downstream — INSERT-path
evaluation is not filtering by op mask. Likely candidates:
shouldCheckConstraint or its callers in the constraint-builder layer.

Test reference

stage-6-check-on-delete.spec.ts

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions