Repository navigation
Compile field conversions into the expression tree rules already execute - #1133
Conversation
Signed-off-by: Nash Aschenbath <wwh86696@163.com>
…ranch Signed-off-by: Nash Aschenbath <wwh86696@163.com>
WaylandYang
left a comment
There was a problem hiding this comment.
Thank you. Unlike #1131 this one has a written scope, #555, and it stays inside it: the three node kinds the issue names, text accepted at write time and only the tree stored, MAX_EXPR_DEPTH unchanged, no migration and no new external dependency.
Read in full: expressions.rs and rule_expression_input.rs. The compiler is an allowlist that falls through to "unsupported", resolves names to attribute ids of the current base, and re-validates its own output through Expr::from_json, so the text and JSON entries cannot drift apart. Sharing one decoder also removed three copies of it.
Checked on a real server built from 1cbbe25:
| Input | Result |
|---|---|
CAST(amount_cents AS DOUBLE PRECISION) / 100 |
stored as a tree of attribute ids, shown readably in Business rules |
CASE channel_code WHEN 1 THEN 'app' WHEN 2 THEN 'web' ELSE 'other' END |
the same |
amount_cents; DROP TABLE facts, (SELECT 1), lower(amount_cents), CAST(… AS TEXT), a searched CASE |
422 bad_expression |
no_such_attr / 100 |
422 unknown_expression_attribute |
One thing to know, not a request: a CASE key is compared by type, so a code stored as the text "1" does not match WHEN 1 and the rule yields nothing. That is consistent with "a failed conversion is absent"; it may deserve a line in docs/design/rules.md when alignment (#554) starts feeding it real columns.
Merging. Thanks again.
Why
An amount in cents, a channel code and a creation month need conversions that the numeric rule-expression tree cannot express. ADR 0036 makes these conversions part of that tree so an alignment can store a definition with attribute references rather than a dialect-specific SQL string.
Closes #555.
What changes
CASEand UTC year/month/day truncation to the shared expression tree. Case results have one scalar type, with at most 32 literal arms; every referenced reading remains a premise. Missing inputs, invalid conversions and unmatched cases withoutELSEproduce no result. Numeric evaluation keeps the existing floating-point semantics.{"expression":"CAST(amount AS DOUBLE PRECISION) / 100"}in a computed conclusion or comparison operand. The existing SQL parser compiles an allowlisted scalar expression, resolves attribute keys within the current base and stores only its UUID tree, including in definition history. The four-edge tree limit remains; text input is capped at 8192 bytes. Statements, subqueries, aggregates, searched cases, arbitrary casts/functions and function modifiers are refused.Table alignment/adoption and SQL rendering remain #554 and #556. Declaration/unit validation remains the proposal in ADR 0049. This change adds no migration and does not provide fixed-scale decimal accounting or a new expression editor.
How it was checked
All six upstream CI checks passed for
1cbbe25e76f5a77d97b69922b9df767daf2e6b20.cargo test --offline --locked --workspace: 1,474 passed, six existing opt-in tests ignored. The run used PostgreSQL/pgvector withUTOPIA_TEST_REQUIRE_DB=1andUTOPIA_TEST_REQUIRE_PDFTOTEXT=1; fresh database migrations passed.cargo fmt --all --check, workspace clippy for all targets with-D warnings, andcargo build --offline --locked --workspacepassed.The ignored cases are live OCR/RSS acceptance and dedicated materialization-delivery experiments. No real-model benchmark, external SQL-engine acceptance or browser interaction run is claimed here.
Before review
git commit -s)cargo fmt --all --check,cargo clippy --workspace --all-targets -- -D warningsandcargo test --workspacepassweb/:pnpm buildandpnpm testpassUTOPIA_DATABASE_URLset