SLOPE: Planner Optimizations on Monotonic Expressions — May 2026 Summary
Overview
The SLOPE patch enables PostgreSQL's planner to recognize that monotonic transformations of indexed columns preserve sort order, eliminating unnecessary Sort nodes and enabling streaming GroupAggregate and MinMax rewrites. May 2026 saw limited but high-impact activity: closure of one correctness issue (NULL handling) immediately followed by discovery of a deeper correctness problem (IEEE-754 floats), which forced a reconceptualization of the safety model for slope tagging.
Key Developments
NULL Handling Validated (May 8)
Zsolt Parragi confirmed that Alexandre's exhaustive 32-case NULLS FIRST/LAST test grid and the associated fix are correct, closing out the NULL-placement correctness pitfall from April.
IEEE-754 Infinity/NaN Breaks Float Monotonicity (May 8)
Zsolt demonstrated that x * 'Infinity'::float8 violates monotonicity because 0 * Inf = NaN, and PostgreSQL sorts NaN last regardless of sort direction. An index scan on x emits the NaN-producing row in the middle of the stream, while a Sort-based plan places it at the end — a plan-dependent result difference (correctness bug).
This generalizes: any float multiplication/division where one operand is ±Inf can manufacture NaN from a finite input, breaking the ordering guarantee.
Empirical Corner-Case Enumeration (May 10)
Alexandre responded with slope_corner_cases.sql, an exhaustive regression test mapping six sentinel float values (-inf, -1, 0, 1, +inf, nan) through all relevant expression/direction combinations. The violations collapse to two families:
-
Arithmetic with an infinite constant — addition, multiplication, and division with
±Infproduce NaN from finite inputs. Exception:x - Infis safe (NaN only arises from already-infinite input). -
Decreasing functions on NaN-bearing types — PostgreSQL fixes NaN placement as "last under ASC" regardless of sort direction. A descending slope would need NaN first to match reverse-index traversal, but the sort operator cannot be made to cooperate. This means the
reverse_sort/nulls_firsttoggle logic is insufficient for float types even for mathematically monotonic functions like unary minus.
Emerging Design Principle
A pattern is now clear across three independent correctness failures (intervals, Inf/NaN, decreasing-on-NaN-types): slope tagging is unsafe wherever the type's comparison semantics are not a strict homomorphism of the operator's arithmetic. The "tag by pg_proc OID alone" model is demonstrably insufficient; value-level guards (inspecting constant operands at plan time) and type-level guards (detecting non-NULL sentinels with fixed placement) are prerequisites for correctness.
Proposed Resolution
Alexandre proposes surgical disablement: suppress the slope optimization when (a) a float arithmetic op has a non-finite constant operand, or (b) the composed slope is SLOPE_DESC on a NaN-bearing type. This preserves the common cases (ts * 1000, x + 1.0) while excluding the pathological ones.
Partial-Domain Functions
Alexandre raised whether domain-restricted functions like sqrt(x) (which raises an error for x < 0 rather than returning NaN) can be safely tagged monotonic. The reasoning parallels integer overflow: an error terminates the query rather than producing misordered results. This likely generalizes to ln, log, acos, etc., but requires case-by-case audit since some float wrappers historically return NaN rather than erroring.
Status
The patch targets PG20. No committer engaged in May. The correctness model is maturing — from naive per-function tagging toward a layered system with function-level, value-level, and type-level guards — but the implementation has not yet caught up to the conceptual framework. The value-dependent slope inspection pattern (needed for both left(str, n) and float Inf guards) is increasingly a prerequisite rather than a follow-up.