017. Emit direct predicates for simple JSONB String-list any() callbacks

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

Problem and mechanism

A simple any() callback over a directly bound JSONB List<String> can be lowered through several projections even when the callback only compares its element with a literal String. For this shape, the implementation recognizes a callback body that is exactly equality between its bound element and a literal String, in either operand order, then uses the same JSONB containment predicate as direct contains():

tags:any(tag=>tag="auth")
("records"."tags" IS NOT NULL AND
  "records"."tags" @> jsonb_build_array(($1::text)))

Eligibility uses resolved binding identity, not variable spelling. A callback parameter may shadow an outer variable and still qualify when the equality uses the callback's own parameter. For example, tags:any(name=>name="auth") name="Alice" can use the direct path. If the equality instead refers to a captured or outer binding, it retains the general lowering.

Applicability

Execution profile Status Reason
Direct JSONB List<String> with item-equals-literal callback Applied Lowers to containment without projection barriers.
Nullable direct JSONB list with the same callback Applied The predicate retains the container null check.
Captured/outer binding, complex body, guards, type observation, null literal, or other representation Not applied Retains general callback lowering.

Reproduction

The SQL-shape comparison uses tags:any(tag=>tag="auth") and the direct physical binding of tags to JSONB column records.tags, declared as List<String>. The baseline is commit c5d6fed; the implementation is commit 8ad3fd9. The code is in backends/sql/direct_jsonb_membership.go, backends/sql/scalar_where.go, and its focused tests. The reported lengths count generated WHERE expression characters; barriers count OFFSET 0 projections. Both forms bind one text parameter.

Targeted unit and local/PostgreSQL parity tests passed for callback binding identity, captures and shadowing, null/presence behavior, negation and boolean composition, NUL rejection, and fallback observations. Full go test ./..., go vet ./..., go vet -tags=integration ./backends/sql, and independent critical review passed.

Results

HFF filter Prior WHERE length / barriers / parameters Direct WHERE length / barriers / parameters
tags:any(tag=>tag="auth") 884 characters / 7 / 1 84 characters / 0 / 1

Plain EXPLAIN with default planner settings on the empty temporary fixture selected a Bitmap Index Scan with both jsonb_ops and jsonb_path_ops, using the same @> index condition as contains(). This plan observation is fixture-specific; no EXPLAIN ANALYZE or execution timing was collected, so it does not establish a runtime speedup.

Correctness and tradeoffs

Eligibility is restricted to the directly bound physical JSONB List<String> and an equality callback that compares the actual callback item binding to a literal String. A callback parameter may shadow an outer variable; the resolved binding determines whether the direct path applies. Comparisons that use a captured or outer binding, extra callback operations, guards, type observations, null literals, metadata-backed values, plain JSON, dynamic lists, and other element types retain the general lowering. Targeted parity checks cover callback binding identity, nullable receivers, boolean composition, and ineligible fallback shapes.

Decision and limits

The implementation changes SQL construction only for the exact equality-callback shape above. It does not rewrite arbitrary callbacks or promise PostgreSQL short-circuiting, index selection, or execution speed. Validate generated SQL and plans against representative indexed tables before relying on index use.

Explore HFF
Search documentation

Search the language specification and guides.