Repository navigation
Conversation
…rsist_source Batched MFP evaluation precomputes each step's WebAssembly calls over the live rows, in any position, and then evaluates the step per row, replaying the recorded outcomes. Results, including error precedence and short-circuiting, match per-row evaluation exactly. persist_source evaluates such MFPs over batches of decoded rows, so the MFP stays pushed down and filter pushdown applies to it.
Statement text is limited to 1 MiB before lexing, and every arrow-udf module is larger than that once base64-encoded. CREATE FUNCTION ... USING BASE64 $n takes the module as a text bind parameter instead. Planning substitutes it into the statement, so create_sql still carries the module and re-plans at boot without parameters. Statement logging records the parameters of CREATE FUNCTION as <REDACTED>. mz udf create and mz udf sql emit psql's \bind (psql 16 and later).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Do not merge. This is an experiment, up for discussion and to see what CI thinks. It is one large stack; if we pursue it, it would land as separate PRs per concern.
What this is
User-defined scalar functions compiled to WebAssembly:
Behind
enable_wasm_functions, off by default and on in CI. The design doc isdoc/developer/design/20260930_wasm_udfs.md.Design in brief
arrow-udfcrate's#[function]macro load unchanged, including vectorized guests that take whole Arrow columns throughbatch_fn.random_get, a clock frozen at the epoch, no filesystem or network. A row's result is defined as the result of calling the function on that row alone. A batch that traps or exhausts its limits is bisected until every row has its own outcome.CASE,COALESCE,ANDandORare exactly what row-at-a-time evaluation gives. Batching happens inMfpoperators and insidepersist_source's decode, where filter pushdown is kept. Join closures,Reducekey and value plans, and peeks still call one row at a time.mz_exprdepends only on aWasmInvokertrait. wasmtime lives in the newmz-wasm-udfcrate, linked by clusterd and themzCLI, not environmentd. Calls are never constant-folded, so environmentd validates modules but never runs them.InstallWasmModule, ships module bytes to replicas before any dataflow or peek that uses them. It is kept across history compaction and replayed on reconnect.CREATE FUNCTION ... LANGUAGE wasm [STRICT] USING BASE64 { '...' | $n } [WITH (EXPORT, FUEL, MEMORY)],DROP FUNCTION, andSHOW [REDACTED] CREATE FUNCTION. Statement text is capped at 1 MiB, and arrow-udf modules exceed that once base64-encoded, so a module is usually sent as a bind parameter. Planning substitutes it intocreate_sql. Statement logging recordsCREATE FUNCTIONparameters as<REDACTED>.mz udf check | call | sql | create | pull | replay. These validate a module, call it locally with the same runtime and limits a cluster uses, check that results do not depend on batching, and debug failing rows from a region.Commits
design: the design doc.wasm-udf: a guest fixture module (16 functions exercising types, errors, traps, fuel, memory, state and WASI), checked in gzipped with its build script.wasm-udf-abi: signatures, type mapping and module validation.expr: theVariadicFunc::Wasmvariant, the invoker trait, and the batched MFP evaluator.wasm-udf: the deterministic runtime.compute: module installation on replicas, and batching inMfpoperators.sql:CREATE FUNCTIONandDROP FUNCTION, catalog and adapter.wasm-udf: vectorized guests and configurable batch sizes.mz: theudfsubcommands.expr, storage: precompute-and-replay for exact per-row semantics, and batching inpersist_source.sql, mz: modules as bind parameters, and statement logging redaction.design: how this fits into columnar scalar evaluation.Tests
mz-wasm-udf-abiunit tests: signature encoding, type mapping, module validation.mz-wasm-udfintegration tests against the fixture: types, NULLs, errors, traps, fuel, memory, bisection, determinism of WASI imports, batch sizing, andbatch_fnguests.mz-exprtests for the batched evaluator. Batched and per-row results match, including error precedence, filters before a call, and calls underIfandAND.CREATE FUNCTION, includingUSING BASE64 $n.src/environmentd/tests/wasm_udf.rsend to end:DROP FUNCTIONand its dependency checks;persist_sourcepath, with UDF errors in an untakenCASEbranch that must not surface.Known gaps
Table functions, aggregates, overloads,
CREATE OR REPLACE FUNCTION, introspection for batch sizes and fuel, and batching in joins,Reduceand peeks. No security review of running guest code in clusterd yet. These are listed in the design doc's open questions and future work.Generated with Claude Code