You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(nodedb): support INSERT ... ON CONFLICT DO UPDATE SET with expression evaluation
Introduce `UpdateValue` on the bridge — a tagged union carrying either
pre-encoded msgpack bytes (fast literal path) or a `SqlExpr` that the
Data Plane evaluates against the existing row at apply time.
Planner changes:
- `SqlPlan::Upsert` gains an `on_conflict_updates` field for the SET
assignments extracted from `ON CONFLICT (...) DO UPDATE SET`.
- `dml::plan_upsert_with_on_conflict` routes `INSERT ... ON CONFLICT DO
UPDATE SET` through the upsert path, carrying the assignments.
- `assignments_to_update_values` converts planner `SqlExpr` to
`UpdateValue`, choosing `Literal` for constant RHS and `Expr` for
anything that must be evaluated per-row.
- `ScanFilter` gains an `expr: Option<SqlExpr>` field so complex WHERE
clauses (scalar functions, arithmetic, non-literal BETWEEN) that the
planner cannot reduce to simple triples are shipped verbatim to the
Data Plane for row-level evaluation.
- `sql_expr_to_bridge_expr` extended to cover `UnaryOp`, `IsNull`,
`Between`, `Substring`, `Trim`, and `Case` expressions.
- `sql_plan_convert/filter.rs` populates the new `expr` field for
general-purpose `FilterExpr::Expr` predicates.
Executor changes:
- `bulk_dml` and `upsert` handlers receive `&[(String, UpdateValue)]`
instead of `&[(String, Vec<u8>)]`; literal arms are identical to the
previous fast path, expression arms evaluate against a pre-update
snapshot of the row (matching PostgreSQL semantics — assignments do
not observe each other).
- Empty `filter_bytes` in `bulk_dml` now means "no WHERE clause" instead
of a deserialization error.
- `check_generated_readonly` and `needs_recomputation` generified over
the update-value type so both call sites compile without duplication.
All existing call sites updated to pass `expr: None` on the `ScanFilter`
constructor and supply the required `on_conflict_updates` slice.
0 commit comments