Skip to content

feat(v3): float4/float8 encrypted-domain types#299

Merged
tobyhede merged 6 commits into
eql_v3from
eql_v3_float_domains
Jun 19, 2026
Merged

feat(v3): float4/float8 encrypted-domain types#299
tobyhede merged 6 commits into
eql_v3from
eql_v3_float_domains

Conversation

@tobyhede

@tobyhede tobyhede commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds IEEE-754 binary-float encrypted-domain coverage (real/float4 and double precision/float8) to the eql_v3 scalar surface, fully wired through codegen, the SQLx matrix oracle, and an edge-case regression suite. Implements the committed plan (docs/plans/2026-06-19-float-encrypted-domain-plan.md).

Both widths are ordered scalars reusing the existing four-domain shape, and both encrypt through a single f64 crypto path (Plaintext::Float(Some(x as f64))) — float4 vs float8 is purely a Postgres-surface distinction; the ciphertext/ORE term are byte-identical. Float is a new ScalarKind (F32/F64); the kind-agnostic codegen renderers generate the SQL with no codegen change (the flagged primary risk — confirmed a false alarm).

What's in here (one commit per task)

  • CatalogScalarKind::F32/F64, Fixture::Float, FLOAT4/FLOAT8 specs + invariant tests.
  • HarnessF4(f32)/F8(f64) newtypes (Ord via total_cmp, #[sqlx(transparent)]), value accessors via the shared lazy_values! macro, hand-written ScalarType/OrderedScalar/SignedScalar, guards (incl. an f32→f64 widening-monotonicity guard).
  • Crypto pathEqlPlaintext for F4/F8Plaintext::Float; Cast::REAL/DOUBLE, PlaintextSqlType::REAL/DOUBLE_PRECISION.
  • Routing — proc-macro is_float_token + float fixture discriminator, scalar_fixture! float arm, matrix dispatch lines.
  • Tests — fixture-oracle + e2e-oracle suites, sign-boundary tests, a cross-width byte-identity test (F4(x) and F8(x as f64) share hm/ob), and a float_special suite (NaN / ±0 / ±Inf) that encrypts fresh so NaN never enters the shared fixture table.
  • Artefacts/docs — committed tests/codegen/reference/{float4,float8}/ baselines, CHANGELOG entry, docs/upgrading/v2.4.md (U-001).

Verified locally (no DB required)

  • cargo test -p eql-scalars (71), cargo test -p eql-tests-macros (22, incl. 2 float tests)
  • cargo test -p eql_tests --lib float guards + EqlPlaintext float tests (11) + fixture-module spec tests
  • mise run test:matrix:inventoryfloat4 → ordered, float8 → ordered, catalog reconciled
  • mise run codegen:parity, mise run test:codegen (71), mise run clean && mise run build, mise run test:self_contained_v3
  • Full encrypted_domain binary compiles under --features proptest-e2e
  • Fixture generation through real cipherstash encryption (eql_v2_float4.sql/eql_v2_float8.sql, 13 rows each)

Deferred to CI (needs Postgres + ZeroKMS, unavailable locally)

The DB-backed runs — fixture/e2e oracles, sign-boundary, float_special, and the full matrix — run in CI. (Local Docker was unusable this session.)

Note: included one pre-existing fix

1f605a1f syncs matrix_tests_storage_only.txt with the storage_count_distinct_extractor arm that tests/sqlx/src/matrix.rs already emits — pre-existing drift on eql_v3 that blocked test:matrix:inventory on bool (unrelated to float). Regenerated via the documented command.

Summary by CodeRabbit

  • New Features
    • Added support for encrypted floating-point values via new eql_v3.float4 and eql_v3.float8 ordered encrypted-domain types.
    • Enabled equality and full comparison operations (<, <=, >, >=) on encrypted float columns.
    • Provided TypeScript type bindings and JSON schemas for float encrypted domains and their comparison variants.

tobyhede added a commit that referenced this pull request Jun 19, 2026
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f703fb56-c0ff-4f9b-8f5a-91d1cd0e1e1f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch eql_v3_float_domains

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/codegen/reference/float4/float4_ord_ore_operators.sql (1)

118-146: Add COMMUTATOR declarations to containment operators.

The @> and <@ operators are logical commutators—they express reciprocal containment relationships—but these operator overloads omit the COMMUTATOR metadata. This prevents the planner from inferring symmetry optimizations.

Suggested fix
 CREATE OPERATOR @> (
   FUNCTION = eql_v3.contains,
-  LEFTARG = eql_v3.float4_ord_ore, RIGHTARG = eql_v3.float4_ord_ore
+  LEFTARG = eql_v3.float4_ord_ore, RIGHTARG = eql_v3.float4_ord_ore,
+  COMMUTATOR = <@
 );

 CREATE OPERATOR <@ (
   FUNCTION = eql_v3.contained_by,
-  LEFTARG = eql_v3.float4_ord_ore, RIGHTARG = eql_v3.float4_ord_ore
+  LEFTARG = eql_v3.float4_ord_ore, RIGHTARG = eql_v3.float4_ord_ore,
+  COMMUTATOR = @>
 );

Note: This issue exists across all float operator baselines (float4/float8, all variants). Apply the same fix pattern consistently.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/codegen/reference/float4/float4_ord_ore_operators.sql` around lines 118
- 146, The CREATE OPERATOR statements for @> and <@ operators are missing
COMMUTATOR declarations that define their reciprocal relationships. Add
COMMUTATOR metadata to each operator: for the @> operator with LEFTARG =
eql_v3.float4_ord_ore and RIGHTARG = eql_v3.float4_ord_ore, add COMMUTATOR = <@,
and for the corresponding <@ operator add COMMUTATOR = @>. For the mixed-type
overloads (eql_v3.float4_ord_ore with jsonb), the @> operator with LEFTARG =
eql_v3.float4_ord_ore and RIGHTARG = jsonb should reference the <@ operator with
swapped argument types, and vice versa using the appropriate operator syntax to
specify argument type order. Apply this pattern consistently across all three
pairs of operator definitions in the diff.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/sqlx/src/scalar_domains.rs`:
- Around line 802-815: The F4 struct (and F8 at lines 833-846) derives standard
IEEE PartialEq while implementing Ord using total_cmp, which violates Rust trait
invariants. Remove PartialEq from the derive macro for both F4 and F8 structs,
then implement a custom PartialEq for each that is consistent with their Ord
implementations by using total_cmp for equality comparisons instead of the
default IEEE semantics.

---

Nitpick comments:
In `@tests/codegen/reference/float4/float4_ord_ore_operators.sql`:
- Around line 118-146: The CREATE OPERATOR statements for @> and <@ operators
are missing COMMUTATOR declarations that define their reciprocal relationships.
Add COMMUTATOR metadata to each operator: for the @> operator with LEFTARG =
eql_v3.float4_ord_ore and RIGHTARG = eql_v3.float4_ord_ore, add COMMUTATOR = <@,
and for the corresponding <@ operator add COMMUTATOR = @>. For the mixed-type
overloads (eql_v3.float4_ord_ore with jsonb), the @> operator with LEFTARG =
eql_v3.float4_ord_ore and RIGHTARG = jsonb should reference the <@ operator with
swapped argument types, and vice versa using the appropriate operator syntax to
specify argument type order. Apply this pattern consistently across all three
pairs of operator definitions in the diff.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 890727e5-db03-4ac5-bd71-2e15200e77c0

📥 Commits

Reviewing files that changed from the base of the PR and between 302a5f1 and c20b8a4.

📒 Files selected for processing (61)
  • CHANGELOG.md
  • crates/eql-scalars/src/fixture.rs
  • crates/eql-scalars/src/kind.rs
  • crates/eql-scalars/src/lib.rs
  • crates/eql-scalars/src/proptest_invariants.rs
  • crates/eql-scalars/src/tests.rs
  • crates/eql-tests-macros/src/lib.rs
  • crates/eql-types/bindings/v3/Float4.ts
  • crates/eql-types/bindings/v3/Float4Eq.ts
  • crates/eql-types/bindings/v3/Float4Ord.ts
  • crates/eql-types/bindings/v3/Float4OrdOre.ts
  • crates/eql-types/bindings/v3/Float8.ts
  • crates/eql-types/bindings/v3/Float8Eq.ts
  • crates/eql-types/bindings/v3/Float8Ord.ts
  • crates/eql-types/bindings/v3/Float8OrdOre.ts
  • crates/eql-types/schema/v3/float4.json
  • crates/eql-types/schema/v3/float4_eq.json
  • crates/eql-types/schema/v3/float4_ord.json
  • crates/eql-types/schema/v3/float4_ord_ore.json
  • crates/eql-types/schema/v3/float8.json
  • crates/eql-types/schema/v3/float8_eq.json
  • crates/eql-types/schema/v3/float8_ord.json
  • crates/eql-types/schema/v3/float8_ord_ore.json
  • crates/eql-types/src/v3/float4.rs
  • crates/eql-types/src/v3/float8.rs
  • crates/eql-types/src/v3/mod.rs
  • docs/plans/2026-06-19-float-encrypted-domain-plan.md
  • docs/upgrading/v2.4.md
  • tests/codegen/reference/float4/float4_eq_functions.sql
  • tests/codegen/reference/float4/float4_eq_operators.sql
  • tests/codegen/reference/float4/float4_functions.sql
  • tests/codegen/reference/float4/float4_operators.sql
  • tests/codegen/reference/float4/float4_ord_aggregates.sql
  • tests/codegen/reference/float4/float4_ord_functions.sql
  • tests/codegen/reference/float4/float4_ord_operators.sql
  • tests/codegen/reference/float4/float4_ord_ore_aggregates.sql
  • tests/codegen/reference/float4/float4_ord_ore_functions.sql
  • tests/codegen/reference/float4/float4_ord_ore_operators.sql
  • tests/codegen/reference/float4/float4_types.sql
  • tests/codegen/reference/float8/float8_eq_functions.sql
  • tests/codegen/reference/float8/float8_eq_operators.sql
  • tests/codegen/reference/float8/float8_functions.sql
  • tests/codegen/reference/float8/float8_operators.sql
  • tests/codegen/reference/float8/float8_ord_aggregates.sql
  • tests/codegen/reference/float8/float8_ord_functions.sql
  • tests/codegen/reference/float8/float8_ord_operators.sql
  • tests/codegen/reference/float8/float8_ord_ore_aggregates.sql
  • tests/codegen/reference/float8/float8_ord_ore_functions.sql
  • tests/codegen/reference/float8/float8_ord_ore_operators.sql
  • tests/codegen/reference/float8/float8_types.sql
  • tests/sqlx/snapshots/matrix_tests_storage_only.txt
  • tests/sqlx/src/fixtures/eql_plaintext.rs
  • tests/sqlx/src/fixtures/scalar_fixture.rs
  • tests/sqlx/src/lib.rs
  • tests/sqlx/src/scalar_domains.rs
  • tests/sqlx/src/scalar_types.rs
  • tests/sqlx/tests/encrypted_domain.rs
  • tests/sqlx/tests/encrypted_domain/float_special.rs
  • tests/sqlx/tests/encrypted_domain/property/e2e_oracle.rs
  • tests/sqlx/tests/encrypted_domain/property/fixture_oracle.rs
  • tests/sqlx/tests/encrypted_domain/signed.rs

Comment thread tests/sqlx/src/scalar_domains.rs Outdated
tobyhede added 4 commits June 19, 2026 20:06
float4/float8 ScalarSpec rows (Float kind/fixture) in eql-scalars::CATALOG
and the committed codegen reference baselines the generator parity gate
checks against.
float4/float8 v3 domain payload types in eql-types, with the generated
TypeScript bindings and JSON Schemas for each domain variant.
Fixture routing in the matrix proc-macro plus the float4/float8 arms of the
fixture/e2e oracle suites, the sign-boundary monotonicity sweep, the
float_special NaN/+/-0/+/-Inf regression suite, and the storage-only matrix
snapshot.
CHANGELOG Added entry for the float4/float8 families, with the IEEE-754
caveats (NaN ordering, +/-0 equality, f64 widening) folded inline. No
docs/upgrading/ note: this is additive eql_v3, not an eql_v2 release.
@tobyhede tobyhede force-pushed the eql_v3_float_domains branch from c20b8a4 to f299ecd Compare June 19, 2026 10:07
tobyhede added 2 commits June 19, 2026 20:08
…N caveat, order tripwire

- eql-scalars: correct the FLOAT4_FIXTURES comment — the values are dyadic
  rationals (n/2^k), not 'powers of two and halves'; add a keep-it-dyadic
  warning so a non-f32-exact fixture (e.g. 0.1) can't silently desync the oracle.
- eql-types: document NaN/-0.0/+-Inf special-value behaviour on the float8
  module (and point float4 at it) — NaN is never rejected server-side, so the
  caller-facing 'reject NaN client-side' guidance lives next to the types.
- float_special: add nan_order_position_is_deterministic_and_total, a tripwire
  locking the total+deterministic order the Block-ORE index relies on (without
  pinning NaN's unspecified direction).
- Drop the dangling reference to the removed U-001 upgrade note.
Derived IEEE PartialEq (NaN != NaN, +0.0 == -0.0) was inconsistent with the
manual Eq/Ord impls built on total_cmp (NaN == NaN, +0.0 != -0.0), breaking
Eq's reflexivity contract and Ord/PartialEq equality agreement.
@tobyhede tobyhede merged commit a2a31f6 into eql_v3 Jun 19, 2026
16 checks passed
@tobyhede tobyhede deleted the eql_v3_float_domains branch June 19, 2026 12:35
tobyhede added a commit that referenced this pull request Jun 20, 2026
feat(v3): float4/float8 encrypted-domain types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant