023. Lower PostgreSQL Float work with the native approximate model

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

Problem and mechanism

After scalar comparisons stopped round-tripping values through JSON, the PostgreSQL Float path still used a custom underflow decoder and exact formatting and arithmetic emulation. This step removes those mechanisms in favor of PostgreSQL's native Float model: double precision for ordinary operations and checked numeric fallback for extreme arithmetic magnitudes.

The change preserves Int/Float subtype markers, exact Int operations, exact mixed Int/Float comparisons, null behavior for invalid operations, and JSONB metadata requirements where storage lost an observable Float representation. It does not make Float results or decimal text identical to the Local backend.

Applicability

Workload Status Reason
Dynamic scalar Float self-comparison Applied Consume Float values through PostgreSQL's native model without canonical JSON round-trips.
Dynamic Float/Int ordering Applied Use the native Float result model while retaining exact mixed numeric ordering.
Float arithmetic, parsing, rounding, and output Applied Follow the Float profile and checked extreme-value conversion rules.
Int-only operations and exact mixed numeric comparison Not changed These retain their existing exact contracts.
Structural Float sort keys Not changed Some structural sort paths still use exact decomposition.

Reproduction

The SQL-shape baseline is commit 88c545c. The focused pair fixtures use schema-known JSONB fields whose possible values are String|Float and String|Float versus String|Int. The Float schema fixes the numeric subtype in these shape cases; additional parity fixtures exercise native JSON and metadata-backed JSONB, including signed zero and boundary values.

The implementation is covered by the repository unit and vet suites, focused PostgreSQL/local Float comparison and serialization tests, native Float boundary tests, and JSON structural precision regressions. Plain plans were inspected without ANALYZE; no timing or benchmark was collected. The focused commands are:

GOTOOLCHAIN=go1.27.1 go test ./...
GOTOOLCHAIN=go1.27.1 go vet ./...
HFF_POSTGRES_CONTAINER=<container> GOTOOLCHAIN=go1.27.1 go test -tags=integration ./backends/sql -run 'TestPostgreSQL(NativeFloatModel|NativeFloatAndBytesInMatchesLocal|NativeFloatStructuralPrecision|JSONFloatUnderflow|FloatArithmetic|NumericRounding|PrimitiveStringConversions|StrictJSONParsing|SharedScalarConformance|DynamicJSONPairs|SchemaKnownDynamicPairs)$' -count=1

Results

Filter Baseline WHERE bytes / barriers Native-model WHERE bytes / barriers
fchoice=fchoice, `String Float` 6,570 / 16
fchoice<choice, `String FloatvsString Int`

For the fchoice=fchoice plan, the baseline had 34 plan lines, 13 nested-loop nodes, and no generate_series function scan. The candidate had 10 plan lines, 3 nested-loop nodes, and no generate_series scan. These are plan-structure observations, not execution-time or speed claims.

Correctness and tradeoffs

The focused suites include 3,528 PostgreSQL native-rounding results, the 2,016-case dynamic-pair matrix, 208 physical-spelling checks, 324 canonical JSON controls, native arithmetic scopes, 23 Float boundary/session cases, and eight structural precision regressions. Additional coverage includes 4,559 strict JSON parsing cases, 8,262 primitive string-conversion cases, and 87 shared scalar-conformance cases. Int behavior, exact mixed comparisons, subtype markers, and JSONB representability checks remain covered separately.

Native Float semantics can differ at rounding boundaries and in decimal text. The PostgreSQL JSON text transport requires extra_float_digits > 0; HFF does not set or inspect this session setting. Applications must satisfy the backend's Float profile requirements.

Decision and limits

The PostgreSQL backend uses its declared native Float model for the supported Float operations. This record makes no runtime-speed claim. Exact Float decomposition remains in some structural sorting code; the decision does not claim that every SQL path has eliminated it.

Explore HFF
Search documentation

Search the language specification and guides.