Skip to content

fix(codegen): map postgres range columns to PgRange for oxide format - #25

Draft
Mattt (aevv) wants to merge 1 commit into
mattt/emit-uuid-import-in-oxide-codegenfrom
mattt/map-postgres-ranges-in-oxide-codegen
Draft

fix(codegen): map postgres range columns to PgRange for oxide format#25
Mattt (aevv) wants to merge 1 commit into
mattt/emit-uuid-import-in-oxide-codegenfrom
mattt/map-postgres-ranges-in-oxide-codegen

Conversation

@aevv

@aevv Mattt (aevv) commented Aug 23, 2026

Copy link
Copy Markdown

Stacked on #24 — review that one first; this PR's diff is the second commit only, and its base retargets to oxide-codegen once #24 merges.

Range columns generate a struct that compiles and then fails to decode. sea-schema surfaces them as ColumnType::Custom, which write_rs_type renders as String — correct for the standard format, where get_col_type_attrs pairs it with select_as = "text", but the oxide format decodes straight into the model struct via sqlx::FromRow:

ColumnDecode { index: "range", source: "mismatched types; Rust type
  `Option<String>` (as SQL type `TEXT`) is not compatible with SQL type `NUMRANGE`" }

This is latent rather than live: bin_table_data.bin_range has been an int8range generating as Option<String> for a while, but oxide never hits it because ev_db hand-writes its own BinTableData with Option<PgRange<i64>> — plausibly because the generated one was unusable. This PR makes the generated type match that hand-written one, so the workaround can eventually go away.

All six range types now render as sqlx's PgRange, honouring --date-time-crate for the temporal ones.

Two constraints shape the output:

  • PgRange implements neither Serialize nor Deserialize, and serde has no impls for std::ops::Bound, so there is nothing to derive. Range fields carry #[serde(skip)]; skipping needs Default to deserialize, so they are always Option regardless of nullability. This matches existing practice — the hand-written BinTableData derives no serde at all — but it does mean a range is silently absent from JSON rather than failing loudly. If a consumer ever needs it serialized, the fix is to emit a representation here rather than to un-skip.
  • BigDecimal implements only PartialEq, so an entity holding a numrange cannot derive Eq. get_oxide_eq_needed handles that the way get_eq_needed already does for floats. Ranges over Eq element types keep the derive.

Verified by regenerating evervault/common-specs against a live Postgres and reading a real numrange row back into the generated struct.

The three pre-existing sea-orm-codegen --lib failures (test_get_info, test_get_rs_type_with_chrono, test_gen_postgres) are the Json mapping ones already noted in #24, unrelated to this change.

🤖 Generated with Claude Code

sea-schema surfaces range columns as ColumnType::Custom, which
write_rs_type renders as String. That is correct for the standard format,
where get_col_type_attrs pairs it with select_as = "text", but the oxide
format decodes rows straight into the model struct with sqlx::FromRow, so
a numrange column produced a struct that compiled and then failed at
runtime with "Rust type Option<String> is not compatible with SQL type
NUMRANGE".

Render the six range types as sqlx's PgRange instead, following the
element types sqlx implements and honouring --date-time-crate for the
temporal ones.

Two constraints shape the output. PgRange implements neither Serialize
nor Deserialize, so range fields carry #[serde(skip)]; skipping a field
requires Default to deserialize, so they are always Option regardless of
nullability. BigDecimal implements only PartialEq, so an entity holding a
numrange cannot derive Eq, which get_oxide_eq_needed now accounts for the
way get_eq_needed already does for floats.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@aevv
Mattt (aevv) changed the base branch from oxide-codegen to mattt/emit-uuid-import-in-oxide-codegen August 23, 2026 11:07
@aevv Mattt (aevv) changed the title fix(codegen): make oxide entities compile and decode for uuid and range columns fix(codegen): map postgres range columns to PgRange for oxide format Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant