Skip to content

Support temporal/period constraints: PRIMARY KEY/UNIQUE ... WITHOUT OVERLAPS (PG17) and FOREIGN KEY ... PERIOD (PG18) #2073

@pematt

Description

@pematt

Feature description

pgModeler cannot model PostgreSQL's native temporal (period) constraints, so databases that use them cannot be round-tripped, diffed, or generated from a model.

Two related, standard-SQL features are missing:

  1. Temporal PRIMARY KEY / UNIQUE — WITHOUT OVERLAPS (PostgreSQL 17+)
    ALTER TABLE subscription_statuses
    ADD CONSTRAINT subscription_statuses_pk
    PRIMARY KEY (status_id, valid_period WITHOUT OVERLAPS);
  2. The trailing key column is a range/multirange (e.g. tstzrange); WITHOUT OVERLAPS enforces that rows sharing the scalar key parts may not have overlapping periods. (Requires btree_gist when scalar columns participate.)
  3. Temporal FOREIGN KEY — PERIOD (PostgreSQL 18+)
    ALTER TABLE subscriptions
    ADD CONSTRAINT subscriptions_status_fk
    FOREIGN KEY (status_id, PERIOD valid_period)
    REFERENCES subscription_statuses (status_id, PERIOD valid_period);
  4. The PERIOD column must be covered, for the entire referencing period, by the union of matching referenced rows.

What's needed in pgModeler:

  • Constraint editor: a WITHOUT OVERLAPS flag on the last column of a PK/UNIQUE constraint, and a PERIOD flag on the period column of a FK (both source and referenced column lists).
  • SQL generation: emit the WITHOUT OVERLAPS / PERIOD keywords. The current template conf/schemas/sql/constraint.sch has no token for either — it only supports the classic constraint attributes (pk-constr, fk-constr, uq-constr, del-action, upd-action, deferrable, …).
  • Model/XML: a way to persist the flags (e.g. a without-overlaps="true" attribute on pk-constr/uq-constr and a per-column period="true" marker on fk-constr) so models round-trip.
  • Reverse engineering & diff: import these constraints from a live DB and treat them as first-class in the diff tool, so they aren't reported as drift / scheduled for DROP when a modeled DB already uses them.

Sample image

Not a visual/diagram feature — it's DDL generation + the constraint editor. The minimal UI touchpoints:

  ┌─ Primary key / Unique constraint ──────────────┐
  │ Columns:  [status_id          ]                 │
  │           [valid_period        ]  ☑ WITHOUT OVERLAPS   ← new checkbox on last col
  └─────────────────────────────────────────────────┘

  ┌─ Foreign key ──────────────────────────────────┐
  │ Src columns:   status_id ,  valid_period ☑ PERIOD     ← new "PERIOD" flag
  │ Ref columns:   status_id ,  valid_period ☑ PERIOD
  │ ON DELETE [NO ACTION ▾]   ON UPDATE [NO ACTION ▾]│
  └─────────────────────────────────────────────────┘

Additional info

  • Versions: WITHOUT OVERLAPS for PK/UNIQUE shipped in PostgreSQL 17; temporal FOREIGN KEY ... PERIOD (and UPDATE/DELETE ... FOR PORTION OF, which is DML and out of scope here) shipped in PostgreSQL 18. Tested working on PostgreSQL 18.3, including a temporal FK on a partitioned referencing table.
  • Reproduction (current behaviour): create the constraints above in a database, then reverse-engineer it in pgModeler 2.0.0-beta — the temporal qualifiers are lost; and a model→DB diff of a database that uses them reports them as objects to drop, because the model can't represent them.
  • Impact: projects on PG17/18 that adopt temporal integrity must currently emulate it with BEFORE INSERT/UPDATE/DELETE trigger functions (to keep the relationship inside the pgModeler model and out of the diff tool's "drift" set). Native template support would let these be modeled directly and retire the trigger workarounds.
  • Docs: PostgreSQL CREATE TABLE / ALTER TABLE constraint syntax (WITHOUT OVERLAPS, PERIOD), and the SQL:2011 application-time period tables this implements.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions