Skip to content

feat(scalars): add eql_v3.timestamptz encrypted-domain type (equality-only)#257

Merged
tobyhede merged 3 commits into
eql_v3from
v3-domain-type-timestamptz
Jun 9, 2026
Merged

feat(scalars): add eql_v3.timestamptz encrypted-domain type (equality-only)#257
tobyhede merged 3 commits into
eql_v3from
v3-domain-type-timestamptz

Conversation

@tobyhede

@tobyhede tobyhede commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What

Add eql_v3.timestamptz as an equality-only encrypted-domain scalar (storage + _eq via HMAC; = / <>). Ordering is deferred: cipherstash encrypts Plaintext::Timestamp at 12-block ORE width but EQL's only ORE comparator is 8-block, so an ordered domain would silently mis-order.

Rides the generalized harness (#261)

Rebased onto v3-scalar-harness-reduction, the per-type surface is +259 / 5 files (was +671 / 10). The whole type is:

  • catalog row (eql-scalars): ScalarKind::Timestamptz, Fixture::Timestamptz, EQ_ONLY_DOMAINS, the TIMESTAMPTZ spec + CATALOG append.
  • one temporal_values! call (scalar_domains.rs):
temporal_values! {
    cell = TIMESTAMPTZ_VALUES_CELL, accessor = timestamptz_values,
    rust_type = chrono::DateTime<chrono::Utc>, spec = eql_scalars::TIMESTAMPTZ,
    variant = Timestamptz, pg_type = "timestamptz",
    parse = |s| DateTime::parse_from_rfc3339(s).unwrap().with_timezone(&Utc),
    min_pivot = .., max_pivot = .., sql_lit = |v| format!("'{}'", v.to_rfc3339()),
}
  • one bare dispatch line (scalar_types.rs): timestamptz => chrono::DateTime<chrono::Utc>,
  • cast wiring (eql_plaintext.rs) + CHANGELOG.

No marker, no second snapshot, no macro change — the catalog's eq-only domain shape drives everything: the emitter picks scalar_matrix! { caps = [eq] }, and the inventory derives its eq-only name subset from the single baseline.

Status / verification

@coderabbitai

coderabbitai Bot commented Jun 3, 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: c15e0882-70a0-48e4-a2b5-fa3a7f5b1016

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 v3-domain-type-timestamptz

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.

@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch from 37dc457 to cea046f Compare June 3, 2026 09:10
@tobyhede tobyhede force-pushed the v3-domain-type-date branch from 3fa7497 to b8b8726 Compare June 3, 2026 10:58
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch from cea046f to ef32e5d Compare June 4, 2026 12:43
@tobyhede tobyhede force-pushed the v3-domain-type-date branch from b8b8726 to fd0bffc Compare June 4, 2026 12:44
Base automatically changed from v3-domain-type-date to eql_v3 June 4, 2026 23:06
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch 2 times, most recently from 7f489e8 to 55c19b8 Compare June 5, 2026 00:00
@tobyhede tobyhede changed the base branch from eql_v3 to v3-bounded-int-kind June 5, 2026 01:21
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch 3 times, most recently from 4a595ea to d21954f Compare June 5, 2026 01:53
Base automatically changed from v3-bounded-int-kind to eql_v3 June 5, 2026 04:52
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch from d21954f to 16ad2bb Compare June 5, 2026 12:38
@tobyhede tobyhede changed the base branch from eql_v3 to v3-scalar-harness-reduction June 5, 2026 12:38
Base automatically changed from v3-scalar-harness-reduction to eql_v3 June 8, 2026 22:44
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch from 16ad2bb to badaedf Compare June 8, 2026 23:07

@auxesis auxesis 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.

Nice works, thanks @tobyhede.

@auxesis auxesis 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.

Claude identified two gaps, which are posted inline.

There are two other gaps not posted inline:

  • to_sql_literal RFC3339 rendering is not unit-pinned. tests/sqlx/src/scalar_domains.rs:230 uses format!("'{}'", v.to_rfc3339()) — a new, timestamptz-specific path distinct from date's Display-based sql_lit. It's exercised transitively by the matrix (via fetch_fixture_payload), but no focused test pins the literal form. A one-liner — assert_eq!(<chrono::DateTime<chrono::Utc> as ScalarType>::to_sql_literal(Default::default()), "'1970-01-01T00:00:00+00:00'") — would lock it and catch a stray format change.
  • to_plaintext roundtrip only covers the epoch. datetime_utc_to_plaintext_wraps_in_timestamp_variant (eql_plaintext.rs) uses DateTime::<Utc>::default(); a value carrying a time-of-day (e.g. one of the …T23:20:50Z fixtures) would be a marginally stronger roundtrip, though the existing assert_eq!(value, ts) is already value-generic. Low priority.

Comment thread tests/sqlx/src/scalar_domains.rs
Comment thread crates/eql-scalars/src/lib.rs

@auxesis auxesis 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.

Missing tests need addressing.

tobyhede added a commit that referenced this pull request Jun 9, 2026
…ctness

Address PR #257 review feedback. The temporal_values! auto-generated tests
re-run the exact parse closure over all-UTC (`…Z`) catalog fixtures, so they
cannot catch a regression that drops the offset→UTC conversion, and fixture
distinctness is keyed by string upstream in eql-scalars (which is zero-dep, no
chrono) so two RFC3339 strings denoting the same UTC instant pass as distinct.

Add two harness-side guards alongside the timestamptz temporal_values! call:

- rfc3339_offset_is_normalized_to_utc: feeds an offset-bearing RFC3339 string
  and asserts it resolves to the same instant as the Z form (fails on a switch
  to .naive_utc()).
- fixtures_are_distinct_by_instant: dedups timestamptz_values() by parsed
  DateTime<Utc>, guarding the property the fixture table keys on.
tobyhede added 3 commits June 9, 2026 19:33
…-only)

Add the timestamptz scalar encrypted-domain type to the eql_v3 family as
EQUALITY-ONLY: storage + eql_v3.timestamptz_eq (= / <> via HMAC), no ord
domains, no MIN/MAX aggregates.

Ordering is deferred: cipherstash encrypts Plaintext::Timestamp at native
12-block ORE width, but EQL's only ORE comparator
(eql_v2.compare_ore_block_u64_8_256_term) is hardcoded to 8 blocks, so an
ordered timestamptz domain would silently mis-order. Ordering follows once a
wide-ORE (12-block) term lands.

- catalog: add EQ_ONLY_DOMAINS (storage + _eq); point TIMESTAMPTZ at it.
  Replace all_types_share_the_same_domain_shape with a shape-aware test
  (every type matches one of two known shapes) plus a pin of which token uses
  which shape.
- dispatch: extend the scalar_types! entry grammar with an optional [eq_only]
  marker; eq-only entries emit eq_only_scalar_matrix! instead of
  ordered_numeric_matrix!. ordered int4/int2/date emission is byte-identical.
- matrix: eq_only_scalar_matrix! now derives its three pivots from the
  ScalarType impl (like the ordered macro) instead of requiring explicit
  pivots — the first consumer wires cleanly with no per-call pivot authoring.
- inventory: make mise test:matrix:inventory shape-aware. Add the second
  canonical snapshot matrix_tests_eq_only.txt; each discovered type is
  compared against the snapshot matching its shape (ordered vs eq-only).
  Document the two-shape mechanism in snapshots/README.md. matrix_tests.txt
  is unchanged.
- CHANGELOG: timestamptz ships equality-only, ordering deferred.
…ctness

Address PR #257 review feedback. The temporal_values! auto-generated tests
re-run the exact parse closure over all-UTC (`…Z`) catalog fixtures, so they
cannot catch a regression that drops the offset→UTC conversion, and fixture
distinctness is keyed by string upstream in eql-scalars (which is zero-dep, no
chrono) so two RFC3339 strings denoting the same UTC instant pass as distinct.

Add two harness-side guards alongside the timestamptz temporal_values! call:

- rfc3339_offset_is_normalized_to_utc: feeds an offset-bearing RFC3339 string
  and asserts it resolves to the same instant as the Z form (fails on a switch
  to .naive_utc()).
- fixtures_are_distinct_by_instant: dedups timestamptz_values() by parsed
  DateTime<Utc>, guarding the property the fixture table keys on.
@tobyhede tobyhede force-pushed the v3-domain-type-timestamptz branch from fac889e to e0177f3 Compare June 9, 2026 09:34
@tobyhede tobyhede requested a review from auxesis June 9, 2026 10:11
@tobyhede tobyhede merged commit 49e6d01 into eql_v3 Jun 9, 2026
11 checks passed
@tobyhede tobyhede deleted the v3-domain-type-timestamptz branch June 9, 2026 23:20
tobyhede added a commit that referenced this pull request Jun 20, 2026
…ctness

Address PR #257 review feedback. The temporal_values! auto-generated tests
re-run the exact parse closure over all-UTC (`…Z`) catalog fixtures, so they
cannot catch a regression that drops the offset→UTC conversion, and fixture
distinctness is keyed by string upstream in eql-scalars (which is zero-dep, no
chrono) so two RFC3339 strings denoting the same UTC instant pass as distinct.

Add two harness-side guards alongside the timestamptz temporal_values! call:

- rfc3339_offset_is_normalized_to_utc: feeds an offset-bearing RFC3339 string
  and asserts it resolves to the same instant as the Z form (fails on a switch
  to .naive_utc()).
- fixtures_are_distinct_by_instant: dedups timestamptz_values() by parsed
  DateTime<Utc>, guarding the property the fixture table keys on.
tobyhede added a commit that referenced this pull request Jun 20, 2026
feat(scalars): add eql_v3.timestamptz encrypted-domain type (equality-only)
tobyhede added a commit that referenced this pull request Jun 22, 2026
…ctness

Address PR #257 review feedback. The temporal_values! auto-generated tests
re-run the exact parse closure over all-UTC (`…Z`) catalog fixtures, so they
cannot catch a regression that drops the offset→UTC conversion, and fixture
distinctness is keyed by string upstream in eql-scalars (which is zero-dep, no
chrono) so two RFC3339 strings denoting the same UTC instant pass as distinct.

Add two harness-side guards alongside the timestamptz temporal_values! call:

- rfc3339_offset_is_normalized_to_utc: feeds an offset-bearing RFC3339 string
  and asserts it resolves to the same instant as the Z form (fails on a switch
  to .naive_utc()).
- fixtures_are_distinct_by_instant: dedups timestamptz_values() by parsed
  DateTime<Utc>, guarding the property the fixture table keys on.
@tobyhede tobyhede mentioned this pull request Jun 22, 2026
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.

2 participants