043. Lower relation endpoint checks to existence predicates

  • Status: Implemented
  • Date: 2026-10-14

Problem and mechanism

For a plain bound SQL relation, the constant Int checks has(0) and has(-1) only need to know whether at least one related row exists. The translator can use the same correlated EXISTS witness for both checks rather than count all related rows or compute an indexed element. The surrounding parent and relation presence/null case remains in place:

CASE
  WHEN parent_is_missing OR relation_is_null THEN NULL::boolean
  ELSE EXISTS (
    SELECT 1 FROM relation_items AS item
    WHERE item.parent_id = parent.id
  )
END

This does not require a unique order because either endpoint check is true exactly when the list is nonempty. The database may choose any physical plan; the lowering does not prescribe scan order or early termination.

Applicability

Expression Status Reason
Plain SQL relation with constant Int has(0) or has(-1) Applied Uses the correlated existence witness and preserves relation state.
Other indexes, including constant has(-2) Not applied They retain cardinality/index lowering.
Invalid Float indexes Not applied They retain the general lowering and its result behavior.
Computed or guarded relation values Not applied directly These retain their existing list-materialization path.

Reproduction

The baseline is commit b23b3c0. The candidate is the implementation represented by this record. The durable paired test is TestPostgreSQLRelationHasEndIndicesMatchLocal. With Go 1.27.1 and a PostgreSQL test container, run:

HFF_POSTGRES_CONTAINER=<container> go test -tags=integration ./backends/sql \
  -run '^TestPostgreSQLRelationHasEndIndicesMatchLocal$' -count=1

The test covered eight query forms over six fixtures, for 48 PostgreSQL/local comparisons. Cases included nonempty, empty, null, and missing relation state; a relation containing a null-valued item; negation; null observation; the has(-2) fallback; and an invalid Float index. The SQL package unit tests also passed.

The plain EXPLAIN diagnostic used empty temporary parent and item tables with a B-tree index on the child correlation key:

BEGIN;
CREATE TEMP TABLE hff_relation_parents (
    id bigint, items_present boolean, items_null boolean
);
CREATE TEMP TABLE hff_relation_items (parent_id bigint, value bigint);
CREATE INDEX hff_relation_items_parent_idx
    ON hff_relation_items (parent_id);
SET LOCAL enable_seqscan=off;
EXPLAIN SELECT records.id
FROM hff_relation_parents AS records
WHERE COALESCE(
    (CASE
      WHEN (records.items_present) IS NOT TRUE OR (records.items_null) IS TRUE
        THEN NULL::boolean
      ELSE EXISTS (
        SELECT 1 FROM hff_relation_items AS item
        WHERE item.parent_id=records.id
      )
    END),
    FALSE
);
ROLLBACK;

The empty-table plan used a hashed SubPlan with a Bitmap Heap Scan and Bitmap Index Scan on the child correlation index; it contained no aggregate or COUNT. Sequential scans were disabled for this diagnostic.

Results

No execution-time or allocation benchmark was collected. The plan only shows the shape selected for this empty-table fixture; it does not establish per-parent early termination, runtime speed, or plan selection for populated tables.

Correctness and tradeoffs

The paired fixtures preserve the relation's parent and relation presence/null behavior. Empty relations do not match either endpoint check; a null-valued item still makes the relation nonempty. Null or missing relations remain governed by their existing state expressions. Other constant indexes, including has(-2), and invalid Float indexes keep the previous cardinality/general path.

Decision and limits

Use the existence witness only for constant Int has(0) and has(-1) on a plain bound relation. For example, has(-2) remains on the general path. No unique order is needed for the optimized checks. The checked plan is not a timing result and does not predict plans for other schemas or data.

Explore HFF
Search documentation

Search the language specification and guides.