Skip to content

Range operators on eql_v2_encrypted use incorrect selectivity functions (scalarltsel on > and >=) #216

Description

@coderdan

Summary

src/operators/>.sql and src/operators/>=.sql declare every CREATE OPERATOR with RESTRICT = scalarltsel, JOIN = scalarltjoinsel. Those are the "less-than" selectivity estimators. PostgreSQL ships symmetric estimators that should be used instead:

Operator Should be
> RESTRICT = scalargtsel, JOIN = scalargtjoinsel
>= RESTRICT = scalargesel, JOIN = scalargejoinsel

The inner ore_block_u64_8_256 operators on the underlying domain type are declared correctly (src/ore_block_u64_8_256/operators.sql uses scalargtsel / scalargejoinsel), so the inconsistency is only at the eql_v2_encrypted outer layer.

Impact

Wrong selectivity estimates feed the planner inaccurate row counts for > and >= predicates. Symptoms:

  • Index-vs-seq-scan flips on the wrong threshold for range queries.
  • Join order chosen on bad cardinality assumptions.
  • ORDER BY + LIMIT plans can pick the wrong access path when the planner thinks WHERE col > $1 is selective when it isn't (or vice versa).

The bug is silent until cardinality matters. With the range-operator inlining in #211, bare-form range queries now structurally match functional ORE indexes, which makes selectivity hints load-bearing for plan choice — so the cost of leaving this wrong is higher than it was pre-2.3.

Scope

Three CREATE OPERATOR blocks in each of src/operators/>.sql and src/operators/>=.sql (six total), plus regenerated release/ artefacts. No behaviour change for individual query results — only planner estimates. No upgrade note needed.

Detected by

CodeRabbit on #211 review. PR scope was operator inlining, so this was deferred.

Verification

Compare EXPLAIN ANALYZE plans on a 100k-row Block ORE column for WHERE col > $1 (high-selectivity vs. low-selectivity bounds) before/after the change; expected row estimates should track actual within a constant factor.

Metadata

Metadata

Assignees

Labels

EQLbugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions