Skip to content

feat(hex2int): add hex2int UDF for SQLite and Postgres#67

Open
kronosapiens wants to merge 4 commits intodojoengine:mainfrom
kronosapiens:kronosapiens/sqlite-hex2int-udf
Open

feat(hex2int): add hex2int UDF for SQLite and Postgres#67
kronosapiens wants to merge 4 commits intodojoengine:mainfrom
kronosapiens:kronosapiens/sqlite-hex2int-udf

Conversation

@kronosapiens
Copy link
Copy Markdown

Summary

  • Adds a hex2int(text) -> int64 SQL function that converts hex-encoded integer strings (with or without 0x/0X prefix) to signed 64-bit integers, enabling built-in aggregation on hex-string columns.
  • SQLite: implemented as a scalar UDF registered via sqlite3_auto_extension in crates/sqlite/src/udf.rs. install_udfs() is called once from EcsService::new, so every connection in the process — including the /sql endpoint's AnyPool — picks it up automatically with no per-connection wiring.
  • Postgres: equivalent public.hex2int() shipped as migration 004_hex2int_function.sql under introspect-postgres-sink, so it lands on any Postgres DB the ECS sink initializes.
  • Both implementations handle hex strings up to 256 bits by keeping only the rightmost 16 hex chars (lower 64 bits). Values that fit in u64 are preserved exactly; larger values are truncated to their low 64 bits. NULL → NULL.

Test plan

  • cargo test -p torii-sqlite — SQLite UDF unit tests (basic, no prefix, u64::MAX, NULL, zero, uppercase prefix, 256-bit zero-padded, 256-bit with non-zero high bits).
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo fmt --all -- --check
  • CI: new postgres:16 service on the test job runs the Postgres integration test in crates/introspect-postgres-sink/tests/hex2int.rs against the real migration. Test is skipped locally when DATABASE_URL is unset.

🤖 Generated with Claude Code

kronosapiens and others added 4 commits April 16, 2026 16:02
Enables built-in SQLite aggregation functions (MAX, MIN, SUM, etc.)
on hex-encoded integer columns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch the SQLite UDF to sqlite3_auto_extension so every connection
in-process (including the /sql endpoint's AnyPool) gets hex2int without
per-connection wiring. Add a matching public.hex2int() in the
introspect-postgres-sink migrations, handling hex strings up to 256 bits
by keeping only the lower 64 bits. Wire install_udfs() into
EcsService::new, and add a Postgres integration test plus a postgres:16
service to the CI test job.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Use pointer::cast() instead of `as *const _`, and replace
match-on-Result with if-let/else to address ptr_as_ptr and
single_match_else lints failing CI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…Migrator

The raw Migrator::run doesn't create the `introspect` schema that
migration 002 writes into, so the test panicked with "schema
\"introspect\" does not exist". Use SchemaMigrator, which matches how
the sink itself runs these migrations in processor.rs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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