Skip to content

Deparser drops WHERE clause from EXCLUDE constraints #287

@devin-ai-integration

Description

@devin-ai-integration

Bug Description

The deparser silently drops the WHERE clause from EXCLUDE constraints during parse → deparse cycles.

Input SQL

CREATE TABLE test_exclude_where (
  id uuid PRIMARY KEY,
  database_id uuid NOT NULL,
  status text NOT NULL DEFAULT 'pending',
  EXCLUDE USING btree (database_id WITH =)
    WHERE (status = 'pending')
);

Deparsed output

CREATE TABLE test_exclude_where (id uuid PRIMARY KEY, database_id uuid NOT NULL, status text NOT NULL DEFAULT 'pending', EXCLUDE USING btree (database_id WITH =))

The WHERE (status = 'pending') predicate is completely lost.

Root Cause

The CONSTR_EXCLUSION handler in packages/deparser/src/deparser.ts (lines ~3038-3070) handles access_method and exclusions but never checks or outputs node.where_clause.

The parser correctly preserves where_clause in the AST (verified — the constraint node has a full where_clause A_Expr), but the deparser never visits it.

Impact

This silently changes constraint semantics:

  • With WHERE: "only one pending row per database_id" (partial exclusion)
  • Without WHERE: "only one row per database_id ever" (total exclusion)

Discovered in constructive-db's database_transfer table — pgpm package uses the deparser to bundle SQL, and the bundled output was missing the WHERE clause.

Suggested Fix

In the CONSTR_EXCLUSION case, after the exclusions block and before the break:

if (node.where_clause) {
  output.push('WHERE');
  output.push('(' + this.visit(node.where_clause, context) + ')');
}

Failing Test

PR #286 adds a failing test case (misc/issues-18.sql) that reproduces this bug.

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