Skip to content

refactor(eql-domains): move kind/fixtures off DomainFamily into TypeFixtures records - #326

Merged
tobyhede merged 3 commits into
eql_v3from
pr3-domain-fixtures-module-split
Jun 29, 2026
Merged

refactor(eql-domains): move kind/fixtures off DomainFamily into TypeFixtures records#326
tobyhede merged 3 commits into
eql_v3from
pr3-domain-fixtures-module-split

Conversation

@tobyhede

@tobyhede tobyhede commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Slims eql_domains::DomainFamily to a purely-structural { name, domains } by moving the kind and fixtures concern into a dedicated fixture-layer record (TypeFixtures), keeping one crate with a clean one-way fixtures → catalog dependency, and preserving byte-for-byte output (SQL / TS / JSON / dump-catalog).

  • DomainFamily is now exactly { name: &'static str, domains: &'static [Domain] }kind/fixtures removed as fields.
  • New fixtures module owns the fixture vocabulary: ScalarKind, BoundedIntKind, Fixture, the fixtures!/int_values!/text_values! macros, the *_VALUES consts, and a per-type TypeFixtures { family: &DomainFamily, kind, values } record (INT4_FIXTURESFLOAT8_FIXTURES) plus a FIXTURES table mirroring CATALOG order.
  • The old struct-enforced 1:1 between a catalog row and its kind/fixtures is replaced by a compile-time const parity block in fixtures/record.rs (assert!(FIXTURES.len() == CATALOG.len()) + name/order check via a const fn str_eq). It const-evaluates on every cargo build and fails the build with error[E0080] on a missing/misaligned record — it cannot be #[cfg]-gated or filtered out, unlike a runtime test.
  • All .kind/.fixtures readers rewired: eql-domains tests, eql-tests-macros kind-predicates (new fixtures_for_token), and tests/sqlx/src/scalar_domains.rs macros/inline readers.

All public crate-root paths are preserved via pub use fixtures::{…} re-exports; *_VALUES keep identical names and types. PR 4 (bindings) reads only name/domains/terms/ENVELOPE_KEYS, so it is unaffected.

This supersedes the spec's separate eql-fixtures crate extraction (a crate adds a manifest/build-edge and cycle risk for no benefit, since the dependency is one-way) and the earlier fields-on-DomainFamily draft (those fields are removed, not retained).

Scope of the const block (no overclaim)

The const _ block proves name + order coverage only. Fixture-VALUE correctness stays gated by the in-crate value/invariant tests (values_tests, bounds/distinctness/pivot/kind-pairing invariant_tests/float_tests/catalog_tests) plus a verbatim-move literal diff.

Verification (all DB-free / creds-free)

  • mise run test:crates — fmt + clippy -D warnings + tests for all four lean crates ✅
  • mise run codegen:parity — generated SQL byte-identical to committed references ✅
  • mise run types:check — TS bindings + JSON schemas, no git diff ✅
  • mise run test:matrix:inventory — tests/sqlx matrix compiles with rewired macros; catalog reconciled ✅
  • cargo run -p eql-codegen -- dump-catalog | shasum — digest identical pre/post ✅
  • Verbatim-move literal diff — fixture literal multiset byte-identical pre/post ✅
  • mise run test:matrix:expand{int4,text,bool}_expanded.rs snapshots stable (macro emits byte-identical tokens) ✅

Notes

  • Internal refactor with no user-facing change (no SQL / binding / operator / error-message change; dump-catalog byte-identical), so per the changelog discipline no CHANGELOG.md entry is added.
  • One fix beyond the plan's enumeration: eql-tests-macros's unknown_token_fails_loudly #[should_panic] message updated from CATALOG to FIXTURESis_temporal_token now legitimately panics via the FIXTURES lookup; the loud-failure behavior is preserved.

Summary by CodeRabbit

  • Refactor

    • Reorganized the app’s scalar/fixture handling into a clearer structure, with shared type data and generated values now managed consistently across the codebase.
    • Simplified type metadata so core catalog entries are more focused and easier to maintain.
  • Bug Fixes

    • Improved validation for generated integer and text values, helping catch out-of-range or mismatched fixture data earlier.
    • Tightened consistency checks so type-specific values stay aligned with their catalog entries.
  • Tests

    • Updated automated checks to cover the new fixture and value layout.

…ixtures records

Slim DomainFamily to structural { name, domains }; relocate the fixture
vocabulary (ScalarKind, BoundedIntKind, Fixture, fixtures!/int_values!/
text_values!, *_VALUES) into a fixtures module, and pair each catalog row with
its kind+values via a per-type TypeFixtures record + FIXTURES table. The old
struct-enforced 1:1 is replaced by a compile-time const parity block
(FIXTURES mirrors CATALOG by name+order, checked on every build).
Behaviour-preserving: generated SQL/TS/JSON and dump-catalog are
byte-identical; no fixture value changes. Supersedes the spec's eql-fixtures
crate extraction and the earlier fields-on-struct draft.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

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: 1dd7a8af-7064-4d72-9498-4aa5e222377e

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:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr3-domain-fixtures-module-split

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.

… kind guard, doc fix

- Add str_eq_tests::str_eq_matches_iff_byte_identical: the parity guard's
  only new logic was exercised solely on the matching path against aligned
  data, so a str_eq bug (true on length-equal-but-differing bytes) would
  silently neuter it. Pin equal/length-diff/one-byte-diff cases. (#2)
- Add catalog_tests::every_record_kind_matches_its_family: a catalog-wide
  family.name -> kind guard over EVERY record (the parity block checks only
  name+length, so a swapped kind like { family: &INT8, kind: I16 } would
  otherwise pass). Extends the int-only test to all 10 kinds. (#1)
- Align ScalarKind::Timestamptz doc with Date: accessors are unreachable by
  construction (as_bounded_int() -> None), not 'panic'. (#3)
@tobyhede
tobyhede changed the base branch from main to eql_v3 June 29, 2026 03:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@crates/eql-domains/src/fixtures/kind.rs`:
- Around line 5-8: Update the documentation in Kind’s fixture comments to
enumerate all non-integer variants now present in the enum. The current
docstrings on the Kind accessors and related comments still mention only
Numeric/Text/Jsonb/Date or “the others”; revise those descriptions to include
Timestamptz, Bool, F32, and F64 as non-integer kinds, keeping the wording
exhaustive and consistent with Kind and its fixed-width integer accessors.

In `@crates/eql-domains/src/tests.rs`:
- Around line 879-907: Move the `family.name` ↔ `kind` invariant out of
`every_record_kind_matches_its_family` and enforce it in the fixture layer so
`fixtures_for_token(token).kind` cannot diverge at compile time. Update the
`TypeFixtures` construction/parity path in the fixtures definitions to either
derive `kind` directly from `family` or add a const-time check that binds them
together, then keep the test as a secondary safety net if needed. Focus on the
`TypeFixtures` records and the macro-facing lookup used by
`crates/eql-tests-macros/src/lib.rs` so mismatches are caught before expansion.
🪄 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: 84c5060c-883b-4722-b83a-9665b6f9c8cc

📥 Commits

Reviewing files that changed from the base of the PR and between 155bb47 and 1b5a74c.

📒 Files selected for processing (10)
  • crates/eql-domains/src/fixture.rs
  • crates/eql-domains/src/fixtures/fixture.rs
  • crates/eql-domains/src/fixtures/kind.rs
  • crates/eql-domains/src/fixtures/mod.rs
  • crates/eql-domains/src/fixtures/record.rs
  • crates/eql-domains/src/fixtures/values.rs
  • crates/eql-domains/src/lib.rs
  • crates/eql-domains/src/tests.rs
  • crates/eql-tests-macros/src/lib.rs
  • tests/sqlx/src/scalar_domains.rs
💤 Files with no reviewable changes (1)
  • crates/eql-domains/src/fixture.rs

Comment thread crates/eql-domains/src/fixtures/kind.rs Outdated
Comment on lines +5 to +8
/// The fixed-width integer kinds — exactly those scalar kinds with an `i128`
/// range and `MIN`/`MAX`/`Zero` sentinels. These accessors are **total**: every
/// variant answers every method. Non-integer kinds (`Numeric`/`Text`/`Jsonb`/
/// `Date`) are simply not representable here, so there is no partial function to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Keep the non-integer kind docs exhaustive.

The docs still describe non-integers as only Numeric/Text/Jsonb/Date or “the others” as Numeric/Text/Jsonb, but the enum now includes Timestamptz, Bool, F32, and F64 too.

Suggested doc update
-/// variant answers every method. Non-integer kinds (`Numeric`/`Text`/`Jsonb`/
-/// `Date`) are simply not representable here, so there is no partial function to
+/// variant answers every method. Non-integer kinds (`Numeric`/`Text`/`Jsonb`/
+/// `Date`/`Timestamptz`/`Bool`/`F32`/`F64`) are simply not representable here,
+/// so there is no partial function to
@@
-/// the others (`Numeric`/`Text`/`Jsonb`) have string fixtures and no numeric
-/// range — though `Numeric`/`Text` are still ORE-orderable, only `Jsonb` is not.
+/// non-integer kinds have no fixed-width integer range. `Numeric`/`Text`/
+/// `Date`/`Timestamptz`/`F32`/`F64` are ordered where their catalog rows include
+/// ORE, `Jsonb` is not ordered, and `Bool` is storage-only.

Also applies to: 19-21

🤖 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 `@crates/eql-domains/src/fixtures/kind.rs` around lines 5 - 8, Update the
documentation in Kind’s fixture comments to enumerate all non-integer variants
now present in the enum. The current docstrings on the Kind accessors and
related comments still mention only Numeric/Text/Jsonb/Date or “the others”;
revise those descriptions to include Timestamptz, Bool, F32, and F64 as
non-integer kinds, keeping the wording exhaustive and consistent with Kind and
its fixed-width integer accessors.

Comment on lines +879 to +907
/// Catalog-wide `family.name` ↔ `kind` guard over EVERY record, not just the
/// integer ones. `TypeFixtures` carries `family` and `kind` as independent
/// fields, and the compile-time parity block checks only `family.name` +
/// length — so `TypeFixtures { family: &INT8, kind: I16, .. }` would compile
/// and the parity block would pass. This test is the single guard that binds
/// every record's `kind` to the kind its family is supposed to map onto, for
/// all kinds (the non-integer kinds are otherwise only checked by individual
/// `*_spec` tests). A mismatched or swapped `kind` fails here.
#[test]
fn every_record_kind_matches_its_family() {
for rec in FIXTURES {
let expected = match rec.family.name {
"int2" => ScalarKind::I16,
"int4" => ScalarKind::I32,
"int8" => ScalarKind::I64,
"date" => ScalarKind::Date,
"timestamptz" => ScalarKind::Timestamptz,
"numeric" => ScalarKind::Numeric,
"text" => ScalarKind::Text,
"bool" => ScalarKind::Bool,
"float4" => ScalarKind::F32,
"float8" => ScalarKind::F64,
other => panic!("unmapped scalar token {other} in FIXTURES"),
};
assert_eq!(
rec.kind, expected,
"{} record carries the wrong kind",
rec.family.name
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Promote the familykind check out of the test suite.

This test is currently the only place that binds TypeFixtures.kind to family.name, but the production predicates in crates/eql-tests-macros/src/lib.rs now branch on fixtures_for_token(token).kind. That means a mismatched kind still compiles, passes the const parity block, and changes macro expansion unless this test suite runs. Please move this invariant into the fixture-layer const parity guard, or derive kind from family instead of storing it twice.

🤖 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 `@crates/eql-domains/src/tests.rs` around lines 879 - 907, Move the
`family.name` ↔ `kind` invariant out of `every_record_kind_matches_its_family`
and enforce it in the fixture layer so `fixtures_for_token(token).kind` cannot
diverge at compile time. Update the `TypeFixtures` construction/parity path in
the fixtures definitions to either derive `kind` directly from `family` or add a
const-time check that binds them together, then keep the test as a secondary
safety net if needed. Focus on the `TypeFixtures` records and the macro-facing
lookup used by `crates/eql-tests-macros/src/lib.rs` so mismatches are caught
before expansion.

…e time

Address PR review:
- Hoist the family.name <-> kind invariant into the compile-time parity
  block (kind_tag/expected_kind in fixtures/record.rs) so a mismatched
  TypeFixtures.kind fails the eql-domains build before any consumer
  (incl. eql-tests-macros expansion) reads FIXTURES; keep the runtime
  test as a secondary safety net.
- Make the ScalarKind/BoundedIntKind non-integer-kind docs exhaustive
  (add Timestamptz/Bool/F32/F64; fix stale ORE-orderability wording).
- Fix stale BOOL.fixtures -> BOOL_FIXTURES.values doc comment.
@tobyhede
tobyhede merged commit 0878e06 into eql_v3 Jun 29, 2026
18 checks passed
@tobyhede
tobyhede deleted the pr3-domain-fixtures-module-split branch June 29, 2026 04:33
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