diff --git a/Cargo.toml b/Cargo.toml index fbc03e29..369b377e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -212,6 +212,7 @@ members = [ "extensions/icebergscan-component", "extensions/autocomplete-component", "extensions/statsduck-component", + "tools/catalog-sig-extract", ] # talib-component carries its own `[workspace]` table (an independent lockfile — diff --git a/crates/ducklink-cli/src/lib.rs b/crates/ducklink-cli/src/lib.rs index 70715c27..361e83f8 100644 --- a/crates/ducklink-cli/src/lib.rs +++ b/crates/ducklink-cli/src/lib.rs @@ -344,7 +344,13 @@ fn run_repl(conn: &duckdb::Connection) -> Result<(), String> { statement.push_str(trimmed); if !trimmed.ends_with(';') { - statement.push(' '); + // Preserve line breaks between joined input lines so DuckDB's + // parser correctly terminates SQL line comments (`-- ...`) at + // end-of-line. Joining with a single space instead caused + // `-- comment\nSELECT 1;` to become `-- comment SELECT 1;`, + // which the parser reads as one giant line comment that + // swallows the following statement. + statement.push('\n'); write_continuation_prompt(&out)?; continue; } diff --git a/crates/ducklink-host/Cargo.toml b/crates/ducklink-host/Cargo.toml index 5dfbd49c..1edd1a97 100644 --- a/crates/ducklink-host/Cargo.toml +++ b/crates/ducklink-host/Cargo.toml @@ -11,10 +11,12 @@ clap = { version = "4.5", features = ["derive"] } wasmtime = { version = "46.0.1", features = ["component-model", "cache"] } wasmtime-wasi = "46.0.1" # Tiered Virtual Memory: host-owned regions back DuckDB's >4 GiB spill tier. -# tvm-core is wasmtime-free, so it works with this host's pinned wasmtime (39) -# even though tvm-wasmtime targets 45; the manager/bytes host traits are -# implemented in this crate against this host's bindgen. -tvm-core = { path = "../../../tvm-wasm/crates/tvm-core" } +# tvm-core is wasmtime-free; the manager/bytes host traits are implemented in +# this crate against this host's bindgen. Sourced via a pinned git rev of +# tvm-wasm (not a local path) so ducklink builds standalone AND so ChimeraDB's +# in-process build (which links ducklink-host + sqlink-host) resolves a SINGLE +# tvm-core source — sqlink-host pins the same rev. See chimeradb/PLAN-inprocess.md PR1. +tvm-core = { git = "https://github.com/tegmentum/tvm-wasm.git", rev = "6f3bae38fad4addd4de1837ab151f4ac871d1dd4" } # TLS for `ducklink serve` (the httpd). Blocking rustls over the accept # loop's TcpStream; rcgen mints the --tls-self-signed cert. Mirrors the # sqlite-wasm-httpd stack. @@ -38,7 +40,12 @@ hex = "0.4" # trust-gated CompileCache. Used here to HMAC-authenticate the precompiled # `.cwasm` (a `.cwasm` deserializes to runnable machine code, so it must be # trusted). compose-core is wasmtime-free and sqlite-free. -compose-core = { git = "https://github.com/tegmentum/webassembly-component-orchestration.git", branch = "main" } +compose-core = { git = "https://github.com/tegmentum/webassembly-component-orchestration.git", rev = "416226921cc166e98016f534a73bd6c9b7dcb33c" } +# Ergonomic error enum for the sub-ext loader (Phase D). The rest of the +# crate uses anyhow at the boundary; internally SubExtError is a `thiserror` +# enum so callers can pattern-match on `SubExtError::PlanMissing` vs a compose +# failure without stringly parsing. +thiserror = "1" # Home-dir resolution for the per-machine HMAC key + FsBlobStore cache root. dirs = "5" # Shared, db-agnostic crates (also consumed by the sqlink host). datalink is diff --git a/crates/ducklink-host/src/lib.rs b/crates/ducklink-host/src/lib.rs index 592c07d5..ba95b044 100644 --- a/crates/ducklink-host/src/lib.rs +++ b/crates/ducklink-host/src/lib.rs @@ -117,6 +117,13 @@ pub mod compose_dynlink_test_support { mod delta_rewrite; mod plan_shape; mod prefix; +/// Phase D: per-sub-extension `compose:dynlink` bridge + composed-provider +/// loader (`postgis_core -> {plan, bridge, derived-from}` maps and the +/// `materialize_sub_ext_provider` composer). Public so downstream host +/// embedders (and this crate's tests) can configure it directly instead of +/// going through env vars. +pub mod sub_ext; +pub use sub_ext::{sub_ext_provider_id, SubExtError, SubExtLoader}; /// Defensive guard for a parser extension's returned rewrite (v3 @3.0.0 /// parser-dispatch boundary). The core RE-PLANS the rewrite, so a bad component @@ -491,6 +498,129 @@ impl core_storage_host::Host for CoreStoreState { .dispatch_storage_scan_close(scan) .map_err(convert_extension_duckerror_to_core) } + + // M2c write surface: transactions + DDL + DML. The core imports these + // through `storage-host`; the host resolves the (ext, callback-handle) + // via the same `resolve_storage_backend` picker the read side uses and + // routes to the writable component's `storage-write-dispatch` export + // through the ExtensionInstance's `storage_*` trampolines. + fn storage_begin_transaction( + &mut self, + catalog: u32, + ) -> Result { + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_begin_transaction(catalog) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_commit_transaction(&mut self, txn: u32) -> Result<(), core_types::Duckerror> { + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_commit_transaction(txn) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_rollback_transaction( + &mut self, + txn: u32, + ) -> Result<(), core_types::Duckerror> { + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_rollback_transaction(txn) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_create_table( + &mut self, + txn: u32, + table: String, + columns: Vec, + ) -> Result<(), core_types::Duckerror> { + let ext_columns: Vec = columns + .into_iter() + .map(convert_core_columndef_to_extension) + .collect(); + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_create_table(txn, &table, &ext_columns) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_insert_rows( + &mut self, + txn: u32, + table: String, + rows: Vec>, + ) -> Result { + let ext_rows: Vec> = rows + .into_iter() + .map(|row| { + row.into_iter() + .map(convert_core_duckvalue_to_extension) + .collect() + }) + .collect(); + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_insert_rows(txn, &table, &ext_rows) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_delete_rows( + &mut self, + txn: u32, + table: String, + rowids: Vec, + ) -> Result { + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_delete_rows(txn, &table, &rowids) + .map_err(convert_extension_duckerror_to_core) + } + + fn storage_update_rows( + &mut self, + txn: u32, + table: String, + rowids: Vec, + updated_columns: Vec, + rows: Vec>, + ) -> Result { + let ext_rows: Vec> = rows + .into_iter() + .map(|row| { + row.into_iter() + .map(convert_core_duckvalue_to_extension) + .collect() + }) + .collect(); + let mut manager = self + .extension_manager + .lock() + .expect("extension manager mutex poisoned"); + manager + .dispatch_storage_update_rows(txn, &table, &rowids, &updated_columns, &ext_rows) + .map_err(convert_extension_duckerror_to_core) + } } // Item 3 / M2a: the core imports `duckdb:extension/index-host` for custom-index @@ -1818,6 +1948,16 @@ struct ExtensionManager { registry_index: Arc, resolver_policy: resolver::ResolvePolicy, last_resolutions: HashMap, + // Phase D: per-sub-extension `compose:dynlink` bridge + composed-provider + // loader. Holds the `sub_ext -> {plan, bridge, derived-from}` maps and the + // materialize-on-first-LOAD composer. `ensure_extension_loaded` consults + // `sub_ext_loader.has_bridge(name)` BEFORE the flat + // `/.wasm` shortcut and, when it matches, composes + // + registers the sub-ext's provider (once) and loads the bridge wasm + // instead. Registered against the process-global `ProviderRegistry` so + // one composed provider serves every bridge that plugs it (the + // postgis + mobilitydb dedup path). + sub_ext_loader: sub_ext::SubExtLoader, } impl ExtensionManager { @@ -1845,6 +1985,13 @@ impl ExtensionManager { .collect::>() }) .unwrap_or_default(); + // Phase D: the sub-ext loader shares the process-global + // `ProviderRegistry` (built lazily against `engine`) so a composed + // provider registered here on first LOAD resolves through the same + // registry as the `DUCKLINK_PROVIDERS`-declared ones and every + // bridge component sees it. + let sub_ext_loader = + sub_ext::SubExtLoader::from_env(dynlink_provider_registry(&engine).clone()); Self { engine, core: None, @@ -1872,6 +2019,7 @@ impl ExtensionManager { denied, }, last_resolutions: HashMap::new(), + sub_ext_loader, } } @@ -2095,6 +2243,46 @@ impl ExtensionManager { } data.aggregates.extend(qualified_aggregates); + // SCALAR_EX (2.2.0 rich scalars): same NAME-KEYED `{prefix}__{name}` + // namespacing as base scalars. Prefixing here means the QUALIFIED form + // of a scalar_ex registration surfaces on `data.scalar_ex` too — so a + // future direct consumer of `scalar_ex` (once the interim projection + // in `drain_pending` is retired) still sees prefixed shadows without + // any extra wiring. Today the base-scalar projection makes the SCALARS + // block above also prefix the projected copy; the double-record is a + // no-op because `note_prefix_registration` dedups on + // (expansion, name, shape, n_args), and the retained-def slot ends up + // storing a `ScalarEx` variant (which wins over the earlier `Scalar` + // insert for the same key). Once the projection is removed, SCALARS + // skips the scalar_ex entries entirely and this block is the only + // path that prefixes them. + let mut qualified_scalar_ex: Vec = Vec::new(); + for entry in &data.scalar_ex { + let n_args = entry.arguments.len() as i32; + let info = self.prefix_registry.resolve(&entry.extension); + self.note_prefix_registration( + &entry.extension, + &entry.name, + Shape::Scalar, + n_args, + &info, + ); + self.prefix_retained.insert( + &info.expansion, + &info.prefix, + &entry.name, + Shape::Scalar, + n_args, + prefix::RetainedDef::ScalarEx(entry.clone()), + ); + if let Some(qname) = prefix::qualified_name(&info.prefix, &entry.name) { + let mut dup = entry.clone(); + dup.name = qname; + qualified_scalar_ex.push(dup); + } + } + data.scalar_ex.extend(qualified_scalar_ex); + // MACROS (v1.1): a macro is dispatched by NAME (it becomes a DuckDB // CREATE MACRO), so `{prefix}__{name}` namespacing applies identically. // Arity is the parameter count. @@ -2282,6 +2470,7 @@ impl ExtensionManager { // are skipped (a macro can't forward an unknown arity). let params = match def { prefix::RetainedDef::Scalar(r) => Some(macro_param_names(&r.arguments)), + prefix::RetainedDef::ScalarEx(r) => Some(macro_param_names(&r.arguments)), prefix::RetainedDef::Aggregate(r) => Some(macro_param_names(&r.arguments)), prefix::RetainedDef::Table(_) => None, // table macros differ; skip prefix::RetainedDef::Macro(r) => Some(r.parameters.clone()), @@ -2568,6 +2757,101 @@ impl ExtensionManager { instance.storage_scan_close(handle, scan) } + // --- M2c write surface: transactions + DDL + DML --- + // + // Each method resolves the (ext, handle) pair the storage backend + // registered (same picker as the read-side scan) and forwards to the + // ExtensionInstance's `storage_*` write trampoline + // (ducklink-runtime/src/extension.rs). Errors bubble up as + // `extension_types::Duckerror` which the core-side impl re-maps. + + fn dispatch_storage_begin_transaction( + &mut self, + catalog: u32, + ) -> Result { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_begin_transaction(handle, catalog) + } + + fn dispatch_storage_commit_transaction( + &mut self, + txn: u32, + ) -> Result<(), extension_types::Duckerror> { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_commit_transaction(handle, txn) + } + + fn dispatch_storage_rollback_transaction( + &mut self, + txn: u32, + ) -> Result<(), extension_types::Duckerror> { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_rollback_transaction(handle, txn) + } + + fn dispatch_storage_create_table( + &mut self, + txn: u32, + table: &str, + columns: &[extension_types::Columndef], + ) -> Result<(), extension_types::Duckerror> { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_create_table(handle, txn, table, columns) + } + + fn dispatch_storage_insert_rows( + &mut self, + txn: u32, + table: &str, + rows: &[Vec], + ) -> Result { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_insert_rows(handle, txn, table, rows) + } + + fn dispatch_storage_delete_rows( + &mut self, + txn: u32, + table: &str, + rowids: &[i64], + ) -> Result { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_delete_rows(handle, txn, table, rowids) + } + + fn dispatch_storage_update_rows( + &mut self, + txn: u32, + table: &str, + rowids: &[i64], + updated_columns: &[u32], + rows: &[Vec], + ) -> Result { + let (ext, handle) = self.resolve_storage_backend()?; + let instance = self.extensions.get_mut(&ext).ok_or_else(|| { + extension_types::Duckerror::Invalidstate(format!("storage extension '{ext}' not loaded")) + })?; + instance.storage_update_rows(handle, txn, table, rowids, updated_columns, rows) + } + // --- Item 3 / M2a: custom index (build + search) routing --- /// The custom index TYPE names every component has registered (via @@ -3051,23 +3335,68 @@ impl ExtensionManager { return Ok(true); } - // Multi-provider resolution (design A): pick a certified provider via the - // resolver candidate pipeline instead of the bare filename shortcut. An - // extension absent from the manifest falls back to the filename. - let artifact = match self.resolve_provider_artifact(&sanitized) { - Ok(p) => p, - Err(reason) => { - eprintln!("[resolver] no admissible provider for '{sanitized}': {reason}"); + // Phase D: per-sub-extension `compose:dynlink` bridge branch. If the + // requested name is present in `sub_ext_loader.sub_ext_bridge_paths`, + // materialize the composed provider (once) and load the configured + // bridge wasm instead of taking the flat resolver path. This runs + // BEFORE `resolve_provider_artifact` so a sub-ext bridge stored + // outside `` (e.g. under a `postgis-core-ducklink-bridge` + // checkout) doesn't need to be symlinked into the extensions dir. + // Falls through to the standard resolver when neither the bridge map + // nor a plan is configured for `sanitized` — preserves the existing + // LOAD semantics for every non-sub-ext extension bit-identically. + let artifact = if self.sub_ext_loader.has_bridge(&sanitized) { + // Compose + register the composed provider under + // `-composed`. Idempotent; a re-issued LOAD hits the + // materialized guard and no-ops. + match self.sub_ext_loader.materialize_sub_ext_provider(&sanitized) { + Ok(provider_id) => eprintln!( + "[sub-ext] '{sanitized}' composed provider registered as '{provider_id}'" + ), + Err(err) => { + eprintln!( + "[sub-ext] '{sanitized}' materialization failed: {err}; skipping load request" + ); + return Ok(false); + } + } + let bridge = self + .sub_ext_loader + .bridge_path(&sanitized) + .expect("has_bridge guarded above") + .to_path_buf(); + if !bridge.exists() { + eprintln!( + "[sub-ext] bridge wasm for '{sanitized}' not found at {}; skipping load request", + bridge.display() + ); return Ok(false); } - }; - if !artifact.exists() { eprintln!( - "[extension-manager] resolved artifact for '{sanitized}' not found at {}; skipping load request", - artifact.display() + "[sub-ext] '{sanitized}' bridge wasm: {}", + bridge.display() ); - return Ok(false); - } + bridge + } else { + // Multi-provider resolution (design A): pick a certified provider via the + // resolver candidate pipeline instead of the bare filename shortcut. An + // extension absent from the manifest falls back to the filename. + let artifact = match self.resolve_provider_artifact(&sanitized) { + Ok(p) => p, + Err(reason) => { + eprintln!("[resolver] no admissible provider for '{sanitized}': {reason}"); + return Ok(false); + } + }; + if !artifact.exists() { + eprintln!( + "[extension-manager] resolved artifact for '{sanitized}' not found at {}; skipping load request", + artifact.display() + ); + return Ok(false); + } + artifact + }; let core = match self.core.as_ref() { Some(core) => core.clone(), @@ -5758,6 +6087,44 @@ fn convert_extension_columndef_to_core(col: extension_types::Columndef) -> core_ } } +// M2c: inverse mapping used by the write-side storage-host imports (create-table, +// insert-rows, update-rows) to hand the core -> extension trampoline the same +// Logicaltype / Columndef shape ExtensionInstance expects. +fn convert_core_logicaltype_to_extension( + ty: core_types::Logicaltype, +) -> extension_types::Logicaltype { + match ty { + core_types::Logicaltype::Boolean => extension_types::Logicaltype::Boolean, + core_types::Logicaltype::Int64 => extension_types::Logicaltype::Int64, + core_types::Logicaltype::Uint64 => extension_types::Logicaltype::Uint64, + core_types::Logicaltype::Float64 => extension_types::Logicaltype::Float64, + core_types::Logicaltype::Text => extension_types::Logicaltype::Text, + core_types::Logicaltype::Blob => extension_types::Logicaltype::Blob, + core_types::Logicaltype::Int32 => extension_types::Logicaltype::Int32, + core_types::Logicaltype::Timestamp => extension_types::Logicaltype::Timestamp, + core_types::Logicaltype::Int8 => extension_types::Logicaltype::Int8, + core_types::Logicaltype::Int16 => extension_types::Logicaltype::Int16, + core_types::Logicaltype::Uint8 => extension_types::Logicaltype::Uint8, + core_types::Logicaltype::Uint16 => extension_types::Logicaltype::Uint16, + core_types::Logicaltype::Uint32 => extension_types::Logicaltype::Uint32, + core_types::Logicaltype::Float32 => extension_types::Logicaltype::Float32, + core_types::Logicaltype::Date => extension_types::Logicaltype::Date, + core_types::Logicaltype::Time => extension_types::Logicaltype::Time, + core_types::Logicaltype::Timestamptz => extension_types::Logicaltype::Timestamptz, + core_types::Logicaltype::Decimal => extension_types::Logicaltype::Decimal, + core_types::Logicaltype::Interval => extension_types::Logicaltype::Interval, + core_types::Logicaltype::Uuid => extension_types::Logicaltype::Uuid, + core_types::Logicaltype::Complex(expr) => extension_types::Logicaltype::Complex(expr), + } +} + +fn convert_core_columndef_to_extension(col: core_types::Columndef) -> extension_types::Columndef { + extension_types::Columndef { + name: col.name, + logical: convert_core_logicaltype_to_extension(col.logical), + } +} + // M2b: convert a core-WIT scan-request into the storage-interface scan-request // the backing component's storage-dispatch expects. fn convert_core_compare_op_to_storage(op: core_storage_host::CompareOp) -> storage_scan::CompareOp { @@ -5836,6 +6203,11 @@ fn convert_core_scan_request_to_storage( }) .collect(), limit: request.limit, + // M2c: forward the wants-rowid flag verbatim to the guest's + // storage-dispatch scan-open. The read side (SELECT) leaves this + // false; UPDATE/DELETE plans set it via the C++ WasmScanInitGlobal + // so the guest appends rowid trailers to each row. + wants_rowid: request.wants_rowid, } } @@ -6148,7 +6520,6 @@ pub fn run_cli_with_stdio( args: &[impl AsRef], preopens: &[(&Path, &str)], ) -> Result> { - let engine = build_engine()?; let owned_preopens = resolve_preopens_with_default(preopens)?; let preopen_refs: Vec<(&Path, &str)> = owned_preopens .iter() @@ -6156,6 +6527,50 @@ pub fn run_cli_with_stdio( .collect(); let args_vec: Vec = args.iter().map(|s| s.as_ref().to_owned()).collect(); let cli_wasi = build_wasi_ctx_inherit(&args_vec, &preopen_refs)?; + run_cli_inner(artifacts, owned_preopens, cli_wasi) +} + +/// Like `run_cli_with_stdio`, but drives the CLI with in-memory stdio: `stdin` +/// is fed `stdin_bytes` (e.g. a SQL script) and the CLI's stdout is captured and +/// returned. For in-process query execution (no subprocess). Host-side log lines +/// (extension loading, etc.) still go to the process's real stderr via +/// `eprintln`, not through this captured pipe. +pub fn run_cli_capture( + artifacts: &ComponentArtifacts, + args: &[impl AsRef], + preopens: &[(&Path, &str)], + stdin_bytes: &[u8], +) -> Result { + let owned_preopens = resolve_preopens_with_default(preopens)?; + let preopen_refs: Vec<(&Path, &str)> = owned_preopens + .iter() + .map(|(host, guest)| (host.as_path(), guest.as_str())) + .collect(); + let args_vec: Vec = args.iter().map(|s| s.as_ref().to_owned()).collect(); + let stdin = MemoryInputPipe::new(stdin_bytes.to_vec()); + let stdout = MemoryOutputPipe::new(usize::MAX); + let stderr = MemoryOutputPipe::new(usize::MAX); + let cli_wasi = + build_wasi_ctx_with_pipes(&args_vec, &preopen_refs, stdin, stdout.clone(), stderr)?; + // The CLI's own exit Result is irrelevant here; we want its captured output. + let _ = run_cli_inner(artifacts, owned_preopens, cli_wasi)?; + Ok(String::from_utf8_lossy(&stdout.contents()).into_owned()) +} + +/// Shared core of the CLI run path: instantiate the composed core + dotcmd +/// registry, wire the linker, and drive the CLI component's `wasi:cli/run`. +/// `cli_wasi` carries the CLI's stdio — inherited (`run_cli_with_stdio`) or +/// in-memory pipes (`run_cli_capture`). +fn run_cli_inner( + artifacts: &ComponentArtifacts, + owned_preopens: Vec<(PathBuf, String)>, + cli_wasi: WasiCtx, +) -> Result> { + let engine = build_engine()?; + let preopen_refs: Vec<(&Path, &str)> = owned_preopens + .iter() + .map(|(host, guest)| (host.as_path(), guest.as_str())) + .collect(); let core_wasi = build_wasi_ctx_inherit(&[String::from("duckdb-core")], &preopen_refs)?; let extension_manager = Arc::new(Mutex::new(ExtensionManager::new(engine.clone()))); @@ -6275,6 +6690,69 @@ mod tests { assert!(validate_parser_rewrite("ggsql", "VISUALIZE x", "SELECT 1").is_ok()); } + #[test] + fn apply_function_prefixes_surfaces_bare_and_prefixed_scalar_ex() { + // A `register-scalar-ex` registration must reach the prefixed-dispatch + // surface: the SCALAR_EX arm in `apply_function_prefixes` prefixes it + // just like a base scalar, so a `{prefix}__{name}` copy is appended to + // `data.scalar_ex` and the retained-def slot stores a `ScalarEx` arm. + // This locks the fix in against a regression when the interim + // `drain_pending` projection into `scalars` is retired. + let engine = build_engine().expect("engine"); + let mut manager = ExtensionManager::new(engine); + let mut data = PendingRegistrationsData::default(); + data.scalar_ex.push(reg::ScalarExReg { + extension: "myext".to_string(), + name: "concat_ws".to_string(), + arguments: vec![reg::FuncArg { + name: Some("sep".to_string()), + logical: reg::LogicalType::Text, + }], + varargs: Some(reg::LogicalType::Text), + returns: reg::LogicalType::Text, + special_null: true, + callback_handle: 77, + options: None, + }); + + manager.apply_function_prefixes(&mut data); + + // The raw scalar_ex slot carries BOTH the bare name and a + // `{prefix}__concat_ws` shadow. + let names: Vec<&str> = data.scalar_ex.iter().map(|e| e.name.as_str()).collect(); + assert!( + names.iter().any(|n| *n == "concat_ws"), + "bare scalar_ex name preserved; got {names:?}" + ); + assert_eq!( + names.len(), + 2, + "prefixed shadow appended to scalar_ex; got {names:?}" + ); + let prefixed = names.iter().find(|n| n.contains("__concat_ws")).copied(); + assert!( + prefixed.is_some(), + "{{prefix}}__concat_ws shadow missing; got {names:?}" + ); + + // Retained-def slot carries the ScalarEx arm (not a projection to + // Scalar) — the pin machinery must see the richer shape. + let expansion = prefixed + .and_then(|q| q.split_once("__").map(|(p, _)| p.to_string())) + .expect("prefixed name has expansion prefix"); + // The retained key uses the resolver's expansion (not the SQL prefix + // string), which for an unknown extension falls back to + // `ducklink-internal://`. Look up via that fallback. + let fallback_expansion = format!("ducklink-internal://{expansion}"); + let retained = manager + .prefix_retained + .get("concat_ws", prefix::Shape::Scalar, 1, &fallback_expansion); + assert!( + matches!(retained, Some(prefix::RetainedDef::ScalarEx(_))), + "retained-def slot must be a ScalarEx arm (got {retained:?})" + ); + } + #[test] fn network_grant_adapter_preserves_behavior() { use datalink_policy::Capability; diff --git a/crates/ducklink-host/src/prefix.rs b/crates/ducklink-host/src/prefix.rs index 39529bf6..1943ae4b 100644 --- a/crates/ducklink-host/src/prefix.rs +++ b/crates/ducklink-host/src/prefix.rs @@ -405,6 +405,14 @@ pub enum RetainedDef { Collation(String, String, bool), /// (name, extension, callback_handle) Pragma(String, String, u32), + /// A 2.2.0 richer scalar (`register-scalar-ex`) — varargs, optionally named + /// args, special NULL-handling. Retained separately from `Scalar` so a pin + /// against a scalar_ex registration keeps its richer shape even after the + /// interim `drain_pending` projection into `scalars` is retired. Currently + /// pin-wrapped like `Scalar` (a macro alias forwards positional args to the + /// prefixed form); the wrapper is fine because scalar_ex still dispatches + /// through the base scalar sink today. + ScalarEx(reg::ScalarExReg), } /// Identity of a retained def: bare name + shape + arity + expansion. The diff --git a/crates/ducklink-host/src/sub_ext.rs b/crates/ducklink-host/src/sub_ext.rs new file mode 100644 index 00000000..79067db3 --- /dev/null +++ b/crates/ducklink-host/src/sub_ext.rs @@ -0,0 +1,712 @@ +//! Phase D: per-sub-extension `compose:dynlink` bridge + composed-provider +//! loader for `ducklink-host`. Mirrors +//! `datafission::df-plugin-loader::UnifiedPluginLoader::materialize_sub_ext_provider` +//! but wires into ducklink's `ProviderRegistry` and its `LOAD ` path. +//! +//! Data flow at `LOAD postgis_core`: +//! +//! 1. `ExtensionManager::ensure_extension_loaded` checks +//! [`SubExtLoader::has_bridge`] for the requested name; if present it +//! takes the sub-ext branch instead of the flat +//! `/.wasm` resolution. +//! 2. [`SubExtLoader::materialize_sub_ext_provider`] parses the plan JSON, +//! resolves any zero-digest components through the +//! derived-from chain (recursing on this same method), composes via +//! `compose_core::emit::EmitHandler`, writes the composed bytes to a +//! stable file under `/composed-providers/-composed.wasm`, +//! and registers under `sub_ext_provider_id(sub_ext)` in the +//! process-global `ProviderRegistry`. Idempotent — a re-issued LOAD is a +//! no-op after first hit. +//! 3. The caller then loads the bridge component's path +//! (`sub_ext_bridge_paths[name]`) through ducklink's normal +//! `load_component_with_dynlink` path; the bridge's `resolve-by-id` +//! import routes to the newly-registered composed provider. +//! +//! Config comes from four env vars — parallel to `DUCKLINK_PROVIDERS`: +//! +//! ```text +//! DUCKLINK_SUB_EXT_PLANS==:=... +//! DUCKLINK_SUB_EXT_BRIDGES==:=... +//! DUCKLINK_SUB_EXT_DERIVED==:=... +//! DUCKLINK_SUB_EXT_PREBUILT==:=... +//! ``` +//! +//! `DUCKLINK_SUB_EXT_PREBUILT` (short-circuit path — Phase D / Option B): +//! when a sub-ext has a prebuilt, self-contained composed wasm on disk +//! (e.g. the ~126 MB `postgis-composed.wasm` monolith produced by +//! `postgis-wasm/scripts/compose.sh`), register that wasm directly under +//! `-composed` and skip the plan-driven compose entirely. Used +//! when the plan-driven sub-composed artifact would leak unresolved +//! sibling-wasm imports (see recon: 19 imports on `postgis-core-composed` +//! because `postgis_wasm.wasm` statically imports all 30+ external +//! instances). A prebuilt entry takes precedence over a plan entry for +//! the same sub-ext. +//! +//! `:` is the entry separator (matches datafission's convention and dodges +//! the `,` that DuckDB users habitually stuff into env vars for other reasons). +//! +//! Kept in its own module so the massive `lib.rs` doesn't grow further and +//! so the API surface (`SubExtLoader`, `SubExtError`, `sub_ext_provider_id`) +//! is unit-testable without dragging the whole `ExtensionManager` in. + +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::path::{Path, PathBuf}; + +use compose_core::blobs::BlobStore; +use compose_core::emit::EmitHandler; +use compose_core::events::EventCollector; +use compose_core::host::SystemClock; +use compose_core::types::PlanV1; + +use crate::ProviderRegistry; + +/// Canonical provider id under which a sub-extension's composed backend +/// registers with the process-global `ProviderRegistry`. A bridge component +/// resolves through this id via `compose:dynlink/linker.resolve-by-id`. +/// Stable across sessions; identical to the datafission convention. +pub fn sub_ext_provider_id(sub_ext: &str) -> String { + format!("{sub_ext}-composed") +} + +/// Placeholder-digest predicate: a component whose real bytes come from +/// composing an upstream sub-ext's plan is authored with an all-zero +/// digest so plan JSON is byte-stable across regenerations. The loader +/// resolves such components via [`SubExtLoader::sub_ext_derived_from`]. +fn is_zero_digest(digest: &[u8]) -> bool { + !digest.is_empty() && digest.iter().all(|b| *b == 0) +} + +/// compose-core's build-tool blob-size ceiling (1 GiB). Inlined so this +/// module doesn't drag in a limits import. +const COMPOSE_MAX_BLOB_SIZE: u64 = 1 << 30; + +#[derive(Debug, thiserror::Error)] +pub enum SubExtError { + #[error( + "no plan registered for sub-extension '{sub_ext}' — populate DUCKLINK_SUB_EXT_PLANS or SubExtLoader::sub_ext_plan_paths" + )] + PlanMissing { sub_ext: String }, + + #[error( + "no bridge registered for sub-extension '{sub_ext}' — populate DUCKLINK_SUB_EXT_BRIDGES or SubExtLoader::sub_ext_bridge_paths" + )] + BridgeMissing { sub_ext: String }, + + #[error("failed to materialize sub-extension '{sub_ext}' from plan {plan:?}: {reason}")] + Materialization { + sub_ext: String, + plan: PathBuf, + reason: String, + }, + + #[error("failed to register composed provider '{id}' from {path:?}: {reason}")] + ProviderRegistration { + id: String, + path: PathBuf, + reason: String, + }, +} + +impl SubExtError { + fn mat(sub_ext: &str, plan: &Path, reason: impl Into) -> Self { + Self::Materialization { + sub_ext: sub_ext.to_string(), + plan: plan.to_path_buf(), + reason: reason.into(), + } + } +} + +/// Owns the sub-ext ↔ (plan, bridge) maps and the compose-core CAS/cache +/// roots. Lives inside `ExtensionManager` but is a self-contained, +/// unit-testable unit — the constructor takes only what materialization +/// needs (an engine-bound `ProviderRegistry` + two dirs), not the whole +/// LOAD-path state. +pub struct SubExtLoader { + registry: ProviderRegistry, + + /// `sub_ext -> plan.json path`. Populated from CLI/env/config; consulted + /// on the first LOAD of the sub-ext to compose its provider bytes. + pub sub_ext_plan_paths: BTreeMap, + + /// `sub_ext -> bridge.wasm path`. Populated from CLI/env/config; consulted + /// on the first LOAD of the sub-ext to pick the wasm the guest actually + /// instantiates. Split from the flat `/.wasm` path + /// so a sub-ext's bridge can live anywhere on disk. + pub sub_ext_bridge_paths: BTreeMap, + + /// `plan-component-id -> upstream-sub-ext-id`. Every plan component + /// whose digest is the 32-byte all-zeros placeholder is chain-resolved + /// through this map before the current plan composes: the referenced + /// upstream is composed first (recursing back through + /// [`SubExtLoader::materialize_sub_ext_provider`] so the same idempotence + /// guard dedups a shared upstream) and its composed digest is spliced + /// into an in-memory clone of the current plan. + pub sub_ext_derived_from: BTreeMap, + + /// `sub_ext -> prebuilt-composed-wasm-path`. Short-circuits the + /// plan-driven compose: if an entry exists for `sub_ext`, the loader + /// registers the prebuilt wasm directly under `sub_ext_provider_id` + /// and skips reading/parsing/composing the plan JSON entirely. Used + /// when the plan-driven per-sub-ext composed artifact would leak + /// unresolved sibling-wasm imports (the `postgis-core-composed` + /// 19-import gap) and the application ships a self-contained + /// monolithic composed wasm as a fallback. Takes precedence over + /// `sub_ext_plan_paths` for the same key. + pub sub_ext_prebuilt_paths: BTreeMap, + + /// `sub_ext -> upstream-sub-ext-id` — Phase 9.1 shared-shim alias. + /// Sub-exts whose composed provider IS an upstream sub-ext's provider + /// (rather than a distinct shim) route through this map instead of + /// materializing their own. Example: `postgis_topology`, + /// `postgis_3d`, `postgis_metadata`, `postgis_clustering` all share + /// the `postgis_core-composed` provider — one 30 MB wasm instead of + /// four independent registrations. Bridges for aliased subs are + /// emitted with `--provider-id -composed` so their + /// `resolve-by-id` import lands on the shared registration. + /// + /// When `LOAD ` fires against a key in this map, + /// `materialize_sub_ext_provider` recurses into the upstream, marks + /// both entries materialized (idempotence guard covers repeat LOADs + /// of either the upstream or any of its aliased children), and + /// returns the UPSTREAM provider id. Populated from + /// `DUCKLINK_SUB_EXT_ALIAS` env var. + pub sub_ext_shim_alias: BTreeMap, + + /// Blob CAS root (default `/.compose/blobs`). Every plan + /// component's digest must resolve to a blob under this root — the + /// application layer (postgis-wasm's `plans/verify.sh` or an + /// equivalent) is responsible for pre-seeding the CAS. + pub blob_cas_path: PathBuf, + + /// compose-core cache directory (default `/.compose/cache`). Keyed + /// by `emit_key = H(plan bytes)`; a repeat compose of the same plan + /// hits this and produces zero disk I/O beyond the read. + pub compose_cache_path: PathBuf, + + /// Idempotence guard — sub-exts already materialized this session. + materialized_sub_exts: HashSet, + + /// `sub_ext -> composed CompositionResult.digest`. Populated by + /// [`SubExtLoader::materialize_sub_ext_provider`] BEFORE the idempotence + /// insert so a downstream sub-ext that hits the early-return path still + /// sees the digest cached here. + composed_digests: HashMap>, +} + +impl SubExtLoader { + /// Blank loader with default CAS/cache paths (relative to cwd) and no + /// entries. Populate the public map fields (or use + /// [`SubExtLoader::from_env`]) before calling + /// [`SubExtLoader::materialize_sub_ext_provider`]. + pub fn new(registry: ProviderRegistry) -> Self { + Self { + registry, + sub_ext_plan_paths: BTreeMap::new(), + sub_ext_bridge_paths: BTreeMap::new(), + sub_ext_derived_from: BTreeMap::new(), + sub_ext_prebuilt_paths: BTreeMap::new(), + sub_ext_shim_alias: BTreeMap::new(), + blob_cas_path: PathBuf::from(".compose/blobs"), + compose_cache_path: PathBuf::from(".compose/cache"), + materialized_sub_exts: HashSet::new(), + composed_digests: HashMap::new(), + } + } + + /// Loader seeded from the three env vars (`DUCKLINK_SUB_EXT_PLANS`, + /// `DUCKLINK_SUB_EXT_BRIDGES`, `DUCKLINK_SUB_EXT_DERIVED`) plus the + /// optional `DUCKLINK_COMPOSE_BLOB_CAS` / `DUCKLINK_COMPOSE_CACHE` + /// overrides for the CAS/cache dirs. Malformed entries are logged and + /// skipped so a typo doesn't abort startup. + pub fn from_env(registry: ProviderRegistry) -> Self { + let mut this = Self::new(registry); + this.sub_ext_plan_paths = parse_map_env("DUCKLINK_SUB_EXT_PLANS"); + this.sub_ext_bridge_paths = parse_map_env("DUCKLINK_SUB_EXT_BRIDGES"); + this.sub_ext_derived_from = parse_map_env("DUCKLINK_SUB_EXT_DERIVED") + .into_iter() + .map(|(k, v)| (k, v.to_string_lossy().into_owned())) + .collect(); + this.sub_ext_prebuilt_paths = parse_map_env("DUCKLINK_SUB_EXT_PREBUILT"); + // Phase 9.1 shared-shim aliases. Same PathBuf-valued parse form + // as `_DERIVED`, but the value is an id string not a path (the + // upstream sub-ext name) — reuse the parser + convert. + this.sub_ext_shim_alias = parse_map_env("DUCKLINK_SUB_EXT_ALIAS") + .into_iter() + .map(|(k, v)| (k, v.to_string_lossy().into_owned())) + .collect(); + if let Ok(p) = std::env::var("DUCKLINK_COMPOSE_BLOB_CAS") { + if !p.trim().is_empty() { + this.blob_cas_path = PathBuf::from(p.trim()); + } + } + if let Ok(p) = std::env::var("DUCKLINK_COMPOSE_CACHE") { + if !p.trim().is_empty() { + this.compose_cache_path = PathBuf::from(p.trim()); + } + } + this + } + + /// True if `sub_ext` has an associated bridge wasm path OR a prebuilt + /// monolith registered under it. `LOAD`'s sub-ext branch takes the + /// bridge from these maps instead of resolving through the flat + /// `/.wasm` shortcut. + /// + /// A prebuilt entry alone is enough to route through the sub-ext + /// branch — the pure-monolith mode ships a single wasm that answers + /// both the composed-provider slot (via `compose:dynlink/endpoint`) + /// and the extension bridge slot, so a user configuring only + /// `DUCKLINK_SUB_EXT_PREBUILT` should still hit materialization + get + /// the prebuilt path back as the bridge to load. + /// [`SubExtLoader::bridge_path`] mirrors this fallback so + /// `has_bridge` ⇔ `bridge_path.is_some()` remains an invariant. + pub fn has_bridge(&self, sub_ext: &str) -> bool { + // A prebuilt/bridge entry on the sub-ext directly, OR an alias + // entry (Phase 9.1) whose upstream has a prebuilt/bridge. Aliased + // subs still need their OWN bridge_paths entry (so the aliased + // bridge wasm gets loaded), but the composed-provider path comes + // from the upstream — so a sub-ext that ONLY has a bridge_paths + // entry and points at an alias upstream via sub_ext_shim_alias + // must still return true here. + if self.sub_ext_prebuilt_paths.contains_key(sub_ext) + || self.sub_ext_bridge_paths.contains_key(sub_ext) + { + return true; + } + if let Some(upstream) = self.sub_ext_shim_alias.get(sub_ext) { + return self.sub_ext_prebuilt_paths.contains_key(upstream) + || self.sub_ext_bridge_paths.contains_key(upstream); + } + false + } + + /// Bridge wasm path for `sub_ext`, if configured. Prefers an explicit + /// `sub_ext_bridge_paths` entry (the plan-driven path's dedicated + /// bridge wasm), falls back to the prebuilt monolith path so the + /// pure-monolith mode (only `DUCKLINK_SUB_EXT_PREBUILT` set) still + /// returns a wasm the LOAD path can instantiate. + pub fn bridge_path(&self, sub_ext: &str) -> Option<&Path> { + self.sub_ext_bridge_paths + .get(sub_ext) + .or_else(|| self.sub_ext_prebuilt_paths.get(sub_ext)) + .map(PathBuf::as_path) + } + + /// Whether this sub-ext has already been composed + registered. + /// Exposed so a test (or the LOAD path's diagnostics) can observe the + /// idempotence guard without racing on repeated composes. + pub fn is_materialized(&self, sub_ext: &str) -> bool { + self.materialized_sub_exts.contains(sub_ext) + } + + /// Compose the sub-ext's plan, write the composed bytes to a stable + /// file under `/composed-providers/`, and register the file + /// under `sub_ext_provider_id(sub_ext)` in the shared + /// `ProviderRegistry`. Ported from + /// `datafission::df-plugin-loader::UnifiedPluginLoader::materialize_sub_ext_provider` + /// (`~/git/datafission/crates/df-plugin-loader/src/loader.rs:337`); the + /// only changes are: + /// * `&mut self` instead of `&self` + `Mutex`-guarded fields + /// (ducklink already threads `Arc>`, so an + /// inner mutex would double-lock); + /// * registration goes through this crate's `ProviderRegistry` handle + /// (which owns the wasmtime engine) rather than + /// `wasm_extension::register_provider_path`. + pub fn materialize_sub_ext_provider(&mut self, sub_ext: &str) -> Result { + let provider_id = sub_ext_provider_id(sub_ext); + + if self.materialized_sub_exts.contains(sub_ext) { + return Ok(provider_id); + } + + // Phase 9.1 shared-shim alias branch. Sub-exts whose composed + // provider IS an upstream sub-ext's provider (e.g. + // postgis_topology / _3d / _metadata / _clustering → postgis_core) + // recurse into the upstream's materialization instead of + // registering a fresh provider under `-composed`. + // + // Order matters: alias takes precedence over both the + // prebuilt shortcut AND the plan-driven compose so aliased subs + // NEVER register their own provider id. The upstream's + // registration (idempotent by id in ProviderRegistry) is what + // the aliased bridge's `resolve-by-id(-composed)` + // baked-in provider id will find at instantiate time. + if let Some(upstream) = self.sub_ext_shim_alias.get(sub_ext).cloned() { + let upstream_id = self.materialize_sub_ext_provider(&upstream)?; + // Mark THIS sub-ext materialized too so a repeat LOAD is a + // no-op (returns the same upstream id without re-recursing). + self.materialized_sub_exts.insert(sub_ext.to_string()); + eprintln!( + "[sub-ext] '{sub_ext}' aliased to '{upstream}' — using shared provider '{upstream_id}'" + ); + return Ok(upstream_id); + } + + // Phase D / Option B short-circuit: if the sub-ext has a + // prebuilt, self-contained composed wasm on disk, register that + // directly and skip the plan-driven compose entirely. This is + // the escape hatch for when the plan-driven per-sub-ext composed + // artifact would leak unresolved sibling-wasm imports (e.g. the + // `postgis-core-composed` 19-import gap) and the application + // ships a monolithic composed wasm as a self-contained fallback. + // + // Preemption order: + // 1. materialized guard (above) — no-op on repeat LOAD + // 2. prebuilt shortcut (here) — register file, done + // 3. plan-driven compose (below) — the normal path + if let Some(prebuilt) = self.sub_ext_prebuilt_paths.get(sub_ext).cloned() { + if !prebuilt.exists() { + return Err(SubExtError::mat( + sub_ext, + &prebuilt, + format!("prebuilt provider wasm not found at {}", prebuilt.display()), + )); + } + self.registry + .register_provider(provider_id.clone(), &prebuilt) + .map_err(|reason| SubExtError::ProviderRegistration { + id: provider_id.clone(), + path: prebuilt.clone(), + reason, + })?; + eprintln!( + "[sub-ext] '{sub_ext}' short-circuit: registered prebuilt monolith \ + {} as provider '{provider_id}'; skipping plan-driven compose", + prebuilt.display() + ); + // Read the prebuilt once and write it into the compose CAS so a + // DOWNSTREAM sub-ext (plan-driven, derived-from this one) can + // splice the digest into its plan and have the bytes waiting at + // `blobs.get(digest)` where compose-core expects them. Without + // this write, mixed mode (postgis_core prebuilt + postgis_raster + // plan-driven → postgis_core) fails with `BlobNotFound` when the + // raster compose walks the derived-from chain. + let bytes = std::fs::read(&prebuilt).map_err(|e| { + SubExtError::mat(sub_ext, &prebuilt, format!("digest read: {e}")) + })?; + let blobs = + BlobStore::new(self.blob_cas_path.clone(), COMPOSE_MAX_BLOB_SIZE).map_err(|e| { + SubExtError::mat( + sub_ext, + &prebuilt, + format!("open blob CAS at {}: {e}", self.blob_cas_path.display()), + ) + })?; + let digest = blobs.put(&bytes).map_err(|e| { + SubExtError::mat( + sub_ext, + &prebuilt, + format!("CAS put for prebuilt shortcut: {e}"), + ) + })?; + self.composed_digests.insert(sub_ext.to_string(), digest); + self.materialized_sub_exts.insert(sub_ext.to_string()); + return Ok(provider_id); + } + + let plan_path = self + .sub_ext_plan_paths + .get(sub_ext) + .cloned() + .ok_or_else(|| SubExtError::PlanMissing { + sub_ext: sub_ext.to_string(), + })?; + + let plan_bytes = std::fs::read(&plan_path) + .map_err(|e| SubExtError::mat(sub_ext, &plan_path, format!("read plan: {e}")))?; + + let mut plan: PlanV1 = serde_json::from_slice(&plan_bytes).map_err(|e| { + SubExtError::mat(sub_ext, &plan_path, format!("parse plan as JSON: {e}")) + })?; + + // Chain-resolve every zero-digest component through the derived-from + // map (recursing back into this method so the idempotence guard + // dedups shared upstreams). This must run BEFORE the EmitHandler is + // constructed — the recursive call opens its own BlobStore/EmitHandler, + // safe because their roots come from `self` and don't nest. + for component in plan.components.iter_mut() { + if !is_zero_digest(&component.digest) { + continue; + } + let upstream = self + .sub_ext_derived_from + .get(&component.id) + .cloned() + .ok_or_else(|| { + SubExtError::mat( + sub_ext, + &plan_path, + format!( + "component '{}' has an all-zero digest placeholder but no \ + sub_ext_derived_from entry maps it to an upstream sub-ext", + component.id + ), + ) + })?; + + self.materialize_sub_ext_provider(&upstream)?; + + let upstream_digest = + self.composed_digests + .get(&upstream) + .cloned() + .ok_or_else(|| { + SubExtError::mat( + sub_ext, + &plan_path, + format!( + "upstream sub-ext '{}' for derived component '{}' composed \ + but produced no cached digest", + upstream, component.id + ), + ) + })?; + component.digest = upstream_digest; + } + + // Compose. compose-core keys on `emit_key = H(plan bytes)`; a repeat + // compose with the same plan cache-hits. + let blobs = BlobStore::new(self.blob_cas_path.clone(), COMPOSE_MAX_BLOB_SIZE).map_err( + |e| { + SubExtError::mat( + sub_ext, + &plan_path, + format!("open blob CAS at {}: {e}", self.blob_cas_path.display()), + ) + }, + )?; + let clock = SystemClock::shared(); + let events = EventCollector::new(clock); + std::fs::create_dir_all(&self.compose_cache_path).map_err(|e| { + SubExtError::mat( + sub_ext, + &plan_path, + format!( + "create compose cache at {}: {e}", + self.compose_cache_path.display() + ), + ) + })?; + + let emit = EmitHandler::new(blobs.clone(), events, self.compose_cache_path.clone()); + let result = emit + .compose(&plan) + .map_err(|e| SubExtError::mat(sub_ext, &plan_path, format!("compose: {e}")))?; + + // Stash the composed digest BEFORE the idempotence insert so a + // downstream sub-ext that recurses in and hits the early return still + // sees the digest cached here. + self.composed_digests + .insert(sub_ext.to_string(), result.digest.clone()); + + // Materialize the composed bytes to a stable file so the process- + // global `ProviderRegistry` can register it by path. + let composed_bytes = blobs.get(&result.digest).map_err(|e| { + SubExtError::mat( + sub_ext, + &plan_path, + format!("read composed artifact from CAS: {e}"), + ) + })?; + let provider_dir = self.blob_cas_path.join("composed-providers"); + std::fs::create_dir_all(&provider_dir).map_err(|e| { + SubExtError::mat( + sub_ext, + &plan_path, + format!("create {}: {e}", provider_dir.display()), + ) + })?; + let provider_path = provider_dir.join(format!("{provider_id}.wasm")); + std::fs::write(&provider_path, &composed_bytes).map_err(|e| { + SubExtError::mat( + sub_ext, + &plan_path, + format!("write {}: {e}", provider_path.display()), + ) + })?; + + self.registry + .register_provider(provider_id.clone(), &provider_path) + .map_err(|reason| SubExtError::ProviderRegistration { + id: provider_id.clone(), + path: provider_path.clone(), + reason, + })?; + + self.materialized_sub_exts.insert(sub_ext.to_string()); + Ok(provider_id) + } +} + +/// Parse `=:=...` into a BTreeMap. `:` is the +/// entry separator (matches datafission's convention) but a `,` is +/// also accepted to be forgiving. Malformed entries are logged to stderr +/// and skipped. +fn parse_map_env(var: &str) -> BTreeMap { + let spec = match std::env::var(var) { + Ok(s) if !s.trim().is_empty() => s, + _ => return BTreeMap::new(), + }; + let mut out = BTreeMap::new(); + for entry in spec + .split(|c: char| c == ':' || c == ',') + .map(str::trim) + .filter(|e| !e.is_empty()) + { + match entry.split_once('=') { + Some((k, v)) if !k.trim().is_empty() && !v.trim().is_empty() => { + out.insert(k.trim().to_string(), PathBuf::from(v.trim())); + } + _ => eprintln!( + "[sub-ext] {var}: skipping malformed entry '{entry}' (expected name=path)" + ), + } + } + out +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn provider_id_is_sub_ext_dash_composed() { + assert_eq!(sub_ext_provider_id("postgis_core"), "postgis_core-composed"); + assert_eq!(sub_ext_provider_id("mobilitydb"), "mobilitydb-composed"); + } + + #[test] + fn is_zero_digest_rejects_empty_and_nonzero() { + assert!(!is_zero_digest(&[])); + assert!(is_zero_digest(&[0u8; 32])); + assert!(!is_zero_digest(&[0u8, 0, 1, 0])); + } + + #[test] + fn prebuilt_shortcut_registers_wasm_and_skips_compose() { + use wasmtime::{Config, Engine}; + + // A minimal valid WebAssembly component (magic + component version). + // Enough for `Component::from_binary` to succeed at registration + // time; the resolve-by-id path never fires in this unit test so + // the exports don't matter. + let component_bytes: Vec = vec![ + 0x00, 0x61, 0x73, 0x6d, // \0asm + 0x0d, 0x00, 0x01, 0x00, // component version + ]; + let tmp = tempfile::tempdir().unwrap(); + let prebuilt = tmp.path().join("postgis-composed.wasm"); + std::fs::write(&prebuilt, &component_bytes).unwrap(); + + let mut cfg = Config::new(); + cfg.wasm_component_model(true); + let engine = Engine::new(&cfg).unwrap(); + let registry = ProviderRegistry::new(engine); + let mut loader = SubExtLoader::new(registry.clone()); + // Point the CAS at the tempdir so the shortcut's `blobs.put` write + // (added to keep the mixed-mode chain's compose invariant intact) + // doesn't pollute the working tree with a `.compose/` dir. + loader.blob_cas_path = tmp.path().join("blobs"); + + // Register prebuilt but no plan; materialize must register-then-return. + loader + .sub_ext_prebuilt_paths + .insert("postgis_core".to_string(), prebuilt.clone()); + + let id = loader + .materialize_sub_ext_provider("postgis_core") + .expect("prebuilt shortcut must succeed with no plan"); + assert_eq!(id, "postgis_core-composed"); + assert!(loader.is_materialized("postgis_core")); + + // Second call is a no-op via the materialized guard. + assert_eq!( + loader.materialize_sub_ext_provider("postgis_core").unwrap(), + id + ); + + // Provider is registered (compile-time only, no resident instance). + assert_eq!(registry.resident_count(&id), 0); + } + + #[test] + fn shim_alias_recurses_to_upstream_and_shares_provider_id() { + use wasmtime::{Config, Engine}; + + let component_bytes: Vec = vec![ + 0x00, 0x61, 0x73, 0x6d, // \0asm + 0x0d, 0x00, 0x01, 0x00, // component version + ]; + let tmp = tempfile::tempdir().unwrap(); + let prebuilt = tmp.path().join("postgis-core-composed.wasm"); + std::fs::write(&prebuilt, &component_bytes).unwrap(); + + let mut cfg = Config::new(); + cfg.wasm_component_model(true); + let engine = Engine::new(&cfg).unwrap(); + let registry = ProviderRegistry::new(engine); + let mut loader = SubExtLoader::new(registry.clone()); + loader.blob_cas_path = tmp.path().join("blobs"); + + // postgis_core has a real prebuilt; postgis_topology and + // postgis_3d alias into it — no prebuilt or plan of their own. + loader + .sub_ext_prebuilt_paths + .insert("postgis_core".into(), prebuilt.clone()); + loader + .sub_ext_shim_alias + .insert("postgis_topology".into(), "postgis_core".into()); + loader + .sub_ext_shim_alias + .insert("postgis_3d".into(), "postgis_core".into()); + + // Materialize the aliased sub — must return the UPSTREAM + // provider id, not `postgis_topology-composed`. + let topology_id = loader + .materialize_sub_ext_provider("postgis_topology") + .expect("alias must resolve to upstream materialization"); + assert_eq!(topology_id, "postgis_core-composed"); + + // Both aliased AND upstream marked materialized so repeat LOADs + // are no-ops. + assert!(loader.is_materialized("postgis_topology")); + assert!(loader.is_materialized("postgis_core")); + + // Second aliased sub also resolves to the same shared upstream — + // proves one shim answers all N aliased children. + let threed_id = loader + .materialize_sub_ext_provider("postgis_3d") + .expect("second alias must reuse upstream provider"); + assert_eq!(threed_id, "postgis_core-composed"); + + // Registry has exactly ONE registration under + // `postgis_core-composed`. Neither `postgis_topology-composed` + // nor `postgis_3d-composed` was ever registered. + assert_eq!(registry.resident_count("postgis_core-composed"), 0); + assert_eq!(registry.resident_count("postgis_topology-composed"), 0); + assert_eq!(registry.resident_count("postgis_3d-composed"), 0); + } + + #[test] + fn parse_map_env_handles_colon_and_comma_separators() { + // Use unique env var names so parallel test threads don't clobber + // each other. std::env::set_var is `unsafe` from Rust 2024 onward; + // the crate is edition 2021 so the plain call is stable here. + std::env::set_var("DUCKLINK_TEST_MAP_ENV_A", "a=/x:b=/y"); + let m = parse_map_env("DUCKLINK_TEST_MAP_ENV_A"); + assert_eq!(m.get("a"), Some(&PathBuf::from("/x"))); + assert_eq!(m.get("b"), Some(&PathBuf::from("/y"))); + + std::env::set_var("DUCKLINK_TEST_MAP_ENV_B", "c=/p,d=/q"); + let m = parse_map_env("DUCKLINK_TEST_MAP_ENV_B"); + assert_eq!(m.get("c"), Some(&PathBuf::from("/p"))); + assert_eq!(m.get("d"), Some(&PathBuf::from("/q"))); + + std::env::remove_var("DUCKLINK_TEST_MAP_ENV_C"); + assert!(parse_map_env("DUCKLINK_TEST_MAP_ENV_C").is_empty()); + + std::env::remove_var("DUCKLINK_TEST_MAP_ENV_A"); + std::env::remove_var("DUCKLINK_TEST_MAP_ENV_B"); + } +} diff --git a/crates/ducklink-host/tests/sub_ext_materialize.rs b/crates/ducklink-host/tests/sub_ext_materialize.rs new file mode 100644 index 00000000..7e562a18 --- /dev/null +++ b/crates/ducklink-host/tests/sub_ext_materialize.rs @@ -0,0 +1,296 @@ +//! Phase D: materialize_sub_ext_provider integration test. +//! +//! Configures `sub_ext_bridge_paths["postgis_core"] = ` +//! and `sub_ext_plan_paths["postgis_core"] = ` against +//! an in-tempdir compose CAS, seeds the CAS with a minimal component +//! blob, then calls `SubExtLoader::materialize_sub_ext_provider("postgis_core")` +//! and asserts: +//! +//! * the returned provider id is `postgis_core-composed`, +//! * the composed bytes are materialized to +//! `/composed-providers/postgis_core-composed.wasm`, +//! * the composed provider is now registered in the shared +//! `ProviderRegistry` (the same registry `LOAD` consults for a bridge +//! that imports `compose:dynlink/linker.resolve-by-id("postgis_core-composed")`), +//! * a second call is a no-op (idempotence guard), and +//! * `has_bridge(...)` correctly reports which sub-exts should take the +//! bridge branch in `ensure_extension_loaded`. +//! +//! Mirrors the shape of `tests/compose_dynlink_dlopen.rs` (same registry +//! + same engine wiring) so it fails alongside that test when the +//! `compose:dynlink` plumbing regresses. The bridge wasm is a +//! placeholder (a minimal component so `.exists()` succeeds if the +//! caller ever runs the ensure-load side, and no more) — Phase D's +//! contract is registry population, not bridge instantiation, which +//! `compose_dynlink_dlopen.rs` already covers end-to-end. + +use std::path::PathBuf; + +use compose_core::blobs::BlobStore; +use compose_core::types::{ComponentSpec, PlanV1, Policy}; +use ducklink_host::{sub_ext_provider_id, ProviderRegistry, SubExtLoader}; +use wasmtime::{Config, Engine}; + +/// Minimal valid WebAssembly component (magic + component version). +/// Same fixture the compose-core tests use for plan composition. +fn minimal_component_bytes() -> Vec { + vec![ + 0x00, 0x61, 0x73, 0x6d, // \0asm + 0x0d, 0x00, 0x01, 0x00, // component version + ] +} + +fn test_engine() -> Engine { + let mut config = Config::new(); + config.wasm_component_model(true); + Engine::new(&config).expect("engine") +} + +#[test] +fn materialize_sub_ext_provider_composes_registers_and_is_idempotent() { + let workdir = tempfile::tempdir().expect("tempdir"); + let cas = workdir.path().join("blobs"); + let cache = workdir.path().join("cache"); + std::fs::create_dir_all(&cas).unwrap(); + std::fs::create_dir_all(&cache).unwrap(); + + // 1. Seed the blob CAS with a valid minimal component and get its + // content digest. compose-core's EmitHandler will look up the plan's + // root component by this digest and emit it (a single-component plan + // is a passthrough — the emit result's digest equals the input's). + let blobs = BlobStore::new(cas.clone(), 1 << 20).expect("blob store"); + let component_bytes = minimal_component_bytes(); + let digest = blobs.put(&component_bytes).expect("put component blob"); + + // 2. Write a PlanV1 JSON on disk that points at that blob as its + // single root component. materialize_sub_ext_provider parses this + // from disk before composing. + let plan = PlanV1 { + version: "1".to_string(), + root: "root".to_string(), + components: vec![ComponentSpec { + id: "root".to_string(), + digest: digest.clone(), + source: None, + }], + bindings: vec![], + secrets: vec![], + policy: Policy::default(), + linkage: Default::default(), + explicit_exports: vec![], + }; + let plan_path = workdir.path().join("postgis-composed.plan.json"); + std::fs::write(&plan_path, serde_json::to_vec_pretty(&plan).unwrap()).unwrap(); + + // 3. Also drop a placeholder bridge wasm so `has_bridge` -> path -> exists + // exercises the same code path the extension load will take. The + // bytes don't need to be a valid component here — this test only + // covers the registry-population side of Phase D (the actual + // bridge instantiation is covered by `compose_dynlink_dlopen.rs`). + let bridge_path = workdir.path().join("postgis_core_bridge.wasm"); + std::fs::write(&bridge_path, minimal_component_bytes()).unwrap(); + + // 4. Build the shared engine + provider registry (the same wiring + // ExtensionManager uses at runtime) and seed the SubExtLoader. + let engine = test_engine(); + let registry = ProviderRegistry::new(engine.clone()); + let mut loader = SubExtLoader::new(registry.clone()); + loader.blob_cas_path = cas.clone(); + loader.compose_cache_path = cache.clone(); + loader + .sub_ext_plan_paths + .insert("postgis_core".to_string(), plan_path.clone()); + loader + .sub_ext_bridge_paths + .insert("postgis_core".to_string(), bridge_path.clone()); + + // 5. has_bridge routes LOAD through the sub-ext branch; an unknown + // name falls through to the standard extensions-dir resolution. + assert!(loader.has_bridge("postgis_core")); + assert!(!loader.has_bridge("httpfs")); + assert_eq!( + loader.bridge_path("postgis_core"), + Some(bridge_path.as_path()) + ); + + // 6. Materialize. Returns the canonical provider id and, as a + // side effect, (a) writes composed bytes to the CAS's + // `composed-providers/` subdir, (b) registers those bytes under + // that id in the shared registry. + let provider_id = loader + .materialize_sub_ext_provider("postgis_core") + .expect("materialize sub-ext provider"); + assert_eq!(provider_id, "postgis_core-composed"); + assert_eq!(provider_id, sub_ext_provider_id("postgis_core")); + + // 7. Composed wasm is written to a stable, path-registerable file. + let composed_wasm = cas + .join("composed-providers") + .join("postgis_core-composed.wasm"); + assert!( + composed_wasm.exists(), + "composed provider bytes must be materialized at {}", + composed_wasm.display() + ); + + // 8. Idempotence — a re-issued LOAD hits the materialized guard and + // no-ops. It must NOT touch the CAS / registry a second time. + assert!(loader.is_materialized("postgis_core")); + let provider_id_again = loader + .materialize_sub_ext_provider("postgis_core") + .expect("idempotent materialize"); + assert_eq!(provider_id_again, provider_id); + + // 9. Provider is now resolvable by any bridge that plugs it. + // resident_count starts at 0 (materialization only *registers* + + // compiles the provider; instantiation is lazy on first + // resolve-by-id call from a bridge). Non-zero would indicate an + // unwanted eager instantiation. + assert_eq!( + registry.resident_count(&provider_id), + 0, + "provider must be registered but NOT yet instantiated after materialize" + ); +} + +#[test] +fn materialize_sub_ext_provider_reports_missing_plan() { + let engine = test_engine(); + let registry = ProviderRegistry::new(engine.clone()); + let mut loader = SubExtLoader::new(registry); + // No plan registered → PlanMissing error, no partial materialization. + let err = loader + .materialize_sub_ext_provider("unknown_ext") + .expect_err("must report PlanMissing when nothing is configured"); + match err { + ducklink_host::SubExtError::PlanMissing { sub_ext } => { + assert_eq!(sub_ext, "unknown_ext"); + } + other => panic!("expected PlanMissing, got {other:?}"), + } + assert!(!loader.is_materialized("unknown_ext")); +} + +#[test] +fn has_bridge_and_bridge_path_wire_the_load_time_branch() { + let engine = test_engine(); + let registry = ProviderRegistry::new(engine); + let mut loader = SubExtLoader::new(registry); + let bridge_path = PathBuf::from("/tmp/postgis_core_bridge.wasm"); + loader + .sub_ext_bridge_paths + .insert("postgis_core".to_string(), bridge_path.clone()); + assert!(loader.has_bridge("postgis_core")); + assert_eq!(loader.bridge_path("postgis_core"), Some(bridge_path.as_path())); + assert!(!loader.has_bridge("mobilitydb")); + assert_eq!(loader.bridge_path("mobilitydb"), None); +} + +#[test] +fn prebuilt_only_config_routes_through_sub_ext_branch() { + // In the pure-monolith mode the user sets DUCKLINK_SUB_EXT_PREBUILT + // alone (per the postgis-wasm README). `has_bridge` must still return + // true for that sub-ext so LOAD takes the sub-ext branch instead of + // the flat resolver, and `bridge_path` must fall back to the prebuilt + // wasm so the .expect() in ExtensionManager doesn't panic. + let engine = test_engine(); + let registry = ProviderRegistry::new(engine); + let mut loader = SubExtLoader::new(registry); + let prebuilt = PathBuf::from("/tmp/postgis-monolith-provider.wasm"); + loader + .sub_ext_prebuilt_paths + .insert("postgis_core".to_string(), prebuilt.clone()); + assert!(loader.has_bridge("postgis_core")); + assert_eq!(loader.bridge_path("postgis_core"), Some(prebuilt.as_path())); + // Explicit bridge still wins when both are set. + let bridge = PathBuf::from("/tmp/postgis_core_bridge.wasm"); + loader + .sub_ext_bridge_paths + .insert("postgis_core".to_string(), bridge.clone()); + assert_eq!(loader.bridge_path("postgis_core"), Some(bridge.as_path())); +} + +#[test] +fn mixed_mode_prebuilt_upstream_seeds_cas_for_derived_plan() { + // The regression this pins: postgis_core registered as prebuilt + + // postgis_raster driven by a plan that has a zero-digest placeholder + // component derived from postgis_core. Before the fix the prebuilt + // shortcut cached sha256(prebuilt) in composed_digests but never + // wrote the bytes into the CAS, so the raster compose walked the + // derived-from chain, spliced the prebuilt digest into the raster + // plan, then failed with BlobNotFound when compose-core tried to + // read those bytes back from the CAS. + let workdir = tempfile::tempdir().expect("tempdir"); + let cas = workdir.path().join("blobs"); + let cache = workdir.path().join("cache"); + std::fs::create_dir_all(&cas).unwrap(); + std::fs::create_dir_all(&cache).unwrap(); + + // Prebuilt monolith for postgis_core. Contents are the minimal valid + // component blob so wasmtime accepts them at registration time. + let prebuilt = workdir.path().join("postgis-monolith-provider.wasm"); + std::fs::write(&prebuilt, minimal_component_bytes()).unwrap(); + + // Plan for postgis_raster: one component with an all-zero digest + // that will be spliced via sub_ext_derived_from -> postgis_core. + // A single-component plan composes as a passthrough — the result + // digest equals the spliced input digest — so we don't need to + // model raster-specific bytes here. + let raster_plan = PlanV1 { + version: "1".to_string(), + root: "root".to_string(), + components: vec![ComponentSpec { + id: "root".to_string(), + digest: vec![0u8; 32], + source: None, + }], + bindings: vec![], + secrets: vec![], + policy: Policy::default(), + linkage: Default::default(), + explicit_exports: vec![], + }; + let raster_plan_path = workdir.path().join("postgis-raster.plan.json"); + std::fs::write( + &raster_plan_path, + serde_json::to_vec_pretty(&raster_plan).unwrap(), + ) + .unwrap(); + + let engine = test_engine(); + let registry = ProviderRegistry::new(engine); + let mut loader = SubExtLoader::new(registry); + loader.blob_cas_path = cas.clone(); + loader.compose_cache_path = cache; + loader + .sub_ext_prebuilt_paths + .insert("postgis_core".to_string(), prebuilt.clone()); + loader + .sub_ext_plan_paths + .insert("postgis_raster".to_string(), raster_plan_path); + loader + .sub_ext_derived_from + .insert("root".to_string(), "postgis_core".to_string()); + + // Materialize the downstream. This recurses into postgis_core (which + // hits the prebuilt shortcut), splices the resolved digest into the + // raster plan, then composes. Without the CAS-write fix, the compose + // step returns BlobNotFound for the spliced digest. + let raster_id = loader + .materialize_sub_ext_provider("postgis_raster") + .expect("mixed-mode chain must resolve prebuilt upstream via CAS"); + assert_eq!(raster_id, "postgis_raster-composed"); + assert!(loader.is_materialized("postgis_core")); + assert!(loader.is_materialized("postgis_raster")); + + // The prebuilt's bytes are readable from the compose CAS at the + // digest cached under postgis_core — this is the invariant every + // downstream compose relies on. + let blobs = BlobStore::new(cas, 1 << 20).expect("open CAS"); + let prebuilt_bytes = std::fs::read(&prebuilt).unwrap(); + let digest = compose_core::blobs::compute_digest(&prebuilt_bytes); + let round_trip = blobs + .get(&digest) + .expect("prebuilt bytes must be present in CAS after shortcut"); + assert_eq!(round_trip, prebuilt_bytes); +} diff --git a/crates/ducklink-loader/src/bindings.rs b/crates/ducklink-loader/src/bindings.rs index 1f10793b..25fc307c 100644 --- a/crates/ducklink-loader/src/bindings.rs +++ b/crates/ducklink-loader/src/bindings.rs @@ -569,6 +569,219 @@ pub mod duckdb { } } } + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod column_types { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::__link_custom_section_describing_imports; + use super::super::super::_rt; + /// Re-used flat records from the row-major model (identical layout). + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Decimalvalue { + pub lower: u64, + pub upper: u64, + pub width: u8, + pub scale: u8, + } + impl ::core::fmt::Debug for Decimalvalue { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Decimalvalue") + .field("lower", &self.lower) + .field("upper", &self.upper) + .field("width", &self.width) + .field("scale", &self.scale) + .finish() + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Intervalvalue { + pub months: i32, + pub days: i32, + pub micros: i64, + } + impl ::core::fmt::Debug for Intervalvalue { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Intervalvalue") + .field("months", &self.months) + .field("days", &self.days) + .field("micros", &self.micros) + .finish() + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Uuidvalue { + pub hi: u64, + pub lo: u64, + } + impl ::core::fmt::Debug for Uuidvalue { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Uuidvalue") + .field("hi", &self.hi) + .field("lo", &self.lo) + .finish() + } + } + #[derive(Clone)] + pub struct Complexvalue { + pub type_expr: _rt::String, + pub json: _rt::String, + } + impl ::core::fmt::Debug for Complexvalue { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Complexvalue") + .field("type-expr", &self.type_expr) + .field("json", &self.json) + .finish() + } + } + /// A typed, contiguous COLUMN: one buffer per DuckDB physical type. DuckDB + /// vectors are ALREADY flat contiguous arrays, so the core fills these arms by + /// memcpy-ing straight from `duckdb_vector_get_data` -- no per-cell read loop. + /// + /// Fixed-width arms (boolean..uuid) lower/lift as a bulk memcpy. The two + /// variable-width arms (text/blob) stay element-wise -- unavoidable for + /// var-len data, and identical in cost to the row-major path for those types. + /// The escape hatch (`complex`) is also element-wise; FUTURE composite types + /// ride it with no further contract bump, exactly as the row-major `complex`. + #[derive(Clone)] + pub enum Column { + Boolean(_rt::Vec), + Int64(_rt::Vec), + Uint64(_rt::Vec), + Float64(_rt::Vec), + Int32(_rt::Vec), + Timestamp(_rt::Vec), + Int8(_rt::Vec), + Int16(_rt::Vec), + Uint8(_rt::Vec), + Uint16(_rt::Vec), + Uint32(_rt::Vec), + Float32(_rt::Vec), + Date(_rt::Vec), + Time(_rt::Vec), + Timestamptz(_rt::Vec), + Decimal(_rt::Vec), + Interval(_rt::Vec), + Uuid(_rt::Vec), + Text(_rt::Vec<_rt::String>), + Blob(_rt::Vec<_rt::Vec>), + Complex(_rt::Vec), + } + impl ::core::fmt::Debug for Column { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + Column::Boolean(e) => { + f.debug_tuple("Column::Boolean").field(e).finish() + } + Column::Int64(e) => { + f.debug_tuple("Column::Int64").field(e).finish() + } + Column::Uint64(e) => { + f.debug_tuple("Column::Uint64").field(e).finish() + } + Column::Float64(e) => { + f.debug_tuple("Column::Float64").field(e).finish() + } + Column::Int32(e) => { + f.debug_tuple("Column::Int32").field(e).finish() + } + Column::Timestamp(e) => { + f.debug_tuple("Column::Timestamp").field(e).finish() + } + Column::Int8(e) => { + f.debug_tuple("Column::Int8").field(e).finish() + } + Column::Int16(e) => { + f.debug_tuple("Column::Int16").field(e).finish() + } + Column::Uint8(e) => { + f.debug_tuple("Column::Uint8").field(e).finish() + } + Column::Uint16(e) => { + f.debug_tuple("Column::Uint16").field(e).finish() + } + Column::Uint32(e) => { + f.debug_tuple("Column::Uint32").field(e).finish() + } + Column::Float32(e) => { + f.debug_tuple("Column::Float32").field(e).finish() + } + Column::Date(e) => { + f.debug_tuple("Column::Date").field(e).finish() + } + Column::Time(e) => { + f.debug_tuple("Column::Time").field(e).finish() + } + Column::Timestamptz(e) => { + f.debug_tuple("Column::Timestamptz").field(e).finish() + } + Column::Decimal(e) => { + f.debug_tuple("Column::Decimal").field(e).finish() + } + Column::Interval(e) => { + f.debug_tuple("Column::Interval").field(e).finish() + } + Column::Uuid(e) => { + f.debug_tuple("Column::Uuid").field(e).finish() + } + Column::Text(e) => { + f.debug_tuple("Column::Text").field(e).finish() + } + Column::Blob(e) => { + f.debug_tuple("Column::Blob").field(e).finish() + } + Column::Complex(e) => { + f.debug_tuple("Column::Complex").field(e).finish() + } + } + } + } + /// A column plus its validity + row count -- the unit of columnar transfer. + /// + /// `validity` is a packed little-endian bitmap (bit i set => row i valid), + /// byte-for-byte the layout of DuckDB's own validity mask, so the core copies + /// `duckdb_vector_get_validity` straight in. An EMPTY bitmap means "all rows + /// valid" (the common fast path: zero allocation, mirroring DuckDB's null + /// validity pointer). NULL is carried out-of-band here, so the data buffer + /// stays a flat typed array -- NULL handling is identical to the row-major + /// path (where a NULL is the `duckvalue.null` arm). + #[derive(Clone)] + pub struct Colvec { + pub data: Column, + pub validity: _rt::Vec, + pub rows: u32, + } + impl ::core::fmt::Debug for Colvec { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("Colvec") + .field("data", &self.data) + .field("validity", &self.validity) + .field("rows", &self.rows) + .finish() + } + } + } } } #[rustfmt::skip] @@ -3349,6 +3562,13 @@ pub mod exports { } } pub mod extension { + /// major-4 COLUMNAR dispatch. The hot path (per-DataChunk scalar / aggregate / + /// cast) is now columnar: arguments cross the canonical ABI as typed `colvec`s + /// (one bulk memcpy per fixed-width column) instead of the row-major + /// `list>` tagged-variant batch that major-3 used. The cold + /// singleton paths (call-scalar / call-table / call-pragma / call-cast) stay + /// row-major `duckvalue` for ergonomics -- they are off the hot path. See + /// column-types.wit and docs/v4-columnar-abi.md. #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] pub mod callback_dispatch { #[used] @@ -3359,10 +3579,10 @@ pub mod exports { pub type Duckvalue = super::super::super::super::duckdb::extension::types::Duckvalue; pub type Invokeinfo = super::super::super::super::duckdb::extension::types::Invokeinfo; pub type Resultset = super::super::super::super::duckdb::extension::types::Resultset; - pub type Rowbatch = super::super::super::super::duckdb::extension::types::Rowbatch; + pub type Colvec = super::super::super::super::duckdb::extension::column_types::Colvec; #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_call_scalar_cabi( + pub unsafe fn _export_call_scalar_batch_col_cabi( arg0: i32, arg1: *mut u8, arg2: usize, @@ -3371,233 +3591,417 @@ pub mod exports { arg5: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - let base38 = arg1; - let len38 = arg2; - let mut result38 = _rt::Vec::with_capacity(len38); - for i in 0..len38 { - let base = base38 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - let e38 = { + let base82 = arg1; + let len82 = arg2; + let mut result82 = _rt::Vec::with_capacity(len82); + for i in 0..len82 { + let base = base82 + .add(i * (6 * ::core::mem::size_of::<*const u8>())); + let e82 = { let l0 = i32::from(*base.add(0).cast::()); - use super::super::super::super::duckdb::extension::types::Duckvalue as V37; - let v37 = match l0 { - 0 => V37::Null, + use super::super::super::super::duckdb::extension::column_types::Column as V77; + let v77 = match l0 { + 0 => { + let e77 = { + let l1 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l1; + let len4 = l2; + let mut result4 = _rt::Vec::with_capacity(len4); + for i in 0..len4 { + let base = base4.add(i * 1); + let e4 = { + let l3 = i32::from(*base.add(0).cast::()); + _rt::bool_lift(l3 as u8) + }; + result4.push(e4); + } + _rt::cabi_dealloc(base4, len4 * 1, 1); + result4 + }; + V77::Boolean(e77) + } 1 => { - let e37 = { - let l1 = i32::from(*base.add(8).cast::()); - _rt::bool_lift(l1 as u8) + let e77 = { + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + _rt::Vec::from_raw_parts(l5.cast(), len7, len7) }; - V37::Boolean(e37) + V77::Int64(e77) } 2 => { - let e37 = { - let l2 = *base.add(8).cast::(); - l2 + let e77 = { + let l8 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) }; - V37::Int64(e37) + V77::Uint64(e77) } 3 => { - let e37 = { - let l3 = *base.add(8).cast::(); - l3 as u64 + let e77 = { + let l11 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len13 = l12; + _rt::Vec::from_raw_parts(l11.cast(), len13, len13) }; - V37::Uint64(e37) + V77::Float64(e77) } 4 => { - let e37 = { - let l4 = *base.add(8).cast::(); - l4 + let e77 = { + let l14 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len16 = l15; + _rt::Vec::from_raw_parts(l14.cast(), len16, len16) }; - V37::Float64(e37) + V77::Int32(e77) } 5 => { - let e37 = { - let l5 = *base.add(8).cast::<*mut u8>(); - let l6 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let e77 = { + let l17 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len7 = l6; - let bytes7 = _rt::Vec::from_raw_parts( - l5.cast(), - len7, - len7, - ); - _rt::string_lift(bytes7) + let len19 = l18; + _rt::Vec::from_raw_parts(l17.cast(), len19, len19) }; - V37::Text(e37) + V77::Timestamp(e77) } 6 => { - let e37 = { - let l8 = *base.add(8).cast::<*mut u8>(); - let l9 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let e77 = { + let l20 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len10 = l9; - _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + let len22 = l21; + _rt::Vec::from_raw_parts(l20.cast(), len22, len22) }; - V37::Blob(e37) + V77::Int8(e77) } 7 => { - let e37 = { - let l11 = *base.add(8).cast::(); - l11 + let e77 = { + let l23 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l24 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len25 = l24; + _rt::Vec::from_raw_parts(l23.cast(), len25, len25) }; - V37::Int32(e37) + V77::Int16(e77) } 8 => { - let e37 = { - let l12 = *base.add(8).cast::(); - l12 + let e77 = { + let l26 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len28 = l27; + _rt::Vec::from_raw_parts(l26.cast(), len28, len28) }; - V37::Timestamp(e37) + V77::Uint8(e77) } 9 => { - let e37 = { - let l13 = i32::from(*base.add(8).cast::()); - l13 as i8 + let e77 = { + let l29 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l30 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len31 = l30; + _rt::Vec::from_raw_parts(l29.cast(), len31, len31) }; - V37::Int8(e37) + V77::Uint16(e77) } 10 => { - let e37 = { - let l14 = i32::from(*base.add(8).cast::()); - l14 as i16 + let e77 = { + let l32 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l33 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len34 = l33; + _rt::Vec::from_raw_parts(l32.cast(), len34, len34) }; - V37::Int16(e37) + V77::Uint32(e77) } 11 => { - let e37 = { - let l15 = i32::from(*base.add(8).cast::()); - l15 as u8 + let e77 = { + let l35 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l36 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len37 = l36; + _rt::Vec::from_raw_parts(l35.cast(), len37, len37) }; - V37::Uint8(e37) + V77::Float32(e77) } 12 => { - let e37 = { - let l16 = i32::from(*base.add(8).cast::()); - l16 as u16 + let e77 = { + let l38 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len40 = l39; + _rt::Vec::from_raw_parts(l38.cast(), len40, len40) }; - V37::Uint16(e37) + V77::Date(e77) } 13 => { - let e37 = { - let l17 = *base.add(8).cast::(); - l17 as u32 + let e77 = { + let l41 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l42 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len43 = l42; + _rt::Vec::from_raw_parts(l41.cast(), len43, len43) }; - V37::Uint32(e37) + V77::Time(e77) } 14 => { - let e37 = { - let l18 = *base.add(8).cast::(); - l18 + let e77 = { + let l44 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l45 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len46 = l45; + _rt::Vec::from_raw_parts(l44.cast(), len46, len46) }; - V37::Float32(e37) + V77::Timestamptz(e77) } 15 => { - let e37 = { - let l19 = *base.add(8).cast::(); - l19 + let e77 = { + let l47 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l48 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len49 = l48; + _rt::Vec::from_raw_parts(l47.cast(), len49, len49) }; - V37::Date(e37) + V77::Decimal(e77) } 16 => { - let e37 = { - let l20 = *base.add(8).cast::(); - l20 + let e77 = { + let l50 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l51 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len52 = l51; + _rt::Vec::from_raw_parts(l50.cast(), len52, len52) }; - V37::Time(e37) + V77::Interval(e77) } 17 => { - let e37 = { - let l21 = *base.add(8).cast::(); - l21 + let e77 = { + let l53 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l54 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len55 = l54; + _rt::Vec::from_raw_parts(l53.cast(), len55, len55) }; - V37::Timestamptz(e37) + V77::Uuid(e77) } 18 => { - let e37 = { - let l22 = *base.add(8).cast::(); - let l23 = *base.add(16).cast::(); - let l24 = i32::from(*base.add(24).cast::()); - let l25 = i32::from(*base.add(25).cast::()); - super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: l22 as u64, - upper: l23 as u64, - width: l24 as u8, - scale: l25 as u8, + let e77 = { + let l56 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l57 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base61 = l56; + let len61 = l57; + let mut result61 = _rt::Vec::with_capacity(len61); + for i in 0..len61 { + let base = base61 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e61 = { + let l58 = *base.add(0).cast::<*mut u8>(); + let l59 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len60 = l59; + let bytes60 = _rt::Vec::from_raw_parts( + l58.cast(), + len60, + len60, + ); + _rt::string_lift(bytes60) + }; + result61.push(e61); } + _rt::cabi_dealloc( + base61, + len61 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result61 }; - V37::Decimal(e37) + V77::Text(e77) } 19 => { - let e37 = { - let l26 = *base.add(8).cast::(); - let l27 = *base.add(12).cast::(); - let l28 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Intervalvalue { - months: l26, - days: l27, - micros: l28, - } - }; - V37::Interval(e37) - } - 20 => { - let e37 = { - let l29 = *base.add(8).cast::(); - let l30 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: l29 as u64, - lo: l30 as u64, + let e77 = { + let l62 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l63 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base67 = l62; + let len67 = l63; + let mut result67 = _rt::Vec::with_capacity(len67); + for i in 0..len67 { + let base = base67 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e67 = { + let l64 = *base.add(0).cast::<*mut u8>(); + let l65 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len66 = l65; + _rt::Vec::from_raw_parts(l64.cast(), len66, len66) + }; + result67.push(e67); } + _rt::cabi_dealloc( + base67, + len67 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result67 }; - V37::Uuid(e37) + V77::Blob(e77) } n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); - let e37 = { - let l31 = *base.add(8).cast::<*mut u8>(); - let l32 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len33 = l32; - let bytes33 = _rt::Vec::from_raw_parts( - l31.cast(), - len33, - len33, - ); - let l34 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + debug_assert_eq!(n, 20, "invalid enum discriminant"); + let e77 = { + let l68 = *base + .add(::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l35 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + let l69 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len36 = l35; - let bytes36 = _rt::Vec::from_raw_parts( - l34.cast(), - len36, - len36, - ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes33), - json: _rt::string_lift(bytes36), + let base76 = l68; + let len76 = l69; + let mut result76 = _rt::Vec::with_capacity(len76); + for i in 0..len76 { + let base = base76 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + let e76 = { + let l70 = *base.add(0).cast::<*mut u8>(); + let l71 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len72 = l71; + let bytes72 = _rt::Vec::from_raw_parts( + l70.cast(), + len72, + len72, + ); + let l73 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l74 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len75 = l74; + let bytes75 = _rt::Vec::from_raw_parts( + l73.cast(), + len75, + len75, + ); + super::super::super::super::duckdb::extension::column_types::Complexvalue { + type_expr: _rt::string_lift(bytes72), + json: _rt::string_lift(bytes75), + } + }; + result76.push(e76); } + _rt::cabi_dealloc( + base76, + len76 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result76 }; - V37::Complex(e37) + V77::Complex(e77) } }; - v37 + let l78 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l79 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len80 = l79; + let l81 = *base + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::(); + super::super::super::super::duckdb::extension::column_types::Colvec { + data: v77, + validity: _rt::Vec::from_raw_parts( + l78.cast(), + len80, + len80, + ), + rows: l81 as u32, + } }; - result38.push(e38); + result82.push(e82); } _rt::cabi_dealloc( - base38, - len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, + base82, + len82 * (6 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), ); - let result39 = T::call_scalar( + let result83 = T::call_scalar_batch_col( arg0 as u32, - result38, + result82, super::super::super::super::duckdb::extension::types::Invokeinfo { rowindex: match arg3 { 0 => None, @@ -3610,340 +4014,897 @@ pub mod exports { iswindow: _rt::bool_lift(arg5 as u8), }, ); - let ptr40 = (&raw mut _RET_AREA.0).cast::(); - match result39 { + let ptr84 = (&raw mut _RET_AREA.0).cast::(); + match result83 { Ok(e) => { - *ptr40.add(0).cast::() = (0i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckvalue as V49; - match e { - V49::Null => { - *ptr40.add(8).cast::() = (0i32) as u8; + *ptr84.add(0).cast::() = (0i32) as u8; + let super::super::super::super::duckdb::extension::column_types::Colvec { + data: data85, + validity: validity85, + rows: rows85, + } = e; + use super::super::super::super::duckdb::extension::column_types::Column as V112; + match data85 { + V112::Boolean(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec86 = e; + let len86 = vec86.len(); + let layout86 = _rt::alloc::Layout::from_size_align_unchecked( + vec86.len() * 1, + 1, + ); + let result86 = if layout86.size() != 0 { + let ptr = _rt::alloc::alloc(layout86).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout86); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec86.into_iter().enumerate() { + let base = result86.add(i * 1); + { + *base.add(0).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + } + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len86; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result86; } - V49::Boolean(e) => { - *ptr40.add(8).cast::() = (1i32) as u8; - *ptr40.add(16).cast::() = (match e { - true => 1, - false => 0, - }) as u8; + V112::Int64(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec87 = (e).into_boxed_slice(); + let ptr87 = vec87.as_ptr().cast::(); + let len87 = vec87.len(); + ::core::mem::forget(vec87); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len87; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr87.cast_mut(); } - V49::Int64(e) => { - *ptr40.add(8).cast::() = (2i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i64(e); + V112::Uint64(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec88 = (e).into_boxed_slice(); + let ptr88 = vec88.as_ptr().cast::(); + let len88 = vec88.len(); + ::core::mem::forget(vec88); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len88; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr88.cast_mut(); } - V49::Uint64(e) => { - *ptr40.add(8).cast::() = (3i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i64(e); + V112::Float64(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec89 = (e).into_boxed_slice(); + let ptr89 = vec89.as_ptr().cast::(); + let len89 = vec89.len(); + ::core::mem::forget(vec89); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len89; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr89.cast_mut(); } - V49::Float64(e) => { - *ptr40.add(8).cast::() = (4i32) as u8; - *ptr40.add(16).cast::() = _rt::as_f64(e); + V112::Int32(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec90 = (e).into_boxed_slice(); + let ptr90 = vec90.as_ptr().cast::(); + let len90 = vec90.len(); + ::core::mem::forget(vec90); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len90; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr90.cast_mut(); } - V49::Text(e) => { - *ptr40.add(8).cast::() = (5i32) as u8; - let vec41 = (e.into_bytes()).into_boxed_slice(); - let ptr41 = vec41.as_ptr().cast::(); - let len41 = vec41.len(); - ::core::mem::forget(vec41); - *ptr40 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len41; - *ptr40.add(16).cast::<*mut u8>() = ptr41.cast_mut(); + V112::Timestamp(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + let vec91 = (e).into_boxed_slice(); + let ptr91 = vec91.as_ptr().cast::(); + let len91 = vec91.len(); + ::core::mem::forget(vec91); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len91; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr91.cast_mut(); } - V49::Blob(e) => { - *ptr40.add(8).cast::() = (6i32) as u8; - let vec42 = (e).into_boxed_slice(); - let ptr42 = vec42.as_ptr().cast::(); - let len42 = vec42.len(); - ::core::mem::forget(vec42); - *ptr40 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len42; - *ptr40.add(16).cast::<*mut u8>() = ptr42.cast_mut(); + V112::Int8(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + let vec92 = (e).into_boxed_slice(); + let ptr92 = vec92.as_ptr().cast::(); + let len92 = vec92.len(); + ::core::mem::forget(vec92); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len92; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr92.cast_mut(); } - V49::Int32(e) => { - *ptr40.add(8).cast::() = (7i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i32(e); + V112::Int16(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + let vec93 = (e).into_boxed_slice(); + let ptr93 = vec93.as_ptr().cast::(); + let len93 = vec93.len(); + ::core::mem::forget(vec93); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len93; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr93.cast_mut(); } - V49::Timestamp(e) => { - *ptr40.add(8).cast::() = (8i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i64(e); + V112::Uint8(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + let vec94 = (e).into_boxed_slice(); + let ptr94 = vec94.as_ptr().cast::(); + let len94 = vec94.len(); + ::core::mem::forget(vec94); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len94; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr94.cast_mut(); } - V49::Int8(e) => { - *ptr40.add(8).cast::() = (9i32) as u8; - *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u8; + V112::Uint16(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + let vec95 = (e).into_boxed_slice(); + let ptr95 = vec95.as_ptr().cast::(); + let len95 = vec95.len(); + ::core::mem::forget(vec95); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len95; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr95.cast_mut(); } - V49::Int16(e) => { - *ptr40.add(8).cast::() = (10i32) as u8; - *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u16; + V112::Uint32(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + let vec96 = (e).into_boxed_slice(); + let ptr96 = vec96.as_ptr().cast::(); + let len96 = vec96.len(); + ::core::mem::forget(vec96); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len96; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr96.cast_mut(); } - V49::Uint8(e) => { - *ptr40.add(8).cast::() = (11i32) as u8; - *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u8; + V112::Float32(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + let vec97 = (e).into_boxed_slice(); + let ptr97 = vec97.as_ptr().cast::(); + let len97 = vec97.len(); + ::core::mem::forget(vec97); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len97; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr97.cast_mut(); } - V49::Uint16(e) => { - *ptr40.add(8).cast::() = (12i32) as u8; - *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u16; + V112::Date(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + let vec98 = (e).into_boxed_slice(); + let ptr98 = vec98.as_ptr().cast::(); + let len98 = vec98.len(); + ::core::mem::forget(vec98); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len98; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr98.cast_mut(); } - V49::Uint32(e) => { - *ptr40.add(8).cast::() = (13i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i32(e); + V112::Time(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + let vec99 = (e).into_boxed_slice(); + let ptr99 = vec99.as_ptr().cast::(); + let len99 = vec99.len(); + ::core::mem::forget(vec99); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len99; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr99.cast_mut(); } - V49::Float32(e) => { - *ptr40.add(8).cast::() = (14i32) as u8; - *ptr40.add(16).cast::() = _rt::as_f32(e); + V112::Timestamptz(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + let vec100 = (e).into_boxed_slice(); + let ptr100 = vec100.as_ptr().cast::(); + let len100 = vec100.len(); + ::core::mem::forget(vec100); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len100; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr100.cast_mut(); } - V49::Date(e) => { - *ptr40.add(8).cast::() = (15i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i32(e); - } - V49::Time(e) => { - *ptr40.add(8).cast::() = (16i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i64(e); + V112::Decimal(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + let vec101 = (e).into_boxed_slice(); + let ptr101 = vec101.as_ptr().cast::(); + let len101 = vec101.len(); + ::core::mem::forget(vec101); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len101; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr101.cast_mut(); } - V49::Timestamptz(e) => { - *ptr40.add(8).cast::() = (17i32) as u8; - *ptr40.add(16).cast::() = _rt::as_i64(e); + V112::Interval(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + let vec102 = (e).into_boxed_slice(); + let ptr102 = vec102.as_ptr().cast::(); + let len102 = vec102.len(); + ::core::mem::forget(vec102); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len102; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr102.cast_mut(); } - V49::Decimal(e) => { - *ptr40.add(8).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower43, - upper: upper43, - width: width43, - scale: scale43, - } = e; - *ptr40.add(16).cast::() = _rt::as_i64(lower43); - *ptr40.add(24).cast::() = _rt::as_i64(upper43); - *ptr40.add(32).cast::() = (_rt::as_i32(width43)) as u8; - *ptr40.add(33).cast::() = (_rt::as_i32(scale43)) as u8; + V112::Uuid(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + let vec103 = (e).into_boxed_slice(); + let ptr103 = vec103.as_ptr().cast::(); + let len103 = vec103.len(); + ::core::mem::forget(vec103); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len103; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr103.cast_mut(); } - V49::Interval(e) => { - *ptr40.add(8).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months44, - days: days44, - micros: micros44, - } = e; - *ptr40.add(16).cast::() = _rt::as_i32(months44); - *ptr40.add(20).cast::() = _rt::as_i32(days44); - *ptr40.add(24).cast::() = _rt::as_i64(micros44); + V112::Text(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + let vec105 = e; + let len105 = vec105.len(); + let layout105 = _rt::alloc::Layout::from_size_align_unchecked( + vec105.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result105 = if layout105.size() != 0 { + let ptr = _rt::alloc::alloc(layout105).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout105); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec105.into_iter().enumerate() { + let base = result105 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec104 = (e.into_bytes()).into_boxed_slice(); + let ptr104 = vec104.as_ptr().cast::(); + let len104 = vec104.len(); + ::core::mem::forget(vec104); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len104; + *base.add(0).cast::<*mut u8>() = ptr104.cast_mut(); + } + } + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len105; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result105; } - V49::Uuid(e) => { - *ptr40.add(8).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi45, - lo: lo45, - } = e; - *ptr40.add(16).cast::() = _rt::as_i64(hi45); - *ptr40.add(24).cast::() = _rt::as_i64(lo45); + V112::Blob(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + let vec107 = e; + let len107 = vec107.len(); + let layout107 = _rt::alloc::Layout::from_size_align_unchecked( + vec107.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result107 = if layout107.size() != 0 { + let ptr = _rt::alloc::alloc(layout107).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout107); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec107.into_iter().enumerate() { + let base = result107 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec106 = (e).into_boxed_slice(); + let ptr106 = vec106.as_ptr().cast::(); + let len106 = vec106.len(); + ::core::mem::forget(vec106); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len106; + *base.add(0).cast::<*mut u8>() = ptr106.cast_mut(); + } + } + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len107; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result107; } - V49::Complex(e) => { - *ptr40.add(8).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr46, - json: json46, - } = e; - let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); - let ptr47 = vec47.as_ptr().cast::(); - let len47 = vec47.len(); - ::core::mem::forget(vec47); - *ptr40 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len47; - *ptr40.add(16).cast::<*mut u8>() = ptr47.cast_mut(); - let vec48 = (json46.into_bytes()).into_boxed_slice(); - let ptr48 = vec48.as_ptr().cast::(); - let len48 = vec48.len(); - ::core::mem::forget(vec48); - *ptr40 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len48; - *ptr40 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr48.cast_mut(); + V112::Complex(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec111 = e; + let len111 = vec111.len(); + let layout111 = _rt::alloc::Layout::from_size_align_unchecked( + vec111.len() * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result111 = if layout111.size() != 0 { + let ptr = _rt::alloc::alloc(layout111).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout111); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec111.into_iter().enumerate() { + let base = result111 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + { + let super::super::super::super::duckdb::extension::column_types::Complexvalue { + type_expr: type_expr108, + json: json108, + } = e; + let vec109 = (type_expr108.into_bytes()).into_boxed_slice(); + let ptr109 = vec109.as_ptr().cast::(); + let len109 = vec109.len(); + ::core::mem::forget(vec109); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len109; + *base.add(0).cast::<*mut u8>() = ptr109.cast_mut(); + let vec110 = (json108.into_bytes()).into_boxed_slice(); + let ptr110 = vec110.as_ptr().cast::(); + let len110 = vec110.len(); + ::core::mem::forget(vec110); + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len110; + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr110.cast_mut(); + } + } + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len111; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result111; } } + let vec113 = (validity85).into_boxed_slice(); + let ptr113 = vec113.as_ptr().cast::(); + let len113 = vec113.len(); + ::core::mem::forget(vec113); + *ptr84 + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::() = len113; + *ptr84 + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr113.cast_mut(); + *ptr84 + .add(6 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(rows85); } Err(e) => { - *ptr40.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V55; + *ptr84.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V119; match e { - V55::Invalidargument(e) => { - *ptr40.add(8).cast::() = (0i32) as u8; - let vec50 = (e.into_bytes()).into_boxed_slice(); - let ptr50 = vec50.as_ptr().cast::(); - let len50 = vec50.len(); - ::core::mem::forget(vec50); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len50; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr50.cast_mut(); + V119::Invalidargument(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec114 = (e.into_bytes()).into_boxed_slice(); + let ptr114 = vec114.as_ptr().cast::(); + let len114 = vec114.len(); + ::core::mem::forget(vec114); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len114; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr114.cast_mut(); } - V55::Unsupported(e) => { - *ptr40.add(8).cast::() = (1i32) as u8; - let vec51 = (e.into_bytes()).into_boxed_slice(); - let ptr51 = vec51.as_ptr().cast::(); - let len51 = vec51.len(); - ::core::mem::forget(vec51); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len51; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr51.cast_mut(); + V119::Unsupported(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec115 = (e.into_bytes()).into_boxed_slice(); + let ptr115 = vec115.as_ptr().cast::(); + let len115 = vec115.len(); + ::core::mem::forget(vec115); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len115; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr115.cast_mut(); } - V55::Invalidstate(e) => { - *ptr40.add(8).cast::() = (2i32) as u8; - let vec52 = (e.into_bytes()).into_boxed_slice(); - let ptr52 = vec52.as_ptr().cast::(); - let len52 = vec52.len(); - ::core::mem::forget(vec52); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len52; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr52.cast_mut(); + V119::Invalidstate(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec116 = (e.into_bytes()).into_boxed_slice(); + let ptr116 = vec116.as_ptr().cast::(); + let len116 = vec116.len(); + ::core::mem::forget(vec116); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len116; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr116.cast_mut(); } - V55::Io(e) => { - *ptr40.add(8).cast::() = (3i32) as u8; - let vec53 = (e.into_bytes()).into_boxed_slice(); - let ptr53 = vec53.as_ptr().cast::(); - let len53 = vec53.len(); - ::core::mem::forget(vec53); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len53; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr53.cast_mut(); + V119::Io(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec117 = (e.into_bytes()).into_boxed_slice(); + let ptr117 = vec117.as_ptr().cast::(); + let len117 = vec117.len(); + ::core::mem::forget(vec117); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len117; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr117.cast_mut(); } - V55::Internal(e) => { - *ptr40.add(8).cast::() = (4i32) as u8; - let vec54 = (e.into_bytes()).into_boxed_slice(); - let ptr54 = vec54.as_ptr().cast::(); - let len54 = vec54.len(); - ::core::mem::forget(vec54); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len54; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr54.cast_mut(); + V119::Internal(e) => { + *ptr84 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec118 = (e.into_bytes()).into_boxed_slice(); + let ptr118 = vec118.as_ptr().cast::(); + let len118 = vec118.len(); + ::core::mem::forget(vec118); + *ptr84 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len118; + *ptr84 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr118.cast_mut(); } } } }; - ptr40 + ptr84 } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn __post_return_call_scalar(arg0: *mut u8) { + pub unsafe fn __post_return_call_scalar_batch_col( + arg0: *mut u8, + ) { let l0 = i32::from(*arg0.add(0).cast::()); match l0 { 0 => { - let l1 = i32::from(*arg0.add(8).cast::()); + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); match l1 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l2 = *arg0.add(16).cast::<*mut u8>(); + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); let l3 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l2, l3, 1); + let base4 = l2; + let len4 = l3; + _rt::cabi_dealloc(base4, len4 * 1, 1); } - 6 => { - let l4 = *arg0.add(16).cast::<*mut u8>(); + 1 => { let l5 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - let base6 = l4; - let len6 = l5; - _rt::cabi_dealloc(base6, len6 * 1, 1); + let base7 = l5; + let len7 = l6; + _rt::cabi_dealloc(base7, len7 * 8, 8); } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l7 = *arg0.add(16).cast::<*mut u8>(); + 2 => { let l8 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l7, l8, 1); + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); let l9 = *arg0 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l8; + let len10 = l9; + _rt::cabi_dealloc(base10, len10 * 8, 8); + } + 3 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l10 = *arg0 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l9, l10, 1); + let base13 = l11; + let len13 = l12; + _rt::cabi_dealloc(base13, len13 * 8, 8); + } + 4 => { + let l14 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base16 = l14; + let len16 = l15; + _rt::cabi_dealloc(base16, len16 * 4, 4); + } + 5 => { + let l17 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base19 = l17; + let len19 = l18; + _rt::cabi_dealloc(base19, len19 * 8, 8); + } + 6 => { + let l20 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base22 = l20; + let len22 = l21; + _rt::cabi_dealloc(base22, len22 * 1, 1); + } + 7 => { + let l23 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l24 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base25 = l23; + let len25 = l24; + _rt::cabi_dealloc(base25, len25 * 2, 2); + } + 8 => { + let l26 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base28 = l26; + let len28 = l27; + _rt::cabi_dealloc(base28, len28 * 1, 1); + } + 9 => { + let l29 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l30 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base31 = l29; + let len31 = l30; + _rt::cabi_dealloc(base31, len31 * 2, 2); + } + 10 => { + let l32 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l33 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base34 = l32; + let len34 = l33; + _rt::cabi_dealloc(base34, len34 * 4, 4); + } + 11 => { + let l35 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l36 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base37 = l35; + let len37 = l36; + _rt::cabi_dealloc(base37, len37 * 4, 4); + } + 12 => { + let l38 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base40 = l38; + let len40 = l39; + _rt::cabi_dealloc(base40, len40 * 4, 4); + } + 13 => { + let l41 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l42 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base43 = l41; + let len43 = l42; + _rt::cabi_dealloc(base43, len43 * 8, 8); + } + 14 => { + let l44 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l45 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base46 = l44; + let len46 = l45; + _rt::cabi_dealloc(base46, len46 * 8, 8); + } + 15 => { + let l47 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l48 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base49 = l47; + let len49 = l48; + _rt::cabi_dealloc(base49, len49 * 24, 8); + } + 16 => { + let l50 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l51 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base52 = l50; + let len52 = l51; + _rt::cabi_dealloc(base52, len52 * 16, 8); + } + 17 => { + let l53 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l54 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base55 = l53; + let len55 = l54; + _rt::cabi_dealloc(base55, len55 * 16, 8); + } + 18 => { + let l56 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l57 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base60 = l56; + let len60 = l57; + for i in 0..len60 { + let base = base60 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l58 = *base.add(0).cast::<*mut u8>(); + let l59 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l58, l59, 1); + } + } + _rt::cabi_dealloc( + base60, + len60 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + 19 => { + let l61 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l62 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base66 = l61; + let len66 = l62; + for i in 0..len66 { + let base = base66 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l63 = *base.add(0).cast::<*mut u8>(); + let l64 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base65 = l63; + let len65 = l64; + _rt::cabi_dealloc(base65, len65 * 1, 1); + } + } + _rt::cabi_dealloc( + base66, + len66 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l67 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l68 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base73 = l67; + let len73 = l68; + for i in 0..len73 { + let base = base73 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + { + let l69 = *base.add(0).cast::<*mut u8>(); + let l70 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l69, l70, 1); + let l71 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l72 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l71, l72, 1); + } + } + _rt::cabi_dealloc( + base73, + len73 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); } } + let l74 = *arg0 + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l75 = *arg0 + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base76 = l74; + let len76 = l75; + _rt::cabi_dealloc(base76, len76 * 1, 1); } _ => { - let l11 = i32::from(*arg0.add(8).cast::()); - match l11 { + let l77 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l77 { 0 => { - let l12 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l78 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l13 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l79 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l12, l13, 1); + _rt::cabi_dealloc(l78, l79, 1); } 1 => { - let l14 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l80 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l15 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l81 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l14, l15, 1); + _rt::cabi_dealloc(l80, l81, 1); } 2 => { - let l16 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l82 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l17 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l83 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l16, l17, 1); + _rt::cabi_dealloc(l82, l83, 1); } 3 => { - let l18 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l84 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l19 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l85 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l18, l19, 1); + _rt::cabi_dealloc(l84, l85, 1); } _ => { - let l20 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l86 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l21 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l87 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l20, l21, 1); + _rt::cabi_dealloc(l86, l87, 1); } } } @@ -3951,667 +4912,755 @@ pub mod exports { } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_call_scalar_batch_cabi( + pub unsafe fn _export_call_aggregate_col_cabi( arg0: i32, arg1: *mut u8, arg2: usize, - arg3: i32, - arg4: i64, - arg5: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - let base41 = arg1; - let len41 = arg2; - let mut result41 = _rt::Vec::with_capacity(len41); - for i in 0..len41 { - let base = base41 - .add(i * (2 * ::core::mem::size_of::<*const u8>())); - let e41 = { - let l0 = *base.add(0).cast::<*mut u8>(); - let l1 = *base - .add(::core::mem::size_of::<*const u8>()) - .cast::(); - let base40 = l0; - let len40 = l1; - let mut result40 = _rt::Vec::with_capacity(len40); - for i in 0..len40 { - let base = base40 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - let e40 = { - let l2 = i32::from(*base.add(0).cast::()); - use super::super::super::super::duckdb::extension::types::Duckvalue as V39; - let v39 = match l2 { - 0 => V39::Null, - 1 => { - let e39 = { - let l3 = i32::from(*base.add(8).cast::()); + let base82 = arg1; + let len82 = arg2; + let mut result82 = _rt::Vec::with_capacity(len82); + for i in 0..len82 { + let base = base82 + .add(i * (6 * ::core::mem::size_of::<*const u8>())); + let e82 = { + let l0 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::column_types::Column as V77; + let v77 = match l0 { + 0 => { + let e77 = { + let l1 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l1; + let len4 = l2; + let mut result4 = _rt::Vec::with_capacity(len4); + for i in 0..len4 { + let base = base4.add(i * 1); + let e4 = { + let l3 = i32::from(*base.add(0).cast::()); _rt::bool_lift(l3 as u8) }; - V39::Boolean(e39) - } - 2 => { - let e39 = { - let l4 = *base.add(8).cast::(); - l4 - }; - V39::Int64(e39) - } - 3 => { - let e39 = { - let l5 = *base.add(8).cast::(); - l5 as u64 - }; - V39::Uint64(e39) - } - 4 => { - let e39 = { - let l6 = *base.add(8).cast::(); - l6 - }; - V39::Float64(e39) - } - 5 => { - let e39 = { - let l7 = *base.add(8).cast::<*mut u8>(); - let l8 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len9 = l8; - let bytes9 = _rt::Vec::from_raw_parts( - l7.cast(), - len9, - len9, - ); - _rt::string_lift(bytes9) - }; - V39::Text(e39) - } - 6 => { - let e39 = { - let l10 = *base.add(8).cast::<*mut u8>(); - let l11 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len12 = l11; - _rt::Vec::from_raw_parts(l10.cast(), len12, len12) - }; - V39::Blob(e39) + result4.push(e4); } - 7 => { - let e39 = { - let l13 = *base.add(8).cast::(); - l13 - }; - V39::Int32(e39) - } - 8 => { - let e39 = { - let l14 = *base.add(8).cast::(); - l14 - }; - V39::Timestamp(e39) - } - 9 => { - let e39 = { - let l15 = i32::from(*base.add(8).cast::()); - l15 as i8 - }; - V39::Int8(e39) - } - 10 => { - let e39 = { - let l16 = i32::from(*base.add(8).cast::()); - l16 as i16 - }; - V39::Int16(e39) - } - 11 => { - let e39 = { - let l17 = i32::from(*base.add(8).cast::()); - l17 as u8 - }; - V39::Uint8(e39) - } - 12 => { - let e39 = { - let l18 = i32::from(*base.add(8).cast::()); - l18 as u16 - }; - V39::Uint16(e39) - } - 13 => { - let e39 = { - let l19 = *base.add(8).cast::(); - l19 as u32 - }; - V39::Uint32(e39) - } - 14 => { - let e39 = { - let l20 = *base.add(8).cast::(); - l20 - }; - V39::Float32(e39) - } - 15 => { - let e39 = { - let l21 = *base.add(8).cast::(); - l21 - }; - V39::Date(e39) - } - 16 => { - let e39 = { - let l22 = *base.add(8).cast::(); - l22 - }; - V39::Time(e39) - } - 17 => { - let e39 = { - let l23 = *base.add(8).cast::(); - l23 - }; - V39::Timestamptz(e39) - } - 18 => { - let e39 = { - let l24 = *base.add(8).cast::(); - let l25 = *base.add(16).cast::(); - let l26 = i32::from(*base.add(24).cast::()); - let l27 = i32::from(*base.add(25).cast::()); - super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: l24 as u64, - upper: l25 as u64, - width: l26 as u8, - scale: l27 as u8, - } - }; - V39::Decimal(e39) - } - 19 => { - let e39 = { - let l28 = *base.add(8).cast::(); - let l29 = *base.add(12).cast::(); - let l30 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Intervalvalue { - months: l28, - days: l29, - micros: l30, - } + _rt::cabi_dealloc(base4, len4 * 1, 1); + result4 + }; + V77::Boolean(e77) + } + 1 => { + let e77 = { + let l5 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + _rt::Vec::from_raw_parts(l5.cast(), len7, len7) + }; + V77::Int64(e77) + } + 2 => { + let e77 = { + let l8 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + }; + V77::Uint64(e77) + } + 3 => { + let e77 = { + let l11 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len13 = l12; + _rt::Vec::from_raw_parts(l11.cast(), len13, len13) + }; + V77::Float64(e77) + } + 4 => { + let e77 = { + let l14 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len16 = l15; + _rt::Vec::from_raw_parts(l14.cast(), len16, len16) + }; + V77::Int32(e77) + } + 5 => { + let e77 = { + let l17 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len19 = l18; + _rt::Vec::from_raw_parts(l17.cast(), len19, len19) + }; + V77::Timestamp(e77) + } + 6 => { + let e77 = { + let l20 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len22 = l21; + _rt::Vec::from_raw_parts(l20.cast(), len22, len22) + }; + V77::Int8(e77) + } + 7 => { + let e77 = { + let l23 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l24 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len25 = l24; + _rt::Vec::from_raw_parts(l23.cast(), len25, len25) + }; + V77::Int16(e77) + } + 8 => { + let e77 = { + let l26 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len28 = l27; + _rt::Vec::from_raw_parts(l26.cast(), len28, len28) + }; + V77::Uint8(e77) + } + 9 => { + let e77 = { + let l29 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l30 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len31 = l30; + _rt::Vec::from_raw_parts(l29.cast(), len31, len31) + }; + V77::Uint16(e77) + } + 10 => { + let e77 = { + let l32 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l33 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len34 = l33; + _rt::Vec::from_raw_parts(l32.cast(), len34, len34) + }; + V77::Uint32(e77) + } + 11 => { + let e77 = { + let l35 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l36 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len37 = l36; + _rt::Vec::from_raw_parts(l35.cast(), len37, len37) + }; + V77::Float32(e77) + } + 12 => { + let e77 = { + let l38 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len40 = l39; + _rt::Vec::from_raw_parts(l38.cast(), len40, len40) + }; + V77::Date(e77) + } + 13 => { + let e77 = { + let l41 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l42 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len43 = l42; + _rt::Vec::from_raw_parts(l41.cast(), len43, len43) + }; + V77::Time(e77) + } + 14 => { + let e77 = { + let l44 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l45 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len46 = l45; + _rt::Vec::from_raw_parts(l44.cast(), len46, len46) + }; + V77::Timestamptz(e77) + } + 15 => { + let e77 = { + let l47 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l48 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len49 = l48; + _rt::Vec::from_raw_parts(l47.cast(), len49, len49) + }; + V77::Decimal(e77) + } + 16 => { + let e77 = { + let l50 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l51 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len52 = l51; + _rt::Vec::from_raw_parts(l50.cast(), len52, len52) + }; + V77::Interval(e77) + } + 17 => { + let e77 = { + let l53 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l54 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len55 = l54; + _rt::Vec::from_raw_parts(l53.cast(), len55, len55) + }; + V77::Uuid(e77) + } + 18 => { + let e77 = { + let l56 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l57 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base61 = l56; + let len61 = l57; + let mut result61 = _rt::Vec::with_capacity(len61); + for i in 0..len61 { + let base = base61 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e61 = { + let l58 = *base.add(0).cast::<*mut u8>(); + let l59 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len60 = l59; + let bytes60 = _rt::Vec::from_raw_parts( + l58.cast(), + len60, + len60, + ); + _rt::string_lift(bytes60) }; - V39::Interval(e39) + result61.push(e61); } - 20 => { - let e39 = { - let l31 = *base.add(8).cast::(); - let l32 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: l31 as u64, - lo: l32 as u64, - } + _rt::cabi_dealloc( + base61, + len61 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result61 + }; + V77::Text(e77) + } + 19 => { + let e77 = { + let l62 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l63 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base67 = l62; + let len67 = l63; + let mut result67 = _rt::Vec::with_capacity(len67); + for i in 0..len67 { + let base = base67 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e67 = { + let l64 = *base.add(0).cast::<*mut u8>(); + let l65 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len66 = l65; + _rt::Vec::from_raw_parts(l64.cast(), len66, len66) }; - V39::Uuid(e39) + result67.push(e67); } - n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); - let e39 = { - let l33 = *base.add(8).cast::<*mut u8>(); - let l34 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + _rt::cabi_dealloc( + base67, + len67 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result67 + }; + V77::Blob(e77) + } + n => { + debug_assert_eq!(n, 20, "invalid enum discriminant"); + let e77 = { + let l68 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l69 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base76 = l68; + let len76 = l69; + let mut result76 = _rt::Vec::with_capacity(len76); + for i in 0..len76 { + let base = base76 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + let e76 = { + let l70 = *base.add(0).cast::<*mut u8>(); + let l71 = *base + .add(::core::mem::size_of::<*const u8>()) .cast::(); - let len35 = l34; - let bytes35 = _rt::Vec::from_raw_parts( - l33.cast(), - len35, - len35, + let len72 = l71; + let bytes72 = _rt::Vec::from_raw_parts( + l70.cast(), + len72, + len72, ); - let l36 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l73 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l37 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + let l74 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len38 = l37; - let bytes38 = _rt::Vec::from_raw_parts( - l36.cast(), - len38, - len38, + let len75 = l74; + let bytes75 = _rt::Vec::from_raw_parts( + l73.cast(), + len75, + len75, ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes35), - json: _rt::string_lift(bytes38), + super::super::super::super::duckdb::extension::column_types::Complexvalue { + type_expr: _rt::string_lift(bytes72), + json: _rt::string_lift(bytes75), } }; - V39::Complex(e39) + result76.push(e76); } + _rt::cabi_dealloc( + base76, + len76 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result76 }; - v39 - }; - result40.push(e40); + V77::Complex(e77) + } + }; + let l78 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l79 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len80 = l79; + let l81 = *base + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::(); + super::super::super::super::duckdb::extension::column_types::Colvec { + data: v77, + validity: _rt::Vec::from_raw_parts( + l78.cast(), + len80, + len80, + ), + rows: l81 as u32, } - _rt::cabi_dealloc( - base40, - len40 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, - ); - result40 }; - result41.push(e41); + result82.push(e82); } _rt::cabi_dealloc( - base41, - len41 * (2 * ::core::mem::size_of::<*const u8>()), + base82, + len82 * (6 * ::core::mem::size_of::<*const u8>()), ::core::mem::size_of::<*const u8>(), ); - let result42 = T::call_scalar_batch( - arg0 as u32, - result41, - super::super::super::super::duckdb::extension::types::Invokeinfo { - rowindex: match arg3 { - 0 => None, - 1 => { - let e = arg4 as u64; - Some(e) - } - _ => _rt::invalid_enum_discriminant(), - }, - iswindow: _rt::bool_lift(arg5 as u8), - }, - ); - let ptr43 = (&raw mut _RET_AREA.0).cast::(); - match result42 { + let result83 = T::call_aggregate_col(arg0 as u32, result82); + let ptr84 = (&raw mut _RET_AREA.0).cast::(); + match result83 { Ok(e) => { - *ptr43.add(0).cast::() = (0i32) as u8; - let vec53 = e; - let len53 = vec53.len(); - let layout53 = _rt::alloc::Layout::from_size_align_unchecked( - vec53.len() - * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, - ); - let result53 = if layout53.size() != 0 { - let ptr = _rt::alloc::alloc(layout53).cast::(); - if ptr.is_null() { - _rt::alloc::handle_alloc_error(layout53); + *ptr84.add(0).cast::() = (0i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckvalue as V93; + match e { + V93::Null => { + *ptr84.add(8).cast::() = (0i32) as u8; } - ptr - } else { - ::core::ptr::null_mut() - }; - for (i, e) in vec53.into_iter().enumerate() { - let base = result53 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - { - use super::super::super::super::duckdb::extension::types::Duckvalue as V52; - match e { - V52::Null => { - *base.add(0).cast::() = (0i32) as u8; - } - V52::Boolean(e) => { - *base.add(0).cast::() = (1i32) as u8; - *base.add(8).cast::() = (match e { - true => 1, - false => 0, - }) as u8; - } - V52::Int64(e) => { - *base.add(0).cast::() = (2i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V52::Uint64(e) => { - *base.add(0).cast::() = (3i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V52::Float64(e) => { - *base.add(0).cast::() = (4i32) as u8; - *base.add(8).cast::() = _rt::as_f64(e); - } - V52::Text(e) => { - *base.add(0).cast::() = (5i32) as u8; - let vec44 = (e.into_bytes()).into_boxed_slice(); - let ptr44 = vec44.as_ptr().cast::(); - let len44 = vec44.len(); - ::core::mem::forget(vec44); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len44; - *base.add(8).cast::<*mut u8>() = ptr44.cast_mut(); - } - V52::Blob(e) => { - *base.add(0).cast::() = (6i32) as u8; - let vec45 = (e).into_boxed_slice(); - let ptr45 = vec45.as_ptr().cast::(); - let len45 = vec45.len(); - ::core::mem::forget(vec45); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len45; - *base.add(8).cast::<*mut u8>() = ptr45.cast_mut(); - } - V52::Int32(e) => { - *base.add(0).cast::() = (7i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V52::Timestamp(e) => { - *base.add(0).cast::() = (8i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V52::Int8(e) => { - *base.add(0).cast::() = (9i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u8; - } - V52::Int16(e) => { - *base.add(0).cast::() = (10i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u16; - } - V52::Uint8(e) => { - *base.add(0).cast::() = (11i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u8; - } - V52::Uint16(e) => { - *base.add(0).cast::() = (12i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u16; - } - V52::Uint32(e) => { - *base.add(0).cast::() = (13i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V52::Float32(e) => { - *base.add(0).cast::() = (14i32) as u8; - *base.add(8).cast::() = _rt::as_f32(e); - } - V52::Date(e) => { - *base.add(0).cast::() = (15i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V52::Time(e) => { - *base.add(0).cast::() = (16i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V52::Timestamptz(e) => { - *base.add(0).cast::() = (17i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V52::Decimal(e) => { - *base.add(0).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower46, - upper: upper46, - width: width46, - scale: scale46, - } = e; - *base.add(8).cast::() = _rt::as_i64(lower46); - *base.add(16).cast::() = _rt::as_i64(upper46); - *base.add(24).cast::() = (_rt::as_i32(width46)) as u8; - *base.add(25).cast::() = (_rt::as_i32(scale46)) as u8; - } - V52::Interval(e) => { - *base.add(0).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months47, - days: days47, - micros: micros47, - } = e; - *base.add(8).cast::() = _rt::as_i32(months47); - *base.add(12).cast::() = _rt::as_i32(days47); - *base.add(16).cast::() = _rt::as_i64(micros47); - } - V52::Uuid(e) => { - *base.add(0).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi48, - lo: lo48, - } = e; - *base.add(8).cast::() = _rt::as_i64(hi48); - *base.add(16).cast::() = _rt::as_i64(lo48); - } - V52::Complex(e) => { - *base.add(0).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr49, - json: json49, - } = e; - let vec50 = (type_expr49.into_bytes()).into_boxed_slice(); - let ptr50 = vec50.as_ptr().cast::(); - let len50 = vec50.len(); - ::core::mem::forget(vec50); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len50; - *base.add(8).cast::<*mut u8>() = ptr50.cast_mut(); - let vec51 = (json49.into_bytes()).into_boxed_slice(); - let ptr51 = vec51.as_ptr().cast::(); - let len51 = vec51.len(); - ::core::mem::forget(vec51); - *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len51; - *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr51.cast_mut(); - } - } + V93::Boolean(e) => { + *ptr84.add(8).cast::() = (1i32) as u8; + *ptr84.add(16).cast::() = (match e { + true => 1, + false => 0, + }) as u8; } - } - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len53; - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = result53; - } - Err(e) => { - *ptr43.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V59; - match e { - V59::Invalidargument(e) => { - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::() = (0i32) as u8; - let vec54 = (e.into_bytes()).into_boxed_slice(); - let ptr54 = vec54.as_ptr().cast::(); - let len54 = vec54.len(); - ::core::mem::forget(vec54); - *ptr43 - .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len54; - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr54.cast_mut(); + V93::Int64(e) => { + *ptr84.add(8).cast::() = (2i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i64(e); + } + V93::Uint64(e) => { + *ptr84.add(8).cast::() = (3i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i64(e); + } + V93::Float64(e) => { + *ptr84.add(8).cast::() = (4i32) as u8; + *ptr84.add(16).cast::() = _rt::as_f64(e); + } + V93::Text(e) => { + *ptr84.add(8).cast::() = (5i32) as u8; + let vec85 = (e.into_bytes()).into_boxed_slice(); + let ptr85 = vec85.as_ptr().cast::(); + let len85 = vec85.len(); + ::core::mem::forget(vec85); + *ptr84 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len85; + *ptr84.add(16).cast::<*mut u8>() = ptr85.cast_mut(); + } + V93::Blob(e) => { + *ptr84.add(8).cast::() = (6i32) as u8; + let vec86 = (e).into_boxed_slice(); + let ptr86 = vec86.as_ptr().cast::(); + let len86 = vec86.len(); + ::core::mem::forget(vec86); + *ptr84 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len86; + *ptr84.add(16).cast::<*mut u8>() = ptr86.cast_mut(); } - V59::Unsupported(e) => { - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::() = (1i32) as u8; - let vec55 = (e.into_bytes()).into_boxed_slice(); - let ptr55 = vec55.as_ptr().cast::(); - let len55 = vec55.len(); - ::core::mem::forget(vec55); - *ptr43 - .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len55; - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr55.cast_mut(); + V93::Int32(e) => { + *ptr84.add(8).cast::() = (7i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i32(e); } - V59::Invalidstate(e) => { - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::() = (2i32) as u8; - let vec56 = (e.into_bytes()).into_boxed_slice(); - let ptr56 = vec56.as_ptr().cast::(); - let len56 = vec56.len(); - ::core::mem::forget(vec56); - *ptr43 - .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len56; - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr56.cast_mut(); + V93::Timestamp(e) => { + *ptr84.add(8).cast::() = (8i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i64(e); } - V59::Io(e) => { - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::() = (3i32) as u8; - let vec57 = (e.into_bytes()).into_boxed_slice(); - let ptr57 = vec57.as_ptr().cast::(); - let len57 = vec57.len(); - ::core::mem::forget(vec57); - *ptr43 - .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len57; - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr57.cast_mut(); + V93::Int8(e) => { + *ptr84.add(8).cast::() = (9i32) as u8; + *ptr84.add(16).cast::() = (_rt::as_i32(e)) as u8; } - V59::Internal(e) => { - *ptr43 - .add(::core::mem::size_of::<*const u8>()) - .cast::() = (4i32) as u8; - let vec58 = (e.into_bytes()).into_boxed_slice(); - let ptr58 = vec58.as_ptr().cast::(); - let len58 = vec58.len(); - ::core::mem::forget(vec58); - *ptr43 - .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len58; - *ptr43 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr58.cast_mut(); + V93::Int16(e) => { + *ptr84.add(8).cast::() = (10i32) as u8; + *ptr84.add(16).cast::() = (_rt::as_i32(e)) as u16; + } + V93::Uint8(e) => { + *ptr84.add(8).cast::() = (11i32) as u8; + *ptr84.add(16).cast::() = (_rt::as_i32(e)) as u8; + } + V93::Uint16(e) => { + *ptr84.add(8).cast::() = (12i32) as u8; + *ptr84.add(16).cast::() = (_rt::as_i32(e)) as u16; + } + V93::Uint32(e) => { + *ptr84.add(8).cast::() = (13i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i32(e); + } + V93::Float32(e) => { + *ptr84.add(8).cast::() = (14i32) as u8; + *ptr84.add(16).cast::() = _rt::as_f32(e); + } + V93::Date(e) => { + *ptr84.add(8).cast::() = (15i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i32(e); + } + V93::Time(e) => { + *ptr84.add(8).cast::() = (16i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i64(e); + } + V93::Timestamptz(e) => { + *ptr84.add(8).cast::() = (17i32) as u8; + *ptr84.add(16).cast::() = _rt::as_i64(e); + } + V93::Decimal(e) => { + *ptr84.add(8).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower87, + upper: upper87, + width: width87, + scale: scale87, + } = e; + *ptr84.add(16).cast::() = _rt::as_i64(lower87); + *ptr84.add(24).cast::() = _rt::as_i64(upper87); + *ptr84.add(32).cast::() = (_rt::as_i32(width87)) as u8; + *ptr84.add(33).cast::() = (_rt::as_i32(scale87)) as u8; + } + V93::Interval(e) => { + *ptr84.add(8).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months88, + days: days88, + micros: micros88, + } = e; + *ptr84.add(16).cast::() = _rt::as_i32(months88); + *ptr84.add(20).cast::() = _rt::as_i32(days88); + *ptr84.add(24).cast::() = _rt::as_i64(micros88); + } + V93::Uuid(e) => { + *ptr84.add(8).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi89, + lo: lo89, + } = e; + *ptr84.add(16).cast::() = _rt::as_i64(hi89); + *ptr84.add(24).cast::() = _rt::as_i64(lo89); + } + V93::Complex(e) => { + *ptr84.add(8).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr90, + json: json90, + } = e; + let vec91 = (type_expr90.into_bytes()).into_boxed_slice(); + let ptr91 = vec91.as_ptr().cast::(); + let len91 = vec91.len(); + ::core::mem::forget(vec91); + *ptr84 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len91; + *ptr84.add(16).cast::<*mut u8>() = ptr91.cast_mut(); + let vec92 = (json90.into_bytes()).into_boxed_slice(); + let ptr92 = vec92.as_ptr().cast::(); + let len92 = vec92.len(); + ::core::mem::forget(vec92); + *ptr84 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len92; + *ptr84 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr92.cast_mut(); + } + } + } + Err(e) => { + *ptr84.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V99; + match e { + V99::Invalidargument(e) => { + *ptr84.add(8).cast::() = (0i32) as u8; + let vec94 = (e.into_bytes()).into_boxed_slice(); + let ptr94 = vec94.as_ptr().cast::(); + let len94 = vec94.len(); + ::core::mem::forget(vec94); + *ptr84 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len94; + *ptr84 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr94.cast_mut(); + } + V99::Unsupported(e) => { + *ptr84.add(8).cast::() = (1i32) as u8; + let vec95 = (e.into_bytes()).into_boxed_slice(); + let ptr95 = vec95.as_ptr().cast::(); + let len95 = vec95.len(); + ::core::mem::forget(vec95); + *ptr84 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len95; + *ptr84 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr95.cast_mut(); + } + V99::Invalidstate(e) => { + *ptr84.add(8).cast::() = (2i32) as u8; + let vec96 = (e.into_bytes()).into_boxed_slice(); + let ptr96 = vec96.as_ptr().cast::(); + let len96 = vec96.len(); + ::core::mem::forget(vec96); + *ptr84 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len96; + *ptr84 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr96.cast_mut(); + } + V99::Io(e) => { + *ptr84.add(8).cast::() = (3i32) as u8; + let vec97 = (e.into_bytes()).into_boxed_slice(); + let ptr97 = vec97.as_ptr().cast::(); + let len97 = vec97.len(); + ::core::mem::forget(vec97); + *ptr84 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len97; + *ptr84 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr97.cast_mut(); + } + V99::Internal(e) => { + *ptr84.add(8).cast::() = (4i32) as u8; + let vec98 = (e.into_bytes()).into_boxed_slice(); + let ptr98 = vec98.as_ptr().cast::(); + let len98 = vec98.len(); + ::core::mem::forget(vec98); + *ptr84 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len98; + *ptr84 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr98.cast_mut(); } } } }; - ptr43 + ptr84 } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn __post_return_call_scalar_batch(arg0: *mut u8) { + pub unsafe fn __post_return_call_aggregate_col(arg0: *mut u8) { let l0 = i32::from(*arg0.add(0).cast::()); match l0 { 0 => { - let l1 = *arg0 - .add(::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l2 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base13 = l1; - let len13 = l2; - for i in 0..len13 { - let base = base13 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - { - let l3 = i32::from(*base.add(0).cast::()); - match l3 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l4 = *base.add(8).cast::<*mut u8>(); - let l5 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l4, l5, 1); - } - 6 => { - let l6 = *base.add(8).cast::<*mut u8>(); - let l7 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base8 = l6; - let len8 = l7; - _rt::cabi_dealloc(base8, len8 * 1, 1); - } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l9 = *base.add(8).cast::<*mut u8>(); - let l10 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l9, l10, 1); - let l11 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l12 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l11, l12, 1); - } - } + let l1 = i32::from(*arg0.add(8).cast::()); + match l1 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l2 = *arg0.add(16).cast::<*mut u8>(); + let l3 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 6 => { + let l4 = *arg0.add(16).cast::<*mut u8>(); + let l5 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base6 = l4; + let len6 = l5; + _rt::cabi_dealloc(base6, len6 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l7 = *arg0.add(16).cast::<*mut u8>(); + let l8 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + let l9 = *arg0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); } } - _rt::cabi_dealloc( - base13, - len13 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, - ); } _ => { - let l14 = i32::from( - *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), - ); - match l14 { + let l11 = i32::from(*arg0.add(8).cast::()); + match l11 { 0 => { - let l15 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) + let l12 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l16 = *arg0 - .add(3 * ::core::mem::size_of::<*const u8>()) + let l13 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l15, l16, 1); + _rt::cabi_dealloc(l12, l13, 1); } 1 => { - let l17 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) + let l14 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l18 = *arg0 - .add(3 * ::core::mem::size_of::<*const u8>()) + let l15 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l17, l18, 1); + _rt::cabi_dealloc(l14, l15, 1); } 2 => { - let l19 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) + let l16 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l20 = *arg0 - .add(3 * ::core::mem::size_of::<*const u8>()) + let l17 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l19, l20, 1); + _rt::cabi_dealloc(l16, l17, 1); } 3 => { - let l21 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) + let l18 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l22 = *arg0 - .add(3 * ::core::mem::size_of::<*const u8>()) + let l19 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l21, l22, 1); + _rt::cabi_dealloc(l18, l19, 1); } _ => { - let l23 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) + let l20 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l24 = *arg0 - .add(3 * ::core::mem::size_of::<*const u8>()) + let l21 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l23, l24, 1); + _rt::cabi_dealloc(l20, l21, 1); } } } @@ -4619,672 +5668,1165 @@ pub mod exports { } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_call_table_cabi( + pub unsafe fn _export_call_cast_col_cabi( arg0: i32, - arg1: *mut u8, - arg2: usize, + arg1: i32, + arg2: *mut u8, + arg3: usize, + arg4: *mut u8, + arg5: usize, + arg6: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - let base38 = arg1; - let len38 = arg2; - let mut result38 = _rt::Vec::with_capacity(len38); - for i in 0..len38 { - let base = base38 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - let e38 = { - let l0 = i32::from(*base.add(0).cast::()); - use super::super::super::super::duckdb::extension::types::Duckvalue as V37; - let v37 = match l0 { - 0 => V37::Null, - 1 => { - let e37 = { - let l1 = i32::from(*base.add(8).cast::()); - _rt::bool_lift(l1 as u8) - }; - V37::Boolean(e37) - } - 2 => { - let e37 = { - let l2 = *base.add(8).cast::(); - l2 - }; - V37::Int64(e37) - } - 3 => { - let e37 = { - let l3 = *base.add(8).cast::(); - l3 as u64 - }; - V37::Uint64(e37) - } - 4 => { - let e37 = { - let l4 = *base.add(8).cast::(); - l4 + use super::super::super::super::duckdb::extension::column_types::Column as V34; + let v34 = match arg1 { + 0 => { + let e34 = { + let base1 = arg2; + let len1 = arg3; + let mut result1 = _rt::Vec::with_capacity(len1); + for i in 0..len1 { + let base = base1.add(i * 1); + let e1 = { + let l0 = i32::from(*base.add(0).cast::()); + _rt::bool_lift(l0 as u8) }; - V37::Float64(e37) + result1.push(e1); } - 5 => { - let e37 = { - let l5 = *base.add(8).cast::<*mut u8>(); - let l6 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + _rt::cabi_dealloc(base1, len1 * 1, 1); + result1 + }; + V34::Boolean(e34) + } + 1 => { + let e34 = { + let len2 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len2, len2) + }; + V34::Int64(e34) + } + 2 => { + let e34 = { + let len3 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len3, len3) + }; + V34::Uint64(e34) + } + 3 => { + let e34 = { + let len4 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len4, len4) + }; + V34::Float64(e34) + } + 4 => { + let e34 = { + let len5 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len5, len5) + }; + V34::Int32(e34) + } + 5 => { + let e34 = { + let len6 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len6, len6) + }; + V34::Timestamp(e34) + } + 6 => { + let e34 = { + let len7 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len7, len7) + }; + V34::Int8(e34) + } + 7 => { + let e34 = { + let len8 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len8, len8) + }; + V34::Int16(e34) + } + 8 => { + let e34 = { + let len9 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len9, len9) + }; + V34::Uint8(e34) + } + 9 => { + let e34 = { + let len10 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len10, len10) + }; + V34::Uint16(e34) + } + 10 => { + let e34 = { + let len11 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len11, len11) + }; + V34::Uint32(e34) + } + 11 => { + let e34 = { + let len12 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len12, len12) + }; + V34::Float32(e34) + } + 12 => { + let e34 = { + let len13 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len13, len13) + }; + V34::Date(e34) + } + 13 => { + let e34 = { + let len14 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len14, len14) + }; + V34::Time(e34) + } + 14 => { + let e34 = { + let len15 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len15, len15) + }; + V34::Timestamptz(e34) + } + 15 => { + let e34 = { + let len16 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len16, len16) + }; + V34::Decimal(e34) + } + 16 => { + let e34 = { + let len17 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len17, len17) + }; + V34::Interval(e34) + } + 17 => { + let e34 = { + let len18 = arg3; + _rt::Vec::from_raw_parts(arg2.cast(), len18, len18) + }; + V34::Uuid(e34) + } + 18 => { + let e34 = { + let base22 = arg2; + let len22 = arg3; + let mut result22 = _rt::Vec::with_capacity(len22); + for i in 0..len22 { + let base = base22 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e22 = { + let l19 = *base.add(0).cast::<*mut u8>(); + let l20 = *base + .add(::core::mem::size_of::<*const u8>()) .cast::(); - let len7 = l6; - let bytes7 = _rt::Vec::from_raw_parts( - l5.cast(), - len7, - len7, + let len21 = l20; + let bytes21 = _rt::Vec::from_raw_parts( + l19.cast(), + len21, + len21, ); - _rt::string_lift(bytes7) + _rt::string_lift(bytes21) }; - V37::Text(e37) + result22.push(e22); } - 6 => { - let e37 = { - let l8 = *base.add(8).cast::<*mut u8>(); - let l9 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + _rt::cabi_dealloc( + base22, + len22 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result22 + }; + V34::Text(e34) + } + 19 => { + let e34 = { + let base26 = arg2; + let len26 = arg3; + let mut result26 = _rt::Vec::with_capacity(len26); + for i in 0..len26 { + let base = base26 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e26 = { + let l23 = *base.add(0).cast::<*mut u8>(); + let l24 = *base + .add(::core::mem::size_of::<*const u8>()) .cast::(); - let len10 = l9; - _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + let len25 = l24; + _rt::Vec::from_raw_parts(l23.cast(), len25, len25) }; - V37::Blob(e37) + result26.push(e26); } - 7 => { - let e37 = { - let l11 = *base.add(8).cast::(); - l11 + _rt::cabi_dealloc( + base26, + len26 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result26 + }; + V34::Blob(e34) + } + n => { + debug_assert_eq!(n, 20, "invalid enum discriminant"); + let e34 = { + let base33 = arg2; + let len33 = arg3; + let mut result33 = _rt::Vec::with_capacity(len33); + for i in 0..len33 { + let base = base33 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + let e33 = { + let l27 = *base.add(0).cast::<*mut u8>(); + let l28 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len29 = l28; + let bytes29 = _rt::Vec::from_raw_parts( + l27.cast(), + len29, + len29, + ); + let l30 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l31 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len32 = l31; + let bytes32 = _rt::Vec::from_raw_parts( + l30.cast(), + len32, + len32, + ); + super::super::super::super::duckdb::extension::column_types::Complexvalue { + type_expr: _rt::string_lift(bytes29), + json: _rt::string_lift(bytes32), + } }; - V37::Int32(e37) + result33.push(e33); } - 8 => { - let e37 = { - let l12 = *base.add(8).cast::(); - l12 + _rt::cabi_dealloc( + base33, + len33 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + result33 + }; + V34::Complex(e34) + } + }; + let len35 = arg5; + let result36 = T::call_cast_col( + arg0 as u32, + super::super::super::super::duckdb::extension::column_types::Colvec { + data: v34, + validity: _rt::Vec::from_raw_parts( + arg4.cast(), + len35, + len35, + ), + rows: arg6 as u32, + }, + ); + let ptr37 = (&raw mut _RET_AREA.0).cast::(); + match result36 { + Ok(e) => { + *ptr37.add(0).cast::() = (0i32) as u8; + let super::super::super::super::duckdb::extension::column_types::Colvec { + data: data38, + validity: validity38, + rows: rows38, + } = e; + use super::super::super::super::duckdb::extension::column_types::Column as V65; + match data38 { + V65::Boolean(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec39 = e; + let len39 = vec39.len(); + let layout39 = _rt::alloc::Layout::from_size_align_unchecked( + vec39.len() * 1, + 1, + ); + let result39 = if layout39.size() != 0 { + let ptr = _rt::alloc::alloc(layout39).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout39); + } + ptr + } else { + ::core::ptr::null_mut() }; - V37::Timestamp(e37) + for (i, e) in vec39.into_iter().enumerate() { + let base = result39.add(i * 1); + { + *base.add(0).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + } + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len39; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result39; } - 9 => { - let e37 = { - let l13 = i32::from(*base.add(8).cast::()); - l13 as i8 - }; - V37::Int8(e37) + V65::Int64(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec40 = (e).into_boxed_slice(); + let ptr40 = vec40.as_ptr().cast::(); + let len40 = vec40.len(); + ::core::mem::forget(vec40); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len40; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr40.cast_mut(); } - 10 => { - let e37 = { - let l14 = i32::from(*base.add(8).cast::()); - l14 as i16 - }; - V37::Int16(e37) + V65::Uint64(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec41 = (e).into_boxed_slice(); + let ptr41 = vec41.as_ptr().cast::(); + let len41 = vec41.len(); + ::core::mem::forget(vec41); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len41; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr41.cast_mut(); } - 11 => { - let e37 = { - let l15 = i32::from(*base.add(8).cast::()); - l15 as u8 - }; - V37::Uint8(e37) + V65::Float64(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec42 = (e).into_boxed_slice(); + let ptr42 = vec42.as_ptr().cast::(); + let len42 = vec42.len(); + ::core::mem::forget(vec42); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len42; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr42.cast_mut(); } - 12 => { - let e37 = { - let l16 = i32::from(*base.add(8).cast::()); - l16 as u16 - }; - V37::Uint16(e37) + V65::Int32(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec43 = (e).into_boxed_slice(); + let ptr43 = vec43.as_ptr().cast::(); + let len43 = vec43.len(); + ::core::mem::forget(vec43); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len43; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr43.cast_mut(); } - 13 => { - let e37 = { - let l17 = *base.add(8).cast::(); - l17 as u32 - }; - V37::Uint32(e37) + V65::Timestamp(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + let vec44 = (e).into_boxed_slice(); + let ptr44 = vec44.as_ptr().cast::(); + let len44 = vec44.len(); + ::core::mem::forget(vec44); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len44; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr44.cast_mut(); } - 14 => { - let e37 = { - let l18 = *base.add(8).cast::(); - l18 - }; - V37::Float32(e37) + V65::Int8(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + let vec45 = (e).into_boxed_slice(); + let ptr45 = vec45.as_ptr().cast::(); + let len45 = vec45.len(); + ::core::mem::forget(vec45); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len45; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr45.cast_mut(); } - 15 => { - let e37 = { - let l19 = *base.add(8).cast::(); - l19 - }; - V37::Date(e37) + V65::Int16(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + let vec46 = (e).into_boxed_slice(); + let ptr46 = vec46.as_ptr().cast::(); + let len46 = vec46.len(); + ::core::mem::forget(vec46); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len46; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr46.cast_mut(); } - 16 => { - let e37 = { - let l20 = *base.add(8).cast::(); - l20 - }; - V37::Time(e37) + V65::Uint8(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + let vec47 = (e).into_boxed_slice(); + let ptr47 = vec47.as_ptr().cast::(); + let len47 = vec47.len(); + ::core::mem::forget(vec47); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len47; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr47.cast_mut(); } - 17 => { - let e37 = { - let l21 = *base.add(8).cast::(); - l21 - }; - V37::Timestamptz(e37) + V65::Uint16(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + let vec48 = (e).into_boxed_slice(); + let ptr48 = vec48.as_ptr().cast::(); + let len48 = vec48.len(); + ::core::mem::forget(vec48); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len48; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr48.cast_mut(); } - 18 => { - let e37 = { - let l22 = *base.add(8).cast::(); - let l23 = *base.add(16).cast::(); - let l24 = i32::from(*base.add(24).cast::()); - let l25 = i32::from(*base.add(25).cast::()); - super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: l22 as u64, - upper: l23 as u64, - width: l24 as u8, - scale: l25 as u8, - } - }; - V37::Decimal(e37) + V65::Uint32(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + let vec49 = (e).into_boxed_slice(); + let ptr49 = vec49.as_ptr().cast::(); + let len49 = vec49.len(); + ::core::mem::forget(vec49); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len49; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr49.cast_mut(); } - 19 => { - let e37 = { - let l26 = *base.add(8).cast::(); - let l27 = *base.add(12).cast::(); - let l28 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Intervalvalue { - months: l26, - days: l27, - micros: l28, - } - }; - V37::Interval(e37) + V65::Float32(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + let vec50 = (e).into_boxed_slice(); + let ptr50 = vec50.as_ptr().cast::(); + let len50 = vec50.len(); + ::core::mem::forget(vec50); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len50; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr50.cast_mut(); } - 20 => { - let e37 = { - let l29 = *base.add(8).cast::(); - let l30 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: l29 as u64, - lo: l30 as u64, + V65::Date(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + let vec51 = (e).into_boxed_slice(); + let ptr51 = vec51.as_ptr().cast::(); + let len51 = vec51.len(); + ::core::mem::forget(vec51); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len51; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr51.cast_mut(); + } + V65::Time(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + let vec52 = (e).into_boxed_slice(); + let ptr52 = vec52.as_ptr().cast::(); + let len52 = vec52.len(); + ::core::mem::forget(vec52); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len52; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr52.cast_mut(); + } + V65::Timestamptz(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + let vec53 = (e).into_boxed_slice(); + let ptr53 = vec53.as_ptr().cast::(); + let len53 = vec53.len(); + ::core::mem::forget(vec53); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len53; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr53.cast_mut(); + } + V65::Decimal(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + let vec54 = (e).into_boxed_slice(); + let ptr54 = vec54.as_ptr().cast::(); + let len54 = vec54.len(); + ::core::mem::forget(vec54); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len54; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr54.cast_mut(); + } + V65::Interval(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + let vec55 = (e).into_boxed_slice(); + let ptr55 = vec55.as_ptr().cast::(); + let len55 = vec55.len(); + ::core::mem::forget(vec55); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len55; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr55.cast_mut(); + } + V65::Uuid(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + let vec56 = (e).into_boxed_slice(); + let ptr56 = vec56.as_ptr().cast::(); + let len56 = vec56.len(); + ::core::mem::forget(vec56); + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len56; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr56.cast_mut(); + } + V65::Text(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + let vec58 = e; + let len58 = vec58.len(); + let layout58 = _rt::alloc::Layout::from_size_align_unchecked( + vec58.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result58 = if layout58.size() != 0 { + let ptr = _rt::alloc::alloc(layout58).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout58); } + ptr + } else { + ::core::ptr::null_mut() }; - V37::Uuid(e37) + for (i, e) in vec58.into_iter().enumerate() { + let base = result58 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec57 = (e.into_bytes()).into_boxed_slice(); + let ptr57 = vec57.as_ptr().cast::(); + let len57 = vec57.len(); + ::core::mem::forget(vec57); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len57; + *base.add(0).cast::<*mut u8>() = ptr57.cast_mut(); + } + } + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len58; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result58; } - n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); - let e37 = { - let l31 = *base.add(8).cast::<*mut u8>(); - let l32 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len33 = l32; - let bytes33 = _rt::Vec::from_raw_parts( - l31.cast(), - len33, - len33, - ); - let l34 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l35 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len36 = l35; - let bytes36 = _rt::Vec::from_raw_parts( - l34.cast(), - len36, - len36, - ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes33), - json: _rt::string_lift(bytes36), + V65::Blob(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + let vec60 = e; + let len60 = vec60.len(); + let layout60 = _rt::alloc::Layout::from_size_align_unchecked( + vec60.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result60 = if layout60.size() != 0 { + let ptr = _rt::alloc::alloc(layout60).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout60); } + ptr + } else { + ::core::ptr::null_mut() }; - V37::Complex(e37) - } - }; - v37 - }; - result38.push(e38); - } - _rt::cabi_dealloc( - base38, - len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, - ); - let result39 = T::call_table(arg0 as u32, result38); - let ptr40 = (&raw mut _RET_AREA.0).cast::(); - match result39 { - Ok(e) => { - *ptr40.add(0).cast::() = (0i32) as u8; - let vec51 = e; - let len51 = vec51.len(); - let layout51 = _rt::alloc::Layout::from_size_align_unchecked( - vec51.len() * (2 * ::core::mem::size_of::<*const u8>()), - ::core::mem::size_of::<*const u8>(), - ); - let result51 = if layout51.size() != 0 { - let ptr = _rt::alloc::alloc(layout51).cast::(); - if ptr.is_null() { - _rt::alloc::handle_alloc_error(layout51); + for (i, e) in vec60.into_iter().enumerate() { + let base = result60 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec59 = (e).into_boxed_slice(); + let ptr59 = vec59.as_ptr().cast::(); + let len59 = vec59.len(); + ::core::mem::forget(vec59); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len59; + *base.add(0).cast::<*mut u8>() = ptr59.cast_mut(); + } + } + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len60; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result60; } - ptr - } else { - ::core::ptr::null_mut() - }; - for (i, e) in vec51.into_iter().enumerate() { - let base = result51 - .add(i * (2 * ::core::mem::size_of::<*const u8>())); - { - let vec50 = e; - let len50 = vec50.len(); - let layout50 = _rt::alloc::Layout::from_size_align_unchecked( - vec50.len() - * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, + V65::Complex(e) => { + *ptr37 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec64 = e; + let len64 = vec64.len(); + let layout64 = _rt::alloc::Layout::from_size_align_unchecked( + vec64.len() * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), ); - let result50 = if layout50.size() != 0 { - let ptr = _rt::alloc::alloc(layout50).cast::(); + let result64 = if layout64.size() != 0 { + let ptr = _rt::alloc::alloc(layout64).cast::(); if ptr.is_null() { - _rt::alloc::handle_alloc_error(layout50); + _rt::alloc::handle_alloc_error(layout64); } ptr } else { ::core::ptr::null_mut() }; - for (i, e) in vec50.into_iter().enumerate() { - let base = result50 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + for (i, e) in vec64.into_iter().enumerate() { + let base = result64 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); { - use super::super::super::super::duckdb::extension::types::Duckvalue as V49; - match e { - V49::Null => { - *base.add(0).cast::() = (0i32) as u8; - } - V49::Boolean(e) => { - *base.add(0).cast::() = (1i32) as u8; - *base.add(8).cast::() = (match e { - true => 1, - false => 0, - }) as u8; - } - V49::Int64(e) => { - *base.add(0).cast::() = (2i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V49::Uint64(e) => { - *base.add(0).cast::() = (3i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V49::Float64(e) => { - *base.add(0).cast::() = (4i32) as u8; - *base.add(8).cast::() = _rt::as_f64(e); - } - V49::Text(e) => { - *base.add(0).cast::() = (5i32) as u8; - let vec41 = (e.into_bytes()).into_boxed_slice(); - let ptr41 = vec41.as_ptr().cast::(); - let len41 = vec41.len(); - ::core::mem::forget(vec41); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len41; - *base.add(8).cast::<*mut u8>() = ptr41.cast_mut(); - } - V49::Blob(e) => { - *base.add(0).cast::() = (6i32) as u8; - let vec42 = (e).into_boxed_slice(); - let ptr42 = vec42.as_ptr().cast::(); - let len42 = vec42.len(); - ::core::mem::forget(vec42); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len42; - *base.add(8).cast::<*mut u8>() = ptr42.cast_mut(); - } - V49::Int32(e) => { - *base.add(0).cast::() = (7i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V49::Timestamp(e) => { - *base.add(0).cast::() = (8i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V49::Int8(e) => { - *base.add(0).cast::() = (9i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u8; - } - V49::Int16(e) => { - *base.add(0).cast::() = (10i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u16; - } - V49::Uint8(e) => { - *base.add(0).cast::() = (11i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u8; - } - V49::Uint16(e) => { - *base.add(0).cast::() = (12i32) as u8; - *base.add(8).cast::() = (_rt::as_i32(e)) as u16; - } - V49::Uint32(e) => { - *base.add(0).cast::() = (13i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V49::Float32(e) => { - *base.add(0).cast::() = (14i32) as u8; - *base.add(8).cast::() = _rt::as_f32(e); - } - V49::Date(e) => { - *base.add(0).cast::() = (15i32) as u8; - *base.add(8).cast::() = _rt::as_i32(e); - } - V49::Time(e) => { - *base.add(0).cast::() = (16i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V49::Timestamptz(e) => { - *base.add(0).cast::() = (17i32) as u8; - *base.add(8).cast::() = _rt::as_i64(e); - } - V49::Decimal(e) => { - *base.add(0).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower43, - upper: upper43, - width: width43, - scale: scale43, - } = e; - *base.add(8).cast::() = _rt::as_i64(lower43); - *base.add(16).cast::() = _rt::as_i64(upper43); - *base.add(24).cast::() = (_rt::as_i32(width43)) as u8; - *base.add(25).cast::() = (_rt::as_i32(scale43)) as u8; - } - V49::Interval(e) => { - *base.add(0).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months44, - days: days44, - micros: micros44, - } = e; - *base.add(8).cast::() = _rt::as_i32(months44); - *base.add(12).cast::() = _rt::as_i32(days44); - *base.add(16).cast::() = _rt::as_i64(micros44); - } - V49::Uuid(e) => { - *base.add(0).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi45, - lo: lo45, - } = e; - *base.add(8).cast::() = _rt::as_i64(hi45); - *base.add(16).cast::() = _rt::as_i64(lo45); - } - V49::Complex(e) => { - *base.add(0).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr46, - json: json46, - } = e; - let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); - let ptr47 = vec47.as_ptr().cast::(); - let len47 = vec47.len(); - ::core::mem::forget(vec47); - *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len47; - *base.add(8).cast::<*mut u8>() = ptr47.cast_mut(); - let vec48 = (json46.into_bytes()).into_boxed_slice(); - let ptr48 = vec48.as_ptr().cast::(); - let len48 = vec48.len(); - ::core::mem::forget(vec48); - *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len48; - *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr48.cast_mut(); - } - } + let super::super::super::super::duckdb::extension::column_types::Complexvalue { + type_expr: type_expr61, + json: json61, + } = e; + let vec62 = (type_expr61.into_bytes()).into_boxed_slice(); + let ptr62 = vec62.as_ptr().cast::(); + let len62 = vec62.len(); + ::core::mem::forget(vec62); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len62; + *base.add(0).cast::<*mut u8>() = ptr62.cast_mut(); + let vec63 = (json61.into_bytes()).into_boxed_slice(); + let ptr63 = vec63.as_ptr().cast::(); + let len63 = vec63.len(); + ::core::mem::forget(vec63); + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len63; + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr63.cast_mut(); } } - *base - .add(::core::mem::size_of::<*const u8>()) - .cast::() = len50; - *base.add(0).cast::<*mut u8>() = result50; + *ptr37 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len64; + *ptr37 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result64; } } - *ptr40 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len51; - *ptr40 - .add(::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = result51; + let vec66 = (validity38).into_boxed_slice(); + let ptr66 = vec66.as_ptr().cast::(); + let len66 = vec66.len(); + ::core::mem::forget(vec66); + *ptr37 + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::() = len66; + *ptr37 + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr66.cast_mut(); + *ptr37 + .add(6 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(rows38); } Err(e) => { - *ptr40.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V57; + *ptr37.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V72; match e { - V57::Invalidargument(e) => { - *ptr40 + V72::Invalidargument(e) => { + *ptr37 .add(::core::mem::size_of::<*const u8>()) .cast::() = (0i32) as u8; - let vec52 = (e.into_bytes()).into_boxed_slice(); - let ptr52 = vec52.as_ptr().cast::(); - let len52 = vec52.len(); - ::core::mem::forget(vec52); - *ptr40 + let vec67 = (e.into_bytes()).into_boxed_slice(); + let ptr67 = vec67.as_ptr().cast::(); + let len67 = vec67.len(); + ::core::mem::forget(vec67); + *ptr37 .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len52; - *ptr40 + .cast::() = len67; + *ptr37 .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr52.cast_mut(); + .cast::<*mut u8>() = ptr67.cast_mut(); } - V57::Unsupported(e) => { - *ptr40 + V72::Unsupported(e) => { + *ptr37 .add(::core::mem::size_of::<*const u8>()) .cast::() = (1i32) as u8; - let vec53 = (e.into_bytes()).into_boxed_slice(); - let ptr53 = vec53.as_ptr().cast::(); - let len53 = vec53.len(); - ::core::mem::forget(vec53); - *ptr40 + let vec68 = (e.into_bytes()).into_boxed_slice(); + let ptr68 = vec68.as_ptr().cast::(); + let len68 = vec68.len(); + ::core::mem::forget(vec68); + *ptr37 .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len53; - *ptr40 + .cast::() = len68; + *ptr37 .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr53.cast_mut(); + .cast::<*mut u8>() = ptr68.cast_mut(); } - V57::Invalidstate(e) => { - *ptr40 + V72::Invalidstate(e) => { + *ptr37 .add(::core::mem::size_of::<*const u8>()) .cast::() = (2i32) as u8; - let vec54 = (e.into_bytes()).into_boxed_slice(); - let ptr54 = vec54.as_ptr().cast::(); - let len54 = vec54.len(); - ::core::mem::forget(vec54); - *ptr40 + let vec69 = (e.into_bytes()).into_boxed_slice(); + let ptr69 = vec69.as_ptr().cast::(); + let len69 = vec69.len(); + ::core::mem::forget(vec69); + *ptr37 .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len54; - *ptr40 + .cast::() = len69; + *ptr37 .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr54.cast_mut(); + .cast::<*mut u8>() = ptr69.cast_mut(); } - V57::Io(e) => { - *ptr40 + V72::Io(e) => { + *ptr37 .add(::core::mem::size_of::<*const u8>()) .cast::() = (3i32) as u8; - let vec55 = (e.into_bytes()).into_boxed_slice(); - let ptr55 = vec55.as_ptr().cast::(); - let len55 = vec55.len(); - ::core::mem::forget(vec55); - *ptr40 + let vec70 = (e.into_bytes()).into_boxed_slice(); + let ptr70 = vec70.as_ptr().cast::(); + let len70 = vec70.len(); + ::core::mem::forget(vec70); + *ptr37 .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len55; - *ptr40 + .cast::() = len70; + *ptr37 .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr55.cast_mut(); + .cast::<*mut u8>() = ptr70.cast_mut(); } - V57::Internal(e) => { - *ptr40 + V72::Internal(e) => { + *ptr37 .add(::core::mem::size_of::<*const u8>()) .cast::() = (4i32) as u8; - let vec56 = (e.into_bytes()).into_boxed_slice(); - let ptr56 = vec56.as_ptr().cast::(); - let len56 = vec56.len(); - ::core::mem::forget(vec56); - *ptr40 + let vec71 = (e.into_bytes()).into_boxed_slice(); + let ptr71 = vec71.as_ptr().cast::(); + let len71 = vec71.len(); + ::core::mem::forget(vec71); + *ptr37 .add(3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len56; - *ptr40 + .cast::() = len71; + *ptr37 .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr56.cast_mut(); + .cast::<*mut u8>() = ptr71.cast_mut(); } } } }; - ptr40 + ptr37 } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn __post_return_call_table(arg0: *mut u8) { + pub unsafe fn __post_return_call_cast_col(arg0: *mut u8) { let l0 = i32::from(*arg0.add(0).cast::()); match l0 { 0 => { - let l1 = *arg0 - .add(::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l2 = *arg0 - .add(2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base16 = l1; - let len16 = l2; - for i in 0..len16 { - let base = base16 - .add(i * (2 * ::core::mem::size_of::<*const u8>())); - { - let l3 = *base.add(0).cast::<*mut u8>(); - let l4 = *base - .add(::core::mem::size_of::<*const u8>()) + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - let base15 = l3; - let len15 = l4; - for i in 0..len15 { - let base = base15 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - { - let l5 = i32::from(*base.add(0).cast::()); - match l5 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l6 = *base.add(8).cast::<*mut u8>(); - let l7 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l6, l7, 1); - } - 6 => { - let l8 = *base.add(8).cast::<*mut u8>(); - let l9 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base10 = l8; - let len10 = l9; - _rt::cabi_dealloc(base10, len10 * 1, 1); - } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l11 = *base.add(8).cast::<*mut u8>(); - let l12 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l11, l12, 1); - let l13 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l14 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l13, l14, 1); - } - } + let base4 = l2; + let len4 = l3; + _rt::cabi_dealloc(base4, len4 * 1, 1); + } + 1 => { + let l5 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base7 = l5; + let len7 = l6; + _rt::cabi_dealloc(base7, len7 * 8, 8); + } + 2 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l8; + let len10 = l9; + _rt::cabi_dealloc(base10, len10 * 8, 8); + } + 3 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base13 = l11; + let len13 = l12; + _rt::cabi_dealloc(base13, len13 * 8, 8); + } + 4 => { + let l14 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base16 = l14; + let len16 = l15; + _rt::cabi_dealloc(base16, len16 * 4, 4); + } + 5 => { + let l17 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base19 = l17; + let len19 = l18; + _rt::cabi_dealloc(base19, len19 * 8, 8); + } + 6 => { + let l20 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base22 = l20; + let len22 = l21; + _rt::cabi_dealloc(base22, len22 * 1, 1); + } + 7 => { + let l23 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l24 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base25 = l23; + let len25 = l24; + _rt::cabi_dealloc(base25, len25 * 2, 2); + } + 8 => { + let l26 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base28 = l26; + let len28 = l27; + _rt::cabi_dealloc(base28, len28 * 1, 1); + } + 9 => { + let l29 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l30 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base31 = l29; + let len31 = l30; + _rt::cabi_dealloc(base31, len31 * 2, 2); + } + 10 => { + let l32 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l33 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base34 = l32; + let len34 = l33; + _rt::cabi_dealloc(base34, len34 * 4, 4); + } + 11 => { + let l35 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l36 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base37 = l35; + let len37 = l36; + _rt::cabi_dealloc(base37, len37 * 4, 4); + } + 12 => { + let l38 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base40 = l38; + let len40 = l39; + _rt::cabi_dealloc(base40, len40 * 4, 4); + } + 13 => { + let l41 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l42 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base43 = l41; + let len43 = l42; + _rt::cabi_dealloc(base43, len43 * 8, 8); + } + 14 => { + let l44 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l45 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base46 = l44; + let len46 = l45; + _rt::cabi_dealloc(base46, len46 * 8, 8); + } + 15 => { + let l47 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l48 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base49 = l47; + let len49 = l48; + _rt::cabi_dealloc(base49, len49 * 24, 8); + } + 16 => { + let l50 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l51 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base52 = l50; + let len52 = l51; + _rt::cabi_dealloc(base52, len52 * 16, 8); + } + 17 => { + let l53 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l54 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base55 = l53; + let len55 = l54; + _rt::cabi_dealloc(base55, len55 * 16, 8); + } + 18 => { + let l56 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l57 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base60 = l56; + let len60 = l57; + for i in 0..len60 { + let base = base60 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l58 = *base.add(0).cast::<*mut u8>(); + let l59 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l58, l59, 1); } } _rt::cabi_dealloc( - base15, - len15 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, + base60, + len60 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + 19 => { + let l61 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l62 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base66 = l61; + let len66 = l62; + for i in 0..len66 { + let base = base66 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l63 = *base.add(0).cast::<*mut u8>(); + let l64 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base65 = l63; + let len65 = l64; + _rt::cabi_dealloc(base65, len65 * 1, 1); + } + } + _rt::cabi_dealloc( + base66, + len66 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l67 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l68 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base73 = l67; + let len73 = l68; + for i in 0..len73 { + let base = base73 + .add(i * (4 * ::core::mem::size_of::<*const u8>())); + { + let l69 = *base.add(0).cast::<*mut u8>(); + let l70 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l69, l70, 1); + let l71 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l72 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l71, l72, 1); + } + } + _rt::cabi_dealloc( + base73, + len73 * (4 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), ); } } - _rt::cabi_dealloc( - base16, - len16 * (2 * ::core::mem::size_of::<*const u8>()), - ::core::mem::size_of::<*const u8>(), - ); + let l74 = *arg0 + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l75 = *arg0 + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base76 = l74; + let len76 = l75; + _rt::cabi_dealloc(base76, len76 * 1, 1); } _ => { - let l17 = i32::from( + let l77 = i32::from( *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), ); - match l17 { + match l77 { 0 => { - let l18 = *arg0 + let l78 = *arg0 .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l19 = *arg0 + let l79 = *arg0 .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l18, l19, 1); + _rt::cabi_dealloc(l78, l79, 1); } 1 => { - let l20 = *arg0 + let l80 = *arg0 .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l21 = *arg0 + let l81 = *arg0 .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l20, l21, 1); + _rt::cabi_dealloc(l80, l81, 1); } 2 => { - let l22 = *arg0 + let l82 = *arg0 .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l23 = *arg0 + let l83 = *arg0 .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l22, l23, 1); + _rt::cabi_dealloc(l82, l83, 1); } 3 => { - let l24 = *arg0 + let l84 = *arg0 .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l25 = *arg0 + let l85 = *arg0 .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l24, l25, 1); + _rt::cabi_dealloc(l84, l85, 1); } _ => { - let l26 = *arg0 + let l86 = *arg0 .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l27 = *arg0 + let l87 = *arg0 .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l26, l27, 1); + _rt::cabi_dealloc(l86, l87, 1); } } } @@ -5292,1060 +6834,1112 @@ pub mod exports { } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_call_aggregate_cabi( + pub unsafe fn _export_call_scalar_cabi( arg0: i32, arg1: *mut u8, arg2: usize, + arg3: i32, + arg4: i64, + arg5: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - let base41 = arg1; - let len41 = arg2; - let mut result41 = _rt::Vec::with_capacity(len41); - for i in 0..len41 { - let base = base41 - .add(i * (2 * ::core::mem::size_of::<*const u8>())); - let e41 = { - let l0 = *base.add(0).cast::<*mut u8>(); - let l1 = *base - .add(::core::mem::size_of::<*const u8>()) - .cast::(); - let base40 = l0; - let len40 = l1; - let mut result40 = _rt::Vec::with_capacity(len40); - for i in 0..len40 { - let base = base40 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - let e40 = { - let l2 = i32::from(*base.add(0).cast::()); - use super::super::super::super::duckdb::extension::types::Duckvalue as V39; - let v39 = match l2 { - 0 => V39::Null, - 1 => { - let e39 = { - let l3 = i32::from(*base.add(8).cast::()); - _rt::bool_lift(l3 as u8) - }; - V39::Boolean(e39) - } - 2 => { - let e39 = { - let l4 = *base.add(8).cast::(); - l4 - }; - V39::Int64(e39) - } - 3 => { - let e39 = { - let l5 = *base.add(8).cast::(); - l5 as u64 - }; - V39::Uint64(e39) - } - 4 => { - let e39 = { - let l6 = *base.add(8).cast::(); - l6 - }; - V39::Float64(e39) - } - 5 => { - let e39 = { - let l7 = *base.add(8).cast::<*mut u8>(); - let l8 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len9 = l8; - let bytes9 = _rt::Vec::from_raw_parts( - l7.cast(), - len9, - len9, - ); - _rt::string_lift(bytes9) - }; - V39::Text(e39) - } - 6 => { - let e39 = { - let l10 = *base.add(8).cast::<*mut u8>(); - let l11 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len12 = l11; - _rt::Vec::from_raw_parts(l10.cast(), len12, len12) - }; - V39::Blob(e39) - } - 7 => { - let e39 = { - let l13 = *base.add(8).cast::(); - l13 - }; - V39::Int32(e39) - } - 8 => { - let e39 = { - let l14 = *base.add(8).cast::(); - l14 - }; - V39::Timestamp(e39) - } - 9 => { - let e39 = { - let l15 = i32::from(*base.add(8).cast::()); - l15 as i8 - }; - V39::Int8(e39) - } - 10 => { - let e39 = { - let l16 = i32::from(*base.add(8).cast::()); - l16 as i16 - }; - V39::Int16(e39) - } - 11 => { - let e39 = { - let l17 = i32::from(*base.add(8).cast::()); - l17 as u8 - }; - V39::Uint8(e39) - } - 12 => { - let e39 = { - let l18 = i32::from(*base.add(8).cast::()); - l18 as u16 - }; - V39::Uint16(e39) - } - 13 => { - let e39 = { - let l19 = *base.add(8).cast::(); - l19 as u32 - }; - V39::Uint32(e39) - } - 14 => { - let e39 = { - let l20 = *base.add(8).cast::(); - l20 - }; - V39::Float32(e39) - } - 15 => { - let e39 = { - let l21 = *base.add(8).cast::(); - l21 - }; - V39::Date(e39) - } - 16 => { - let e39 = { - let l22 = *base.add(8).cast::(); - l22 - }; - V39::Time(e39) - } - 17 => { - let e39 = { - let l23 = *base.add(8).cast::(); - l23 - }; - V39::Timestamptz(e39) - } - 18 => { - let e39 = { - let l24 = *base.add(8).cast::(); - let l25 = *base.add(16).cast::(); - let l26 = i32::from(*base.add(24).cast::()); - let l27 = i32::from(*base.add(25).cast::()); - super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: l24 as u64, - upper: l25 as u64, - width: l26 as u8, - scale: l27 as u8, - } - }; - V39::Decimal(e39) - } - 19 => { - let e39 = { - let l28 = *base.add(8).cast::(); - let l29 = *base.add(12).cast::(); - let l30 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Intervalvalue { - months: l28, - days: l29, - micros: l30, - } - }; - V39::Interval(e39) - } - 20 => { - let e39 = { - let l31 = *base.add(8).cast::(); - let l32 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: l31 as u64, - lo: l32 as u64, - } - }; - V39::Uuid(e39) - } - n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); - let e39 = { - let l33 = *base.add(8).cast::<*mut u8>(); - let l34 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len35 = l34; - let bytes35 = _rt::Vec::from_raw_parts( - l33.cast(), - len35, - len35, - ); - let l36 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l37 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len38 = l37; - let bytes38 = _rt::Vec::from_raw_parts( - l36.cast(), - len38, - len38, - ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes35), - json: _rt::string_lift(bytes38), - } - }; - V39::Complex(e39) - } + let base38 = arg1; + let len38 = arg2; + let mut result38 = _rt::Vec::with_capacity(len38); + for i in 0..len38 { + let base = base38 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + let e38 = { + let l0 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V37; + let v37 = match l0 { + 0 => V37::Null, + 1 => { + let e37 = { + let l1 = i32::from(*base.add(8).cast::()); + _rt::bool_lift(l1 as u8) }; - v39 - }; - result40.push(e40); - } - _rt::cabi_dealloc( - base40, - len40 * (24 + 2 * ::core::mem::size_of::<*const u8>()), - 8, - ); - result40 - }; - result41.push(e41); - } - _rt::cabi_dealloc( - base41, - len41 * (2 * ::core::mem::size_of::<*const u8>()), - ::core::mem::size_of::<*const u8>(), - ); - let result42 = T::call_aggregate(arg0 as u32, result41); - let ptr43 = (&raw mut _RET_AREA.0).cast::(); - match result42 { - Ok(e) => { - *ptr43.add(0).cast::() = (0i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckvalue as V52; - match e { - V52::Null => { - *ptr43.add(8).cast::() = (0i32) as u8; - } - V52::Boolean(e) => { - *ptr43.add(8).cast::() = (1i32) as u8; - *ptr43.add(16).cast::() = (match e { - true => 1, - false => 0, - }) as u8; + V37::Boolean(e37) } - V52::Int64(e) => { - *ptr43.add(8).cast::() = (2i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i64(e); + 2 => { + let e37 = { + let l2 = *base.add(8).cast::(); + l2 + }; + V37::Int64(e37) } - V52::Uint64(e) => { - *ptr43.add(8).cast::() = (3i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i64(e); + 3 => { + let e37 = { + let l3 = *base.add(8).cast::(); + l3 as u64 + }; + V37::Uint64(e37) } - V52::Float64(e) => { - *ptr43.add(8).cast::() = (4i32) as u8; - *ptr43.add(16).cast::() = _rt::as_f64(e); + 4 => { + let e37 = { + let l4 = *base.add(8).cast::(); + l4 + }; + V37::Float64(e37) } - V52::Text(e) => { - *ptr43.add(8).cast::() = (5i32) as u8; - let vec44 = (e.into_bytes()).into_boxed_slice(); - let ptr44 = vec44.as_ptr().cast::(); - let len44 = vec44.len(); - ::core::mem::forget(vec44); - *ptr43 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len44; - *ptr43.add(16).cast::<*mut u8>() = ptr44.cast_mut(); + 5 => { + let e37 = { + let l5 = *base.add(8).cast::<*mut u8>(); + let l6 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, + ); + _rt::string_lift(bytes7) + }; + V37::Text(e37) } - V52::Blob(e) => { - *ptr43.add(8).cast::() = (6i32) as u8; - let vec45 = (e).into_boxed_slice(); - let ptr45 = vec45.as_ptr().cast::(); - let len45 = vec45.len(); - ::core::mem::forget(vec45); - *ptr43 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len45; - *ptr43.add(16).cast::<*mut u8>() = ptr45.cast_mut(); + 6 => { + let e37 = { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + }; + V37::Blob(e37) } - V52::Int32(e) => { - *ptr43.add(8).cast::() = (7i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i32(e); + 7 => { + let e37 = { + let l11 = *base.add(8).cast::(); + l11 + }; + V37::Int32(e37) } - V52::Timestamp(e) => { - *ptr43.add(8).cast::() = (8i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i64(e); + 8 => { + let e37 = { + let l12 = *base.add(8).cast::(); + l12 + }; + V37::Timestamp(e37) } - V52::Int8(e) => { - *ptr43.add(8).cast::() = (9i32) as u8; - *ptr43.add(16).cast::() = (_rt::as_i32(e)) as u8; + 9 => { + let e37 = { + let l13 = i32::from(*base.add(8).cast::()); + l13 as i8 + }; + V37::Int8(e37) } - V52::Int16(e) => { - *ptr43.add(8).cast::() = (10i32) as u8; - *ptr43.add(16).cast::() = (_rt::as_i32(e)) as u16; + 10 => { + let e37 = { + let l14 = i32::from(*base.add(8).cast::()); + l14 as i16 + }; + V37::Int16(e37) } - V52::Uint8(e) => { - *ptr43.add(8).cast::() = (11i32) as u8; - *ptr43.add(16).cast::() = (_rt::as_i32(e)) as u8; + 11 => { + let e37 = { + let l15 = i32::from(*base.add(8).cast::()); + l15 as u8 + }; + V37::Uint8(e37) } - V52::Uint16(e) => { - *ptr43.add(8).cast::() = (12i32) as u8; - *ptr43.add(16).cast::() = (_rt::as_i32(e)) as u16; + 12 => { + let e37 = { + let l16 = i32::from(*base.add(8).cast::()); + l16 as u16 + }; + V37::Uint16(e37) } - V52::Uint32(e) => { - *ptr43.add(8).cast::() = (13i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i32(e); + 13 => { + let e37 = { + let l17 = *base.add(8).cast::(); + l17 as u32 + }; + V37::Uint32(e37) } - V52::Float32(e) => { - *ptr43.add(8).cast::() = (14i32) as u8; - *ptr43.add(16).cast::() = _rt::as_f32(e); + 14 => { + let e37 = { + let l18 = *base.add(8).cast::(); + l18 + }; + V37::Float32(e37) } - V52::Date(e) => { - *ptr43.add(8).cast::() = (15i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i32(e); + 15 => { + let e37 = { + let l19 = *base.add(8).cast::(); + l19 + }; + V37::Date(e37) } - V52::Time(e) => { - *ptr43.add(8).cast::() = (16i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i64(e); + 16 => { + let e37 = { + let l20 = *base.add(8).cast::(); + l20 + }; + V37::Time(e37) } - V52::Timestamptz(e) => { - *ptr43.add(8).cast::() = (17i32) as u8; - *ptr43.add(16).cast::() = _rt::as_i64(e); + 17 => { + let e37 = { + let l21 = *base.add(8).cast::(); + l21 + }; + V37::Timestamptz(e37) } - V52::Decimal(e) => { - *ptr43.add(8).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower46, - upper: upper46, - width: width46, - scale: scale46, - } = e; - *ptr43.add(16).cast::() = _rt::as_i64(lower46); - *ptr43.add(24).cast::() = _rt::as_i64(upper46); - *ptr43.add(32).cast::() = (_rt::as_i32(width46)) as u8; - *ptr43.add(33).cast::() = (_rt::as_i32(scale46)) as u8; + 18 => { + let e37 = { + let l22 = *base.add(8).cast::(); + let l23 = *base.add(16).cast::(); + let l24 = i32::from(*base.add(24).cast::()); + let l25 = i32::from(*base.add(25).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l22 as u64, + upper: l23 as u64, + width: l24 as u8, + scale: l25 as u8, + } + }; + V37::Decimal(e37) } - V52::Interval(e) => { - *ptr43.add(8).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months47, - days: days47, - micros: micros47, - } = e; - *ptr43.add(16).cast::() = _rt::as_i32(months47); - *ptr43.add(20).cast::() = _rt::as_i32(days47); - *ptr43.add(24).cast::() = _rt::as_i64(micros47); + 19 => { + let e37 = { + let l26 = *base.add(8).cast::(); + let l27 = *base.add(12).cast::(); + let l28 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l26, + days: l27, + micros: l28, + } + }; + V37::Interval(e37) } - V52::Uuid(e) => { - *ptr43.add(8).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi48, - lo: lo48, - } = e; - *ptr43.add(16).cast::() = _rt::as_i64(hi48); - *ptr43.add(24).cast::() = _rt::as_i64(lo48); + 20 => { + let e37 = { + let l29 = *base.add(8).cast::(); + let l30 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l29 as u64, + lo: l30 as u64, + } + }; + V37::Uuid(e37) } - V52::Complex(e) => { - *ptr43.add(8).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr49, - json: json49, - } = e; - let vec50 = (type_expr49.into_bytes()).into_boxed_slice(); - let ptr50 = vec50.as_ptr().cast::(); - let len50 = vec50.len(); - ::core::mem::forget(vec50); - *ptr43 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len50; - *ptr43.add(16).cast::<*mut u8>() = ptr50.cast_mut(); - let vec51 = (json49.into_bytes()).into_boxed_slice(); - let ptr51 = vec51.as_ptr().cast::(); - let len51 = vec51.len(); - ::core::mem::forget(vec51); - *ptr43 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len51; - *ptr43 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr51.cast_mut(); + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e37 = { + let l31 = *base.add(8).cast::<*mut u8>(); + let l32 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len33 = l32; + let bytes33 = _rt::Vec::from_raw_parts( + l31.cast(), + len33, + len33, + ); + let l34 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l35 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len36 = l35; + let bytes36 = _rt::Vec::from_raw_parts( + l34.cast(), + len36, + len36, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes33), + json: _rt::string_lift(bytes36), + } + }; + V37::Complex(e37) } - } - } - Err(e) => { - *ptr43.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V58; + }; + v37 + }; + result38.push(e38); + } + _rt::cabi_dealloc( + base38, + len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result39 = T::call_scalar( + arg0 as u32, + result38, + super::super::super::super::duckdb::extension::types::Invokeinfo { + rowindex: match arg3 { + 0 => None, + 1 => { + let e = arg4 as u64; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + iswindow: _rt::bool_lift(arg5 as u8), + }, + ); + let ptr40 = (&raw mut _RET_AREA.0).cast::(); + match result39 { + Ok(e) => { + *ptr40.add(0).cast::() = (0i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckvalue as V49; match e { - V58::Invalidargument(e) => { - *ptr43.add(8).cast::() = (0i32) as u8; - let vec53 = (e.into_bytes()).into_boxed_slice(); - let ptr53 = vec53.as_ptr().cast::(); - let len53 = vec53.len(); - ::core::mem::forget(vec53); - *ptr43 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len53; - *ptr43 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr53.cast_mut(); + V49::Null => { + *ptr40.add(8).cast::() = (0i32) as u8; } - V58::Unsupported(e) => { - *ptr43.add(8).cast::() = (1i32) as u8; - let vec54 = (e.into_bytes()).into_boxed_slice(); - let ptr54 = vec54.as_ptr().cast::(); - let len54 = vec54.len(); - ::core::mem::forget(vec54); - *ptr43 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len54; - *ptr43 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr54.cast_mut(); + V49::Boolean(e) => { + *ptr40.add(8).cast::() = (1i32) as u8; + *ptr40.add(16).cast::() = (match e { + true => 1, + false => 0, + }) as u8; } - V58::Invalidstate(e) => { - *ptr43.add(8).cast::() = (2i32) as u8; - let vec55 = (e.into_bytes()).into_boxed_slice(); - let ptr55 = vec55.as_ptr().cast::(); - let len55 = vec55.len(); - ::core::mem::forget(vec55); - *ptr43 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len55; - *ptr43 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr55.cast_mut(); + V49::Int64(e) => { + *ptr40.add(8).cast::() = (2i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i64(e); } - V58::Io(e) => { - *ptr43.add(8).cast::() = (3i32) as u8; - let vec56 = (e.into_bytes()).into_boxed_slice(); - let ptr56 = vec56.as_ptr().cast::(); - let len56 = vec56.len(); - ::core::mem::forget(vec56); - *ptr43 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len56; - *ptr43 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr56.cast_mut(); + V49::Uint64(e) => { + *ptr40.add(8).cast::() = (3i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i64(e); } - V58::Internal(e) => { - *ptr43.add(8).cast::() = (4i32) as u8; - let vec57 = (e.into_bytes()).into_boxed_slice(); - let ptr57 = vec57.as_ptr().cast::(); - let len57 = vec57.len(); - ::core::mem::forget(vec57); - *ptr43 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len57; - *ptr43 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr57.cast_mut(); + V49::Float64(e) => { + *ptr40.add(8).cast::() = (4i32) as u8; + *ptr40.add(16).cast::() = _rt::as_f64(e); } - } - } - }; - ptr43 - } - #[doc(hidden)] - #[allow(non_snake_case)] - pub unsafe fn __post_return_call_aggregate(arg0: *mut u8) { - let l0 = i32::from(*arg0.add(0).cast::()); - match l0 { - 0 => { - let l1 = i32::from(*arg0.add(8).cast::()); - match l1 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l2 = *arg0.add(16).cast::<*mut u8>(); - let l3 = *arg0 + V49::Text(e) => { + *ptr40.add(8).cast::() = (5i32) as u8; + let vec41 = (e.into_bytes()).into_boxed_slice(); + let ptr41 = vec41.as_ptr().cast::(); + let len41 = vec41.len(); + ::core::mem::forget(vec41); + *ptr40 .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l2, l3, 1); + .cast::() = len41; + *ptr40.add(16).cast::<*mut u8>() = ptr41.cast_mut(); } - 6 => { - let l4 = *arg0.add(16).cast::<*mut u8>(); - let l5 = *arg0 + V49::Blob(e) => { + *ptr40.add(8).cast::() = (6i32) as u8; + let vec42 = (e).into_boxed_slice(); + let ptr42 = vec42.as_ptr().cast::(); + let len42 = vec42.len(); + ::core::mem::forget(vec42); + *ptr40 .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base6 = l4; - let len6 = l5; - _rt::cabi_dealloc(base6, len6 * 1, 1); + .cast::() = len42; + *ptr40.add(16).cast::<*mut u8>() = ptr42.cast_mut(); } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l7 = *arg0.add(16).cast::<*mut u8>(); - let l8 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l7, l8, 1); - let l9 = *arg0 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l10 = *arg0 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l9, l10, 1); + V49::Int32(e) => { + *ptr40.add(8).cast::() = (7i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i32(e); } - } - } - _ => { - let l11 = i32::from(*arg0.add(8).cast::()); - match l11 { - 0 => { - let l12 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l13 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l12, l13, 1); + V49::Timestamp(e) => { + *ptr40.add(8).cast::() = (8i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i64(e); } - 1 => { - let l14 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l15 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l14, l15, 1); + V49::Int8(e) => { + *ptr40.add(8).cast::() = (9i32) as u8; + *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u8; } - 2 => { - let l16 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l17 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l16, l17, 1); + V49::Int16(e) => { + *ptr40.add(8).cast::() = (10i32) as u8; + *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u16; } - 3 => { - let l18 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l19 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l18, l19, 1); + V49::Uint8(e) => { + *ptr40.add(8).cast::() = (11i32) as u8; + *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u8; } - _ => { - let l20 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l21 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l20, l21, 1); - } - } - } - } - } - #[doc(hidden)] - #[allow(non_snake_case)] - pub unsafe fn _export_call_pragma_cabi( - arg0: i32, - arg1: *mut u8, - arg2: usize, - ) -> *mut u8 { - #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - let base38 = arg1; - let len38 = arg2; - let mut result38 = _rt::Vec::with_capacity(len38); - for i in 0..len38 { - let base = base38 - .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); - let e38 = { - let l0 = i32::from(*base.add(0).cast::()); - use super::super::super::super::duckdb::extension::types::Duckvalue as V37; - let v37 = match l0 { - 0 => V37::Null, - 1 => { - let e37 = { - let l1 = i32::from(*base.add(8).cast::()); - _rt::bool_lift(l1 as u8) - }; - V37::Boolean(e37) - } - 2 => { - let e37 = { - let l2 = *base.add(8).cast::(); - l2 - }; - V37::Int64(e37) + V49::Uint16(e) => { + *ptr40.add(8).cast::() = (12i32) as u8; + *ptr40.add(16).cast::() = (_rt::as_i32(e)) as u16; } - 3 => { - let e37 = { - let l3 = *base.add(8).cast::(); - l3 as u64 - }; - V37::Uint64(e37) + V49::Uint32(e) => { + *ptr40.add(8).cast::() = (13i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i32(e); } - 4 => { - let e37 = { - let l4 = *base.add(8).cast::(); - l4 - }; - V37::Float64(e37) + V49::Float32(e) => { + *ptr40.add(8).cast::() = (14i32) as u8; + *ptr40.add(16).cast::() = _rt::as_f32(e); } - 5 => { - let e37 = { - let l5 = *base.add(8).cast::<*mut u8>(); - let l6 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len7 = l6; - let bytes7 = _rt::Vec::from_raw_parts( - l5.cast(), - len7, - len7, - ); - _rt::string_lift(bytes7) - }; - V37::Text(e37) + V49::Date(e) => { + *ptr40.add(8).cast::() = (15i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i32(e); } - 6 => { - let e37 = { - let l8 = *base.add(8).cast::<*mut u8>(); - let l9 = *base - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let len10 = l9; - _rt::Vec::from_raw_parts(l8.cast(), len10, len10) - }; - V37::Blob(e37) + V49::Time(e) => { + *ptr40.add(8).cast::() = (16i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i64(e); } - 7 => { - let e37 = { - let l11 = *base.add(8).cast::(); - l11 - }; - V37::Int32(e37) + V49::Timestamptz(e) => { + *ptr40.add(8).cast::() = (17i32) as u8; + *ptr40.add(16).cast::() = _rt::as_i64(e); } - 8 => { - let e37 = { - let l12 = *base.add(8).cast::(); - l12 - }; - V37::Timestamp(e37) + V49::Decimal(e) => { + *ptr40.add(8).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower43, + upper: upper43, + width: width43, + scale: scale43, + } = e; + *ptr40.add(16).cast::() = _rt::as_i64(lower43); + *ptr40.add(24).cast::() = _rt::as_i64(upper43); + *ptr40.add(32).cast::() = (_rt::as_i32(width43)) as u8; + *ptr40.add(33).cast::() = (_rt::as_i32(scale43)) as u8; } - 9 => { - let e37 = { - let l13 = i32::from(*base.add(8).cast::()); - l13 as i8 - }; - V37::Int8(e37) + V49::Interval(e) => { + *ptr40.add(8).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months44, + days: days44, + micros: micros44, + } = e; + *ptr40.add(16).cast::() = _rt::as_i32(months44); + *ptr40.add(20).cast::() = _rt::as_i32(days44); + *ptr40.add(24).cast::() = _rt::as_i64(micros44); } - 10 => { - let e37 = { - let l14 = i32::from(*base.add(8).cast::()); - l14 as i16 - }; - V37::Int16(e37) + V49::Uuid(e) => { + *ptr40.add(8).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi45, + lo: lo45, + } = e; + *ptr40.add(16).cast::() = _rt::as_i64(hi45); + *ptr40.add(24).cast::() = _rt::as_i64(lo45); } - 11 => { - let e37 = { - let l15 = i32::from(*base.add(8).cast::()); - l15 as u8 - }; - V37::Uint8(e37) + V49::Complex(e) => { + *ptr40.add(8).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr46, + json: json46, + } = e; + let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); + let ptr47 = vec47.as_ptr().cast::(); + let len47 = vec47.len(); + ::core::mem::forget(vec47); + *ptr40 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len47; + *ptr40.add(16).cast::<*mut u8>() = ptr47.cast_mut(); + let vec48 = (json46.into_bytes()).into_boxed_slice(); + let ptr48 = vec48.as_ptr().cast::(); + let len48 = vec48.len(); + ::core::mem::forget(vec48); + *ptr40 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len48; + *ptr40 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr48.cast_mut(); } - 12 => { - let e37 = { - let l16 = i32::from(*base.add(8).cast::()); - l16 as u16 - }; - V37::Uint16(e37) + } + } + Err(e) => { + *ptr40.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V55; + match e { + V55::Invalidargument(e) => { + *ptr40.add(8).cast::() = (0i32) as u8; + let vec50 = (e.into_bytes()).into_boxed_slice(); + let ptr50 = vec50.as_ptr().cast::(); + let len50 = vec50.len(); + ::core::mem::forget(vec50); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len50; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr50.cast_mut(); } - 13 => { - let e37 = { - let l17 = *base.add(8).cast::(); - l17 as u32 - }; - V37::Uint32(e37) + V55::Unsupported(e) => { + *ptr40.add(8).cast::() = (1i32) as u8; + let vec51 = (e.into_bytes()).into_boxed_slice(); + let ptr51 = vec51.as_ptr().cast::(); + let len51 = vec51.len(); + ::core::mem::forget(vec51); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len51; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr51.cast_mut(); } - 14 => { - let e37 = { - let l18 = *base.add(8).cast::(); - l18 - }; - V37::Float32(e37) + V55::Invalidstate(e) => { + *ptr40.add(8).cast::() = (2i32) as u8; + let vec52 = (e.into_bytes()).into_boxed_slice(); + let ptr52 = vec52.as_ptr().cast::(); + let len52 = vec52.len(); + ::core::mem::forget(vec52); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len52; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr52.cast_mut(); } - 15 => { - let e37 = { - let l19 = *base.add(8).cast::(); - l19 - }; - V37::Date(e37) + V55::Io(e) => { + *ptr40.add(8).cast::() = (3i32) as u8; + let vec53 = (e.into_bytes()).into_boxed_slice(); + let ptr53 = vec53.as_ptr().cast::(); + let len53 = vec53.len(); + ::core::mem::forget(vec53); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len53; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr53.cast_mut(); } - 16 => { - let e37 = { - let l20 = *base.add(8).cast::(); - l20 - }; - V37::Time(e37) + V55::Internal(e) => { + *ptr40.add(8).cast::() = (4i32) as u8; + let vec54 = (e.into_bytes()).into_boxed_slice(); + let ptr54 = vec54.as_ptr().cast::(); + let len54 = vec54.len(); + ::core::mem::forget(vec54); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len54; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr54.cast_mut(); } - 17 => { + } + } + }; + ptr40 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_call_scalar(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = i32::from(*arg0.add(8).cast::()); + match l1 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l2 = *arg0.add(16).cast::<*mut u8>(); + let l3 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 6 => { + let l4 = *arg0.add(16).cast::<*mut u8>(); + let l5 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base6 = l4; + let len6 = l5; + _rt::cabi_dealloc(base6, len6 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l7 = *arg0.add(16).cast::<*mut u8>(); + let l8 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + let l9 = *arg0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + } + } + _ => { + let l11 = i32::from(*arg0.add(8).cast::()); + match l11 { + 0 => { + let l12 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l13 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l12, l13, 1); + } + 1 => { + let l14 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l14, l15, 1); + } + 2 => { + let l16 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l17 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l16, l17, 1); + } + 3 => { + let l18 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); + } + _ => { + let l20 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l20, l21, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_call_table_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let base38 = arg1; + let len38 = arg2; + let mut result38 = _rt::Vec::with_capacity(len38); + for i in 0..len38 { + let base = base38 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + let e38 = { + let l0 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V37; + let v37 = match l0 { + 0 => V37::Null, + 1 => { let e37 = { - let l21 = *base.add(8).cast::(); - l21 + let l1 = i32::from(*base.add(8).cast::()); + _rt::bool_lift(l1 as u8) }; - V37::Timestamptz(e37) + V37::Boolean(e37) } - 18 => { + 2 => { let e37 = { - let l22 = *base.add(8).cast::(); - let l23 = *base.add(16).cast::(); - let l24 = i32::from(*base.add(24).cast::()); - let l25 = i32::from(*base.add(25).cast::()); - super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: l22 as u64, - upper: l23 as u64, - width: l24 as u8, - scale: l25 as u8, - } + let l2 = *base.add(8).cast::(); + l2 }; - V37::Decimal(e37) + V37::Int64(e37) } - 19 => { + 3 => { let e37 = { - let l26 = *base.add(8).cast::(); - let l27 = *base.add(12).cast::(); - let l28 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Intervalvalue { - months: l26, - days: l27, - micros: l28, - } + let l3 = *base.add(8).cast::(); + l3 as u64 }; - V37::Interval(e37) + V37::Uint64(e37) } - 20 => { + 4 => { let e37 = { - let l29 = *base.add(8).cast::(); - let l30 = *base.add(16).cast::(); - super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: l29 as u64, - lo: l30 as u64, - } + let l4 = *base.add(8).cast::(); + l4 }; - V37::Uuid(e37) + V37::Float64(e37) } - n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); + 5 => { let e37 = { - let l31 = *base.add(8).cast::<*mut u8>(); - let l32 = *base + let l5 = *base.add(8).cast::<*mut u8>(); + let l6 = *base .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len33 = l32; - let bytes33 = _rt::Vec::from_raw_parts( - l31.cast(), - len33, - len33, + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, ); - let l34 = *base - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l35 = *base - .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + _rt::string_lift(bytes7) + }; + V37::Text(e37) + } + 6 => { + let e37 = { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) .cast::(); - let len36 = l35; - let bytes36 = _rt::Vec::from_raw_parts( - l34.cast(), - len36, - len36, - ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes33), - json: _rt::string_lift(bytes36), - } + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) }; - V37::Complex(e37) + V37::Blob(e37) } - }; - v37 - }; - result38.push(e38); - } - _rt::cabi_dealloc( - base38, - len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 7 => { + let e37 = { + let l11 = *base.add(8).cast::(); + l11 + }; + V37::Int32(e37) + } + 8 => { + let e37 = { + let l12 = *base.add(8).cast::(); + l12 + }; + V37::Timestamp(e37) + } + 9 => { + let e37 = { + let l13 = i32::from(*base.add(8).cast::()); + l13 as i8 + }; + V37::Int8(e37) + } + 10 => { + let e37 = { + let l14 = i32::from(*base.add(8).cast::()); + l14 as i16 + }; + V37::Int16(e37) + } + 11 => { + let e37 = { + let l15 = i32::from(*base.add(8).cast::()); + l15 as u8 + }; + V37::Uint8(e37) + } + 12 => { + let e37 = { + let l16 = i32::from(*base.add(8).cast::()); + l16 as u16 + }; + V37::Uint16(e37) + } + 13 => { + let e37 = { + let l17 = *base.add(8).cast::(); + l17 as u32 + }; + V37::Uint32(e37) + } + 14 => { + let e37 = { + let l18 = *base.add(8).cast::(); + l18 + }; + V37::Float32(e37) + } + 15 => { + let e37 = { + let l19 = *base.add(8).cast::(); + l19 + }; + V37::Date(e37) + } + 16 => { + let e37 = { + let l20 = *base.add(8).cast::(); + l20 + }; + V37::Time(e37) + } + 17 => { + let e37 = { + let l21 = *base.add(8).cast::(); + l21 + }; + V37::Timestamptz(e37) + } + 18 => { + let e37 = { + let l22 = *base.add(8).cast::(); + let l23 = *base.add(16).cast::(); + let l24 = i32::from(*base.add(24).cast::()); + let l25 = i32::from(*base.add(25).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l22 as u64, + upper: l23 as u64, + width: l24 as u8, + scale: l25 as u8, + } + }; + V37::Decimal(e37) + } + 19 => { + let e37 = { + let l26 = *base.add(8).cast::(); + let l27 = *base.add(12).cast::(); + let l28 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l26, + days: l27, + micros: l28, + } + }; + V37::Interval(e37) + } + 20 => { + let e37 = { + let l29 = *base.add(8).cast::(); + let l30 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l29 as u64, + lo: l30 as u64, + } + }; + V37::Uuid(e37) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e37 = { + let l31 = *base.add(8).cast::<*mut u8>(); + let l32 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len33 = l32; + let bytes33 = _rt::Vec::from_raw_parts( + l31.cast(), + len33, + len33, + ); + let l34 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l35 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len36 = l35; + let bytes36 = _rt::Vec::from_raw_parts( + l34.cast(), + len36, + len36, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes33), + json: _rt::string_lift(bytes36), + } + }; + V37::Complex(e37) + } + }; + v37 + }; + result38.push(e38); + } + _rt::cabi_dealloc( + base38, + len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), 8, ); - let result39 = T::call_pragma(arg0 as u32, result38); + let result39 = T::call_table(arg0 as u32, result38); let ptr40 = (&raw mut _RET_AREA.0).cast::(); match result39 { Ok(e) => { *ptr40.add(0).cast::() = (0i32) as u8; - match e { - Some(e) => { - *ptr40.add(8).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckvalue as V49; - match e { - V49::Null => { - *ptr40.add(16).cast::() = (0i32) as u8; - } - V49::Boolean(e) => { - *ptr40.add(16).cast::() = (1i32) as u8; - *ptr40.add(24).cast::() = (match e { - true => 1, - false => 0, - }) as u8; - } - V49::Int64(e) => { - *ptr40.add(16).cast::() = (2i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i64(e); - } - V49::Uint64(e) => { - *ptr40.add(16).cast::() = (3i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i64(e); - } - V49::Float64(e) => { - *ptr40.add(16).cast::() = (4i32) as u8; - *ptr40.add(24).cast::() = _rt::as_f64(e); - } - V49::Text(e) => { - *ptr40.add(16).cast::() = (5i32) as u8; - let vec41 = (e.into_bytes()).into_boxed_slice(); - let ptr41 = vec41.as_ptr().cast::(); - let len41 = vec41.len(); - ::core::mem::forget(vec41); - *ptr40 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len41; - *ptr40.add(24).cast::<*mut u8>() = ptr41.cast_mut(); - } - V49::Blob(e) => { - *ptr40.add(16).cast::() = (6i32) as u8; - let vec42 = (e).into_boxed_slice(); - let ptr42 = vec42.as_ptr().cast::(); - let len42 = vec42.len(); - ::core::mem::forget(vec42); - *ptr40 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len42; - *ptr40.add(24).cast::<*mut u8>() = ptr42.cast_mut(); - } - V49::Int32(e) => { - *ptr40.add(16).cast::() = (7i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i32(e); - } - V49::Timestamp(e) => { - *ptr40.add(16).cast::() = (8i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i64(e); - } - V49::Int8(e) => { - *ptr40.add(16).cast::() = (9i32) as u8; - *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u8; - } - V49::Int16(e) => { - *ptr40.add(16).cast::() = (10i32) as u8; - *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u16; - } - V49::Uint8(e) => { - *ptr40.add(16).cast::() = (11i32) as u8; - *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u8; + let vec51 = e; + let len51 = vec51.len(); + let layout51 = _rt::alloc::Layout::from_size_align_unchecked( + vec51.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result51 = if layout51.size() != 0 { + let ptr = _rt::alloc::alloc(layout51).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout51); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec51.into_iter().enumerate() { + let base = result51 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec50 = e; + let len50 = vec50.len(); + let layout50 = _rt::alloc::Layout::from_size_align_unchecked( + vec50.len() + * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result50 = if layout50.size() != 0 { + let ptr = _rt::alloc::alloc(layout50).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout50); } - V49::Uint16(e) => { - *ptr40.add(16).cast::() = (12i32) as u8; - *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u16; - } - V49::Uint32(e) => { - *ptr40.add(16).cast::() = (13i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i32(e); - } - V49::Float32(e) => { - *ptr40.add(16).cast::() = (14i32) as u8; - *ptr40.add(24).cast::() = _rt::as_f32(e); - } - V49::Date(e) => { - *ptr40.add(16).cast::() = (15i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i32(e); - } - V49::Time(e) => { - *ptr40.add(16).cast::() = (16i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i64(e); - } - V49::Timestamptz(e) => { - *ptr40.add(16).cast::() = (17i32) as u8; - *ptr40.add(24).cast::() = _rt::as_i64(e); - } - V49::Decimal(e) => { - *ptr40.add(16).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower43, - upper: upper43, - width: width43, - scale: scale43, - } = e; - *ptr40.add(24).cast::() = _rt::as_i64(lower43); - *ptr40.add(32).cast::() = _rt::as_i64(upper43); - *ptr40.add(40).cast::() = (_rt::as_i32(width43)) as u8; - *ptr40.add(41).cast::() = (_rt::as_i32(scale43)) as u8; - } - V49::Interval(e) => { - *ptr40.add(16).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months44, - days: days44, - micros: micros44, - } = e; - *ptr40.add(24).cast::() = _rt::as_i32(months44); - *ptr40.add(28).cast::() = _rt::as_i32(days44); - *ptr40.add(32).cast::() = _rt::as_i64(micros44); - } - V49::Uuid(e) => { - *ptr40.add(16).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi45, - lo: lo45, - } = e; - *ptr40.add(24).cast::() = _rt::as_i64(hi45); - *ptr40.add(32).cast::() = _rt::as_i64(lo45); - } - V49::Complex(e) => { - *ptr40.add(16).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr46, - json: json46, - } = e; - let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); - let ptr47 = vec47.as_ptr().cast::(); - let len47 = vec47.len(); - ::core::mem::forget(vec47); - *ptr40 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len47; - *ptr40.add(24).cast::<*mut u8>() = ptr47.cast_mut(); - let vec48 = (json46.into_bytes()).into_boxed_slice(); - let ptr48 = vec48.as_ptr().cast::(); - let len48 = vec48.len(); - ::core::mem::forget(vec48); - *ptr40 - .add(24 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::() = len48; - *ptr40 - .add(24 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr48.cast_mut(); + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec50.into_iter().enumerate() { + let base = result50 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + use super::super::super::super::duckdb::extension::types::Duckvalue as V49; + match e { + V49::Null => { + *base.add(0).cast::() = (0i32) as u8; + } + V49::Boolean(e) => { + *base.add(0).cast::() = (1i32) as u8; + *base.add(8).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + V49::Int64(e) => { + *base.add(0).cast::() = (2i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V49::Uint64(e) => { + *base.add(0).cast::() = (3i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V49::Float64(e) => { + *base.add(0).cast::() = (4i32) as u8; + *base.add(8).cast::() = _rt::as_f64(e); + } + V49::Text(e) => { + *base.add(0).cast::() = (5i32) as u8; + let vec41 = (e.into_bytes()).into_boxed_slice(); + let ptr41 = vec41.as_ptr().cast::(); + let len41 = vec41.len(); + ::core::mem::forget(vec41); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len41; + *base.add(8).cast::<*mut u8>() = ptr41.cast_mut(); + } + V49::Blob(e) => { + *base.add(0).cast::() = (6i32) as u8; + let vec42 = (e).into_boxed_slice(); + let ptr42 = vec42.as_ptr().cast::(); + let len42 = vec42.len(); + ::core::mem::forget(vec42); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len42; + *base.add(8).cast::<*mut u8>() = ptr42.cast_mut(); + } + V49::Int32(e) => { + *base.add(0).cast::() = (7i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V49::Timestamp(e) => { + *base.add(0).cast::() = (8i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V49::Int8(e) => { + *base.add(0).cast::() = (9i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V49::Int16(e) => { + *base.add(0).cast::() = (10i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V49::Uint8(e) => { + *base.add(0).cast::() = (11i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V49::Uint16(e) => { + *base.add(0).cast::() = (12i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V49::Uint32(e) => { + *base.add(0).cast::() = (13i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V49::Float32(e) => { + *base.add(0).cast::() = (14i32) as u8; + *base.add(8).cast::() = _rt::as_f32(e); + } + V49::Date(e) => { + *base.add(0).cast::() = (15i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V49::Time(e) => { + *base.add(0).cast::() = (16i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V49::Timestamptz(e) => { + *base.add(0).cast::() = (17i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V49::Decimal(e) => { + *base.add(0).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower43, + upper: upper43, + width: width43, + scale: scale43, + } = e; + *base.add(8).cast::() = _rt::as_i64(lower43); + *base.add(16).cast::() = _rt::as_i64(upper43); + *base.add(24).cast::() = (_rt::as_i32(width43)) as u8; + *base.add(25).cast::() = (_rt::as_i32(scale43)) as u8; + } + V49::Interval(e) => { + *base.add(0).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months44, + days: days44, + micros: micros44, + } = e; + *base.add(8).cast::() = _rt::as_i32(months44); + *base.add(12).cast::() = _rt::as_i32(days44); + *base.add(16).cast::() = _rt::as_i64(micros44); + } + V49::Uuid(e) => { + *base.add(0).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi45, + lo: lo45, + } = e; + *base.add(8).cast::() = _rt::as_i64(hi45); + *base.add(16).cast::() = _rt::as_i64(lo45); + } + V49::Complex(e) => { + *base.add(0).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr46, + json: json46, + } = e; + let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); + let ptr47 = vec47.as_ptr().cast::(); + let len47 = vec47.len(); + ::core::mem::forget(vec47); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len47; + *base.add(8).cast::<*mut u8>() = ptr47.cast_mut(); + let vec48 = (json46.into_bytes()).into_boxed_slice(); + let ptr48 = vec48.as_ptr().cast::(); + let len48 = vec48.len(); + ::core::mem::forget(vec48); + *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len48; + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr48.cast_mut(); + } + } } } + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len50; + *base.add(0).cast::<*mut u8>() = result50; } - None => { - *ptr40.add(8).cast::() = (0i32) as u8; - } - }; + } + *ptr40 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len51; + *ptr40 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result51; } Err(e) => { *ptr40.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V55; + use super::super::super::super::duckdb::extension::types::Duckerror as V57; match e { - V55::Invalidargument(e) => { - *ptr40.add(8).cast::() = (0i32) as u8; - let vec50 = (e.into_bytes()).into_boxed_slice(); - let ptr50 = vec50.as_ptr().cast::(); - let len50 = vec50.len(); - ::core::mem::forget(vec50); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len50; - *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr50.cast_mut(); - } - V55::Unsupported(e) => { - *ptr40.add(8).cast::() = (1i32) as u8; - let vec51 = (e.into_bytes()).into_boxed_slice(); - let ptr51 = vec51.as_ptr().cast::(); - let len51 = vec51.len(); - ::core::mem::forget(vec51); - *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len51; + V57::Invalidargument(e) => { *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr51.cast_mut(); - } - V55::Invalidstate(e) => { - *ptr40.add(8).cast::() = (2i32) as u8; + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; let vec52 = (e.into_bytes()).into_boxed_slice(); let ptr52 = vec52.as_ptr().cast::(); let len52 = vec52.len(); ::core::mem::forget(vec52); *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len52; *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>() = ptr52.cast_mut(); } - V55::Io(e) => { - *ptr40.add(8).cast::() = (3i32) as u8; + V57::Unsupported(e) => { + *ptr40 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; let vec53 = (e.into_bytes()).into_boxed_slice(); let ptr53 = vec53.as_ptr().cast::(); let len53 = vec53.len(); ::core::mem::forget(vec53); *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len53; *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>() = ptr53.cast_mut(); } - V55::Internal(e) => { - *ptr40.add(8).cast::() = (4i32) as u8; + V57::Invalidstate(e) => { + *ptr40 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; let vec54 = (e.into_bytes()).into_boxed_slice(); let ptr54 = vec54.as_ptr().cast::(); let len54 = vec54.len(); ::core::mem::forget(vec54); *ptr40 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len54; *ptr40 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>() = ptr54.cast_mut(); } + V57::Io(e) => { + *ptr40 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec55 = (e.into_bytes()).into_boxed_slice(); + let ptr55 = vec55.as_ptr().cast::(); + let len55 = vec55.len(); + ::core::mem::forget(vec55); + *ptr40 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len55; + *ptr40 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr55.cast_mut(); + } + V57::Internal(e) => { + *ptr40 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec56 = (e.into_bytes()).into_boxed_slice(); + let ptr56 = vec56.as_ptr().cast::(); + let len56 = vec56.len(); + ::core::mem::forget(vec56); + *ptr40 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len56; + *ptr40 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr56.cast_mut(); + } } } }; @@ -6353,116 +7947,148 @@ pub mod exports { } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn __post_return_call_pragma(arg0: *mut u8) { + pub unsafe fn __post_return_call_table(arg0: *mut u8) { let l0 = i32::from(*arg0.add(0).cast::()); match l0 { 0 => { - let l1 = i32::from(*arg0.add(8).cast::()); - match l1 { - 0 => {} - _ => { - let l2 = i32::from(*arg0.add(16).cast::()); - match l2 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l3 = *arg0.add(24).cast::<*mut u8>(); - let l4 = *arg0 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l3, l4, 1); - } - 6 => { - let l5 = *arg0.add(24).cast::<*mut u8>(); - let l6 = *arg0 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base7 = l5; - let len7 = l6; - _rt::cabi_dealloc(base7, len7 * 1, 1); - } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l8 = *arg0.add(24).cast::<*mut u8>(); - let l9 = *arg0 - .add(24 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l8, l9, 1); - let l10 = *arg0 - .add(24 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l11 = *arg0 - .add(24 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l10, l11, 1); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base16 = l1; + let len16 = l2; + for i in 0..len16 { + let base = base16 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base15 = l3; + let len15 = l4; + for i in 0..len15 { + let base = base15 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + let l5 = i32::from(*base.add(0).cast::()); + match l5 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l6 = *base.add(8).cast::<*mut u8>(); + let l7 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 6 => { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l8; + let len10 = l9; + _rt::cabi_dealloc(base10, len10 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l11 = *base.add(8).cast::<*mut u8>(); + let l12 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + let l13 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } } } + _rt::cabi_dealloc( + base15, + len15 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); } } + _rt::cabi_dealloc( + base16, + len16 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); } _ => { - let l12 = i32::from(*arg0.add(8).cast::()); - match l12 { + let l17 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l17 { 0 => { - let l13 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l18 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l14 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l19 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l13, l14, 1); + _rt::cabi_dealloc(l18, l19, 1); } 1 => { - let l15 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l20 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l16 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l21 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l15, l16, 1); + _rt::cabi_dealloc(l20, l21, 1); } 2 => { - let l17 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l22 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l18 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l17, l18, 1); + let l23 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l22, l23, 1); } 3 => { - let l19 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l24 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l20 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l25 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l19, l20, 1); + _rt::cabi_dealloc(l24, l25, 1); } _ => { - let l21 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l26 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l22 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l27 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l21, l22, 1); + _rt::cabi_dealloc(l26, l27, 1); } } } @@ -6470,598 +8096,7810 @@ pub mod exports { } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn _export_call_cast_cabi( + pub unsafe fn _export_call_pragma_cabi( arg0: i32, - arg1: i32, - arg2: ::core::mem::MaybeUninit, - arg3: i64, - arg4: ::core::mem::MaybeUninit, - arg5: usize, + arg1: *mut u8, + arg2: usize, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); - use super::super::super::super::duckdb::extension::types::Duckvalue as V4; - let v4 = match arg1 { - 0 => V4::Null, - 1 => { - let e4 = _rt::bool_lift( - arg2.assume_init() as i64 as i32 as u8, - ); - V4::Boolean(e4) - } - 2 => { - let e4 = arg2.assume_init() as i64; - V4::Int64(e4) - } - 3 => { - let e4 = arg2.assume_init() as i64 as u64; - V4::Uint64(e4) - } - 4 => { - let e4 = f64::from_bits(arg2.assume_init() as i64 as u64); - V4::Float64(e4) - } - 5 => { - let e4 = { - let len0 = arg3 as usize; - let bytes0 = _rt::Vec::from_raw_parts( - arg2.as_ptr().cast::<*mut u8>().read().cast(), - len0, - len0, - ); - _rt::string_lift(bytes0) - }; - V4::Text(e4) - } - 6 => { - let e4 = { - let len1 = arg3 as usize; - _rt::Vec::from_raw_parts( - arg2.as_ptr().cast::<*mut u8>().read().cast(), - len1, - len1, - ) - }; - V4::Blob(e4) - } - 7 => { - let e4 = arg2.assume_init() as i64 as i32; - V4::Int32(e4) - } - 8 => { - let e4 = arg2.assume_init() as i64; - V4::Timestamp(e4) - } - 9 => { - let e4 = arg2.assume_init() as i64 as i32 as i8; - V4::Int8(e4) - } - 10 => { - let e4 = arg2.assume_init() as i64 as i32 as i16; - V4::Int16(e4) - } - 11 => { - let e4 = arg2.assume_init() as i64 as i32 as u8; - V4::Uint8(e4) - } - 12 => { - let e4 = arg2.assume_init() as i64 as i32 as u16; - V4::Uint16(e4) - } - 13 => { - let e4 = arg2.assume_init() as i64 as i32 as u32; - V4::Uint32(e4) - } - 14 => { - let e4 = f32::from_bits(arg2.assume_init() as i64 as u32); - V4::Float32(e4) - } - 15 => { - let e4 = arg2.assume_init() as i64 as i32; - V4::Date(e4) - } - 16 => { - let e4 = arg2.assume_init() as i64; - V4::Time(e4) - } - 17 => { - let e4 = arg2.assume_init() as i64; - V4::Timestamptz(e4) - } - 18 => { - let e4 = super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: arg2.assume_init() as i64 as u64, - upper: arg3 as u64, - width: arg4.assume_init() as i64 as i32 as u8, - scale: arg5 as i32 as u8, - }; - V4::Decimal(e4) - } - 19 => { - let e4 = super::super::super::super::duckdb::extension::types::Intervalvalue { - months: arg2.assume_init() as i64 as i32, - days: arg3 as i32, - micros: arg4.assume_init() as i64, - }; - V4::Interval(e4) - } - 20 => { - let e4 = super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: arg2.assume_init() as i64 as u64, - lo: arg3 as u64, - }; - V4::Uuid(e4) - } - n => { - debug_assert_eq!(n, 21, "invalid enum discriminant"); - let e4 = { - let len2 = arg3 as usize; - let bytes2 = _rt::Vec::from_raw_parts( - arg2.as_ptr().cast::<*mut u8>().read().cast(), - len2, - len2, - ); - let len3 = arg5; - let bytes3 = _rt::Vec::from_raw_parts( - arg4.as_ptr().cast::<*mut u8>().read().cast(), - len3, - len3, - ); - super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: _rt::string_lift(bytes2), - json: _rt::string_lift(bytes3), + let base38 = arg1; + let len38 = arg2; + let mut result38 = _rt::Vec::with_capacity(len38); + for i in 0..len38 { + let base = base38 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + let e38 = { + let l0 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V37; + let v37 = match l0 { + 0 => V37::Null, + 1 => { + let e37 = { + let l1 = i32::from(*base.add(8).cast::()); + _rt::bool_lift(l1 as u8) + }; + V37::Boolean(e37) + } + 2 => { + let e37 = { + let l2 = *base.add(8).cast::(); + l2 + }; + V37::Int64(e37) + } + 3 => { + let e37 = { + let l3 = *base.add(8).cast::(); + l3 as u64 + }; + V37::Uint64(e37) + } + 4 => { + let e37 = { + let l4 = *base.add(8).cast::(); + l4 + }; + V37::Float64(e37) + } + 5 => { + let e37 = { + let l5 = *base.add(8).cast::<*mut u8>(); + let l6 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, + ); + _rt::string_lift(bytes7) + }; + V37::Text(e37) + } + 6 => { + let e37 = { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + }; + V37::Blob(e37) + } + 7 => { + let e37 = { + let l11 = *base.add(8).cast::(); + l11 + }; + V37::Int32(e37) + } + 8 => { + let e37 = { + let l12 = *base.add(8).cast::(); + l12 + }; + V37::Timestamp(e37) + } + 9 => { + let e37 = { + let l13 = i32::from(*base.add(8).cast::()); + l13 as i8 + }; + V37::Int8(e37) + } + 10 => { + let e37 = { + let l14 = i32::from(*base.add(8).cast::()); + l14 as i16 + }; + V37::Int16(e37) + } + 11 => { + let e37 = { + let l15 = i32::from(*base.add(8).cast::()); + l15 as u8 + }; + V37::Uint8(e37) + } + 12 => { + let e37 = { + let l16 = i32::from(*base.add(8).cast::()); + l16 as u16 + }; + V37::Uint16(e37) + } + 13 => { + let e37 = { + let l17 = *base.add(8).cast::(); + l17 as u32 + }; + V37::Uint32(e37) + } + 14 => { + let e37 = { + let l18 = *base.add(8).cast::(); + l18 + }; + V37::Float32(e37) + } + 15 => { + let e37 = { + let l19 = *base.add(8).cast::(); + l19 + }; + V37::Date(e37) + } + 16 => { + let e37 = { + let l20 = *base.add(8).cast::(); + l20 + }; + V37::Time(e37) + } + 17 => { + let e37 = { + let l21 = *base.add(8).cast::(); + l21 + }; + V37::Timestamptz(e37) + } + 18 => { + let e37 = { + let l22 = *base.add(8).cast::(); + let l23 = *base.add(16).cast::(); + let l24 = i32::from(*base.add(24).cast::()); + let l25 = i32::from(*base.add(25).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l22 as u64, + upper: l23 as u64, + width: l24 as u8, + scale: l25 as u8, + } + }; + V37::Decimal(e37) + } + 19 => { + let e37 = { + let l26 = *base.add(8).cast::(); + let l27 = *base.add(12).cast::(); + let l28 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l26, + days: l27, + micros: l28, + } + }; + V37::Interval(e37) + } + 20 => { + let e37 = { + let l29 = *base.add(8).cast::(); + let l30 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l29 as u64, + lo: l30 as u64, + } + }; + V37::Uuid(e37) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e37 = { + let l31 = *base.add(8).cast::<*mut u8>(); + let l32 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len33 = l32; + let bytes33 = _rt::Vec::from_raw_parts( + l31.cast(), + len33, + len33, + ); + let l34 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l35 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len36 = l35; + let bytes36 = _rt::Vec::from_raw_parts( + l34.cast(), + len36, + len36, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes33), + json: _rt::string_lift(bytes36), + } + }; + V37::Complex(e37) + } + }; + v37 + }; + result38.push(e38); + } + _rt::cabi_dealloc( + base38, + len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result39 = T::call_pragma(arg0 as u32, result38); + let ptr40 = (&raw mut _RET_AREA.0).cast::(); + match result39 { + Ok(e) => { + *ptr40.add(0).cast::() = (0i32) as u8; + match e { + Some(e) => { + *ptr40.add(8).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckvalue as V49; + match e { + V49::Null => { + *ptr40.add(16).cast::() = (0i32) as u8; + } + V49::Boolean(e) => { + *ptr40.add(16).cast::() = (1i32) as u8; + *ptr40.add(24).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + V49::Int64(e) => { + *ptr40.add(16).cast::() = (2i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i64(e); + } + V49::Uint64(e) => { + *ptr40.add(16).cast::() = (3i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i64(e); + } + V49::Float64(e) => { + *ptr40.add(16).cast::() = (4i32) as u8; + *ptr40.add(24).cast::() = _rt::as_f64(e); + } + V49::Text(e) => { + *ptr40.add(16).cast::() = (5i32) as u8; + let vec41 = (e.into_bytes()).into_boxed_slice(); + let ptr41 = vec41.as_ptr().cast::(); + let len41 = vec41.len(); + ::core::mem::forget(vec41); + *ptr40 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len41; + *ptr40.add(24).cast::<*mut u8>() = ptr41.cast_mut(); + } + V49::Blob(e) => { + *ptr40.add(16).cast::() = (6i32) as u8; + let vec42 = (e).into_boxed_slice(); + let ptr42 = vec42.as_ptr().cast::(); + let len42 = vec42.len(); + ::core::mem::forget(vec42); + *ptr40 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len42; + *ptr40.add(24).cast::<*mut u8>() = ptr42.cast_mut(); + } + V49::Int32(e) => { + *ptr40.add(16).cast::() = (7i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i32(e); + } + V49::Timestamp(e) => { + *ptr40.add(16).cast::() = (8i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i64(e); + } + V49::Int8(e) => { + *ptr40.add(16).cast::() = (9i32) as u8; + *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u8; + } + V49::Int16(e) => { + *ptr40.add(16).cast::() = (10i32) as u8; + *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u16; + } + V49::Uint8(e) => { + *ptr40.add(16).cast::() = (11i32) as u8; + *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u8; + } + V49::Uint16(e) => { + *ptr40.add(16).cast::() = (12i32) as u8; + *ptr40.add(24).cast::() = (_rt::as_i32(e)) as u16; + } + V49::Uint32(e) => { + *ptr40.add(16).cast::() = (13i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i32(e); + } + V49::Float32(e) => { + *ptr40.add(16).cast::() = (14i32) as u8; + *ptr40.add(24).cast::() = _rt::as_f32(e); + } + V49::Date(e) => { + *ptr40.add(16).cast::() = (15i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i32(e); + } + V49::Time(e) => { + *ptr40.add(16).cast::() = (16i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i64(e); + } + V49::Timestamptz(e) => { + *ptr40.add(16).cast::() = (17i32) as u8; + *ptr40.add(24).cast::() = _rt::as_i64(e); + } + V49::Decimal(e) => { + *ptr40.add(16).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower43, + upper: upper43, + width: width43, + scale: scale43, + } = e; + *ptr40.add(24).cast::() = _rt::as_i64(lower43); + *ptr40.add(32).cast::() = _rt::as_i64(upper43); + *ptr40.add(40).cast::() = (_rt::as_i32(width43)) as u8; + *ptr40.add(41).cast::() = (_rt::as_i32(scale43)) as u8; + } + V49::Interval(e) => { + *ptr40.add(16).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months44, + days: days44, + micros: micros44, + } = e; + *ptr40.add(24).cast::() = _rt::as_i32(months44); + *ptr40.add(28).cast::() = _rt::as_i32(days44); + *ptr40.add(32).cast::() = _rt::as_i64(micros44); + } + V49::Uuid(e) => { + *ptr40.add(16).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi45, + lo: lo45, + } = e; + *ptr40.add(24).cast::() = _rt::as_i64(hi45); + *ptr40.add(32).cast::() = _rt::as_i64(lo45); + } + V49::Complex(e) => { + *ptr40.add(16).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr46, + json: json46, + } = e; + let vec47 = (type_expr46.into_bytes()).into_boxed_slice(); + let ptr47 = vec47.as_ptr().cast::(); + let len47 = vec47.len(); + ::core::mem::forget(vec47); + *ptr40 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len47; + *ptr40.add(24).cast::<*mut u8>() = ptr47.cast_mut(); + let vec48 = (json46.into_bytes()).into_boxed_slice(); + let ptr48 = vec48.as_ptr().cast::(); + let len48 = vec48.len(); + ::core::mem::forget(vec48); + *ptr40 + .add(24 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len48; + *ptr40 + .add(24 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr48.cast_mut(); + } + } + } + None => { + *ptr40.add(8).cast::() = (0i32) as u8; + } + }; + } + Err(e) => { + *ptr40.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V55; + match e { + V55::Invalidargument(e) => { + *ptr40.add(8).cast::() = (0i32) as u8; + let vec50 = (e.into_bytes()).into_boxed_slice(); + let ptr50 = vec50.as_ptr().cast::(); + let len50 = vec50.len(); + ::core::mem::forget(vec50); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len50; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr50.cast_mut(); + } + V55::Unsupported(e) => { + *ptr40.add(8).cast::() = (1i32) as u8; + let vec51 = (e.into_bytes()).into_boxed_slice(); + let ptr51 = vec51.as_ptr().cast::(); + let len51 = vec51.len(); + ::core::mem::forget(vec51); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len51; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr51.cast_mut(); + } + V55::Invalidstate(e) => { + *ptr40.add(8).cast::() = (2i32) as u8; + let vec52 = (e.into_bytes()).into_boxed_slice(); + let ptr52 = vec52.as_ptr().cast::(); + let len52 = vec52.len(); + ::core::mem::forget(vec52); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len52; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr52.cast_mut(); + } + V55::Io(e) => { + *ptr40.add(8).cast::() = (3i32) as u8; + let vec53 = (e.into_bytes()).into_boxed_slice(); + let ptr53 = vec53.as_ptr().cast::(); + let len53 = vec53.len(); + ::core::mem::forget(vec53); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len53; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr53.cast_mut(); + } + V55::Internal(e) => { + *ptr40.add(8).cast::() = (4i32) as u8; + let vec54 = (e.into_bytes()).into_boxed_slice(); + let ptr54 = vec54.as_ptr().cast::(); + let len54 = vec54.len(); + ::core::mem::forget(vec54); + *ptr40 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len54; + *ptr40 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr54.cast_mut(); + } + } + } + }; + ptr40 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_call_pragma(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = i32::from(*arg0.add(8).cast::()); + match l1 { + 0 => {} + _ => { + let l2 = i32::from(*arg0.add(16).cast::()); + match l2 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l3 = *arg0.add(24).cast::<*mut u8>(); + let l4 = *arg0 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l3, l4, 1); + } + 6 => { + let l5 = *arg0.add(24).cast::<*mut u8>(); + let l6 = *arg0 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base7 = l5; + let len7 = l6; + _rt::cabi_dealloc(base7, len7 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l8 = *arg0.add(24).cast::<*mut u8>(); + let l9 = *arg0 + .add(24 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + let l10 = *arg0 + .add(24 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(24 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + _ => { + let l12 = i32::from(*arg0.add(8).cast::()); + match l12 { + 0 => { + let l13 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + 1 => { + let l15 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l16 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l15, l16, 1); + } + 2 => { + let l17 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l17, l18, 1); + } + 3 => { + let l19 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l20 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l19, l20, 1); + } + _ => { + let l21 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l22 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l21, l22, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_call_cast_cabi( + arg0: i32, + arg1: i32, + arg2: ::core::mem::MaybeUninit, + arg3: i64, + arg4: ::core::mem::MaybeUninit, + arg5: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + use super::super::super::super::duckdb::extension::types::Duckvalue as V4; + let v4 = match arg1 { + 0 => V4::Null, + 1 => { + let e4 = _rt::bool_lift( + arg2.assume_init() as i64 as i32 as u8, + ); + V4::Boolean(e4) + } + 2 => { + let e4 = arg2.assume_init() as i64; + V4::Int64(e4) + } + 3 => { + let e4 = arg2.assume_init() as i64 as u64; + V4::Uint64(e4) + } + 4 => { + let e4 = f64::from_bits(arg2.assume_init() as i64 as u64); + V4::Float64(e4) + } + 5 => { + let e4 = { + let len0 = arg3 as usize; + let bytes0 = _rt::Vec::from_raw_parts( + arg2.as_ptr().cast::<*mut u8>().read().cast(), + len0, + len0, + ); + _rt::string_lift(bytes0) + }; + V4::Text(e4) + } + 6 => { + let e4 = { + let len1 = arg3 as usize; + _rt::Vec::from_raw_parts( + arg2.as_ptr().cast::<*mut u8>().read().cast(), + len1, + len1, + ) + }; + V4::Blob(e4) + } + 7 => { + let e4 = arg2.assume_init() as i64 as i32; + V4::Int32(e4) + } + 8 => { + let e4 = arg2.assume_init() as i64; + V4::Timestamp(e4) + } + 9 => { + let e4 = arg2.assume_init() as i64 as i32 as i8; + V4::Int8(e4) + } + 10 => { + let e4 = arg2.assume_init() as i64 as i32 as i16; + V4::Int16(e4) + } + 11 => { + let e4 = arg2.assume_init() as i64 as i32 as u8; + V4::Uint8(e4) + } + 12 => { + let e4 = arg2.assume_init() as i64 as i32 as u16; + V4::Uint16(e4) + } + 13 => { + let e4 = arg2.assume_init() as i64 as i32 as u32; + V4::Uint32(e4) + } + 14 => { + let e4 = f32::from_bits(arg2.assume_init() as i64 as u32); + V4::Float32(e4) + } + 15 => { + let e4 = arg2.assume_init() as i64 as i32; + V4::Date(e4) + } + 16 => { + let e4 = arg2.assume_init() as i64; + V4::Time(e4) + } + 17 => { + let e4 = arg2.assume_init() as i64; + V4::Timestamptz(e4) + } + 18 => { + let e4 = super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: arg2.assume_init() as i64 as u64, + upper: arg3 as u64, + width: arg4.assume_init() as i64 as i32 as u8, + scale: arg5 as i32 as u8, + }; + V4::Decimal(e4) + } + 19 => { + let e4 = super::super::super::super::duckdb::extension::types::Intervalvalue { + months: arg2.assume_init() as i64 as i32, + days: arg3 as i32, + micros: arg4.assume_init() as i64, + }; + V4::Interval(e4) + } + 20 => { + let e4 = super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: arg2.assume_init() as i64 as u64, + lo: arg3 as u64, + }; + V4::Uuid(e4) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e4 = { + let len2 = arg3 as usize; + let bytes2 = _rt::Vec::from_raw_parts( + arg2.as_ptr().cast::<*mut u8>().read().cast(), + len2, + len2, + ); + let len3 = arg5; + let bytes3 = _rt::Vec::from_raw_parts( + arg4.as_ptr().cast::<*mut u8>().read().cast(), + len3, + len3, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes2), + json: _rt::string_lift(bytes3), + } + }; + V4::Complex(e4) + } + }; + let result5 = T::call_cast(arg0 as u32, v4); + let ptr6 = (&raw mut _RET_AREA.0).cast::(); + match result5 { + Ok(e) => { + *ptr6.add(0).cast::() = (0i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckvalue as V15; + match e { + V15::Null => { + *ptr6.add(8).cast::() = (0i32) as u8; + } + V15::Boolean(e) => { + *ptr6.add(8).cast::() = (1i32) as u8; + *ptr6.add(16).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + V15::Int64(e) => { + *ptr6.add(8).cast::() = (2i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i64(e); + } + V15::Uint64(e) => { + *ptr6.add(8).cast::() = (3i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i64(e); + } + V15::Float64(e) => { + *ptr6.add(8).cast::() = (4i32) as u8; + *ptr6.add(16).cast::() = _rt::as_f64(e); + } + V15::Text(e) => { + *ptr6.add(8).cast::() = (5i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr6 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr6.add(16).cast::<*mut u8>() = ptr7.cast_mut(); + } + V15::Blob(e) => { + *ptr6.add(8).cast::() = (6i32) as u8; + let vec8 = (e).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr6 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr6.add(16).cast::<*mut u8>() = ptr8.cast_mut(); + } + V15::Int32(e) => { + *ptr6.add(8).cast::() = (7i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i32(e); + } + V15::Timestamp(e) => { + *ptr6.add(8).cast::() = (8i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i64(e); + } + V15::Int8(e) => { + *ptr6.add(8).cast::() = (9i32) as u8; + *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u8; + } + V15::Int16(e) => { + *ptr6.add(8).cast::() = (10i32) as u8; + *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u16; + } + V15::Uint8(e) => { + *ptr6.add(8).cast::() = (11i32) as u8; + *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u8; + } + V15::Uint16(e) => { + *ptr6.add(8).cast::() = (12i32) as u8; + *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u16; + } + V15::Uint32(e) => { + *ptr6.add(8).cast::() = (13i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i32(e); + } + V15::Float32(e) => { + *ptr6.add(8).cast::() = (14i32) as u8; + *ptr6.add(16).cast::() = _rt::as_f32(e); + } + V15::Date(e) => { + *ptr6.add(8).cast::() = (15i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i32(e); + } + V15::Time(e) => { + *ptr6.add(8).cast::() = (16i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i64(e); + } + V15::Timestamptz(e) => { + *ptr6.add(8).cast::() = (17i32) as u8; + *ptr6.add(16).cast::() = _rt::as_i64(e); + } + V15::Decimal(e) => { + *ptr6.add(8).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower9, + upper: upper9, + width: width9, + scale: scale9, + } = e; + *ptr6.add(16).cast::() = _rt::as_i64(lower9); + *ptr6.add(24).cast::() = _rt::as_i64(upper9); + *ptr6.add(32).cast::() = (_rt::as_i32(width9)) as u8; + *ptr6.add(33).cast::() = (_rt::as_i32(scale9)) as u8; + } + V15::Interval(e) => { + *ptr6.add(8).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months10, + days: days10, + micros: micros10, + } = e; + *ptr6.add(16).cast::() = _rt::as_i32(months10); + *ptr6.add(20).cast::() = _rt::as_i32(days10); + *ptr6.add(24).cast::() = _rt::as_i64(micros10); + } + V15::Uuid(e) => { + *ptr6.add(8).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi11, + lo: lo11, + } = e; + *ptr6.add(16).cast::() = _rt::as_i64(hi11); + *ptr6.add(24).cast::() = _rt::as_i64(lo11); + } + V15::Complex(e) => { + *ptr6.add(8).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr12, + json: json12, + } = e; + let vec13 = (type_expr12.into_bytes()).into_boxed_slice(); + let ptr13 = vec13.as_ptr().cast::(); + let len13 = vec13.len(); + ::core::mem::forget(vec13); + *ptr6 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len13; + *ptr6.add(16).cast::<*mut u8>() = ptr13.cast_mut(); + let vec14 = (json12.into_bytes()).into_boxed_slice(); + let ptr14 = vec14.as_ptr().cast::(); + let len14 = vec14.len(); + ::core::mem::forget(vec14); + *ptr6 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len14; + *ptr6 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr14.cast_mut(); + } + } + } + Err(e) => { + *ptr6.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V21; + match e { + V21::Invalidargument(e) => { + *ptr6.add(8).cast::() = (0i32) as u8; + let vec16 = (e.into_bytes()).into_boxed_slice(); + let ptr16 = vec16.as_ptr().cast::(); + let len16 = vec16.len(); + ::core::mem::forget(vec16); + *ptr6 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len16; + *ptr6 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr16.cast_mut(); + } + V21::Unsupported(e) => { + *ptr6.add(8).cast::() = (1i32) as u8; + let vec17 = (e.into_bytes()).into_boxed_slice(); + let ptr17 = vec17.as_ptr().cast::(); + let len17 = vec17.len(); + ::core::mem::forget(vec17); + *ptr6 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len17; + *ptr6 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr17.cast_mut(); + } + V21::Invalidstate(e) => { + *ptr6.add(8).cast::() = (2i32) as u8; + let vec18 = (e.into_bytes()).into_boxed_slice(); + let ptr18 = vec18.as_ptr().cast::(); + let len18 = vec18.len(); + ::core::mem::forget(vec18); + *ptr6 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len18; + *ptr6 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr18.cast_mut(); + } + V21::Io(e) => { + *ptr6.add(8).cast::() = (3i32) as u8; + let vec19 = (e.into_bytes()).into_boxed_slice(); + let ptr19 = vec19.as_ptr().cast::(); + let len19 = vec19.len(); + ::core::mem::forget(vec19); + *ptr6 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len19; + *ptr6 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr19.cast_mut(); + } + V21::Internal(e) => { + *ptr6.add(8).cast::() = (4i32) as u8; + let vec20 = (e.into_bytes()).into_boxed_slice(); + let ptr20 = vec20.as_ptr().cast::(); + let len20 = vec20.len(); + ::core::mem::forget(vec20); + *ptr6 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len20; + *ptr6 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr20.cast_mut(); + } + } + } + }; + ptr6 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_call_cast(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = i32::from(*arg0.add(8).cast::()); + match l1 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l2 = *arg0.add(16).cast::<*mut u8>(); + let l3 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 6 => { + let l4 = *arg0.add(16).cast::<*mut u8>(); + let l5 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base6 = l4; + let len6 = l5; + _rt::cabi_dealloc(base6, len6 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l7 = *arg0.add(16).cast::<*mut u8>(); + let l8 = *arg0 + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + let l9 = *arg0 + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + } + } + _ => { + let l11 = i32::from(*arg0.add(8).cast::()); + match l11 { + 0 => { + let l12 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l13 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l12, l13, 1); + } + 1 => { + let l14 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l14, l15, 1); + } + 2 => { + let l16 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l17 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l16, l17, 1); + } + 3 => { + let l18 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); + } + _ => { + let l20 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l20, l21, 1); + } + } + } + } + } + pub trait Guest { + /// HOT PATH: one columnar call per DataChunk. `args` is one colvec per + /// argument column (all with the same `rows`); the result is a single colvec + /// of the function's return type, same `rows`. Row i of every input column + /// maps to row i of the output, validity preserved. Fixed-width columns cross + /// as bulk memcpy. Semantically identical to a per-row call-scalar loop. + fn call_scalar_batch_col( + handle: u32, + args: _rt::Vec, + ctx: Invokeinfo, + ) -> Result; + /// Columnar aggregate fold: the buffered group as columns (one colvec per + /// argument). The guest folds in-vector (state never crosses the boundary, as + /// in major-3) and returns the single finalized value. + fn call_aggregate_col( + handle: u32, + args: _rt::Vec, + ) -> Result; + /// Columnar cast: one input column -> one output column. + fn call_cast_col( + handle: u32, + arg: Colvec, + ) -> Result; + /// --- cold singleton paths kept row-major (not on the hot path) --- + fn call_scalar( + handle: u32, + args: _rt::Vec, + ctx: Invokeinfo, + ) -> Result; + fn call_table( + handle: u32, + args: _rt::Vec, + ) -> Result; + fn call_pragma( + handle: u32, + args: _rt::Vec, + ) -> Result, Duckerror>; + fn call_cast( + handle: u32, + value: Duckvalue, + ) -> Result; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_callback_dispatch_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-scalar-batch-col")] + unsafe extern "C" fn export_call_scalar_batch_col(arg0 : i32, + arg1 : * mut u8, arg2 : usize, arg3 : i32, arg4 : i64, arg5 : + i32,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_scalar_batch_col_cabi::<$ty > (arg0, arg1, arg2, + arg3, arg4, arg5) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-scalar-batch-col")] + unsafe extern "C" fn _post_return_call_scalar_batch_col(arg0 : * + mut u8,) { unsafe { $($path_to_types)*:: + __post_return_call_scalar_batch_col::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-aggregate-col")] + unsafe extern "C" fn export_call_aggregate_col(arg0 : i32, arg1 : + * mut u8, arg2 : usize,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_call_aggregate_col_cabi::<$ty > + (arg0, arg1, arg2) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-aggregate-col")] + unsafe extern "C" fn _post_return_call_aggregate_col(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_call_aggregate_col::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-cast-col")] unsafe + extern "C" fn export_call_cast_col(arg0 : i32, arg1 : i32, arg2 : + * mut u8, arg3 : usize, arg4 : * mut u8, arg5 : usize, arg6 : + i32,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_cast_col_cabi::<$ty > (arg0, arg1, arg2, arg3, arg4, + arg5, arg6) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-cast-col")] + unsafe extern "C" fn _post_return_call_cast_col(arg0 : * mut u8,) + { unsafe { $($path_to_types)*:: __post_return_call_cast_col::<$ty + > (arg0) } } #[unsafe (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-scalar")] unsafe + extern "C" fn export_call_scalar(arg0 : i32, arg1 : * mut u8, + arg2 : usize, arg3 : i32, arg4 : i64, arg5 : i32,) -> * mut u8 { + unsafe { $($path_to_types)*:: _export_call_scalar_cabi::<$ty > + (arg0, arg1, arg2, arg3, arg4, arg5) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-scalar")] + unsafe extern "C" fn _post_return_call_scalar(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_call_scalar::<$ty > + (arg0) } } #[unsafe (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-table")] unsafe + extern "C" fn export_call_table(arg0 : i32, arg1 : * mut u8, arg2 + : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_table_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-table")] + unsafe extern "C" fn _post_return_call_table(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_call_table::<$ty > + (arg0) } } #[unsafe (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-pragma")] unsafe + extern "C" fn export_call_pragma(arg0 : i32, arg1 : * mut u8, + arg2 : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_pragma_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-pragma")] + unsafe extern "C" fn _post_return_call_pragma(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_call_pragma::<$ty > + (arg0) } } #[unsafe (export_name = + "duckdb:extension/callback-dispatch@4.0.0#call-cast")] unsafe + extern "C" fn export_call_cast(arg0 : i32, arg1 : i32, arg2 : + ::core::mem::MaybeUninit::< u64 >, arg3 : i64, arg4 : + ::core::mem::MaybeUninit::< u64 >, arg5 : usize,) -> * mut u8 { + unsafe { $($path_to_types)*:: _export_call_cast_cabi::<$ty > + (arg0, arg1, arg2, arg3, arg4, arg5) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/callback-dispatch@4.0.0#call-cast")] + unsafe extern "C" fn _post_return_call_cast(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_call_cast::<$ty > + (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_callback_dispatch_4_0_0_cabi; + #[repr(align(8))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 40 + 2 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 40 + + 2 * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core storage callbacks. The DuckDB-compiled-to-wasm core IMPORTS this + /// interface; the native host PROVIDES it and routes each call to the storage + /// component (e.g. sqlitewasm) that registered an ATTACH backend, driving that + /// component's `storage-dispatch` export. This mirrors how the core imports + /// `callback-dispatch` (call-table etc.) for function dispatch. + /// + /// M2a needs only attach + table/column enumeration; scan-open/next/close are + /// declared for M2b but the core may not call them yet. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod storage_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type Duckerror = super::super::super::super::duckdb::extension::types::Duckerror; + pub type Columndef = super::super::super::super::duckdb::extension::types::Columndef; + pub type Duckvalue = super::super::super::super::duckdb::extension::types::Duckvalue; + pub type Resultset = _rt::Vec<_rt::Vec>; + /// Comparison pushed into a scan as an AND-ed predicate. Mirrors the backing + /// component's storage.compare-op. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum CompareOp { + Eq, + Ne, + Lt, + Le, + Gt, + Ge, + IsNull, + IsNotNull, + } + impl ::core::fmt::Debug for CompareOp { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + CompareOp::Eq => f.debug_tuple("CompareOp::Eq").finish(), + CompareOp::Ne => f.debug_tuple("CompareOp::Ne").finish(), + CompareOp::Lt => f.debug_tuple("CompareOp::Lt").finish(), + CompareOp::Le => f.debug_tuple("CompareOp::Le").finish(), + CompareOp::Gt => f.debug_tuple("CompareOp::Gt").finish(), + CompareOp::Ge => f.debug_tuple("CompareOp::Ge").finish(), + CompareOp::IsNull => { + f.debug_tuple("CompareOp::IsNull").finish() + } + CompareOp::IsNotNull => { + f.debug_tuple("CompareOp::IsNotNull").finish() + } + } + } + } + impl CompareOp { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> CompareOp { + if !cfg!(debug_assertions) { + return ::core::mem::transmute(val); + } + match val { + 0 => CompareOp::Eq, + 1 => CompareOp::Ne, + 2 => CompareOp::Lt, + 3 => CompareOp::Le, + 4 => CompareOp::Gt, + 5 => CompareOp::Ge, + 6 => CompareOp::IsNull, + 7 => CompareOp::IsNotNull, + _ => panic!("invalid enum discriminant"), + } + } + } + /// One predicate. `column` indexes the table's FULL column list (not the + /// projection). Pushdown is best-effort: the engine re-applies every filter. + #[derive(Clone)] + pub struct ScanFilter { + pub column: u32, + pub op: CompareOp, + pub value: Duckvalue, + } + impl ::core::fmt::Debug for ScanFilter { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("ScanFilter") + .field("column", &self.column) + .field("op", &self.op) + .field("value", &self.value) + .finish() + } + } + /// What the engine asks a scan to produce. Mirrors the component's + /// storage.scan-request. + #[derive(Clone)] + pub struct ScanRequest { + pub table: _rt::String, + pub projection: _rt::Vec, + /// column indices to emit, in order; empty = all + pub filters: _rt::Vec, + pub limit: Option, + } + impl ::core::fmt::Debug for ScanRequest { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("ScanRequest") + .field("table", &self.table) + .field("projection", &self.projection) + .field("filters", &self.filters) + .field("limit", &self.limit) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_list_types_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::storage_list_types(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec3 = result0; + let len3 = vec3.len(); + let layout3 = _rt::alloc::Layout::from_size_align_unchecked( + vec3.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result3 = if layout3.size() != 0 { + let ptr = _rt::alloc::alloc(layout3).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout3); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec3.into_iter().enumerate() { + let base = result3 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len3; + *ptr1.add(0).cast::<*mut u8>() = result3; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_list_types(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l0; + let len4 = l1; + for i in 0..len4 { + let base = base4 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + _rt::cabi_dealloc( + base4, + len4 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_attach_cabi( + arg0: *mut u8, + arg1: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg1; + let bytes0 = _rt::Vec::from_raw_parts(arg0.cast(), len0, len0); + let result1 = T::storage_attach(_rt::string_lift(bytes0)); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(e); + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V8; + match e { + V8::Invalidargument(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + V8::Unsupported(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V8::Invalidstate(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V8::Io(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V8::Internal(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + } + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_attach(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_list_tables_cabi( + arg0: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::storage_list_tables(arg0 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + let vec3 = e; + let len3 = vec3.len(); + let layout3 = _rt::alloc::Layout::from_size_align_unchecked( + vec3.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result3 = if layout3.size() != 0 { + let ptr = _rt::alloc::alloc(layout3).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout3); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec3.into_iter().enumerate() { + let base = result3 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + } + } + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result3; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V9; + match e { + V9::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V9::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V9::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V9::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V9::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_list_tables( + arg0: *mut u8, + ) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base5 = l1; + let len5 = l2; + for i in 0..len5 { + let base = base5 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l3, l4, 1); + } + } + _rt::cabi_dealloc( + base5, + len5 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l6 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l6 { + 0 => { + let l7 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + } + 1 => { + let l9 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + 2 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + } + 3 => { + let l13 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + _ => { + let l15 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l16 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l15, l16, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_table_columns_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + let result1 = T::storage_table_columns( + arg0 as u32, + _rt::string_lift(bytes0), + ); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + let vec7 = e; + let len7 = vec7.len(); + let layout7 = _rt::alloc::Layout::from_size_align_unchecked( + vec7.len() * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result7 = if layout7.size() != 0 { + let ptr = _rt::alloc::alloc(layout7).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout7); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec7.into_iter().enumerate() { + let base = result7 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let super::super::super::super::duckdb::extension::types::Columndef { + name: name3, + logical: logical3, + } = e; + let vec4 = (name3.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *base.add(0).cast::<*mut u8>() = ptr4.cast_mut(); + use super::super::super::super::duckdb::extension::types::Logicaltype as V6; + match logical3 { + V6::Boolean => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + V6::Int64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + } + V6::Uint64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + } + V6::Float64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + } + V6::Text => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + } + V6::Blob => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + } + V6::Int32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + } + V6::Timestamp => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + } + V6::Int8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + } + V6::Int16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + } + V6::Uint8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + } + V6::Uint16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + } + V6::Uint32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + } + V6::Float32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + } + V6::Date => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + } + V6::Time => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + } + V6::Timestamptz => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + } + V6::Decimal => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + } + V6::Interval => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + } + V6::Uuid => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + } + V6::Complex(e) => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + } + } + } + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result7; + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V13; + match e { + V13::Invalidargument(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + V13::Unsupported(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec9 = (e.into_bytes()).into_boxed_slice(); + let ptr9 = vec9.as_ptr().cast::(); + let len9 = vec9.len(); + ::core::mem::forget(vec9); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len9; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr9.cast_mut(); + } + V13::Invalidstate(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec10 = (e.into_bytes()).into_boxed_slice(); + let ptr10 = vec10.as_ptr().cast::(); + let len10 = vec10.len(); + ::core::mem::forget(vec10); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len10; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr10.cast_mut(); + } + V13::Io(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec11 = (e.into_bytes()).into_boxed_slice(); + let ptr11 = vec11.as_ptr().cast::(); + let len11 = vec11.len(); + ::core::mem::forget(vec11); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len11; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr11.cast_mut(); + } + V13::Internal(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec12 = (e.into_bytes()).into_boxed_slice(); + let ptr12 = vec12.as_ptr().cast::(); + let len12 = vec12.len(); + ::core::mem::forget(vec12); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len12; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr12.cast_mut(); + } + } + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_table_columns( + arg0: *mut u8, + ) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base8 = l1; + let len8 = l2; + for i in 0..len8 { + let base = base8 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l3, l4, 1); + let l5 = i32::from( + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + match l5 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => {} + 6 => {} + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + _ => { + let l6 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + } + } + } + _rt::cabi_dealloc( + base8, + len8 * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l9 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l9 { + 0 => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + 1 => { + let l12 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l13 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l12, l13, 1); + } + 2 => { + let l14 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l14, l15, 1); + } + 3 => { + let l16 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l17 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l16, l17, 1); + } + _ => { + let l18 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_scan_open_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + arg3: *mut u8, + arg4: usize, + arg5: *mut u8, + arg6: usize, + arg7: i32, + arg8: i64, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + let len1 = arg4; + let base42 = arg5; + let len42 = arg6; + let mut result42 = _rt::Vec::with_capacity(len42); + for i in 0..len42 { + let base = base42 + .add(i * (32 + 2 * ::core::mem::size_of::<*const u8>())); + let e42 = { + let l2 = *base.add(0).cast::(); + let l3 = i32::from(*base.add(4).cast::()); + let l4 = i32::from(*base.add(8).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V41; + let v41 = match l4 { + 0 => V41::Null, + 1 => { + let e41 = { + let l5 = i32::from(*base.add(16).cast::()); + _rt::bool_lift(l5 as u8) + }; + V41::Boolean(e41) + } + 2 => { + let e41 = { + let l6 = *base.add(16).cast::(); + l6 + }; + V41::Int64(e41) + } + 3 => { + let e41 = { + let l7 = *base.add(16).cast::(); + l7 as u64 + }; + V41::Uint64(e41) + } + 4 => { + let e41 = { + let l8 = *base.add(16).cast::(); + l8 + }; + V41::Float64(e41) + } + 5 => { + let e41 = { + let l9 = *base.add(16).cast::<*mut u8>(); + let l10 = *base + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len11 = l10; + let bytes11 = _rt::Vec::from_raw_parts( + l9.cast(), + len11, + len11, + ); + _rt::string_lift(bytes11) + }; + V41::Text(e41) + } + 6 => { + let e41 = { + let l12 = *base.add(16).cast::<*mut u8>(); + let l13 = *base + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len14 = l13; + _rt::Vec::from_raw_parts(l12.cast(), len14, len14) + }; + V41::Blob(e41) + } + 7 => { + let e41 = { + let l15 = *base.add(16).cast::(); + l15 + }; + V41::Int32(e41) + } + 8 => { + let e41 = { + let l16 = *base.add(16).cast::(); + l16 + }; + V41::Timestamp(e41) + } + 9 => { + let e41 = { + let l17 = i32::from(*base.add(16).cast::()); + l17 as i8 + }; + V41::Int8(e41) + } + 10 => { + let e41 = { + let l18 = i32::from(*base.add(16).cast::()); + l18 as i16 + }; + V41::Int16(e41) + } + 11 => { + let e41 = { + let l19 = i32::from(*base.add(16).cast::()); + l19 as u8 + }; + V41::Uint8(e41) + } + 12 => { + let e41 = { + let l20 = i32::from(*base.add(16).cast::()); + l20 as u16 + }; + V41::Uint16(e41) + } + 13 => { + let e41 = { + let l21 = *base.add(16).cast::(); + l21 as u32 + }; + V41::Uint32(e41) + } + 14 => { + let e41 = { + let l22 = *base.add(16).cast::(); + l22 + }; + V41::Float32(e41) + } + 15 => { + let e41 = { + let l23 = *base.add(16).cast::(); + l23 + }; + V41::Date(e41) + } + 16 => { + let e41 = { + let l24 = *base.add(16).cast::(); + l24 + }; + V41::Time(e41) + } + 17 => { + let e41 = { + let l25 = *base.add(16).cast::(); + l25 + }; + V41::Timestamptz(e41) + } + 18 => { + let e41 = { + let l26 = *base.add(16).cast::(); + let l27 = *base.add(24).cast::(); + let l28 = i32::from(*base.add(32).cast::()); + let l29 = i32::from(*base.add(33).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l26 as u64, + upper: l27 as u64, + width: l28 as u8, + scale: l29 as u8, + } + }; + V41::Decimal(e41) + } + 19 => { + let e41 = { + let l30 = *base.add(16).cast::(); + let l31 = *base.add(20).cast::(); + let l32 = *base.add(24).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l30, + days: l31, + micros: l32, + } + }; + V41::Interval(e41) + } + 20 => { + let e41 = { + let l33 = *base.add(16).cast::(); + let l34 = *base.add(24).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l33 as u64, + lo: l34 as u64, + } + }; + V41::Uuid(e41) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e41 = { + let l35 = *base.add(16).cast::<*mut u8>(); + let l36 = *base + .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len37 = l36; + let bytes37 = _rt::Vec::from_raw_parts( + l35.cast(), + len37, + len37, + ); + let l38 = *base + .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l39 = *base + .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len40 = l39; + let bytes40 = _rt::Vec::from_raw_parts( + l38.cast(), + len40, + len40, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes37), + json: _rt::string_lift(bytes40), + } + }; + V41::Complex(e41) + } + }; + ScanFilter { + column: l2 as u32, + op: CompareOp::_lift(l3 as u8), + value: v41, + } + }; + result42.push(e42); + } + _rt::cabi_dealloc( + base42, + len42 * (32 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result43 = T::storage_scan_open( + arg0 as u32, + ScanRequest { + table: _rt::string_lift(bytes0), + projection: _rt::Vec::from_raw_parts( + arg3.cast(), + len1, + len1, + ), + filters: result42, + limit: match arg7 { + 0 => None, + 1 => { + let e = arg8 as u64; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + }, + ); + let ptr44 = (&raw mut _RET_AREA.0).cast::(); + match result43 { + Ok(e) => { + *ptr44.add(0).cast::() = (0i32) as u8; + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(e); + } + Err(e) => { + *ptr44.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V50; + match e { + V50::Invalidargument(e) => { + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec45 = (e.into_bytes()).into_boxed_slice(); + let ptr45 = vec45.as_ptr().cast::(); + let len45 = vec45.len(); + ::core::mem::forget(vec45); + *ptr44 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len45; + *ptr44 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr45.cast_mut(); + } + V50::Unsupported(e) => { + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec46 = (e.into_bytes()).into_boxed_slice(); + let ptr46 = vec46.as_ptr().cast::(); + let len46 = vec46.len(); + ::core::mem::forget(vec46); + *ptr44 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len46; + *ptr44 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr46.cast_mut(); + } + V50::Invalidstate(e) => { + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec47 = (e.into_bytes()).into_boxed_slice(); + let ptr47 = vec47.as_ptr().cast::(); + let len47 = vec47.len(); + ::core::mem::forget(vec47); + *ptr44 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len47; + *ptr44 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr47.cast_mut(); + } + V50::Io(e) => { + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec48 = (e.into_bytes()).into_boxed_slice(); + let ptr48 = vec48.as_ptr().cast::(); + let len48 = vec48.len(); + ::core::mem::forget(vec48); + *ptr44 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len48; + *ptr44 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr48.cast_mut(); + } + V50::Internal(e) => { + *ptr44 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec49 = (e.into_bytes()).into_boxed_slice(); + let ptr49 = vec49.as_ptr().cast::(); + let len49 = vec49.len(); + ::core::mem::forget(vec49); + *ptr44 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len49; + *ptr44 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr49.cast_mut(); + } + } + } + }; + ptr44 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_scan_open(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_scan_next_cabi( + arg0: i32, + arg1: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::storage_scan_next(arg0 as u32, arg1 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + let vec12 = e; + let len12 = vec12.len(); + let layout12 = _rt::alloc::Layout::from_size_align_unchecked( + vec12.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result12 = if layout12.size() != 0 { + let ptr = _rt::alloc::alloc(layout12).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout12); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec12.into_iter().enumerate() { + let base = result12 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec11 = e; + let len11 = vec11.len(); + let layout11 = _rt::alloc::Layout::from_size_align_unchecked( + vec11.len() + * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result11 = if layout11.size() != 0 { + let ptr = _rt::alloc::alloc(layout11).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout11); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec11.into_iter().enumerate() { + let base = result11 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + use super::super::super::super::duckdb::extension::types::Duckvalue as V10; + match e { + V10::Null => { + *base.add(0).cast::() = (0i32) as u8; + } + V10::Boolean(e) => { + *base.add(0).cast::() = (1i32) as u8; + *base.add(8).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + V10::Int64(e) => { + *base.add(0).cast::() = (2i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Uint64(e) => { + *base.add(0).cast::() = (3i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Float64(e) => { + *base.add(0).cast::() = (4i32) as u8; + *base.add(8).cast::() = _rt::as_f64(e); + } + V10::Text(e) => { + *base.add(0).cast::() = (5i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base.add(8).cast::<*mut u8>() = ptr2.cast_mut(); + } + V10::Blob(e) => { + *base.add(0).cast::() = (6i32) as u8; + let vec3 = (e).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(8).cast::<*mut u8>() = ptr3.cast_mut(); + } + V10::Int32(e) => { + *base.add(0).cast::() = (7i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Timestamp(e) => { + *base.add(0).cast::() = (8i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Int8(e) => { + *base.add(0).cast::() = (9i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V10::Int16(e) => { + *base.add(0).cast::() = (10i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V10::Uint8(e) => { + *base.add(0).cast::() = (11i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V10::Uint16(e) => { + *base.add(0).cast::() = (12i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V10::Uint32(e) => { + *base.add(0).cast::() = (13i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Float32(e) => { + *base.add(0).cast::() = (14i32) as u8; + *base.add(8).cast::() = _rt::as_f32(e); + } + V10::Date(e) => { + *base.add(0).cast::() = (15i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Time(e) => { + *base.add(0).cast::() = (16i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Timestamptz(e) => { + *base.add(0).cast::() = (17i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Decimal(e) => { + *base.add(0).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower4, + upper: upper4, + width: width4, + scale: scale4, + } = e; + *base.add(8).cast::() = _rt::as_i64(lower4); + *base.add(16).cast::() = _rt::as_i64(upper4); + *base.add(24).cast::() = (_rt::as_i32(width4)) as u8; + *base.add(25).cast::() = (_rt::as_i32(scale4)) as u8; + } + V10::Interval(e) => { + *base.add(0).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months5, + days: days5, + micros: micros5, + } = e; + *base.add(8).cast::() = _rt::as_i32(months5); + *base.add(12).cast::() = _rt::as_i32(days5); + *base.add(16).cast::() = _rt::as_i64(micros5); + } + V10::Uuid(e) => { + *base.add(0).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi6, + lo: lo6, + } = e; + *base.add(8).cast::() = _rt::as_i64(hi6); + *base.add(16).cast::() = _rt::as_i64(lo6); + } + V10::Complex(e) => { + *base.add(0).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr7, + json: json7, + } = e; + let vec8 = (type_expr7.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *base.add(8).cast::<*mut u8>() = ptr8.cast_mut(); + let vec9 = (json7.into_bytes()).into_boxed_slice(); + let ptr9 = vec9.as_ptr().cast::(); + let len9 = vec9.len(); + ::core::mem::forget(vec9); + *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len9; + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr9.cast_mut(); + } + } + } + } + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len11; + *base.add(0).cast::<*mut u8>() = result11; + } + } + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len12; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result12; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V18; + match e { + V18::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec13 = (e.into_bytes()).into_boxed_slice(); + let ptr13 = vec13.as_ptr().cast::(); + let len13 = vec13.len(); + ::core::mem::forget(vec13); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len13; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr13.cast_mut(); + } + V18::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec14 = (e.into_bytes()).into_boxed_slice(); + let ptr14 = vec14.as_ptr().cast::(); + let len14 = vec14.len(); + ::core::mem::forget(vec14); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len14; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr14.cast_mut(); + } + V18::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec15 = (e.into_bytes()).into_boxed_slice(); + let ptr15 = vec15.as_ptr().cast::(); + let len15 = vec15.len(); + ::core::mem::forget(vec15); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len15; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr15.cast_mut(); + } + V18::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec16 = (e.into_bytes()).into_boxed_slice(); + let ptr16 = vec16.as_ptr().cast::(); + let len16 = vec16.len(); + ::core::mem::forget(vec16); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len16; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr16.cast_mut(); + } + V18::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec17 = (e.into_bytes()).into_boxed_slice(); + let ptr17 = vec17.as_ptr().cast::(); + let len17 = vec17.len(); + ::core::mem::forget(vec17); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len17; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr17.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_scan_next(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base16 = l1; + let len16 = l2; + for i in 0..len16 { + let base = base16 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base15 = l3; + let len15 = l4; + for i in 0..len15 { + let base = base15 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + let l5 = i32::from(*base.add(0).cast::()); + match l5 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l6 = *base.add(8).cast::<*mut u8>(); + let l7 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 6 => { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l8; + let len10 = l9; + _rt::cabi_dealloc(base10, len10 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l11 = *base.add(8).cast::<*mut u8>(); + let l12 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + let l13 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + } + } + _rt::cabi_dealloc( + base15, + len15 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + } + } + _rt::cabi_dealloc( + base16, + len16 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l17 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l17 { + 0 => { + let l18 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); + } + 1 => { + let l20 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l20, l21, 1); + } + 2 => { + let l22 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l23 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l22, l23, 1); + } + 3 => { + let l24 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l25 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l24, l25, 1); + } + _ => { + let l26 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l26, l27, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_storage_scan_close_cabi( + arg0: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::storage_scan_close(arg0 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V7; + match e { + V7::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + V7::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + V7::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V7::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V7::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_storage_scan_close(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + pub trait Guest { + /// Enumerate the ATTACH `TYPE` names that components have registered (via + /// `register-storage`) so far this session. The core calls this lazily (before + /// running queries) and registers a wasm StorageExtension for each type it has + /// not yet seen, so `ATTACH ... (TYPE )` can dispatch to that component. + /// This replaces the previous hardcoded "sqlitewasm" registration at DB-open. + fn storage_list_types() -> _rt::Vec<_rt::String>; + /// Open the foreign catalog named by an ATTACH DSN (a host file path for the + /// native host). The host stages the file bytes into the backing component and + /// returns the component-side catalog handle. + fn storage_attach(dsn: _rt::String) -> Result; + /// Enumerate the catalog's base tables. + fn storage_list_tables( + catalog: u32, + ) -> Result<_rt::Vec<_rt::String>, Duckerror>; + /// Enumerate one table's columns (name + duckdb logical type). + fn storage_table_columns( + catalog: u32, + table: _rt::String, + ) -> Result<_rt::Vec, Duckerror>; + /// M2b scan surface: engine-driven projection + filter pushdown. + fn storage_scan_open( + catalog: u32, + request: ScanRequest, + ) -> Result; + fn storage_scan_next( + scan: u32, + max_rows: u32, + ) -> Result; + fn storage_scan_close(scan: u32) -> Result; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_storage_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/storage-host@4.0.0#storage-list-types")] unsafe + extern "C" fn export_storage_list_types() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_storage_list_types_cabi::<$ty > () } + } #[unsafe (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-list-types")] + unsafe extern "C" fn _post_return_storage_list_types(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_list_types::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-attach")] unsafe + extern "C" fn export_storage_attach(arg0 : * mut u8, arg1 : + usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_storage_attach_cabi::<$ty > (arg0, arg1) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-attach")] + unsafe extern "C" fn _post_return_storage_attach(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_attach::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-list-tables")] + unsafe extern "C" fn export_storage_list_tables(arg0 : i32,) -> * + mut u8 { unsafe { $($path_to_types)*:: + _export_storage_list_tables_cabi::<$ty > (arg0) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-list-tables")] + unsafe extern "C" fn _post_return_storage_list_tables(arg0 : * + mut u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_list_tables::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-table-columns")] + unsafe extern "C" fn export_storage_table_columns(arg0 : i32, + arg1 : * mut u8, arg2 : usize,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_storage_table_columns_cabi::<$ty > + (arg0, arg1, arg2) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-table-columns")] + unsafe extern "C" fn _post_return_storage_table_columns(arg0 : * + mut u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_table_columns::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-scan-open")] unsafe + extern "C" fn export_storage_scan_open(arg0 : i32, arg1 : * mut + u8, arg2 : usize, arg3 : * mut u8, arg4 : usize, arg5 : * mut u8, + arg6 : usize, arg7 : i32, arg8 : i64,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_storage_scan_open_cabi::<$ty > + (arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-scan-open")] + unsafe extern "C" fn _post_return_storage_scan_open(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_scan_open::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-scan-next")] unsafe + extern "C" fn export_storage_scan_next(arg0 : i32, arg1 : i32,) + -> * mut u8 { unsafe { $($path_to_types)*:: + _export_storage_scan_next_cabi::<$ty > (arg0, arg1) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-scan-next")] + unsafe extern "C" fn _post_return_storage_scan_next(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_scan_next::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/storage-host@4.0.0#storage-scan-close")] unsafe + extern "C" fn export_storage_scan_close(arg0 : i32,) -> * mut u8 + { unsafe { $($path_to_types)*:: + _export_storage_scan_close_cabi::<$ty > (arg0) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/storage-host@4.0.0#storage-scan-close")] + unsafe extern "C" fn _post_return_storage_scan_close(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_storage_scan_close::<$ty > (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_storage_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core custom-index callbacks (Item 3 / M2a). The DuckDB-compiled-to-wasm + /// core IMPORTS this interface; the native host PROVIDES it and routes each call + /// to the index component (e.g. hnswfns) that registered a custom index type, + /// driving that component's `index-dispatch` export. This mirrors how the core + /// imports `storage-host` for ATTACH backends. + /// + /// The lifecycle is BUILD-then-SEARCH, in memory for M2a (persistence later): + /// index-type-list -> register a DuckDB IndexType per declared type + /// index-create / index-append / index-build (the CREATE INDEX build pipeline) + /// index-search (explicit kNN; the optimizer auto-rewrite is M2b) + /// index-drop + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod index_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type Duckerror = super::super::super::super::duckdb::extension::types::Duckerror; + /// One nearest-neighbour result mirroring index-dispatch.index-hit. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct IndexHit { + pub rowid: i64, + pub distance: f32, + } + impl ::core::fmt::Debug for IndexHit { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("IndexHit") + .field("rowid", &self.rowid) + .field("distance", &self.distance) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_type_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::index_type_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec3 = result0; + let len3 = vec3.len(); + let layout3 = _rt::alloc::Layout::from_size_align_unchecked( + vec3.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result3 = if layout3.size() != 0 { + let ptr = _rt::alloc::alloc(layout3).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout3); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec3.into_iter().enumerate() { + let base = result3 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len3; + *ptr1.add(0).cast::<*mut u8>() = result3; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_type_list(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l0; + let len4 = l1; + for i in 0..len4 { + let base = base4 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + _rt::cabi_dealloc( + base4, + len4 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_create_cabi( + arg0: *mut u8, + arg1: usize, + arg2: *mut u8, + arg3: usize, + arg4: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg1; + let bytes0 = _rt::Vec::from_raw_parts(arg0.cast(), len0, len0); + let len1 = arg3; + let bytes1 = _rt::Vec::from_raw_parts(arg2.cast(), len1, len1); + let result2 = T::index_create( + _rt::string_lift(bytes0), + _rt::string_lift(bytes1), + arg4 as u32, + ); + let ptr3 = (&raw mut _RET_AREA.0).cast::(); + match result2 { + Ok(e) => { + *ptr3.add(0).cast::() = (0i32) as u8; + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(e); + } + Err(e) => { + *ptr3.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V9; + match e { + V9::Invalidargument(e) => { + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr3 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr3 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V9::Unsupported(e) => { + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr3 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr3 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V9::Invalidstate(e) => { + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr3 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr3 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V9::Io(e) => { + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr3 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr3 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V9::Internal(e) => { + *ptr3 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr3 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr3 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + } + } + }; + ptr3 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_create(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_append_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + arg3: *mut u8, + arg4: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let base4 = arg3; + let len4 = arg4; + let mut result4 = _rt::Vec::with_capacity(len4); + for i in 0..len4 { + let base = base4 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + let e4 = { + let l1 = *base.add(0).cast::<*mut u8>(); + let l2 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let len3 = l2; + _rt::Vec::from_raw_parts(l1.cast(), len3, len3) + }; + result4.push(e4); + } + _rt::cabi_dealloc( + base4, + len4 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result5 = T::index_append( + arg0 as u32, + _rt::Vec::from_raw_parts(arg1.cast(), len0, len0), + result4, + ); + let ptr6 = (&raw mut _RET_AREA.0).cast::(); + match result5 { + Ok(_) => { + *ptr6.add(0).cast::() = (0i32) as u8; + } + Err(e) => { + *ptr6.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V12; + match e { + V12::Invalidargument(e) => { + *ptr6 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr6 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr6 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V12::Unsupported(e) => { + *ptr6 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr6 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr6 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + V12::Invalidstate(e) => { + *ptr6 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec9 = (e.into_bytes()).into_boxed_slice(); + let ptr9 = vec9.as_ptr().cast::(); + let len9 = vec9.len(); + ::core::mem::forget(vec9); + *ptr6 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len9; + *ptr6 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr9.cast_mut(); + } + V12::Io(e) => { + *ptr6 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec10 = (e.into_bytes()).into_boxed_slice(); + let ptr10 = vec10.as_ptr().cast::(); + let len10 = vec10.len(); + ::core::mem::forget(vec10); + *ptr6 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len10; + *ptr6 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr10.cast_mut(); + } + V12::Internal(e) => { + *ptr6 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec11 = (e.into_bytes()).into_boxed_slice(); + let ptr11 = vec11.as_ptr().cast::(); + let len11 = vec11.len(); + ::core::mem::forget(vec11); + *ptr6 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len11; + *ptr6 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr11.cast_mut(); + } + } + } + }; + ptr6 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_append(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_build_cabi(arg0: i32) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::index_build(arg0 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(_) => { + *ptr1.add(0).cast::() = (0i32) as u8; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V7; + match e { + V7::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + V7::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + V7::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V7::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V7::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_build(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_search_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + arg3: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let result1 = T::index_search( + arg0 as u32, + _rt::Vec::from_raw_parts(arg1.cast(), len0, len0), + arg3 as u32, + ); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + let vec3 = (e).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V9; + match e { + V9::Invalidargument(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V9::Unsupported(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V9::Invalidstate(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V9::Io(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V9::Internal(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + } + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_search(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base3 = l1; + let len3 = l2; + _rt::cabi_dealloc(base3, len3 * 16, 8); + } + _ => { + let l4 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l4 { + 0 => { + let l5 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l5, l6, 1); + } + 1 => { + let l7 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + } + 2 => { + let l9 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + 3 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + } + _ => { + let l13 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_index_drop_cabi(arg0: i32) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::index_drop(arg0 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(_) => { + *ptr1.add(0).cast::() = (0i32) as u8; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V7; + match e { + V7::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + V7::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + V7::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V7::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V7::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_index_drop(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + 1 => { + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + 2 => { + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 3 => { + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l8, l9, 1); + } + _ => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); + } + } + } + } + } + pub trait Guest { + /// Enumerate the custom index TYPE names components have registered (via + /// `register-index-type`). The core calls this lazily (before running queries) + /// and registers a wasm IndexType for each not-yet-seen name, so + /// `CREATE INDEX ... USING ` dispatches to that component. This replaces + /// the M1 hardcoded "wasm_hnsw" registration. + fn index_type_list() -> _rt::Vec<_rt::String>; + /// Allocate an empty index builder for `(type-name, index-name)` whose key is a + /// FLOAT[dims] vector. Returns a component-side index-handle, 0 on error. + fn index_create( + type_name: _rt::String, + index_name: _rt::String, + dims: u32, + ) -> Result; + /// Accumulate a batch of (rowid, vector) rows into the builder. + fn index_append( + handle: u32, + rowids: _rt::Vec, + vectors: _rt::Vec<_rt::Vec>, + ) -> Result<(), Duckerror>; + /// Finalize: build the ANN map from every appended row. + fn index_build(handle: u32) -> Result<(), Duckerror>; + /// k nearest neighbours of `query`, closest first. + fn index_search( + handle: u32, + query: _rt::Vec, + k: u32, + ) -> Result<_rt::Vec, Duckerror>; + /// Free the index + handle. + fn index_drop(handle: u32) -> Result<(), Duckerror>; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_index_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/index-host@4.0.0#index-type-list")] unsafe + extern "C" fn export_index_type_list() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_index_type_list_cabi::<$ty > () } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-type-list")] + unsafe extern "C" fn _post_return_index_type_list(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_index_type_list::<$ty > (arg0) } } #[unsafe + (export_name = "duckdb:extension/index-host@4.0.0#index-create")] + unsafe extern "C" fn export_index_create(arg0 : * mut u8, arg1 : + usize, arg2 : * mut u8, arg3 : usize, arg4 : i32,) -> * mut u8 { + unsafe { $($path_to_types)*:: _export_index_create_cabi::<$ty > + (arg0, arg1, arg2, arg3, arg4) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-create")] + unsafe extern "C" fn _post_return_index_create(arg0 : * mut u8,) + { unsafe { $($path_to_types)*:: __post_return_index_create::<$ty + > (arg0) } } #[unsafe (export_name = + "duckdb:extension/index-host@4.0.0#index-append")] unsafe extern + "C" fn export_index_append(arg0 : i32, arg1 : * mut u8, arg2 : + usize, arg3 : * mut u8, arg4 : usize,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_index_append_cabi::<$ty > (arg0, + arg1, arg2, arg3, arg4) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-append")] + unsafe extern "C" fn _post_return_index_append(arg0 : * mut u8,) + { unsafe { $($path_to_types)*:: __post_return_index_append::<$ty + > (arg0) } } #[unsafe (export_name = + "duckdb:extension/index-host@4.0.0#index-build")] unsafe extern + "C" fn export_index_build(arg0 : i32,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_index_build_cabi::<$ty > (arg0) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-build")] + unsafe extern "C" fn _post_return_index_build(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_index_build::<$ty > + (arg0) } } #[unsafe (export_name = + "duckdb:extension/index-host@4.0.0#index-search")] unsafe extern + "C" fn export_index_search(arg0 : i32, arg1 : * mut u8, arg2 : + usize, arg3 : i32,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_index_search_cabi::<$ty > (arg0, arg1, arg2, arg3) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-search")] + unsafe extern "C" fn _post_return_index_search(arg0 : * mut u8,) + { unsafe { $($path_to_types)*:: __post_return_index_search::<$ty + > (arg0) } } #[unsafe (export_name = + "duckdb:extension/index-host@4.0.0#index-drop")] unsafe extern + "C" fn export_index_drop(arg0 : i32,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_index_drop_cabi::<$ty > (arg0) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/index-host@4.0.0#index-drop")] unsafe + extern "C" fn _post_return_index_drop(arg0 : * mut u8,) { unsafe + { $($path_to_types)*:: __post_return_index_drop::<$ty > (arg0) } + } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_index_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core collation pull. The DuckDB-compiled-to-wasm core IMPORTS this + /// interface; the native host PROVIDES it, returning the collations that + /// components have declared (via the `collation.register-collation` WIT call). + /// This mirrors how the core pulls ATTACH `TYPE` names via + /// `storage-host.storage-list-types`. + /// + /// A collation reuses an already-registered scalar (text -> sort-key text) as + /// its transform. The core looks the scalar up by name in the catalog and wraps + /// it in a DuckDB collation (CreateCollationInfo), so `ORDER BY x COLLATE name` + /// resolves to it. Registration is dynamic (mid-session): the core pulls this + /// list lazily before each query and registers each collation it has not yet + /// seen, dedup-guarded. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod collation_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + /// One collation a component declared: its catalog name, the already-registered + /// scalar that performs the (text -> sort-key text) transform, and whether the + /// collation can be combined with other collations. + #[derive(Clone)] + pub struct CollationSpec { + pub name: _rt::String, + pub transform_scalar: _rt::String, + pub combinable: bool, + } + impl ::core::fmt::Debug for CollationSpec { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("CollationSpec") + .field("name", &self.name) + .field("transform-scalar", &self.transform_scalar) + .field("combinable", &self.combinable) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_collation_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::collation_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec5 = result0; + let len5 = vec5.len(); + let layout5 = _rt::alloc::Layout::from_size_align_unchecked( + vec5.len() * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result5 = if layout5.size() != 0 { + let ptr = _rt::alloc::alloc(layout5).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout5); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec5.into_iter().enumerate() { + let base = result5 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let CollationSpec { + name: name2, + transform_scalar: transform_scalar2, + combinable: combinable2, + } = e; + let vec3 = (name2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(0).cast::<*mut u8>() = ptr3.cast_mut(); + let vec4 = (transform_scalar2.into_bytes()) + .into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::() = (match combinable2 { + true => 1, + false => 0, + }) as u8; + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len5; + *ptr1.add(0).cast::<*mut u8>() = result5; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_collation_list(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base6 = l0; + let len6 = l1; + for i in 0..len6 { + let base = base6 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + let l4 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + } + _rt::cabi_dealloc( + base6, + len6 * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + pub trait Guest { + /// Enumerate the collations components have declared so far this session. + fn collation_list() -> _rt::Vec; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_collation_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/collation-host@4.0.0#collation-list")] unsafe + extern "C" fn export_collation_list() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_collation_list_cabi::<$ty > () } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/collation-host@4.0.0#collation-list")] + unsafe extern "C" fn _post_return_collation_list(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_collation_list::<$ty > (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_collation_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core pragma pull (Item 4). The DuckDB-compiled-to-wasm core IMPORTS + /// this interface; the native host PROVIDES it, returning the pragmas that + /// components have declared (via the existing `runtime.pragma-registry.register-call` + /// WIT call). This mirrors `collation-host.collation-list` / `storage-host.storage-list-types`. + /// + /// KEY DESIGN (avoids re-entrancy): a PRAGMA callback runs MID-QUERY, so the + /// component must NOT call back into SQL during the callback. Instead the core + /// intercepts `PRAGMA (...)` in its query path, dispatches the pragma + /// (callback-dispatch.call-pragma -> the component), and the component RETURNS a + /// SQL script as a text value. The core then runs that script on the same + /// connection. The component never re-enters SQL. + /// + /// `callback-handle` is the host-side handle the core passes to + /// `callback-dispatch.call-pragma` to dispatch this pragma to the owning component. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod pragma_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + /// One pragma a component declared: the PRAGMA name the user types + /// (`PRAGMA (...)`) and the dispatch handle for callback-dispatch.call-pragma. + #[derive(Clone)] + pub struct PragmaSpec { + pub name: _rt::String, + pub callback_handle: u32, + } + impl ::core::fmt::Debug for PragmaSpec { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("PragmaSpec") + .field("name", &self.name) + .field("callback-handle", &self.callback_handle) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_pragma_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::pragma_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec4 = result0; + let len4 = vec4.len(); + let layout4 = _rt::alloc::Layout::from_size_align_unchecked( + vec4.len() * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result4 = if layout4.size() != 0 { + let ptr = _rt::alloc::alloc(layout4).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout4); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec4.into_iter().enumerate() { + let base = result4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let PragmaSpec { + name: name2, + callback_handle: callback_handle2, + } = e; + let vec3 = (name2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(0).cast::<*mut u8>() = ptr3.cast_mut(); + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(callback_handle2); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len4; + *ptr1.add(0).cast::<*mut u8>() = result4; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_pragma_list(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l0; + let len4 = l1; + for i in 0..len4 { + let base = base4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + _rt::cabi_dealloc( + base4, + len4 * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + pub trait Guest { + /// Enumerate the pragmas components have declared so far this session. + fn pragma_list() -> _rt::Vec; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_pragma_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/pragma-host@4.0.0#pragma-list")] unsafe extern + "C" fn export_pragma_list() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_pragma_list_cabi::<$ty > () } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/pragma-host@4.0.0#pragma-list")] + unsafe extern "C" fn _post_return_pragma_list(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_pragma_list::<$ty > + (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_pragma_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 2 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 2 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core parser pull + dispatch (2.3.0 / v3). The DuckDB-compiled-to-wasm + /// core IMPORTS this interface; the native host PROVIDES it. Mirrors + /// `pragma-host`: the core pulls the parser extensions components have declared + /// (via `parser.register-parser-extension`), and -- when the built-in parser + /// rejects a statement -- offers the raw statement text to each, applying the + /// string->SQL REWRITE the owning component returns. The component never returns a + /// bound parse tree (the by-value WIT recursion wall); only text in, SQL out. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod parser_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type Duckerror = super::super::super::super::duckdb::extension::types::Duckerror; + /// One parser extension a component declared: a name + the dispatch handle the + /// host routes `call-parse` through to the owning component. + #[derive(Clone)] + pub struct ParserSpec { + pub name: _rt::String, + pub callback_handle: u32, + } + impl ::core::fmt::Debug for ParserSpec { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("ParserSpec") + .field("name", &self.name) + .field("callback-handle", &self.callback_handle) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_parser_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::parser_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec4 = result0; + let len4 = vec4.len(); + let layout4 = _rt::alloc::Layout::from_size_align_unchecked( + vec4.len() * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result4 = if layout4.size() != 0 { + let ptr = _rt::alloc::alloc(layout4).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout4); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec4.into_iter().enumerate() { + let base = result4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let ParserSpec { + name: name2, + callback_handle: callback_handle2, + } = e; + let vec3 = (name2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(0).cast::<*mut u8>() = ptr3.cast_mut(); + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(callback_handle2); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len4; + *ptr1.add(0).cast::<*mut u8>() = result4; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_parser_list(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l0; + let len4 = l1; + for i in 0..len4 { + let base = base4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + _rt::cabi_dealloc( + base4, + len4 * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_call_parse_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + let result1 = T::call_parse(arg0 as u32, _rt::string_lift(bytes0)); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + match e { + Some(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + None => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + }; + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V9; + match e { + V9::Invalidargument(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V9::Unsupported(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V9::Invalidstate(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V9::Io(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V9::Internal(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + } + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_call_parse(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => {} + _ => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + } + _ => { + let l4 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l4 { + 0 => { + let l5 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l5, l6, 1); + } + 1 => { + let l7 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + } + 2 => { + let l9 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + 3 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + } + _ => { + let l13 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + } + } + } + pub trait Guest { + /// Enumerate the parser extensions components have declared so far this session. + fn parser_list() -> _rt::Vec; + /// Offer the unrecognized statement `query` to the parser extension `handle`. + /// Returns `some(rewrite-sql)` if the component claims + rewrites it, or `none` + /// if it declines (the core proceeds to its own parse error). + fn call_parse( + handle: u32, + query: _rt::String, + ) -> Result, Duckerror>; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_parser_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/parser-host@4.0.0#parser-list")] unsafe extern + "C" fn export_parser_list() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_parser_list_cabi::<$ty > () } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/parser-host@4.0.0#parser-list")] + unsafe extern "C" fn _post_return_parser_list(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_parser_list::<$ty > + (arg0) } } #[unsafe (export_name = + "duckdb:extension/parser-host@4.0.0#call-parse")] unsafe extern + "C" fn export_call_parse(arg0 : i32, arg1 : * mut u8, arg2 : + usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_parse_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe + (export_name = + "cabi_post_duckdb:extension/parser-host@4.0.0#call-parse")] + unsafe extern "C" fn _post_return_call_parse(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_call_parse::<$ty > + (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_parser_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// Host -> core optimizer pull + dispatch (2.3.0 / v3, additive within major-3). + /// The DuckDB-compiled-to-wasm core IMPORTS this; the native host PROVIDES it. + /// Mirrors `parser-host`: at optimize time the core flattens the bound logical plan + /// into a neutral JSON descriptor (op-type names + params, NOT a by-value + /// LogicalOperator tree) and offers it to each declared optimizer rule via + /// `call-optimize`. The owning component returns a string->SQL REWRITE the core + /// re-plans in place (the `rewrite-query` directive), or none (declined). No plan + /// node crosses the boundary by value. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod optimizer_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type Duckerror = super::super::super::super::duckdb::extension::types::Duckerror; + /// One optimizer rule a component declared: a name + the dispatch handle the + /// host routes `call-optimize` through to the owning component. + #[derive(Clone)] + pub struct OptimizerSpec { + pub rule_name: _rt::String, + pub callback_handle: u32, + } + impl ::core::fmt::Debug for OptimizerSpec { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("OptimizerSpec") + .field("rule-name", &self.rule_name) + .field("callback-handle", &self.callback_handle) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_optimizer_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::optimizer_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec4 = result0; + let len4 = vec4.len(); + let layout4 = _rt::alloc::Layout::from_size_align_unchecked( + vec4.len() * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result4 = if layout4.size() != 0 { + let ptr = _rt::alloc::alloc(layout4).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout4); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec4.into_iter().enumerate() { + let base = result4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let OptimizerSpec { + rule_name: rule_name2, + callback_handle: callback_handle2, + } = e; + let vec3 = (rule_name2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(0).cast::<*mut u8>() = ptr3.cast_mut(); + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(callback_handle2); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len4; + *ptr1.add(0).cast::<*mut u8>() = result4; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_optimizer_list(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base4 = l0; + let len4 = l1; + for i in 0..len4 { + let base = base4 + .add(i * (3 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + _rt::cabi_dealloc( + base4, + len4 * (3 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_call_optimize_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + let result1 = T::call_optimize( + arg0 as u32, + _rt::string_lift(bytes0), + ); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + match e { + Some(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + None => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + }; + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V9; + match e { + V9::Invalidargument(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); + } + V9::Unsupported(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); + } + V9::Invalidstate(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + V9::Io(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec7 = (e.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len7; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr7.cast_mut(); + } + V9::Internal(e) => { + *ptr2 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec8 = (e.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *ptr2 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *ptr2 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr8.cast_mut(); + } + } + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_call_optimize(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { + 0 => {} + _ => { + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + } + } + } + _ => { + let l4 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l4 { + 0 => { + let l5 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l6 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l5, l6, 1); + } + 1 => { + let l7 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l8 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l7, l8, 1); + } + 2 => { + let l9 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + 3 => { + let l11 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l12 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + } + _ => { + let l13 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + } + } + } + pub trait Guest { + /// Enumerate the optimizer rules components have declared so far this session. + fn optimizer_list() -> _rt::Vec; + /// Offer the flattened plan (`plan-json`) to the rule `handle`. Returns + /// `some(rewrite-sql)` if the rule rewrites the query (the core re-plans it in + /// place), or `none` if it declines / the directive is not a query rewrite. + fn call_optimize( + handle: u32, + plan_json: _rt::String, + ) -> Result, Duckerror>; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_optimizer_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/optimizer-host@4.0.0#optimizer-list")] unsafe + extern "C" fn export_optimizer_list() -> * mut u8 { unsafe { + $($path_to_types)*:: _export_optimizer_list_cabi::<$ty > () } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/optimizer-host@4.0.0#optimizer-list")] + unsafe extern "C" fn _post_return_optimizer_list(arg0 : * mut + u8,) { unsafe { $($path_to_types)*:: + __post_return_optimizer_list::<$ty > (arg0) } } #[unsafe + (export_name = + "duckdb:extension/optimizer-host@4.0.0#call-optimize")] unsafe + extern "C" fn export_call_optimize(arg0 : i32, arg1 : * mut u8, + arg2 : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_call_optimize_cabi::<$ty > (arg0, arg1, arg2) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/optimizer-host@4.0.0#call-optimize")] + unsafe extern "C" fn _post_return_call_optimize(arg0 : * mut u8,) + { unsafe { $($path_to_types)*:: __post_return_call_optimize::<$ty + > (arg0) } } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_optimizer_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] + struct _RetArea( + [::core::mem::MaybeUninit< + u8, + >; 4 * ::core::mem::size_of::<*const u8>()], + ); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], + ); + } + /// httpfs M2. Host -> core file I/O callbacks. The DuckDB-compiled-to-wasm core + /// IMPORTS this interface; the native host PROVIDES it and routes each call to + /// the files-backend component (e.g. webfs) that registered a files backend, + /// driving that component's `file-dispatch` export. This mirrors how the core + /// imports `storage-host` for ATTACH foreign-catalog dispatch. + /// + /// Simple + robust M2 contract (no HTTP Range): the component, on file-open, + /// does a single GET of the whole file, caches the bytes, and returns its size. + /// file-read slices the cache; file-close drops it. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod files_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + /// The component-side file handle plus the total size discovered at open. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct FileOpenResult { + pub handle: u32, + pub size: u64, + } + impl ::core::fmt::Debug for FileOpenResult { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("FileOpenResult") + .field("handle", &self.handle) + .field("size", &self.size) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_file_open_cabi( + arg0: *mut u8, + arg1: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let len0 = arg1; + let bytes0 = _rt::Vec::from_raw_parts(arg0.cast(), len0, len0); + let result1 = T::file_open(_rt::string_lift(bytes0)); + let ptr2 = (&raw mut _RET_AREA.0).cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + let FileOpenResult { handle: handle3, size: size3 } = e; + *ptr2.add(8).cast::() = _rt::as_i32(handle3); + *ptr2.add(16).cast::() = _rt::as_i64(size3); + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr2 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr2.add(8).cast::<*mut u8>() = ptr4.cast_mut(); + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_file_open(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = *arg0.add(8).cast::<*mut u8>(); + let l2 = *arg0 + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l1, l2, 1); + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_file_read_cabi( + arg0: i32, + arg1: i64, + arg2: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::file_read(arg0 as u32, arg1 as u64, arg2 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + let vec2 = (e).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_file_read(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base3 = l1; + let len3 = l2; + _rt::cabi_dealloc(base3, len3 * 1, 1); + } + _ => { + let l4 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l4, l5, 1); + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_file_close_cabi(arg0: i32) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::file_close(arg0 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(_) => { + *ptr1.add(0).cast::() = (0i32) as u8; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_file_close(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => {} + _ => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l1, l2, 1); + } + } + } + pub trait Guest { + /// Fetch + cache the resource named by `url`; return a file handle + total size. + fn file_open( + url: _rt::String, + ) -> Result; + /// Return up to `len` bytes from the cached resource starting at `offset`. + /// A short read at EOF is allowed (returns fewer bytes than requested). + fn file_read( + handle: u32, + offset: u64, + len: u32, + ) -> Result<_rt::Vec, _rt::String>; + /// Drop the cache entry for `handle`. + fn file_close(handle: u32) -> Result<(), _rt::String>; + } + #[doc(hidden)] + macro_rules! __export_duckdb_extension_files_host_4_0_0_cabi { + ($ty:ident with_types_in $($path_to_types:tt)*) => { + const _ : () = { #[unsafe (export_name = + "duckdb:extension/files-host@4.0.0#file-open")] unsafe extern "C" + fn export_file_open(arg0 : * mut u8, arg1 : usize,) -> * mut u8 { + unsafe { $($path_to_types)*:: _export_file_open_cabi::<$ty > + (arg0, arg1) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/files-host@4.0.0#file-open")] unsafe + extern "C" fn _post_return_file_open(arg0 : * mut u8,) { unsafe { + $($path_to_types)*:: __post_return_file_open::<$ty > (arg0) } } + #[unsafe (export_name = + "duckdb:extension/files-host@4.0.0#file-read")] unsafe extern "C" + fn export_file_read(arg0 : i32, arg1 : i64, arg2 : i32,) -> * mut + u8 { unsafe { $($path_to_types)*:: _export_file_read_cabi::<$ty > + (arg0, arg1, arg2) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/files-host@4.0.0#file-read")] unsafe + extern "C" fn _post_return_file_read(arg0 : * mut u8,) { unsafe { + $($path_to_types)*:: __post_return_file_read::<$ty > (arg0) } } + #[unsafe (export_name = + "duckdb:extension/files-host@4.0.0#file-close")] unsafe extern + "C" fn export_file_close(arg0 : i32,) -> * mut u8 { unsafe { + $($path_to_types)*:: _export_file_close_cabi::<$ty > (arg0) } } + #[unsafe (export_name = + "cabi_post_duckdb:extension/files-host@4.0.0#file-close")] unsafe + extern "C" fn _post_return_file_close(arg0 : * mut u8,) { unsafe + { $($path_to_types)*:: __post_return_file_close::<$ty > (arg0) } + } }; + }; + } + #[doc(hidden)] + pub(crate) use __export_duckdb_extension_files_host_4_0_0_cabi; + #[repr(align(8))] + struct _RetArea([::core::mem::MaybeUninit; 24]); + static mut _RET_AREA: _RetArea = _RetArea( + [::core::mem::MaybeUninit::uninit(); 24], + ); + } + /// Host -> core callbacks for a STREAMING + FILTER-PUSHDOWN table function (3.1.0, + /// the first additive MINOR off the frozen major-3 baseline). The DuckDB-compiled- + /// to-wasm core IMPORTS this interface; the host PROVIDES it and routes each call + /// (by the global callback-handle the function was registered with) to the owning + /// component's `table-stream-dispatch` export (open-filtered / next / close). + /// Mirrors `storage-host` (the proven by-value-safe filter-pushdown bridge), but + /// for a NAMED table function with bound argument values instead of a catalog. + #[allow(dead_code, async_fn_in_trait, unused_imports, clippy::all)] + pub mod table_stream_host { + #[used] + #[doc(hidden)] + static __FORCE_SECTION_REF: fn() = super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + pub type Duckerror = super::super::super::super::duckdb::extension::types::Duckerror; + pub type Columndef = super::super::super::super::duckdb::extension::types::Columndef; + pub type Duckvalue = super::super::super::super::duckdb::extension::types::Duckvalue; + pub type Resultset = _rt::Vec<_rt::Vec>; + /// A streaming + filter-pushdown-capable table function a component declared + /// (via the component-facing `table-stream.register-filterable-table` marker). + /// The core pulls this list lazily (before queries, like collation/optimizer + /// sync) and registers a real C++ streaming TableFunction (filter_pushdown = + /// true) for each not-yet-seen entry. `arguments` are the positional argument + /// types (name informational); `columns` is the emitted schema; `handle` is the + /// global routable callback-handle threaded into ts-open-filtered/next/close. + #[derive(Clone)] + pub struct FilterableTable { + pub name: _rt::String, + pub arguments: _rt::Vec, + pub columns: _rt::Vec, + pub handle: u32, + } + impl ::core::fmt::Debug for FilterableTable { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("FilterableTable") + .field("name", &self.name) + .field("arguments", &self.arguments) + .field("columns", &self.columns) + .field("handle", &self.handle) + .finish() + } + } + /// The pushed-down comparator. Mirrors table-stream-dispatch.filter-op. + #[repr(u8)] + #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)] + pub enum TsFilterOp { + Eq, + Ne, + Lt, + Le, + Gt, + Ge, + IsIn, + IsNull, + IsNotNull, + } + impl ::core::fmt::Debug for TsFilterOp { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + match self { + TsFilterOp::Eq => f.debug_tuple("TsFilterOp::Eq").finish(), + TsFilterOp::Ne => f.debug_tuple("TsFilterOp::Ne").finish(), + TsFilterOp::Lt => f.debug_tuple("TsFilterOp::Lt").finish(), + TsFilterOp::Le => f.debug_tuple("TsFilterOp::Le").finish(), + TsFilterOp::Gt => f.debug_tuple("TsFilterOp::Gt").finish(), + TsFilterOp::Ge => f.debug_tuple("TsFilterOp::Ge").finish(), + TsFilterOp::IsIn => { + f.debug_tuple("TsFilterOp::IsIn").finish() + } + TsFilterOp::IsNull => { + f.debug_tuple("TsFilterOp::IsNull").finish() + } + TsFilterOp::IsNotNull => { + f.debug_tuple("TsFilterOp::IsNotNull").finish() + } + } + } + } + impl TsFilterOp { + #[doc(hidden)] + pub unsafe fn _lift(val: u8) -> TsFilterOp { + if !cfg!(debug_assertions) { + return ::core::mem::transmute(val); + } + match val { + 0 => TsFilterOp::Eq, + 1 => TsFilterOp::Ne, + 2 => TsFilterOp::Lt, + 3 => TsFilterOp::Le, + 4 => TsFilterOp::Gt, + 5 => TsFilterOp::Ge, + 6 => TsFilterOp::IsIn, + 7 => TsFilterOp::IsNull, + 8 => TsFilterOp::IsNotNull, + _ => panic!("invalid enum discriminant"), + } + } + } + /// One pushed-down clause. `column` indexes the EMITTED (post-projection) + /// schema; `values` carries the constant operand(s) (empty for is-null/ + /// is-not-null, one for the scalar comparators, many for is-in). The full filter + /// is the AND of all clauses. Best-effort: the engine re-applies every filter. + #[derive(Clone)] + pub struct TsFilter { + pub column: u32, + pub op: TsFilterOp, + pub values: _rt::Vec, + } + impl ::core::fmt::Debug for TsFilter { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("TsFilter") + .field("column", &self.column) + .field("op", &self.op) + .field("values", &self.values) + .finish() + } + } + /// Opening a streaming cursor returns an opaque cursor handle plus the emitted + /// column schema (after projection). + #[derive(Clone)] + pub struct TsOpenResult { + pub cursor: u32, + pub columns: _rt::Vec, + } + impl ::core::fmt::Debug for TsOpenResult { + fn fmt( + &self, + f: &mut ::core::fmt::Formatter<'_>, + ) -> ::core::fmt::Result { + f.debug_struct("TsOpenResult") + .field("cursor", &self.cursor) + .field("columns", &self.columns) + .finish() + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_filterable_table_list_cabi() -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::filterable_table_list(); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + let vec14 = result0; + let len14 = vec14.len(); + let layout14 = _rt::alloc::Layout::from_size_align_unchecked( + vec14.len() * (7 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result14 = if layout14.size() != 0 { + let ptr = _rt::alloc::alloc(layout14).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout14); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec14.into_iter().enumerate() { + let base = result14 + .add(i * (7 * ::core::mem::size_of::<*const u8>())); + { + let FilterableTable { + name: name2, + arguments: arguments2, + columns: columns2, + handle: handle2, + } = e; + let vec3 = (name2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(0).cast::<*mut u8>() = ptr3.cast_mut(); + let vec8 = arguments2; + let len8 = vec8.len(); + let layout8 = _rt::alloc::Layout::from_size_align_unchecked( + vec8.len() * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result8 = if layout8.size() != 0 { + let ptr = _rt::alloc::alloc(layout8).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout8); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec8.into_iter().enumerate() { + let base = result8 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let super::super::super::super::duckdb::extension::types::Columndef { + name: name4, + logical: logical4, + } = e; + let vec5 = (name4.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *base.add(0).cast::<*mut u8>() = ptr5.cast_mut(); + use super::super::super::super::duckdb::extension::types::Logicaltype as V7; + match logical4 { + V7::Boolean => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + V7::Int64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + } + V7::Uint64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + } + V7::Float64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + } + V7::Text => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + } + V7::Blob => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + } + V7::Int32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + } + V7::Timestamp => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + } + V7::Int8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + } + V7::Int16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + } + V7::Uint8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + } + V7::Uint16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + } + V7::Uint32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + } + V7::Float32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + } + V7::Date => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + } + V7::Time => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + } + V7::Timestamptz => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + } + V7::Decimal => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + } + V7::Interval => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + } + V7::Uuid => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + } + V7::Complex(e) => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); + } + } + } + } + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result8; + let vec13 = columns2; + let len13 = vec13.len(); + let layout13 = _rt::alloc::Layout::from_size_align_unchecked( + vec13.len() * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result13 = if layout13.size() != 0 { + let ptr = _rt::alloc::alloc(layout13).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout13); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec13.into_iter().enumerate() { + let base = result13 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let super::super::super::super::duckdb::extension::types::Columndef { + name: name9, + logical: logical9, + } = e; + let vec10 = (name9.into_bytes()).into_boxed_slice(); + let ptr10 = vec10.as_ptr().cast::(); + let len10 = vec10.len(); + ::core::mem::forget(vec10); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len10; + *base.add(0).cast::<*mut u8>() = ptr10.cast_mut(); + use super::super::super::super::duckdb::extension::types::Logicaltype as V12; + match logical9 { + V12::Boolean => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + V12::Int64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + } + V12::Uint64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + } + V12::Float64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + } + V12::Text => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + } + V12::Blob => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + } + V12::Int32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + } + V12::Timestamp => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + } + V12::Int8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + } + V12::Int16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + } + V12::Uint8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + } + V12::Uint16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + } + V12::Uint32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + } + V12::Float32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + } + V12::Date => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + } + V12::Time => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + } + V12::Timestamptz => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + } + V12::Decimal => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + } + V12::Interval => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + } + V12::Uuid => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + } + V12::Complex(e) => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec11 = (e.into_bytes()).into_boxed_slice(); + let ptr11 = vec11.as_ptr().cast::(); + let len11 = vec11.len(); + ::core::mem::forget(vec11); + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::() = len11; + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr11.cast_mut(); + } + } + } + } + *base + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::() = len13; + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result13; + *base + .add(6 * ::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(handle2); + } + } + *ptr1.add(::core::mem::size_of::<*const u8>()).cast::() = len14; + *ptr1.add(0).cast::<*mut u8>() = result14; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_filterable_table_list( + arg0: *mut u8, + ) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base20 = l0; + let len20 = l1; + for i in 0..len20 { + let base = base20 + .add(i * (7 * ::core::mem::size_of::<*const u8>())); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l2, l3, 1); + let l4 = *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l5 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base11 = l4; + let len11 = l5; + for i in 0..len11 { + let base = base11 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let l6 = *base.add(0).cast::<*mut u8>(); + let l7 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + let l8 = i32::from( + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + match l8 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => {} + 6 => {} + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + _ => { + let l9 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l10 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l9, l10, 1); + } + } + } + } + _rt::cabi_dealloc( + base11, + len11 * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let l12 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l13 = *base + .add(5 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base19 = l12; + let len19 = l13; + for i in 0..len19 { + let base = base19 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let l14 = *base.add(0).cast::<*mut u8>(); + let l15 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l14, l15, 1); + let l16 = i32::from( + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + match l16 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => {} + 6 => {} + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + _ => { + let l17 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l18 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l17, l18, 1); + } + } + } + } + _rt::cabi_dealloc( + base19, + len19 * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + } + _rt::cabi_dealloc( + base20, + len20 * (7 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_ts_open_filtered_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + arg3: *mut u8, + arg4: usize, + arg5: *mut u8, + arg6: usize, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let base38 = arg1; + let len38 = arg2; + let mut result38 = _rt::Vec::with_capacity(len38); + for i in 0..len38 { + let base = base38 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + let e38 = { + let l0 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V37; + let v37 = match l0 { + 0 => V37::Null, + 1 => { + let e37 = { + let l1 = i32::from(*base.add(8).cast::()); + _rt::bool_lift(l1 as u8) + }; + V37::Boolean(e37) + } + 2 => { + let e37 = { + let l2 = *base.add(8).cast::(); + l2 + }; + V37::Int64(e37) + } + 3 => { + let e37 = { + let l3 = *base.add(8).cast::(); + l3 as u64 + }; + V37::Uint64(e37) + } + 4 => { + let e37 = { + let l4 = *base.add(8).cast::(); + l4 + }; + V37::Float64(e37) + } + 5 => { + let e37 = { + let l5 = *base.add(8).cast::<*mut u8>(); + let l6 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len7 = l6; + let bytes7 = _rt::Vec::from_raw_parts( + l5.cast(), + len7, + len7, + ); + _rt::string_lift(bytes7) + }; + V37::Text(e37) + } + 6 => { + let e37 = { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len10 = l9; + _rt::Vec::from_raw_parts(l8.cast(), len10, len10) + }; + V37::Blob(e37) + } + 7 => { + let e37 = { + let l11 = *base.add(8).cast::(); + l11 + }; + V37::Int32(e37) + } + 8 => { + let e37 = { + let l12 = *base.add(8).cast::(); + l12 + }; + V37::Timestamp(e37) + } + 9 => { + let e37 = { + let l13 = i32::from(*base.add(8).cast::()); + l13 as i8 + }; + V37::Int8(e37) + } + 10 => { + let e37 = { + let l14 = i32::from(*base.add(8).cast::()); + l14 as i16 + }; + V37::Int16(e37) + } + 11 => { + let e37 = { + let l15 = i32::from(*base.add(8).cast::()); + l15 as u8 + }; + V37::Uint8(e37) + } + 12 => { + let e37 = { + let l16 = i32::from(*base.add(8).cast::()); + l16 as u16 + }; + V37::Uint16(e37) + } + 13 => { + let e37 = { + let l17 = *base.add(8).cast::(); + l17 as u32 + }; + V37::Uint32(e37) + } + 14 => { + let e37 = { + let l18 = *base.add(8).cast::(); + l18 + }; + V37::Float32(e37) + } + 15 => { + let e37 = { + let l19 = *base.add(8).cast::(); + l19 + }; + V37::Date(e37) + } + 16 => { + let e37 = { + let l20 = *base.add(8).cast::(); + l20 + }; + V37::Time(e37) + } + 17 => { + let e37 = { + let l21 = *base.add(8).cast::(); + l21 + }; + V37::Timestamptz(e37) + } + 18 => { + let e37 = { + let l22 = *base.add(8).cast::(); + let l23 = *base.add(16).cast::(); + let l24 = i32::from(*base.add(24).cast::()); + let l25 = i32::from(*base.add(25).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l22 as u64, + upper: l23 as u64, + width: l24 as u8, + scale: l25 as u8, + } + }; + V37::Decimal(e37) + } + 19 => { + let e37 = { + let l26 = *base.add(8).cast::(); + let l27 = *base.add(12).cast::(); + let l28 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l26, + days: l27, + micros: l28, + } + }; + V37::Interval(e37) + } + 20 => { + let e37 = { + let l29 = *base.add(8).cast::(); + let l30 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l29 as u64, + lo: l30 as u64, + } + }; + V37::Uuid(e37) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e37 = { + let l31 = *base.add(8).cast::<*mut u8>(); + let l32 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len33 = l32; + let bytes33 = _rt::Vec::from_raw_parts( + l31.cast(), + len33, + len33, + ); + let l34 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l35 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len36 = l35; + let bytes36 = _rt::Vec::from_raw_parts( + l34.cast(), + len36, + len36, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes33), + json: _rt::string_lift(bytes36), + } + }; + V37::Complex(e37) + } + }; + v37 + }; + result38.push(e38); + } + _rt::cabi_dealloc( + base38, + len38 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let len39 = arg4; + let base83 = arg5; + let len83 = arg6; + let mut result83 = _rt::Vec::with_capacity(len83); + for i in 0..len83 { + let base = base83 + .add(i * (8 + 2 * ::core::mem::size_of::<*const u8>())); + let e83 = { + let l40 = *base.add(0).cast::(); + let l41 = i32::from(*base.add(4).cast::()); + let l42 = *base.add(8).cast::<*mut u8>(); + let l43 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base82 = l42; + let len82 = l43; + let mut result82 = _rt::Vec::with_capacity(len82); + for i in 0..len82 { + let base = base82 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + let e82 = { + let l44 = i32::from(*base.add(0).cast::()); + use super::super::super::super::duckdb::extension::types::Duckvalue as V81; + let v81 = match l44 { + 0 => V81::Null, + 1 => { + let e81 = { + let l45 = i32::from(*base.add(8).cast::()); + _rt::bool_lift(l45 as u8) + }; + V81::Boolean(e81) + } + 2 => { + let e81 = { + let l46 = *base.add(8).cast::(); + l46 + }; + V81::Int64(e81) + } + 3 => { + let e81 = { + let l47 = *base.add(8).cast::(); + l47 as u64 + }; + V81::Uint64(e81) + } + 4 => { + let e81 = { + let l48 = *base.add(8).cast::(); + l48 + }; + V81::Float64(e81) + } + 5 => { + let e81 = { + let l49 = *base.add(8).cast::<*mut u8>(); + let l50 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len51 = l50; + let bytes51 = _rt::Vec::from_raw_parts( + l49.cast(), + len51, + len51, + ); + _rt::string_lift(bytes51) + }; + V81::Text(e81) + } + 6 => { + let e81 = { + let l52 = *base.add(8).cast::<*mut u8>(); + let l53 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len54 = l53; + _rt::Vec::from_raw_parts(l52.cast(), len54, len54) + }; + V81::Blob(e81) + } + 7 => { + let e81 = { + let l55 = *base.add(8).cast::(); + l55 + }; + V81::Int32(e81) + } + 8 => { + let e81 = { + let l56 = *base.add(8).cast::(); + l56 + }; + V81::Timestamp(e81) + } + 9 => { + let e81 = { + let l57 = i32::from(*base.add(8).cast::()); + l57 as i8 + }; + V81::Int8(e81) + } + 10 => { + let e81 = { + let l58 = i32::from(*base.add(8).cast::()); + l58 as i16 + }; + V81::Int16(e81) + } + 11 => { + let e81 = { + let l59 = i32::from(*base.add(8).cast::()); + l59 as u8 + }; + V81::Uint8(e81) + } + 12 => { + let e81 = { + let l60 = i32::from(*base.add(8).cast::()); + l60 as u16 + }; + V81::Uint16(e81) + } + 13 => { + let e81 = { + let l61 = *base.add(8).cast::(); + l61 as u32 + }; + V81::Uint32(e81) + } + 14 => { + let e81 = { + let l62 = *base.add(8).cast::(); + l62 + }; + V81::Float32(e81) + } + 15 => { + let e81 = { + let l63 = *base.add(8).cast::(); + l63 + }; + V81::Date(e81) + } + 16 => { + let e81 = { + let l64 = *base.add(8).cast::(); + l64 + }; + V81::Time(e81) + } + 17 => { + let e81 = { + let l65 = *base.add(8).cast::(); + l65 + }; + V81::Timestamptz(e81) + } + 18 => { + let e81 = { + let l66 = *base.add(8).cast::(); + let l67 = *base.add(16).cast::(); + let l68 = i32::from(*base.add(24).cast::()); + let l69 = i32::from(*base.add(25).cast::()); + super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: l66 as u64, + upper: l67 as u64, + width: l68 as u8, + scale: l69 as u8, + } + }; + V81::Decimal(e81) + } + 19 => { + let e81 = { + let l70 = *base.add(8).cast::(); + let l71 = *base.add(12).cast::(); + let l72 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Intervalvalue { + months: l70, + days: l71, + micros: l72, + } + }; + V81::Interval(e81) + } + 20 => { + let e81 = { + let l73 = *base.add(8).cast::(); + let l74 = *base.add(16).cast::(); + super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: l73 as u64, + lo: l74 as u64, + } + }; + V81::Uuid(e81) + } + n => { + debug_assert_eq!(n, 21, "invalid enum discriminant"); + let e81 = { + let l75 = *base.add(8).cast::<*mut u8>(); + let l76 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len77 = l76; + let bytes77 = _rt::Vec::from_raw_parts( + l75.cast(), + len77, + len77, + ); + let l78 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l79 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let len80 = l79; + let bytes80 = _rt::Vec::from_raw_parts( + l78.cast(), + len80, + len80, + ); + super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: _rt::string_lift(bytes77), + json: _rt::string_lift(bytes80), + } + }; + V81::Complex(e81) + } + }; + v81 + }; + result82.push(e82); + } + _rt::cabi_dealloc( + base82, + len82 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + TsFilter { + column: l40 as u32, + op: TsFilterOp::_lift(l41 as u8), + values: result82, + } + }; + result83.push(e83); + } + _rt::cabi_dealloc( + base83, + len83 * (8 + 2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result84 = T::ts_open_filtered( + arg0 as u32, + result38, + _rt::Vec::from_raw_parts(arg3.cast(), len39, len39), + result83, + ); + let ptr85 = (&raw mut _RET_AREA.0).cast::(); + match result84 { + Ok(e) => { + *ptr85.add(0).cast::() = (0i32) as u8; + let TsOpenResult { cursor: cursor86, columns: columns86 } = e; + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = _rt::as_i32(cursor86); + let vec91 = columns86; + let len91 = vec91.len(); + let layout91 = _rt::alloc::Layout::from_size_align_unchecked( + vec91.len() * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result91 = if layout91.size() != 0 { + let ptr = _rt::alloc::alloc(layout91).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout91); } + ptr + } else { + ::core::ptr::null_mut() }; - V4::Complex(e4) + for (i, e) in vec91.into_iter().enumerate() { + let base = result91 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let super::super::super::super::duckdb::extension::types::Columndef { + name: name87, + logical: logical87, + } = e; + let vec88 = (name87.into_bytes()).into_boxed_slice(); + let ptr88 = vec88.as_ptr().cast::(); + let len88 = vec88.len(); + ::core::mem::forget(vec88); + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len88; + *base.add(0).cast::<*mut u8>() = ptr88.cast_mut(); + use super::super::super::super::duckdb::extension::types::Logicaltype as V90; + match logical87 { + V90::Boolean => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + } + V90::Int64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + } + V90::Uint64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + } + V90::Float64 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + } + V90::Text => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + } + V90::Blob => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (5i32) as u8; + } + V90::Int32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (6i32) as u8; + } + V90::Timestamp => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (7i32) as u8; + } + V90::Int8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (8i32) as u8; + } + V90::Int16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (9i32) as u8; + } + V90::Uint8 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (10i32) as u8; + } + V90::Uint16 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (11i32) as u8; + } + V90::Uint32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (12i32) as u8; + } + V90::Float32 => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (13i32) as u8; + } + V90::Date => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (14i32) as u8; + } + V90::Time => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (15i32) as u8; + } + V90::Timestamptz => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (16i32) as u8; + } + V90::Decimal => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (17i32) as u8; + } + V90::Interval => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (18i32) as u8; + } + V90::Uuid => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (19i32) as u8; + } + V90::Complex(e) => { + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = (20i32) as u8; + let vec89 = (e.into_bytes()).into_boxed_slice(); + let ptr89 = vec89.as_ptr().cast::(); + let len89 = vec89.len(); + ::core::mem::forget(vec89); + *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::() = len89; + *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr89.cast_mut(); + } + } + } + } + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len91; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result91; } - }; - let result5 = T::call_cast(arg0 as u32, v4); - let ptr6 = (&raw mut _RET_AREA.0).cast::(); - match result5 { - Ok(e) => { - *ptr6.add(0).cast::() = (0i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckvalue as V15; + Err(e) => { + *ptr85.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V97; match e { - V15::Null => { - *ptr6.add(8).cast::() = (0i32) as u8; - } - V15::Boolean(e) => { - *ptr6.add(8).cast::() = (1i32) as u8; - *ptr6.add(16).cast::() = (match e { - true => 1, - false => 0, - }) as u8; - } - V15::Int64(e) => { - *ptr6.add(8).cast::() = (2i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i64(e); - } - V15::Uint64(e) => { - *ptr6.add(8).cast::() = (3i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i64(e); - } - V15::Float64(e) => { - *ptr6.add(8).cast::() = (4i32) as u8; - *ptr6.add(16).cast::() = _rt::as_f64(e); - } - V15::Text(e) => { - *ptr6.add(8).cast::() = (5i32) as u8; - let vec7 = (e.into_bytes()).into_boxed_slice(); - let ptr7 = vec7.as_ptr().cast::(); - let len7 = vec7.len(); - ::core::mem::forget(vec7); - *ptr6 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len7; - *ptr6.add(16).cast::<*mut u8>() = ptr7.cast_mut(); - } - V15::Blob(e) => { - *ptr6.add(8).cast::() = (6i32) as u8; - let vec8 = (e).into_boxed_slice(); - let ptr8 = vec8.as_ptr().cast::(); - let len8 = vec8.len(); - ::core::mem::forget(vec8); - *ptr6 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::() = len8; - *ptr6.add(16).cast::<*mut u8>() = ptr8.cast_mut(); - } - V15::Int32(e) => { - *ptr6.add(8).cast::() = (7i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i32(e); - } - V15::Timestamp(e) => { - *ptr6.add(8).cast::() = (8i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i64(e); - } - V15::Int8(e) => { - *ptr6.add(8).cast::() = (9i32) as u8; - *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u8; + V97::Invalidargument(e) => { + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec92 = (e.into_bytes()).into_boxed_slice(); + let ptr92 = vec92.as_ptr().cast::(); + let len92 = vec92.len(); + ::core::mem::forget(vec92); + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len92; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr92.cast_mut(); } - V15::Int16(e) => { - *ptr6.add(8).cast::() = (10i32) as u8; - *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u16; + V97::Unsupported(e) => { + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec93 = (e.into_bytes()).into_boxed_slice(); + let ptr93 = vec93.as_ptr().cast::(); + let len93 = vec93.len(); + ::core::mem::forget(vec93); + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len93; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr93.cast_mut(); } - V15::Uint8(e) => { - *ptr6.add(8).cast::() = (11i32) as u8; - *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u8; + V97::Invalidstate(e) => { + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec94 = (e.into_bytes()).into_boxed_slice(); + let ptr94 = vec94.as_ptr().cast::(); + let len94 = vec94.len(); + ::core::mem::forget(vec94); + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len94; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr94.cast_mut(); } - V15::Uint16(e) => { - *ptr6.add(8).cast::() = (12i32) as u8; - *ptr6.add(16).cast::() = (_rt::as_i32(e)) as u16; + V97::Io(e) => { + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec95 = (e.into_bytes()).into_boxed_slice(); + let ptr95 = vec95.as_ptr().cast::(); + let len95 = vec95.len(); + ::core::mem::forget(vec95); + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len95; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr95.cast_mut(); } - V15::Uint32(e) => { - *ptr6.add(8).cast::() = (13i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i32(e); + V97::Internal(e) => { + *ptr85 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec96 = (e.into_bytes()).into_boxed_slice(); + let ptr96 = vec96.as_ptr().cast::(); + let len96 = vec96.len(); + ::core::mem::forget(vec96); + *ptr85 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len96; + *ptr85 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr96.cast_mut(); } - V15::Float32(e) => { - *ptr6.add(8).cast::() = (14i32) as u8; - *ptr6.add(16).cast::() = _rt::as_f32(e); + } + } + }; + ptr85 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_ts_open_filtered(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base8 = l1; + let len8 = l2; + for i in 0..len8 { + let base = base8 + .add(i * (5 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l3, l4, 1); + let l5 = i32::from( + *base + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(), + ); + match l5 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => {} + 6 => {} + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + _ => { + let l6 = *base + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l7 = *base + .add(4 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + } } - V15::Date(e) => { - *ptr6.add(8).cast::() = (15i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i32(e); + } + _rt::cabi_dealloc( + base8, + len8 * (5 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l9 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l9 { + 0 => { + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l10, l11, 1); } - V15::Time(e) => { - *ptr6.add(8).cast::() = (16i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i64(e); + 1 => { + let l12 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l13 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l12, l13, 1); } - V15::Timestamptz(e) => { - *ptr6.add(8).cast::() = (17i32) as u8; - *ptr6.add(16).cast::() = _rt::as_i64(e); + 2 => { + let l14 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l15 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l14, l15, 1); } - V15::Decimal(e) => { - *ptr6.add(8).cast::() = (18i32) as u8; - let super::super::super::super::duckdb::extension::types::Decimalvalue { - lower: lower9, - upper: upper9, - width: width9, - scale: scale9, - } = e; - *ptr6.add(16).cast::() = _rt::as_i64(lower9); - *ptr6.add(24).cast::() = _rt::as_i64(upper9); - *ptr6.add(32).cast::() = (_rt::as_i32(width9)) as u8; - *ptr6.add(33).cast::() = (_rt::as_i32(scale9)) as u8; + 3 => { + let l16 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l17 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l16, l17, 1); } - V15::Interval(e) => { - *ptr6.add(8).cast::() = (19i32) as u8; - let super::super::super::super::duckdb::extension::types::Intervalvalue { - months: months10, - days: days10, - micros: micros10, - } = e; - *ptr6.add(16).cast::() = _rt::as_i32(months10); - *ptr6.add(20).cast::() = _rt::as_i32(days10); - *ptr6.add(24).cast::() = _rt::as_i64(micros10); + _ => { + let l18 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); } - V15::Uuid(e) => { - *ptr6.add(8).cast::() = (20i32) as u8; - let super::super::super::super::duckdb::extension::types::Uuidvalue { - hi: hi11, - lo: lo11, - } = e; - *ptr6.add(16).cast::() = _rt::as_i64(hi11); - *ptr6.add(24).cast::() = _rt::as_i64(lo11); + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_ts_next_cabi( + arg0: i32, + arg1: i32, + arg2: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::ts_next(arg0 as u32, arg1 as u32, arg2 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + let vec12 = e; + let len12 = vec12.len(); + let layout12 = _rt::alloc::Layout::from_size_align_unchecked( + vec12.len() * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + let result12 = if layout12.size() != 0 { + let ptr = _rt::alloc::alloc(layout12).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout12); } - V15::Complex(e) => { - *ptr6.add(8).cast::() = (21i32) as u8; - let super::super::super::super::duckdb::extension::types::Complexvalue { - type_expr: type_expr12, - json: json12, - } = e; - let vec13 = (type_expr12.into_bytes()).into_boxed_slice(); + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec12.into_iter().enumerate() { + let base = result12 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let vec11 = e; + let len11 = vec11.len(); + let layout11 = _rt::alloc::Layout::from_size_align_unchecked( + vec11.len() + * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + let result11 = if layout11.size() != 0 { + let ptr = _rt::alloc::alloc(layout11).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout11); + } + ptr + } else { + ::core::ptr::null_mut() + }; + for (i, e) in vec11.into_iter().enumerate() { + let base = result11 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + use super::super::super::super::duckdb::extension::types::Duckvalue as V10; + match e { + V10::Null => { + *base.add(0).cast::() = (0i32) as u8; + } + V10::Boolean(e) => { + *base.add(0).cast::() = (1i32) as u8; + *base.add(8).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + V10::Int64(e) => { + *base.add(0).cast::() = (2i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Uint64(e) => { + *base.add(0).cast::() = (3i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Float64(e) => { + *base.add(0).cast::() = (4i32) as u8; + *base.add(8).cast::() = _rt::as_f64(e); + } + V10::Text(e) => { + *base.add(0).cast::() = (5i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *base.add(8).cast::<*mut u8>() = ptr2.cast_mut(); + } + V10::Blob(e) => { + *base.add(0).cast::() = (6i32) as u8; + let vec3 = (e).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *base.add(8).cast::<*mut u8>() = ptr3.cast_mut(); + } + V10::Int32(e) => { + *base.add(0).cast::() = (7i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Timestamp(e) => { + *base.add(0).cast::() = (8i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Int8(e) => { + *base.add(0).cast::() = (9i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V10::Int16(e) => { + *base.add(0).cast::() = (10i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V10::Uint8(e) => { + *base.add(0).cast::() = (11i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u8; + } + V10::Uint16(e) => { + *base.add(0).cast::() = (12i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + V10::Uint32(e) => { + *base.add(0).cast::() = (13i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Float32(e) => { + *base.add(0).cast::() = (14i32) as u8; + *base.add(8).cast::() = _rt::as_f32(e); + } + V10::Date(e) => { + *base.add(0).cast::() = (15i32) as u8; + *base.add(8).cast::() = _rt::as_i32(e); + } + V10::Time(e) => { + *base.add(0).cast::() = (16i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Timestamptz(e) => { + *base.add(0).cast::() = (17i32) as u8; + *base.add(8).cast::() = _rt::as_i64(e); + } + V10::Decimal(e) => { + *base.add(0).cast::() = (18i32) as u8; + let super::super::super::super::duckdb::extension::types::Decimalvalue { + lower: lower4, + upper: upper4, + width: width4, + scale: scale4, + } = e; + *base.add(8).cast::() = _rt::as_i64(lower4); + *base.add(16).cast::() = _rt::as_i64(upper4); + *base.add(24).cast::() = (_rt::as_i32(width4)) as u8; + *base.add(25).cast::() = (_rt::as_i32(scale4)) as u8; + } + V10::Interval(e) => { + *base.add(0).cast::() = (19i32) as u8; + let super::super::super::super::duckdb::extension::types::Intervalvalue { + months: months5, + days: days5, + micros: micros5, + } = e; + *base.add(8).cast::() = _rt::as_i32(months5); + *base.add(12).cast::() = _rt::as_i32(days5); + *base.add(16).cast::() = _rt::as_i64(micros5); + } + V10::Uuid(e) => { + *base.add(0).cast::() = (20i32) as u8; + let super::super::super::super::duckdb::extension::types::Uuidvalue { + hi: hi6, + lo: lo6, + } = e; + *base.add(8).cast::() = _rt::as_i64(hi6); + *base.add(16).cast::() = _rt::as_i64(lo6); + } + V10::Complex(e) => { + *base.add(0).cast::() = (21i32) as u8; + let super::super::super::super::duckdb::extension::types::Complexvalue { + type_expr: type_expr7, + json: json7, + } = e; + let vec8 = (type_expr7.into_bytes()).into_boxed_slice(); + let ptr8 = vec8.as_ptr().cast::(); + let len8 = vec8.len(); + ::core::mem::forget(vec8); + *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::() = len8; + *base.add(8).cast::<*mut u8>() = ptr8.cast_mut(); + let vec9 = (json7.into_bytes()).into_boxed_slice(); + let ptr9 = vec9.as_ptr().cast::(); + let len9 = vec9.len(); + ::core::mem::forget(vec9); + *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len9; + *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr9.cast_mut(); + } + } + } + } + *base + .add(::core::mem::size_of::<*const u8>()) + .cast::() = len11; + *base.add(0).cast::<*mut u8>() = result11; + } + } + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::() = len12; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = result12; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V18; + match e { + V18::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec13 = (e.into_bytes()).into_boxed_slice(); let ptr13 = vec13.as_ptr().cast::(); let len13 = vec13.len(); ::core::mem::forget(vec13); - *ptr6 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len13; - *ptr6.add(16).cast::<*mut u8>() = ptr13.cast_mut(); - let vec14 = (json12.into_bytes()).into_boxed_slice(); + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr13.cast_mut(); + } + V18::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec14 = (e.into_bytes()).into_boxed_slice(); let ptr14 = vec14.as_ptr().cast::(); let len14 = vec14.len(); ::core::mem::forget(vec14); - *ptr6 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len14; - *ptr6 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>() = ptr14.cast_mut(); } - } - } - Err(e) => { - *ptr6.add(0).cast::() = (1i32) as u8; - use super::super::super::super::duckdb::extension::types::Duckerror as V21; - match e { - V21::Invalidargument(e) => { - *ptr6.add(8).cast::() = (0i32) as u8; + V18::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec15 = (e.into_bytes()).into_boxed_slice(); + let ptr15 = vec15.as_ptr().cast::(); + let len15 = vec15.len(); + ::core::mem::forget(vec15); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len15; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr15.cast_mut(); + } + V18::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; let vec16 = (e.into_bytes()).into_boxed_slice(); let ptr16 = vec16.as_ptr().cast::(); let len16 = vec16.len(); ::core::mem::forget(vec16); - *ptr6 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::() = len16; - *ptr6 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>() = ptr16.cast_mut(); } - V21::Unsupported(e) => { - *ptr6.add(8).cast::() = (1i32) as u8; - let vec17 = (e.into_bytes()).into_boxed_slice(); - let ptr17 = vec17.as_ptr().cast::(); - let len17 = vec17.len(); - ::core::mem::forget(vec17); - *ptr6 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len17; - *ptr6 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr17.cast_mut(); + V18::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec17 = (e.into_bytes()).into_boxed_slice(); + let ptr17 = vec17.as_ptr().cast::(); + let len17 = vec17.len(); + ::core::mem::forget(vec17); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len17; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr17.cast_mut(); + } + } + } + }; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_ts_next(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => { + let l1 = *arg0 + .add(::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base16 = l1; + let len16 = l2; + for i in 0..len16 { + let base = base16 + .add(i * (2 * ::core::mem::size_of::<*const u8>())); + { + let l3 = *base.add(0).cast::<*mut u8>(); + let l4 = *base + .add(::core::mem::size_of::<*const u8>()) + .cast::(); + let base15 = l3; + let len15 = l4; + for i in 0..len15 { + let base = base15 + .add(i * (24 + 2 * ::core::mem::size_of::<*const u8>())); + { + let l5 = i32::from(*base.add(0).cast::()); + match l5 { + 0 => {} + 1 => {} + 2 => {} + 3 => {} + 4 => {} + 5 => { + let l6 = *base.add(8).cast::<*mut u8>(); + let l7 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l6, l7, 1); + } + 6 => { + let l8 = *base.add(8).cast::<*mut u8>(); + let l9 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + let base10 = l8; + let len10 = l9; + _rt::cabi_dealloc(base10, len10 * 1, 1); + } + 7 => {} + 8 => {} + 9 => {} + 10 => {} + 11 => {} + 12 => {} + 13 => {} + 14 => {} + 15 => {} + 16 => {} + 17 => {} + 18 => {} + 19 => {} + 20 => {} + _ => { + let l11 = *base.add(8).cast::<*mut u8>(); + let l12 = *base + .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l11, l12, 1); + let l13 = *base + .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l14 = *base + .add(8 + 3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + } + } + _rt::cabi_dealloc( + base15, + len15 * (24 + 2 * ::core::mem::size_of::<*const u8>()), + 8, + ); + } + } + _rt::cabi_dealloc( + base16, + len16 * (2 * ::core::mem::size_of::<*const u8>()), + ::core::mem::size_of::<*const u8>(), + ); + } + _ => { + let l17 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l17 { + 0 => { + let l18 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l19 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l18, l19, 1); + } + 1 => { + let l20 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l21 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l20, l21, 1); + } + 2 => { + let l22 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l23 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l22, l23, 1); + } + 3 => { + let l24 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l25 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l24, l25, 1); + } + _ => { + let l26 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>(); + let l27 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::(); + _rt::cabi_dealloc(l26, l27, 1); + } + } + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_ts_close_cabi( + arg0: i32, + arg1: i32, + ) -> *mut u8 { + #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); + let result0 = T::ts_close(arg0 as u32, arg1 as u32); + let ptr1 = (&raw mut _RET_AREA.0).cast::(); + match result0 { + Ok(e) => { + *ptr1.add(0).cast::() = (0i32) as u8; + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + Err(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + use super::super::super::super::duckdb::extension::types::Duckerror as V7; + match e { + V7::Invalidargument(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (0i32) as u8; + let vec2 = (e.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len2; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr2.cast_mut(); + } + V7::Unsupported(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len3; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr3.cast_mut(); } - V21::Invalidstate(e) => { - *ptr6.add(8).cast::() = (2i32) as u8; - let vec18 = (e.into_bytes()).into_boxed_slice(); - let ptr18 = vec18.as_ptr().cast::(); - let len18 = vec18.len(); - ::core::mem::forget(vec18); - *ptr6 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len18; - *ptr6 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr18.cast_mut(); + V7::Invalidstate(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (2i32) as u8; + let vec4 = (e.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len4; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr4.cast_mut(); } - V21::Io(e) => { - *ptr6.add(8).cast::() = (3i32) as u8; - let vec19 = (e.into_bytes()).into_boxed_slice(); - let ptr19 = vec19.as_ptr().cast::(); - let len19 = vec19.len(); - ::core::mem::forget(vec19); - *ptr6 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len19; - *ptr6 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr19.cast_mut(); + V7::Io(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (3i32) as u8; + let vec5 = (e.into_bytes()).into_boxed_slice(); + let ptr5 = vec5.as_ptr().cast::(); + let len5 = vec5.len(); + ::core::mem::forget(vec5); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len5; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr5.cast_mut(); } - V21::Internal(e) => { - *ptr6.add(8).cast::() = (4i32) as u8; - let vec20 = (e.into_bytes()).into_boxed_slice(); - let ptr20 = vec20.as_ptr().cast::(); - let len20 = vec20.len(); - ::core::mem::forget(vec20); - *ptr6 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::() = len20; - *ptr6 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>() = ptr20.cast_mut(); + V7::Internal(e) => { + *ptr1 + .add(::core::mem::size_of::<*const u8>()) + .cast::() = (4i32) as u8; + let vec6 = (e.into_bytes()).into_boxed_slice(); + let ptr6 = vec6.as_ptr().cast::(); + let len6 = vec6.len(); + ::core::mem::forget(vec6); + *ptr1 + .add(3 * ::core::mem::size_of::<*const u8>()) + .cast::() = len6; + *ptr1 + .add(2 * ::core::mem::size_of::<*const u8>()) + .cast::<*mut u8>() = ptr6.cast_mut(); } } } }; - ptr6 + ptr1 } #[doc(hidden)] #[allow(non_snake_case)] - pub unsafe fn __post_return_call_cast(arg0: *mut u8) { + pub unsafe fn __post_return_ts_close(arg0: *mut u8) { let l0 = i32::from(*arg0.add(0).cast::()); match l0 { - 0 => { - let l1 = i32::from(*arg0.add(8).cast::()); - match l1 { - 0 => {} - 1 => {} - 2 => {} - 3 => {} - 4 => {} - 5 => { - let l2 = *arg0.add(16).cast::<*mut u8>(); - let l3 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l2, l3, 1); - } - 6 => { - let l4 = *arg0.add(16).cast::<*mut u8>(); - let l5 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - let base6 = l4; - let len6 = l5; - _rt::cabi_dealloc(base6, len6 * 1, 1); - } - 7 => {} - 8 => {} - 9 => {} - 10 => {} - 11 => {} - 12 => {} - 13 => {} - 14 => {} - 15 => {} - 16 => {} - 17 => {} - 18 => {} - 19 => {} - 20 => {} - _ => { - let l7 = *arg0.add(16).cast::<*mut u8>(); - let l8 = *arg0 - .add(16 + 1 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l7, l8, 1); - let l9 = *arg0 - .add(16 + 2 * ::core::mem::size_of::<*const u8>()) - .cast::<*mut u8>(); - let l10 = *arg0 - .add(16 + 3 * ::core::mem::size_of::<*const u8>()) - .cast::(); - _rt::cabi_dealloc(l9, l10, 1); - } - } - } + 0 => {} _ => { - let l11 = i32::from(*arg0.add(8).cast::()); - match l11 { + let l1 = i32::from( + *arg0.add(::core::mem::size_of::<*const u8>()).cast::(), + ); + match l1 { 0 => { - let l12 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l2 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l13 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l3 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l12, l13, 1); + _rt::cabi_dealloc(l2, l3, 1); } 1 => { - let l14 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l4 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l15 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l5 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l14, l15, 1); + _rt::cabi_dealloc(l4, l5, 1); } 2 => { - let l16 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l6 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l17 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l7 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l16, l17, 1); + _rt::cabi_dealloc(l6, l7, 1); } 3 => { - let l18 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l8 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l19 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l9 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l18, l19, 1); + _rt::cabi_dealloc(l8, l9, 1); } _ => { - let l20 = *arg0 - .add(8 + 1 * ::core::mem::size_of::<*const u8>()) + let l10 = *arg0 + .add(2 * ::core::mem::size_of::<*const u8>()) .cast::<*mut u8>(); - let l21 = *arg0 - .add(8 + 2 * ::core::mem::size_of::<*const u8>()) + let l11 = *arg0 + .add(3 * ::core::mem::size_of::<*const u8>()) .cast::(); - _rt::cabi_dealloc(l20, l21, 1); + _rt::cabi_dealloc(l10, l11, 1); } } } } } pub trait Guest { - fn call_scalar( + /// Enumerate the filterable streaming table functions declared so far. + fn filterable_table_list() -> _rt::Vec; + /// Open a streaming cursor for the registered table function `handle` with the + /// bound `args`, a `projection` (emitted column indices; empty = all), and the + /// conjunctive pushed-down `filters`. + fn ts_open_filtered( handle: u32, args: _rt::Vec, - ctx: Invokeinfo, - ) -> Result; - /// Batched scalar dispatch: one call per DataChunk (<= 2048 rows) instead of - /// one per row, amortizing the WIT boundary crossing. `rows` is the chunk's - /// arguments (one inner list per row); `ctx.rowindex` is the first row's index - /// (the i-th row is ctx.rowindex + i). Returns one result value per row, in - /// order. Semantically identical to calling call-scalar per row. - fn call_scalar_batch( - handle: u32, - rows: Rowbatch, - ctx: Invokeinfo, - ) -> Result<_rt::Vec, Duckerror>; - fn call_table( + projection: _rt::Vec, + filters: _rt::Vec, + ) -> Result; + /// Pull up to `max-rows` from the cursor; an empty resultset signals EOF. + fn ts_next( handle: u32, - args: _rt::Vec, + cursor: u32, + max_rows: u32, ) -> Result; - fn call_aggregate( - handle: u32, - rows: Rowbatch, - ) -> Result; - fn call_pragma( - handle: u32, - args: _rt::Vec, - ) -> Result, Duckerror>; - fn call_cast( - handle: u32, - value: Duckvalue, - ) -> Result; + /// Close the cursor and free its state. + fn ts_close(handle: u32, cursor: u32) -> Result; } #[doc(hidden)] - macro_rules! __export_duckdb_extension_callback_dispatch_2_0_0_cabi { + macro_rules! __export_duckdb_extension_table_stream_host_4_0_0_cabi { ($ty:ident with_types_in $($path_to_types:tt)*) => { const _ : () = { #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-scalar")] unsafe - extern "C" fn export_call_scalar(arg0 : i32, arg1 : * mut u8, - arg2 : usize, arg3 : i32, arg4 : i64, arg5 : i32,) -> * mut u8 { - unsafe { $($path_to_types)*:: _export_call_scalar_cabi::<$ty > - (arg0, arg1, arg2, arg3, arg4, arg5) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-scalar")] - unsafe extern "C" fn _post_return_call_scalar(arg0 : * mut u8,) { - unsafe { $($path_to_types)*:: __post_return_call_scalar::<$ty > - (arg0) } } #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-scalar-batch")] - unsafe extern "C" fn export_call_scalar_batch(arg0 : i32, arg1 : - * mut u8, arg2 : usize, arg3 : i32, arg4 : i64, arg5 : i32,) -> * - mut u8 { unsafe { $($path_to_types)*:: - _export_call_scalar_batch_cabi::<$ty > (arg0, arg1, arg2, arg3, - arg4, arg5) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-scalar-batch")] - unsafe extern "C" fn _post_return_call_scalar_batch(arg0 : * mut - u8,) { unsafe { $($path_to_types)*:: - __post_return_call_scalar_batch::<$ty > (arg0) } } #[unsafe + "duckdb:extension/table-stream-host@4.0.0#filterable-table-list")] + unsafe extern "C" fn export_filterable_table_list() -> * mut u8 { + unsafe { $($path_to_types)*:: + _export_filterable_table_list_cabi::<$ty > () } } #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-table")] unsafe - extern "C" fn export_call_table(arg0 : i32, arg1 : * mut u8, arg2 - : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: - _export_call_table_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe + "cabi_post_duckdb:extension/table-stream-host@4.0.0#filterable-table-list")] + unsafe extern "C" fn _post_return_filterable_table_list(arg0 : * + mut u8,) { unsafe { $($path_to_types)*:: + __post_return_filterable_table_list::<$ty > (arg0) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-table")] - unsafe extern "C" fn _post_return_call_table(arg0 : * mut u8,) { - unsafe { $($path_to_types)*:: __post_return_call_table::<$ty > - (arg0) } } #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-aggregate")] - unsafe extern "C" fn export_call_aggregate(arg0 : i32, arg1 : * - mut u8, arg2 : usize,) -> * mut u8 { unsafe { - $($path_to_types)*:: _export_call_aggregate_cabi::<$ty > (arg0, - arg1, arg2) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-aggregate")] - unsafe extern "C" fn _post_return_call_aggregate(arg0 : * mut + "duckdb:extension/table-stream-host@4.0.0#ts-open-filtered")] + unsafe extern "C" fn export_ts_open_filtered(arg0 : i32, arg1 : * + mut u8, arg2 : usize, arg3 : * mut u8, arg4 : usize, arg5 : * mut + u8, arg6 : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: + _export_ts_open_filtered_cabi::<$ty > (arg0, arg1, arg2, arg3, + arg4, arg5, arg6) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/table-stream-host@4.0.0#ts-open-filtered")] + unsafe extern "C" fn _post_return_ts_open_filtered(arg0 : * mut u8,) { unsafe { $($path_to_types)*:: - __post_return_call_aggregate::<$ty > (arg0) } } #[unsafe + __post_return_ts_open_filtered::<$ty > (arg0) } } #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-pragma")] unsafe - extern "C" fn export_call_pragma(arg0 : i32, arg1 : * mut u8, - arg2 : usize,) -> * mut u8 { unsafe { $($path_to_types)*:: - _export_call_pragma_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe + "duckdb:extension/table-stream-host@4.0.0#ts-next")] unsafe + extern "C" fn export_ts_next(arg0 : i32, arg1 : i32, arg2 : i32,) + -> * mut u8 { unsafe { $($path_to_types)*:: + _export_ts_next_cabi::<$ty > (arg0, arg1, arg2) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-pragma")] - unsafe extern "C" fn _post_return_call_pragma(arg0 : * mut u8,) { - unsafe { $($path_to_types)*:: __post_return_call_pragma::<$ty > + "cabi_post_duckdb:extension/table-stream-host@4.0.0#ts-next")] + unsafe extern "C" fn _post_return_ts_next(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_ts_next::<$ty > (arg0) } } #[unsafe (export_name = - "duckdb:extension/callback-dispatch@2.0.0#call-cast")] unsafe - extern "C" fn export_call_cast(arg0 : i32, arg1 : i32, arg2 : - ::core::mem::MaybeUninit::< u64 >, arg3 : i64, arg4 : - ::core::mem::MaybeUninit::< u64 >, arg5 : usize,) -> * mut u8 { - unsafe { $($path_to_types)*:: _export_call_cast_cabi::<$ty > - (arg0, arg1, arg2, arg3, arg4, arg5) } } #[unsafe (export_name = - "cabi_post_duckdb:extension/callback-dispatch@2.0.0#call-cast")] - unsafe extern "C" fn _post_return_call_cast(arg0 : * mut u8,) { - unsafe { $($path_to_types)*:: __post_return_call_cast::<$ty > + "duckdb:extension/table-stream-host@4.0.0#ts-close")] unsafe + extern "C" fn export_ts_close(arg0 : i32, arg1 : i32,) -> * mut + u8 { unsafe { $($path_to_types)*:: _export_ts_close_cabi::<$ty > + (arg0, arg1) } } #[unsafe (export_name = + "cabi_post_duckdb:extension/table-stream-host@4.0.0#ts-close")] + unsafe extern "C" fn _post_return_ts_close(arg0 : * mut u8,) { + unsafe { $($path_to_types)*:: __post_return_ts_close::<$ty > (arg0) } } }; }; } #[doc(hidden)] - pub(crate) use __export_duckdb_extension_callback_dispatch_2_0_0_cabi; - #[repr(align(8))] + pub(crate) use __export_duckdb_extension_table_stream_host_4_0_0_cabi; + #[cfg_attr(target_pointer_width = "64", repr(align(8)))] + #[cfg_attr(target_pointer_width = "32", repr(align(4)))] struct _RetArea( [::core::mem::MaybeUninit< u8, - >; 40 + 2 * ::core::mem::size_of::<*const u8>()], + >; 4 * ::core::mem::size_of::<*const u8>()], ); static mut _RET_AREA: _RetArea = _RetArea( - [::core::mem::MaybeUninit::uninit(); 40 - + 2 * ::core::mem::size_of::<*const u8>()], + [::core::mem::MaybeUninit::uninit(); 4 + * ::core::mem::size_of::<*const u8>()], ); } } @@ -8178,9 +17016,33 @@ macro_rules! __export_loader_stub_impl { exports::duckdb::component::extension_loader_hooks::__export_duckdb_component_extension_loader_hooks_cabi!($ty with_types_in $($path_to_types_root)*:: exports::duckdb::component::extension_loader_hooks); $($path_to_types_root)*:: - exports::duckdb::extension::callback_dispatch::__export_duckdb_extension_callback_dispatch_2_0_0_cabi!($ty + exports::duckdb::extension::callback_dispatch::__export_duckdb_extension_callback_dispatch_4_0_0_cabi!($ty with_types_in $($path_to_types_root)*:: exports::duckdb::extension::callback_dispatch); $($path_to_types_root)*:: + exports::duckdb::extension::storage_host::__export_duckdb_extension_storage_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: + exports::duckdb::extension::storage_host); $($path_to_types_root)*:: + exports::duckdb::extension::index_host::__export_duckdb_extension_index_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::duckdb::extension::index_host); + $($path_to_types_root)*:: + exports::duckdb::extension::collation_host::__export_duckdb_extension_collation_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: + exports::duckdb::extension::collation_host); $($path_to_types_root)*:: + exports::duckdb::extension::pragma_host::__export_duckdb_extension_pragma_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::duckdb::extension::pragma_host); + $($path_to_types_root)*:: + exports::duckdb::extension::parser_host::__export_duckdb_extension_parser_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::duckdb::extension::parser_host); + $($path_to_types_root)*:: + exports::duckdb::extension::optimizer_host::__export_duckdb_extension_optimizer_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: + exports::duckdb::extension::optimizer_host); $($path_to_types_root)*:: + exports::duckdb::extension::files_host::__export_duckdb_extension_files_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: exports::duckdb::extension::files_host); + $($path_to_types_root)*:: + exports::duckdb::extension::table_stream_host::__export_duckdb_extension_table_stream_host_4_0_0_cabi!($ty + with_types_in $($path_to_types_root)*:: + exports::duckdb::extension::table_stream_host); $($path_to_types_root)*:: exports::tvm::memory::manager::__export_tvm_memory_manager_0_1_0_cabi!($ty with_types_in $($path_to_types_root)*:: exports::tvm::memory::manager); $($path_to_types_root)*:: @@ -8196,17 +17058,17 @@ pub(crate) use __export_loader_stub_impl as export; )] #[doc(hidden)] #[allow(clippy::octal_escapes)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 3877] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xa3\x1d\x01A\x02\x01\ -A\x1a\x01B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04\ -text\0\0\x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05u\ -int8\0\0\x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0bt\ -imestamptz\0\0\x07decimal\0\0\x08interval\0\0\x04uuid\0\0\x07complex\x01s\0\x04\0\ -\x0blogicaltype\x03\0\0\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0c\ -decimalvalue\x03\0\x02\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dinterval\ -value\x03\0\x04\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x06\x01r\x02\x09\ -type-exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x08\x01ks\x01r\x02\x04name\x0a\x07\ -logical\x01\x04\0\x07funcarg\x03\0\x0b\x01n\x05\x0ddeterministic\x0bcommutative\x09\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6681] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\x973\x01A\x02\x01A,\x01\ +B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04text\0\0\ +\x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05uint8\0\0\ +\x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0btimestamp\ +tz\0\0\x07decimal\0\0\x08interval\0\0\x04uuid\0\0\x07complex\x01s\0\x04\0\x0blog\ +icaltype\x03\0\0\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecim\ +alvalue\x03\0\x02\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\ +\x03\0\x04\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x06\x01r\x02\x09type-\ +exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x08\x01ks\x01r\x02\x04name\x0a\x07log\ +ical\x01\x04\0\x07funcarg\x03\0\x0b\x01n\x05\x0ddeterministic\x0bcommutative\x09\ stateless\x0dsideeffecting\x0adeprecated\x04\0\x09funcflags\x03\0\x0d\x01ps\x01r\ \x03\x0bdescription\x0a\x04tags\x0f\x0aattributes\x0e\x04\0\x08funcopts\x03\0\x10\ \x01r\x02\x04names\x07logical\x01\x04\0\x09columndef\x03\0\x12\x01r\x02\x0bdescr\ @@ -8225,63 +17087,127 @@ configerror\x03\0#\x01m\x05\x05trace\x05debug\x04info\x04warn\x05error\x04\0\x08 loglevel\x03\0%\x01r\x02\x03keys\x05values\x04\0\x08logfield\x03\0'\x01m\x07\x06\ scalar\x05table\x09aggregate\x06pragma\x05macro\x07catalog\x0bfile-format\x04\0\x0e\ capabilitykind\x03\0)\x01p*\x01r\x03\x04names\x07version\x0a\x08requires+\x04\0\x0a\ -loadresult\x03\0,\x03\0\x1cduckdb:extension/types@2.0.0\x05\0\x01B\x0a\x01m\x07\x08\ -hot-heap\x0cobject-arena\x0ablob-arena\x0apage-store\x07scratch\x0cdevice-state\x0a\ -code-cache\x04\0\x0bregion-kind\x03\0\0\x01m\x04\x03hot\x04warm\x04cold\x08exter\ -nal\x04\0\x09residency\x03\0\x02\x01r\x03\x09region-id{\x0ageneration{\x06offset\ -y\x04\0\x06handle\x03\0\x04\x01r\x06\x02id{\x0ageneration{\x04kind\x01\x08capaci\ -tyy\x04usedy\x09residency\x03\x04\0\x0bregion-info\x03\0\x06\x01q\x07\x10region-\ -not-found\x01{\0\x0cstale-handle\0\0\x0dout-of-bounds\0\0\x0cnot-resident\0\0\x11\ -allocation-failed\0\0\x0dbacking-store\x01s\0\x06pinned\0\0\x04\0\x09tvm-error\x03\ -\0\x08\x03\0\x16tvm:memory/types@0.1.0\x05\x01\x01B\x02\x01@\x01\x04names\0\x7f\x04\ -\0\x0crequest-load\x01\0\x04\0&duckdb:component/host-extension-loader\x05\x02\x02\ -\x03\0\0\x0blogicaltype\x02\x03\0\0\x09columndef\x02\x03\0\0\x09funcflags\x01B+\x02\ -\x03\x02\x01\x03\x04\0\x0blogicaltype\x03\0\0\x02\x03\x02\x01\x04\x04\0\x09colum\ -ndef\x03\0\x02\x02\x03\x02\x01\x05\x04\0\x09funcflags\x03\0\x04\x01ks\x01r\x02\x04\ -name\x06\x07logical\x01\x04\0\x08func-arg\x03\0\x07\x01ps\x01r\x03\x0bdescriptio\ -n\x06\x04tags\x09\x0aattributes\x05\x04\0\x09func-opts\x03\0\x0a\x01r\x02\x0bdes\ -cription\x06\x04tags\x09\x04\0\x08ext-opts\x03\0\x0c\x01p\x08\x01k\x0b\x01r\x05\x04\ -names\x09arguments\x0e\x07returns\x01\x0fcallback-handley\x07options\x0f\x04\0\x13\ -scalar-registration\x03\0\x10\x01p\x03\x01k\x0d\x01r\x05\x04names\x09arguments\x0e\ -\x07columns\x12\x0fcallback-handley\x07options\x13\x04\0\x12table-registration\x03\ -\0\x14\x01r\x05\x04names\x09arguments\x0e\x07returns\x01\x0fcallback-handley\x07\ -options\x0f\x04\0\x16aggregate-registration\x03\0\x16\x01r\x04\x06schemas\x04nam\ -es\x0aparameters\x09\x0edefinition-sqls\x04\0\x12macro-registration\x03\0\x18\x01\ -r\x02\x0aextensions\x09\x0dfunction-names\x04\0\x1dreplacement-scan-registration\ -\x03\0\x1a\x01r\x02\x04names\x08physicals\x04\0\x19logical-type-registration\x03\ -\0\x1c\x01r\x03\x06sources\x06targets\x0fcallback-handley\x04\0\x11cast-registra\ -tion\x03\0\x1e\x01p\x11\x01p\x15\x01p\x17\x01p\x19\x01p\x1b\x01p\x1d\x01p\x1f\x01\ -r\x07\x07scalars\x20\x06tables!\x0aaggregates\"\x06macros#\x11replacement-scans$\ -\x0dlogical-types%\x05casts&\x04\0\x15pending-registrations\x03\0'\x01@\0\0(\x04\ -\0\x19get-pending-registrations\x01)\x04\0'duckdb:component/extension-loader-hoo\ -ks\x05\x06\x02\x03\0\0\x09duckerror\x02\x03\0\0\x09duckvalue\x02\x03\0\0\x0ainvo\ -keinfo\x02\x03\0\0\x09resultset\x02\x03\0\0\x08rowbatch\x01B\x1c\x02\x03\x02\x01\ -\x07\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x08\x04\0\x09duckvalue\x03\0\x02\ -\x02\x03\x02\x01\x09\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\x0a\x04\0\x09\ -resultset\x03\0\x06\x02\x03\x02\x01\x0b\x04\0\x08rowbatch\x03\0\x08\x01p\x03\x01\ -j\x01\x03\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\x0bcall\ --scalar\x01\x0c\x01j\x01\x0a\x01\x01\x01@\x03\x06handley\x04rows\x09\x03ctx\x05\0\ -\x0d\x04\0\x11call-scalar-batch\x01\x0e\x01j\x01\x07\x01\x01\x01@\x02\x06handley\ -\x04args\x0a\0\x0f\x04\0\x0acall-table\x01\x10\x01@\x02\x06handley\x04rows\x09\0\ -\x0b\x04\0\x0ecall-aggregate\x01\x11\x01k\x03\x01j\x01\x12\x01\x01\x01@\x02\x06h\ -andley\x04args\x0a\0\x13\x04\0\x0bcall-pragma\x01\x14\x01@\x02\x06handley\x05val\ -ue\x03\0\x0b\x04\0\x09call-cast\x01\x15\x04\0(duckdb:extension/callback-dispatch\ -@2.0.0\x05\x0c\x02\x03\0\x01\x0bregion-kind\x02\x03\0\x01\x06handle\x02\x03\0\x01\ -\x0bregion-info\x02\x03\0\x01\x09tvm-error\x01B\x16\x02\x03\x02\x01\x0d\x04\0\x0b\ -region-kind\x03\0\0\x02\x03\x02\x01\x0e\x04\0\x06handle\x03\0\x02\x02\x03\x02\x01\ -\x0f\x04\0\x0bregion-info\x03\0\x04\x02\x03\x02\x01\x10\x04\0\x09tvm-error\x03\0\ -\x06\x01j\x01{\x01\x07\x01@\x02\x04kind\x01\x08capacityy\0\x08\x04\0\x0dcreate-r\ -egion\x01\x09\x01j\0\x01\x07\x01@\x01\x09region-id{\0\x0a\x04\0\x0edestroy-regio\ -n\x01\x0b\x01j\x01\x03\x01\x07\x01@\x02\x09region-id{\x04sizey\0\x0c\x04\0\x05al\ -loc\x01\x0d\x01@\x01\x03ptr\x03\0\x0a\x04\0\x07dealloc\x01\x0e\x01j\x01\x05\x01\x07\ -\x01@\x01\x09region-id{\0\x0f\x04\0\x0fdescribe-region\x01\x10\x04\0\x18tvm:memo\ -ry/manager@0.1.0\x05\x11\x01B\x0b\x02\x03\x02\x01\x0e\x04\0\x06handle\x03\0\0\x02\ -\x03\x02\x01\x10\x04\0\x09tvm-error\x03\0\x02\x01p}\x01j\x01\x04\x01\x03\x01@\x02\ -\x03ptr\x01\x03leny\0\x05\x04\0\x04read\x01\x06\x01j\0\x01\x03\x01@\x02\x03ptr\x01\ -\x04data\x04\0\x07\x04\0\x05write\x01\x08\x04\0\x16tvm:memory/bytes@0.1.0\x05\x12\ -\x04\0\x1educkdb:loader-stub/loader-stub\x04\0\x0b\x11\x01\0\x0bloader-stub\x03\0\ -\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bi\ -ndgen-rust\x060.41.0"; +loadresult\x03\0,\x03\0\x1cduckdb:extension/types@4.0.0\x05\0\x01B\x1d\x01r\x04\x05\ +lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecimalvalue\x03\0\0\x01r\x03\x06m\ +onthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\x03\0\x02\x01r\x02\x02hiw\x02l\ +ow\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\x09type-exprs\x04jsons\x04\0\x0ccomplex\ +value\x03\0\x06\x01p\x7f\x01px\x01pw\x01pu\x01pz\x01p~\x01p|\x01p}\x01p{\x01py\x01\ +pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01p\x0f\x01p\x07\x01q\x15\x07boolean\x01\x08\ +\0\x05int64\x01\x09\0\x06uint64\x01\x0a\0\x07float64\x01\x0b\0\x05int32\x01\x0c\0\ +\x09timestamp\x01\x09\0\x04int8\x01\x0d\0\x05int16\x01\x0e\0\x05uint8\x01\x0f\0\x06\ +uint16\x01\x10\0\x06uint32\x01\x11\0\x07float32\x01\x12\0\x04date\x01\x0c\0\x04t\ +ime\x01\x09\0\x0btimestamptz\x01\x09\0\x07decimal\x01\x13\0\x08interval\x01\x14\0\ +\x04uuid\x01\x15\0\x04text\x01\x16\0\x04blob\x01\x17\0\x07complex\x01\x18\0\x04\0\ +\x06column\x03\0\x19\x01r\x03\x04data\x1a\x08validity\x0f\x04rowsy\x04\0\x06colv\ +ec\x03\0\x1b\x03\0#duckdb:extension/column-types@4.0.0\x05\x01\x01B\x0a\x01m\x07\ +\x08hot-heap\x0cobject-arena\x0ablob-arena\x0apage-store\x07scratch\x0cdevice-st\ +ate\x0acode-cache\x04\0\x0bregion-kind\x03\0\0\x01m\x04\x03hot\x04warm\x04cold\x08\ +external\x04\0\x09residency\x03\0\x02\x01r\x03\x09region-id{\x0ageneration{\x06o\ +ffsety\x04\0\x06handle\x03\0\x04\x01r\x06\x02id{\x0ageneration{\x04kind\x01\x08c\ +apacityy\x04usedy\x09residency\x03\x04\0\x0bregion-info\x03\0\x06\x01q\x07\x10re\ +gion-not-found\x01{\0\x0cstale-handle\0\0\x0dout-of-bounds\0\0\x0cnot-resident\0\ +\0\x11allocation-failed\0\0\x0dbacking-store\x01s\0\x06pinned\0\0\x04\0\x09tvm-e\ +rror\x03\0\x08\x03\0\x16tvm:memory/types@0.1.0\x05\x02\x01B\x02\x01@\x01\x04name\ +s\0\x7f\x04\0\x0crequest-load\x01\0\x04\0&duckdb:component/host-extension-loader\ +\x05\x03\x02\x03\0\0\x0blogicaltype\x02\x03\0\0\x09columndef\x02\x03\0\0\x09func\ +flags\x01B+\x02\x03\x02\x01\x04\x04\0\x0blogicaltype\x03\0\0\x02\x03\x02\x01\x05\ +\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x06\x04\0\x09funcflags\x03\0\x04\x01\ +ks\x01r\x02\x04name\x06\x07logical\x01\x04\0\x08func-arg\x03\0\x07\x01ps\x01r\x03\ +\x0bdescription\x06\x04tags\x09\x0aattributes\x05\x04\0\x09func-opts\x03\0\x0a\x01\ +r\x02\x0bdescription\x06\x04tags\x09\x04\0\x08ext-opts\x03\0\x0c\x01p\x08\x01k\x0b\ +\x01r\x05\x04names\x09arguments\x0e\x07returns\x01\x0fcallback-handley\x07option\ +s\x0f\x04\0\x13scalar-registration\x03\0\x10\x01p\x03\x01k\x0d\x01r\x05\x04names\ +\x09arguments\x0e\x07columns\x12\x0fcallback-handley\x07options\x13\x04\0\x12tab\ +le-registration\x03\0\x14\x01r\x05\x04names\x09arguments\x0e\x07returns\x01\x0fc\ +allback-handley\x07options\x0f\x04\0\x16aggregate-registration\x03\0\x16\x01r\x04\ +\x06schemas\x04names\x0aparameters\x09\x0edefinition-sqls\x04\0\x12macro-registr\ +ation\x03\0\x18\x01r\x02\x0aextensions\x09\x0dfunction-names\x04\0\x1dreplacemen\ +t-scan-registration\x03\0\x1a\x01r\x02\x04names\x08physicals\x04\0\x19logical-ty\ +pe-registration\x03\0\x1c\x01r\x03\x06sources\x06targets\x0fcallback-handley\x04\ +\0\x11cast-registration\x03\0\x1e\x01p\x11\x01p\x15\x01p\x17\x01p\x19\x01p\x1b\x01\ +p\x1d\x01p\x1f\x01r\x07\x07scalars\x20\x06tables!\x0aaggregates\"\x06macros#\x11\ +replacement-scans$\x0dlogical-types%\x05casts&\x04\0\x15pending-registrations\x03\ +\0'\x01@\0\0(\x04\0\x19get-pending-registrations\x01)\x04\0'duckdb:component/ext\ +ension-loader-hooks\x05\x07\x02\x03\0\0\x09duckerror\x02\x03\0\0\x09duckvalue\x02\ +\x03\0\0\x0ainvokeinfo\x02\x03\0\0\x09resultset\x02\x03\0\x01\x06colvec\x01B\x1f\ +\x02\x03\x02\x01\x08\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x09\x04\0\x09duc\ +kvalue\x03\0\x02\x02\x03\x02\x01\x0a\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\ +\x0b\x04\0\x09resultset\x03\0\x06\x02\x03\x02\x01\x0c\x04\0\x06colvec\x03\0\x08\x01\ +p\x09\x01j\x01\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\ +\x15call-scalar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06handley\x04ar\ +gs\x0a\0\x0d\x04\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03arg\x09\0\ +\x0b\x04\0\x0dcall-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04args\x10\x03\ +ctx\x05\0\x0d\x04\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\x06hand\ +ley\x04args\x10\0\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\x01\x01\ +@\x02\x06handley\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\x06hand\ +ley\x05value\x03\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension/callbac\ +k-dispatch@4.0.0\x05\x0d\x01B'\x02\x03\x02\x01\x08\x04\0\x09duckerror\x03\0\0\x02\ +\x03\x02\x01\x05\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09duckv\ +alue\x03\0\x04\x01p\x05\x01p\x06\x04\0\x09resultset\x03\0\x07\x01m\x08\x02eq\x02\ +ne\x02lt\x02le\x02gt\x02ge\x07is-null\x0bis-not-null\x04\0\x0acompare-op\x03\0\x09\ +\x01r\x03\x06columny\x02op\x0a\x05value\x05\x04\0\x0bscan-filter\x03\0\x0b\x01py\ +\x01p\x0c\x01kw\x01r\x04\x05tables\x0aprojection\x0d\x07filters\x0e\x05limit\x0f\ +\x04\0\x0cscan-request\x03\0\x10\x01ps\x01@\0\0\x12\x04\0\x12storage-list-types\x01\ +\x13\x01j\x01y\x01\x01\x01@\x01\x03dsns\0\x14\x04\0\x0estorage-attach\x01\x15\x01\ +j\x01\x12\x01\x01\x01@\x01\x07catalogy\0\x16\x04\0\x13storage-list-tables\x01\x17\ +\x01p\x03\x01j\x01\x18\x01\x01\x01@\x02\x07catalogy\x05tables\0\x19\x04\0\x15sto\ +rage-table-columns\x01\x1a\x01@\x02\x07catalogy\x07request\x11\0\x14\x04\0\x11st\ +orage-scan-open\x01\x1b\x01j\x01\x08\x01\x01\x01@\x02\x04scany\x08max-rowsy\0\x1c\ +\x04\0\x11storage-scan-next\x01\x1d\x01j\x01\x7f\x01\x01\x01@\x01\x04scany\0\x1e\ +\x04\0\x12storage-scan-close\x01\x1f\x04\0#duckdb:extension/storage-host@4.0.0\x05\ +\x0e\x01B\x17\x02\x03\x02\x01\x08\x04\0\x09duckerror\x03\0\0\x01r\x02\x05rowidx\x08\ +distancev\x04\0\x09index-hit\x03\0\x02\x01ps\x01@\0\0\x04\x04\0\x0findex-type-li\ +st\x01\x05\x01j\x01y\x01\x01\x01@\x03\x09type-names\x0aindex-names\x04dimsy\0\x06\ +\x04\0\x0cindex-create\x01\x07\x01px\x01pv\x01p\x09\x01j\0\x01\x01\x01@\x03\x06h\ +andley\x06rowids\x08\x07vectors\x0a\0\x0b\x04\0\x0cindex-append\x01\x0c\x01@\x01\ +\x06handley\0\x0b\x04\0\x0bindex-build\x01\x0d\x01p\x03\x01j\x01\x0e\x01\x01\x01\ +@\x03\x06handley\x05query\x09\x01ky\0\x0f\x04\0\x0cindex-search\x01\x10\x04\0\x0a\ +index-drop\x01\x0d\x04\0!duckdb:extension/index-host@4.0.0\x05\x0f\x01B\x05\x01r\ +\x03\x04names\x10transform-scalars\x0acombinable\x7f\x04\0\x0ecollation-spec\x03\ +\0\0\x01p\x01\x01@\0\0\x02\x04\0\x0ecollation-list\x01\x03\x04\0%duckdb:extensio\ +n/collation-host@4.0.0\x05\x10\x01B\x05\x01r\x02\x04names\x0fcallback-handley\x04\ +\0\x0bpragma-spec\x03\0\0\x01p\x01\x01@\0\0\x02\x04\0\x0bpragma-list\x01\x03\x04\ +\0\"duckdb:extension/pragma-host@4.0.0\x05\x11\x01B\x0b\x02\x03\x02\x01\x08\x04\0\ +\x09duckerror\x03\0\0\x01r\x02\x04names\x0fcallback-handley\x04\0\x0bparser-spec\ +\x03\0\x02\x01p\x03\x01@\0\0\x04\x04\0\x0bparser-list\x01\x05\x01ks\x01j\x01\x06\ +\x01\x01\x01@\x02\x06handley\x05querys\0\x07\x04\0\x0acall-parse\x01\x08\x04\0\"\ +duckdb:extension/parser-host@4.0.0\x05\x12\x01B\x0b\x02\x03\x02\x01\x08\x04\0\x09\ +duckerror\x03\0\0\x01r\x02\x09rule-names\x0fcallback-handley\x04\0\x0eoptimizer-\ +spec\x03\0\x02\x01p\x03\x01@\0\0\x04\x04\0\x0eoptimizer-list\x01\x05\x01ks\x01j\x01\ +\x06\x01\x01\x01@\x02\x06handley\x09plan-jsons\0\x07\x04\0\x0dcall-optimize\x01\x08\ +\x04\0%duckdb:extension/optimizer-host@4.0.0\x05\x13\x01B\x0c\x01r\x02\x06handle\ +y\x04sizew\x04\0\x10file-open-result\x03\0\0\x01j\x01\x01\x01s\x01@\x01\x03urls\0\ +\x02\x04\0\x09file-open\x01\x03\x01p}\x01j\x01\x04\x01s\x01@\x03\x06handley\x06o\ +ffsetw\x03leny\0\x05\x04\0\x09file-read\x01\x06\x01j\0\x01s\x01@\x01\x06handley\0\ +\x07\x04\0\x0afile-close\x01\x08\x04\0!duckdb:extension/files-host@4.0.0\x05\x14\ +\x01B\x20\x02\x03\x02\x01\x08\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x05\x04\ +\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\x04\0\x09duckvalue\x03\0\x04\x01p\x05\ +\x01p\x06\x04\0\x09resultset\x03\0\x07\x01p\x03\x01r\x04\x04names\x09arguments\x09\ +\x07columns\x09\x06handley\x04\0\x10filterable-table\x03\0\x0a\x01m\x09\x02eq\x02\ +ne\x02lt\x02le\x02gt\x02ge\x05is-in\x07is-null\x0bis-not-null\x04\0\x0cts-filter\ +-op\x03\0\x0c\x01r\x03\x06columny\x02op\x0d\x06values\x06\x04\0\x09ts-filter\x03\ +\0\x0e\x01r\x02\x06cursory\x07columns\x09\x04\0\x0ets-open-result\x03\0\x10\x01p\ +\x0b\x01@\0\0\x12\x04\0\x15filterable-table-list\x01\x13\x01py\x01p\x0f\x01j\x01\ +\x11\x01\x01\x01@\x04\x06handley\x04args\x06\x0aprojection\x14\x07filters\x15\0\x16\ +\x04\0\x10ts-open-filtered\x01\x17\x01j\x01\x08\x01\x01\x01@\x03\x06handley\x06c\ +ursory\x08max-rowsy\0\x18\x04\0\x07ts-next\x01\x19\x01j\x01\x7f\x01\x01\x01@\x02\ +\x06handley\x06cursory\0\x1a\x04\0\x08ts-close\x01\x1b\x04\0(duckdb:extension/ta\ +ble-stream-host@4.0.0\x05\x15\x02\x03\0\x02\x0bregion-kind\x02\x03\0\x02\x06hand\ +le\x02\x03\0\x02\x0bregion-info\x02\x03\0\x02\x09tvm-error\x01B\x16\x02\x03\x02\x01\ +\x16\x04\0\x0bregion-kind\x03\0\0\x02\x03\x02\x01\x17\x04\0\x06handle\x03\0\x02\x02\ +\x03\x02\x01\x18\x04\0\x0bregion-info\x03\0\x04\x02\x03\x02\x01\x19\x04\0\x09tvm\ +-error\x03\0\x06\x01j\x01{\x01\x07\x01@\x02\x04kind\x01\x08capacityy\0\x08\x04\0\ +\x0dcreate-region\x01\x09\x01j\0\x01\x07\x01@\x01\x09region-id{\0\x0a\x04\0\x0ed\ +estroy-region\x01\x0b\x01j\x01\x03\x01\x07\x01@\x02\x09region-id{\x04sizey\0\x0c\ +\x04\0\x05alloc\x01\x0d\x01@\x01\x03ptr\x03\0\x0a\x04\0\x07dealloc\x01\x0e\x01j\x01\ +\x05\x01\x07\x01@\x01\x09region-id{\0\x0f\x04\0\x0fdescribe-region\x01\x10\x04\0\ +\x18tvm:memory/manager@0.1.0\x05\x1a\x01B\x0b\x02\x03\x02\x01\x17\x04\0\x06handl\ +e\x03\0\0\x02\x03\x02\x01\x19\x04\0\x09tvm-error\x03\0\x02\x01p}\x01j\x01\x04\x01\ +\x03\x01@\x02\x03ptr\x01\x03leny\0\x05\x04\0\x04read\x01\x06\x01j\0\x01\x03\x01@\ +\x02\x03ptr\x01\x04data\x04\0\x07\x04\0\x05write\x01\x08\x04\0\x16tvm:memory/byt\ +es@0.1.0\x05\x1b\x04\0\x1educkdb:loader-stub/loader-stub\x04\0\x0b\x11\x01\0\x0b\ +loader-stub\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x07\ +0.227.1\x10wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/crates/ducklink-loader/src/lib.rs b/crates/ducklink-loader/src/lib.rs index bccd40b8..131b78e9 100644 --- a/crates/ducklink-loader/src/lib.rs +++ b/crates/ducklink-loader/src/lib.rs @@ -16,7 +16,12 @@ use bindings::exports::duckdb::component::extension_loader_hooks::{ }; use bindings::exports::duckdb::component::host_extension_loader::Guest as LoaderGuest; use bindings::exports::duckdb::extension::callback_dispatch::{ - Duckerror, Duckvalue, Guest as DispatchGuest, Invokeinfo, Resultset, Rowbatch, + Colvec, Duckerror, Duckvalue, Guest as DispatchGuest, Invokeinfo, Resultset, +}; +// The eight host->core callback interfaces (extension-registered backends). +use bindings::exports::duckdb::extension::{ + collation_host, files_host, index_host, optimizer_host, parser_host, pragma_host, + storage_host, table_stream_host, }; use bindings::exports::tvm::memory::bytes::Guest as TvmBytesGuest; use bindings::exports::tvm::memory::manager::{ @@ -59,19 +64,25 @@ impl DispatchGuest for Component { Err(unreachable_dispatch()) } - fn call_scalar_batch( + // HOT PATH: columnar scalar/aggregate/cast (major-4). Unreachable in a + // standalone build (nothing registers a handle), but must type-check. + fn call_scalar_batch_col( _handle: u32, - _rows: Rowbatch, + _args: Vec, _ctx: Invokeinfo, - ) -> Result, Duckerror> { + ) -> Result { Err(unreachable_dispatch()) } - fn call_table(_handle: u32, _args: Vec) -> Result { + fn call_aggregate_col(_handle: u32, _args: Vec) -> Result { Err(unreachable_dispatch()) } - fn call_aggregate(_handle: u32, _rows: Rowbatch) -> Result { + fn call_cast_col(_handle: u32, _arg: Colvec) -> Result { + Err(unreachable_dispatch()) + } + + fn call_table(_handle: u32, _args: Vec) -> Result { Err(unreachable_dispatch()) } @@ -87,6 +98,146 @@ impl DispatchGuest for Component { } } +// --- Host->core backend callbacks (major-4). --------------------------------- +// The core imports these so extension-registered backends can service ATTACH +// storage, vector indexes, collations, pragmas, parsers, optimizer rules, remote +// files, and filtered table streams. A standalone registers no backends, so each +// `*-list` enumerator returns empty (the core registers nothing and its built-in +// local/in-memory functionality is unaffected) and every per-handle operation is +// unreachable — nothing ever hands out a handle to call back on. + +impl storage_host::Guest for Component { + fn storage_list_types() -> Vec { + Vec::new() + } + fn storage_attach(_dsn: String) -> Result { + Err(unreachable_dispatch()) + } + fn storage_list_tables(_catalog: u32) -> Result, Duckerror> { + Err(unreachable_dispatch()) + } + fn storage_table_columns( + _catalog: u32, + _table: String, + ) -> Result, Duckerror> { + Err(unreachable_dispatch()) + } + fn storage_scan_open( + _catalog: u32, + _request: storage_host::ScanRequest, + ) -> Result { + Err(unreachable_dispatch()) + } + fn storage_scan_next( + _scan: u32, + _max_rows: u32, + ) -> Result { + Err(unreachable_dispatch()) + } + fn storage_scan_close(_scan: u32) -> Result { + Err(unreachable_dispatch()) + } +} + +impl index_host::Guest for Component { + fn index_type_list() -> Vec { + Vec::new() + } + fn index_create( + _type_name: String, + _index_name: String, + _dims: u32, + ) -> Result { + Err(unreachable_dispatch()) + } + fn index_append( + _handle: u32, + _rowids: Vec, + _vectors: Vec>, + ) -> Result<(), Duckerror> { + Err(unreachable_dispatch()) + } + fn index_build(_handle: u32) -> Result<(), Duckerror> { + Err(unreachable_dispatch()) + } + fn index_search( + _handle: u32, + _query: Vec, + _k: u32, + ) -> Result, Duckerror> { + Err(unreachable_dispatch()) + } + fn index_drop(_handle: u32) -> Result<(), Duckerror> { + Err(unreachable_dispatch()) + } +} + +impl collation_host::Guest for Component { + fn collation_list() -> Vec { + Vec::new() + } +} + +impl pragma_host::Guest for Component { + fn pragma_list() -> Vec { + Vec::new() + } +} + +impl parser_host::Guest for Component { + fn parser_list() -> Vec { + Vec::new() + } + fn call_parse(_handle: u32, _query: String) -> Result, Duckerror> { + Err(unreachable_dispatch()) + } +} + +impl optimizer_host::Guest for Component { + fn optimizer_list() -> Vec { + Vec::new() + } + fn call_optimize(_handle: u32, _plan_json: String) -> Result, Duckerror> { + Err(unreachable_dispatch()) + } +} + +impl files_host::Guest for Component { + fn file_open(_url: String) -> Result { + Err("standalone build has no files backend".to_string()) + } + fn file_read(_handle: u32, _offset: u64, _len: u32) -> Result, String> { + Err("standalone build has no files backend".to_string()) + } + fn file_close(_handle: u32) -> Result<(), String> { + Err("standalone build has no files backend".to_string()) + } +} + +impl table_stream_host::Guest for Component { + fn filterable_table_list() -> Vec { + Vec::new() + } + fn ts_open_filtered( + _handle: u32, + _args: Vec, + _projection: Vec, + _filters: Vec, + ) -> Result { + Err(unreachable_dispatch()) + } + fn ts_next( + _handle: u32, + _cursor: u32, + _max_rows: u32, + ) -> Result { + Err(unreachable_dispatch()) + } + fn ts_close(_handle: u32, _cursor: u32) -> Result { + Err(unreachable_dispatch()) + } +} + // TVM spill tier. The standalone has no 64-bit host to own regions, so the stub // declines region creation; the core's spill bridge (tvm_spill.rs) treats a // failed create-region as "TVM unavailable", disables the bridge, and falls back diff --git a/crates/ducklink-runtime/Cargo.toml b/crates/ducklink-runtime/Cargo.toml index 62712f1d..6e34c50a 100644 --- a/crates/ducklink-runtime/Cargo.toml +++ b/crates/ducklink-runtime/Cargo.toml @@ -24,12 +24,17 @@ hex = "0.4" # former inline `component_contract_major`/`check_component_contract` so the # same guard backs both the ducklink and sqlink hosts (datalink is public). # The witcanon CONTRACT_DIGEST (above) stays per-repo; this is the @MAJOR proxy. -datalink-contract = { git = "https://github.com/tegmentum/datalink.git", rev = "88782655415e22bb67c4cb3575a10fc1938b14e0" } +datalink-contract = { git = "https://github.com/tegmentum/datalink.git", rev = "80010adf7c9ec3d07674bba12585c787328217f5" } # The shared store-generic compose:dynlink/linker host machinery + the # ResidentBackend (instantiate-once-and-reuse provider lifecycle). ducklink's # compose_dynlink module is now a thin adapter over this; the resolve/invoke # bridge + bindings live here, shared with the other wasm-component hosts. -datalink-dynlink = { git = "https://github.com/tegmentum/datalink.git", rev = "88782655415e22bb67c4cb3575a10fc1938b14e0" } +datalink-dynlink = { git = "https://github.com/tegmentum/datalink.git", rev = "80010adf7c9ec3d07674bba12585c787328217f5" } +# `PendingKind::iter()` is derived via `EnumIter` so `PendingKind::all()` stays +# in lockstep with the enum without a hand-maintained mirror array or a +# hardcoded variant-count assert. `strum` is stable-Rust (no nightly required) +# and pulls in `strum_macros` transitively via its `derive` feature. +strum = { version = "0.26", features = ["derive"] } [build-dependencies] # Same witcanon scheme, used in build.rs to hash the canonical WIT into a const. diff --git a/crates/ducklink-runtime/src/extension.rs b/crates/ducklink-runtime/src/extension.rs index fae2c1ad..2e78c611 100644 --- a/crates/ducklink-runtime/src/extension.rs +++ b/crates/ducklink-runtime/src/extension.rs @@ -368,8 +368,119 @@ struct PendingAggregateRegistry { entries: Vec, } +/// Every kind of registration a component can capture. A `PendingKind` names +/// exactly one `pending_*` buffer on [`ExtensionStoreState`] and its matching +/// `Vec<...>` field on [`PendingRegistrationsData`]. +/// +/// The compile-time exhaustiveness lock on this enum is the drift guard: the +/// `match` in [`PendingKind::as_str`] must cover every variant, and adding a +/// variant to the enum without extending `as_str` fails compilation. The +/// mirror over-every-variant iterator is derived by [`strum::EnumIter`] and +/// exposed through [`PendingKind::all`], so a new variant is picked up +/// automatically — no hand-maintained `ALL` array to keep synchronized and +/// no hardcoded variant count to bump. Together the exhaustive `as_str` +/// match and the derived iterator mean a NEW pending buffer cannot silently +/// skip the drain: the developer must extend `as_str` here plus the matching +/// field on `PendingRegistrationsData` (which the field-by-field drain + +/// append below directly references). +#[derive(Clone, Copy, Debug, PartialEq, Eq, strum::EnumIter)] +pub enum PendingKind { + Scalar, + Table, + Aggregate, + Macro, + ReplacementScan, + LogicalType, + Cast, + Storage, + ScalarEx, + Index, + Files, + Collation, + Pragma, + CopyHandler, + Secret, + Setting, + TableMacro, + ModifiedType, + EnumType, + ConnCallback, + CoordinateSystem, + ArrowTable, + Encoding, + Compression, + Parser, + Optimizer, + FilterableTable, +} + +impl PendingKind { + /// Every variant, in declaration order. Derived from the + /// [`strum::EnumIter`] impl so a new variant is picked up automatically + /// — no hand-maintained mirror array or hardcoded variant count. The + /// EXHAUSTIVE `as_str` match below is the compile-time drift guard for + /// the label surface; between the two, adding a variant without wiring + /// it into either surface is impossible. + pub fn all() -> impl Iterator + Clone { + ::iter() + } + + /// Stable label for logs / diagnostics. The `match` here is EXHAUSTIVE: + /// adding a `PendingKind` variant without extending this match fails + /// compilation, which is the drift guard promised by the type. + pub const fn as_str(self) -> &'static str { + match self { + PendingKind::Scalar => "scalar", + PendingKind::Table => "table", + PendingKind::Aggregate => "aggregate", + PendingKind::Macro => "macro", + PendingKind::ReplacementScan => "replacement-scan", + PendingKind::LogicalType => "logical-type", + PendingKind::Cast => "cast", + PendingKind::Storage => "storage", + PendingKind::ScalarEx => "scalar-ex", + PendingKind::Index => "index", + PendingKind::Files => "files", + PendingKind::Collation => "collation", + PendingKind::Pragma => "pragma", + PendingKind::CopyHandler => "copy-handler", + PendingKind::Secret => "secret", + PendingKind::Setting => "setting", + PendingKind::TableMacro => "table-macro", + PendingKind::ModifiedType => "modified-type", + PendingKind::EnumType => "enum-type", + PendingKind::ConnCallback => "conn-callback", + PendingKind::CoordinateSystem => "coordinate-system", + PendingKind::ArrowTable => "arrow-table", + PendingKind::Encoding => "encoding", + PendingKind::Compression => "compression", + PendingKind::Parser => "parser", + PendingKind::Optimizer => "optimizer", + PendingKind::FilterableTable => "filterable-table", + } + } +} + /// The full set of registrations captured from one or more components, ready /// for a direction-specific sink to forward into the database. +/// +/// Every `pending_*` buffer on [`ExtensionStoreState`] surfaces through a +/// same-named `Vec<...>` field here, so a component's registration is never +/// silently dropped: if the direction-specific host forgets to eagerly drain +/// one via a `take_pending_*` accessor, [`ExtensionStoreState::drain_pending`] +/// picks it up at the standard drain hook instead. The [`PendingKind`] enum's +/// exhaustive match is the drift guard against this list going stale. +/// +/// `scalar_ex` carries the RICHER (2.2.0) scalar registrations captured via +/// `runtime-ext.register-scalar-ex` (varargs, optionally named args, special +/// NULL-handling). Until the wasm-core `pending-registrations` WIT record +/// grows a matching `scalar-ex` arm and the C++ core-shim consumes it, every +/// `scalar_ex` entry is ALSO projected down into `scalars` at drain time +/// (see [`ExtensionStoreState::drain_pending`]) so LOAD at least surfaces +/// the function by name through the existing base-scalar WIT sink. That +/// projection drops `varargs` and `special_null` — it is temporary. Once +/// the core sink lands, the interim projection must be removed to avoid +/// double-registration. #[derive(Default)] pub struct PendingRegistrationsData { pub scalars: Vec, @@ -380,6 +491,27 @@ pub struct PendingRegistrationsData { pub logical_types: Vec, pub casts: Vec, pub storages: Vec, + /// Richer (2.2.0) scalar registrations. See struct-level doc: entries here + /// are also projected into `scalars` for the current interim sink. + pub scalar_ex: Vec, + pub indexes: Vec, + pub files: Vec, + pub collations: Vec, + pub pragmas: Vec, + pub copy_handlers: Vec, + pub secrets: Vec, + pub settings: Vec, + pub table_macros: Vec, + pub modified_types: Vec, + pub enum_types: Vec, + pub conn_callbacks: Vec, + pub coordinate_systems: Vec, + pub arrow_tables: Vec, + pub encodings: Vec, + pub compressions: Vec, + pub parsers: Vec, + pub optimizers: Vec, + pub filterable_tables: Vec, } impl PendingRegistrationsData { @@ -392,6 +524,25 @@ impl PendingRegistrationsData { self.logical_types.append(&mut other.logical_types); self.casts.append(&mut other.casts); self.storages.append(&mut other.storages); + self.scalar_ex.append(&mut other.scalar_ex); + self.indexes.append(&mut other.indexes); + self.files.append(&mut other.files); + self.collations.append(&mut other.collations); + self.pragmas.append(&mut other.pragmas); + self.copy_handlers.append(&mut other.copy_handlers); + self.secrets.append(&mut other.secrets); + self.settings.append(&mut other.settings); + self.table_macros.append(&mut other.table_macros); + self.modified_types.append(&mut other.modified_types); + self.enum_types.append(&mut other.enum_types); + self.conn_callbacks.append(&mut other.conn_callbacks); + self.coordinate_systems.append(&mut other.coordinate_systems); + self.arrow_tables.append(&mut other.arrow_tables); + self.encodings.append(&mut other.encodings); + self.compressions.append(&mut other.compressions); + self.parsers.append(&mut other.parsers); + self.optimizers.append(&mut other.optimizers); + self.filterable_tables.append(&mut other.filterable_tables); } } @@ -682,6 +833,57 @@ impl ExtensionStoreState { let logical_types = std::mem::take(&mut self.pending_logical_types); let casts = std::mem::take(&mut self.pending_casts); let storages = std::mem::take(&mut self.pending_storages); + + // 2.2.0 (Item 6): drain register-scalar-ex captures. Until the wasm-core + // `pending-registrations` WIT record grows a `scalar-ex` arm and the + // C++ core-shim consumes it, every `scalar-ex` entry is ALSO PROJECTED + // DOWN into `scalars` (dropping `varargs` and `special_null`) so LOAD + // surfaces the function name through the existing base-scalar sink. + // TEMPORARY: remove this projection when the core scalar-ex sink lands + // (otherwise a future direct consumer of `scalar_ex` will double-register). + let scalar_ex = std::mem::take(&mut self.pending_scalar_ex); + for entry in &scalar_ex { + scalars.push(PendingScalar { + extension: entry.extension.clone(), + name: entry.name.clone(), + arguments: entry.arguments.clone(), + returns: entry.returns.clone(), + callback_handle: entry.callback_handle, + options: entry.options.clone(), + }); + } + + // Drain EVERY remaining pending_* buffer here so the outer aggregate is + // the single choke point that surfaces a component's registrations. The + // direction-specific host may have already emptied some of these via a + // `take_pending_*` accessor right after `load()` (storages, indexes, + // files, collations, pragmas, parsers, optimizers, filterable_tables); + // in that case `std::mem::take` here just yields an empty Vec. Buffers + // NO direction currently drains eagerly (copy_handlers, secrets, + // settings, table_macros, modified_types, enum_types, conn_callbacks, + // coordinate_systems, arrow_tables, encodings, compressions) surface + // here instead of being silently dropped. New pending kinds MUST be + // added to the `PendingKind` enum (whose exhaustive match is the drift + // guard) plus this drain and `PendingRegistrationsData::append`. + let indexes = std::mem::take(&mut self.pending_indexes); + let files = std::mem::take(&mut self.pending_files); + let collations = std::mem::take(&mut self.pending_collations); + let pragmas = std::mem::take(&mut self.pending_pragmas); + let copy_handlers = std::mem::take(&mut self.pending_copy_handlers); + let secrets = std::mem::take(&mut self.pending_secrets); + let settings = std::mem::take(&mut self.pending_settings); + let table_macros = std::mem::take(&mut self.pending_table_macros); + let modified_types = std::mem::take(&mut self.pending_modified_types); + let enum_types = std::mem::take(&mut self.pending_enum_types); + let conn_callbacks = std::mem::take(&mut self.pending_conn_callbacks); + let coordinate_systems = std::mem::take(&mut self.pending_coordinate_systems); + let arrow_tables = std::mem::take(&mut self.pending_arrow_tables); + let encodings = std::mem::take(&mut self.pending_encodings); + let compressions = std::mem::take(&mut self.pending_compressions); + let parsers = std::mem::take(&mut self.pending_parsers); + let optimizers = std::mem::take(&mut self.pending_optimizers); + let filterable_tables = std::mem::take(&mut self.pending_filterable_tables); + let pending = PendingRegistrationsData { scalars, tables, @@ -691,6 +893,25 @@ impl ExtensionStoreState { logical_types, casts, storages, + scalar_ex, + indexes, + files, + collations, + pragmas, + copy_handlers, + secrets, + settings, + table_macros, + modified_types, + enum_types, + conn_callbacks, + coordinate_systems, + arrow_tables, + encodings, + compressions, + parsers, + optimizers, + filterable_tables, }; let scalar_names = summarize_registration_names(&pending.scalars, |entry| entry.name.as_str()); @@ -700,13 +921,16 @@ impl ExtensionStoreState { summarize_registration_names(&pending.aggregates, |entry| entry.name.as_str()); let macro_names = summarize_registration_names(&pending.macros, |entry| entry.name.as_str()); + let scalar_ex_names = + summarize_registration_names(&pending.scalar_ex, |entry| entry.name.as_str()); eprintln!( - "[extension-runtime:{}] draining pending registrations: scalars={} ({scalar_names}), tables={} ({table_names}), aggregates={} ({aggregate_names}), macros={} ({macro_names})", + "[extension-runtime:{}] draining pending registrations: scalars={} ({scalar_names}), tables={} ({table_names}), aggregates={} ({aggregate_names}), macros={} ({macro_names}), scalar_ex={} ({scalar_ex_names})", self.extension_name, pending.scalars.len(), pending.tables.len(), pending.aggregates.len(), - pending.macros.len() + pending.macros.len(), + pending.scalar_ex.len() ); pending } @@ -2891,6 +3115,7 @@ impl ExtensionInstance { txn: u32, table: &str, rowids: &[i64], + updated_columns: &[u32], rows: &[Vec], ) -> Result { self.storage_write_bindings()?; @@ -2898,7 +3123,15 @@ impl ExtensionInstance { let guest = bindings.duckdb_extension_storage_write_dispatch(); let store = &mut self.store; guest - .call_update_rows(store.as_context_mut(), handle, txn, table, rowids, rows) + .call_update_rows( + store.as_context_mut(), + handle, + txn, + table, + rowids, + updated_columns, + rows, + ) .map_err(map_extension_trap)? } @@ -4457,6 +4690,58 @@ mod tests { assert!(drained.aggregates.is_empty()); assert!(drained.macros.is_empty()); assert!(drained.logical_types.is_empty()); + assert!(drained.scalar_ex.is_empty()); + } + + #[test] + fn drain_pending_carries_scalar_ex_and_projects_into_scalars() { + // 2.2.0 (Item 6) scalar-ex registrations must reach the drain output. + // Since the wasm-core WIT `pending-registrations` record has no + // `scalar-ex` arm yet, `drain_pending` PROJECTS each entry down into + // `scalars` (dropping varargs / special_null) so LOAD surfaces the + // function name through the existing base-scalar sink. The raw entry + // is also preserved on the new `scalar_ex` field for future direct + // consumers. This test locks that dual behavior in until the interim + // projection is retired. + use extension_runtime::Logicaltype as L; + let mut state = test_state(); + + extension_runtime_ext::Host::register_scalar_ex( + &mut state, + "concat_ws".to_string(), + vec![extension_runtime_ext::Funcarg { + name: Some("sep".to_string()), + logical: L::Text, + }] + .into(), + Some(L::Text), + L::Text, + extension_runtime_ext::NullHandling::Special, + 77, + None, + ) + .expect("register_scalar_ex"); + + let drained = state.drain_pending(); + + // Raw scalar-ex entry preserved. + assert_eq!(drained.scalar_ex.len(), 1, "scalar_ex must be drained"); + assert_eq!(drained.scalar_ex[0].name, "concat_ws"); + assert_eq!(drained.scalar_ex[0].callback_handle, 77); + assert!(drained.scalar_ex[0].special_null); + assert_eq!(drained.scalar_ex[0].varargs, Some(reg::LogicalType::Text)); + + // Interim projection: same entry surfaces as a base scalar so the + // existing WIT `pending-registrations.scalars` sink registers the + // function by name. + assert_eq!( + drained.scalars.len(), + 1, + "scalar_ex must be projected into scalars for LOAD" + ); + assert_eq!(drained.scalars[0].name, "concat_ws"); + assert_eq!(drained.scalars[0].callback_handle, 77); + assert_eq!(drained.scalars[0].returns, reg::LogicalType::Text); } #[test] @@ -4467,6 +4752,267 @@ mod tests { assert!(s.contains("+2 more")); assert_eq!(summarize_registration_names::<&str, _>(&[], |n| n), "none"); } + + #[test] + fn pending_kind_all_stays_in_sync_with_variants() { + // The derived `PendingKind::all()` iterator visits every variant + // (`strum::EnumIter`) and each variant renders through the + // exhaustive `as_str` match to a distinct label. If a variant is + // added, the derive picks it up automatically; if the developer + // forgets to extend `as_str`, that match fails compile. + let mut labels: Vec<&str> = PendingKind::all().map(|k| k.as_str()).collect(); + let n = labels.len(); + labels.sort(); + labels.dedup(); + assert_eq!( + labels.len(), + n, + "PendingKind::all() has a duplicate label: {labels:?}" + ); + } + + #[test] + fn drain_pending_surfaces_every_pending_buffer() { + // The SYSTEMIC drain guard: for EVERY pending_* buffer on the store + // state, push one synthetic entry and verify `drain_pending()` surfaces + // it on the matching field of `PendingRegistrationsData`. This is the + // runtime companion to the compile-time `PendingKind` exhaustiveness + // lock — together they stop a new pending buffer from silently + // draining nowhere. + use extension_runtime::Logicaltype as L; + let mut state = test_state(); + + // ScalarRegistry / TableRegistry / AggregateRegistry keep their own + // per-registry buffers that fold into pending_scalars/tables/aggregates + // on drop; push directly into the retained buffers here so the test + // stays independent of the resource-drop dance. + state.pending_scalars.push(reg::ScalarReg { + extension: "ext".into(), + name: "s".into(), + arguments: vec![], + returns: reg::LogicalType::Int64, + callback_handle: 1, + options: None, + }); + state.pending_tables.push(reg::TableReg { + extension: "ext".into(), + name: "t".into(), + arguments: vec![], + columns: vec![], + callback_handle: 2, + options: None, + }); + state.pending_aggregates.push(reg::AggregateReg { + extension: "ext".into(), + name: "a".into(), + arguments: vec![], + returns: reg::LogicalType::Int64, + callback_handle: 3, + options: None, + }); + state.pending_macros.push(reg::MacroReg { + extension: "ext".into(), + schema: "main".into(), + name: "m".into(), + parameters: vec![], + definition_sql: "SELECT 1".into(), + }); + state.pending_replacement_scans.push(reg::ReplacementScanReg { + extension: "ext".into(), + extensions: vec!["csv".into()], + function_name: "read_csv".into(), + }); + state.pending_logical_types.push(reg::LogicalTypeReg { + extension: "ext".into(), + name: "myint".into(), + physical: "INTEGER".into(), + }); + state.pending_casts.push(reg::CastReg { + extension: "ext".into(), + source: "TEXT".into(), + target: "INTEGER".into(), + callback_handle: 4, + }); + state.pending_storages.push(reg::StorageReg { + extension: "ext".into(), + type_name: "sqlitewasm".into(), + callback_handle: 5, + options: None, + }); + state.pending_scalar_ex.push(reg::ScalarExReg { + extension: "ext".into(), + name: "concat_ws".into(), + arguments: vec![], + varargs: Some(reg::LogicalType::Text), + returns: reg::LogicalType::Text, + special_null: true, + callback_handle: 6, + options: None, + }); + state.pending_indexes.push(reg::IndexReg { + extension: "ext".into(), + type_name: "wasm_hnsw".into(), + }); + state.pending_files.push(reg::FilesReg { + extension: "ext".into(), + callback_handle: 7, + }); + state.pending_collations.push(reg::CollationReg { + extension: "ext".into(), + name: "icu_en".into(), + transform_scalar: "icu_sort".into(), + combinable: false, + }); + state.pending_pragmas.push(reg::PragmaReg { + extension: "ext".into(), + name: "my_pragma".into(), + callback_handle: 8, + }); + state.pending_copy_handlers.push(reg::CopyHandlerReg { + extension: "ext".into(), + file_extension: "parquet".into(), + function_handle: 9, + }); + state.pending_secrets.push(reg::SecretReg { + extension: "ext".into(), + type_name: "s3".into(), + provider: None, + params: vec![], + callback_handle: 10, + }); + state.pending_settings.push(reg::SettingReg { + extension: "ext".into(), + name: "my_threshold".into(), + description: "knob".into(), + ty: "bigint".into(), + default_value: Some("42".into()), + scope: "global".into(), + }); + state.pending_table_macros.push(reg::TableMacroReg { + extension: "ext".into(), + schema: "main".into(), + name: "series".into(), + parameters: vec!["n".into()], + body_sql: "SELECT * FROM range(n)".into(), + }); + state.pending_modified_types.push(reg::ModifiedTypeReg { + extension: "ext".into(), + name: "price".into(), + type_expr: "DECIMAL(18,3)".into(), + }); + state.pending_enum_types.push(reg::EnumTypeReg { + extension: "ext".into(), + name: "mood".into(), + members: vec!["happy".into(), "sad".into()], + }); + state.pending_conn_callbacks.push(reg::ConnCallbackReg { + extension: "ext".into(), + on_opened: true, + on_closed: false, + callback_handle: 11, + }); + state.pending_coordinate_systems.push(reg::CoordinateSystemReg { + extension: "ext".into(), + auth_name: "EPSG".into(), + code: 4326, + wkt: "GEOGCRS[...]".into(), + }); + state.pending_arrow_tables.push(reg::ArrowTableReg { + extension: "ext".into(), + name: "feed".into(), + columns: vec![reg::ColumnDef { + name: "v".into(), + logical: reg::LogicalType::Int64, + }], + callback_handle: 12, + }); + state.pending_encodings.push(reg::EncodingReg { + extension: "ext".into(), + name: "latin-1".into(), + aliases: vec!["iso-8859-1".into()], + callback_handle: 13, + }); + state.pending_compressions.push(reg::CompressionReg { + extension: "ext".into(), + name: "zstd".into(), + file_extension: "zst".into(), + callback_handle: 14, + }); + state.pending_parsers.push(reg::ParserReg { + extension: "ext".into(), + name: "ggsql".into(), + callback_handle: 15, + }); + state.pending_optimizers.push(reg::OptimizerReg { + extension: "ext".into(), + rule_name: "hoist_filters".into(), + callback_handle: 16, + }); + state.pending_filterable_tables.push(reg::FilterableTableReg { + extension: "ext".into(), + name: "read_stream".into(), + arguments: vec![], + columns: vec![], + callback_handle: 17, + }); + + // Guarantee the compile-time as_str / EnumIter lockstep is what this + // test actually validates: one buffer per kind. The + // `PendingKind::all()` iterator is derived, so a new variant lands + // here automatically; the drain assertions further below then flag + // the missing case unless the developer extends this test too. + let _: L = L::Text; // keep the `use` in play across the rustc future edition. + let variant_count = PendingKind::all().count(); + assert!( + variant_count > 0, + "PendingKind::all() must enumerate at least one variant" + ); + + let drained = state.drain_pending(); + // Every field surfaces exactly one entry. Note: `scalar_ex` ALSO + // projects an interim scalars entry (see drain_pending doc), so the + // scalars total is 2 (bare `s` + projected `concat_ws`). + assert_eq!(drained.scalars.len(), 2, "scalars drained (bare + scalar_ex projection)"); + assert_eq!(drained.tables.len(), 1, "tables drained"); + assert_eq!(drained.aggregates.len(), 1, "aggregates drained"); + assert_eq!(drained.macros.len(), 1, "macros drained"); + assert_eq!(drained.replacement_scans.len(), 1, "replacement_scans drained"); + assert_eq!(drained.logical_types.len(), 1, "logical_types drained"); + assert_eq!(drained.casts.len(), 1, "casts drained"); + assert_eq!(drained.storages.len(), 1, "storages drained"); + assert_eq!(drained.scalar_ex.len(), 1, "scalar_ex drained"); + assert_eq!( + drained.scalars.iter().filter(|s| s.name == "concat_ws").count(), + 1, + "scalar_ex projected into scalars" + ); + assert_eq!(drained.indexes.len(), 1, "indexes drained"); + assert_eq!(drained.files.len(), 1, "files drained"); + assert_eq!(drained.collations.len(), 1, "collations drained"); + assert_eq!(drained.pragmas.len(), 1, "pragmas drained"); + assert_eq!(drained.copy_handlers.len(), 1, "copy_handlers drained"); + assert_eq!(drained.secrets.len(), 1, "secrets drained"); + assert_eq!(drained.settings.len(), 1, "settings drained"); + assert_eq!(drained.table_macros.len(), 1, "table_macros drained"); + assert_eq!(drained.modified_types.len(), 1, "modified_types drained"); + assert_eq!(drained.enum_types.len(), 1, "enum_types drained"); + assert_eq!(drained.conn_callbacks.len(), 1, "conn_callbacks drained"); + assert_eq!(drained.coordinate_systems.len(), 1, "coordinate_systems drained"); + assert_eq!(drained.arrow_tables.len(), 1, "arrow_tables drained"); + assert_eq!(drained.encodings.len(), 1, "encodings drained"); + assert_eq!(drained.compressions.len(), 1, "compressions drained"); + assert_eq!(drained.parsers.len(), 1, "parsers drained"); + assert_eq!(drained.optimizers.len(), 1, "optimizers drained"); + assert_eq!(drained.filterable_tables.len(), 1, "filterable_tables drained"); + + // Re-draining a spent state yields empty vectors on every field (the + // buffers were consumed via std::mem::take). + let empty = state.drain_pending(); + assert!(empty.scalars.is_empty()); + assert!(empty.indexes.is_empty()); + assert!(empty.copy_handlers.is_empty()); + assert!(empty.filterable_tables.is_empty()); + } } /// Add the full `duckdb:extension` capability surface to `linker`: the wasip2 diff --git a/crates/ducklink-runtime/src/lib.rs b/crates/ducklink-runtime/src/lib.rs index d320e9fe..d694ccfc 100644 --- a/crates/ducklink-runtime/src/lib.rs +++ b/crates/ducklink-runtime/src/lib.rs @@ -326,7 +326,7 @@ pub use extension::{ load_component_with_dynlink, summarize_extopts, summarize_funcopts, summarize_registration_names, summarize_runtime_columns, summarize_runtime_funcargs, ConfigError, ExtensionInstance, ExtensionServices, ExtensionStoreState, LogField, LogLevel, - PendingRegistrationsData, + PendingKind, PendingRegistrationsData, }; /// The generated wasmtime bindings for the `duckdb:extension-host` world — the diff --git a/crates/ducklink-runtime/tests/runtime_units.rs b/crates/ducklink-runtime/tests/runtime_units.rs index 4fdcc626..4e138375 100644 --- a/crates/ducklink-runtime/tests/runtime_units.rs +++ b/crates/ducklink-runtime/tests/runtime_units.rs @@ -309,6 +309,125 @@ fn pending_append_merges_all_kinds_and_drains_other() { target: "b".to_string(), callback_handle: 3, }); + other.scalar_ex.push(reg::ScalarExReg { + extension: "ext".to_string(), + name: "concat_ws".to_string(), + arguments: vec![], + varargs: Some(reg::LogicalType::Text), + returns: reg::LogicalType::Text, + special_null: true, + callback_handle: 4, + options: None, + }); + // The SYSTEMIC append coverage: every additive pending_* buffer surfaces + // through `PendingRegistrationsData` and must survive an `append()`. If a + // new buffer is added but this test is not extended, the count assertions + // below still pass — the exhaustive `PendingKind::as_str` match plus the + // `strum::EnumIter`-derived `PendingKind::all()` (see extension.rs) is + // what stops the field from being forgotten in `append`/`drain_pending`. + other.indexes.push(reg::IndexReg { + extension: "ext".to_string(), + type_name: "wasm_hnsw".to_string(), + }); + other.files.push(reg::FilesReg { + extension: "ext".to_string(), + callback_handle: 5, + }); + other.collations.push(reg::CollationReg { + extension: "ext".to_string(), + name: "icu_en".to_string(), + transform_scalar: "icu_sort".to_string(), + combinable: false, + }); + other.pragmas.push(reg::PragmaReg { + extension: "ext".to_string(), + name: "my_pragma".to_string(), + callback_handle: 6, + }); + other.copy_handlers.push(reg::CopyHandlerReg { + extension: "ext".to_string(), + file_extension: "parquet".to_string(), + function_handle: 7, + }); + other.secrets.push(reg::SecretReg { + extension: "ext".to_string(), + type_name: "s3".to_string(), + provider: None, + params: vec![], + callback_handle: 8, + }); + other.settings.push(reg::SettingReg { + extension: "ext".to_string(), + name: "my_threshold".to_string(), + description: "knob".to_string(), + ty: "bigint".to_string(), + default_value: None, + scope: "global".to_string(), + }); + other.table_macros.push(reg::TableMacroReg { + extension: "ext".to_string(), + schema: "main".to_string(), + name: "series".to_string(), + parameters: vec![], + body_sql: "SELECT 1".to_string(), + }); + other.modified_types.push(reg::ModifiedTypeReg { + extension: "ext".to_string(), + name: "price".to_string(), + type_expr: "DECIMAL(18,3)".to_string(), + }); + other.enum_types.push(reg::EnumTypeReg { + extension: "ext".to_string(), + name: "mood".to_string(), + members: vec!["happy".to_string()], + }); + other.conn_callbacks.push(reg::ConnCallbackReg { + extension: "ext".to_string(), + on_opened: true, + on_closed: false, + callback_handle: 9, + }); + other.coordinate_systems.push(reg::CoordinateSystemReg { + extension: "ext".to_string(), + auth_name: "EPSG".to_string(), + code: 4326, + wkt: "GEOGCRS[...]".to_string(), + }); + other.arrow_tables.push(reg::ArrowTableReg { + extension: "ext".to_string(), + name: "feed".to_string(), + columns: vec![], + callback_handle: 10, + }); + other.encodings.push(reg::EncodingReg { + extension: "ext".to_string(), + name: "latin-1".to_string(), + aliases: vec![], + callback_handle: 11, + }); + other.compressions.push(reg::CompressionReg { + extension: "ext".to_string(), + name: "zstd".to_string(), + file_extension: "zst".to_string(), + callback_handle: 12, + }); + other.parsers.push(reg::ParserReg { + extension: "ext".to_string(), + name: "ggsql".to_string(), + callback_handle: 13, + }); + other.optimizers.push(reg::OptimizerReg { + extension: "ext".to_string(), + rule_name: "hoist_filters".to_string(), + callback_handle: 14, + }); + other.filterable_tables.push(reg::FilterableTableReg { + extension: "ext".to_string(), + name: "read_stream".to_string(), + arguments: vec![], + columns: vec![], + callback_handle: 15, + }); base.append(other); @@ -319,4 +438,26 @@ fn pending_append_merges_all_kinds_and_drains_other() { assert_eq!(base.macros.len(), 1); assert_eq!(base.casts.len(), 1); assert_eq!(base.aggregates.len(), 0); + assert_eq!(base.scalar_ex.len(), 1, "scalar_ex must also merge on append"); + assert_eq!(base.scalar_ex[0].name, "concat_ws"); + assert_eq!(base.scalar_ex[0].callback_handle, 4); + // Every additive pending_* buffer must survive the append. + assert_eq!(base.indexes.len(), 1); + assert_eq!(base.files.len(), 1); + assert_eq!(base.collations.len(), 1); + assert_eq!(base.pragmas.len(), 1); + assert_eq!(base.copy_handlers.len(), 1); + assert_eq!(base.secrets.len(), 1); + assert_eq!(base.settings.len(), 1); + assert_eq!(base.table_macros.len(), 1); + assert_eq!(base.modified_types.len(), 1); + assert_eq!(base.enum_types.len(), 1); + assert_eq!(base.conn_callbacks.len(), 1); + assert_eq!(base.coordinate_systems.len(), 1); + assert_eq!(base.arrow_tables.len(), 1); + assert_eq!(base.encodings.len(), 1); + assert_eq!(base.compressions.len(), 1); + assert_eq!(base.parsers.len(), 1); + assert_eq!(base.optimizers.len(), 1); + assert_eq!(base.filterable_tables.len(), 1); } diff --git a/crates/ducklink-runtime/wit/deps/duckdb-extension/storage-write-dispatch.wit b/crates/ducklink-runtime/wit/deps/duckdb-extension/storage-write-dispatch.wit index 2617766f..2ecc2cb5 100644 --- a/crates/ducklink-runtime/wit/deps/duckdb-extension/storage-write-dispatch.wit +++ b/crates/ducklink-runtime/wit/deps/duckdb-extension/storage-write-dispatch.wit @@ -38,11 +38,19 @@ interface storage-write-dispatch { table: string, rowids: list) -> result; - // Update rows by row-id (parallel `rowids` / `rows`); returns the number - // updated. + // Update rows by row-id (parallel `rowids` / `rows`). Each `rows[i]` is a + // PARTIAL row that carries ONLY the SET values; the schema-index of each + // cell is given by the parallel-indexed entry in `updated-columns`, so + // `rows[i][j]` sets column `updated-columns[j]` on the row identified by + // `rowids[i]`. Mirrors the storage-host `storage-update-rows` semantic -- + // the ducklink host forwards `LogicalUpdate::columns` (captured at plan + // time by WasmPhysicalUpdate) verbatim as `updated-columns` and the SET + // cells of each child DataChunk as the parallel `rows` payload. Returns + // the number of rows successfully updated. update-rows: func(handle: u32, txn: u32, table: string, rowids: list, + updated-columns: list, rows: list>) -> result; } diff --git a/crates/ducklink-runtime/wit/deps/duckdb-extension/storage.wit b/crates/ducklink-runtime/wit/deps/duckdb-extension/storage.wit index 7f1c4c57..b38f983f 100644 --- a/crates/ducklink-runtime/wit/deps/duckdb-extension/storage.wit +++ b/crates/ducklink-runtime/wit/deps/duckdb-extension/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/crates/storage-boundary-test/tests/boundary.rs b/crates/storage-boundary-test/tests/boundary.rs index 48020636..e7eb07dc 100644 --- a/crates/storage-boundary-test/tests/boundary.rs +++ b/crates/storage-boundary-test/tests/boundary.rs @@ -66,6 +66,9 @@ macro_rules! unreachable_import { // ---- types (marker trait: no functions) ---- impl ext::types::Host for State {} +// ---- column-types (marker trait: no functions, major-4 columnar model) ---- +impl ext::column_types::Host for State {} + // ---- logging ---- impl ext::logging::Host for State { fn log(&mut self, _level: ext::types::Loglevel, _message: String, _target: Option) { @@ -433,6 +436,7 @@ fn pushdown_crosses_wit_boundary() { value: Duckvalue::Int64(1), }], limit: None, + wants_rowid: false, }; let scan = sd .call_storage_scan_open(&mut store, HANDLE, cat, &req) @@ -459,6 +463,7 @@ fn pushdown_crosses_wit_boundary() { projection: vec![], filters: vec![], limit: None, + wants_rowid: false, }; let scan2 = sd .call_storage_scan_open(&mut store, HANDLE, cat, &full) diff --git a/crates/storage-boundary-test/tests/write_boundary.rs b/crates/storage-boundary-test/tests/write_boundary.rs new file mode 100644 index 00000000..7aa475b2 --- /dev/null +++ b/crates/storage-boundary-test/tests/write_boundary.rs @@ -0,0 +1,286 @@ +//! Cross-boundary integration test for the WRITABLE half of the storage +//! contract. +//! +//! Loads the built synthetic writer bridge (from either the sibling repo or +//! the local `artifacts/extensions/` staging dir) and drives its +//! `storage-write-dispatch@2.0.0` exports through the WIT component boundary +//! via wasmtime, proving that transactional / DDL / DML calls round-trip +//! ACROSS the interface: args are encoded into the component's linear memory +//! by the canonical ABI and the resultset (rowids + counts) is decoded back +//! out, not merely exercised by the component's native Rust logic. This is +//! the mirror-image counterpart to `boundary.rs` (which exercises the +//! read-side `storage-dispatch` interface against the sqlite component). +//! +//! Strategy: identical to the read-side test. The bridge is a plain writer +//! component with NO imports (its `writer` world only exports +//! storage-write-dispatch), so we just instantiate it and call the exports +//! directly. `handle = 1` and `catalog = 1` are the fixed values the bridge +//! serves (it does not model a callback registry / catalog table). + +use wasmtime::component::{Component, Linker, ResourceTable}; +use wasmtime::{Config, Engine, Store}; + +mod bindings { + wasmtime::component::bindgen!({ + path: "wit-write", + world: "write-boundary-test", + }); +} + +use bindings::duckdb::extension as ext; +use bindings::WriteBoundaryTest; +use ext::types::Duckvalue; + +// The v0.2.0 bridge's `guest.load()` calls storage.register-storage; +// wasmtime instantiation refuses to bind a component that imports an +// interface the linker cannot satisfy, so provide a no-op host impl for +// every interface the bridge world imports. The write-boundary test never +// actually calls guest.load() -- it drives the storage-write-dispatch +// export directly -- so the host impls are only there so the LINKER's +// satisfaction check passes at instantiate-time. +impl ext::types::Host for State {} +impl ext::storage::Host for State { + fn register_storage( + &mut self, + _type_name: String, + _callback_handle: u32, + _options: Option, + ) -> Result { + Ok(0) + } +} + +/// Store state. The writer bridge's `writer` world imports nothing from the +/// `duckdb:extension` package, but the wasip2 stdlib pulls in `wasi:io` / +/// `wasi:cli` / `wasi:filesystem` implicitly (Mutex + OnceLock allocate, +/// panic-time stderr goes through wasi-cli); satisfy those with a real (but +/// idle) `WasiCtx` so instantiation succeeds. The dispatch calls never touch +/// them. +struct State { + table: ResourceTable, + wasi: wasmtime_wasi::WasiCtx, +} + +impl Default for State { + fn default() -> Self { + State { + table: ResourceTable::new(), + wasi: wasmtime_wasi::WasiCtxBuilder::new().build(), + } + } +} + +impl wasmtime_wasi::WasiView for State { + fn ctx(&mut self) -> wasmtime_wasi::WasiCtxView<'_> { + wasmtime_wasi::WasiCtxView { + ctx: &mut self.wasi, + table: &mut self.table, + } + } +} + +const HANDLE: u32 = 1; +const CATALOG: u32 = 1; + +fn locate_writer_bridge_wasm() -> std::path::PathBuf { + // 1. explicit env var wins (CI). + if let Ok(p) = std::env::var("DUCKLINK_WRITER_BRIDGE_WASM") { + return std::path::PathBuf::from(p); + } + // 2. staged copy in the local artifacts dir (developer convenience: + // `cp .../synthetic_mutating_ducklink_bridge_dynlink.wasm + // ducklink/artifacts/extensions/synthetic_mutating_ducklink.wasm`). + let manifest = env!("CARGO_MANIFEST_DIR"); + let staged = std::path::Path::new(manifest) + .join("../../artifacts/extensions/synthetic_mutating_ducklink.wasm"); + if staged.exists() { + return staged; + } + // 3. sibling checkout (default dev layout: ~/git/synthetic-mutating-vtab- + // ducklink-bridge/ next to ~/git/ducklink/). + let home = std::env::var("HOME").expect("HOME env var"); + let sibling = std::path::PathBuf::from(home).join( + "git/synthetic-mutating-vtab-ducklink-bridge/target/wasm32-wasip2/release/\ + synthetic_mutating_ducklink_bridge_dynlink.wasm", + ); + if sibling.exists() { + return sibling; + } + panic!( + "writer bridge wasm not found. tried:\n\ + \x20 * $DUCKLINK_WRITER_BRIDGE_WASM (unset)\n\ + \x20 * {}\n\ + \x20 * {}\n\ + build the bridge with:\n\ + \x20 (cd ~/git/synthetic-mutating-vtab-ducklink-bridge && \ + cargo build --target wasm32-wasip2 --release)\n\ + then either set DUCKLINK_WRITER_BRIDGE_WASM= or copy the wasm to \ + the staged location.", + staged.display(), + sibling.display(), + ); +} + +fn columns_kv() -> Vec { + vec![ + ext::types::Columndef { + name: "key".to_string(), + logical: ext::types::Logicaltype::Text, + }, + ext::types::Columndef { + name: "value".to_string(), + logical: ext::types::Logicaltype::Text, + }, + ] +} + +fn row(k: &str, v: &str) -> Vec { + vec![Duckvalue::Text(k.to_string()), Duckvalue::Text(v.to_string())] +} + +fn setup() -> (Store, WriteBoundaryTest) { + let mut config = Config::new(); + config.wasm_component_model(true); + let engine = Engine::new(&config).expect("engine"); + + // The v0.2.0 bridge's `writer` world imports `duckdb:extension/storage` + // (needed by guest.load's register-storage call) plus the wasip2 stdlib's + // wasi:io / wasi:cli / wasi:filesystem. Bind both: WriteBoundaryTest's + // bindgen-generated add_to_linker wires the storage host trait we + // implemented above, and wasmtime_wasi covers the wasi side. + let mut linker: Linker = Linker::new(&engine); + wasmtime_wasi::p2::add_to_linker_sync(&mut linker).expect("wasi add_to_linker"); + WriteBoundaryTest::add_to_linker::>( + &mut linker, + |s| s, + ) + .expect("write-boundary add_to_linker"); + let mut store = Store::new(&engine, State::default()); + + let wasm_path = locate_writer_bridge_wasm(); + let bytes = std::fs::read(&wasm_path) + .unwrap_or_else(|e| panic!("read {}: {e}", wasm_path.display())); + assert_eq!( + &bytes[0..8], + &[0x00, 0x61, 0x73, 0x6d, 0x0d, 0x00, 0x01, 0x00], + "not a wasm component (bad magic) at {}", + wasm_path.display() + ); + let component = Component::new(&engine, &bytes).expect("Component::new"); + let instance = + WriteBoundaryTest::instantiate(&mut store, &component, &linker).expect("instantiate"); + (store, instance) +} + +/// Full happy path: begin -> create -> insert -> update -> delete -> commit. +/// Every dispatch call round-trips through the canonical ABI; the assertions +/// check the returned counts / rowids the component emits. +#[test] +fn write_dispatch_crosses_wit_boundary() { + let (mut store, instance) = setup(); + let wd = instance.duckdb_extension_storage_write_dispatch(); + + // begin_transaction across the boundary. + let txn = wd + .call_begin_transaction(&mut store, HANDLE, CATALOG) + .expect("begin_transaction host call") + .expect("begin_transaction component result"); + assert!(txn >= 1, "txn handle must be non-zero, got {txn}"); + + // create_table across the boundary. + let cols = columns_kv(); + wd.call_create_table(&mut store, HANDLE, txn, "kv_store", &cols) + .expect("create_table host call") + .expect("create_table component result"); + + // insert_rows across the boundary. Two rows, count=2. + let rows = vec![row("alpha", "1"), row("beta", "2")]; + let inserted = wd + .call_insert_rows(&mut store, HANDLE, txn, "kv_store", &rows) + .expect("insert_rows host call") + .expect("insert_rows component result"); + assert_eq!(inserted, 2, "insert returned {inserted}, want 2"); + + // update_rows across the boundary. The bridge assigns rowids 1..=N in + // monotonic order; update rowid 1 in place, count=1. The v4.0.1 wire + // carries `updated_columns` alongside the SET cells (partial-row + // semantic): here we SET both kv_store columns (schema indices 0 and + // 1), matching a `UPDATE ... SET key=?, value=?` shape. + let update_row = vec![row("alpha", "one")]; + let updated = wd + .call_update_rows( + &mut store, + HANDLE, + txn, + "kv_store", + &[1_i64], + &[0_u32, 1_u32], + &update_row, + ) + .expect("update_rows host call") + .expect("update_rows component result"); + assert_eq!(updated, 1, "update returned {updated}, want 1"); + + // delete_rows across the boundary. Delete rowid 2, count=1. + let deleted = wd + .call_delete_rows(&mut store, HANDLE, txn, "kv_store", &[2_i64]) + .expect("delete_rows host call") + .expect("delete_rows component result"); + assert_eq!(deleted, 1, "delete returned {deleted}, want 1"); + + // commit_transaction across the boundary. + wd.call_commit_transaction(&mut store, HANDLE, txn) + .expect("commit_transaction host call") + .expect("commit_transaction component result"); +} + +/// Rollback path: begin -> insert -> rollback. After rollback, a new txn +/// starts from the pre-rollback committed state (the bridge's committed +/// state was already populated by `write_dispatch_crosses_wit_boundary`, +/// so this test starts with a fresh setup and checks that a rollback +/// leaves no writes visible in the next txn). +#[test] +fn write_dispatch_rollback_crosses_wit_boundary() { + let (mut store, instance) = setup(); + let wd = instance.duckdb_extension_storage_write_dispatch(); + + // begin_transaction + create_table + insert 3 rows. + let txn = wd + .call_begin_transaction(&mut store, HANDLE, CATALOG) + .expect("begin_transaction host call") + .expect("begin_transaction component result"); + let cols = columns_kv(); + wd.call_create_table(&mut store, HANDLE, txn, "kv_store", &cols) + .expect("create_table host call") + .expect("create_table component result"); + let rows = vec![row("k1", "v1"), row("k2", "v2"), row("k3", "v3")]; + let inserted = wd + .call_insert_rows(&mut store, HANDLE, txn, "kv_store", &rows) + .expect("insert_rows host call") + .expect("insert_rows component result"); + assert_eq!(inserted, 3, "insert returned {inserted}, want 3"); + + // rollback_transaction across the boundary. + wd.call_rollback_transaction(&mut store, HANDLE, txn) + .expect("rollback_transaction host call") + .expect("rollback_transaction component result"); + + // Open a new txn and delete a rowid the rolled-back txn had inserted. + // The rollback should have discarded the shadow, so the delete of a + // never-committed rowid returns 0 (nothing to delete). + let txn2 = wd + .call_begin_transaction(&mut store, HANDLE, CATALOG) + .expect("begin_transaction (rerun) host call") + .expect("begin_transaction (rerun) component result"); + let deleted = wd + .call_delete_rows(&mut store, HANDLE, txn2, "kv_store", &[1_i64, 2_i64, 3_i64]) + .expect("delete_rows (post-rollback) host call") + .expect("delete_rows (post-rollback) component result"); + assert_eq!( + deleted, 0, + "post-rollback delete returned {deleted}, want 0 (shadow was discarded)" + ); + wd.call_rollback_transaction(&mut store, HANDLE, txn2) + .expect("cleanup rollback host call") + .expect("cleanup rollback component result"); +} diff --git a/crates/storage-boundary-test/wit-write/boundary.wit b/crates/storage-boundary-test/wit-write/boundary.wit new file mode 100644 index 00000000..cef9276f --- /dev/null +++ b/crates/storage-boundary-test/wit-write/boundary.wit @@ -0,0 +1,26 @@ +package boundary-test:write@0.2.0; + +use duckdb:extension/types@4.0.0; +use duckdb:extension/storage-write-dispatch@4.0.0; + +// Host-side world for the write-boundary integration test. Binds against the +// storage-write-dispatch@4.0.0 export of the synthetic ducklink storage +// bridge (`synthetic:writer/writer` v0.2.0). We only bind the write side -- +// the bridge's guest / callback-dispatch / storage-dispatch exports are +// unused by this test and are ignored by wasmtime bindgen because they are +// not listed in this world. +// +// This test still exercises the storage-write-dispatch calls directly +// without going through a `guest.load()` register-storage handshake; that +// path is covered end-to-end by the `synthetic-mutating-ducklink` shim- +// bridge-smoke case. +world write-boundary-test { + // The bridge is now full-stack: guest.load() calls storage.register-storage, + // so wasmtime's instantiation fails if the linker cannot satisfy the storage + // import. Bind it here (see State::register_storage for the no-op impl) so + // this test can still instantiate the bridge and drive the write-side + // trampolines directly without going through a real LOAD. + import duckdb:extension/storage@4.0.0; + + export duckdb:extension/storage-write-dispatch@4.0.0; +} diff --git a/crates/storage-boundary-test/wit-write/deps.toml b/crates/storage-boundary-test/wit-write/deps.toml new file mode 100644 index 00000000..04447887 --- /dev/null +++ b/crates/storage-boundary-test/wit-write/deps.toml @@ -0,0 +1,6 @@ +[package] +name = "boundary-test:write" +version = "0.2.0" + +[dependencies] +"duckdb:extension" = { path = "deps/duckdb-extension" } diff --git a/crates/storage-boundary-test/wit-write/deps/duckdb-extension/deps.toml b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/deps.toml new file mode 100644 index 00000000..f0d09d11 --- /dev/null +++ b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/deps.toml @@ -0,0 +1,3 @@ +[package] +name = "duckdb:extension" +version = "2.0.0" diff --git a/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage-write-dispatch.wit b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage-write-dispatch.wit new file mode 100644 index 00000000..2ecc2cb5 --- /dev/null +++ b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage-write-dispatch.wit @@ -0,0 +1,56 @@ +package duckdb:extension@4.0.0; + +use types; + +// Host -> component callbacks for the WRITABLE half of a storage backend +// (additive, 2.1.0). The read-only `storage-dispatch` (attach/list/scan) is left +// INTACT; this adds the mutating path -- transactions, DDL, and DML -- for +// storage backends that can write through. Exported by writable storage +// components via the separate `duckdb-extension-storage-write` world. +// +// Every call carries `handle` = the callback-handle the component passed to +// storage.register-storage; `catalog` is the catalog handle from +// storage-dispatch.storage-attach. +interface storage-write-dispatch { + use types.{duckerror, duckvalue, columndef}; + + // Begin a transaction on `catalog`; returns a transaction handle. + begin-transaction: func(handle: u32, catalog: u32) -> result; + + commit-transaction: func(handle: u32, txn: u32) -> result<_, duckerror>; + rollback-transaction: func(handle: u32, txn: u32) -> result<_, duckerror>; + + // CREATE TABLE within `txn`. + create-table: func(handle: u32, + txn: u32, + table: string, + columns: list) -> result<_, duckerror>; + + // Append rows; returns the number inserted. + insert-rows: func(handle: u32, + txn: u32, + table: string, + rows: list>) -> result; + + // Delete rows by row-id; returns the number deleted. + delete-rows: func(handle: u32, + txn: u32, + table: string, + rowids: list) -> result; + + // Update rows by row-id (parallel `rowids` / `rows`). Each `rows[i]` is a + // PARTIAL row that carries ONLY the SET values; the schema-index of each + // cell is given by the parallel-indexed entry in `updated-columns`, so + // `rows[i][j]` sets column `updated-columns[j]` on the row identified by + // `rowids[i]`. Mirrors the storage-host `storage-update-rows` semantic -- + // the ducklink host forwards `LogicalUpdate::columns` (captured at plan + // time by WasmPhysicalUpdate) verbatim as `updated-columns` and the SET + // cells of each child DataChunk as the parallel `rows` payload. Returns + // the number of rows successfully updated. + update-rows: func(handle: u32, + txn: u32, + table: string, + rowids: list, + updated-columns: list, + rows: list>) -> result; +} diff --git a/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage.wit b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage.wit new file mode 100644 index 00000000..b38f983f --- /dev/null +++ b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/storage.wit @@ -0,0 +1,54 @@ +package duckdb:extension@4.0.0; + +use types; + +// Storage / catalog backend surface. A component that wants to back an +// ATTACH-able catalog (a DB scanner) registers a backend here in load(), then +// implements the `storage-dispatch` export the host calls to enumerate and +// scan. The native library that reads the foreign store (e.g. SQLite) is +// compiled to wasm INSIDE the component, behind this stable boundary. +// +// Kept as a SEPARATE interface (not folded into runtime's capability variant) +// so existing components' frozen WIT copies stay structurally unchanged. +interface storage { + use types.{duckerror, duckvalue, extopts}; + + // Comparison pushed into a scan as an AND-ed predicate. + enum compare-op { + eq, ne, lt, le, gt, ge, is-null, is-not-null, + } + + // One predicate. `column` indexes the table's FULL column list (not the + // projection). Pushdown is best-effort: the engine re-applies every filter, + // so a backend may ignore any predicate it cannot evaluate. + record scan-filter { + column: u32, + op: compare-op, + value: duckvalue, // ignored for is-null / is-not-null + } + + // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. + record scan-request { + table: string, + projection: list, // column indices to emit, in order; empty = all + filters: list, + limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row + } + + // Called by the component in load() to declare a backend keyed by an ATTACH + // TYPE name (e.g. "sqlite"). `callback-handle` is an opaque id the host + // passes back to every storage-dispatch call so the component can route it. + register-storage: func(type-name: string, + callback-handle: u32, + options: option) -> result; +} diff --git a/crates/storage-boundary-test/wit-write/deps/duckdb-extension/types.wit b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/types.wit new file mode 100644 index 00000000..32e3a1c2 --- /dev/null +++ b/crates/storage-boundary-test/wit-write/deps/duckdb-extension/types.wit @@ -0,0 +1,173 @@ +package duckdb:extension@4.0.0; + +interface types { + // ESCAPE-HATCH logical type. The `complex` arm carries a DuckDB type-expression + // string (e.g. "INTEGER[]", "STRUCT(a INTEGER, b VARCHAR)"); the core resolves it + // to a real logical type. This makes `logicaltype` a `variant` (was an `enum`); the + // fieldless arms keep their discriminant order, so the canonical-ABI is appended-to, + // not reordered. Any FUTURE type rides this arm with no further contract bump. + variant logicaltype { + boolean, + int64, + uint64, + float64, + text, + blob, + int32, + timestamp, + int8, + int16, + uint8, + uint16, + uint32, + float32, + date, + time, + timestamptz, + decimal, + interval, + uuid, + complex(string), + } + + // DuckDB DECIMAL is a HUGEINT-backed scaled integer: + // value = ((upper as i128) << 64 | lower as i128), interpreted with + // `width` total digits and `scale` fractional digits. + record decimalvalue { + lower: u64, + upper: u64, + width: u8, + scale: u8, + } + + // DuckDB INTERVAL: months + days + microseconds components. + record intervalvalue { + months: s32, + days: s32, + micros: s64, + } + + // 128-bit UUID. hi/lo are the logical big-endian halves of the UUID value + // (NOT the sign-flipped physical hugeint storage DuckDB uses internally). + record uuidvalue { + hi: u64, + lo: u64, + } + + // ESCAPE-HATCH composite value. `type-expr` is a DuckDB type string (e.g. + // "INTEGER[]" / "STRUCT(a INTEGER, b VARCHAR)") and `json` is the value rendered + // as JSON (e.g. "[10,20,30]" / {"a":1,"b":"hi"}). This is a FLAT record -- it does + // NOT reference `duckvalue`, so there is no recursive WIT cycle. The core + // reconstructs the real LIST/STRUCT vector from the JSON via the duckdb C vector + // API (which has no recursion limit). + record complexvalue { + type-expr: string, + json: string, + } + + record funcarg { + name: option, + logical: logicaltype, + } + + flags funcflags { + deterministic, + commutative, + stateless, + sideeffecting, + deprecated, + } + + record funcopts { + description: option, + tags: list, + attributes: funcflags, + } + + record columndef { + name: string, + logical: logicaltype, + } + + record extopts { + description: option, + tags: list, + } + + variant duckvalue { + null, + boolean(bool), + int64(s64), + uint64(u64), + float64(f64), + text(string), + blob(list), + int32(s32), + timestamp(s64), + int8(s8), + int16(s16), + uint8(u8), + uint16(u16), + uint32(u32), + float32(f32), + date(s32), + time(s64), + timestamptz(s64), + decimal(decimalvalue), + interval(intervalvalue), + uuid(uuidvalue), + complex(complexvalue), + } + + type resultset = list>; + type rowbatch = list>; + + record invokeinfo { + rowindex: option, + iswindow: bool, + } + + variant duckerror { + invalidargument(string), + unsupported(string), + invalidstate(string), + io(string), + internal(string), + } + + variant configerror { + invalidkey(string), + typemismatch(string), + unavailable(string), + internalconfig(string), + } + + enum loglevel { + trace, + debug, + info, + warn, + error, + } + + record logfield { + key: string, + value: string, + } + + record loadresult { + name: string, + version: option, + requires: list, + } + + enum capabilitykind { + scalar, + table, + aggregate, + pragma, + macro, + catalog, + file-format, + } +} diff --git a/crates/storage-boundary-test/wit/boundary.wit b/crates/storage-boundary-test/wit/boundary.wit index 0fab5da1..36219567 100644 --- a/crates/storage-boundary-test/wit/boundary.wit +++ b/crates/storage-boundary-test/wit/boundary.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use runtime; use callback-dispatch; diff --git a/crates/storage-boundary-test/wit/callback-dispatch.wit b/crates/storage-boundary-test/wit/callback-dispatch.wit index 4bcb3a34..ff36486b 100644 --- a/crates/storage-boundary-test/wit/callback-dispatch.wit +++ b/crates/storage-boundary-test/wit/callback-dispatch.wit @@ -1,19 +1,41 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; +use column-types; +// major-4 COLUMNAR dispatch. The hot path (per-DataChunk scalar / aggregate / +// cast) is now columnar: arguments cross the canonical ABI as typed `colvec`s +// (one bulk memcpy per fixed-width column) instead of the row-major +// `list>` tagged-variant batch that major-3 used. The cold +// singleton paths (call-scalar / call-table / call-pragma / call-cast) stay +// row-major `duckvalue` for ergonomics -- they are off the hot path. See +// column-types.wit and docs/v4-columnar-abi.md. interface callback-dispatch { - use types.{duckerror, duckvalue, invokeinfo, resultset, rowbatch}; + use types.{duckerror, duckvalue, invokeinfo, resultset}; + use column-types.{colvec}; - call-scalar: func(handle: u32, args: list, ctx: invokeinfo) -> result; - // Batched scalar dispatch: one call per DataChunk (<= 2048 rows) instead of - // one per row, amortizing the WIT boundary crossing. `rows` is the chunk's - // arguments (one inner list per row); `ctx.rowindex` is the first row's index - // (the i-th row is ctx.rowindex + i). Returns one result value per row, in - // order. Semantically identical to calling call-scalar per row. - call-scalar-batch: func(handle: u32, rows: rowbatch, ctx: invokeinfo) -> result, duckerror>; + // HOT PATH: one columnar call per DataChunk. `args` is one colvec per + // argument column (all with the same `rows`); the result is a single colvec + // of the function's return type, same `rows`. Row i of every input column + // maps to row i of the output, validity preserved. Fixed-width columns cross + // as bulk memcpy. Semantically identical to a per-row call-scalar loop. + call-scalar-batch-col: func(handle: u32, args: list, ctx: invokeinfo) + -> result; + + // Columnar aggregate fold: the buffered group as columns (one colvec per + // argument). The guest folds in-vector (state never crosses the boundary, as + // in major-3) and returns the single finalized value. + call-aggregate-col: func(handle: u32, args: list) + -> result; + + // Columnar cast: one input column -> one output column. + call-cast-col: func(handle: u32, arg: colvec) -> result; + + // --- cold singleton paths kept row-major (not on the hot path) --- + call-scalar: func(handle: u32, args: list, ctx: invokeinfo) + -> result; call-table: func(handle: u32, args: list) -> result; - call-aggregate: func(handle: u32, rows: rowbatch) -> result; - call-pragma: func(handle: u32, args: list) -> result, duckerror>; + call-pragma: func(handle: u32, args: list) + -> result, duckerror>; call-cast: func(handle: u32, value: duckvalue) -> result; } diff --git a/crates/storage-boundary-test/wit/catalog.wit b/crates/storage-boundary-test/wit/catalog.wit index c9f88c66..840c4c1c 100644 --- a/crates/storage-boundary-test/wit/catalog.wit +++ b/crates/storage-boundary-test/wit/catalog.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; interface catalog { use runtime.{cast-callback}; diff --git a/crates/storage-boundary-test/wit/column-types.wit b/crates/storage-boundary-test/wit/column-types.wit new file mode 100644 index 00000000..be31d050 --- /dev/null +++ b/crates/storage-boundary-test/wit/column-types.wit @@ -0,0 +1,69 @@ +// LIVE major-4 columnar value model (duckdb:extension@4.0.0). +// +// The columnar counterpart of types.wit's row-major `duckvalue`. This is the +// HOT-PATH transfer unit for scalar/aggregate/cast dispatch on major-4: the core +// fills a `colvec` by memcpy-ing straight from `duckdb_vector_get_data` and the +// guest lifts it as a bulk slice -- no per-cell tagged-variant marshalling. +// +// The win: a fixed-width `column` arm (e.g. `int64(list)`) crosses the +// canonical ABI as a SINGLE bulk memcpy, vs the (now-removed) row-major +// `list>` which serialized a ~24-byte tagged variant per cell +// plus a per-row inner-list realloc. Measured 82-110x on a 1M-row i64 scalar +// (benches/columnar-abi-prototype). +package duckdb:extension@4.0.0; + +interface column-types { + // Re-used flat records from the row-major model (identical layout). + record decimalvalue { lower: u64, upper: u64, width: u8, scale: u8 } + record intervalvalue { months: s32, days: s32, micros: s64 } + record uuidvalue { hi: u64, lo: u64 } + record complexvalue { type-expr: string, json: string } + + // A typed, contiguous COLUMN: one buffer per DuckDB physical type. DuckDB + // vectors are ALREADY flat contiguous arrays, so the core fills these arms by + // memcpy-ing straight from `duckdb_vector_get_data` -- no per-cell read loop. + // + // Fixed-width arms (boolean..uuid) lower/lift as a bulk memcpy. The two + // variable-width arms (text/blob) stay element-wise -- unavoidable for + // var-len data, and identical in cost to the row-major path for those types. + // The escape hatch (`complex`) is also element-wise; FUTURE composite types + // ride it with no further contract bump, exactly as the row-major `complex`. + variant column { + boolean(list), + int64(list), + uint64(list), + float64(list), + int32(list), + timestamp(list), + int8(list), + int16(list), + uint8(list), + uint16(list), + uint32(list), + float32(list), + date(list), + time(list), + timestamptz(list), + decimal(list), + interval(list), + uuid(list), + text(list), + blob(list>), + complex(list), + } + + // A column plus its validity + row count -- the unit of columnar transfer. + // + // `validity` is a packed little-endian bitmap (bit i set => row i valid), + // byte-for-byte the layout of DuckDB's own validity mask, so the core copies + // `duckdb_vector_get_validity` straight in. An EMPTY bitmap means "all rows + // valid" (the common fast path: zero allocation, mirroring DuckDB's null + // validity pointer). NULL is carried out-of-band here, so the data buffer + // stays a flat typed array -- NULL handling is identical to the row-major + // path (where a NULL is the `duckvalue.null` arm). + record colvec { + data: column, + validity: list, + rows: u32, + } +} diff --git a/crates/storage-boundary-test/wit/config.wit b/crates/storage-boundary-test/wit/config.wit index 82a446a7..ddc6e5d4 100644 --- a/crates/storage-boundary-test/wit/config.wit +++ b/crates/storage-boundary-test/wit/config.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; diff --git a/crates/storage-boundary-test/wit/files.wit b/crates/storage-boundary-test/wit/files.wit index 2b7b4895..fe16d0f8 100644 --- a/crates/storage-boundary-test/wit/files.wit +++ b/crates/storage-boundary-test/wit/files.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; interface files { type table-function-handle = u32; diff --git a/crates/storage-boundary-test/wit/guest.wit b/crates/storage-boundary-test/wit/guest.wit index 99f79631..df6d06fa 100644 --- a/crates/storage-boundary-test/wit/guest.wit +++ b/crates/storage-boundary-test/wit/guest.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; diff --git a/crates/storage-boundary-test/wit/logging.wit b/crates/storage-boundary-test/wit/logging.wit index 04caa4b5..8e7d809f 100644 --- a/crates/storage-boundary-test/wit/logging.wit +++ b/crates/storage-boundary-test/wit/logging.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; diff --git a/crates/storage-boundary-test/wit/runtime.wit b/crates/storage-boundary-test/wit/runtime.wit index c9afdb76..e6104a71 100644 --- a/crates/storage-boundary-test/wit/runtime.wit +++ b/crates/storage-boundary-test/wit/runtime.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; diff --git a/crates/storage-boundary-test/wit/storage-dispatch.wit b/crates/storage-boundary-test/wit/storage-dispatch.wit index f97a8835..2f12888e 100644 --- a/crates/storage-boundary-test/wit/storage-dispatch.wit +++ b/crates/storage-boundary-test/wit/storage-dispatch.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; use storage; diff --git a/crates/storage-boundary-test/wit/storage.wit b/crates/storage-boundary-test/wit/storage.wit index f97df5c8..b38f983f 100644 --- a/crates/storage-boundary-test/wit/storage.wit +++ b/crates/storage-boundary-test/wit/storage.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; use types; @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/crates/storage-boundary-test/wit/types.wit b/crates/storage-boundary-test/wit/types.wit index f4d60063..32e3a1c2 100644 --- a/crates/storage-boundary-test/wit/types.wit +++ b/crates/storage-boundary-test/wit/types.wit @@ -1,4 +1,4 @@ -package duckdb:extension; +package duckdb:extension@4.0.0; interface types { // ESCAPE-HATCH logical type. The `complex` arm carries a DuckDB type-expression diff --git a/crates/table-stream-boundary-test/wit/storage-write-dispatch.wit b/crates/table-stream-boundary-test/wit/storage-write-dispatch.wit index 2617766f..2ecc2cb5 100644 --- a/crates/table-stream-boundary-test/wit/storage-write-dispatch.wit +++ b/crates/table-stream-boundary-test/wit/storage-write-dispatch.wit @@ -38,11 +38,19 @@ interface storage-write-dispatch { table: string, rowids: list) -> result; - // Update rows by row-id (parallel `rowids` / `rows`); returns the number - // updated. + // Update rows by row-id (parallel `rowids` / `rows`). Each `rows[i]` is a + // PARTIAL row that carries ONLY the SET values; the schema-index of each + // cell is given by the parallel-indexed entry in `updated-columns`, so + // `rows[i][j]` sets column `updated-columns[j]` on the row identified by + // `rowids[i]`. Mirrors the storage-host `storage-update-rows` semantic -- + // the ducklink host forwards `LogicalUpdate::columns` (captured at plan + // time by WasmPhysicalUpdate) verbatim as `updated-columns` and the SET + // cells of each child DataChunk as the parallel `rows` payload. Returns + // the number of rows successfully updated. update-rows: func(handle: u32, txn: u32, table: string, rowids: list, + updated-columns: list, rows: list>) -> result; } diff --git a/crates/table-stream-boundary-test/wit/storage.wit b/crates/table-stream-boundary-test/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/crates/table-stream-boundary-test/wit/storage.wit +++ b/crates/table-stream-boundary-test/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/deploy/r2/publish-catalog.sh b/deploy/r2/publish-catalog.sh new file mode 100755 index 00000000..feafcde6 --- /dev/null +++ b/deploy/r2/publish-catalog.sh @@ -0,0 +1,253 @@ +#!/usr/bin/env bash +# publish-catalog.sh — sync the bundled ducklink-extension catalog snapshot into +# the live R2 catalog that browser/CLI extensions fetch at runtime. +# +# Source of truth (bundled): ducklink-extension/assets/catalog-snapshot.json +# Live target (fetched by users): R2 key ducklink/catalog.json in the datalink-ext +# bucket, served publicly at https://ext.ducklink.dev/catalog.json. +# +# Why MERGE and not overwrite: +# The live catalog carries top-level fields the bundled snapshot may not +# (or may lag on): _schema (documentation of field meanings), builtins +# (statically-linked DuckDB extensions), dotcmds, categories, registry_url, +# version. These are edited on the live side between releases. Blowing them +# away with the bundle's copy would drop human-curated docs and metadata. +# +# Instead: fetch the live JSON, REPLACE the extensions array with the bundle's +# extensions array (the only thing the release actually re-derives), bump the +# `updated` timestamp to now, and put the result back. Every OTHER top-level +# key on the live catalog is preserved byte-for-byte. +# +# Backup policy: +# Before the put, the current live object is copied to +# ducklink/catalog.backup..json +# inside the same bucket. Cheap, immutable, easy to grep for a rollback. +# +# When to use this: +# After cutting a ducklink-extension release that regenerates +# assets/catalog-snapshot.json — run this with --dry-run first, review the +# additions/removals summary, then rerun without --dry-run to mirror. +# +# Usage: +# publish-catalog.sh [--snapshot ] [--dry-run] +# +# Options: +# --snapshot Local snapshot to publish. Defaults to +# $HOME/git/ducklink-extension/assets/catalog-snapshot.json. +# --dry-run Fetch + merge + diff, but do NOT back up or upload. +# +# Environment: +# R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY — R2 API creds (loaded from +# ${R2_ENV_FILE:-~/git/datalink/r2.env} if unset). +# R2_BUCKET — override the target bucket (default datalink-ext). +# R2_ACCOUNT_ID — override the R2 account (default the tegmentum account). +# +# Requires: aws CLI, python3, md5sum (or md5 on macOS). +# +# Companion to publish-native.sh (native .duckdb_extension binaries) and +# publish-artifacts.sh (plugin/standalone/browser deploy artifacts). Those +# publish immutable, digest-keyed objects; this one mutates a single mutable +# JSON file, so it does a backup + merge instead of a plain put. +set -euo pipefail + +# --- args -------------------------------------------------------------------- +DEFAULT_SNAPSHOT="$HOME/git/ducklink-extension/assets/catalog-snapshot.json" +snapshot="$DEFAULT_SNAPSHOT" +dry_run=0 + +usage() { + sed -nE '/^#/{s/^# ?//; p}' "$0" | head -n 45 + exit 1 +} + +while [ $# -gt 0 ]; do + case "$1" in + --snapshot) snapshot="$2"; shift 2;; + --dry-run) dry_run=1; shift;; + -h|--help) usage;; + *) echo "unexpected arg: $1" >&2; exit 2;; + esac +done + +if [ ! -f "$snapshot" ]; then + echo "publish-catalog: snapshot not found: $snapshot" >&2 + exit 1 +fi + +# --- credentials ------------------------------------------------------------- +R2_ENV_FILE="${R2_ENV_FILE:-$HOME/git/datalink/r2.env}" +if [ -z "${R2_ACCESS_KEY_ID:-}" ] && [ -f "$R2_ENV_FILE" ]; then + # shellcheck disable=SC1090 + set -a; source "$R2_ENV_FILE"; set +a +fi +: "${R2_ACCESS_KEY_ID:?R2_ACCESS_KEY_ID not set (CI org secret or $R2_ENV_FILE)}" +: "${R2_SECRET_ACCESS_KEY:?R2_SECRET_ACCESS_KEY not set (CI org secret or $R2_ENV_FILE)}" +R2_BUCKET="${R2_BUCKET:-datalink-ext}" +R2_ACCOUNT_ID="${R2_ACCOUNT_ID:-a633389b157fd8a9ec3d3a27cd375643}" +ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com" +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY_ID" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_ACCESS_KEY" +export AWS_DEFAULT_REGION="${AWS_DEFAULT_REGION:-auto}" + +KEY="ducklink/catalog.json" +NOW_TS="$(date -u +%Y%m%dT%H%M%SZ)" +BACKUP_KEY="ducklink/catalog.backup.${NOW_TS}.json" + +STAGE="$(mktemp -d -t ducklink-catalog.XXXX)" +trap 'rm -rf "$STAGE"' EXIT +LIVE="$STAGE/live.json" +MERGED="$STAGE/merged.json" + +echo "publish-catalog:" +echo " snapshot: $snapshot" +echo " bucket: ${R2_BUCKET}" +echo " key: ${KEY}" +echo " backup: ${BACKUP_KEY}" +echo " endpoint: ${ENDPOINT}" +[ "$dry_run" = "1" ] && echo " (dry-run — no backup, no upload)" +echo "" + +# --- fetch live -------------------------------------------------------------- +if ! aws s3api get-object --endpoint-url "$ENDPOINT" --bucket "$R2_BUCKET" --key "$KEY" "$LIVE" >/dev/null; then + echo "publish-catalog: unable to fetch current live catalog r2://${R2_BUCKET}/${KEY}" >&2 + exit 1 +fi +live_size=$(wc -c < "$LIVE" | tr -d ' ') +echo "fetched live: $live_size bytes" + +# --- merge + diff summary ---------------------------------------------------- +SNAPSHOT="$snapshot" LIVE="$LIVE" MERGED="$MERGED" NOW_ISO="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ +python3 - <<'PY' +import json, os, sys + +with open(os.environ["LIVE"]) as f: + live = json.load(f) +with open(os.environ["SNAPSHOT"]) as f: + snap = json.load(f) + +live_exts = live.get("extensions") or [] +snap_exts = snap.get("extensions") or [] +if not isinstance(snap_exts, list): + print("publish-catalog: snapshot .extensions is not a list", file=sys.stderr) + sys.exit(1) + +def names(exts): + return [e.get("name") for e in exts if isinstance(e, dict) and e.get("name")] + +live_names = names(live_exts) +snap_names = names(snap_exts) +live_set = set(live_names) +snap_set = set(snap_names) +additions = sorted(snap_set - live_set) +removals = sorted(live_set - snap_set) +unchanged = sorted(live_set & snap_set) + +# Detect in-place modifications (same name, different content). +by_name_live = {e.get("name"): e for e in live_exts if isinstance(e, dict) and e.get("name")} +by_name_snap = {e.get("name"): e for e in snap_exts if isinstance(e, dict) and e.get("name")} +modifications = [] +for n in unchanged: + if by_name_live[n] != by_name_snap[n]: + modifications.append(n) +modifications.sort() + +# Build merged catalog: live is the base, extensions is replaced wholesale, +# updated is bumped to now. Every other top-level key comes from live. +merged = dict(live) +merged["extensions"] = snap_exts +merged["updated"] = os.environ["NOW_ISO"] + +with open(os.environ["MERGED"], "w") as f: + # ensure_ascii=True keeps the file byte-identical across platforms and + # matches how the live catalog is encoded today; sort_keys=False preserves + # the top-level order the live catalog already uses. + json.dump(merged, f, ensure_ascii=True, indent=2, sort_keys=False) + f.write("\n") + +# --- diff summary --- +def sample(xs, n=25): + if len(xs) <= n: + return xs + return xs[:n] + [f"... (+{len(xs) - n} more)"] + +print("diff:") +print(f" extensions live -> snapshot : {len(live_exts)} -> {len(snap_exts)}") +print(f" additions ({len(additions)}):") +for n in sample(additions): + print(f" + {n}") +print(f" removals ({len(removals)}):") +for n in sample(removals): + print(f" - {n}") +print(f" modified (same name, different fields) ({len(modifications)}):") +for n in sample(modifications): + print(f" ~ {n}") +PY + +merged_size=$(wc -c < "$MERGED" | tr -d ' ') +echo "" +echo "merged: $merged_size bytes" + +# md5 of merged file — R2 returns this as the ETag for single-part uploads, +# so we can HEAD-verify after the put. +if command -v md5sum >/dev/null 2>&1; then + merged_md5=$(md5sum "$MERGED" | awk '{print $1}') +else + merged_md5=$(md5 -q "$MERGED") +fi +echo " md5: $merged_md5" + +if [ "$dry_run" = "1" ]; then + echo "" + echo "dry-run: skipping backup + upload. merged JSON left at:" + echo " $MERGED" + # keep the merged file around for inspection when dry-running + trap - EXIT + exit 0 +fi + +# --- backup live ------------------------------------------------------------- +echo "" +echo "backup: copying r2://${R2_BUCKET}/${KEY} -> r2://${R2_BUCKET}/${BACKUP_KEY}" +aws s3api copy-object \ + --endpoint-url "$ENDPOINT" \ + --bucket "$R2_BUCKET" \ + --copy-source "${R2_BUCKET}/${KEY}" \ + --key "$BACKUP_KEY" \ + --metadata-directive COPY \ + >/dev/null + +# --- upload merged ----------------------------------------------------------- +echo "upload: putting merged catalog to r2://${R2_BUCKET}/${KEY}" +aws s3api put-object \ + --endpoint-url "$ENDPOINT" \ + --bucket "$R2_BUCKET" \ + --key "$KEY" \ + --body "$MERGED" \ + --content-type "application/json" \ + --cache-control "public, max-age=300" \ + >/dev/null + +# --- verify at R2 origin ----------------------------------------------------- +# HEAD directly at the R2 endpoint — the CDN (ext.ducklink.dev) will lag ~5 min +# behind due to Cache-Control: max-age=300, so verifying the CDN would be flaky. +head_out=$(aws s3api head-object --endpoint-url "$ENDPOINT" --bucket "$R2_BUCKET" --key "$KEY") +remote_size=$(printf '%s' "$head_out" | python3 -c 'import json,sys;print(json.load(sys.stdin)["ContentLength"])') +remote_etag=$(printf '%s' "$head_out" | python3 -c 'import json,sys;print(json.load(sys.stdin)["ETag"].strip(chr(34)))') + +echo "verify (R2 origin):" +echo " size: local=$merged_size remote=$remote_size" +echo " etag: local(md5)=$merged_md5 remote=$remote_etag" + +fail=0 +if [ "$merged_size" != "$remote_size" ]; then + echo " FAIL: size mismatch" >&2; fail=1 +fi +if [ "$merged_md5" != "$remote_etag" ]; then + echo " FAIL: etag mismatch (upload may have been multipart; check aws s3api version)" >&2; fail=1 +fi +if [ "$fail" != "0" ]; then exit 1; fi + +echo " OK" +echo "" +echo "done. public url: https://ext.ducklink.dev/catalog.json (CDN cache TTL 300s)" +echo "backup preserved at r2://${R2_BUCKET}/${BACKUP_KEY}" diff --git a/deploy/r2/publish-native.sh b/deploy/r2/publish-native.sh new file mode 100755 index 00000000..266b1215 --- /dev/null +++ b/deploy/r2/publish-native.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash +# publish-native.sh — upload a native `.duckdb_extension` artifact to R2 for +# ducklink's `LOAD NATIVE 'name'` distribution. +# +# Layout (matches src/catalog.rs::NATIVE_BLOB_BASE): +# native/sha256///.duckdb_extension +# +# Idempotent + immutable: the digest is in the URL, so the object is either +# already correct or brand-new. Uploads set cache-control: immutable + +# content-type: application/octet-stream, so once uploaded, the object is +# safe to cache forever at the edge. +# +# Usage: +# publish-native.sh [--name ] [--platform

] +# +# Options: +# --name Registered SQL name of the extension. Defaults to the +# file's basename without .duckdb_extension. +# --platform

DuckDB platform triple (osx_arm64 / linux_amd64 / ...). +# Auto-detected from `duckdb --version` output if omitted. +# +# Environment: +# R2_ACCESS_KEY_ID + R2_SECRET_ACCESS_KEY — R2 API creds (loaded from +# ${R2_ENV_FILE:-~/git/datalink/r2.env} if unset). +# +# Requires: aws CLI, shasum. No cargo/npm build — this expects the artifact to +# already exist on disk (build separately per the ducklink-native Makefile). +# +# Companion to publish-artifacts.sh (which publishes ducklink itself as a +# community-loadable plugin/CLI/browser bundle). This script is exclusively +# for the native .duckdb_extension binaries LOAD NATIVE fetches. +set -euo pipefail + +usage() { + sed -nE '/^#/{s/^# ?//; p}' "$0" | head -n 30 + exit 1 +} + +path="" +name="" +platform="" +while [ $# -gt 0 ]; do + case "$1" in + --name) name="$2"; shift 2;; + --platform) platform="$2"; shift 2;; + -h|--help) usage;; + *) if [ -z "$path" ]; then path="$1"; shift; else echo "unexpected arg: $1" >&2; exit 2; fi;; + esac +done + +if [ -z "$path" ]; then usage; fi +if [ ! -f "$path" ]; then echo "$path: not a file" >&2; exit 1; fi + +# Default name = basename minus .duckdb_extension. +if [ -z "$name" ]; then + base=$(basename "$path") + name="${base%.duckdb_extension}" +fi + +# Default platform via duckdb --version. +if [ -z "$platform" ]; then + if command -v duckdb >/dev/null 2>&1; then + platform=$(duckdb -c "PRAGMA platform;" 2>/dev/null | tail -1 | tr -d ' ' || true) + fi + if [ -z "$platform" ]; then + echo "publish-native: unable to auto-detect platform. Pass --platform ." >&2 + exit 1 + fi +fi + +# --- credentials ------------------------------------------------------------- +R2_ENV_FILE="${R2_ENV_FILE:-$HOME/git/datalink/r2.env}" +if [ -z "${R2_ACCESS_KEY_ID:-}" ] && [ -f "$R2_ENV_FILE" ]; then + # shellcheck disable=SC1090 + set -a; source "$R2_ENV_FILE"; set +a +fi +: "${R2_ACCESS_KEY_ID:?R2_ACCESS_KEY_ID not set (CI org secret or $R2_ENV_FILE)}" +: "${R2_SECRET_ACCESS_KEY:?R2_SECRET_ACCESS_KEY not set (CI org secret or $R2_ENV_FILE)}" +R2_BUCKET="${R2_BUCKET:-datalink-ext}" +R2_ACCOUNT_ID="${R2_ACCOUNT_ID:-a633389b157fd8a9ec3d3a27cd375643}" +ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com" +export AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY_ID" +export AWS_SECRET_ACCESS_KEY="$R2_SECRET_ACCESS_KEY" + +digest=$(shasum -a 256 "$path" | awk '{print $1}') +key="native/sha256/${digest}/${platform}/${name}.duckdb_extension" + +echo "publishing:" +echo " local: $path" +echo " digest: sha256:${digest}" +echo " platform: ${platform}" +echo " name: ${name}" +echo " bucket: ${R2_BUCKET}" +echo " key: ${key}" +echo " url: https://ext.ducklink.dev/${key}" + +if aws s3api head-object --endpoint-url "$ENDPOINT" --bucket "$R2_BUCKET" --key "$key" >/dev/null 2>&1; then + echo "already present; nothing to upload (digest-keyed layout guarantees a no-op)" + exit 0 +fi + +aws s3api put-object \ + --endpoint-url "$ENDPOINT" \ + --bucket "$R2_BUCKET" \ + --key "$key" \ + --body "$path" \ + --content-type "application/octet-stream" \ + --cache-control "public, max-age=31536000, immutable" \ + >/dev/null + +# Quick verify — HEAD the object and confirm size matches. +size_local=$(wc -c < "$path" | tr -d ' ') +size_remote=$(aws s3api head-object --endpoint-url "$ENDPOINT" --bucket "$R2_BUCKET" --key "$key" --query ContentLength --output text) +if [ "$size_local" != "$size_remote" ]; then + echo "verify: size mismatch (local=$size_local remote=$size_remote)" >&2 + exit 1 +fi +echo "uploaded ($size_local bytes verified)" diff --git a/docs/python-source-tier-plan.md b/docs/python-source-tier-plan.md new file mode 100644 index 00000000..3a064169 --- /dev/null +++ b/docs/python-source-tier-plan.md @@ -0,0 +1,110 @@ +# ducklink Python Source Tier — Plan + +Status: **designed 2026-07-01, not built.** All key decisions settled. + +## Goal + +Author a ducklink extension in **Python** and run it with **no compilation**. +Guiding principle: *"you should be able to compile it — you just shouldn't have +to."* This is a third authoring tier alongside the compiled ones. + +| Tier | Build | Speed | Size | Audience | +|---|---|---|---|---| +| Rust/C → wasm | toolchain | fastest | small | perf-critical | +| Python → compiled | opt-in | fast | ~20 MB (embeds CPython) | ship a Python ext standalone | +| **Python → interpreted** | **none** | slower | source-only | glue, prototyping, reach | + +One authoring API; **two execution modes off the same `.py`** — **run** (interpret, +zero-build, default) and **compile** (opt-in). Prototype interpreted, graduate to +compiled when a hot path or a shippable artifact demands it. + +## Architecture: drive pylon, don't build a runtime + +ducklink does **not** build a Python runtime — it drives **pylon** +(`~/git/python-wasm`): CPython 3.14 (+ MicroPython 1.24) compiled to +`wasm32-wasip2`, **dynlink-first** (ADR-001), on the *same* compose:dynlink +framework as the retired sqlink loader. Pylon already provides the two hard +pieces: + +- **`tegmentum:py-offload`** — `offload.run(env-id, task{entry:"module:callable", + args:list, codec}) -> outcome(ok(bytes)|raised(py-error))`. That *is* "call + a Python function with encoded args, get an encoded result." +- **`py-package` + composectl** — content-addressed `env-id` (interpreter + + resolved wheels), backend selection, and composectl composing a + content-addressed **worker artifact** = the "compile" mode, already built. +- **deps** — pip into a `$PYLON_HOME/site-packages` mount today; uv-wasm as its + own component on pylon's roadmap. + +ducklink hosts pylon as a **resident, reentrant dynlink provider** (the #227/#228 +machinery — warm, stateful, reentrant). + +## Settled decisions + +1. **Discovery = manifest via `offload.run`.** The ducklink Python API builds a + manifest inside the script's module; ducklink reads it via + `offload.run(entry="ducklink.runtime:manifest")`. **Zero pylon change**; pylon + stays generic. +2. **Codec = arrow-columnar from day one.** A column of N rows per `offload.run`, + aligned with the ducklink `@4.0.0` columnar ABI. **Requires implementing + pylon's reserved `arrow` codec** + columnar marshalling — the one pylon-side + build item. +3. **Default runtime = CPython 3.14.** MicroPython is opt-in later. + +## What ducklink adds (small) + +1. **ducklink Python API** (pure-Python, shipped into the script env): + `@ducklink.scalar/table/aggregate` decorators mapping type hints → WIT/DuckDB + types; builds the manifest; exposes the `ducklink.runtime:manifest` entry. +2. **`ducklink_run('x.py')` glue**: host pylon as a resident reentrant provider; + run script → read manifest → register SQL functions → dispatch each call via + `offload.run` (arrow-columnar, batched). +3. **pylon arrow codec** (the one pylon-side piece). +4. **PEP 723 inline deps** (`# /// script`) → resolved to a pylon `env-id`. + +## Dispatch flow + +`ducklink_run('x.py')`: +1. Resolve the script's inline deps → a pylon `env-id`. +2. Instantiate/reuse the resident pylon provider (warm). +3. `offload.run(entry="x")` — load the script; the decorators populate the manifest. +4. `offload.run(entry="ducklink.runtime:manifest")` → `[{name, kind, args, returns, entry}]`. +5. Register each as a SQL scalar/table/aggregate. + +Per SQL call (batched, columnar): +6. Encode the input **column** (arrow) → `offload.run(task{entry:"x:fn", + args:, codec:arrow})` → decode the output column. + +Reentrancy: a Python function that itself runs SQL re-enters the engine via the +proven #221 deep-reentrant provider path. + +## Two modes, same `.py` + +- **run** — drive a shared resident pylon worker; zero-build; default. +- **compile** — composectl emits a content-addressed worker with the script baked + in (pylon already does this); for speed / self-contained distribution / no + pylon dependency. `py-package.tier: in-wasm`. + +## Phasing + +- **Phase 0 — spike:** one scalar end-to-end (`@ducklink.scalar def upper(s:str)->str`), + **msgpack-per-row** for speed of proof, on the wasmtime host — validates + run → manifest → register → dispatch before the arrow investment. +- **Phase 1:** the ducklink Python API (scalar/table/aggregate + manifest) + the + `ducklink_run` resident-provider glue. +- **Phase 2:** pylon **arrow codec** + arrow-columnar batched dispatch (the perf + tier, `@4.0.0`-aligned). +- **Phase 3:** PEP 723 inline deps → `env-id` resolution. +- **Phase 4:** **compile mode** (composectl worker artifact) + catalog integration + (source modules in the catalog). +- **Phase 5:** MicroPython opt-in; native-dep tier (Pyodide-style wasm wheels). + +## Open items / risks + +- **pylon arrow codec is unimplemented** (Phase 3 on pylon's own roadmap) — the + main new pylon-side work the codec decision forces. +- **Native deps** (numpy/pandas) need pre-built wasm wheels — a later tier; pure- + Python deps are tractable now. +- **Perf:** even batched, interpreted Python is slower than compiled — this tier + is for reach/convenience; the compiled tier owns hot paths. +- **Browser:** pylon runs in-browser via jco; the deep-reentrant arm needs jco + 1.15.x (per the #228 caveat). diff --git a/docs/v4-columnar-abi.md b/docs/v4-columnar-abi.md index 0423fef9..898a4858 100644 --- a/docs/v4-columnar-abi.md +++ b/docs/v4-columnar-abi.md @@ -111,7 +111,7 @@ Major-4 is a TRUE break: it removes the row-major batch entries and bumps (call-scalar-batch-col / call-aggregate-col / call-cast-col; cold singletons row-major) are in the live world. `CONTRACT_MAJOR = 4`, `CONTRACT_MINOR = 0`, `CONTRACT_VERSION = 4.0.0`, propagated across the tree (2397 WIT files). - New canonical digest **`a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40`** + New canonical digest **`b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3`** (43 canonical files), confirmed emitted by `ducklink-runtime/build.rs`. - **Codegen columnar emission.** `datalink-extcore`'s `duckdb_shim!` / `duckdb_agg_shim!` emit the columnar dispatch (colvec<->NeutralColVec bridge to diff --git a/docs/versioning-and-support-policy.md b/docs/versioning-and-support-policy.md new file mode 100644 index 00000000..f8195921 --- /dev/null +++ b/docs/versioning-and-support-policy.md @@ -0,0 +1,129 @@ +# ducklink Versioning & Support Policy + +Status: draft. Establishes the versioning rules before the `@4.0.0` cutover so the +first real contract bump is a non-event. + +## The three version axes + +1. **WIT contract** — `duckdb:extension@MAJOR.MINOR.PATCH`, the host↔module + interface. Its MAJOR is the *generation*. +2. **DuckDB version** — the database ducklink loads into. Owned by DuckDB, not us. +3. **Module version** — each wasm extension's own semver. + +A module artifact is uniquely keyed by **(contract-generation, duckdb-version, platform)**. + +## Core rule: lockstep major = contract generation + +- The **WIT contract MAJOR is the generation**. ducklink (the host extension) + shares it: **ducklink `4.x` speaks contract `@4`**, and modules built for it are + generation 4. +- **User-facing rule:** host major *N* runs module generation *N* — **strict + within-major; cross-major is REJECTED.** A user needs a host whose major MATCHES + the module's generation. +- **DECIDED 2026-07-01 — one uniform model across ALL hosts.** The + `ducklink-runtime` CLI + the browser/demo cores already enforce within-major + forward-compat and reject cross-major (`ducklink-runtime/src/lib.rs:84-94, + 141-157`); the **native extension is being tightened to match** (v4.0.1), + removing its earlier lenient "runs generations ≤ N" cross-major loading. This + supersedes the earlier backward-compat verification — backward-compat is NOT a + guarantee; the model is strict same-major. (Tightening requires the extension's + bundled snapshot to be gen-4, so offline name-resolution/loads aren't rejected — + shipped together in v4.0.1.) +- **Implementation (decoupled):** each module keeps its **own semver**; the catalog + `providers[].abi` records the contract generation each provider blob was built + for. The host resolves by selecting the **newest provider whose generation ≤ the + host's**, falling back to the entry's top-level `content_digest`. This gives the + simple "match on major" signal *without* overloading a module's own semver (so a + module's independent breaking change still has room). +- **Backward-compat is not guaranteed forever.** The @2→@4 transition preserved it + (old components still instantiate on the new host), so today's effective rule is + "host runs generations ≤ N." A future breaking generation only requires revising + two centralized spots — `select_provider` and the `runnable` predicate. +- **Coupling is MAJOR-only.** Additive contract changes (`@4.0 → @4.1`) are + backward-compatible — a gen-4.0 module runs on a 4.1 host; no module rebuild is + forced. + +## The @4.0.0 cutover + +- Bump **ducklink `0.5.x → 4.0.0`** to align the host version with contract + generation 4 (semver permits a free major jump; it signals the generation). +- Reconcile the 6 straggler modules (`a5`, `jsonata`, `minijinja`, `pcap`, + `sqlitecompat`, `tera`) into the `@4.0.0` line and rebuild them for gen-4. +- Publish a single gen-4 catalog. Retire the enriched `@2.2.0` catalog once gen-4 + is complete **and the WIT is frozen**. + +## Contract-bump cadence + +- MAJOR bumps are **rare, deliberate events** — only for genuinely breaking WIT + changes. The WIT freeze policy is the lever that keeps them infrequent. +- Everything else ships as additive contract MINORs (no new-blob obligation) or as + module minor/patch. +- Goal: **≤ 2 live generations** at any time. + +## Multi-generation support window + +- Support **current + previous generation (N and N-1)**. +- When N+1 ships: N-1 → `deprecated`; **EOL 6 months after deprecation** (one + DuckDB release cycle). +- Each supported generation = a full, reproducible blob set (deterministic build + pipeline) + catalog providers for that generation. +- Blobs are **content-addressed and immutable**, so generations coexist at ~zero + cost. **Never delete a blob inside a supported window.** +- Surface status in the catalog (`providers[].status`: `supported` / `deprecated` + / `eol`) and via `ducklink.capabilities` / a new `ducklink.versions` view. + +## DuckDB-version axis (separate; DuckDB-owned) + +- DuckDB distributes extensions per **(duckdb-version, platform)**. + community-extensions rebuilds for **latest-stable + next** on each DuckDB + release; **old binaries are frozen**, not updated. +- **Consequence (community channel only):** through **community-extensions** you + cannot ship bugfixes to users on *old* DuckDB versions — its pipeline builds + only latest-stable + next, and old binaries are frozen. This limit is specific + to the community channel. **We can still support old versions ourselves** by + publishing our own builds to a `custom_extension_repository` (see escape + hatches) — we control exactly which DuckDB versions we build and patch for. The + trade-off vs. community is ours to run (build matrix + users set the repo). +- **Escape hatches:** + - **Self-host** via `custom_extension_repository` — you own the build matrix and + can target any DuckDB versions. + - **Stable C ABI (common tier only)** — one portable binary would load across + every DuckDB with extension API ≥ `1.2.0`, carrying fixes to all versions in + the window. **Blocked upstream today:** `libduckdb-sys` hardcodes + `-DDUCKDB_EXTENSION_API_VERSION_UNSTABLE` (`build.rs:624`), stamping the footer + `C_STRUCT_UNSTABLE`. The registration APIs the common tier needs + (`register_{scalar,table,aggregate}_function`) are in the stable `v1.2.0` set, + so portability is reachable via a duckdb-rs "stable ABI" build mode (or a + hand-rolled entrypoint) + a symbol audit + a `C_STRUCT` / `min_duckdb_version` + footer. + +## Tier portability summary + +| Tier | Surface | ABI | DuckDB-version | Platforms | +|---|---|---|---|---| +| **Common** | `ducklink_load`, `ducklink.*` views | stable C API (currently pinned by `libduckdb-sys`) | portable *if* moved to stable ABI; else per-version | all | +| **Advanced** | `LOAD WASM` | internal C++ ABI | **hard-locked** to exact DuckDB version | osx/linux only | + +## Decisions & open items + +- **EOL window: 6 months** after deprecation (one DuckDB cycle). ✓ decided. +- **In progress:** host provider-selection-by-generation + `providers[].status` + + a `ducklink.versions` view (client resolves the top-level `content_digest` + today, not a per-generation provider). +- **On hold:** the stable-ABI build-mode ask to duckdb-rs / `libduckdb-sys` (would + let one common-tier binary span DuckDB versions). Not required for old-version + support — self-publishing to a `custom_extension_repository` already covers + that; revisit only as a convenience if the per-version build matrix becomes + painful. +- **Symbol audit DONE (2026-06-30):** the common tier is stable-`v1.2.0`-clean + EXCEPT that `duckdb-rs` executes all SQL over the UNSTABLE Arrow C-API + (`Connection::execute` → `duckdb_execute_prepared_arrow` / `duckdb_query_arrow_schema` / + `duckdb_arrow_rows_changed`). ducklink's own code hits it in exactly TWO spots: + the `COMMENT ON FUNCTION` (`src/lib.rs:310`) and the `ducklink.*` view creation + (`src/reg_duckdb.rs:1610`). All registration / vector I/O / dispatch / aggregates + are stable; the suspected client-context / bind-result-column / vector-create + helpers are NOT reached. So a stable-portable common tier = (1) a `libduckdb-sys` + stable-build mode (drop the forced `-DDUCKDB_EXTENSION_API_VERSION_UNSTABLE`, + `build.rs:624`) + (2) re-plumb those two `con.execute` calls onto stable + `duckdb_prepare` + `duckdb_execute_prepared` + `duckdb_fetch_chunk`. Small and + scoped, not a rewrite. Advanced tier is unaffected (inherently version-locked). diff --git a/extensions/mysqlwasm-component/src/bindings.rs b/extensions/mysqlwasm-component/src/bindings.rs index c128d801..8b7908fa 100644 --- a/extensions/mysqlwasm-component/src/bindings.rs +++ b/extensions/mysqlwasm-component/src/bindings.rs @@ -8494,6 +8494,15 @@ pub mod duckdb { } } /// What the engine asks a scan to produce. + /// + /// `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + /// rowid as the FINAL cell of every row returned by `storage-scan-next` + /// (after the projected column cells, which stay in projection order). The + /// ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + /// `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + /// WasmScanInitGlobal strips those rowid slots from `projection` and sets + /// this flag so the guest supplies the rowid values the sink then round- + /// trips into `storage-write-dispatch.update-rows` / `.delete-rows`. #[derive(Clone)] pub struct ScanRequest { pub table: _rt::String, @@ -8501,6 +8510,8 @@ pub mod duckdb { /// column indices to emit, in order; empty = all pub filters: _rt::Vec, pub limit: Option, + /// best-effort row cap + pub wants_rowid: bool, } impl ::core::fmt::Debug for ScanRequest { fn fmt( @@ -8512,6 +8523,7 @@ pub mod duckdb { .field("projection", &self.projection) .field("filters", &self.filters) .field("limit", &self.limit) + .field("wants-rowid", &self.wants_rowid) .finish() } } @@ -16382,6 +16394,7 @@ pub mod exports { arg7: usize, arg8: i32, arg9: i64, + arg10: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); let len0 = arg3; @@ -16638,6 +16651,7 @@ pub mod exports { } _ => _rt::invalid_enum_discriminant(), }, + wants_rowid: _rt::bool_lift(arg10 as u8), }, ); let ptr44 = (&raw mut _RET_AREA.0).cast::(); @@ -17665,10 +17679,11 @@ pub mod exports { "duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn export_storage_scan_open(arg0 : i32, arg1 : i32, arg2 : * mut u8, arg3 : usize, arg4 : * mut u8, arg5 : - usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64,) -> - * mut u8 { unsafe { $($path_to_types)*:: + usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64, + arg10 : i32,) -> * mut u8 { unsafe { $($path_to_types)*:: _export_storage_scan_open_cabi::<$ty > (arg0, arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8, arg9) } } #[unsafe (export_name = + arg4, arg5, arg6, arg7, arg8, arg9, arg10) } } #[unsafe + (export_name = "cabi_post_duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn _post_return_storage_scan_open(arg0 : * mut u8,) { unsafe { $($path_to_types)*:: @@ -17999,8 +18014,8 @@ pub(crate) use __export_duckdb_extension_storage_impl as export; )] #[doc(hidden)] #[allow(clippy::octal_escapes)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6757] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd63\x01A\x02\x01A(\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6770] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xe33\x01A\x02\x01A(\x01\ B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04text\0\0\ \x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05uint8\0\0\ \x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0btimestamp\ @@ -18104,55 +18119,55 @@ scan\x0c\0\x0f\x04\0\x19register-replacement-scan\x01\x10\x01j\x01\x07\x01s\x01@ \0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x04\x04\0\x07\ extopts\x03\0\x04\x01m\x08\x02eq\x02ne\x02lt\x02le\x02gt\x02ge\x07is-null\x0bis-\ not-null\x04\0\x0acompare-op\x03\0\x06\x01r\x03\x06columny\x02op\x07\x05value\x03\ -\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x04\x05tables\x0aproje\ -ction\x0a\x07filters\x0b\x05limit\x0c\x04\0\x0cscan-request\x03\0\x0d\x01k\x05\x01\ -j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07options\x0f\0\x10\x04\ -\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/storage@4.0.0\x05\x15\x01\ -B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecimalvalue\x03\ -\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\x03\0\x02\x01\ -r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\x09type-exprs\x04jsons\ -\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01pu\x01pz\x01p~\x01p|\x01\ -p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01p\x0f\x01p\x07\x01q\x15\ -\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\0\x07float64\x01\x0b\0\ -\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\0\x05int16\x01\x0e\0\x05\ -uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\x07float32\x01\x12\0\x04\ -date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\0\x07decimal\x01\x13\0\x08\ -interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\x04blob\x01\x17\0\x07comp\ -lex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04data\x1a\x08validity\x0f\x04\ -rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension/column-types@4.0.0\x05\x16\ -\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\ -\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01j\x01\x03\x01\x01\x01@\0\ -\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01@\x01\x04keys\x06\0\x07\ -\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutdown\x01\x09\x04\0\x1cdu\ -ckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colvec\x01B\x1f\x02\x03\x02\x01\ -\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\ -\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\x09\x04\0\x09\ -resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\0\x08\x01p\x09\x01j\x01\ -\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\x15call-scal\ -ar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06handley\x04args\x0a\0\x0d\x04\ -\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03arg\x09\0\x0b\x04\0\x0dc\ -all-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04args\x10\x03ctx\x05\0\x0d\x04\ -\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\x06handley\x04args\x10\0\ -\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\x01\x01@\x02\x06handl\ -ey\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\x06handley\x05value\x03\ -\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension/callback-dispatch@4.0.0\ -\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\x01\x02\x04\0\x09ducker\ -ror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\ -\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0cscan-request\x03\0\x06\ -\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\x03dsns\x07options\x09\ -\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\x01@\x03\x06handley\x03\ -dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01ps\x01j\x01\x0f\x01\x01\x01\ -@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-list-tables\x01\x11\x01p\x03\ -\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\x05tables\0\x13\x04\0\x15s\ -torage-table-columns\x01\x14\x01@\x03\x06handley\x07catalogy\x07request\x07\0\x0a\ -\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\x01\x01@\x03\x06handley\x04\ -scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\x17\x01j\x01\x7f\x01\x01\ -\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-scan-close\x01\x19\x01@\x02\ -\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\x1a\x04\0'duckdb:exten\ -sion/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extension/duckdb-extension-stor\ -age@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\x03\0\0\0G\x09producer\ -s\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x060.4\ -1.0"; +\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x05\x05tables\x0aproje\ +ction\x0a\x07filters\x0b\x05limit\x0c\x0bwants-rowid\x7f\x04\0\x0cscan-request\x03\ +\0\x0d\x01k\x05\x01j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07\ +options\x0f\0\x10\x04\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/st\ +orage@4.0.0\x05\x15\x01B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\ +\0\x0cdecimalvalue\x03\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dinte\ +rvalvalue\x03\0\x02\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\ +\x09type-exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01\ +pu\x01pz\x01p~\x01p|\x01p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01\ +p\x0f\x01p\x07\x01q\x15\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\ +\0\x07float64\x01\x0b\0\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\ +\0\x05int16\x01\x0e\0\x05uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\ +\x07float32\x01\x12\0\x04date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\ +\0\x07decimal\x01\x13\0\x08interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\ +\x04blob\x01\x17\0\x07complex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04da\ +ta\x1a\x08validity\x0f\x04rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension\ +/column-types@4.0.0\x05\x16\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\ +\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01\ +j\x01\x03\x01\x01\x01@\0\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01\ +@\x01\x04keys\x06\0\x07\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutd\ +own\x01\x09\x04\0\x1cduckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colve\ +c\x01B\x1f\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\ +\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\ +\x02\x01\x09\x04\0\x09resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\ +\0\x08\x01p\x09\x01j\x01\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\ +\x0b\x04\0\x15call-scalar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06han\ +dley\x04args\x0a\0\x0d\x04\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03\ +arg\x09\0\x0b\x04\0\x0dcall-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04arg\ +s\x10\x03ctx\x05\0\x0d\x04\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\ +\x06handley\x04args\x10\0\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\ +\x01\x01@\x02\x06handley\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\ +\x06handley\x05value\x03\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension\ +/callback-dispatch@4.0.0\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\ +\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\ +\x02\x02\x03\x02\x01\x09\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0c\ +scan-request\x03\0\x06\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\ +\x03dsns\x07options\x09\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\ +\x01@\x03\x06handley\x03dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01\ +ps\x01j\x01\x0f\x01\x01\x01@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-l\ +ist-tables\x01\x11\x01p\x03\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\ +\x05tables\0\x13\x04\0\x15storage-table-columns\x01\x14\x01@\x03\x06handley\x07c\ +atalogy\x07request\x07\0\x0a\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\ +\x01\x01@\x03\x06handley\x04scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\ +\x17\x01j\x01\x7f\x01\x01\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-sc\ +an-close\x01\x19\x01@\x02\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\ +\x1a\x04\0'duckdb:extension/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extensio\ +n/duckdb-extension-storage@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\ +\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10\ +wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/extensions/mysqlwasm-component/wit/storage.wit b/extensions/mysqlwasm-component/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/extensions/mysqlwasm-component/wit/storage.wit +++ b/extensions/mysqlwasm-component/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/extensions/numstream-component/wit/storage-write-dispatch.wit b/extensions/numstream-component/wit/storage-write-dispatch.wit index 2617766f..2ecc2cb5 100644 --- a/extensions/numstream-component/wit/storage-write-dispatch.wit +++ b/extensions/numstream-component/wit/storage-write-dispatch.wit @@ -38,11 +38,19 @@ interface storage-write-dispatch { table: string, rowids: list) -> result; - // Update rows by row-id (parallel `rowids` / `rows`); returns the number - // updated. + // Update rows by row-id (parallel `rowids` / `rows`). Each `rows[i]` is a + // PARTIAL row that carries ONLY the SET values; the schema-index of each + // cell is given by the parallel-indexed entry in `updated-columns`, so + // `rows[i][j]` sets column `updated-columns[j]` on the row identified by + // `rowids[i]`. Mirrors the storage-host `storage-update-rows` semantic -- + // the ducklink host forwards `LogicalUpdate::columns` (captured at plan + // time by WasmPhysicalUpdate) verbatim as `updated-columns` and the SET + // cells of each child DataChunk as the parallel `rows` payload. Returns + // the number of rows successfully updated. update-rows: func(handle: u32, txn: u32, table: string, rowids: list, + updated-columns: list, rows: list>) -> result; } diff --git a/extensions/numstream-component/wit/storage.wit b/extensions/numstream-component/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/extensions/numstream-component/wit/storage.wit +++ b/extensions/numstream-component/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/extensions/postgreswasm-component/src/bindings.rs b/extensions/postgreswasm-component/src/bindings.rs index c128d801..8b7908fa 100644 --- a/extensions/postgreswasm-component/src/bindings.rs +++ b/extensions/postgreswasm-component/src/bindings.rs @@ -8494,6 +8494,15 @@ pub mod duckdb { } } /// What the engine asks a scan to produce. + /// + /// `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + /// rowid as the FINAL cell of every row returned by `storage-scan-next` + /// (after the projected column cells, which stay in projection order). The + /// ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + /// `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + /// WasmScanInitGlobal strips those rowid slots from `projection` and sets + /// this flag so the guest supplies the rowid values the sink then round- + /// trips into `storage-write-dispatch.update-rows` / `.delete-rows`. #[derive(Clone)] pub struct ScanRequest { pub table: _rt::String, @@ -8501,6 +8510,8 @@ pub mod duckdb { /// column indices to emit, in order; empty = all pub filters: _rt::Vec, pub limit: Option, + /// best-effort row cap + pub wants_rowid: bool, } impl ::core::fmt::Debug for ScanRequest { fn fmt( @@ -8512,6 +8523,7 @@ pub mod duckdb { .field("projection", &self.projection) .field("filters", &self.filters) .field("limit", &self.limit) + .field("wants-rowid", &self.wants_rowid) .finish() } } @@ -16382,6 +16394,7 @@ pub mod exports { arg7: usize, arg8: i32, arg9: i64, + arg10: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); let len0 = arg3; @@ -16638,6 +16651,7 @@ pub mod exports { } _ => _rt::invalid_enum_discriminant(), }, + wants_rowid: _rt::bool_lift(arg10 as u8), }, ); let ptr44 = (&raw mut _RET_AREA.0).cast::(); @@ -17665,10 +17679,11 @@ pub mod exports { "duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn export_storage_scan_open(arg0 : i32, arg1 : i32, arg2 : * mut u8, arg3 : usize, arg4 : * mut u8, arg5 : - usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64,) -> - * mut u8 { unsafe { $($path_to_types)*:: + usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64, + arg10 : i32,) -> * mut u8 { unsafe { $($path_to_types)*:: _export_storage_scan_open_cabi::<$ty > (arg0, arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8, arg9) } } #[unsafe (export_name = + arg4, arg5, arg6, arg7, arg8, arg9, arg10) } } #[unsafe + (export_name = "cabi_post_duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn _post_return_storage_scan_open(arg0 : * mut u8,) { unsafe { $($path_to_types)*:: @@ -17999,8 +18014,8 @@ pub(crate) use __export_duckdb_extension_storage_impl as export; )] #[doc(hidden)] #[allow(clippy::octal_escapes)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6757] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd63\x01A\x02\x01A(\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6770] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xe33\x01A\x02\x01A(\x01\ B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04text\0\0\ \x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05uint8\0\0\ \x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0btimestamp\ @@ -18104,55 +18119,55 @@ scan\x0c\0\x0f\x04\0\x19register-replacement-scan\x01\x10\x01j\x01\x07\x01s\x01@ \0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x04\x04\0\x07\ extopts\x03\0\x04\x01m\x08\x02eq\x02ne\x02lt\x02le\x02gt\x02ge\x07is-null\x0bis-\ not-null\x04\0\x0acompare-op\x03\0\x06\x01r\x03\x06columny\x02op\x07\x05value\x03\ -\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x04\x05tables\x0aproje\ -ction\x0a\x07filters\x0b\x05limit\x0c\x04\0\x0cscan-request\x03\0\x0d\x01k\x05\x01\ -j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07options\x0f\0\x10\x04\ -\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/storage@4.0.0\x05\x15\x01\ -B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecimalvalue\x03\ -\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\x03\0\x02\x01\ -r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\x09type-exprs\x04jsons\ -\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01pu\x01pz\x01p~\x01p|\x01\ -p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01p\x0f\x01p\x07\x01q\x15\ -\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\0\x07float64\x01\x0b\0\ -\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\0\x05int16\x01\x0e\0\x05\ -uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\x07float32\x01\x12\0\x04\ -date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\0\x07decimal\x01\x13\0\x08\ -interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\x04blob\x01\x17\0\x07comp\ -lex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04data\x1a\x08validity\x0f\x04\ -rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension/column-types@4.0.0\x05\x16\ -\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\ -\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01j\x01\x03\x01\x01\x01@\0\ -\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01@\x01\x04keys\x06\0\x07\ -\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutdown\x01\x09\x04\0\x1cdu\ -ckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colvec\x01B\x1f\x02\x03\x02\x01\ -\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\ -\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\x09\x04\0\x09\ -resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\0\x08\x01p\x09\x01j\x01\ -\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\x15call-scal\ -ar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06handley\x04args\x0a\0\x0d\x04\ -\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03arg\x09\0\x0b\x04\0\x0dc\ -all-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04args\x10\x03ctx\x05\0\x0d\x04\ -\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\x06handley\x04args\x10\0\ -\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\x01\x01@\x02\x06handl\ -ey\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\x06handley\x05value\x03\ -\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension/callback-dispatch@4.0.0\ -\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\x01\x02\x04\0\x09ducker\ -ror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\ -\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0cscan-request\x03\0\x06\ -\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\x03dsns\x07options\x09\ -\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\x01@\x03\x06handley\x03\ -dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01ps\x01j\x01\x0f\x01\x01\x01\ -@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-list-tables\x01\x11\x01p\x03\ -\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\x05tables\0\x13\x04\0\x15s\ -torage-table-columns\x01\x14\x01@\x03\x06handley\x07catalogy\x07request\x07\0\x0a\ -\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\x01\x01@\x03\x06handley\x04\ -scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\x17\x01j\x01\x7f\x01\x01\ -\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-scan-close\x01\x19\x01@\x02\ -\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\x1a\x04\0'duckdb:exten\ -sion/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extension/duckdb-extension-stor\ -age@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\x03\0\0\0G\x09producer\ -s\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x060.4\ -1.0"; +\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x05\x05tables\x0aproje\ +ction\x0a\x07filters\x0b\x05limit\x0c\x0bwants-rowid\x7f\x04\0\x0cscan-request\x03\ +\0\x0d\x01k\x05\x01j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07\ +options\x0f\0\x10\x04\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/st\ +orage@4.0.0\x05\x15\x01B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\ +\0\x0cdecimalvalue\x03\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dinte\ +rvalvalue\x03\0\x02\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\ +\x09type-exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01\ +pu\x01pz\x01p~\x01p|\x01p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01\ +p\x0f\x01p\x07\x01q\x15\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\ +\0\x07float64\x01\x0b\0\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\ +\0\x05int16\x01\x0e\0\x05uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\ +\x07float32\x01\x12\0\x04date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\ +\0\x07decimal\x01\x13\0\x08interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\ +\x04blob\x01\x17\0\x07complex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04da\ +ta\x1a\x08validity\x0f\x04rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension\ +/column-types@4.0.0\x05\x16\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\ +\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01\ +j\x01\x03\x01\x01\x01@\0\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01\ +@\x01\x04keys\x06\0\x07\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutd\ +own\x01\x09\x04\0\x1cduckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colve\ +c\x01B\x1f\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\ +\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\ +\x02\x01\x09\x04\0\x09resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\ +\0\x08\x01p\x09\x01j\x01\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\ +\x0b\x04\0\x15call-scalar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06han\ +dley\x04args\x0a\0\x0d\x04\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03\ +arg\x09\0\x0b\x04\0\x0dcall-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04arg\ +s\x10\x03ctx\x05\0\x0d\x04\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\ +\x06handley\x04args\x10\0\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\ +\x01\x01@\x02\x06handley\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\ +\x06handley\x05value\x03\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension\ +/callback-dispatch@4.0.0\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\ +\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\ +\x02\x02\x03\x02\x01\x09\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0c\ +scan-request\x03\0\x06\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\ +\x03dsns\x07options\x09\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\ +\x01@\x03\x06handley\x03dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01\ +ps\x01j\x01\x0f\x01\x01\x01@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-l\ +ist-tables\x01\x11\x01p\x03\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\ +\x05tables\0\x13\x04\0\x15storage-table-columns\x01\x14\x01@\x03\x06handley\x07c\ +atalogy\x07request\x07\0\x0a\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\ +\x01\x01@\x03\x06handley\x04scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\ +\x17\x01j\x01\x7f\x01\x01\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-sc\ +an-close\x01\x19\x01@\x02\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\ +\x1a\x04\0'duckdb:extension/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extensio\ +n/duckdb-extension-storage@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\ +\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10\ +wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/extensions/postgreswasm-component/wit/storage.wit b/extensions/postgreswasm-component/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/extensions/postgreswasm-component/wit/storage.wit +++ b/extensions/postgreswasm-component/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/extensions/sqlitewasm-component/src/bindings.rs b/extensions/sqlitewasm-component/src/bindings.rs index c128d801..8b7908fa 100644 --- a/extensions/sqlitewasm-component/src/bindings.rs +++ b/extensions/sqlitewasm-component/src/bindings.rs @@ -8494,6 +8494,15 @@ pub mod duckdb { } } /// What the engine asks a scan to produce. + /// + /// `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + /// rowid as the FINAL cell of every row returned by `storage-scan-next` + /// (after the projected column cells, which stay in projection order). The + /// ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + /// `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + /// WasmScanInitGlobal strips those rowid slots from `projection` and sets + /// this flag so the guest supplies the rowid values the sink then round- + /// trips into `storage-write-dispatch.update-rows` / `.delete-rows`. #[derive(Clone)] pub struct ScanRequest { pub table: _rt::String, @@ -8501,6 +8510,8 @@ pub mod duckdb { /// column indices to emit, in order; empty = all pub filters: _rt::Vec, pub limit: Option, + /// best-effort row cap + pub wants_rowid: bool, } impl ::core::fmt::Debug for ScanRequest { fn fmt( @@ -8512,6 +8523,7 @@ pub mod duckdb { .field("projection", &self.projection) .field("filters", &self.filters) .field("limit", &self.limit) + .field("wants-rowid", &self.wants_rowid) .finish() } } @@ -16382,6 +16394,7 @@ pub mod exports { arg7: usize, arg8: i32, arg9: i64, + arg10: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); let len0 = arg3; @@ -16638,6 +16651,7 @@ pub mod exports { } _ => _rt::invalid_enum_discriminant(), }, + wants_rowid: _rt::bool_lift(arg10 as u8), }, ); let ptr44 = (&raw mut _RET_AREA.0).cast::(); @@ -17665,10 +17679,11 @@ pub mod exports { "duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn export_storage_scan_open(arg0 : i32, arg1 : i32, arg2 : * mut u8, arg3 : usize, arg4 : * mut u8, arg5 : - usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64,) -> - * mut u8 { unsafe { $($path_to_types)*:: + usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64, + arg10 : i32,) -> * mut u8 { unsafe { $($path_to_types)*:: _export_storage_scan_open_cabi::<$ty > (arg0, arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8, arg9) } } #[unsafe (export_name = + arg4, arg5, arg6, arg7, arg8, arg9, arg10) } } #[unsafe + (export_name = "cabi_post_duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn _post_return_storage_scan_open(arg0 : * mut u8,) { unsafe { $($path_to_types)*:: @@ -17999,8 +18014,8 @@ pub(crate) use __export_duckdb_extension_storage_impl as export; )] #[doc(hidden)] #[allow(clippy::octal_escapes)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6757] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd63\x01A\x02\x01A(\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6770] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xe33\x01A\x02\x01A(\x01\ B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04text\0\0\ \x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05uint8\0\0\ \x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0btimestamp\ @@ -18104,55 +18119,55 @@ scan\x0c\0\x0f\x04\0\x19register-replacement-scan\x01\x10\x01j\x01\x07\x01s\x01@ \0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x04\x04\0\x07\ extopts\x03\0\x04\x01m\x08\x02eq\x02ne\x02lt\x02le\x02gt\x02ge\x07is-null\x0bis-\ not-null\x04\0\x0acompare-op\x03\0\x06\x01r\x03\x06columny\x02op\x07\x05value\x03\ -\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x04\x05tables\x0aproje\ -ction\x0a\x07filters\x0b\x05limit\x0c\x04\0\x0cscan-request\x03\0\x0d\x01k\x05\x01\ -j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07options\x0f\0\x10\x04\ -\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/storage@4.0.0\x05\x15\x01\ -B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecimalvalue\x03\ -\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\x03\0\x02\x01\ -r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\x09type-exprs\x04jsons\ -\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01pu\x01pz\x01p~\x01p|\x01\ -p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01p\x0f\x01p\x07\x01q\x15\ -\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\0\x07float64\x01\x0b\0\ -\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\0\x05int16\x01\x0e\0\x05\ -uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\x07float32\x01\x12\0\x04\ -date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\0\x07decimal\x01\x13\0\x08\ -interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\x04blob\x01\x17\0\x07comp\ -lex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04data\x1a\x08validity\x0f\x04\ -rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension/column-types@4.0.0\x05\x16\ -\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\ -\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01j\x01\x03\x01\x01\x01@\0\ -\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01@\x01\x04keys\x06\0\x07\ -\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutdown\x01\x09\x04\0\x1cdu\ -ckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colvec\x01B\x1f\x02\x03\x02\x01\ -\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\ -\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\x09\x04\0\x09\ -resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\0\x08\x01p\x09\x01j\x01\ -\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\x15call-scal\ -ar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06handley\x04args\x0a\0\x0d\x04\ -\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03arg\x09\0\x0b\x04\0\x0dc\ -all-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04args\x10\x03ctx\x05\0\x0d\x04\ -\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\x06handley\x04args\x10\0\ -\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\x01\x01@\x02\x06handl\ -ey\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\x06handley\x05value\x03\ -\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension/callback-dispatch@4.0.0\ -\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\x01\x02\x04\0\x09ducker\ -ror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\ -\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0cscan-request\x03\0\x06\ -\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\x03dsns\x07options\x09\ -\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\x01@\x03\x06handley\x03\ -dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01ps\x01j\x01\x0f\x01\x01\x01\ -@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-list-tables\x01\x11\x01p\x03\ -\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\x05tables\0\x13\x04\0\x15s\ -torage-table-columns\x01\x14\x01@\x03\x06handley\x07catalogy\x07request\x07\0\x0a\ -\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\x01\x01@\x03\x06handley\x04\ -scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\x17\x01j\x01\x7f\x01\x01\ -\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-scan-close\x01\x19\x01@\x02\ -\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\x1a\x04\0'duckdb:exten\ -sion/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extension/duckdb-extension-stor\ -age@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\x03\0\0\0G\x09producer\ -s\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x060.4\ -1.0"; +\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x05\x05tables\x0aproje\ +ction\x0a\x07filters\x0b\x05limit\x0c\x0bwants-rowid\x7f\x04\0\x0cscan-request\x03\ +\0\x0d\x01k\x05\x01j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07\ +options\x0f\0\x10\x04\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/st\ +orage@4.0.0\x05\x15\x01B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\ +\0\x0cdecimalvalue\x03\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dinte\ +rvalvalue\x03\0\x02\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\ +\x09type-exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01\ +pu\x01pz\x01p~\x01p|\x01p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01\ +p\x0f\x01p\x07\x01q\x15\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\ +\0\x07float64\x01\x0b\0\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\ +\0\x05int16\x01\x0e\0\x05uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\ +\x07float32\x01\x12\0\x04date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\ +\0\x07decimal\x01\x13\0\x08interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\ +\x04blob\x01\x17\0\x07complex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04da\ +ta\x1a\x08validity\x0f\x04rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension\ +/column-types@4.0.0\x05\x16\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\ +\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01\ +j\x01\x03\x01\x01\x01@\0\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01\ +@\x01\x04keys\x06\0\x07\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutd\ +own\x01\x09\x04\0\x1cduckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colve\ +c\x01B\x1f\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\ +\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\ +\x02\x01\x09\x04\0\x09resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\ +\0\x08\x01p\x09\x01j\x01\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\ +\x0b\x04\0\x15call-scalar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06han\ +dley\x04args\x0a\0\x0d\x04\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03\ +arg\x09\0\x0b\x04\0\x0dcall-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04arg\ +s\x10\x03ctx\x05\0\x0d\x04\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\ +\x06handley\x04args\x10\0\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\ +\x01\x01@\x02\x06handley\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\ +\x06handley\x05value\x03\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension\ +/callback-dispatch@4.0.0\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\ +\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\ +\x02\x02\x03\x02\x01\x09\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0c\ +scan-request\x03\0\x06\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\ +\x03dsns\x07options\x09\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\ +\x01@\x03\x06handley\x03dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01\ +ps\x01j\x01\x0f\x01\x01\x01@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-l\ +ist-tables\x01\x11\x01p\x03\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\ +\x05tables\0\x13\x04\0\x15storage-table-columns\x01\x14\x01@\x03\x06handley\x07c\ +atalogy\x07request\x07\0\x0a\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\ +\x01\x01@\x03\x06handley\x04scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\ +\x17\x01j\x01\x7f\x01\x01\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-sc\ +an-close\x01\x19\x01@\x02\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\ +\x1a\x04\0'duckdb:extension/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extensio\ +n/duckdb-extension-storage@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\ +\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10\ +wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/extensions/sqlitewasm-component/src/lib.rs b/extensions/sqlitewasm-component/src/lib.rs index a3dd69b9..fede6d12 100644 --- a/extensions/sqlitewasm-component/src/lib.rs +++ b/extensions/sqlitewasm-component/src/lib.rs @@ -770,6 +770,7 @@ mod tests { value: types::Duckvalue::Int64(1), }], limit: None, + wants_rowid: false, }; let rows = run_scan(&conn, &req).unwrap(); assert_eq!(rows.len(), 1); diff --git a/extensions/sqlitewasm-component/wit/storage.wit b/extensions/sqlitewasm-component/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/extensions/sqlitewasm-component/wit/storage.wit +++ b/extensions/sqlitewasm-component/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/extensions/unityscan-component/src/bindings.rs b/extensions/unityscan-component/src/bindings.rs index c128d801..8b7908fa 100644 --- a/extensions/unityscan-component/src/bindings.rs +++ b/extensions/unityscan-component/src/bindings.rs @@ -8494,6 +8494,15 @@ pub mod duckdb { } } /// What the engine asks a scan to produce. + /// + /// `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + /// rowid as the FINAL cell of every row returned by `storage-scan-next` + /// (after the projected column cells, which stay in projection order). The + /// ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + /// `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + /// WasmScanInitGlobal strips those rowid slots from `projection` and sets + /// this flag so the guest supplies the rowid values the sink then round- + /// trips into `storage-write-dispatch.update-rows` / `.delete-rows`. #[derive(Clone)] pub struct ScanRequest { pub table: _rt::String, @@ -8501,6 +8510,8 @@ pub mod duckdb { /// column indices to emit, in order; empty = all pub filters: _rt::Vec, pub limit: Option, + /// best-effort row cap + pub wants_rowid: bool, } impl ::core::fmt::Debug for ScanRequest { fn fmt( @@ -8512,6 +8523,7 @@ pub mod duckdb { .field("projection", &self.projection) .field("filters", &self.filters) .field("limit", &self.limit) + .field("wants-rowid", &self.wants_rowid) .finish() } } @@ -16382,6 +16394,7 @@ pub mod exports { arg7: usize, arg8: i32, arg9: i64, + arg10: i32, ) -> *mut u8 { #[cfg(target_arch = "wasm32")] _rt::run_ctors_once(); let len0 = arg3; @@ -16638,6 +16651,7 @@ pub mod exports { } _ => _rt::invalid_enum_discriminant(), }, + wants_rowid: _rt::bool_lift(arg10 as u8), }, ); let ptr44 = (&raw mut _RET_AREA.0).cast::(); @@ -17665,10 +17679,11 @@ pub mod exports { "duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn export_storage_scan_open(arg0 : i32, arg1 : i32, arg2 : * mut u8, arg3 : usize, arg4 : * mut u8, arg5 : - usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64,) -> - * mut u8 { unsafe { $($path_to_types)*:: + usize, arg6 : * mut u8, arg7 : usize, arg8 : i32, arg9 : i64, + arg10 : i32,) -> * mut u8 { unsafe { $($path_to_types)*:: _export_storage_scan_open_cabi::<$ty > (arg0, arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8, arg9) } } #[unsafe (export_name = + arg4, arg5, arg6, arg7, arg8, arg9, arg10) } } #[unsafe + (export_name = "cabi_post_duckdb:extension/storage-dispatch@4.0.0#storage-scan-open")] unsafe extern "C" fn _post_return_storage_scan_open(arg0 : * mut u8,) { unsafe { $($path_to_types)*:: @@ -17999,8 +18014,8 @@ pub(crate) use __export_duckdb_extension_storage_impl as export; )] #[doc(hidden)] #[allow(clippy::octal_escapes)] -pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6757] = *b"\ -\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd63\x01A\x02\x01A(\x01\ +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 6770] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xe33\x01A\x02\x01A(\x01\ B.\x01q\x15\x07boolean\0\0\x05int64\0\0\x06uint64\0\0\x07float64\0\0\x04text\0\0\ \x04blob\0\0\x05int32\0\0\x09timestamp\0\0\x04int8\0\0\x05int16\0\0\x05uint8\0\0\ \x06uint16\0\0\x06uint32\0\0\x07float32\0\0\x04date\0\0\x04time\0\0\x0btimestamp\ @@ -18104,55 +18119,55 @@ scan\x0c\0\x0f\x04\0\x19register-replacement-scan\x01\x10\x01j\x01\x07\x01s\x01@ \0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x04\x04\0\x07\ extopts\x03\0\x04\x01m\x08\x02eq\x02ne\x02lt\x02le\x02gt\x02ge\x07is-null\x0bis-\ not-null\x04\0\x0acompare-op\x03\0\x06\x01r\x03\x06columny\x02op\x07\x05value\x03\ -\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x04\x05tables\x0aproje\ -ction\x0a\x07filters\x0b\x05limit\x0c\x04\0\x0cscan-request\x03\0\x0d\x01k\x05\x01\ -j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07options\x0f\0\x10\x04\ -\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/storage@4.0.0\x05\x15\x01\ -B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\0\x0cdecimalvalue\x03\ -\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dintervalvalue\x03\0\x02\x01\ -r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\x09type-exprs\x04jsons\ -\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01pu\x01pz\x01p~\x01p|\x01\ -p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01p\x0f\x01p\x07\x01q\x15\ -\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\0\x07float64\x01\x0b\0\ -\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\0\x05int16\x01\x0e\0\x05\ -uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\x07float32\x01\x12\0\x04\ -date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\0\x07decimal\x01\x13\0\x08\ -interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\x04blob\x01\x17\0\x07comp\ -lex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04data\x1a\x08validity\x0f\x04\ -rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension/column-types@4.0.0\x05\x16\ -\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\ -\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01j\x01\x03\x01\x01\x01@\0\ -\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01@\x01\x04keys\x06\0\x07\ -\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutdown\x01\x09\x04\0\x1cdu\ -ckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colvec\x01B\x1f\x02\x03\x02\x01\ -\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\0\x09duckvalue\x03\0\x02\ -\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\x02\x01\x09\x04\0\x09\ -resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\0\x08\x01p\x09\x01j\x01\ -\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\x0b\x04\0\x15call-scal\ -ar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06handley\x04args\x0a\0\x0d\x04\ -\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03arg\x09\0\x0b\x04\0\x0dc\ -all-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04args\x10\x03ctx\x05\0\x0d\x04\ -\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\x06handley\x04args\x10\0\ -\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\x01\x01@\x02\x06handl\ -ey\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\x06handley\x05value\x03\ -\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension/callback-dispatch@4.0.0\ -\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\x01\x02\x04\0\x09ducker\ -ror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\x02\x02\x03\x02\x01\x09\ -\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0cscan-request\x03\0\x06\ -\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\x03dsns\x07options\x09\ -\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\x01@\x03\x06handley\x03\ -dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01ps\x01j\x01\x0f\x01\x01\x01\ -@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-list-tables\x01\x11\x01p\x03\ -\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\x05tables\0\x13\x04\0\x15s\ -torage-table-columns\x01\x14\x01@\x03\x06handley\x07catalogy\x07request\x07\0\x0a\ -\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\x01\x01@\x03\x06handley\x04\ -scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\x17\x01j\x01\x7f\x01\x01\ -\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-scan-close\x01\x19\x01@\x02\ -\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\x1a\x04\0'duckdb:exten\ -sion/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extension/duckdb-extension-stor\ -age@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\x03\0\0\0G\x09producer\ -s\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10wit-bindgen-rust\x060.4\ -1.0"; +\x04\0\x0bscan-filter\x03\0\x08\x01py\x01p\x09\x01kw\x01r\x05\x05tables\x0aproje\ +ction\x0a\x07filters\x0b\x05limit\x0c\x0bwants-rowid\x7f\x04\0\x0cscan-request\x03\ +\0\x0d\x01k\x05\x01j\x01y\x01\x01\x01@\x03\x09type-names\x0fcallback-handley\x07\ +options\x0f\0\x10\x04\0\x10register-storage\x01\x11\x03\0\x1educkdb:extension/st\ +orage@4.0.0\x05\x15\x01B\x1d\x01r\x04\x05lowerw\x05upperw\x05width}\x05scale}\x04\ +\0\x0cdecimalvalue\x03\0\0\x01r\x03\x06monthsz\x04daysz\x06microsx\x04\0\x0dinte\ +rvalvalue\x03\0\x02\x01r\x02\x02hiw\x02low\x04\0\x09uuidvalue\x03\0\x04\x01r\x02\ +\x09type-exprs\x04jsons\x04\0\x0ccomplexvalue\x03\0\x06\x01p\x7f\x01px\x01pw\x01\ +pu\x01pz\x01p~\x01p|\x01p}\x01p{\x01py\x01pv\x01p\x01\x01p\x03\x01p\x05\x01ps\x01\ +p\x0f\x01p\x07\x01q\x15\x07boolean\x01\x08\0\x05int64\x01\x09\0\x06uint64\x01\x0a\ +\0\x07float64\x01\x0b\0\x05int32\x01\x0c\0\x09timestamp\x01\x09\0\x04int8\x01\x0d\ +\0\x05int16\x01\x0e\0\x05uint8\x01\x0f\0\x06uint16\x01\x10\0\x06uint32\x01\x11\0\ +\x07float32\x01\x12\0\x04date\x01\x0c\0\x04time\x01\x09\0\x0btimestamptz\x01\x09\ +\0\x07decimal\x01\x13\0\x08interval\x01\x14\0\x04uuid\x01\x15\0\x04text\x01\x16\0\ +\x04blob\x01\x17\0\x07complex\x01\x18\0\x04\0\x06column\x03\0\x19\x01r\x03\x04da\ +ta\x1a\x08validity\x0f\x04rowsy\x04\0\x06colvec\x03\0\x1b\x03\0#duckdb:extension\ +/column-types@4.0.0\x05\x16\x02\x03\0\0\x0aloadresult\x01B\x0d\x02\x03\x02\x01\x02\ +\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x17\x04\0\x0aloadresult\x03\0\x02\x01\ +j\x01\x03\x01\x01\x01@\0\0\x04\x04\0\x04load\x01\x05\x01ps\x01j\x01\x7f\x01\x01\x01\ +@\x01\x04keys\x06\0\x07\x04\0\x0breconfigure\x01\x08\x01@\0\0\x07\x04\0\x08shutd\ +own\x01\x09\x04\0\x1cduckdb:extension/guest@4.0.0\x05\x18\x02\x03\0\x07\x06colve\ +c\x01B\x1f\x02\x03\x02\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x03\x04\ +\0\x09duckvalue\x03\0\x02\x02\x03\x02\x01\x07\x04\0\x0ainvokeinfo\x03\0\x04\x02\x03\ +\x02\x01\x09\x04\0\x09resultset\x03\0\x06\x02\x03\x02\x01\x19\x04\0\x06colvec\x03\ +\0\x08\x01p\x09\x01j\x01\x09\x01\x01\x01@\x03\x06handley\x04args\x0a\x03ctx\x05\0\ +\x0b\x04\0\x15call-scalar-batch-col\x01\x0c\x01j\x01\x03\x01\x01\x01@\x02\x06han\ +dley\x04args\x0a\0\x0d\x04\0\x12call-aggregate-col\x01\x0e\x01@\x02\x06handley\x03\ +arg\x09\0\x0b\x04\0\x0dcall-cast-col\x01\x0f\x01p\x03\x01@\x03\x06handley\x04arg\ +s\x10\x03ctx\x05\0\x0d\x04\0\x0bcall-scalar\x01\x11\x01j\x01\x07\x01\x01\x01@\x02\ +\x06handley\x04args\x10\0\x12\x04\0\x0acall-table\x01\x13\x01k\x03\x01j\x01\x14\x01\ +\x01\x01@\x02\x06handley\x04args\x10\0\x15\x04\0\x0bcall-pragma\x01\x16\x01@\x02\ +\x06handley\x05value\x03\0\x0d\x04\0\x09call-cast\x01\x17\x04\0(duckdb:extension\ +/callback-dispatch@4.0.0\x05\x1a\x02\x03\0\x06\x0cscan-request\x01B#\x02\x03\x02\ +\x01\x02\x04\0\x09duckerror\x03\0\0\x02\x03\x02\x01\x0b\x04\0\x09columndef\x03\0\ +\x02\x02\x03\x02\x01\x09\x04\0\x09resultset\x03\0\x04\x02\x03\x02\x01\x1b\x04\0\x0c\ +scan-request\x03\0\x06\x01o\x02ss\x01p\x08\x01j\x01y\x01\x01\x01@\x03\x06handley\ +\x03dsns\x07options\x09\0\x0a\x04\0\x0estorage-attach\x01\x0b\x01p}\x01j\0\x01\x01\ +\x01@\x03\x06handley\x03dsns\x05bytes\x0c\0\x0d\x04\0\x0battach-blob\x01\x0e\x01\ +ps\x01j\x01\x0f\x01\x01\x01@\x02\x06handley\x07catalogy\0\x10\x04\0\x13storage-l\ +ist-tables\x01\x11\x01p\x03\x01j\x01\x12\x01\x01\x01@\x03\x06handley\x07catalogy\ +\x05tables\0\x13\x04\0\x15storage-table-columns\x01\x14\x01@\x03\x06handley\x07c\ +atalogy\x07request\x07\0\x0a\x04\0\x11storage-scan-open\x01\x15\x01j\x01\x05\x01\ +\x01\x01@\x03\x06handley\x04scany\x08max-rowsy\0\x16\x04\0\x11storage-scan-next\x01\ +\x17\x01j\x01\x7f\x01\x01\x01@\x02\x06handley\x04scany\0\x18\x04\0\x12storage-sc\ +an-close\x01\x19\x01@\x02\x06handley\x07catalogy\0\x18\x04\0\x0estorage-detach\x01\ +\x1a\x04\0'duckdb:extension/storage-dispatch@4.0.0\x05\x1c\x04\0/duckdb:extensio\ +n/duckdb-extension-storage@4.0.0\x04\0\x0b\x1e\x01\0\x18duckdb-extension-storage\ +\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.227.1\x10\ +wit-bindgen-rust\x060.41.0"; #[inline(never)] #[doc(hidden)] pub fn __link_custom_section_describing_imports() { diff --git a/extensions/unityscan-component/wit/storage.wit b/extensions/unityscan-component/wit/storage.wit index 7f1c4c57..b38f983f 100644 --- a/extensions/unityscan-component/wit/storage.wit +++ b/extensions/unityscan-component/wit/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/native-extension/ducklink b/native-extension/ducklink index 24c9268e..053cbe35 160000 --- a/native-extension/ducklink +++ b/native-extension/ducklink @@ -1 +1 @@ -Subproject commit 24c9268e12dafa1c235290cd5a02987b73a88617 +Subproject commit 053cbe351ed254ab6de32b407db8816de957b142 diff --git a/native-extension/ducklink-native/.gitignore b/native-extension/ducklink-native/.gitignore new file mode 100644 index 00000000..4dc7af66 --- /dev/null +++ b/native-extension/ducklink-native/.gitignore @@ -0,0 +1,6 @@ +/target +/build +/configure/venv +/configure/platform.txt +/configure/extension_version.txt +Cargo.lock diff --git a/native-extension/ducklink-native/Cargo.toml b/native-extension/ducklink-native/Cargo.toml new file mode 100644 index 00000000..9f905fe1 --- /dev/null +++ b/native-extension/ducklink-native/Cargo.toml @@ -0,0 +1,54 @@ +# ducklink-native — curated bundle of perf-sensitive natives for DuckDB. +# +# Companion to the `ducklink` extension. Where `ducklink` embeds wasmtime to +# run ANY of the 216 datalink components dynamically as WASM, this ships a +# CURATED subset compiled directly against duckdb-rs — same pure-logic +# crates, native-DuckDB speed, no sandbox. Users install one or the other +# (or both) depending on whether they need dynamic loading or throughput. +# +# Curation filter: perf-sensitive + no existing native community extension +# equivalent. Anything already covered by a native DuckDB extension stays +# WASM-only via ducklink; anything I/O-bound or rarely-called doesn't +# benefit enough from the native build to be worth the bundle bloat. +[package] +name = "ducklink-native" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "Curated native DuckDB extension: perf-sensitive scalars from the ducklink component catalog" +publish = false + +[lib] +crate-type = ["cdylib", "rlib"] +name = "ducklink_native" + +[features] +default = ["loadable"] +duckdb-api = ["dep:duckdb", "duckdb/vscalar"] +loadable = [ + "duckdb-api", + "duckdb/loadable-extension", + "dep:libduckdb-sys", + "libduckdb-sys/loadable-extension", +] +bundled = ["duckdb-api", "duckdb/bundled"] + +[dependencies] +# Pure-logic crates from datalink — one source of truth, shared with each +# component's ducklink WASM version. Bundle grows as more perf-sensitive +# capabilities warrant inclusion. +aba-core = { path = "../../../datalink/extensions/aba-core" } +iban-core = { path = "../../../datalink/extensions/iban-core" } +isbn-core = { path = "../../../datalink/extensions/isbn-core" } +luhn-core = { path = "../../../datalink/extensions/luhn-core" } +creditcard-core = { path = "../../../datalink/extensions/creditcard-core" } + +# DuckDB C Extension API. Pinned to the community-extensions CI's DuckDB version. +duckdb = { version = "1.10504.0", optional = true, default-features = false } +libduckdb-sys = { version = "1.10504.0", features = ["loadable-extension"], optional = true } + +[profile.release] +lto = true +strip = true + +[workspace] diff --git a/native-extension/ducklink-native/Makefile b/native-extension/ducklink-native/Makefile new file mode 100644 index 00000000..baca721c --- /dev/null +++ b/native-extension/ducklink-native/Makefile @@ -0,0 +1,30 @@ +.PHONY: clean clean_all + +PROJ_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +EXTENSION_NAME=ducklink_native + +# Set to 1 to enable Unstable API (binaries will only work on TARGET_DUCKDB_VERSION, forwards compatibility will be broken) +# Note: currently the Rust C Extension API relies on unstable C API functionality +USE_UNSTABLE_C_API=1 + +# Target DuckDB version +TARGET_DUCKDB_VERSION=v1.5.4 + +all: configure debug + +# Include makefiles from DuckDB +include extension-ci-tools/makefiles/c_api_extensions/base.Makefile +include extension-ci-tools/makefiles/c_api_extensions/rust.Makefile + +configure: venv platform extension_version + +debug: build_extension_library_debug build_extension_with_metadata_debug +release: build_extension_library_release build_extension_with_metadata_release + +test: test_debug +test_debug: test_extension_debug +test_release: test_extension_release + +clean: clean_build clean_rust +clean_all: clean_configure clean diff --git a/native-extension/ducklink-native/description.yml b/native-extension/ducklink-native/description.yml new file mode 100644 index 00000000..f45dfa32 --- /dev/null +++ b/native-extension/ducklink-native/description.yml @@ -0,0 +1,56 @@ +# DuckDB community-extensions manifest. +extension: + name: ducklink_native + description: Curated native DuckDB scalars from the ducklink component catalog (validators, encoders, transforms) + version: 0.1.0 + language: Rust + build: cargo + license: MIT + maintainers: + - tegmentum + requires_toolchains: "rust;python3" + +repo: + github: tegmentum/ducklink-native + ref: v0.1.0 + +docs: + hello_world: | + LOAD ducklink_native; + SELECT aba_validate('021000021'); -- true + SELECT iban_validate('DE89370400440532013000'); -- true + SELECT cc_type('4111111111111111'); -- Visa + extended_description: | + Companion to the `ducklink` extension. Where `ducklink` embeds a + wasmtime host to run any of ~216 datalink components dynamically as + portable WebAssembly (sandboxed, catalog-driven), `ducklink_native` + ships a CURATED subset of perf-sensitive scalars compiled directly + against DuckDB's C Extension API. Same pure-logic crates as the WASM + versions; native execution speed (~20× faster than WASM on + tight-loop scalars); no sandbox. + + Bundled today (15 scalars, 5 domains): + + * aba_validate / aba_frb_district / aba_fed_region + US ABA / bank routing-number checks. + + * iban_validate / iban_country / iban_bban + International bank account number (ISO 13616) checks. + + * isbn_valid / isbn_normalize + ISBN-10 / ISBN-13 checksum + normalize. + + * luhn_validate / luhn_check_digit + Luhn checksum (credit-card family, national IDs, ...). + + * cc_validate / cc_network / cc_type / cc_mask / cc_last4 + / cc_bin / cc_normalize + Credit-card validation + brand detection + masking. + + Use ducklink_native when you're running these functions over many + rows in tight loops. Use ducklink's WASM versions of the SAME + capabilities when sandboxing / portability / dynamic-load matter + more than raw throughput. Or install both — the two extensions + coexist; ducklink's WASM aba_validate and ducklink_native's aba_validate + are just SQL functions with the same signature registered at different + times (whichever loaded last wins). diff --git a/native-extension/ducklink-native/extension-ci-tools b/native-extension/ducklink-native/extension-ci-tools new file mode 120000 index 00000000..c540edc1 --- /dev/null +++ b/native-extension/ducklink-native/extension-ci-tools @@ -0,0 +1 @@ +../ducklink/extension-ci-tools \ No newline at end of file diff --git a/native-extension/ducklink-native/src/lib.rs b/native-extension/ducklink-native/src/lib.rs new file mode 100644 index 00000000..a7a5496c --- /dev/null +++ b/native-extension/ducklink-native/src/lib.rs @@ -0,0 +1,130 @@ +//! `ducklink-native` — curated bundle of native DuckDB scalars sharing pure +//! logic crates with the ducklink WASM catalog. +//! +//! Companion to the `ducklink` extension. Where `ducklink` embeds wasmtime +//! to run any of 216 datalink components dynamically as WASM, this ships +//! a curated subset of perf-sensitive validators / encoders / transforms +//! compiled directly against duckdb-rs. Same pure-logic crates, native +//! DuckDB speed, no sandbox. +//! +//! Bundled today (15 scalars, 5 -core crates): +//! +//! aba_* — US ABA routing-number checks (aba-core) +//! iban_* — International bank account checks (iban-core) +//! isbn_* — ISBN check + normalize (isbn-core) +//! luhn_* — Luhn checksum + check-digit (luhn-core) +//! cc_* — Credit-card validate/brand/mask/... (creditcard-core) +//! +//! Add a new capability by dropping a new module under `src/scalars/`, +//! adding its `-core` dependency to `Cargo.toml`, and appending +//! `register_*` calls in `loadable::init()`. + +pub mod scalars; + +#[cfg(feature = "loadable")] +mod loadable { + use std::error::Error; + use std::ffi::CString; + + use duckdb::ffi; + use duckdb::Connection; + + use crate::scalars::helpers::{BoolAdapter, IntAdapter, TextAdapter}; + use crate::scalars::{aba, creditcard, iban, isbn, luhn}; + + /// DuckDB C-API entry point. DuckDB derives the symbol name from the + /// filename: `ducklink_native.duckdb_extension` -> `ducklink_native_init_c_api`. + /// + /// # Safety + /// Called by DuckDB during `LOAD` with a valid `info` / `access` pair. + #[no_mangle] + pub unsafe extern "C" fn ducklink_native_init_c_api( + info: ffi::duckdb_extension_info, + access: *const ffi::duckdb_extension_access, + ) -> bool { + match init(info, access) { + Ok(loaded) => loaded, + Err(e) => { + if let Some(set_error) = (*access).set_error { + if let Ok(c) = CString::new(e.to_string()) { + set_error(info, c.as_ptr()); + } + } + false + } + } + } + + unsafe fn init( + info: ffi::duckdb_extension_info, + access: *const ffi::duckdb_extension_access, + ) -> Result> { + if !ffi::duckdb_rs_extension_api_init(info, access, "v1.5.4").map_err(stringify)? { + return Ok(false); + } + let get_database = (*access) + .get_database + .ok_or_else(|| stringify("get_database is null in duckdb_extension_access"))?; + let db_ptr = get_database(info); + if db_ptr.is_null() { + return Ok(false); + } + let db: ffi::duckdb_database = *db_ptr; + let con = Connection::open_from_raw(db.cast())?; + + // aba — 3 functions. + register_bool::(&con)?; + register_int::(&con)?; + register_text::(&con)?; + + // iban — 3 functions. + register_bool::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + + // isbn — 2 functions. + register_bool::(&con)?; + register_text::(&con)?; + + // luhn — 2 functions. + register_bool::(&con)?; + register_int::(&con)?; + + // creditcard — 7 functions. + register_bool::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + register_text::(&con)?; + + Ok(true) + } + + /// Wire a `BoolScalar` impl into DuckDB under its declared NAME. + fn register_bool( + con: &Connection, + ) -> Result<(), Box> { + con.register_scalar_function::>(T::NAME) + .map_err(stringify) + } + + fn register_text( + con: &Connection, + ) -> Result<(), Box> { + con.register_scalar_function::>(T::NAME) + .map_err(stringify) + } + + fn register_int( + con: &Connection, + ) -> Result<(), Box> { + con.register_scalar_function::>(T::NAME) + .map_err(stringify) + } + + fn stringify(err: impl std::fmt::Display) -> Box { + err.to_string().into() + } +} diff --git a/native-extension/ducklink-native/src/scalars/aba.rs b/native-extension/ducklink-native/src/scalars/aba.rs new file mode 100644 index 00000000..9fbf7557 --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/aba.rs @@ -0,0 +1,28 @@ +//! `aba_*` scalars — US ABA routing-number checks. Wraps `aba_core::logic`. + +use super::helpers::{BoolScalar, IntScalar, TextScalar}; +use aba_core::logic; + +pub struct Validate; +impl BoolScalar for Validate { + const NAME: &'static str = "aba_validate"; + fn invoke(text: &str) -> bool { + logic::validate(text) + } +} + +pub struct FrbDistrict; +impl IntScalar for FrbDistrict { + const NAME: &'static str = "aba_frb_district"; + fn invoke(text: &str) -> Option { + logic::frb(text).map(|d| d as i64) + } +} + +pub struct FedRegion; +impl TextScalar for FedRegion { + const NAME: &'static str = "aba_fed_region"; + fn invoke(text: &str) -> Option { + logic::frb(text).map(|d| logic::fed_region(d).to_string()) + } +} diff --git a/native-extension/ducklink-native/src/scalars/creditcard.rs b/native-extension/ducklink-native/src/scalars/creditcard.rs new file mode 100644 index 00000000..d47f779c --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/creditcard.rs @@ -0,0 +1,84 @@ +//! `cc_*` scalars — credit-card validation + brand/masking utilities. +//! Wraps `creditcard_core::logic`. + +use super::helpers::{BoolScalar, TextScalar}; +use creditcard_core::logic; + +pub struct Validate; +impl BoolScalar for Validate { + const NAME: &'static str = "cc_validate"; + fn invoke(text: &str) -> bool { + logic::digits(text).map(|d| logic::validate(&d)).unwrap_or(false) + } +} + +pub struct Network; +impl TextScalar for Network { + const NAME: &'static str = "cc_network"; + fn invoke(text: &str) -> Option { + logic::digits(text) + .and_then(|d| logic::network(&d)) + .map(|n| n.to_string()) + } +} + +pub struct Type; +impl TextScalar for Type { + const NAME: &'static str = "cc_type"; + fn invoke(text: &str) -> Option { + let d = logic::digits_only(text); + logic::brand(&d).map(|t| t.to_string()) + } +} + +pub struct Mask; +impl TextScalar for Mask { + const NAME: &'static str = "cc_mask"; + fn invoke(text: &str) -> Option { + let d = logic::digits_only(text); + if d.is_empty() { + None + } else { + Some(logic::mask(&d)) + } + } +} + +pub struct Last4; +impl TextScalar for Last4 { + const NAME: &'static str = "cc_last4"; + fn invoke(text: &str) -> Option { + let d = logic::digits_only(text); + if d.len() >= 4 { + Some(d[d.len() - 4..].to_string()) + } else { + None + } + } +} + +pub struct Bin; +impl TextScalar for Bin { + const NAME: &'static str = "cc_bin"; + fn invoke(text: &str) -> Option { + let d = logic::digits_only(text); + if d.len() >= 6 { + Some(d[..6].to_string()) + } else { + None + } + } +} + +pub struct Normalize; +impl TextScalar for Normalize { + const NAME: &'static str = "cc_normalize"; + fn invoke(text: &str) -> Option { + let d = logic::digits_only(text); + if d.is_empty() { + None + } else { + Some(d) + } + } +} diff --git a/native-extension/ducklink-native/src/scalars/helpers.rs b/native-extension/ducklink-native/src/scalars/helpers.rs new file mode 100644 index 00000000..c3f45e82 --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/helpers.rs @@ -0,0 +1,162 @@ +//! Shared VScalar wrappers for the two dominant shapes in the bundle: +//! +//! * `TEXT -> BOOLEAN` (validators — aba_validate, iban_validate, ...) +//! * `TEXT -> TEXT` (transformers — iban_country, cc_normalize, ...) +//! +//! Both take a single VARCHAR input, all-valid per-row, no NULL propagation +//! from the input side (a NULL input to the wrapped `fn(&str)` never fires — +//! DuckDB routes NULL rows to NULL output automatically for `text -> text`). +//! +//! Each concrete scalar is a zero-sized type implementing `Bool` or `Text`, +//! wired through `bool_scalar!` / `text_scalar!` macros so the boilerplate +//! is one line per function. + +use std::error::Error; + +use duckdb::core::{DataChunkHandle, Inserter, LogicalTypeId}; +use duckdb::ffi; +use duckdb::types::DuckString; +use duckdb::vscalar::{ScalarFunctionSignature, VScalar}; +use duckdb::vtab::arrow::WritableVector; + +/// Trait describing a `TEXT -> BOOLEAN` function via a pure-Rust callable. +/// The `Bool` type parameter is a zero-sized marker; the wrapped function is +/// invoked per row inside `VScalar::invoke`. +pub trait BoolScalar { + /// Function name registered into DuckDB. + const NAME: &'static str; + /// Callable: text in, boolean out. + fn invoke(text: &str) -> bool; +} + +/// Trait describing a `TEXT -> TEXT` function via a pure-Rust callable. +/// `None` from the callable becomes SQL NULL. +pub trait TextScalar { + const NAME: &'static str; + fn invoke(text: &str) -> Option; +} + +/// Trait describing a `TEXT -> BIGINT` function via a pure-Rust callable. +/// `None` from the callable becomes SQL NULL. Used by luhn_check_digit. +pub trait IntScalar { + const NAME: &'static str; + fn invoke(text: &str) -> Option; +} + +/// VScalar adapter — one struct per BoolScalar impl. Written as a generic +/// so registration is one line per function. +pub struct BoolAdapter(std::marker::PhantomData); + +impl VScalar for BoolAdapter { + type State = (); + + fn invoke( + _: &(), + input: &mut DataChunkHandle, + output: &mut dyn WritableVector, + ) -> Result<(), Box> { + let len = input.len(); + let arg = input.flat_vector(0); + let mut out = output.flat_vector(); + unsafe { + let arg_slice = arg.as_slice_with_len::(len); + let out_slice = out.as_mut_slice_with_len::(len); + for i in 0..len { + let mut s = arg_slice[i]; + out_slice[i] = T::invoke(&DuckString::new(&mut s).as_str()); + } + } + Ok(()) + } + + fn signatures() -> Vec { + vec![ScalarFunctionSignature::exact( + vec![LogicalTypeId::Varchar.into()], + LogicalTypeId::Boolean.into(), + )] + } +} + +/// VScalar adapter — one struct per TextScalar impl. +pub struct TextAdapter(std::marker::PhantomData); + +impl VScalar for TextAdapter { + type State = (); + + fn invoke( + _: &(), + input: &mut DataChunkHandle, + output: &mut dyn WritableVector, + ) -> Result<(), Box> { + let len = input.len(); + let arg = input.flat_vector(0); + let mut out = output.flat_vector(); + // Two-pass: pre-collect results (so we can release the input borrow + // before writing back into the output), then write. Cheaper on + // narrow strings than double-borrow gymnastics. + let mut results: Vec> = Vec::with_capacity(len); + unsafe { + let arg_slice = arg.as_slice_with_len::(len); + for i in 0..len { + let mut s = arg_slice[i]; + let text = DuckString::new(&mut s).as_str(); + results.push(T::invoke(&text)); + } + } + for (i, r) in results.into_iter().enumerate() { + match r { + Some(s) => out.insert(i, s.as_str()), + None => out.set_null(i), + } + } + Ok(()) + } + + fn signatures() -> Vec { + vec![ScalarFunctionSignature::exact( + vec![LogicalTypeId::Varchar.into()], + LogicalTypeId::Varchar.into(), + )] + } +} + +/// VScalar adapter — one struct per IntScalar impl. +pub struct IntAdapter(std::marker::PhantomData); + +impl VScalar for IntAdapter { + type State = (); + + fn invoke( + _: &(), + input: &mut DataChunkHandle, + output: &mut dyn WritableVector, + ) -> Result<(), Box> { + let len = input.len(); + let arg = input.flat_vector(0); + let mut out = output.flat_vector(); + let mut nulls: Vec = Vec::new(); + unsafe { + let arg_slice = arg.as_slice_with_len::(len); + let out_slice = out.as_mut_slice_with_len::(len); + for i in 0..len { + let mut s = arg_slice[i]; + let text = DuckString::new(&mut s).as_str(); + match T::invoke(&text) { + Some(n) => out_slice[i] = n, + None => nulls.push(i), + } + } + } + for i in nulls { + out.set_null(i); + } + Ok(()) + } + + fn signatures() -> Vec { + vec![ScalarFunctionSignature::exact( + vec![LogicalTypeId::Varchar.into()], + LogicalTypeId::Bigint.into(), + )] + } +} diff --git a/native-extension/ducklink-native/src/scalars/iban.rs b/native-extension/ducklink-native/src/scalars/iban.rs new file mode 100644 index 00000000..3ccaf0d6 --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/iban.rs @@ -0,0 +1,29 @@ +//! `iban_*` scalars — international bank account number checks. +//! Wraps `iban_core::logic`. + +use super::helpers::{BoolScalar, TextScalar}; +use iban_core::logic; + +pub struct Validate; +impl BoolScalar for Validate { + const NAME: &'static str = "iban_validate"; + fn invoke(text: &str) -> bool { + logic::validate(text) + } +} + +pub struct Country; +impl TextScalar for Country { + const NAME: &'static str = "iban_country"; + fn invoke(text: &str) -> Option { + logic::country(text) + } +} + +pub struct Bban; +impl TextScalar for Bban { + const NAME: &'static str = "iban_bban"; + fn invoke(text: &str) -> Option { + logic::bban(text) + } +} diff --git a/native-extension/ducklink-native/src/scalars/isbn.rs b/native-extension/ducklink-native/src/scalars/isbn.rs new file mode 100644 index 00000000..f2b918a3 --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/isbn.rs @@ -0,0 +1,27 @@ +//! `isbn_*` scalars — International Standard Book Number checks. +//! Wraps `isbn_core::logic`. + +use super::helpers::{BoolScalar, TextScalar}; +use isbn_core::logic; + +pub struct Valid; +impl BoolScalar for Valid { + const NAME: &'static str = "isbn_valid"; + fn invoke(text: &str) -> bool { + // Match the WASM declare!() body byte-for-byte. + logic::is_valid(&logic::clean(text)) + } +} + +pub struct Normalize; +impl TextScalar for Normalize { + const NAME: &'static str = "isbn_normalize"; + fn invoke(text: &str) -> Option { + let body = logic::clean(text); + if logic::is_valid(&body) { + Some(body) + } else { + None + } + } +} diff --git a/native-extension/ducklink-native/src/scalars/luhn.rs b/native-extension/ducklink-native/src/scalars/luhn.rs new file mode 100644 index 00000000..7500eeec --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/luhn.rs @@ -0,0 +1,21 @@ +//! `luhn_*` scalars — Luhn checksum (credit-card check-digit family). +//! Wraps `luhn_core::logic`. + +use super::helpers::{BoolScalar, IntScalar}; +use luhn_core::logic; + +pub struct Validate; +impl BoolScalar for Validate { + const NAME: &'static str = "luhn_validate"; + fn invoke(text: &str) -> bool { + logic::digits(text).map(|d| logic::validate(&d)).unwrap_or(false) + } +} + +pub struct CheckDigit; +impl IntScalar for CheckDigit { + const NAME: &'static str = "luhn_check_digit"; + fn invoke(text: &str) -> Option { + logic::digits(text).map(|d| logic::check_digit(&d) as i64) + } +} diff --git a/native-extension/ducklink-native/src/scalars/mod.rs b/native-extension/ducklink-native/src/scalars/mod.rs new file mode 100644 index 00000000..990265c1 --- /dev/null +++ b/native-extension/ducklink-native/src/scalars/mod.rs @@ -0,0 +1,13 @@ +//! All native scalars in the bundle, one submodule per source `-core` crate. +//! +//! Each submodule exposes zero-sized types implementing [`helpers::BoolScalar`], +//! [`helpers::TextScalar`], or [`helpers::IntScalar`]. `lib.rs` iterates +//! through them at load time and registers each via the appropriate adapter. + +pub mod helpers; + +pub mod aba; +pub mod creditcard; +pub mod iban; +pub mod isbn; +pub mod luhn; diff --git a/python-sdk/.gitignore b/python-sdk/.gitignore new file mode 100644 index 00000000..fb56da59 --- /dev/null +++ b/python-sdk/.gitignore @@ -0,0 +1,7 @@ +__pycache__/ +*.pyc +.pytest_cache/ +*.egg-info/ +dist/ +build/ +.venv/ diff --git a/python-sdk/README.md b/python-sdk/README.md new file mode 100644 index 00000000..2f9e2239 --- /dev/null +++ b/python-sdk/README.md @@ -0,0 +1,86 @@ +# ducklink Python authoring API + +Pure-Python authoring surface for the ducklink Python source tier (Phase 1a of +`docs/python-source-tier-plan.md`). Decorate scalar / table / aggregate +functions; the SDK maps Python type hints to DuckDB/WIT types and builds a +JSON-serializable manifest the host reads via +`offload.run(entry="ducklink.runtime:manifest")`. + +This package is **standalone and pure-Python** — it has no wasm dependency and +is developed and tested in plain CPython. The same authored `.py` is consumed by +both the interpreted (run) and compiled execution modes. + +## Install + +```bash +pip install -e '.[dev]' +``` + +## Authoring + +```python +import ducklink + +@ducklink.scalar +def title_case(s: str) -> str: + return s.title() + +@ducklink.table +def words(text: str) -> list[tuple[str, int]]: + return [(w, len(w)) for w in text.split()] + +@ducklink.aggregate +class Concat: + def __init__(self) -> None: + self.parts: list[str] = [] + def step(self, value: str) -> None: + self.parts.append(value) + def finalize(self) -> str: + return ", ".join(self.parts) + +ducklink.manifest() # -> list[dict] the host registers as SQL functions +``` + +Decorators **return the original callable/class**, so functions stay directly +callable (and pylon can invoke them by `entry="module:name"`). + +## Type mapping + +| Python hint | DuckDB/WIT | +|---|---| +| `str` | `VARCHAR` | +| `int` | `BIGINT` | +| `float` | `DOUBLE` | +| `bool` | `BOOLEAN` | +| `bytes` / `bytearray` / `memoryview` | `BLOB` | +| `Optional[T]` | same as `T` (nullable) | + +Unmapped or missing hints raise `ducklink.TypeMappingError` **at decoration +time** (fail early, not at dispatch). + +## Manifest shape + +```json +[ + {"name": "title_case", "kind": "scalar", + "arguments": [{"name": "s", "type": "VARCHAR"}], + "returns": "VARCHAR", "entry": "text_tools:title_case"}, + {"name": "words", "kind": "table", + "arguments": [{"name": "text", "type": "VARCHAR"}], + "columns": [{"name": "c0", "type": "VARCHAR"}, {"name": "c1", "type": "BIGINT"}], + "entry": "text_tools:words"} +] +``` + +## PEP 723 inline deps + +```python +from ducklink import parse_dependencies_file +parse_dependencies_file("example/text_tools.py") # -> ["unidecode>=1.3"] +``` + +## Tests + +```bash +pytest +``` diff --git a/python-sdk/ducklink/__init__.py b/python-sdk/ducklink/__init__.py new file mode 100644 index 00000000..0d9aaaf1 --- /dev/null +++ b/python-sdk/ducklink/__init__.py @@ -0,0 +1,53 @@ +"""ducklink Python authoring API. + +Author a ducklink extension in Python: decorate scalar / table / aggregate +functions, and the SDK builds a JSON-serializable manifest the host reads to +register SQL functions. The same ``.py`` runs interpreted (zero-build) or +compiled; this package is the stable authoring surface both modes consume. + +Example:: + + import ducklink + + @ducklink.scalar + def title_case(s: str) -> str: + return s.title() + +The manifest is available via :func:`ducklink.runtime.manifest`, which the host +invokes through ``offload.run(entry="ducklink.runtime:manifest")``. +""" + +from __future__ import annotations + +from . import pep723, runtime +from .decorators import aggregate, scalar, table +from .pep723 import parse_dependencies, parse_dependencies_file +from .registry import ( + REGISTRY, + Argument, + Column, + Registration, + Registry, +) +from .runtime import manifest +from .types import TypeMappingError, map_type + +__all__ = [ + "scalar", + "table", + "aggregate", + "manifest", + "runtime", + "pep723", + "parse_dependencies", + "parse_dependencies_file", + "map_type", + "TypeMappingError", + "REGISTRY", + "Registry", + "Registration", + "Argument", + "Column", +] + +__version__ = "0.1.0" diff --git a/python-sdk/ducklink/decorators.py b/python-sdk/ducklink/decorators.py new file mode 100644 index 00000000..5a48ee46 --- /dev/null +++ b/python-sdk/ducklink/decorators.py @@ -0,0 +1,275 @@ +"""The authoring decorators: ``@ducklink.scalar/table/aggregate``. + +Each decorator: + +1. introspects the target's type hints and maps them to DuckDB/WIT types, +2. records a :class:`~ducklink.registry.Registration` in the module-level + registry, and +3. returns the *original* target unchanged, so it remains directly callable + and so the host can invoke it by ``entry="module:name"``. + +Failures (missing hints, unmapped types) are raised *at decoration time*. +""" + +from __future__ import annotations + +import inspect +import typing +from typing import Any, Callable, Optional, TypeVar, get_type_hints + +from .registry import REGISTRY, Argument, Column, Registration, Registry +from .types import TypeMappingError, map_type + +F = TypeVar("F", bound=Callable[..., Any]) +C = TypeVar("C", bound=type) + +_EMPTY = inspect.Parameter.empty + + +def _entry_for(target: Any) -> str: + """Build the ``"module:qualname"`` entry string for a target.""" + module = getattr(target, "__module__", None) or "__main__" + name = getattr(target, "__qualname__", None) or getattr(target, "__name__") + return f"{module}:{name}" + + +def _resolve_hints(func: Callable[..., Any]) -> dict[str, Any]: + """Resolve a callable's type hints, tolerating string annotations.""" + try: + return get_type_hints(func) + except Exception as exc: # pragma: no cover - defensive + raise TypeMappingError( + f"could not resolve type hints for {func.__qualname__!r}: {exc}" + ) from exc + + +def _argument_types( + func: Callable[..., Any], *, kind: str, skip_self: bool = False +) -> list[Argument]: + """Map a callable's parameters to a list of typed :class:`Argument`. + + Every parameter must carry a supported type hint. ``*args``/``**kwargs`` are + rejected: the DuckDB/WIT surface has a fixed arity. + """ + sig = inspect.signature(func) + hints = _resolve_hints(func) + args: list[Argument] = [] + + params = list(sig.parameters.values()) + if skip_self and params: + params = params[1:] + + for param in params: + if param.kind in ( + inspect.Parameter.VAR_POSITIONAL, + inspect.Parameter.VAR_KEYWORD, + ): + raise TypeMappingError( + f"{func.__qualname__!r} uses *args/**kwargs; ducklink " + f"{kind} functions must have a fixed set of typed parameters" + ) + hint = hints.get(param.name, _EMPTY) + if hint is _EMPTY: + raise TypeMappingError( + f"parameter {param.name!r} of {func.__qualname__!r} has no type " + f"hint; every argument of a ducklink {kind} function must be " + "annotated" + ) + type_name = map_type(hint, context=f"parameter {param.name!r}") + args.append(Argument(name=param.name, type=type_name)) + return args + + +def _return_type(func: Callable[..., Any], *, kind: str) -> str: + hints = _resolve_hints(func) + hint = hints.get("return", _EMPTY) + if hint is _EMPTY: + raise TypeMappingError( + f"{func.__qualname__!r} has no return type hint; a ducklink {kind} " + "function must annotate its return type" + ) + return map_type(hint, context=f"return of {func.__qualname__!r}") + + +def _register( + *, + target: Any, + name: str | None, + kind: str, + arguments: list[Argument], + returns: str | None = None, + columns: list[Column] | None = None, + registry: Registry, +) -> None: + reg = Registration( + name=name or target.__name__, + kind=kind, # type: ignore[arg-type] + arguments=arguments, + entry=_entry_for(target), + target=target, + returns=returns, + columns=columns, + ) + registry.add(reg) + + +def scalar( + _func: F | None = None, + *, + name: str | None = None, + registry: Registry | None = None, +) -> Any: + """Register a scalar function (one row in, one value out). + + Usable bare (``@ducklink.scalar``) or with args + (``@ducklink.scalar(name="foo")``). Returns the original function. + """ + reg = registry or REGISTRY + + def decorate(func: F) -> F: + args = _argument_types(func, kind="scalar") + ret = _return_type(func, kind="scalar") + _register( + target=func, + name=name, + kind="scalar", + arguments=args, + returns=ret, + registry=reg, + ) + return func + + if _func is not None: + return decorate(_func) + return decorate + + +def _columns_from_return(func: Callable[..., Any]) -> list[Column]: + """Derive a table function's output columns from its return annotation. + + Supported return shapes: + + * ``list[tuple[T1, T2, ...]]`` / ``Iterable[tuple[...]]`` -> one column per + tuple member, named ``c0``, ``c1``, ... . + * ``list[T]`` / ``Iterable[T]`` of a scalar -> a single column ``c0``. + + Column names may be overridden via the decorator's ``columns=`` argument. + """ + hints = _resolve_hints(func) + hint = hints.get("return", _EMPTY) + if hint is _EMPTY: + raise TypeMappingError( + f"{func.__qualname__!r} has no return type hint; a ducklink table " + "function must annotate its return type (e.g. list[tuple[str, int]])" + ) + + origin = typing.get_origin(hint) + if origin is None: + raise TypeMappingError( + f"return type {hint!r} of {func.__qualname__!r} is not a row " + "collection; a table function must return list[...] / Iterable[...] " + "of rows" + ) + + row_args = typing.get_args(hint) + if not row_args: + raise TypeMappingError( + f"return type {hint!r} of {func.__qualname__!r} is missing its row " + "element type" + ) + row = row_args[0] + + if typing.get_origin(row) is tuple: + members = typing.get_args(row) + if not members or members[-1] is Ellipsis: + raise TypeMappingError( + f"tuple row type of {func.__qualname__!r} must have a fixed set " + "of typed members (no ...)" + ) + return [ + Column(name=f"c{i}", type=map_type(m, context=f"column {i}")) + for i, m in enumerate(members) + ] + + # Single-column table. + return [Column(name="c0", type=map_type(row, context="column 0"))] + + +def table( + _func: F | None = None, + *, + name: str | None = None, + columns: list[str] | None = None, + registry: Registry | None = None, +) -> Any: + """Register a table function (arguments in, rows out). + + The output columns are derived from the return annotation + (``list[tuple[...]]`` or ``list[T]``). Pass ``columns=[...]`` to name them. + Returns the original function. + """ + reg = registry or REGISTRY + + def decorate(func: F) -> F: + args = _argument_types(func, kind="table") + cols = _columns_from_return(func) + if columns is not None: + if len(columns) != len(cols): + raise TypeMappingError( + f"columns={columns!r} has {len(columns)} names but " + f"{func.__qualname__!r} returns {len(cols)} columns" + ) + cols = [Column(name=n, type=c.type) for n, c in zip(columns, cols)] + _register( + target=func, + name=name, + kind="table", + arguments=args, + columns=cols, + registry=reg, + ) + return func + + if _func is not None: + return decorate(_func) + return decorate + + +def aggregate( + _cls: C | None = None, + *, + name: str | None = None, + registry: Registry | None = None, +) -> Any: + """Register an aggregate function, authored as a class. + + Convention: the decorated class defines + ``__init__(self)`` (state setup), ``step(self, )`` (fold one + row), and ``finalize(self) -> `` (produce the result). The argument + types come from ``step`` (minus ``self``); the return type from ``finalize``. + Returns the original class, still directly instantiable. + """ + reg = registry or REGISTRY + + def decorate(cls: C) -> C: + for method in ("step", "finalize"): + if not callable(getattr(cls, method, None)): + raise TypeMappingError( + f"aggregate class {cls.__qualname__!r} must define a " + f"{method}() method" + ) + args = _argument_types(cls.step, kind="aggregate", skip_self=True) + ret = _return_type(cls.finalize, kind="aggregate") + _register( + target=cls, + name=name, + kind="aggregate", + arguments=args, + returns=ret, + registry=reg, + ) + return cls + + if _cls is not None: + return decorate(_cls) + return decorate diff --git a/python-sdk/ducklink/pep723.py b/python-sdk/ducklink/pep723.py new file mode 100644 index 00000000..4a5bc77a --- /dev/null +++ b/python-sdk/ducklink/pep723.py @@ -0,0 +1,86 @@ +"""PEP 723 inline script metadata parsing. + +Extracts the ``script`` metadata block from a ``.py`` file and returns its +declared dependencies. Later phases resolve these into a pylon ``env-id``. + +Reference: https://peps.python.org/pep-0723/ — the reference regular expression +and semantics are followed exactly. +""" + +from __future__ import annotations + +import re +from pathlib import Path +from typing import Any + +try: # Python 3.11+ ships tomllib in the stdlib. + import tomllib +except ModuleNotFoundError: # pragma: no cover - <3.11 fallback + import tomli as tomllib # type: ignore[no-redef] + + +# The reference regex from PEP 723. The ``type`` group captures the block name +# (we care about ``script``); the ``content`` group captures the raw block body. +_BLOCK_RE = re.compile( + r"(?m)^# /// (?P[a-zA-Z0-9-]+)$\s(?P(^#(| .*)$\s)+)^# ///$" +) + + +class Pep723Error(ValueError): + """Raised when a PEP 723 metadata block is malformed or duplicated.""" + + +def read_metadata_block(source: str, block_type: str = "script") -> str | None: + """Return the raw (un-prefixed) content of the named PEP 723 block. + + Returns ``None`` if no block of ``block_type`` is present. Raises + :class:`Pep723Error` if the block appears more than once (per the spec). + """ + matches = [ + m for m in _BLOCK_RE.finditer(source) if m.group("type") == block_type + ] + if len(matches) > 1: + raise Pep723Error( + f"multiple {block_type!r} metadata blocks found; PEP 723 permits at " + "most one" + ) + if not matches: + return None + + content = matches[0].group("content") + # Strip the leading "# " (or bare "#") from each line, per the spec. + lines = [ + line[2:] if line.startswith("# ") else line[1:] + for line in content.splitlines(keepends=True) + ] + return "".join(lines) + + +def parse_metadata(source: str) -> dict[str, Any]: + """Parse the PEP 723 ``script`` block from source into a dict. + + Returns an empty dict when no ``script`` block is present. + """ + raw = read_metadata_block(source, "script") + if raw is None: + return {} + return tomllib.loads(raw) + + +def parse_dependencies(source: str) -> list[str]: + """Return the ``dependencies`` list from a PEP 723 ``script`` block. + + Returns an empty list if there is no block or no ``dependencies`` key. + """ + meta = parse_metadata(source) + deps = meta.get("dependencies", []) + if not isinstance(deps, list) or not all(isinstance(d, str) for d in deps): + raise Pep723Error( + "PEP 723 'dependencies' must be a list of requirement strings" + ) + return deps + + +def parse_dependencies_file(path: str | Path) -> list[str]: + """Read a ``.py`` file and return its PEP 723 dependency list.""" + return parse_dependencies(Path(path).read_text(encoding="utf-8")) diff --git a/python-sdk/ducklink/registry.py b/python-sdk/ducklink/registry.py new file mode 100644 index 00000000..3a47aa56 --- /dev/null +++ b/python-sdk/ducklink/registry.py @@ -0,0 +1,105 @@ +"""The module-level registry of authored functions. + +The decorators (:mod:`ducklink.decorators`) record one :class:`Registration` +per authored function/class here. :func:`ducklink.runtime.manifest` reads this +registry to produce the JSON-serializable manifest the host consumes. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +from typing import Any, Callable, Literal + +Kind = Literal["scalar", "table", "aggregate"] + + +@dataclass(frozen=True) +class Argument: + """A single named function argument and its DuckDB/WIT type.""" + + name: str + type: str + + def to_dict(self) -> dict[str, str]: + return {"name": self.name, "type": self.type} + + +@dataclass(frozen=True) +class Column: + """A single named output column of a table function.""" + + name: str + type: str + + def to_dict(self) -> dict[str, str]: + return {"name": self.name, "type": self.type} + + +@dataclass +class Registration: + """One authored function/class recorded in the registry. + + ``target`` is the original, still-directly-callable object (function for + scalar/table, class for aggregate). ``entry`` is the ``"module:callable"`` + string the host passes to ``offload.run``. + """ + + name: str + kind: Kind + arguments: list[Argument] + entry: str + target: Any + returns: str | None = None + columns: list[Column] | None = None + + def to_manifest_entry(self) -> dict[str, Any]: + entry: dict[str, Any] = { + "name": self.name, + "kind": self.kind, + "arguments": [a.to_dict() for a in self.arguments], + "entry": self.entry, + } + if self.kind == "table": + entry["columns"] = [c.to_dict() for c in (self.columns or [])] + else: + entry["returns"] = self.returns + return entry + + +class Registry: + """An ordered, name-unique collection of registrations.""" + + def __init__(self) -> None: + self._by_name: dict[str, Registration] = {} + self._order: list[str] = [] + + def add(self, reg: Registration) -> None: + if reg.name in self._by_name: + raise ValueError( + f"a ducklink function named {reg.name!r} is already registered; " + "names must be unique within a module" + ) + self._by_name[reg.name] = reg + self._order.append(reg.name) + + def get(self, name: str) -> Registration: + return self._by_name[name] + + def all(self) -> list[Registration]: + return [self._by_name[n] for n in self._order] + + def clear(self) -> None: + """Reset the registry. Primarily for tests.""" + self._by_name.clear() + self._order.clear() + + def __len__(self) -> int: + return len(self._order) + + def __contains__(self, name: object) -> bool: + return name in self._by_name + + +# The single process-global registry the decorators write into and the runtime +# manifest reads from. +REGISTRY = Registry() diff --git a/python-sdk/ducklink/runtime.py b/python-sdk/ducklink/runtime.py new file mode 100644 index 00000000..2f3923c5 --- /dev/null +++ b/python-sdk/ducklink/runtime.py @@ -0,0 +1,32 @@ +"""The runtime manifest surface the host consumes. + +The host reads the authored functions via +``offload.run(entry="ducklink.runtime:manifest")``. :func:`manifest` returns a +JSON-serializable ``list[dict]`` describing every registered function. +""" + +from __future__ import annotations + +from typing import Any + +from .registry import REGISTRY, Registry + + +def manifest(registry: Registry | None = None) -> list[dict[str, Any]]: + """Return the JSON-serializable manifest of all registered functions. + + Each entry has the shape:: + + { + "name": str, + "kind": "scalar" | "table" | "aggregate", + "arguments": [{"name": str, "type": str}, ...], + "entry": "module:callable", + # scalar / aggregate: + "returns": , + # table: + "columns": [{"name": str, "type": str}, ...], + } + """ + reg = registry or REGISTRY + return [r.to_manifest_entry() for r in reg.all()] diff --git a/python-sdk/ducklink/types.py b/python-sdk/ducklink/types.py new file mode 100644 index 00000000..e10a21db --- /dev/null +++ b/python-sdk/ducklink/types.py @@ -0,0 +1,97 @@ +"""Python type hint -> DuckDB/WIT type-name mapping. + +The mapping is deliberately small and explicit. The goal is a stable, obvious +surface: a hint the SDK understands maps to a single canonical DuckDB/WIT type +name; anything else fails *at decoration time* with a clear message, so authors +never discover a bad signature at dispatch time. +""" + +from __future__ import annotations + +import types +import typing +from typing import Any + + +def _is_union_origin(origin: Any) -> bool: + """True for both ``typing.Union[...]`` and PEP 604 ``X | Y`` origins.""" + return origin is typing.Union or origin is getattr(types, "UnionType", ()) + + +class TypeMappingError(TypeError): + """Raised when a Python type hint cannot be mapped to a DuckDB/WIT type. + + Raised eagerly (at decoration time) so signature mistakes surface early. + """ + + +# Canonical Python-type -> DuckDB/WIT type-name table. Order does not matter; +# lookups are exact by the concrete type object. +_SCALAR_MAP: dict[type, str] = { + str: "VARCHAR", + int: "BIGINT", + float: "DOUBLE", + bool: "BOOLEAN", + bytes: "BLOB", + bytearray: "BLOB", + memoryview: "BLOB", +} + + +def _is_optional(hint: Any) -> tuple[bool, Any]: + """Return (is_optional, inner_hint). + + Recognises ``Optional[T]`` / ``Union[T, None]`` / ``T | None``. If optional, + ``inner_hint`` is the non-``None`` member (only single-member optionals are + supported; a genuine multi-type union is rejected by the caller). + """ + origin = typing.get_origin(hint) + # Handle both typing.Union[T, None] (incl. Optional[T]) and PEP 604 + # (T | None), whose origin is types.UnionType on 3.10+. + if _is_union_origin(origin): + args = typing.get_args(hint) + non_none = [a for a in args if a is not type(None)] + has_none = len(non_none) != len(args) + if has_none and len(non_none) == 1: + return True, non_none[0] + # Union with >1 real member, or no None: not a supported optional. + return False, hint + return False, hint + + +def map_type(hint: Any, *, context: str = "") -> str: + """Map a single Python type hint to a DuckDB/WIT type name. + + ``Optional[T]`` maps to the same type name as ``T`` (nullability is implicit + in DuckDB columns). Anything unmapped raises :class:`TypeMappingError`. + """ + where = f" for {context}" if context else "" + + if hint is None or hint is type(None): + raise TypeMappingError( + f"bare None / NoneType is not a valid type{where}; " + "annotate a concrete type such as str, int, float, bool, or bytes" + ) + + is_opt, inner = _is_optional(hint) + if is_opt: + return map_type(inner, context=context) + + # Reject unsupported unions explicitly (distinct from Optional). + if _is_union_origin(typing.get_origin(hint)): + raise TypeMappingError( + f"unsupported union type {hint!r}{where}; " + "only Optional[T] (a union with None) is supported" + ) + + mapped = _SCALAR_MAP.get(hint) + if mapped is None: + supported = ", ".join( + sorted({t.__name__ for t in _SCALAR_MAP}) + ) + raise TypeMappingError( + f"cannot map Python type {getattr(hint, '__name__', hint)!r}{where} " + f"to a DuckDB/WIT type; supported types are: {supported} " + "(each optionally wrapped in Optional[...])" + ) + return mapped diff --git a/python-sdk/example/text_tools.py b/python-sdk/example/text_tools.py new file mode 100644 index 00000000..0f1b3c10 --- /dev/null +++ b/python-sdk/example/text_tools.py @@ -0,0 +1,61 @@ +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "unidecode>=1.3", +# ] +# /// +"""An example ducklink extension authored in Python. + +Run interpreted or compiled off this same file. ``manifest()`` describes every +function below for the host to register as SQL functions. +""" + +from __future__ import annotations + +from typing import Optional + +import ducklink + + +@ducklink.scalar +def title_case(s: str) -> str: + """Title-case a string.""" + return s.title() + + +@ducklink.scalar +def shout(s: str, times: int) -> str: + """Uppercase and repeat a string.""" + return (s.upper() + " ") * times + + +@ducklink.scalar +def maybe_len(s: Optional[str]) -> int: + """Length of a string, or 0 when NULL.""" + return len(s) if s is not None else 0 + + +@ducklink.table +def words(text: str) -> list[tuple[str, int]]: + """Split ``text`` into (word, length) rows.""" + return [(w, len(w)) for w in text.split()] + + +@ducklink.aggregate +class Concat: + """Concatenate string inputs with a separator.""" + + def __init__(self) -> None: + self.parts: list[str] = [] + + def step(self, value: str) -> None: + self.parts.append(value) + + def finalize(self) -> str: + return ", ".join(self.parts) + + +if __name__ == "__main__": + import json + + print(json.dumps(ducklink.manifest(), indent=2)) diff --git a/python-sdk/pyproject.toml b/python-sdk/pyproject.toml new file mode 100644 index 00000000..8e24ff35 --- /dev/null +++ b/python-sdk/pyproject.toml @@ -0,0 +1,24 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "ducklink" +version = "0.1.0" +description = "ducklink Python authoring API: decorate scalar/table/aggregate functions and emit a manifest the host registers as SQL functions." +readme = "README.md" +requires-python = ">=3.11" +license = { text = "MIT" } +authors = [{ name = "ducklink" }] +keywords = ["ducklink", "duckdb", "wasm", "extension", "authoring"] +dependencies = [] + +[project.optional-dependencies] +dev = ["pytest>=7"] + +[tool.hatch.build.targets.wheel] +packages = ["ducklink"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "-q" diff --git a/python-sdk/tests/conftest.py b/python-sdk/tests/conftest.py new file mode 100644 index 00000000..023af922 --- /dev/null +++ b/python-sdk/tests/conftest.py @@ -0,0 +1,11 @@ +import pytest + +from ducklink.registry import REGISTRY + + +@pytest.fixture(autouse=True) +def _clean_registry(): + """Isolate every test: start and end with an empty global registry.""" + REGISTRY.clear() + yield + REGISTRY.clear() diff --git a/python-sdk/tests/test_decorators.py b/python-sdk/tests/test_decorators.py new file mode 100644 index 00000000..5f18aa94 --- /dev/null +++ b/python-sdk/tests/test_decorators.py @@ -0,0 +1,217 @@ +from typing import Optional + +import pytest + +import ducklink +from ducklink.registry import REGISTRY +from ducklink.types import TypeMappingError + + +def test_scalar_registers_and_stays_callable(): + @ducklink.scalar + def add_one(x: int) -> int: + return x + 1 + + # Original function still directly callable. + assert add_one(41) == 42 + + reg = REGISTRY.get("add_one") + assert reg.kind == "scalar" + assert reg.arguments == [ducklink.Argument("x", "BIGINT")] + assert reg.returns == "BIGINT" + # entry is "module:qualname"; for a module-level def qualname == name. + assert reg.entry.startswith("test_decorators:") + assert reg.entry.endswith("add_one") + # The registration keeps the original callable. + assert reg.target is add_one + + +def test_scalar_bare_and_parenthesized_forms(): + @ducklink.scalar + def a(x: str) -> str: + return x + + @ducklink.scalar(name="renamed") + def b(x: str) -> str: + return x + + assert "a" in REGISTRY + assert "renamed" in REGISTRY + assert b("hi") == "hi" + + +def test_scalar_multi_arg_types(): + @ducklink.scalar + def f(s: str, n: int, r: float, flag: bool, blob: bytes) -> str: + return s + + reg = REGISTRY.get("f") + assert [a.type for a in reg.arguments] == [ + "VARCHAR", + "BIGINT", + "DOUBLE", + "BOOLEAN", + "BLOB", + ] + + +def test_scalar_optional_arg(): + @ducklink.scalar + def f(s: Optional[str]) -> int: + return len(s or "") + + assert REGISTRY.get("f").arguments == [ducklink.Argument("s", "VARCHAR")] + + +def test_missing_arg_hint_raises_at_decoration(): + with pytest.raises(TypeMappingError) as exc: + + @ducklink.scalar + def f(x) -> int: # noqa: ANN001 - intentionally unannotated + return 1 + + assert "no type hint" in str(exc.value) + assert "f" not in REGISTRY + + +def test_missing_return_hint_raises(): + with pytest.raises(TypeMappingError) as exc: + + @ducklink.scalar + def f(x: int): + return x + + assert "return" in str(exc.value) + + +def test_unmapped_arg_type_raises(): + with pytest.raises(TypeMappingError): + + @ducklink.scalar + def f(x: complex) -> int: + return 1 + + +def test_varargs_rejected(): + with pytest.raises(TypeMappingError) as exc: + + @ducklink.scalar + def f(*args: int) -> int: + return 0 + + assert "args" in str(exc.value) + + +def test_duplicate_name_rejected(): + @ducklink.scalar + def dup(x: int) -> int: + return x + + with pytest.raises(ValueError): + + @ducklink.scalar(name="dup") + def other(x: int) -> int: + return x + + +def test_table_tuple_rows(): + @ducklink.table + def rows(text: str) -> list[tuple[str, int]]: + return [(w, len(w)) for w in text.split()] + + # Original still callable. + assert rows("a bb") == [("a", 1), ("bb", 2)] + + reg = REGISTRY.get("rows") + assert reg.kind == "table" + assert reg.returns is None + assert reg.columns == [ + ducklink.Column("c0", "VARCHAR"), + ducklink.Column("c1", "BIGINT"), + ] + + +def test_table_single_column(): + @ducklink.table + def nums(text: str) -> list[int]: + return [int(x) for x in text.split()] + + reg = REGISTRY.get("nums") + assert reg.columns == [ducklink.Column("c0", "BIGINT")] + + +def test_table_named_columns(): + @ducklink.table(columns=["word", "length"]) + def rows(text: str) -> list[tuple[str, int]]: + return [] + + reg = REGISTRY.get("rows") + assert reg.columns == [ + ducklink.Column("word", "VARCHAR"), + ducklink.Column("length", "BIGINT"), + ] + + +def test_table_column_count_mismatch_raises(): + with pytest.raises(TypeMappingError): + + @ducklink.table(columns=["only_one"]) + def rows(text: str) -> list[tuple[str, int]]: + return [] + + +def test_table_missing_return_raises(): + with pytest.raises(TypeMappingError): + + @ducklink.table + def rows(text: str): + return [] + + +def test_aggregate_class(): + @ducklink.aggregate + class Sum: + def __init__(self) -> None: + self.total = 0 + + def step(self, value: int) -> None: + self.total += value + + def finalize(self) -> int: + return self.total + + # Class still usable directly. + agg = Sum() + agg.step(2) + agg.step(3) + assert agg.finalize() == 5 + + reg = REGISTRY.get("Sum") + assert reg.kind == "aggregate" + assert reg.arguments == [ducklink.Argument("value", "BIGINT")] + assert reg.returns == "BIGINT" + assert reg.entry.endswith("Sum") + assert reg.target is Sum + + +def test_aggregate_missing_method_raises(): + with pytest.raises(TypeMappingError) as exc: + + @ducklink.aggregate + class Bad: + def step(self, value: int) -> None: + pass + + assert "finalize" in str(exc.value) + + +def test_aggregate_step_needs_hints(): + with pytest.raises(TypeMappingError): + + @ducklink.aggregate + class Bad: + def step(self, value) -> None: # noqa: ANN001 + pass + + def finalize(self) -> int: + return 0 diff --git a/python-sdk/tests/test_example.py b/python-sdk/tests/test_example.py new file mode 100644 index 00000000..825d251a --- /dev/null +++ b/python-sdk/tests/test_example.py @@ -0,0 +1,65 @@ +import importlib.util +import json +from pathlib import Path + +import pytest + +from ducklink import parse_dependencies_file +from ducklink.registry import REGISTRY + +EXAMPLE = Path(__file__).resolve().parent.parent / "example" / "text_tools.py" + + +@pytest.fixture() +def text_tools(): + """Import the example module fresh against the clean registry.""" + spec = importlib.util.spec_from_file_location("text_tools", EXAMPLE) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def test_example_manifest_reads_correctly(text_tools): + import ducklink + + m = ducklink.manifest() + by_name = {e["name"]: e for e in m} + assert set(by_name) == {"title_case", "shout", "maybe_len", "words", "Concat"} + + assert by_name["title_case"]["kind"] == "scalar" + assert by_name["title_case"]["returns"] == "VARCHAR" + assert by_name["title_case"]["entry"] == "text_tools:title_case" + + assert by_name["shout"]["arguments"] == [ + {"name": "s", "type": "VARCHAR"}, + {"name": "times", "type": "BIGINT"}, + ] + + assert by_name["maybe_len"]["arguments"] == [{"name": "s", "type": "VARCHAR"}] + assert by_name["maybe_len"]["returns"] == "BIGINT" + + assert by_name["words"]["kind"] == "table" + assert by_name["words"]["columns"] == [ + {"name": "c0", "type": "VARCHAR"}, + {"name": "c1", "type": "BIGINT"}, + ] + + assert by_name["Concat"]["kind"] == "aggregate" + assert by_name["Concat"]["returns"] == "VARCHAR" + + # Manifest is JSON-serializable. + json.dumps(m) + + +def test_example_functions_still_callable(text_tools): + assert text_tools.title_case("hello world") == "Hello World" + assert text_tools.words("a bb ccc") == [("a", 1), ("bb", 2), ("ccc", 3)] + + c = text_tools.Concat() + c.step("a") + c.step("b") + assert c.finalize() == "a, b" + + +def test_example_pep723_deps(): + assert parse_dependencies_file(EXAMPLE) == ["unidecode>=1.3"] diff --git a/python-sdk/tests/test_pep723.py b/python-sdk/tests/test_pep723.py new file mode 100644 index 00000000..6644f33a --- /dev/null +++ b/python-sdk/tests/test_pep723.py @@ -0,0 +1,117 @@ +import textwrap + +import pytest + +from ducklink import parse_dependencies, parse_dependencies_file +from ducklink.pep723 import Pep723Error, parse_metadata, read_metadata_block + +WITH_DEPS = textwrap.dedent( + '''\ + # /// script + # requires-python = ">=3.11" + # dependencies = [ + # "requests>=2.0", + # "rich", + # ] + # /// + """A module with inline deps.""" + x = 1 + ''' +) + +NO_BLOCK = textwrap.dedent( + '''\ + """A module with no metadata block.""" + x = 1 + ''' +) + +BLOCK_NO_DEPS = textwrap.dedent( + """\ + # /// script + # requires-python = ">=3.11" + # /// + x = 1 + """ +) + +EMPTY_DEPS = textwrap.dedent( + """\ + # /// script + # dependencies = [] + # /// + x = 1 + """ +) + + +def test_parse_dependencies_with_deps(): + assert parse_dependencies(WITH_DEPS) == ["requests>=2.0", "rich"] + + +def test_parse_dependencies_no_block(): + assert parse_dependencies(NO_BLOCK) == [] + + +def test_parse_dependencies_block_without_deps_key(): + assert parse_dependencies(BLOCK_NO_DEPS) == [] + + +def test_parse_dependencies_empty_list(): + assert parse_dependencies(EMPTY_DEPS) == [] + + +def test_parse_metadata_returns_full_dict(): + meta = parse_metadata(WITH_DEPS) + assert meta["requires-python"] == ">=3.11" + assert meta["dependencies"] == ["requests>=2.0", "rich"] + + +def test_read_metadata_block_none_when_absent(): + assert read_metadata_block(NO_BLOCK) is None + + +def test_duplicate_block_raises(): + dup = WITH_DEPS + "\n" + WITH_DEPS + with pytest.raises(Pep723Error): + parse_dependencies(dup) + + +def test_bad_dependencies_type_raises(): + bad = textwrap.dedent( + """\ + # /// script + # dependencies = "not-a-list" + # /// + x = 1 + """ + ) + with pytest.raises(Pep723Error): + parse_dependencies(bad) + + +def test_only_script_block_parsed(): + # A non-"script" block must be ignored; the reference PEP 723 regex requires + # blocks to be separated (not immediately adjacent) to delimit correctly. + src = textwrap.dedent( + """\ + # /// pyproject + # [tool.foo] + # bar = 1 + # /// + + x = 1 + + # /// script + # dependencies = ["a"] + # /// + y = 2 + """ + ) + assert parse_dependencies(src) == ["a"] + + +def test_parse_dependencies_file(tmp_path): + p = tmp_path / "s.py" + p.write_text(WITH_DEPS, encoding="utf-8") + assert parse_dependencies_file(p) == ["requests>=2.0", "rich"] diff --git a/python-sdk/tests/test_runtime.py b/python-sdk/tests/test_runtime.py new file mode 100644 index 00000000..b97448ae --- /dev/null +++ b/python-sdk/tests/test_runtime.py @@ -0,0 +1,78 @@ +import json + +import ducklink +from ducklink import manifest + + +def _define(): + @ducklink.scalar + def title_case(s: str) -> str: + return s.title() + + @ducklink.table + def words(text: str) -> list[tuple[str, int]]: + return [] + + @ducklink.aggregate + class Concat: + def __init__(self) -> None: + self.parts: list[str] = [] + + def step(self, value: str) -> None: + self.parts.append(value) + + def finalize(self) -> str: + return ", ".join(self.parts) + + +def test_manifest_shape(): + _define() + m = manifest() + assert [e["name"] for e in m] == ["title_case", "words", "Concat"] + + scalar_e = m[0] + assert scalar_e == { + "name": "title_case", + "kind": "scalar", + "arguments": [{"name": "s", "type": "VARCHAR"}], + "entry": scalar_e["entry"], + "returns": "VARCHAR", + } + assert scalar_e["entry"].endswith("title_case") + + table_e = m[1] + assert table_e["kind"] == "table" + assert "returns" not in table_e + assert table_e["columns"] == [ + {"name": "c0", "type": "VARCHAR"}, + {"name": "c1", "type": "BIGINT"}, + ] + + agg_e = m[2] + assert agg_e["kind"] == "aggregate" + assert agg_e["returns"] == "VARCHAR" + assert agg_e["arguments"] == [{"name": "value", "type": "VARCHAR"}] + + +def test_manifest_is_json_serializable(): + _define() + s = json.dumps(manifest()) + round_tripped = json.loads(s) + assert isinstance(round_tripped, list) + assert all(isinstance(e, dict) for e in round_tripped) + + +def test_empty_manifest(): + assert manifest() == [] + + +def test_manifest_entry_ordering_preserved(): + @ducklink.scalar + def z(x: int) -> int: + return x + + @ducklink.scalar + def a(x: int) -> int: + return x + + assert [e["name"] for e in manifest()] == ["z", "a"] diff --git a/python-sdk/tests/test_types.py b/python-sdk/tests/test_types.py new file mode 100644 index 00000000..3dd8e4a2 --- /dev/null +++ b/python-sdk/tests/test_types.py @@ -0,0 +1,60 @@ +from typing import Optional, Union + +import pytest + +from ducklink.types import TypeMappingError, map_type + + +@pytest.mark.parametrize( + "hint,expected", + [ + (str, "VARCHAR"), + (int, "BIGINT"), + (float, "DOUBLE"), + (bool, "BOOLEAN"), + (bytes, "BLOB"), + (bytearray, "BLOB"), + (memoryview, "BLOB"), + ], +) +def test_scalar_type_mapping(hint, expected): + assert map_type(hint) == expected + + +@pytest.mark.parametrize( + "hint,expected", + [ + (Optional[str], "VARCHAR"), + (Optional[int], "BIGINT"), + (Union[float, None], "DOUBLE"), + (str | None, "VARCHAR"), + (None | bytes, "BLOB"), + ], +) +def test_optional_maps_to_inner(hint, expected): + assert map_type(hint) == expected + + +def test_unmapped_type_raises(): + with pytest.raises(TypeMappingError) as exc: + map_type(complex) + assert "cannot map" in str(exc.value) + + +def test_none_raises(): + with pytest.raises(TypeMappingError): + map_type(None) + with pytest.raises(TypeMappingError): + map_type(type(None)) + + +def test_multi_member_union_rejected(): + with pytest.raises(TypeMappingError) as exc: + map_type(Union[str, int]) + assert "union" in str(exc.value).lower() + + +def test_error_includes_context(): + with pytest.raises(TypeMappingError) as exc: + map_type(complex, context="parameter 'x'") + assert "parameter 'x'" in str(exc.value) diff --git a/registry/index.json b/registry/index.json index 7db03077..e60591a1 100644 --- a/registry/index.json +++ b/registry/index.json @@ -148,7 +148,7 @@ "source": "builtin", "status": "working", "artifact": "artifacts/extensions/sample_extension.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sample_plus_one", "sample_emit_sequence", @@ -181,10 +181,66 @@ "conformance": { "suite": "sample_extension@4", "suite_digest": "4c6fae795ef67612e82f4a4ea960848a039d25d11aa554139577db829d1694be", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "sample_plus_one", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "sample_emit_sequence", + "kind": "table", + "arguments": [ + { + "name": "limit", + "type": "BIGINT" + } + ], + "columns": [ + { + "name": "value", + "type": "BIGINT" + } + ] + }, + { + "name": "sample_read_path", + "kind": "table", + "arguments": [ + { + "name": "path", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "path", + "type": "VARCHAR" + } + ] + }, + { + "name": "sample_sum", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } ] }, { @@ -210,7 +266,7 @@ "source": "extensions/isin-component", "status": "working", "artifact": "artifacts/extensions/isin.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "isin_validate", "isin_check_digit", @@ -237,10 +293,56 @@ "conformance": { "suite": "isin@4", "suite_digest": "72d666116e2c6ea14bb52afb8a24b27521b25017803262b598c34a571727263b", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "isin_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "isin_check_digit", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "isin_country", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "isin_nsin", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -265,7 +367,7 @@ "source": "extensions/baseN-component", "status": "working", "artifact": "artifacts/extensions/baseN.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "base32_encode", "base32_decode", @@ -295,10 +397,78 @@ "conformance": { "suite": "baseN@4", "suite_digest": "82d734bb13c74c3686d45284b6e41a43bbc23a945759ba83ded926042336de70", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "base32_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "base32_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BLOB" + }, + { + "name": "base58_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "base58_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BLOB" + }, + { + "name": "to_base64", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "from_base64", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BLOB" + } ] }, { @@ -322,7 +492,7 @@ "source": "extensions/luhn-component", "status": "working", "artifact": "artifacts/extensions/luhn.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "luhn_validate", "luhn_check_digit" @@ -335,7 +505,31 @@ "prefix": "luhn", "expansion": "com.tegmentum.ducklink.luhn", "wit_contract_version": "4.0.0", - "content_digest": "531cc06687d18c091b4b81c7259e02126ff1342f8f58ca654a4bc821c8702caf" + "content_digest": "531cc06687d18c091b4b81c7259e02126ff1342f8f58ca654a4bc821c8702caf", + "functions": [ + { + "name": "luhn_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "luhn_check_digit", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "iban", @@ -360,7 +554,7 @@ "source": "extensions/iban-component", "status": "working", "artifact": "artifacts/extensions/iban.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "iban_validate", "iban_country", @@ -374,7 +568,42 @@ "prefix": "iban", "expansion": "com.tegmentum.ducklink.iban", "wit_contract_version": "4.0.0", - "content_digest": "c754998007649ae8927445a574450cd2ec7fff148377a6b232512d0a45dd7044" + "content_digest": "c754998007649ae8927445a574450cd2ec7fff148377a6b232512d0a45dd7044", + "functions": [ + { + "name": "iban_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "iban_country", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "iban_bban", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ean", @@ -398,7 +627,7 @@ "source": "extensions/ean-component", "status": "working", "artifact": "artifacts/extensions/ean.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ean_validate", "ean_check_digit", @@ -413,7 +642,53 @@ "prefix": "ean", "expansion": "com.tegmentum.ducklink.ean", "wit_contract_version": "4.0.0", - "content_digest": "6084c5d6ffbf32f317bdf6d35bc81141e9395e405ac362dbaf1a5f2fb2fbd443" + "content_digest": "6084c5d6ffbf32f317bdf6d35bc81141e9395e405ac362dbaf1a5f2fb2fbd443", + "functions": [ + { + "name": "ean_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "ean_check_digit", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "ean_gs1_prefix", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "upca_to_ean13", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "aba", @@ -436,7 +711,7 @@ "source": "extensions/aba-component", "status": "working", "artifact": "artifacts/extensions/aba.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "aba_validate" ], @@ -460,7 +735,7 @@ "conformance": { "suite": "aba@4", "suite_digest": "e2833ab9fdc2e3b09994610b006002a54c0e37ce82f0964bee33e3fd17328dcc", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } }, @@ -480,10 +755,45 @@ "conformance": { "suite": "aba@4", "suite_digest": "e2833ab9fdc2e3b09994610b006002a54c0e37ce82f0964bee33e3fd17328dcc", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "aba_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "aba_frb_district", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "aba_fed_region", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -507,7 +817,7 @@ "source": "extensions/creditcard-component", "status": "working", "artifact": "artifacts/extensions/creditcard.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "cc_validate", "cc_network", @@ -537,10 +847,89 @@ "conformance": { "suite": "creditcard@4", "suite_digest": "6c0e5ed82a82412bc37faa293125f18440742a3afef5902839c4af70cd88282e", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "cc_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "cc_network", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cc_type", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cc_mask", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cc_last4", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cc_bin", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cc_normalize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -569,7 +958,7 @@ "repository": "https://github.com/tegmentum/ducklink", "source": "extensions/uuidx-component", "artifact": "artifacts/extensions/uuidx.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "keywords": [ "uuid", "v7", @@ -579,7 +968,37 @@ "prefix": "uuidx", "expansion": "com.tegmentum.ducklink.uuidx", "wit_contract_version": "4.0.0", - "content_digest": "3bf565af587c742156904cf905f016dd0355644abc00072c808154e950b6c12f" + "content_digest": "3bf565af587c742156904cf905f016dd0355644abc00072c808154e950b6c12f", + "functions": [ + { + "name": "uuid_v7", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "uuid_version", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "uuid_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "crypto", @@ -613,7 +1032,7 @@ "repository": "https://github.com/tegmentum/ducklink", "source": "extensions/crypto-component", "artifact": "artifacts/extensions/crypto.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "keywords": [ "crypto", "hash", @@ -637,10 +1056,67 @@ "conformance": { "suite": "crypto@4", "suite_digest": "b11bf7ce1601360c5ab2e819c9980b35a35f3b402a2a68188e09d8c8b3b2e2a1", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "sha1", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sha512", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sha3_256", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "blake3", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "crc32", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } ] }, { @@ -664,7 +1140,7 @@ "source": "extensions/markdown-component", "status": "working", "artifact": "artifacts/extensions/markdown.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "md_to_html", "md_to_text" @@ -679,7 +1155,31 @@ "prefix": "markdown", "expansion": "com.tegmentum.ducklink.markdown", "wit_contract_version": "4.0.0", - "content_digest": "e028996e5e6ab98cf10098904f20e3be32b099c0350b72bfe6906e06138207f7" + "content_digest": "e028996e5e6ab98cf10098904f20e3be32b099c0350b72bfe6906e06138207f7", + "functions": [ + { + "name": "md_to_html", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "md_to_text", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "hashfuncs", @@ -703,7 +1203,7 @@ "source": "extensions/hashfuncs-component", "status": "working", "artifact": "artifacts/extensions/hashfuncs.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "xxh32", "xxh64", @@ -721,7 +1221,53 @@ "prefix": "hashfuncs", "expansion": "com.tegmentum.ducklink.hashfuncs", "wit_contract_version": "4.0.0", - "content_digest": "dabfd1bf114dde2d2c1e8e670696c805f0c087c7200c2a6b902e4a323b5a3cd3" + "content_digest": "dabfd1bf114dde2d2c1e8e670696c805f0c087c7200c2a6b902e4a323b5a3cd3", + "functions": [ + { + "name": "xxh32", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "xxh64", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "UBIGINT" + }, + { + "name": "xxh3", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "UBIGINT" + }, + { + "name": "murmur3", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "rapidfuzz", @@ -744,7 +1290,7 @@ "source": "extensions/rapidfuzz-component", "status": "working", "artifact": "artifacts/extensions/rapidfuzz.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "fuzz_ratio", "damerau_levenshtein", @@ -761,7 +1307,69 @@ "prefix": "rapidfuzz", "expansion": "com.tegmentum.ducklink.rapidfuzz", "wit_contract_version": "4.0.0", - "content_digest": "a134fe7240a63611fb6d205fd5cea29a9b090e070d0afb52dfbfe68d50362c80" + "content_digest": "a134fe7240a63611fb6d205fd5cea29a9b090e070d0afb52dfbfe68d50362c80", + "functions": [ + { + "name": "fuzz_ratio", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "damerau_levenshtein", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "indel", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "osa", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "casing", @@ -785,7 +1393,7 @@ "source": "extensions/casing-component", "status": "working", "artifact": "artifacts/extensions/casing.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_snake_case", "to_camel_case", @@ -804,7 +1412,75 @@ "prefix": "casing", "expansion": "com.tegmentum.ducklink.casing", "wit_contract_version": "4.0.0", - "content_digest": "48967200189a0ed1c1e12659e898618ce6a0bd1b7f97715eb4419142b97ff6f0" + "content_digest": "48967200189a0ed1c1e12659e898618ce6a0bd1b7f97715eb4419142b97ff6f0", + "functions": [ + { + "name": "to_snake_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_camel_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_pascal_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_kebab_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_title_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_constant_case", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "csscolor", @@ -827,7 +1503,7 @@ "source": "extensions/csscolor-component", "status": "working", "artifact": "artifacts/extensions/csscolor.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "css_to_hex", "css_to_rgb", @@ -843,7 +1519,42 @@ "prefix": "csscolor", "expansion": "com.tegmentum.ducklink.csscolor", "wit_contract_version": "4.0.0", - "content_digest": "d0b4c683c24088be793646cac9a8ac6c70a32c9af203fc7bb0818a78ab19588a" + "content_digest": "d0b4c683c24088be793646cac9a8ac6c70a32c9af203fc7bb0818a78ab19588a", + "functions": [ + { + "name": "css_to_hex", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "css_to_rgb", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "css_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "url", @@ -865,7 +1576,7 @@ "source": "extensions/url-component", "status": "working", "artifact": "artifacts/extensions/url.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "url_scheme", "url_host", @@ -895,10 +1606,67 @@ "conformance": { "suite": "url@4", "suite_digest": "c5d3eb272b70cc5ec9b92c69ce76d1d3f2ebf0372a6128bea829bc5880428b21", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "url_scheme", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "url_host", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "url_port", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "url_path", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "url_query", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -921,7 +1689,7 @@ "source": "extensions/email-component", "status": "working", "artifact": "artifacts/extensions/email.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "email_validate", "email_domain", @@ -949,10 +1717,45 @@ "conformance": { "suite": "email@4", "suite_digest": "894323cb99caa3ca6e83cac0b9c4fdc307786b324edbd302e976e6d7de4d0b22", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "email_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "email_domain", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "email_local", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -975,7 +1778,7 @@ "source": "extensions/semver-component", "status": "working", "artifact": "artifacts/extensions/semver.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "semver_valid", "semver_major", @@ -1005,10 +1808,71 @@ "conformance": { "suite": "semver@4", "suite_digest": "49f6f5ab2bcf456ee94112167b48933ce1f731984560550560c791b9ee02ed6b", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "semver_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "semver_major", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "semver_minor", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "semver_patch", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "semver_compare", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } ] }, { @@ -1031,7 +1895,7 @@ "source": "extensions/slug-component", "status": "working", "artifact": "artifacts/extensions/slug.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "slugify" ], @@ -1045,7 +1909,20 @@ "prefix": "slug", "expansion": "com.tegmentum.ducklink.slug", "wit_contract_version": "4.0.0", - "content_digest": "85562b4ab7f59afaff2c89acfaf7b1fa8e3ba74127c133ea7c1c32bff695b43e" + "content_digest": "85562b4ab7f59afaff2c89acfaf7b1fa8e3ba74127c133ea7c1c32bff695b43e", + "functions": [ + { + "name": "slugify", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "escape", @@ -1068,7 +1945,7 @@ "source": "extensions/escape-component", "status": "working", "artifact": "artifacts/extensions/escape.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "html_escape", "html_unescape", @@ -1086,7 +1963,53 @@ "prefix": "escape", "expansion": "com.tegmentum.ducklink.escape", "wit_contract_version": "4.0.0", - "content_digest": "d764e23603be77202a0977b921551902150cc7b67499ac57c60396b5b5627390" + "content_digest": "d764e23603be77202a0977b921551902150cc7b67499ac57c60396b5b5627390", + "functions": [ + { + "name": "html_escape", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "html_unescape", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "url_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "url_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "natsort", @@ -1108,7 +2031,7 @@ "source": "extensions/natsort-component", "status": "working", "artifact": "artifacts/extensions/natsort.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "natsort_compare" ], @@ -1122,7 +2045,24 @@ "prefix": "natsort", "expansion": "com.tegmentum.ducklink.natsort", "wit_contract_version": "4.0.0", - "content_digest": "9c4a84c7994a65355516a1b5e78cb2b91c8448008287e7089908a24657714c7f" + "content_digest": "9c4a84c7994a65355516a1b5e78cb2b91c8448008287e7089908a24657714c7f", + "functions": [ + { + "name": "natsort_compare", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "roman", @@ -1144,7 +2084,7 @@ "source": "extensions/roman-component", "status": "working", "artifact": "artifacts/extensions/roman.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_roman", "from_roman", @@ -1174,10 +2114,67 @@ "conformance": { "suite": "roman@4", "suite_digest": "512904f3cdd0188a81e32a429b712a908c385910da65f72d9e015e95f49e0c03", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "to_roman", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "from_roman", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "roman_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "roman_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "roman_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } ] }, { @@ -1200,7 +2197,7 @@ "source": "extensions/humansize-component", "status": "working", "artifact": "artifacts/extensions/humansize.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "humansize", "humansize_binary" @@ -1215,7 +2212,31 @@ "prefix": "humansize", "expansion": "com.tegmentum.ducklink.humansize", "wit_contract_version": "4.0.0", - "content_digest": "95732363ec9d5999f19118a03ea573c4e5eb9fdc6cc374bbfcbc6eb0e9c9e535" + "content_digest": "95732363ec9d5999f19118a03ea573c4e5eb9fdc6cc374bbfcbc6eb0e9c9e535", + "functions": [ + { + "name": "humansize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "humansize_binary", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ids", @@ -1238,7 +2259,7 @@ "source": "extensions/ids-component", "status": "working", "artifact": "artifacts/extensions/ids.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ulid", "nanoid", @@ -1255,7 +2276,32 @@ "prefix": "ids", "expansion": "com.tegmentum.ducklink.ids", "wit_contract_version": "4.0.0", - "content_digest": "461f8e0e1e67422a7723366001b7fc462bd944cb699b7ae6b84a665fe00f2fff" + "content_digest": "461f8e0e1e67422a7723366001b7fc462bd944cb699b7ae6b84a665fe00f2fff", + "functions": [ + { + "name": "ulid", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "nanoid", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "ulid_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "idna", @@ -1278,7 +2324,7 @@ "source": "extensions/idna-component", "status": "working", "artifact": "artifacts/extensions/idna.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "idna_to_ascii", "idna_to_unicode" @@ -1293,7 +2339,31 @@ "prefix": "idna", "expansion": "com.tegmentum.ducklink.idna", "wit_contract_version": "4.0.0", - "content_digest": "ef5e813ff354d6bfd38b5113b22bd385e81335c4127cebd86224d5d5bded3949" + "content_digest": "ef5e813ff354d6bfd38b5113b22bd385e81335c4127cebd86224d5d5bded3949", + "functions": [ + { + "name": "idna_to_ascii", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "idna_to_unicode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "mac", @@ -1316,7 +2386,7 @@ "source": "extensions/mac-component", "status": "working", "artifact": "artifacts/extensions/mac.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "mac_valid", "mac_normalize" @@ -1331,7 +2401,31 @@ "prefix": "mac", "expansion": "com.tegmentum.ducklink.mac", "wit_contract_version": "4.0.0", - "content_digest": "f2ba422fcfaa359fb9ec6ce1b7e0c359be3e33969e59faf0d55dea4fe8d9ed94" + "content_digest": "f2ba422fcfaa359fb9ec6ce1b7e0c359be3e33969e59faf0d55dea4fe8d9ed94", + "functions": [ + { + "name": "mac_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "mac_normalize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "isbn", @@ -1354,7 +2448,7 @@ "source": "extensions/isbn-component", "status": "working", "artifact": "artifacts/extensions/isbn.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "isbn_valid", "isbn_normalize" @@ -1367,7 +2461,31 @@ "prefix": "isbn", "expansion": "com.tegmentum.ducklink.isbn", "wit_contract_version": "4.0.0", - "content_digest": "c74ac740b432eb25de4a2325d20a6950b6d00cc7c216cad029b45dcc8eb5bd9f" + "content_digest": "c74ac740b432eb25de4a2325d20a6950b6d00cc7c216cad029b45dcc8eb5bd9f", + "functions": [ + { + "name": "isbn_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "isbn_normalize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "humantime", @@ -1390,7 +2508,7 @@ "source": "extensions/humantime-component", "status": "working", "artifact": "artifacts/extensions/humantime.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "humantime_parse", "humantime_format" @@ -1405,7 +2523,31 @@ "prefix": "humantime", "expansion": "com.tegmentum.ducklink.humantime", "wit_contract_version": "4.0.0", - "content_digest": "5d0a710735a2e7f3233b996d42d30ebfa06d52580ced6efc0b517af8c880a3d6" + "content_digest": "5d0a710735a2e7f3233b996d42d30ebfa06d52580ced6efc0b517af8c880a3d6", + "functions": [ + { + "name": "humantime_parse", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "humantime_format", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "iso", @@ -1428,7 +2570,7 @@ "source": "extensions/iso-component", "status": "working", "artifact": "artifacts/extensions/iso.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "iso_country_name", "iso_country_alpha3", @@ -1444,7 +2586,42 @@ "prefix": "iso", "expansion": "com.tegmentum.ducklink.iso", "wit_contract_version": "4.0.0", - "content_digest": "4ffe1061aeb851e36002d69558a794487c1b5bad4bf4bf07dec995d677980b9e" + "content_digest": "4ffe1061aeb851e36002d69558a794487c1b5bad4bf4bf07dec995d677980b9e", + "functions": [ + { + "name": "iso_country_name", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "iso_country_alpha3", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "iso_country_numeric", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "morse", @@ -1467,7 +2644,7 @@ "source": "extensions/morse-component", "status": "working", "artifact": "artifacts/extensions/morse.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "morse_encode", "morse_decode" @@ -1480,7 +2657,31 @@ "prefix": "morse", "expansion": "com.tegmentum.ducklink.morse", "wit_contract_version": "4.0.0", - "content_digest": "68fb4c3405b1ec9efd2d9e10d5eebd58bc130e5e9761816a3e2f41460a3618c0" + "content_digest": "68fb4c3405b1ec9efd2d9e10d5eebd58bc130e5e9761816a3e2f41460a3618c0", + "functions": [ + { + "name": "morse_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "morse_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "color", @@ -1503,7 +2704,7 @@ "source": "extensions/color-component", "status": "working", "artifact": "artifacts/extensions/color.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "color_luminance", "color_contrast" @@ -1518,7 +2719,35 @@ "prefix": "color", "expansion": "com.tegmentum.ducklink.color", "wit_contract_version": "4.0.0", - "content_digest": "78ace88e50f94945a773f9d02ffd2ca4283dd65d95a4e7efc2eab625e04a660d" + "content_digest": "78ace88e50f94945a773f9d02ffd2ca4283dd65d95a4e7efc2eab625e04a660d", + "functions": [ + { + "name": "color_luminance", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "color_contrast", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "geohash", @@ -1541,7 +2770,7 @@ "source": "extensions/geohash-component", "status": "working", "artifact": "artifacts/extensions/geohash.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "geohash_encode", "geohash_decode_lat", @@ -1569,10 +2798,53 @@ "conformance": { "suite": "geohash@4", "suite_digest": "0c4a779da6606ebe682fbe3bf150d17d1a6aada4765fcfb96ba3e81ec2434841", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "geohash_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "geohash_decode_lat", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "geohash_decode_lon", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } ] }, { @@ -1596,7 +2868,7 @@ "source": "extensions/parsertools-component", "status": "working", "artifact": "artifacts/extensions/parsertools.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sql_tables", "sql_is_valid", @@ -1612,7 +2884,42 @@ "prefix": "parsertools", "expansion": "com.tegmentum.ducklink.parsertools", "wit_contract_version": "4.0.0", - "content_digest": "8c7dda2a318e85e028cf1d34bfdfabe8a67200c682e23fdcc15ff8506e44fda3" + "content_digest": "8c7dda2a318e85e028cf1d34bfdfabe8a67200c682e23fdcc15ff8506e44fda3", + "functions": [ + { + "name": "sql_tables", + "kind": "scalar", + "arguments": [ + { + "name": "sql", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sql_is_valid", + "kind": "scalar", + "arguments": [ + { + "name": "sql", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "sql_statement_type", + "kind": "scalar", + "arguments": [ + { + "name": "sql", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "currency", @@ -1635,7 +2942,7 @@ "source": "extensions/currency-component", "status": "working", "artifact": "artifacts/extensions/currency.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "currency_name", "currency_symbol", @@ -1652,10 +2959,56 @@ "prefix": "currency", "expansion": "com.tegmentum.ducklink.currency", "wit_contract_version": "4.0.0", - "content_digest": "6ecf48a0788874d9faed9bfb73fda4c7d8e05d99c038a3cdf596a1f39a260150" - }, - { - "name": "hmac", + "content_digest": "6ecf48a0788874d9faed9bfb73fda4c7d8e05d99c038a3cdf596a1f39a260150", + "functions": [ + { + "name": "currency_name", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "currency_symbol", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "currency_numeric", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "currency_exponent", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] + }, + { + "name": "hmac", "version": "0.1.0", "description": "Keyed HMAC: hmac_sha256(key,msg) and hmac_sha512(key,msg) -> hex text (hmac + sha2). NULL arg -> NULL.", "license": "MIT", @@ -1675,7 +3028,7 @@ "source": "extensions/hmac-component", "status": "working", "artifact": "artifacts/extensions/hmac.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hmac_sha256", "hmac_sha512" @@ -1691,7 +3044,39 @@ "prefix": "hmac", "expansion": "com.tegmentum.ducklink.hmac", "wit_contract_version": "4.0.0", - "content_digest": "3adcb12c03c9581b34171f27f41ede5c2c28bd163a908d84456d3410deb70aa7" + "content_digest": "3adcb12c03c9581b34171f27f41ede5c2c28bd163a908d84456d3410deb70aa7", + "functions": [ + { + "name": "hmac_sha256", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hmac_sha512", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "phonetic", @@ -1714,7 +3099,7 @@ "source": "extensions/phonetic-component", "status": "working", "artifact": "artifacts/extensions/phonetic.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "soundex", "metaphone" @@ -1729,7 +3114,31 @@ "prefix": "phonetic", "expansion": "com.tegmentum.ducklink.phonetic", "wit_contract_version": "4.0.0", - "content_digest": "c38aff58e7a76f8c0283bf09d649247a014b6a79794f84e20b8fa5eaabcc7f21" + "content_digest": "c38aff58e7a76f8c0283bf09d649247a014b6a79794f84e20b8fa5eaabcc7f21", + "functions": [ + { + "name": "soundex", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "metaphone", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "jwt", @@ -1752,7 +3161,7 @@ "source": "extensions/jwt-component", "status": "working", "artifact": "artifacts/extensions/jwt.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "jwt_header", "jwt_payload" @@ -1767,7 +3176,31 @@ "prefix": "jwt", "expansion": "com.tegmentum.ducklink.jwt", "wit_contract_version": "4.0.0", - "content_digest": "f3133ceac5ab2bd63293c72a5eb4b5ac08019deab381fd27acf0abd37dafd1cb" + "content_digest": "f3133ceac5ab2bd63293c72a5eb4b5ac08019deab381fd27acf0abd37dafd1cb", + "functions": [ + { + "name": "jwt_header", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "jwt_payload", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "totp", @@ -1790,7 +3223,7 @@ "source": "extensions/totp-component", "status": "working", "artifact": "artifacts/extensions/totp.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "totp" ], @@ -1806,7 +3239,32 @@ "prefix": "totp", "expansion": "com.tegmentum.ducklink.totp", "wit_contract_version": "4.0.0", - "content_digest": "e38070b719620d8a5b82dca8704ef42a372b94d1de802c1fb78c483416a442e7" + "content_digest": "e38070b719620d8a5b82dca8704ef42a372b94d1de802c1fb78c483416a442e7", + "functions": [ + { + "name": "totp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "baseconv", @@ -1829,7 +3287,7 @@ "source": "extensions/baseconv-component", "status": "working", "artifact": "artifacts/extensions/baseconv.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "from_base" ], @@ -1841,7 +3299,24 @@ "prefix": "baseconv", "expansion": "com.tegmentum.ducklink.baseconv", "wit_contract_version": "4.0.0", - "content_digest": "476ec989af7478a2712903afbf395917c8d01ab6518bb3fd35eadbb3d4c81b5d" + "content_digest": "476ec989af7478a2712903afbf395917c8d01ab6518bb3fd35eadbb3d4c81b5d", + "functions": [ + { + "name": "from_base", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "emoji", @@ -1864,7 +3339,7 @@ "source": "extensions/emoji-component", "status": "working", "artifact": "artifacts/extensions/emoji.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "emoji_name", "emoji_shortcode", @@ -1880,7 +3355,42 @@ "prefix": "emoji", "expansion": "com.tegmentum.ducklink.emoji", "wit_contract_version": "4.0.0", - "content_digest": "685c689cf2b98fbae76eaabd9a50b9d021a717e10f6e7a17c74ba4e70be1cdf7" + "content_digest": "685c689cf2b98fbae76eaabd9a50b9d021a717e10f6e7a17c74ba4e70be1cdf7", + "functions": [ + { + "name": "emoji_name", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "emoji_shortcode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "emoji_char", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "whatlang", @@ -1903,7 +3413,7 @@ "source": "extensions/whatlang-component", "status": "working", "artifact": "artifacts/extensions/whatlang.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "detect_language", "detect_language_name", @@ -1919,7 +3429,42 @@ "prefix": "whatlang", "expansion": "com.tegmentum.ducklink.whatlang", "wit_contract_version": "4.0.0", - "content_digest": "294a06a3ea12688ef33ecdfb54efd73e70da1ff77265c241534ebc97a479573b" + "content_digest": "294a06a3ea12688ef33ecdfb54efd73e70da1ff77265c241534ebc97a479573b", + "functions": [ + { + "name": "detect_language", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "detect_language_name", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "detect_script", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ipaddr", @@ -1942,7 +3487,7 @@ "source": "extensions/ipaddr-component", "status": "working", "artifact": "artifacts/extensions/ipaddr.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ip_valid", "ip_version", @@ -1956,7 +3501,42 @@ "prefix": "ipaddr", "expansion": "com.tegmentum.ducklink.ipaddr", "wit_contract_version": "4.0.0", - "content_digest": "38f257f8ad0010d74cd7ad663a81ed5a344065622b17228f17aa27cf3bb877ba" + "content_digest": "38f257f8ad0010d74cd7ad663a81ed5a344065622b17228f17aa27cf3bb877ba", + "functions": [ + { + "name": "ip_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "ip_version", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "ip_is_private", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "mime", @@ -1979,7 +3559,7 @@ "source": "extensions/mime-component", "status": "working", "artifact": "artifacts/extensions/mime.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "mime_type", "mime_from_ext" @@ -1994,7 +3574,31 @@ "prefix": "mime", "expansion": "com.tegmentum.ducklink.mime", "wit_contract_version": "4.0.0", - "content_digest": "bc6731c074b10d98d8ffc47f7a83c74435ec320cb748341fec6435c046aac4bc" + "content_digest": "bc6731c074b10d98d8ffc47f7a83c74435ec320cb748341fec6435c046aac4bc", + "functions": [ + { + "name": "mime_type", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "mime_from_ext", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "pluralize", @@ -2017,7 +3621,7 @@ "source": "extensions/pluralize-component", "status": "working", "artifact": "artifacts/extensions/pluralize.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "pluralize", "singularize" @@ -2032,7 +3636,31 @@ "prefix": "pluralize", "expansion": "com.tegmentum.ducklink.pluralize", "wit_contract_version": "4.0.0", - "content_digest": "159f7b87bff9e8547309cb53f565efe964e088165c7657f075178c63e1683c1b" + "content_digest": "159f7b87bff9e8547309cb53f565efe964e088165c7657f075178c63e1683c1b", + "functions": [ + { + "name": "pluralize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "singularize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "haversine", @@ -2055,7 +3683,7 @@ "source": "extensions/haversine-component", "status": "working", "artifact": "artifacts/extensions/haversine.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "haversine_km", "haversine_mi" @@ -2068,7 +3696,55 @@ "prefix": "haversine", "expansion": "com.tegmentum.ducklink.haversine", "wit_contract_version": "4.0.0", - "content_digest": "84316d8a925d5f51d49e7ccc5e165845f238e2c04dbf4db0fd4525c8a2d22c40" + "content_digest": "84316d8a925d5f51d49e7ccc5e165845f238e2c04dbf4db0fd4525c8a2d22c40", + "functions": [ + { + "name": "haversine_km", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "haversine_mi", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "numwords", @@ -2091,7 +3767,7 @@ "source": "extensions/numwords-component", "status": "working", "artifact": "artifacts/extensions/numwords.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "num_to_words", "num_to_ordinal_words" @@ -2106,7 +3782,31 @@ "prefix": "numwords", "expansion": "com.tegmentum.ducklink.numwords", "wit_contract_version": "4.0.0", - "content_digest": "a6f1dee126e207bcf998460c5a770570c0cb33f3561eebbb0f54d15e140cafc1" + "content_digest": "a6f1dee126e207bcf998460c5a770570c0cb33f3561eebbb0f54d15e140cafc1", + "functions": [ + { + "name": "num_to_words", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "num_to_ordinal_words", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ordinal", @@ -2129,7 +3829,7 @@ "source": "extensions/ordinal-component", "status": "working", "artifact": "artifacts/extensions/ordinal.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ordinal" ], @@ -2141,7 +3841,20 @@ "prefix": "ordinal", "expansion": "com.tegmentum.ducklink.ordinal", "wit_contract_version": "4.0.0", - "content_digest": "ed9222bda1d7a33576333299f16ad573c8e3746ba8839c2cc0fe49980750037a" + "content_digest": "ed9222bda1d7a33576333299f16ad573c8e3746ba8839c2cc0fe49980750037a", + "functions": [ + { + "name": "ordinal", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "nato", @@ -2164,7 +3877,7 @@ "source": "extensions/nato-component", "status": "working", "artifact": "artifacts/extensions/nato.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "nato" ], @@ -2176,7 +3889,20 @@ "prefix": "nato", "expansion": "com.tegmentum.ducklink.nato", "wit_contract_version": "4.0.0", - "content_digest": "76e341a3795fe1e04f243771a278767f80a366293ad4fbfb86dae943b38e3f3b" + "content_digest": "76e341a3795fe1e04f243771a278767f80a366293ad4fbfb86dae943b38e3f3b", + "functions": [ + { + "name": "nato", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ascii85", @@ -2198,7 +3924,7 @@ "source": "extensions/ascii85-component", "status": "working", "artifact": "artifacts/extensions/ascii85.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ascii85_encode", "ascii85_decode" @@ -2225,10 +3951,34 @@ "conformance": { "suite": "ascii85@4", "suite_digest": "df35bc9afa52d8b746e0023d5077fad6823719269b03e3320b9cc3c776703420", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "ascii85_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ascii85_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -2252,7 +4002,7 @@ "source": "extensions/quotedprintable-component", "status": "working", "artifact": "artifacts/extensions/quotedprintable.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "qp_encode", "qp_decode" @@ -2267,7 +4017,31 @@ "prefix": "quotedprintable", "expansion": "com.tegmentum.ducklink.quotedprintable", "wit_contract_version": "4.0.0", - "content_digest": "2099b3ea8093d09350d31ce272868b412656d295d12f1b0f6c88d5cd64dc70ed" + "content_digest": "2099b3ea8093d09350d31ce272868b412656d295d12f1b0f6c88d5cd64dc70ed", + "functions": [ + { + "name": "qp_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "qp_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "unitconv", @@ -2291,7 +4065,7 @@ "source": "extensions/unitconv-component", "status": "working", "artifact": "artifacts/extensions/unitconv.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "unit_convert" ], @@ -2303,7 +4077,28 @@ "prefix": "unitconv", "expansion": "com.tegmentum.ducklink.unitconv", "wit_contract_version": "4.0.0", - "content_digest": "c434ad05004919763d434a0242d1c30a297a865c6ab6e445e47a02bf19554cfa" + "content_digest": "c434ad05004919763d434a0242d1c30a297a865c6ab6e445e47a02bf19554cfa", + "functions": [ + { + "name": "unit_convert", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "wordwrap", @@ -2326,7 +4121,7 @@ "source": "extensions/wordwrap-component", "status": "working", "artifact": "artifacts/extensions/wordwrap.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "word_wrap" ], @@ -2340,7 +4135,24 @@ "prefix": "wordwrap", "expansion": "com.tegmentum.ducklink.wordwrap", "wit_contract_version": "4.0.0", - "content_digest": "ee3e96bc7fc09e2102e80b77d8caf3b589daa0f9800dca8d752a1e34a3665c23" + "content_digest": "ee3e96bc7fc09e2102e80b77d8caf3b589daa0f9800dca8d752a1e34a3665c23", + "functions": [ + { + "name": "word_wrap", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "timezone", @@ -2363,7 +4175,7 @@ "source": "extensions/timezone-component", "status": "working", "artifact": "artifacts/extensions/timezone.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tz_valid", "tz_offset_seconds", @@ -2380,7 +4192,50 @@ "prefix": "timezone", "expansion": "com.tegmentum.ducklink.timezone", "wit_contract_version": "4.0.0", - "content_digest": "6dc11928728453ecf5afeaa634f07e7bc760c6f257b51b34ee184f4056906cae" + "content_digest": "6dc11928728453ecf5afeaa634f07e7bc760c6f257b51b34ee184f4056906cae", + "functions": [ + { + "name": "tz_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "tz_offset_seconds", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "tz_abbreviation", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "rot13", @@ -2403,7 +4258,7 @@ "source": "extensions/rot13-component", "status": "working", "artifact": "artifacts/extensions/rot13.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "rot13", "caesar" @@ -2416,7 +4271,35 @@ "prefix": "rot13", "expansion": "com.tegmentum.ducklink.rot13", "wit_contract_version": "4.0.0", - "content_digest": "9b88cd4e7ca34d0a9868a5e4f3213d4fac57eea8bb4799f17560446f23f0d476" + "content_digest": "9b88cd4e7ca34d0a9868a5e4f3213d4fac57eea8bb4799f17560446f23f0d476", + "functions": [ + { + "name": "rot13", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "caesar", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + }, + { + "name": "shift", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "leetspeak", @@ -2439,7 +4322,7 @@ "source": "extensions/leetspeak-component", "status": "working", "artifact": "artifacts/extensions/leetspeak.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_leet" ], @@ -2451,7 +4334,20 @@ "prefix": "leetspeak", "expansion": "com.tegmentum.ducklink.leetspeak", "wit_contract_version": "4.0.0", - "content_digest": "d2fb0fb5de0948cf1b1ce4db2ac31931c3f2922f31b8e0c3714f43697d91756f" + "content_digest": "d2fb0fb5de0948cf1b1ce4db2ac31931c3f2922f31b8e0c3714f43697d91756f", + "functions": [ + { + "name": "to_leet", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "dms", @@ -2474,7 +4370,7 @@ "source": "extensions/dms-component", "status": "working", "artifact": "artifacts/extensions/dms.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "dms_to_decimal", "decimal_to_dms" @@ -2487,7 +4383,39 @@ "prefix": "dms", "expansion": "com.tegmentum.ducklink.dms", "wit_contract_version": "4.0.0", - "content_digest": "d74608332dcafdfefe35abac811f4ce5d5c235323a1b9d331b5d25e50b56b1b6" + "content_digest": "d74608332dcafdfefe35abac811f4ce5d5c235323a1b9d331b5d25e50b56b1b6", + "functions": [ + { + "name": "dms_to_decimal", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "decimal_to_dms", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "cbor", @@ -2510,7 +4438,7 @@ "source": "extensions/cbor-component", "status": "working", "artifact": "artifacts/extensions/cbor.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "cbor_from_json", "cbor_to_json" @@ -2527,7 +4455,31 @@ "prefix": "cbor", "expansion": "com.tegmentum.ducklink.cbor", "wit_contract_version": "4.0.0", - "content_digest": "5d765ff8adfcf941dc6c7f9b28ee7ced2efc55ad4e46737d12189174125b4299" + "content_digest": "5d765ff8adfcf941dc6c7f9b28ee7ced2efc55ad4e46737d12189174125b4299", + "functions": [ + { + "name": "cbor_from_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "cbor_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "msgpack", @@ -2550,7 +4502,7 @@ "source": "extensions/msgpack-component", "status": "working", "artifact": "artifacts/extensions/msgpack.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "msgpack_from_json", "msgpack_to_json" @@ -2567,7 +4519,31 @@ "prefix": "msgpack", "expansion": "com.tegmentum.ducklink.msgpack", "wit_contract_version": "4.0.0", - "content_digest": "14a60d0dc7f6aaba2695bf3eeea4f2f89103cedbc7f071071916e3e90a6582fb" + "content_digest": "14a60d0dc7f6aaba2695bf3eeea4f2f89103cedbc7f071071916e3e90a6582fb", + "functions": [ + { + "name": "msgpack_from_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "msgpack_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "elements", @@ -2590,7 +4566,7 @@ "source": "extensions/elements-component", "status": "working", "artifact": "artifacts/extensions/elements.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "element_name", "element_number", @@ -2606,7 +4582,42 @@ "prefix": "elements", "expansion": "com.tegmentum.ducklink.elements", "wit_contract_version": "4.0.0", - "content_digest": "35d2137f91a9709f11ec61b060d70c80c583e5ee289dd6e68e0eda0b96a8628e" + "content_digest": "35d2137f91a9709f11ec61b060d70c80c583e5ee289dd6e68e0eda0b96a8628e", + "functions": [ + { + "name": "element_name", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "element_number", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "element_weight", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "vigenere", @@ -2629,7 +4640,7 @@ "source": "extensions/vigenere-component", "status": "working", "artifact": "artifacts/extensions/vigenere.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "vigenere_encrypt", "vigenere_decrypt" @@ -2642,7 +4653,39 @@ "prefix": "vigenere", "expansion": "com.tegmentum.ducklink.vigenere", "wit_contract_version": "4.0.0", - "content_digest": "74f00b669950b38cfd85a13458036216cd745298c40b65e1afc3633b4c888685" + "content_digest": "74f00b669950b38cfd85a13458036216cd745298c40b65e1afc3633b4c888685", + "functions": [ + { + "name": "vigenere_encrypt", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "vigenere_decrypt", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "petname", @@ -2665,7 +4708,7 @@ "source": "extensions/petname-component", "status": "working", "artifact": "artifacts/extensions/petname.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "petname" ], @@ -2679,7 +4722,24 @@ "prefix": "petname", "expansion": "com.tegmentum.ducklink.petname", "wit_contract_version": "4.0.0", - "content_digest": "5519a3066ce209b3fae7fdb556663817ff4b686e5c94e562ee1952915fda24e2" + "content_digest": "5519a3066ce209b3fae7fdb556663817ff4b686e5c94e562ee1952915fda24e2", + "functions": [ + { + "name": "petname", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "base58check", @@ -2702,7 +4762,7 @@ "source": "extensions/base58check-component", "status": "working", "artifact": "artifacts/extensions/base58check.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "base58check_encode", "base58check_decode" @@ -2717,7 +4777,31 @@ "prefix": "base58check", "expansion": "com.tegmentum.ducklink.base58check", "wit_contract_version": "4.0.0", - "content_digest": "08f4d1d8083c0e89260600994dce28ca138e4c8f50071650b764823653d93338" + "content_digest": "08f4d1d8083c0e89260600994dce28ca138e4c8f50071650b764823653d93338", + "functions": [ + { + "name": "base58check_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "base58check_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "checksums", @@ -2740,7 +4824,7 @@ "source": "extensions/checksums-component", "status": "working", "artifact": "artifacts/extensions/checksums.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "crc16", "adler32", @@ -2758,7 +4842,53 @@ "prefix": "checksums", "expansion": "com.tegmentum.ducklink.checksums", "wit_contract_version": "4.0.0", - "content_digest": "6f526ddc9400e387b6f96d3d76f91068e859e234eb92ff262048783ed097709b" + "content_digest": "6f526ddc9400e387b6f96d3d76f91068e859e234eb92ff262048783ed097709b", + "functions": [ + { + "name": "crc16", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "adler32", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "fnv1a_32", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "fnv1a_64", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "UBIGINT" + } + ] }, { "name": "siphash", @@ -2781,7 +4911,7 @@ "source": "extensions/siphash-component", "status": "working", "artifact": "artifacts/extensions/siphash.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "siphash" ], @@ -2795,7 +4925,28 @@ "prefix": "siphash", "expansion": "com.tegmentum.ducklink.siphash", "wit_contract_version": "4.0.0", - "content_digest": "61d8a888df0facb7abf91f589a7a44c4a31674efae42bceeb439f4bb34df03eb" + "content_digest": "61d8a888df0facb7abf91f589a7a44c4a31674efae42bceeb439f4bb34df03eb", + "functions": [ + { + "name": "siphash", + "kind": "scalar", + "arguments": [ + { + "name": "key0", + "type": "BIGINT" + }, + { + "name": "key1", + "type": "BIGINT" + }, + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "UBIGINT" + } + ] }, { "name": "tiktoken", @@ -2819,7 +4970,7 @@ "source": "extensions/tiktoken-component", "status": "working", "artifact": "artifacts/extensions/tiktoken.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tiktoken_count", "tiktoken_encode", @@ -2835,7 +4986,54 @@ "prefix": "tiktoken", "expansion": "com.tegmentum.ducklink.tiktoken", "wit_contract_version": "4.0.0", - "content_digest": "94ea70cc183bceacbe8a346a35d2c62c5b8c6cdd7f35984f41d109436450ccd6" + "content_digest": "94ea70cc183bceacbe8a346a35d2c62c5b8c6cdd7f35984f41d109436450ccd6", + "functions": [ + { + "name": "tiktoken_count", + "kind": "scalar", + "arguments": [ + { + "name": "input", + "type": "VARCHAR" + }, + { + "name": "encoding", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "tiktoken_encode", + "kind": "scalar", + "arguments": [ + { + "name": "input", + "type": "VARCHAR" + }, + { + "name": "encoding", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "tiktoken_decode", + "kind": "scalar", + "arguments": [ + { + "name": "input", + "type": "VARCHAR" + }, + { + "name": "encoding", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "bech32", @@ -2858,7 +5056,7 @@ "source": "extensions/bech32-component", "status": "working", "artifact": "artifacts/extensions/bech32.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "bech32_encode", "bech32_hrp", @@ -2875,7 +5073,57 @@ "prefix": "bech32", "expansion": "com.tegmentum.ducklink.bech32", "wit_contract_version": "4.0.0", - "content_digest": "dcf68ecfc692aa90135f37b35d2007bc8cb86364ef7db6330c399d6566fe267d" + "content_digest": "dcf68ecfc692aa90135f37b35d2007bc8cb86364ef7db6330c399d6566fe267d", + "functions": [ + { + "name": "bech32_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bech32_hrp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bech32_decode_hex", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bech32_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "uuid5", @@ -2898,7 +5146,7 @@ "source": "extensions/uuid5-component", "status": "working", "artifact": "artifacts/extensions/uuid5.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "uuid_v5", "uuid_v3" @@ -2913,7 +5161,39 @@ "prefix": "uuid5", "expansion": "com.tegmentum.ducklink.uuid5", "wit_contract_version": "4.0.0", - "content_digest": "537542a0565be59c61eff5981afbd66c14f7c7d8bc147a200335fdc59da783db" + "content_digest": "537542a0565be59c61eff5981afbd66c14f7c7d8bc147a200335fdc59da783db", + "functions": [ + { + "name": "uuid_v5", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "uuid_v3", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "gravatar", @@ -2936,7 +5216,7 @@ "source": "extensions/gravatar-component", "status": "working", "artifact": "artifacts/extensions/gravatar.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "gravatar_hash", "gravatar_url" @@ -2951,7 +5231,31 @@ "prefix": "gravatar", "expansion": "com.tegmentum.ducklink.gravatar", "wit_contract_version": "4.0.0", - "content_digest": "923be983601dd5ab5fb6e27849fdb65c9391beb81f1bfba6df5de7fb1ba61d84" + "content_digest": "923be983601dd5ab5fb6e27849fdb65c9391beb81f1bfba6df5de7fb1ba61d84", + "functions": [ + { + "name": "gravatar_hash", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "gravatar_url", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "html2text", @@ -2974,7 +5278,7 @@ "source": "extensions/html2text-component", "status": "working", "artifact": "artifacts/extensions/html2text.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "html_to_text" ], @@ -2988,7 +5292,20 @@ "prefix": "html2text", "expansion": "com.tegmentum.ducklink.html2text", "wit_contract_version": "4.0.0", - "content_digest": "fa89be624c678640f56fba211f617cce981f13f143a8242bb4ef5d93c78038b0" + "content_digest": "fa89be624c678640f56fba211f617cce981f13f143a8242bb4ef5d93c78038b0", + "functions": [ + { + "name": "html_to_text", + "kind": "scalar", + "arguments": [ + { + "name": "html", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "textstat", @@ -3011,7 +5328,7 @@ "source": "extensions/textstat-component", "status": "working", "artifact": "artifacts/extensions/textstat.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "word_count", "sentence_count", @@ -3027,7 +5344,64 @@ "prefix": "textstat", "expansion": "com.tegmentum.ducklink.textstat", "wit_contract_version": "4.0.0", - "content_digest": "67ad3c68d1ba52bd7fd9e5661a1575babbfe991013076573999c6306c069b840" + "content_digest": "67ad3c68d1ba52bd7fd9e5661a1575babbfe991013076573999c6306c069b840", + "functions": [ + { + "name": "word_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "sentence_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "syllable_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "flesch_reading_ease", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "reading_time_minutes", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "hashids", @@ -3050,7 +5424,7 @@ "source": "extensions/hashids-component", "status": "working", "artifact": "artifacts/extensions/hashids.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hashids_encode", "hashids_decode" @@ -3065,7 +5439,39 @@ "prefix": "hashids", "expansion": "com.tegmentum.ducklink.hashids", "wit_contract_version": "4.0.0", - "content_digest": "ce3a2542aeeb0174911da243325fe85e8fbaa896aac7be4d5cf6d80c47f631ec" + "content_digest": "ce3a2542aeeb0174911da243325fe85e8fbaa896aac7be4d5cf6d80c47f631ec", + "functions": [ + { + "name": "hashids_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hashids_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "checkdigit", @@ -3088,7 +5494,7 @@ "source": "extensions/checkdigit-component", "status": "working", "artifact": "artifacts/extensions/checkdigit.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "verhoeff_validate", "verhoeff_append", @@ -3103,7 +5509,53 @@ "prefix": "checkdigit", "expansion": "com.tegmentum.ducklink.checkdigit", "wit_contract_version": "4.0.0", - "content_digest": "91bbc152ab777b5ef59b1f8572fb77f6451215f7d0dc1ce23c2179ecef509dcf" + "content_digest": "91bbc152ab777b5ef59b1f8572fb77f6451215f7d0dc1ce23c2179ecef509dcf", + "functions": [ + { + "name": "verhoeff_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "verhoeff_append", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "damm_validate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "damm_append", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "dice", @@ -3126,7 +5578,7 @@ "source": "extensions/dice-component", "status": "working", "artifact": "artifacts/extensions/dice.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "dice_roll", "dice_min", @@ -3142,7 +5594,42 @@ "prefix": "dice", "expansion": "com.tegmentum.ducklink.dice", "wit_contract_version": "4.0.0", - "content_digest": "2e08d12ef99a0d426bfcfb6cc7dd9d3dd4180ca11cda7463641f01361e699385" + "content_digest": "2e08d12ef99a0d426bfcfb6cc7dd9d3dd4180ca11cda7463641f01361e699385", + "functions": [ + { + "name": "dice_roll", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "dice_min", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "dice_max", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "graycode", @@ -3165,7 +5652,7 @@ "source": "extensions/graycode-component", "status": "working", "artifact": "artifacts/extensions/graycode.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "gray_encode", "gray_decode" @@ -3178,7 +5665,31 @@ "prefix": "graycode", "expansion": "com.tegmentum.ducklink.graycode", "wit_contract_version": "4.0.0", - "content_digest": "932f2276c3ac44644502050730111b67227b829dc9c775e7f2b7eb6cf40cb856" + "content_digest": "932f2276c3ac44644502050730111b67227b829dc9c775e7f2b7eb6cf40cb856", + "functions": [ + { + "name": "gray_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "gray_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "cardtype", @@ -3201,7 +5712,7 @@ "source": "extensions/cardtype-component", "status": "working", "artifact": "artifacts/extensions/cardtype.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "card_brand" ], @@ -3213,7 +5724,20 @@ "prefix": "cardtype", "expansion": "com.tegmentum.ducklink.cardtype", "wit_contract_version": "4.0.0", - "content_digest": "59db3a2e2c4004389adbd38af664c887e1da5eedd88a121b2d002abb76e86711" + "content_digest": "59db3a2e2c4004389adbd38af664c887e1da5eedd88a121b2d002abb76e86711", + "functions": [ + { + "name": "card_brand", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "money", @@ -3236,7 +5760,7 @@ "source": "extensions/money-component", "status": "working", "artifact": "artifacts/extensions/money.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "format_money" ], @@ -3250,7 +5774,24 @@ "prefix": "money", "expansion": "com.tegmentum.ducklink.money", "wit_contract_version": "4.0.0", - "content_digest": "03e096dc2a1f9897230d440636a252e48730c4732ed5c3462c34949c00d13261" + "content_digest": "03e096dc2a1f9897230d440636a252e48730c4732ed5c3462c34949c00d13261", + "functions": [ + { + "name": "format_money", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ngrams", @@ -3273,7 +5814,7 @@ "source": "extensions/ngrams-component", "status": "working", "artifact": "artifacts/extensions/ngrams.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "char_ngrams", "word_ngrams" @@ -3288,7 +5829,39 @@ "prefix": "ngrams", "expansion": "com.tegmentum.ducklink.ngrams", "wit_contract_version": "4.0.0", - "content_digest": "34722b0fc920e2a2e262baca694c7fd0954ea2363ea666e0ac5806621d045b38" + "content_digest": "34722b0fc920e2a2e262baca694c7fd0954ea2363ea666e0ac5806621d045b38", + "functions": [ + { + "name": "char_ngrams", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "word_ngrams", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "stem", @@ -3311,7 +5884,7 @@ "source": "extensions/stem-component", "status": "working", "artifact": "artifacts/extensions/stem.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "stem" ], @@ -3325,7 +5898,24 @@ "prefix": "stem", "expansion": "com.tegmentum.ducklink.stem", "wit_contract_version": "4.0.0", - "content_digest": "c481c826058aea69054e9d3041d30ff0b6517a392f6dd85e5a116d4f0ad1b5e2" + "content_digest": "c481c826058aea69054e9d3041d30ff0b6517a392f6dd85e5a116d4f0ad1b5e2", + "functions": [ + { + "name": "stem", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "transliterate", @@ -3348,7 +5938,7 @@ "source": "extensions/transliterate-component", "status": "working", "artifact": "artifacts/extensions/transliterate.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "deunicode" ], @@ -3362,7 +5952,20 @@ "prefix": "transliterate", "expansion": "com.tegmentum.ducklink.transliterate", "wit_contract_version": "4.0.0", - "content_digest": "026512c1590598fa2737b7aa0b3a8422aed3320d959fdd539f0057cc972e477e" + "content_digest": "026512c1590598fa2737b7aa0b3a8422aed3320d959fdd539f0057cc972e477e", + "functions": [ + { + "name": "deunicode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "pluscode", @@ -3385,7 +5988,7 @@ "source": "extensions/pluscode-component", "status": "working", "artifact": "artifacts/extensions/pluscode.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "pluscode_encode", "pluscode_valid", @@ -3403,7 +6006,61 @@ "prefix": "pluscode", "expansion": "com.tegmentum.ducklink.pluscode", "wit_contract_version": "4.0.0", - "content_digest": "3c797495cc754c39297ec8fecb340dafb3546d2fe66bd773dfcf0e9d7916ac3c" + "content_digest": "3c797495cc754c39297ec8fecb340dafb3546d2fe66bd773dfcf0e9d7916ac3c", + "functions": [ + { + "name": "pluscode_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "pluscode_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "pluscode_decode_lat", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "pluscode_decode_lon", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "rot47", @@ -3426,7 +6083,7 @@ "source": "extensions/rot47-component", "status": "working", "artifact": "artifacts/extensions/rot47.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "rot47" ], @@ -3438,7 +6095,20 @@ "prefix": "rot47", "expansion": "com.tegmentum.ducklink.rot47", "wit_contract_version": "4.0.0", - "content_digest": "fddc88a0191b019b434ed71ccb9a78048d8a479d3e530980b78e04dd0d5cab52" + "content_digest": "fddc88a0191b019b434ed71ccb9a78048d8a479d3e530980b78e04dd0d5cab52", + "functions": [ + { + "name": "rot47", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "stopwords", @@ -3461,7 +6131,7 @@ "source": "extensions/stopwords-component", "status": "working", "artifact": "artifacts/extensions/stopwords.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "is_stopword", "remove_stopwords" @@ -3476,10 +6146,42 @@ "prefix": "stopwords", "expansion": "com.tegmentum.ducklink.stopwords", "wit_contract_version": "4.0.0", - "content_digest": "03492d94fc06905cdb7324df41dea442d22761d616e38f80f14f3c5ffb412285" - }, - { - "name": "isbnconv", + "content_digest": "03492d94fc06905cdb7324df41dea442d22761d616e38f80f14f3c5ffb412285", + "functions": [ + { + "name": "is_stopword", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "remove_stopwords", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] + }, + { + "name": "isbnconv", "version": "0.1.0", "description": "ISBN-10 <-> ISBN-13 conversion (hand-rolled checksums): isbn10_to_13, isbn13_to_10 (978-prefixed only). Complements isbn (validate/normalize). Invalid length -> NULL.", "license": "MIT", @@ -3499,7 +6201,7 @@ "source": "extensions/isbnconv-component", "status": "working", "artifact": "artifacts/extensions/isbnconv.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "isbn10_to_13", "isbn13_to_10" @@ -3512,7 +6214,31 @@ "prefix": "isbnconv", "expansion": "com.tegmentum.ducklink.isbnconv", "wit_contract_version": "4.0.0", - "content_digest": "1e38ddd1bd100e1ed574ded66af53cb458ccb7e1b638018d05dd8b37579ec27e" + "content_digest": "1e38ddd1bd100e1ed574ded66af53cb458ccb7e1b638018d05dd8b37579ec27e", + "functions": [ + { + "name": "isbn10_to_13", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "isbn13_to_10", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "passgen", @@ -3535,7 +6261,7 @@ "source": "extensions/passgen-component", "status": "working", "artifact": "artifacts/extensions/passgen.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "gen_password", "gen_password_alnum" @@ -3550,7 +6276,31 @@ "prefix": "passgen", "expansion": "com.tegmentum.ducklink.passgen", "wit_contract_version": "4.0.0", - "content_digest": "5bf1e4e3c4a6036f2d3e9550590afbde1d93a1013e1d40a130fd7248a8c2f42e" + "content_digest": "5bf1e4e3c4a6036f2d3e9550590afbde1d93a1013e1d40a130fd7248a8c2f42e", + "functions": [ + { + "name": "gen_password", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "gen_password_alnum", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "braille", @@ -3573,7 +6323,7 @@ "source": "extensions/braille-component", "status": "working", "artifact": "artifacts/extensions/braille.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_braille" ], @@ -3585,7 +6335,20 @@ "prefix": "braille", "expansion": "com.tegmentum.ducklink.braille", "wit_contract_version": "4.0.0", - "content_digest": "66ddde696ba8818df0eab3451c3c0b90285170848c20fbdc68e5b8ea8ebecabb" + "content_digest": "66ddde696ba8818df0eab3451c3c0b90285170848c20fbdc68e5b8ea8ebecabb", + "functions": [ + { + "name": "to_braille", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "toml", @@ -3608,7 +6371,7 @@ "source": "extensions/toml-component", "status": "working", "artifact": "artifacts/extensions/toml.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "toml_to_json", "json_to_toml" @@ -3624,7 +6387,31 @@ "prefix": "toml", "expansion": "com.tegmentum.ducklink.toml", "wit_contract_version": "4.0.0", - "content_digest": "147926ae9ade4302eed438d80f35c8e4bb53235656f3122f479d2ccdb1f09869" + "content_digest": "147926ae9ade4302eed438d80f35c8e4bb53235656f3122f479d2ccdb1f09869", + "functions": [ + { + "name": "toml_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_to_toml", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "yaml", @@ -3647,7 +6434,7 @@ "source": "extensions/yaml-component", "status": "working", "artifact": "artifacts/extensions/yaml.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "yaml_to_json", "json_to_yaml" @@ -3663,7 +6450,31 @@ "prefix": "yaml", "expansion": "com.tegmentum.ducklink.yaml", "wit_contract_version": "4.0.0", - "content_digest": "2446af404fc86f84ea758e4165c442a46329fbfa560b0326b1529f83c3c4607f" + "content_digest": "2446af404fc86f84ea758e4165c442a46329fbfa560b0326b1529f83c3c4607f", + "functions": [ + { + "name": "yaml_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_to_yaml", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "unicodenorm", @@ -3686,7 +6497,7 @@ "source": "extensions/unicodenorm-component", "status": "working", "artifact": "artifacts/extensions/unicodenorm.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "nfc", "nfd", @@ -3703,7 +6514,53 @@ "prefix": "unicodenorm", "expansion": "com.tegmentum.ducklink.unicodenorm", "wit_contract_version": "4.0.0", - "content_digest": "093f45a4ecd63a2012a1a8aa779e5725e8c93973234a1ebfb649851f7dc9606b" + "content_digest": "093f45a4ecd63a2012a1a8aa779e5725e8c93973234a1ebfb649851f7dc9606b", + "functions": [ + { + "name": "nfc", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "nfd", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "nfkc", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "nfkd", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "unicodewidth", @@ -3726,7 +6583,7 @@ "source": "extensions/unicodewidth-component", "status": "working", "artifact": "artifacts/extensions/unicodewidth.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "grapheme_count", "display_width" @@ -3742,7 +6599,31 @@ "prefix": "unicodewidth", "expansion": "com.tegmentum.ducklink.unicodewidth", "wit_contract_version": "4.0.0", - "content_digest": "29ee6a9dfaa674bea2412b95aa9a809340339e82d6daed1c84a94d1ab452b919" + "content_digest": "29ee6a9dfaa674bea2412b95aa9a809340339e82d6daed1c84a94d1ab452b919", + "functions": [ + { + "name": "grapheme_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "display_width", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "colorconv", @@ -3765,7 +6646,7 @@ "source": "extensions/colorconv-component", "status": "working", "artifact": "artifacts/extensions/colorconv.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hex_to_hsl", "hex_to_hsv", @@ -3779,7 +6660,50 @@ "prefix": "colorconv", "expansion": "com.tegmentum.ducklink.colorconv", "wit_contract_version": "4.0.0", - "content_digest": "dc3fb9830b141b6e82396a8de3c832723a9c6d311b6f29c44f304c6ff38bc96a" + "content_digest": "dc3fb9830b141b6e82396a8de3c832723a9c6d311b6f29c44f304c6ff38bc96a", + "functions": [ + { + "name": "hex_to_hsl", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hex_to_hsv", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hsl_to_hex", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "jsonschema", @@ -3801,7 +6725,7 @@ "source": "extensions/jsonschema-component", "status": "working", "artifact": "artifacts/extensions/jsonschema.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "json_schema_valid" ], @@ -3816,7 +6740,24 @@ "prefix": "jsonschema", "expansion": "com.tegmentum.ducklink.jsonschema", "wit_contract_version": "4.0.0", - "content_digest": "b920068681e22ac01231d6289b0ad5812b9dad563139ead4e1ab4278b46e952c" + "content_digest": "b920068681e22ac01231d6289b0ad5812b9dad563139ead4e1ab4278b46e952c", + "functions": [ + { + "name": "json_schema_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "simhash", @@ -3839,7 +6780,7 @@ "source": "extensions/simhash-component", "status": "working", "artifact": "artifacts/extensions/simhash.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "simhash", "simhash_distance" @@ -3852,7 +6793,35 @@ "prefix": "simhash", "expansion": "com.tegmentum.ducklink.simhash", "wit_contract_version": "4.0.0", - "content_digest": "fa264596464f5811031a082c0a0b0b34420a4f0b21784a7e07ff73d576cf61bd" + "content_digest": "fa264596464f5811031a082c0a0b0b34420a4f0b21784a7e07ff73d576cf61bd", + "functions": [ + { + "name": "simhash", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "UBIGINT" + }, + { + "name": "simhash_distance", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "idextra", @@ -3875,7 +6844,7 @@ "source": "extensions/idextra-component", "status": "working", "artifact": "artifacts/extensions/idextra.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ksuid", "cuid2" @@ -3891,7 +6860,21 @@ "prefix": "idextra", "expansion": "com.tegmentum.ducklink.idextra", "wit_contract_version": "4.0.0", - "content_digest": "dc85613c8303bd7082c695aa50dc452770e2f181db32100cbf2351ccd5e4c110" + "content_digest": "dc85613c8303bd7082c695aa50dc452770e2f181db32100cbf2351ccd5e4c110", + "functions": [ + { + "name": "ksuid", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "cuid2", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + } + ] }, { "name": "phonetic2", @@ -3914,7 +6897,7 @@ "source": "extensions/phonetic2-component", "status": "working", "artifact": "artifacts/extensions/phonetic2.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "nysiis", "refined_soundex", @@ -3930,7 +6913,42 @@ "prefix": "phonetic2", "expansion": "com.tegmentum.ducklink.phonetic2", "wit_contract_version": "4.0.0", - "content_digest": "f0bf6207f8c32294b1f5b5cf6cc7bf17d11699c63cc338ae67d5c349fb8955f8" + "content_digest": "f0bf6207f8c32294b1f5b5cf6cc7bf17d11699c63cc338ae67d5c349fb8955f8", + "functions": [ + { + "name": "nysiis", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "refined_soundex", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "double_metaphone", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "z85", @@ -3953,7 +6971,7 @@ "source": "extensions/z85-component", "status": "working", "artifact": "artifacts/extensions/z85.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "z85_encode", "z85_decode" @@ -3968,7 +6986,31 @@ "prefix": "z85", "expansion": "com.tegmentum.ducklink.z85", "wit_contract_version": "4.0.0", - "content_digest": "91cf984bcde740137802ca0760c47d0719671807ded37d8279e6e6b8a538ab5e" + "content_digest": "91cf984bcde740137802ca0760c47d0719671807ded37d8279e6e6b8a538ab5e", + "functions": [ + { + "name": "z85_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "z85_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "initials", @@ -3991,7 +7033,7 @@ "source": "extensions/initials-component", "status": "working", "artifact": "artifacts/extensions/initials.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "initials", "initials_dotted" @@ -4004,7 +7046,31 @@ "prefix": "initials", "expansion": "com.tegmentum.ducklink.initials", "wit_contract_version": "4.0.0", - "content_digest": "ee3e5e71ab719fc72c8f0d2b2b345e0ff8136a6850323133fbac2ef1168ee68d" + "content_digest": "ee3e5e71ab719fc72c8f0d2b2b345e0ff8136a6850323133fbac2ef1168ee68d", + "functions": [ + { + "name": "initials", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "initials_dotted", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "luhngen", @@ -4027,7 +7093,7 @@ "source": "extensions/luhngen-component", "status": "working", "artifact": "artifacts/extensions/luhngen.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "luhn_check_digit", "luhn_append" @@ -4040,7 +7106,31 @@ "prefix": "luhngen", "expansion": "com.tegmentum.ducklink.luhngen", "wit_contract_version": "4.0.0", - "content_digest": "f8ee7a1ba7ee12c16e83109e9a69103961c8fdead739eb8ef670ae2fce860b79" + "content_digest": "f8ee7a1ba7ee12c16e83109e9a69103961c8fdead739eb8ef670ae2fce860b79", + "functions": [ + { + "name": "luhn_check_digit", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "luhn_append", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "pintest_a", @@ -4064,7 +7154,7 @@ "source": "extensions/pintest-a-component", "status": "working", "artifact": "artifacts/extensions/pintest_a.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "pin_probe" ], @@ -4074,7 +7164,15 @@ "crates": [], "min_duckdb_version": "1.0.0", "wit_contract_version": "4.0.0", - "content_digest": "e54b36bfb58a41da426ba0d8823c4bc85d0e6e436e3637fe1d73b6e38a9f0c54" + "content_digest": "e54b36bfb58a41da426ba0d8823c4bc85d0e6e436e3637fe1d73b6e38a9f0c54", + "functions": [ + { + "name": "pin_probe", + "kind": "scalar", + "arguments": [], + "returns": "INTEGER" + } + ] }, { "name": "pintest_b", @@ -4098,7 +7196,7 @@ "source": "extensions/pintest-b-component", "status": "working", "artifact": "artifacts/extensions/pintest_b.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "pin_probe" ], @@ -4108,7 +7206,15 @@ "crates": [], "min_duckdb_version": "1.0.0", "wit_contract_version": "4.0.0", - "content_digest": "3768199fb35f13dd8253f1aba26ccfff98381bb4b07d560a3ac8e063d390f894" + "content_digest": "3768199fb35f13dd8253f1aba26ccfff98381bb4b07d560a3ac8e063d390f894", + "functions": [ + { + "name": "pin_probe", + "kind": "scalar", + "arguments": [], + "returns": "INTEGER" + } + ] }, { "name": "atbash", @@ -4131,7 +7237,7 @@ "source": "extensions/atbash-component", "status": "working", "artifact": "artifacts/extensions/atbash.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "atbash" ], @@ -4155,10 +7261,23 @@ "conformance": { "suite": "atbash@4", "suite_digest": "618f290b2e4031a00c48453fbfbff5c9128d05f124adbfe12e71eb813493e719", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "atbash", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } ] }, { @@ -4182,7 +7301,7 @@ "source": "extensions/piglatin-component", "status": "working", "artifact": "artifacts/extensions/piglatin.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_pig_latin" ], @@ -4194,7 +7313,20 @@ "prefix": "piglatin", "expansion": "com.tegmentum.ducklink.piglatin", "wit_contract_version": "4.0.0", - "content_digest": "39e937afb02ed3a8fac17a4acd24d89b9fd03a8d023e87affdc5b80253d1f445" + "content_digest": "39e937afb02ed3a8fac17a4acd24d89b9fd03a8d023e87affdc5b80253d1f445", + "functions": [ + { + "name": "to_pig_latin", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "rle", @@ -4217,7 +7349,7 @@ "source": "extensions/rle-component", "status": "working", "artifact": "artifacts/extensions/rle.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "rle_encode", "rle_decode" @@ -4230,7 +7362,31 @@ "prefix": "rle", "expansion": "com.tegmentum.ducklink.rle", "wit_contract_version": "4.0.0", - "content_digest": "16e45533a8cf02a3ba5a044280d5c5053d634136e6c9987acd347f16b5567df1" + "content_digest": "16e45533a8cf02a3ba5a044280d5c5053d634136e6c9987acd347f16b5567df1", + "functions": [ + { + "name": "rle_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "rle_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "bbcode", @@ -4253,7 +7409,7 @@ "source": "extensions/bbcode-component", "status": "working", "artifact": "artifacts/extensions/bbcode.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "bbcode_to_html" ], @@ -4265,7 +7421,20 @@ "prefix": "bbcode", "expansion": "com.tegmentum.ducklink.bbcode", "wit_contract_version": "4.0.0", - "content_digest": "6ff22f6b3ba698ecad8f08bed2b1befd359e2771d5f0dbfe8187b725378a9812" + "content_digest": "6ff22f6b3ba698ecad8f08bed2b1befd359e2771d5f0dbfe8187b725378a9812", + "functions": [ + { + "name": "bbcode_to_html", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "phonenumber", @@ -4288,7 +7457,7 @@ "source": "extensions/phonenumber-component", "status": "working", "artifact": "artifacts/extensions/phonenumber.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "phone_valid", "phone_format", @@ -4304,7 +7473,58 @@ "prefix": "phonenumber", "expansion": "com.tegmentum.ducklink.phonenumber", "wit_contract_version": "4.0.0", - "content_digest": "fe8d6e914546ae738b682e9391c98e1dde4bebe6db591d398f3b6f47bda774d0" + "content_digest": "fe8d6e914546ae738b682e9391c98e1dde4bebe6db591d398f3b6f47bda774d0", + "functions": [ + { + "name": "phone_valid", + "kind": "scalar", + "arguments": [ + { + "name": "number", + "type": "VARCHAR" + }, + { + "name": "region", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "phone_format", + "kind": "scalar", + "arguments": [ + { + "name": "number", + "type": "VARCHAR" + }, + { + "name": "region", + "type": "VARCHAR" + }, + { + "name": "mode", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "phone_country_code", + "kind": "scalar", + "arguments": [ + { + "name": "number", + "type": "VARCHAR" + }, + { + "name": "region", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "pwstrength", @@ -4327,7 +7547,7 @@ "source": "extensions/pwstrength-component", "status": "working", "artifact": "artifacts/extensions/pwstrength.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "password_score", "password_strength" @@ -4342,7 +7562,31 @@ "prefix": "pwstrength", "expansion": "com.tegmentum.ducklink.pwstrength", "wit_contract_version": "4.0.0", - "content_digest": "ba0abfd648d3f5b9ad374e4d3839e039a879c317914e9898d49b679dbc025502" + "content_digest": "ba0abfd648d3f5b9ad374e4d3839e039a879c317914e9898d49b679dbc025502", + "functions": [ + { + "name": "password_score", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "password_strength", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "qrcode", @@ -4365,7 +7609,7 @@ "source": "extensions/qrcode-component", "status": "working", "artifact": "artifacts/extensions/qrcode.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "qr_svg" ], @@ -4379,7 +7623,20 @@ "prefix": "qrcode", "expansion": "com.tegmentum.ducklink.qrcode", "wit_contract_version": "4.0.0", - "content_digest": "76679efabfad700beb510375900d1c1f728c6eb47122439275de1ad8fe135994" + "content_digest": "76679efabfad700beb510375900d1c1f728c6eb47122439275de1ad8fe135994", + "functions": [ + { + "name": "qr_svg", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "aggstat", @@ -4402,7 +7659,7 @@ "source": "extensions/aggstat-component", "status": "working", "artifact": "artifacts/extensions/aggstat.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "harmonic_mean" ], @@ -4426,10 +7683,23 @@ "conformance": { "suite": "aggstat@4", "suite_digest": "14eec21dc0c9373b3c83730b7d2b0d11615595e2fafea5005828a9992a34093e", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "harmonic_mean", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } ] }, { @@ -4453,7 +7723,7 @@ "source": "extensions/bloom-component", "status": "working", "artifact": "artifacts/extensions/bloom.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "bloom_filter", "bloom_contains" @@ -4467,7 +7737,35 @@ "prefix": "bloom", "expansion": "com.tegmentum.ducklink.bloom", "wit_contract_version": "4.0.0", - "content_digest": "ffc5528f8c0f81f99145d5d54eb6cf08ffad022901fbd9033077f7067c587bfb" + "content_digest": "ffc5528f8c0f81f99145d5d54eb6cf08ffad022901fbd9033077f7067c587bfb", + "functions": [ + { + "name": "bloom_contains", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "bloom_filter", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "minhash", @@ -4490,7 +7788,7 @@ "source": "extensions/minhash-component", "status": "working", "artifact": "artifacts/extensions/minhash.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "minhash", "minhash_similarity" @@ -4504,7 +7802,35 @@ "prefix": "minhash", "expansion": "com.tegmentum.ducklink.minhash", "wit_contract_version": "4.0.0", - "content_digest": "6b12e60021db92f754211cbeb8b29ecdc643f0e1c39883f8fc60a61dc8b1ba36" + "content_digest": "6b12e60021db92f754211cbeb8b29ecdc643f0e1c39883f8fc60a61dc8b1ba36", + "functions": [ + { + "name": "minhash_similarity", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "minhash", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "countmin", @@ -4527,7 +7853,7 @@ "source": "extensions/countmin-component", "status": "working", "artifact": "artifacts/extensions/countmin.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "count_min", "cms_estimate" @@ -4541,7 +7867,35 @@ "prefix": "countmin", "expansion": "com.tegmentum.ducklink.countmin", "wit_contract_version": "4.0.0", - "content_digest": "a4f17308cd177afa7c9795df4fc955cf3bf0ca373a4b3aea567979e1ba10a6fb" + "content_digest": "a4f17308cd177afa7c9795df4fc955cf3bf0ca373a4b3aea567979e1ba10a6fb", + "functions": [ + { + "name": "cms_estimate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "count_min", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "dns", @@ -4564,7 +7918,7 @@ "source": "extensions/dns-component", "status": "working", "artifact": "artifacts/extensions/dns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "dns_lookup", "dns_resolve_all" @@ -4578,7 +7932,31 @@ "prefix": "dns", "expansion": "com.tegmentum.ducklink.dns", "wit_contract_version": "4.0.0", - "content_digest": "84c62d4bbd738b4a9ee1d41d42926adfb4936eaffc387a01d27c380e0ed3a770" + "content_digest": "84c62d4bbd738b4a9ee1d41d42926adfb4936eaffc387a01d27c380e0ed3a770", + "functions": [ + { + "name": "dns_lookup", + "kind": "scalar", + "arguments": [ + { + "name": "host", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "dns_resolve_all", + "kind": "scalar", + "arguments": [ + { + "name": "host", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "httpclient", @@ -4601,7 +7979,7 @@ "source": "extensions/httpclient-component", "status": "working", "artifact": "artifacts/extensions/httpclient.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "http_get", "http_status", @@ -4620,7 +7998,46 @@ "prefix": "httpclient", "expansion": "com.tegmentum.ducklink.httpclient", "wit_contract_version": "4.0.0", - "content_digest": "5fc306269a96b434913f159075383e97649dd3b16bf69a67d21db24019bd3bf5" + "content_digest": "5fc306269a96b434913f159075383e97649dd3b16bf69a67d21db24019bd3bf5", + "functions": [ + { + "name": "http_get", + "kind": "scalar", + "arguments": [ + { + "name": "url", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "http_status", + "kind": "scalar", + "arguments": [ + { + "name": "url", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "http_post", + "kind": "scalar", + "arguments": [ + { + "name": "url", + "type": "VARCHAR" + }, + { + "name": "body", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "lorem", @@ -4643,7 +8060,7 @@ "source": "extensions/lorem-component", "status": "working", "artifact": "artifacts/extensions/lorem.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "lorem_words", "lorem_title" @@ -4658,7 +8075,26 @@ "prefix": "lorem", "expansion": "com.tegmentum.ducklink.lorem", "wit_contract_version": "4.0.0", - "content_digest": "db119f3573aa8db6468c6ecf4438fc383544ea4f57fd5cfbb26b0955fe09fa46" + "content_digest": "db119f3573aa8db6468c6ecf4438fc383544ea4f57fd5cfbb26b0955fe09fa46", + "functions": [ + { + "name": "lorem_words", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "lorem_title", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + } + ] }, { "name": "faker", @@ -4681,7 +8117,7 @@ "source": "extensions/faker-component", "status": "working", "artifact": "artifacts/extensions/faker.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "fake_name", "fake_email", @@ -4699,7 +8135,39 @@ "prefix": "faker", "expansion": "com.tegmentum.ducklink.faker", "wit_contract_version": "4.0.0", - "content_digest": "6bcf7aec31c6adab1bd2c0a4122081461ed99fb31affddf9ee1dd46280526b7b" + "content_digest": "6bcf7aec31c6adab1bd2c0a4122081461ed99fb31affddf9ee1dd46280526b7b", + "functions": [ + { + "name": "fake_name", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "fake_email", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "fake_username", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "fake_city", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "fake_company", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + } + ] }, { "name": "passphrase", @@ -4722,7 +8190,7 @@ "source": "extensions/passphrase-component", "status": "working", "artifact": "artifacts/extensions/passphrase.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "passphrase" ], @@ -4736,7 +8204,15 @@ "prefix": "passphrase", "expansion": "com.tegmentum.ducklink.passphrase", "wit_contract_version": "4.0.0", - "content_digest": "1fcb4f1398d1fb8085a7fba5c997e0486038caba379a4ea9e5c4bee1cbc77037" + "content_digest": "1fcb4f1398d1fb8085a7fba5c997e0486038caba379a4ea9e5c4bee1cbc77037", + "functions": [ + { + "name": "passphrase", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + } + ] }, { "name": "h3", @@ -4759,7 +8235,7 @@ "source": "extensions/h3-component", "status": "working", "artifact": "artifacts/extensions/h3.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "h3_latlng_to_cell", "h3_cell_to_lat", @@ -4790,10 +8266,94 @@ "conformance": { "suite": "h3@4", "suite_digest": "bdac7a0ab7cc22fe084b3064a14a558c6ad77ed08691726f94b24fc126fb63dc", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "h3_latlng_to_cell", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "h3_cell_to_lat", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "DOUBLE" + }, + { + "name": "h3_cell_to_lng", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "DOUBLE" + }, + { + "name": "h3_cell_to_parent", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "h3_grid_distance", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "h3_is_valid_cell", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BOOLEAN" + } ] }, { @@ -4817,7 +8377,7 @@ "source": "extensions/lindel-component", "status": "working", "artifact": "artifacts/extensions/lindel.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "morton_encode", "morton_decode_x", @@ -4834,7 +8394,83 @@ "prefix": "lindel", "expansion": "com.tegmentum.ducklink.lindel", "wit_contract_version": "4.0.0", - "content_digest": "e83af9ebbb1d7ba6b06c04d80af14d114aec676d456c5cf66283e51e1984cc06" + "content_digest": "e83af9ebbb1d7ba6b06c04d80af14d114aec676d456c5cf66283e51e1984cc06", + "functions": [ + { + "name": "morton_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "hilbert_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "morton_decode_x", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "morton_decode_y", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "hilbert_decode_x", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "hilbert_decode_y", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "magic", @@ -4857,7 +8493,7 @@ "source": "extensions/magic-component", "status": "working", "artifact": "artifacts/extensions/magic.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "magic_mime", "magic_extension", @@ -4874,7 +8510,53 @@ "prefix": "magic", "expansion": "com.tegmentum.ducklink.magic", "wit_contract_version": "4.0.0", - "content_digest": "c2a0d8dfc124d0d373a789dd4e325fa461e6ea0370ab5bd89b8844f80728ed8d" + "content_digest": "c2a0d8dfc124d0d373a789dd4e325fa461e6ea0370ab5bd89b8844f80728ed8d", + "functions": [ + { + "name": "magic_mime", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "magic_extension", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "magic_matcher_type", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "is_image", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "tsid", @@ -4897,7 +8579,7 @@ "source": "extensions/tsid-component", "status": "working", "artifact": "artifacts/extensions/tsid.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tsid_encode", "tsid_decode", @@ -4912,7 +8594,53 @@ "prefix": "tsid", "expansion": "com.tegmentum.ducklink.tsid", "wit_contract_version": "4.0.0", - "content_digest": "d900348ea6b8263bffad39ed74d02443a4d6b760ab79ac19aa592229558f0f68" + "content_digest": "d900348ea6b8263bffad39ed74d02443a4d6b760ab79ac19aa592229558f0f68", + "functions": [ + { + "name": "tsid_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "tsid_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "tsid_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "tsid_from_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "rhai", @@ -4935,7 +8663,7 @@ "source": "extensions/rhai-component", "status": "working", "artifact": "artifacts/extensions/rhai.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "rhai_eval", "rhai_eval_int", @@ -4951,7 +8679,42 @@ "prefix": "rhai", "expansion": "com.tegmentum.ducklink.rhai", "wit_contract_version": "4.0.0", - "content_digest": "e86e9f36aecdb344eedc42e4dd5b6af2a387e3471d97bf7cec606d1ccc7b56ef" + "content_digest": "e86e9f36aecdb344eedc42e4dd5b6af2a387e3471d97bf7cec606d1ccc7b56ef", + "functions": [ + { + "name": "rhai_eval", + "kind": "scalar", + "arguments": [ + { + "name": "expr", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "rhai_eval_int", + "kind": "scalar", + "arguments": [ + { + "name": "expr", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "rhai_eval_double", + "kind": "scalar", + "arguments": [ + { + "name": "expr", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "bitfilters", @@ -4974,7 +8737,7 @@ "source": "extensions/bitfilters-component", "status": "working", "artifact": "artifacts/extensions/bitfilters.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "xor_filter", "xor_filter_contains" @@ -4991,7 +8754,35 @@ "prefix": "bitfilters", "expansion": "com.tegmentum.ducklink.bitfilters", "wit_contract_version": "4.0.0", - "content_digest": "08b0797c2dca186962ce2099d9370f9d20f6c05e93b2ed56341aa885f5086c6a" + "content_digest": "08b0797c2dca186962ce2099d9370f9d20f6c05e93b2ed56341aa885f5086c6a", + "functions": [ + { + "name": "xor_filter_contains", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "xor_filter", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BLOB" + } + ] }, { "name": "prql", @@ -5008,7 +8799,7 @@ "source": "extensions/prql-component", "status": "working", "artifact": "artifacts/extensions/prql.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "prql_to_sql", "prql_is_valid" @@ -5023,7 +8814,31 @@ "prefix": "prql", "expansion": "com.tegmentum.ducklink.prql", "wit_contract_version": "4.0.0", - "content_digest": "4be949b6c2cd8ee2d677193646f2951fefa1177319ee92b87bf71add0d1db93e" + "content_digest": "4be949b6c2cd8ee2d677193646f2951fefa1177319ee92b87bf71add0d1db93e", + "functions": [ + { + "name": "prql_to_sql", + "kind": "scalar", + "arguments": [ + { + "name": "prql", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "prql_is_valid", + "kind": "scalar", + "arguments": [ + { + "name": "prql", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "jaq", @@ -5040,7 +8855,7 @@ "source": "extensions/jaq-component", "status": "working", "artifact": "artifacts/extensions/jaq.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "jq", "jq_first" @@ -5057,7 +8872,39 @@ "prefix": "jaq", "expansion": "com.tegmentum.ducklink.jaq", "wit_contract_version": "4.0.0", - "content_digest": "faa452af886d1aefb7e9b314b52bda4b54ca6b1ab5febbcda36b5313a527813c" + "content_digest": "faa452af886d1aefb7e9b314b52bda4b54ca6b1ab5febbcda36b5313a527813c", + "functions": [ + { + "name": "jq", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "filter", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "jq_first", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "filter", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "cron", @@ -5074,7 +8921,7 @@ "source": "extensions/cron-component", "status": "working", "artifact": "artifacts/extensions/cron.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "cron_is_valid", "cron_next", @@ -5090,7 +8937,50 @@ "prefix": "cron", "expansion": "com.tegmentum.ducklink.cron", "wit_contract_version": "4.0.0", - "content_digest": "994a33a9588bef95ce1e5e0e282c59df32cf6540c40e12feba1a163e4adc0758" + "content_digest": "994a33a9588bef95ce1e5e0e282c59df32cf6540c40e12feba1a163e4adc0758", + "functions": [ + { + "name": "cron_is_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "cron_next", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "cron_prev", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "xml", @@ -5107,7 +8997,7 @@ "source": "extensions/xml-component", "status": "working", "artifact": "artifacts/extensions/xml.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "xml_valid", "xml_extract", @@ -5123,7 +9013,50 @@ "prefix": "xml", "expansion": "com.tegmentum.ducklink.xml", "wit_contract_version": "4.0.0", - "content_digest": "7f630466cf86736e3d267596dc73012f6fbea7949425fe37c10d1ecf98bc7612" + "content_digest": "7f630466cf86736e3d267596dc73012f6fbea7949425fe37c10d1ecf98bc7612", + "functions": [ + { + "name": "xml_valid", + "kind": "scalar", + "arguments": [ + { + "name": "xml", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "xml_extract", + "kind": "scalar", + "arguments": [ + { + "name": "xml", + "type": "VARCHAR" + }, + { + "name": "xpath", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "xml_extract_all", + "kind": "scalar", + "arguments": [ + { + "name": "xml", + "type": "VARCHAR" + }, + { + "name": "xpath", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "pinyin", @@ -5140,7 +9073,7 @@ "source": "extensions/pinyin-component", "status": "working", "artifact": "artifacts/extensions/pinyin.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_pinyin", "to_pinyin_plain", @@ -5156,12 +9089,47 @@ "prefix": "pinyin", "expansion": "com.tegmentum.ducklink.pinyin", "wit_contract_version": "4.0.0", - "content_digest": "43735b6ee494184519c15cf8f931e3c847b41c2d2e14f2b7ef926bc8e109afab" - }, - { - "name": "sqlformat", - "version": "0.1.0", - "description": "SQL pretty-printer: sql_format, sql_format_compact (sqlformat).", + "content_digest": "43735b6ee494184519c15cf8f931e3c847b41c2d2e14f2b7ef926bc8e109afab", + "functions": [ + { + "name": "to_pinyin", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_pinyin_plain", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_pinyin_initials", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] + }, + { + "name": "sqlformat", + "version": "0.1.0", + "description": "SQL pretty-printer: sql_format, sql_format_compact (sqlformat).", "license": "MIT", "authors": [ "Tegmentum" @@ -5173,7 +9141,7 @@ "source": "extensions/sqlformat-component", "status": "working", "artifact": "artifacts/extensions/sqlformat.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sql_format", "sql_format_compact" @@ -5188,7 +9156,31 @@ "prefix": "sqlformat", "expansion": "com.tegmentum.ducklink.sqlformat", "wit_contract_version": "4.0.0", - "content_digest": "26e3b882f7edc0e1f6b449d2fe78a8c5adb3e28529d9d2f1af13d282f79c9d78" + "content_digest": "26e3b882f7edc0e1f6b449d2fe78a8c5adb3e28529d9d2f1af13d282f79c9d78", + "functions": [ + { + "name": "sql_format", + "kind": "scalar", + "arguments": [ + { + "name": "sql", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sql_format_compact", + "kind": "scalar", + "arguments": [ + { + "name": "sql", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "bencode", @@ -5205,7 +9197,7 @@ "source": "extensions/bencode-component", "status": "working", "artifact": "artifacts/extensions/bencode.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "bencode_to_json", "bencode_is_valid" @@ -5220,7 +9212,31 @@ "prefix": "bencode", "expansion": "com.tegmentum.ducklink.bencode", "wit_contract_version": "4.0.0", - "content_digest": "252dce17cd1273ad08a350023a8d6fd2ad582e5b12d2b4c3ac9ab1022de7240a" + "content_digest": "252dce17cd1273ad08a350023a8d6fd2ad582e5b12d2b4c3ac9ab1022de7240a", + "functions": [ + { + "name": "bencode_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bencode_is_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "maidenhead", @@ -5237,7 +9253,7 @@ "source": "extensions/maidenhead-component", "status": "working", "artifact": "artifacts/extensions/maidenhead.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "to_maidenhead", "maidenhead_lat", @@ -5251,7 +9267,50 @@ "prefix": "maidenhead", "expansion": "com.tegmentum.ducklink.maidenhead", "wit_contract_version": "4.0.0", - "content_digest": "e5a6141b36895514eb951ed4127bba8c61b4fafea81072a2f302ec7ccd101b00" + "content_digest": "e5a6141b36895514eb951ed4127bba8c61b4fafea81072a2f302ec7ccd101b00", + "functions": [ + { + "name": "to_maidenhead", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "maidenhead_lat", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "maidenhead_lon", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "base45", @@ -5268,7 +9327,7 @@ "source": "extensions/base45-component", "status": "working", "artifact": "artifacts/extensions/base45.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "base45_encode", "base45_decode" @@ -5295,10 +9354,34 @@ "conformance": { "suite": "base45@4", "suite_digest": "e57aa548585622a8e25905b4c4ca03f1f27d95cda9e07ea49f2746a719b00a7b", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "base45_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "base45_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BLOB" + } ] }, { @@ -5316,7 +9399,7 @@ "source": "extensions/numfmt-component", "status": "working", "artifact": "artifacts/extensions/numfmt.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "num_group", "num_si" @@ -5329,7 +9412,35 @@ "prefix": "numfmt", "expansion": "com.tegmentum.ducklink.numfmt", "wit_contract_version": "4.0.0", - "content_digest": "aff1100fd0b85500e66ddc974b20b7124230cb6d1b3a67c302ad76b2eca25301" + "content_digest": "aff1100fd0b85500e66ddc974b20b7124230cb6d1b3a67c302ad76b2eca25301", + "functions": [ + { + "name": "num_group", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "num_si", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "mailto", @@ -5346,7 +9457,7 @@ "source": "extensions/mailto-component", "status": "working", "artifact": "artifacts/extensions/mailto.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "mailto_to", "mailto_field", @@ -5362,7 +9473,46 @@ "prefix": "mailto", "expansion": "com.tegmentum.ducklink.mailto", "wit_contract_version": "4.0.0", - "content_digest": "a2584490bf33ba5e38f3555962b6c7691cce830502f9ce7a8b3a34e91e96989f" + "content_digest": "a2584490bf33ba5e38f3555962b6c7691cce830502f9ce7a8b3a34e91e96989f", + "functions": [ + { + "name": "mailto_to", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "mailto_field", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "mailto_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "hexdump", @@ -5379,7 +9529,7 @@ "source": "extensions/hexdump-component", "status": "working", "artifact": "artifacts/extensions/hexdump.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hexdump", "hex_pretty" @@ -5392,7 +9542,31 @@ "prefix": "hexdump", "expansion": "com.tegmentum.ducklink.hexdump", "wit_contract_version": "4.0.0", - "content_digest": "7aeedcb90fb4ff3ba0fc7dfdf86d6e02d34db4bda28ce1fb6baaf1d04d0a12f4" + "content_digest": "7aeedcb90fb4ff3ba0fc7dfdf86d6e02d34db4bda28ce1fb6baaf1d04d0a12f4", + "functions": [ + { + "name": "hexdump", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hex_pretty", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "secp256k1", @@ -5409,7 +9583,7 @@ "source": "extensions/secp256k1-component", "status": "working", "artifact": "artifacts/extensions/secp256k1.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "secp256k1_pubkey", "secp256k1_sign", @@ -5425,7 +9599,54 @@ "prefix": "secp256k1", "expansion": "com.tegmentum.ducklink.secp256k1", "wit_contract_version": "4.0.0", - "content_digest": "01594daa67b476399fed79b6913770e9c7e7735f877facbe042c7fc2b5cef3ff" + "content_digest": "01594daa67b476399fed79b6913770e9c7e7735f877facbe042c7fc2b5cef3ff", + "functions": [ + { + "name": "secp256k1_pubkey", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BLOB" + }, + { + "name": "secp256k1_sign", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + }, + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BLOB" + }, + { + "name": "secp256k1_verify", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + }, + { + "name": "value", + "type": "BLOB" + }, + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "bibtex", @@ -5442,7 +9663,7 @@ "source": "extensions/bibtex-component", "status": "working", "artifact": "artifacts/extensions/bibtex.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "bibtex_count", "bibtex_to_json", @@ -5458,7 +9679,42 @@ "prefix": "bibtex", "expansion": "com.tegmentum.ducklink.bibtex", "wit_contract_version": "4.0.0", - "content_digest": "502a8330618d5164e2d1c0c493b7ffb7783cd9645d723c853763e07a53284a74" + "content_digest": "502a8330618d5164e2d1c0c493b7ffb7783cd9645d723c853763e07a53284a74", + "functions": [ + { + "name": "bibtex_count", + "kind": "scalar", + "arguments": [ + { + "name": "bib", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "bibtex_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "bib", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bibtex_keys", + "kind": "scalar", + "arguments": [ + { + "name": "bib", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "useragent", @@ -5475,7 +9731,7 @@ "source": "extensions/useragent-component", "status": "working", "artifact": "artifacts/extensions/useragent.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ua_browser", "ua_browser_version", @@ -5493,7 +9749,64 @@ "prefix": "useragent", "expansion": "com.tegmentum.ducklink.useragent", "wit_contract_version": "4.0.0", - "content_digest": "aac0093509957f896f49c89248a19f1760d6a40bef036ff0396b70ed7caad07f" + "content_digest": "aac0093509957f896f49c89248a19f1760d6a40bef036ff0396b70ed7caad07f", + "functions": [ + { + "name": "ua_browser", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ua_browser_version", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ua_os", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ua_category", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ua_is_bot", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "ical", @@ -5510,7 +9823,7 @@ "source": "extensions/ical-component", "status": "working", "artifact": "artifacts/extensions/ical.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ical_event_count", "ical_to_json", @@ -5527,7 +9840,42 @@ "prefix": "ical", "expansion": "com.tegmentum.ducklink.ical", "wit_contract_version": "4.0.0", - "content_digest": "1c1d138495d7fe6b8f8017e0f31f3f1ec670595b2ed74d956384137614fca459" + "content_digest": "1c1d138495d7fe6b8f8017e0f31f3f1ec670595b2ed74d956384137614fca459", + "functions": [ + { + "name": "ical_event_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "ical_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ical_summaries", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "tdigest", @@ -5544,7 +9892,7 @@ "source": "extensions/tdigest-component", "status": "working", "artifact": "artifacts/extensions/tdigest.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tdigest", "tdigest_quantile", @@ -5574,10 +9922,49 @@ "conformance": { "suite": "tdigest@4", "suite_digest": "e46de89c85e237d8bf8f6b787c30e70ab800968243e67f4151234e40fd23348e", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "tdigest_quantile", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "tdigest_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BLOB" + } + ], + "returns": "BIGINT" + }, + { + "name": "tdigest", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "BLOB" + } ] }, { @@ -5595,7 +9982,7 @@ "source": "extensions/mlkmeans-component", "status": "working", "artifact": "artifacts/extensions/mlkmeans.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ml_kmeans" ], @@ -5615,7 +10002,28 @@ "prefix": "mlkmeans", "expansion": "com.tegmentum.ducklink.mlkmeans", "wit_contract_version": "4.0.0", - "content_digest": "445dda3ab2b030fb6c65fd84a87c1489aa3e98cf9a0ccca37b3514b25f0094f5" + "content_digest": "445dda3ab2b030fb6c65fd84a87c1489aa3e98cf9a0ccca37b3514b25f0094f5", + "functions": [ + { + "name": "ml_kmeans", + "kind": "aggregate", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "y", + "type": "DOUBLE" + }, + { + "name": "k", + "type": "INTEGER" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "urlpattern", @@ -5632,7 +10040,7 @@ "source": "extensions/urlpattern-component", "status": "working", "artifact": "artifacts/extensions/urlpattern.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "url_pattern_test", "url_pattern_match" @@ -5647,7 +10055,39 @@ "prefix": "urlpattern", "expansion": "com.tegmentum.ducklink.urlpattern", "wit_contract_version": "4.0.0", - "content_digest": "caa293c0656f5deba72a2635ee8eddabb16438930f131bec113161e12f136474" + "content_digest": "caa293c0656f5deba72a2635ee8eddabb16438930f131bec113161e12f136474", + "functions": [ + { + "name": "url_pattern_test", + "kind": "scalar", + "arguments": [ + { + "name": "pattern", + "type": "VARCHAR" + }, + { + "name": "url", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "url_pattern_match", + "kind": "scalar", + "arguments": [ + { + "name": "pattern", + "type": "VARCHAR" + }, + { + "name": "url", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "celestial", @@ -5664,7 +10104,7 @@ "source": "extensions/celestial-component", "status": "working", "artifact": "artifacts/extensions/celestial.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "equatorial_to_galactic_l", "equatorial_to_galactic_b", @@ -5680,7 +10120,100 @@ "prefix": "celestial", "expansion": "com.tegmentum.ducklink.celestial", "wit_contract_version": "4.0.0", - "content_digest": "aa74b1773c79857705be80586fd5ca1c332005ef917efd8fa1d836b9ff4cd2c5" + "content_digest": "aa74b1773c79857705be80586fd5ca1c332005ef917efd8fa1d836b9ff4cd2c5", + "functions": [ + { + "name": "equatorial_to_galactic_l", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "equatorial_to_galactic_b", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "angular_separation", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "hms_to_deg", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "dms_to_deg", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "textlines", @@ -5697,7 +10230,7 @@ "source": "extensions/textlines-component", "status": "working", "artifact": "artifacts/extensions/textlines.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "split_lines" ], @@ -5709,7 +10242,29 @@ "prefix": "textlines", "expansion": "com.tegmentum.ducklink.textlines", "wit_contract_version": "4.0.0", - "content_digest": "480d1e9f5bfc096d4102b98fc5023df472a1413dfe3b9787c66975e55e280a17" + "content_digest": "480d1e9f5bfc096d4102b98fc5023df472a1413dfe3b9787c66975e55e280a17", + "functions": [ + { + "name": "split_lines", + "kind": "table", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "line_no", + "type": "BIGINT" + }, + { + "name": "line", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "netquack", @@ -5726,7 +10281,7 @@ "source": "extensions/netquack-component", "status": "working", "artifact": "artifacts/extensions/netquack.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "registrable_domain", "public_suffix", @@ -5743,7 +10298,53 @@ "prefix": "netquack", "expansion": "com.tegmentum.ducklink.netquack", "wit_contract_version": "4.0.0", - "content_digest": "5e339d4be300212726e832e5e9a9f0909b72854d44aa305d0b0dcb11d0f3a209" + "content_digest": "5e339d4be300212726e832e5e9a9f0909b72854d44aa305d0b0dcb11d0f3a209", + "functions": [ + { + "name": "registrable_domain", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "public_suffix", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "subdomain", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "domain_label", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "openprompt", @@ -5760,7 +10361,7 @@ "source": "extensions/openprompt-component", "status": "working", "artifact": "artifacts/extensions/openprompt.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "prompt", "prompt_model" @@ -5777,7 +10378,35 @@ "prefix": "openprompt", "expansion": "com.tegmentum.ducklink.openprompt", "wit_contract_version": "4.0.0", - "content_digest": "902771b7fd6262f4ae661a24ad62b4b9be733641fe08fe67c4ba7254ff6a1fa3" + "content_digest": "902771b7fd6262f4ae661a24ad62b4b9be733641fe08fe67c4ba7254ff6a1fa3", + "functions": [ + { + "name": "prompt", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "prompt_model", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + }, + { + "name": "model", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "dbf", @@ -5794,7 +10423,7 @@ "source": "extensions/dbf-component", "status": "working", "artifact": "artifacts/extensions/dbf.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "read_dbf" ], @@ -5808,7 +10437,33 @@ "prefix": "dbf", "expansion": "com.tegmentum.ducklink.dbf", "wit_contract_version": "4.0.0", - "content_digest": "b0d19c69a0109d96b92713895d045b203f81fa51d881ccba2c4274ece5d9e3f4" + "content_digest": "b0d19c69a0109d96b92713895d045b203f81fa51d881ccba2c4274ece5d9e3f4", + "functions": [ + { + "name": "read_dbf", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "record_no", + "type": "BIGINT" + }, + { + "name": "field", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "shapefile", @@ -5825,7 +10480,7 @@ "source": "extensions/shapefile-component", "status": "working", "artifact": "artifacts/extensions/shapefile.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "read_shp" ], @@ -5839,7 +10494,33 @@ "prefix": "shapefile", "expansion": "com.tegmentum.ducklink.shapefile", "wit_contract_version": "4.0.0", - "content_digest": "b964afa893bf39c0e3f992b1b088d3b5f645bc959f6c66e21e26a36b3bc7db5b" + "content_digest": "b964afa893bf39c0e3f992b1b088d3b5f645bc959f6c66e21e26a36b3bc7db5b", + "functions": [ + { + "name": "read_shp", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "shape_no", + "type": "BIGINT" + }, + { + "name": "shape_type", + "type": "VARCHAR" + }, + { + "name": "wkt", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "fit", @@ -5856,7 +10537,7 @@ "source": "extensions/fit-component", "status": "working", "artifact": "artifacts/extensions/fit.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "read_fit" ], @@ -5870,7 +10551,37 @@ "prefix": "fit", "expansion": "com.tegmentum.ducklink.fit", "wit_contract_version": "4.0.0", - "content_digest": "9d6f049bf088d1cf2ceef8acfecfb76582589cf771837f790aa2667f647654b6" + "content_digest": "9d6f049bf088d1cf2ceef8acfecfb76582589cf771837f790aa2667f647654b6", + "functions": [ + { + "name": "read_fit", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "record_no", + "type": "BIGINT" + }, + { + "name": "kind", + "type": "VARCHAR" + }, + { + "name": "field", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "warc", @@ -5887,7 +10598,7 @@ "source": "extensions/warc-component", "status": "working", "artifact": "artifacts/extensions/warc.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "read_warc" ], @@ -5901,7 +10612,41 @@ "prefix": "warc", "expansion": "com.tegmentum.ducklink.warc", "wit_contract_version": "4.0.0", - "content_digest": "78f4d52881c76e30bbf258a2c26f205558c763295e97c5e55085d666dbbca104" + "content_digest": "78f4d52881c76e30bbf258a2c26f205558c763295e97c5e55085d666dbbca104", + "functions": [ + { + "name": "read_warc", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "record_no", + "type": "BIGINT" + }, + { + "name": "warc_type", + "type": "VARCHAR" + }, + { + "name": "target_uri", + "type": "VARCHAR" + }, + { + "name": "content_type", + "type": "VARCHAR" + }, + { + "name": "content_length", + "type": "BIGINT" + } + ] + } + ] }, { "name": "html", @@ -5918,7 +10663,7 @@ "source": "extensions/html-component", "status": "working", "artifact": "artifacts/extensions/html.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "html_extract", "html_extract_all", @@ -5934,7 +10679,58 @@ "prefix": "html", "expansion": "com.tegmentum.ducklink.html", "wit_contract_version": "4.0.0", - "content_digest": "4d56f88567df0f548445f02a5c3dc692f19b90e423381fa6af4b6368f50fba0d" + "content_digest": "4d56f88567df0f548445f02a5c3dc692f19b90e423381fa6af4b6368f50fba0d", + "functions": [ + { + "name": "html_extract", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "html_extract_all", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "html_attr", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "vcard", @@ -5951,7 +10747,7 @@ "source": "extensions/vcard-component", "status": "working", "artifact": "artifacts/extensions/vcard.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "vcard_count", "vcard_to_json", @@ -5968,7 +10764,42 @@ "prefix": "vcard", "expansion": "com.tegmentum.ducklink.vcard", "wit_contract_version": "4.0.0", - "content_digest": "9b89c669357893840c357d0db58bef1c8cf11c248173502703f2572f5b7b094c" + "content_digest": "9b89c669357893840c357d0db58bef1c8cf11c248173502703f2572f5b7b094c", + "functions": [ + { + "name": "vcard_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "vcard_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "vcard_names", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ini", @@ -5985,7 +10816,7 @@ "source": "extensions/ini-component", "status": "working", "artifact": "artifacts/extensions/ini.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ini_to_json", "ini_get", @@ -6002,7 +10833,50 @@ "prefix": "ini", "expansion": "com.tegmentum.ducklink.ini", "wit_contract_version": "4.0.0", - "content_digest": "17fac7c7620a2ca09cdc2acda8c01f5610617b9517d2aacc05df4774dfaa807a" + "content_digest": "17fac7c7620a2ca09cdc2acda8c01f5610617b9517d2aacc05df4774dfaa807a", + "functions": [ + { + "name": "ini_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ini_get", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ini_sections", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "plist", @@ -6019,7 +10893,7 @@ "source": "extensions/plist-component", "status": "working", "artifact": "artifacts/extensions/plist.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "plist_to_json", "plist_get" @@ -6034,7 +10908,35 @@ "prefix": "plist", "expansion": "com.tegmentum.ducklink.plist", "wit_contract_version": "4.0.0", - "content_digest": "f9a4f7f12eb34cc622f4b5f12d7e9a387ac331cdfc988bf5c1250fec114fd311" + "content_digest": "f9a4f7f12eb34cc622f4b5f12d7e9a387ac331cdfc988bf5c1250fec114fd311", + "functions": [ + { + "name": "plist_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "plist_get", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "dotenv", @@ -6051,7 +10953,7 @@ "source": "extensions/dotenv-component", "status": "working", "artifact": "artifacts/extensions/dotenv.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "dotenv_to_json", "dotenv_get", @@ -6065,7 +10967,46 @@ "prefix": "dotenv", "expansion": "com.tegmentum.ducklink.dotenv", "wit_contract_version": "4.0.0", - "content_digest": "b31f5ca830e39015193b0ae090c17aa7074e62193e1beb4229310e4f505ca29c" + "content_digest": "b31f5ca830e39015193b0ae090c17aa7074e62193e1beb4229310e4f505ca29c", + "functions": [ + { + "name": "dotenv_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "dotenv_get", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "dotenv_keys", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "hocon", @@ -6082,7 +11023,7 @@ "source": "extensions/hocon-component", "status": "working", "artifact": "artifacts/extensions/hocon.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hocon_to_json", "hocon_get" @@ -6097,7 +11038,35 @@ "prefix": "hocon", "expansion": "com.tegmentum.ducklink.hocon", "wit_contract_version": "4.0.0", - "content_digest": "68e884d4b59bb700a330ffcbfb27b4dde07355a34920b32d9bd1153c0c1a35fa" + "content_digest": "68e884d4b59bb700a330ffcbfb27b4dde07355a34920b32d9bd1153c0c1a35fa", + "functions": [ + { + "name": "hocon_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "hocon_get", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "uuid7", @@ -6114,7 +11083,7 @@ "source": "extensions/uuid7-component", "status": "working", "artifact": "artifacts/extensions/uuid7.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "uuid7_build", "uuid7_timestamp", @@ -6130,7 +11099,46 @@ "prefix": "uuid7", "expansion": "com.tegmentum.ducklink.uuid7", "wit_contract_version": "4.0.0", - "content_digest": "14504d06c8669828a1adc38601ae0be19f9fcc95be30ae3524ab5efb8029a3cb" + "content_digest": "14504d06c8669828a1adc38601ae0be19f9fcc95be30ae3524ab5efb8029a3cb", + "functions": [ + { + "name": "uuid7_build", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "uuid7_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "uuid7_is_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "textdiff", @@ -6147,7 +11155,7 @@ "source": "extensions/textdiff-component", "status": "working", "artifact": "artifacts/extensions/textdiff.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "text_diff", "diff_ratio", @@ -6163,7 +11171,54 @@ "prefix": "textdiff", "expansion": "com.tegmentum.ducklink.textdiff", "wit_contract_version": "4.0.0", - "content_digest": "29f1ade586fbd5fdfa5537f5471dd707f9f313ebdf133e052867ae25a951198b" + "content_digest": "29f1ade586fbd5fdfa5537f5471dd707f9f313ebdf133e052867ae25a951198b", + "functions": [ + { + "name": "text_diff", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "diff_ratio", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "diff_changed_lines", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "polyline", @@ -6180,7 +11235,7 @@ "source": "extensions/polyline-component", "status": "working", "artifact": "artifacts/extensions/polyline.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "polyline_encode", "polyline_decode" @@ -6195,7 +11250,39 @@ "prefix": "polyline", "expansion": "com.tegmentum.ducklink.polyline", "wit_contract_version": "4.0.0", - "content_digest": "418b07617f4c42fb0ab341d96a4f1a97ee7614a174ec43a0210e7fbc23d5ae11" + "content_digest": "418b07617f4c42fb0ab341d96a4f1a97ee7614a174ec43a0210e7fbc23d5ae11", + "functions": [ + { + "name": "polyline_encode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "polyline_decode", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "json_schema", @@ -6212,7 +11299,7 @@ "source": "extensions/json_schema-component", "status": "working", "artifact": "artifacts/extensions/json_schema.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "json_schema_valid", "json_schema_errors" @@ -6227,7 +11314,39 @@ "prefix": "json_schema", "expansion": "com.tegmentum.ducklink.json_schema", "wit_contract_version": "4.0.0", - "content_digest": "cd900d8cdd8a336320ed8d20df427c5bcbe8e559b03c46d69fd968057f8ff4c6" + "content_digest": "cd900d8cdd8a336320ed8d20df427c5bcbe8e559b03c46d69fd968057f8ff4c6", + "functions": [ + { + "name": "json_schema_valid", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "json_schema_errors", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "stochastic", @@ -6244,7 +11363,7 @@ "source": "extensions/stochastic-component", "status": "working", "artifact": "artifacts/extensions/stochastic.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "normal_cdf", "normal_pdf", @@ -6264,7 +11383,134 @@ "prefix": "stochastic", "expansion": "com.tegmentum.ducklink.stochastic", "wit_contract_version": "4.0.0", - "content_digest": "9430466901d442e89f6b575e824ffa02d42bc913d7ee65aaeee08a0b2e7e6775" + "content_digest": "9430466901d442e89f6b575e824ffa02d42bc913d7ee65aaeee08a0b2e7e6775", + "functions": [ + { + "name": "normal_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "normal_pdf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "normal_quantile", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "beta_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "binomial_pmf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "poisson_pmf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "exponential_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "ion", @@ -6281,7 +11527,7 @@ "source": "extensions/ion-component", "status": "working", "artifact": "artifacts/extensions/ion.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ion_to_json", "ion_from_json", @@ -6297,7 +11543,46 @@ "prefix": "ion", "expansion": "com.tegmentum.ducklink.ion", "wit_contract_version": "4.0.0", - "content_digest": "c9f5b697cd30afec0a58bb0af2bbd9eb728c62279b16839eb77fa5df73f4b61c" + "content_digest": "c9f5b697cd30afec0a58bb0af2bbd9eb728c62279b16839eb77fa5df73f4b61c", + "functions": [ + { + "name": "ion_to_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ion_from_json", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ion_get", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "textplot", @@ -6314,7 +11599,7 @@ "source": "extensions/textplot-component", "status": "working", "artifact": "artifacts/extensions/textplot.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "plot_sparkline", "plot_bars", @@ -6330,7 +11615,46 @@ "prefix": "textplot", "expansion": "com.tegmentum.ducklink.textplot", "wit_contract_version": "4.0.0", - "content_digest": "c3ca280a03fe6df93581b1029b2df3bf4f9745c72c2bf8fabd5a289a88b01432" + "content_digest": "c3ca280a03fe6df93581b1029b2df3bf4f9745c72c2bf8fabd5a289a88b01432", + "functions": [ + { + "name": "plot_sparkline", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "plot_bars", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "qr_utf8", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "marisa", @@ -6347,7 +11671,7 @@ "source": "extensions/marisa-component", "status": "working", "artifact": "artifacts/extensions/marisa.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "fst_contains", "fst_prefix", @@ -6363,7 +11687,50 @@ "prefix": "marisa", "expansion": "com.tegmentum.ducklink.marisa", "wit_contract_version": "4.0.0", - "content_digest": "97b09f554a769828d962f523857e6c32332866b92ef52b076dd0e5187f413526" + "content_digest": "97b09f554a769828d962f523857e6c32332866b92ef52b076dd0e5187f413526", + "functions": [ + { + "name": "fst_contains", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "fst_prefix", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "fst_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "frequentitems", @@ -6380,7 +11747,7 @@ "source": "extensions/frequentitems-component", "status": "working", "artifact": "artifacts/extensions/frequentitems.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "top_k", "top_k_value" @@ -6393,7 +11760,39 @@ "prefix": "frequentitems", "expansion": "com.tegmentum.ducklink.frequentitems", "wit_contract_version": "4.0.0", - "content_digest": "2a7df199a162576535bb36e628dfb8c03fdf427bb1a53dea1d912b2d4aa15ee2" + "content_digest": "2a7df199a162576535bb36e628dfb8c03fdf427bb1a53dea1d912b2d4aa15ee2", + "functions": [ + { + "name": "top_k", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "top_k_value", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "sqlitewasm", @@ -6410,7 +11809,7 @@ "source": "extensions/sqlitewasm-component", "status": "working", "artifact": "artifacts/extensions/sqlitewasm.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sqlite_blob_scan" ], @@ -6425,7 +11824,37 @@ "prefix": "sqlitewasm", "expansion": "com.tegmentum.ducklink.sqlitewasm", "wit_contract_version": "4.0.0", - "content_digest": "2343406b43bddd815501c9e5a7705217060d8ca166e465dec9810260c70d7c38" + "content_digest": "7bee6176238ec2666df0f2df75ce977c02bccd00d54981f9869719697d591e1d", + "functions": [ + { + "name": "sqlite_blob_scan", + "kind": "table", + "arguments": [ + { + "name": "db", + "type": "VARCHAR" + }, + { + "name": "table", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "row_no", + "type": "BIGINT" + }, + { + "name": "col", + "type": "VARCHAR" + }, + { + "name": "val", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "jsonfns", @@ -6444,7 +11873,7 @@ "source": "extensions/jsonfns-component", "status": "working", "artifact": "artifacts/extensions/jsonfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "json_valid", "json_extract", @@ -6465,26 +11894,184 @@ ], "min_duckdb_version": "1.0.0", "wit_contract_version": "4.0.0", - "content_digest": "0159b0fcecb4b425042d2b10aaaa390cf296c0827e1a9e0194422daf66571402" - }, - { - "name": "inetfns", - "prefix": "inetfns", - "expansion": "com.tegmentum.ducklink.inet", - "version": "0.1.0", - "description": "Official `inet` extension functions as a loadable component (ipnetwork + std::net): host/family/netmask/network/broadcast/inet_contains. Replaces embedded inet on the lean core.", - "license": "MIT", - "authors": [ - "Tegmentum" - ], - "repository": "https://github.com/tegmentum/ducklink", + "content_digest": "0159b0fcecb4b425042d2b10aaaa390cf296c0827e1a9e0194422daf66571402", + "functions": [ + { + "name": "json_valid", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "json_extract", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_extract_string", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_array_length", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "json_array_length", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "json_type", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_type", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_keys", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_keys", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "json_contains", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + }, + { + "name": "needle", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "json_quote", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_json", + "kind": "scalar", + "arguments": [ + { + "name": "json", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] + }, + { + "name": "inetfns", + "prefix": "inetfns", + "expansion": "com.tegmentum.ducklink.inet", + "version": "0.1.0", + "description": "Official `inet` extension functions as a loadable component (ipnetwork + std::net): host/family/netmask/network/broadcast/inet_contains. Replaces embedded inet on the lean core.", + "license": "MIT", + "authors": [ + "Tegmentum" + ], + "repository": "https://github.com/tegmentum/ducklink", "categories": [ "networking" ], "source": "extensions/inetfns-component", "status": "working", "artifact": "artifacts/extensions/inetfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "host", "family", @@ -6501,7 +12088,79 @@ ], "min_duckdb_version": "1.0.0", "wit_contract_version": "4.0.0", - "content_digest": "fb28a8a372b5ecc8d438bf3278309d5a1902aee8973c7f30738613a428b861d2" + "content_digest": "fb28a8a372b5ecc8d438bf3278309d5a1902aee8973c7f30738613a428b861d2", + "functions": [ + { + "name": "host", + "kind": "scalar", + "arguments": [ + { + "name": "inet", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "family", + "kind": "scalar", + "arguments": [ + { + "name": "inet", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "netmask", + "kind": "scalar", + "arguments": [ + { + "name": "inet", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "network", + "kind": "scalar", + "arguments": [ + { + "name": "inet", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "broadcast", + "kind": "scalar", + "arguments": [ + { + "name": "inet", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "inet_contains", + "kind": "scalar", + "arguments": [ + { + "name": "network", + "type": "VARCHAR" + }, + { + "name": "ip", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "excelfns", @@ -6518,7 +12177,7 @@ "source": "extensions/excelfns-component", "status": "working", "artifact": "artifacts/extensions/excelfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "xlsx_sheets", "read_xlsx", @@ -6534,7 +12193,77 @@ "prefix": "excelfns", "expansion": "com.tegmentum.ducklink.excelfns", "wit_contract_version": "4.0.0", - "content_digest": "381db22df235a613af0c4a4196f8b692e83b68d19bb7f2149f05ee989074afdd" + "content_digest": "381db22df235a613af0c4a4196f8b692e83b68d19bb7f2149f05ee989074afdd", + "functions": [ + { + "name": "xlsx_sheets", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "sheet", + "type": "VARCHAR" + } + ] + }, + { + "name": "read_xlsx", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "sheet", + "type": "VARCHAR" + }, + { + "name": "row_no", + "type": "BIGINT" + }, + { + "name": "col", + "type": "VARCHAR" + }, + { + "name": "val", + "type": "VARCHAR" + } + ] + }, + { + "name": "xlsx_cell", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + }, + { + "name": "sheet", + "type": "VARCHAR" + }, + { + "name": "cell", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "val", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "avrofns", @@ -6551,7 +12280,7 @@ "source": "extensions/avrofns-component", "status": "working", "artifact": "artifacts/extensions/avrofns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "avro_schema", "read_avro", @@ -6568,7 +12297,64 @@ "prefix": "avrofns", "expansion": "com.tegmentum.ducklink.avrofns", "wit_contract_version": "4.0.0", - "content_digest": "9c991c331d0ac8d4621caf35e8f3c3280386c6ec62ab4ec8333340af5683f8d0" + "content_digest": "9c991c331d0ac8d4621caf35e8f3c3280386c6ec62ab4ec8333340af5683f8d0", + "functions": [ + { + "name": "avro_record_count", + "kind": "scalar", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "returns": "BIGINT" + }, + { + "name": "avro_schema", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "field", + "type": "VARCHAR" + }, + { + "name": "type", + "type": "VARCHAR" + } + ] + }, + { + "name": "read_avro", + "kind": "table", + "arguments": [ + { + "name": "data", + "type": "BLOB" + } + ], + "columns": [ + { + "name": "row_no", + "type": "BIGINT" + }, + { + "name": "col", + "type": "VARCHAR" + }, + { + "name": "val", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "spatialfns", @@ -6587,7 +12373,7 @@ "source": "extensions/spatialfns-component", "status": "working", "artifact": "artifacts/extensions/spatialfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ST_Point", "ST_GeomFromText", @@ -6614,7 +12400,183 @@ ], "min_duckdb_version": "1.0.0", "wit_contract_version": "4.0.0", - "content_digest": "b2da9bd6abc3df807c5fea7680513398d9cddf6d6c17ba6b9de7b207c4bebdae" + "content_digest": "b2da9bd6abc3df807c5fea7680513398d9cddf6d6c17ba6b9de7b207c4bebdae", + "functions": [ + { + "name": "ST_Point", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "y", + "type": "DOUBLE" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ST_GeomFromText", + "kind": "scalar", + "arguments": [ + { + "name": "wkt", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ST_AsText", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ST_X", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ST_Y", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ST_Distance", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ST_Area", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ST_Length", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ST_Centroid", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ST_Contains", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "ST_Within", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "ST_Intersects", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + }, + { + "name": "ST_Envelope", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ST_AsGeoJSON", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ftsfns", @@ -6631,7 +12593,7 @@ "source": "extensions/ftsfns-component", "status": "working", "artifact": "artifacts/extensions/ftsfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "fts_tokenize", "fts_stem", @@ -6649,7 +12611,88 @@ "prefix": "ftsfns", "expansion": "com.tegmentum.ducklink.ftsfns", "wit_contract_version": "4.0.0", - "content_digest": "edca625b1ca897f74f3ac3cb1cdb7c9538aa8c93aa09a3661a08e05d2c64d10b" + "content_digest": "edca625b1ca897f74f3ac3cb1cdb7c9538aa8c93aa09a3661a08e05d2c64d10b", + "functions": [ + { + "name": "fts_tokenize", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "fts_stem", + "kind": "scalar", + "arguments": [ + { + "name": "word", + "type": "VARCHAR" + }, + { + "name": "language", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "fts_stem_text", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "bm25_score", + "kind": "scalar", + "arguments": [ + { + "name": "tf", + "type": "BIGINT" + }, + { + "name": "df", + "type": "BIGINT" + }, + { + "name": "doc_len", + "type": "DOUBLE" + }, + { + "name": "avg_doc_len", + "type": "DOUBLE" + }, + { + "name": "num_docs", + "type": "BIGINT" + } + ], + "returns": "DOUBLE" + }, + { + "name": "fts_match", + "kind": "scalar", + "arguments": [ + { + "name": "doc", + "type": "VARCHAR" + }, + { + "name": "query", + "type": "VARCHAR" + } + ], + "returns": "BOOLEAN" + } + ] }, { "name": "icufns", @@ -6666,7 +12709,7 @@ "source": "extensions/icufns-component", "status": "working", "artifact": "artifacts/extensions/icufns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "icu_sort_key", "icu_compare", @@ -6682,7 +12725,87 @@ "prefix": "icufns", "expansion": "com.tegmentum.ducklink.icufns", "wit_contract_version": "4.0.0", - "content_digest": "c3b2a4b67c1f5d0e24ece51698eb43badff981e844db7cdb9c3c349c493b38b1" + "content_digest": "c3b2a4b67c1f5d0e24ece51698eb43badff981e844db7cdb9c3c349c493b38b1", + "functions": [ + { + "name": "icu_sort_key", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + }, + { + "name": "locale", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "icu_compare", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "locale", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "icu_casefold", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "icu_sortkey_en", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "icu_sortkey_sv", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "icu_sortkey_de", + "kind": "scalar", + "arguments": [ + { + "name": "text", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "vssfns", @@ -6699,7 +12822,7 @@ "source": "extensions/vssfns-component", "status": "working", "artifact": "artifacts/extensions/vssfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "vec_l1_distance", "vec_linf_distance", @@ -6713,7 +12836,50 @@ "prefix": "vssfns", "expansion": "com.tegmentum.ducklink.vssfns", "wit_contract_version": "4.0.0", - "content_digest": "4e7d9f12249e764ca05f028001c896cb9e766b3dffa60d2dbe5947802edf139a" + "content_digest": "4e7d9f12249e764ca05f028001c896cb9e766b3dffa60d2dbe5947802edf139a", + "functions": [ + { + "name": "vec_l1_distance", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "vec_linf_distance", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "vec_normalize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "rtreefns", @@ -6730,7 +12896,7 @@ "source": "extensions/rtreefns-component", "status": "working", "artifact": "artifacts/extensions/rtreefns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "rtree_search", "bbox4" @@ -6747,7 +12913,44 @@ "prefix": "rtreefns", "expansion": "com.tegmentum.ducklink.rtreefns", "wit_contract_version": "4.0.0", - "content_digest": "755683a81d477a245dcbc71fe9bade057bf0bb8ef3bc319c6fe16124b7f3fa54" + "content_digest": "755683a81d477a245dcbc71fe9bade057bf0bb8ef3bc319c6fe16124b7f3fa54", + "functions": [ + { + "name": "bbox4", + "kind": "scalar", + "arguments": [ + { + "name": "wkt", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "rtree_search", + "kind": "table", + "arguments": [ + { + "name": "index_name", + "type": "VARCHAR" + }, + { + "name": "bbox", + "type": "VARCHAR" + }, + { + "name": "limit", + "type": "BIGINT" + } + ], + "columns": [ + { + "name": "rowid", + "type": "BIGINT" + } + ] + } + ] }, { "name": "hnswfns", @@ -6764,7 +12967,7 @@ "source": "extensions/hnswfns-component", "status": "working", "artifact": "artifacts/extensions/hnswfns.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "hnsw_search" ], @@ -6779,7 +12982,37 @@ "prefix": "hnswfns", "expansion": "com.tegmentum.ducklink.hnswfns", "wit_contract_version": "4.0.0", - "content_digest": "f3dc9e67ff48809b67e4a491cd9a3334ef4b6300b2562d08f288a911a4677139" + "content_digest": "f3dc9e67ff48809b67e4a491cd9a3334ef4b6300b2562d08f288a911a4677139", + "functions": [ + { + "name": "hnsw_search", + "kind": "table", + "arguments": [ + { + "name": "index_name", + "type": "VARCHAR" + }, + { + "name": "query", + "type": "VARCHAR" + }, + { + "name": "k", + "type": "BIGINT" + } + ], + "columns": [ + { + "name": "rowid", + "type": "BIGINT" + }, + { + "name": "distance", + "type": "FLOAT" + } + ] + } + ] }, { "name": "geomtype", @@ -6796,7 +13029,7 @@ "source": "extensions/geomtype-component", "status": "working", "artifact": "artifacts/extensions/geomtype.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "geom_area", "geom_astext" @@ -6813,7 +13046,31 @@ "prefix": "geomtype", "expansion": "com.tegmentum.ducklink.geomtype", "wit_contract_version": "4.0.0", - "content_digest": "3e5d49a8cffa73c38067ea2852000eb9f3deecd8d4e27cc471ea1dde481705ef" + "content_digest": "3e5d49a8cffa73c38067ea2852000eb9f3deecd8d4e27cc471ea1dde481705ef", + "functions": [ + { + "name": "geom_area", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "BLOB" + } + ], + "returns": "DOUBLE" + }, + { + "name": "geom_astext", + "kind": "scalar", + "arguments": [ + { + "name": "geom", + "type": "BLOB" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "spatialproj", @@ -6830,7 +13087,7 @@ "source": "extensions/spatialproj-component", "status": "working", "artifact": "artifacts/extensions/spatialproj.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "ST_Transform" ], @@ -6849,7 +13106,28 @@ "prefix": "spatialproj", "expansion": "com.tegmentum.ducklink.spatialproj", "wit_contract_version": "4.0.0", - "content_digest": "249eeb88ee79d7fb2c123acec9b98ecb2544f326246bf493dfb529c3d49799a2" + "content_digest": "249eeb88ee79d7fb2c123acec9b98ecb2544f326246bf493dfb529c3d49799a2", + "functions": [ + { + "name": "ST_Transform", + "kind": "scalar", + "arguments": [ + { + "name": "geom_wkt", + "type": "VARCHAR" + }, + { + "name": "from_srid", + "type": "INTEGER" + }, + { + "name": "to_srid", + "type": "INTEGER" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "tpchgen", @@ -6866,7 +13144,7 @@ "source": "extensions/tpchgen-component", "status": "working", "artifact": "artifacts/extensions/tpchgen.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tpch_region", "tpch_nation", @@ -6889,7 +13167,350 @@ "prefix": "tpchgen", "expansion": "com.tegmentum.ducklink.tpchgen", "wit_contract_version": "4.0.0", - "content_digest": "48361ffb0e41097be21d86bb17d88788f1a3b18f99d534c718577d2ce3ff09f3" + "content_digest": "48361ffb0e41097be21d86bb17d88788f1a3b18f99d534c718577d2ce3ff09f3", + "functions": [ + { + "name": "tpch_query", + "kind": "scalar", + "arguments": [ + { + "name": "n", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "tpch_region", + "kind": "table", + "arguments": [], + "columns": [ + { + "name": "r_regionkey", + "type": "BIGINT" + }, + { + "name": "r_name", + "type": "VARCHAR" + }, + { + "name": "r_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_nation", + "kind": "table", + "arguments": [], + "columns": [ + { + "name": "n_nationkey", + "type": "BIGINT" + }, + { + "name": "n_name", + "type": "VARCHAR" + }, + { + "name": "n_regionkey", + "type": "BIGINT" + }, + { + "name": "n_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_supplier", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "s_suppkey", + "type": "BIGINT" + }, + { + "name": "s_name", + "type": "VARCHAR" + }, + { + "name": "s_address", + "type": "VARCHAR" + }, + { + "name": "s_nationkey", + "type": "BIGINT" + }, + { + "name": "s_phone", + "type": "VARCHAR" + }, + { + "name": "s_acctbal", + "type": "DOUBLE" + }, + { + "name": "s_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_customer", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "c_custkey", + "type": "BIGINT" + }, + { + "name": "c_name", + "type": "VARCHAR" + }, + { + "name": "c_address", + "type": "VARCHAR" + }, + { + "name": "c_nationkey", + "type": "BIGINT" + }, + { + "name": "c_phone", + "type": "VARCHAR" + }, + { + "name": "c_acctbal", + "type": "DOUBLE" + }, + { + "name": "c_mktsegment", + "type": "VARCHAR" + }, + { + "name": "c_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_part", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "p_partkey", + "type": "BIGINT" + }, + { + "name": "p_name", + "type": "VARCHAR" + }, + { + "name": "p_mfgr", + "type": "VARCHAR" + }, + { + "name": "p_brand", + "type": "VARCHAR" + }, + { + "name": "p_type", + "type": "VARCHAR" + }, + { + "name": "p_size", + "type": "BIGINT" + }, + { + "name": "p_container", + "type": "VARCHAR" + }, + { + "name": "p_retailprice", + "type": "DOUBLE" + }, + { + "name": "p_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_partsupp", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "ps_partkey", + "type": "BIGINT" + }, + { + "name": "ps_suppkey", + "type": "BIGINT" + }, + { + "name": "ps_availqty", + "type": "BIGINT" + }, + { + "name": "ps_supplycost", + "type": "DOUBLE" + }, + { + "name": "ps_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_orders", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "o_orderkey", + "type": "BIGINT" + }, + { + "name": "o_custkey", + "type": "BIGINT" + }, + { + "name": "o_orderstatus", + "type": "VARCHAR" + }, + { + "name": "o_totalprice", + "type": "DOUBLE" + }, + { + "name": "o_orderdate", + "type": "VARCHAR" + }, + { + "name": "o_orderpriority", + "type": "VARCHAR" + }, + { + "name": "o_clerk", + "type": "VARCHAR" + }, + { + "name": "o_shippriority", + "type": "BIGINT" + }, + { + "name": "o_comment", + "type": "VARCHAR" + } + ] + }, + { + "name": "tpch_lineitem", + "kind": "table", + "arguments": [ + { + "name": "sf", + "type": "DOUBLE" + } + ], + "columns": [ + { + "name": "l_orderkey", + "type": "BIGINT" + }, + { + "name": "l_partkey", + "type": "BIGINT" + }, + { + "name": "l_suppkey", + "type": "BIGINT" + }, + { + "name": "l_linenumber", + "type": "BIGINT" + }, + { + "name": "l_quantity", + "type": "BIGINT" + }, + { + "name": "l_extendedprice", + "type": "DOUBLE" + }, + { + "name": "l_discount", + "type": "DOUBLE" + }, + { + "name": "l_tax", + "type": "DOUBLE" + }, + { + "name": "l_returnflag", + "type": "VARCHAR" + }, + { + "name": "l_linestatus", + "type": "VARCHAR" + }, + { + "name": "l_shipdate", + "type": "VARCHAR" + }, + { + "name": "l_commitdate", + "type": "VARCHAR" + }, + { + "name": "l_receiptdate", + "type": "VARCHAR" + }, + { + "name": "l_shipinstruct", + "type": "VARCHAR" + }, + { + "name": "l_shipmode", + "type": "VARCHAR" + }, + { + "name": "l_comment", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "tpcdsgen", @@ -6906,7 +13527,7 @@ "source": "extensions/tpcdsgen-component", "status": "working", "artifact": "artifacts/extensions/tpcdsgen.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "tpcds_income_band", "tpcds_date_dim_sample" @@ -6919,7 +13540,55 @@ "prefix": "tpcdsgen", "expansion": "com.tegmentum.ducklink.tpcdsgen", "wit_contract_version": "4.0.0", - "content_digest": "81dc4e59a3ff69a4be80471f4f75fd1e4b04956f3e16def35062e937d6dfa731" + "content_digest": "81dc4e59a3ff69a4be80471f4f75fd1e4b04956f3e16def35062e937d6dfa731", + "functions": [ + { + "name": "tpcds_income_band", + "kind": "table", + "arguments": [], + "columns": [ + { + "name": "ib_income_band_sk", + "type": "BIGINT" + }, + { + "name": "ib_lower_bound", + "type": "BIGINT" + }, + { + "name": "ib_upper_bound", + "type": "BIGINT" + } + ] + }, + { + "name": "tpcds_date_dim_sample", + "kind": "table", + "arguments": [], + "columns": [ + { + "name": "d_date_sk", + "type": "BIGINT" + }, + { + "name": "d_date", + "type": "VARCHAR" + }, + { + "name": "d_year", + "type": "BIGINT" + }, + { + "name": "d_moy", + "type": "BIGINT" + }, + { + "name": "d_dom", + "type": "BIGINT" + } + ] + } + ] }, { "name": "deltascan", @@ -6936,7 +13605,7 @@ "source": "extensions/deltascan-component", "status": "working", "artifact": "artifacts/extensions/deltascan.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "delta_log_info", "delta_schema" @@ -6951,7 +13620,57 @@ "prefix": "deltascan", "expansion": "com.tegmentum.ducklink.deltascan", "wit_contract_version": "4.0.0", - "content_digest": "debeada3f1214f467bb6055b19dfd60035f9420a4172cb4b9dba46735e23b9d6" + "content_digest": "debeada3f1214f467bb6055b19dfd60035f9420a4172cb4b9dba46735e23b9d6", + "functions": [ + { + "name": "delta_log_info", + "kind": "table", + "arguments": [ + { + "name": "log_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "version", + "type": "BIGINT" + }, + { + "name": "action", + "type": "VARCHAR" + }, + { + "name": "path", + "type": "VARCHAR" + }, + { + "name": "size", + "type": "BIGINT" + } + ] + }, + { + "name": "delta_schema", + "kind": "table", + "arguments": [ + { + "name": "log_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "column_name", + "type": "VARCHAR" + }, + { + "name": "column_type", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "icebergscan", @@ -6968,7 +13687,7 @@ "source": "extensions/icebergscan-component", "status": "working", "artifact": "artifacts/extensions/icebergscan.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "iceberg_metadata", "iceberg_schema", @@ -6984,7 +13703,85 @@ "prefix": "icebergscan", "expansion": "com.tegmentum.ducklink.icebergscan", "wit_contract_version": "4.0.0", - "content_digest": "66d36995361ebfe1759580ff40654f9ad71256c3fdb4b62e49dd95ccff836c54" + "content_digest": "66d36995361ebfe1759580ff40654f9ad71256c3fdb4b62e49dd95ccff836c54", + "functions": [ + { + "name": "iceberg_metadata", + "kind": "table", + "arguments": [ + { + "name": "metadata_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "key", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ] + }, + { + "name": "iceberg_schema", + "kind": "table", + "arguments": [ + { + "name": "metadata_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "field_id", + "type": "BIGINT" + }, + { + "name": "name", + "type": "VARCHAR" + }, + { + "name": "type", + "type": "VARCHAR" + }, + { + "name": "required", + "type": "BOOLEAN" + } + ] + }, + { + "name": "iceberg_snapshots", + "kind": "table", + "arguments": [ + { + "name": "metadata_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "snapshot_id", + "type": "BIGINT" + }, + { + "name": "sequence_number", + "type": "BIGINT" + }, + { + "name": "timestamp_ms", + "type": "BIGINT" + }, + { + "name": "manifest_list", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "autocomplete", @@ -7001,7 +13798,7 @@ "source": "extensions/autocomplete-component", "status": "working", "artifact": "artifacts/extensions/autocomplete.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sql_complete" ], @@ -7014,7 +13811,29 @@ "prefix": "autocomplete", "expansion": "com.tegmentum.ducklink.autocomplete", "wit_contract_version": "4.0.0", - "content_digest": "3f8b490994d38d8f04a2dfe527b081ba188bcb8f365fd8804883d9a565e7da84" + "content_digest": "3f8b490994d38d8f04a2dfe527b081ba188bcb8f365fd8804883d9a565e7da84", + "functions": [ + { + "name": "sql_complete", + "kind": "table", + "arguments": [ + { + "name": "partial", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "suggestion", + "type": "VARCHAR" + }, + { + "name": "kind", + "type": "VARCHAR" + } + ] + } + ] }, { "name": "statsduck", @@ -7031,7 +13850,7 @@ "source": "extensions/statsduck-component", "status": "working", "artifact": "artifacts/extensions/statsduck.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "adjust_p", "anderson_darling", @@ -7076,7 +13895,615 @@ "prefix": "statsduck", "expansion": "com.tegmentum.ducklink.stats", "wit_contract_version": "4.0.0", - "content_digest": "a1ce3f407070dd39e2bdb57243a281f25c09ebdaab881d1bcd11dce4c80c0498" + "content_digest": "a1ce3f407070dd39e2bdb57243a281f25c09ebdaab881d1bcd11dce4c80c0498", + "functions": [ + { + "name": "ttest_1samp", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + }, + { + "name": "mu", + "type": "DOUBLE" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ttest_2samp", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "equal_var", + "type": "BOOLEAN" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ttest_paired", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "mann_whitney_u", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + }, + { + "name": "continuity", + "type": "BOOLEAN" + } + ], + "returns": "VARCHAR" + }, + { + "name": "wilcoxon_signed_rank", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + }, + { + "name": "continuity", + "type": "BOOLEAN" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sign_test_1samp", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + }, + { + "name": "mu", + "type": "DOUBLE" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "sign_test_paired", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "pearson_test", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "VARCHAR" + }, + { + "name": "y", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "spearman_test", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "VARCHAR" + }, + { + "name": "y", + "type": "VARCHAR" + }, + { + "name": "alternative", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "anova_oneway", + "kind": "scalar", + "arguments": [ + { + "name": "groups", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "chisq_goodness_of_fit", + "kind": "scalar", + "arguments": [ + { + "name": "observed", + "type": "VARCHAR" + }, + { + "name": "expected", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "chisq_independence", + "kind": "scalar", + "arguments": [ + { + "name": "table", + "type": "VARCHAR" + }, + { + "name": "continuity", + "type": "BOOLEAN" + } + ], + "returns": "VARCHAR" + }, + { + "name": "jarque_bera", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ks_test_2samp", + "kind": "scalar", + "arguments": [ + { + "name": "a", + "type": "VARCHAR" + }, + { + "name": "b", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "adjust_p", + "kind": "scalar", + "arguments": [ + { + "name": "pvals", + "type": "VARCHAR" + }, + { + "name": "method", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "t_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "df", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "chisq_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "df", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "f_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "df1", + "type": "DOUBLE" + }, + { + "name": "df2", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "gamma_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "shape", + "type": "DOUBLE" + }, + { + "name": "rate", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "weibull_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "shape", + "type": "DOUBLE" + }, + { + "name": "scale", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "lognormal_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "DOUBLE" + }, + { + "name": "meanlog", + "type": "DOUBLE" + }, + { + "name": "sdlog", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "shapiro_wilk", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "anderson_darling", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "ks_test_1samp", + "kind": "scalar", + "arguments": [ + { + "name": "sample", + "type": "VARCHAR" + }, + { + "name": "dist", + "type": "VARCHAR" + }, + { + "name": "params", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "kendall_test", + "kind": "scalar", + "arguments": [ + { + "name": "x", + "type": "VARCHAR" + }, + { + "name": "y", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "poibin_cdf", + "kind": "scalar", + "arguments": [ + { + "name": "probs", + "type": "VARCHAR" + }, + { + "name": "k", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "lm", + "kind": "table", + "arguments": [ + { + "name": "data_json", + "type": "VARCHAR" + }, + { + "name": "formula_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "term", + "type": "VARCHAR" + }, + { + "name": "estimate", + "type": "DOUBLE" + }, + { + "name": "std_error", + "type": "DOUBLE" + }, + { + "name": "t_value", + "type": "DOUBLE" + }, + { + "name": "p_value", + "type": "DOUBLE" + } + ] + }, + { + "name": "lm_summary", + "kind": "table", + "arguments": [ + { + "name": "data_json", + "type": "VARCHAR" + }, + { + "name": "formula_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "metric", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "DOUBLE" + } + ] + }, + { + "name": "corr_matrix", + "kind": "table", + "arguments": [ + { + "name": "data_json", + "type": "VARCHAR" + }, + { + "name": "method", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "var1", + "type": "VARCHAR" + }, + { + "name": "var2", + "type": "VARCHAR" + }, + { + "name": "correlation", + "type": "DOUBLE" + } + ] + }, + { + "name": "table_one", + "kind": "table", + "arguments": [ + { + "name": "data_json", + "type": "VARCHAR" + } + ], + "columns": [ + { + "name": "variable", + "type": "VARCHAR" + }, + { + "name": "n", + "type": "BIGINT" + }, + { + "name": "mean", + "type": "DOUBLE" + }, + { + "name": "sd", + "type": "DOUBLE" + }, + { + "name": "median", + "type": "DOUBLE" + }, + { + "name": "min", + "type": "DOUBLE" + }, + { + "name": "max", + "type": "DOUBLE" + } + ] + }, + { + "name": "bin_edges", + "kind": "table", + "arguments": [ + { + "name": "sample_json", + "type": "VARCHAR" + }, + { + "name": "method", + "type": "VARCHAR" + }, + { + "name": "bins", + "type": "INTEGER" + } + ], + "columns": [ + { + "name": "bin", + "type": "INTEGER" + }, + { + "name": "lower", + "type": "DOUBLE" + }, + { + "name": "upper", + "type": "DOUBLE" + }, + { + "name": "count", + "type": "BIGINT" + } + ] + } + ] }, { "name": "math", @@ -7100,7 +14527,7 @@ "source": "extensions/math-component", "status": "working", "artifact": "artifacts/extensions/math.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "exp2", "e", @@ -7128,6 +14555,72 @@ "artifact": "artifacts/extensions/math.wasm", "content_digest": "143b4cce0ffabe1f3a3fb834072d560ee6cf8b5f2b185eeae8fe6672377648dd" } + ], + "functions": [ + { + "name": "exp2", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "e", + "kind": "scalar", + "arguments": [], + "returns": "DOUBLE" + }, + { + "name": "rand", + "kind": "scalar", + "arguments": [], + "returns": "DOUBLE" + }, + { + "name": "div", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "truncate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "truncate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } ] }, { @@ -7152,7 +14645,7 @@ "source": "extensions/text_utils-component", "status": "working", "artifact": "artifacts/extensions/text_utils.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "exports": [ "sql_normalize", "insert", @@ -7176,6 +14669,76 @@ "artifact": "artifacts/extensions/text_utils.wasm", "content_digest": "4fe95fb99110150ec3df93faa1eded6939bd5673007368f27ad403b75cf76c62" } + ], + "functions": [ + { + "name": "sql_normalize", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "insert", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "locate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "locate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } ] }, { @@ -7258,9 +14821,669 @@ "min_duckdb_version": "1.0.0", "prefix": "chrono", "expansion": "com.tegmentum.ducklink.chrono", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", - "content_digest": "0cfe3da4634b8073c0a79e256b035eeb88ffa2136c340535ce79878fe009de59" + "content_digest": "0cfe3da4634b8073c0a79e256b035eeb88ffa2136c340535ce79878fe009de59", + "functions": [ + { + "name": "date_parse", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_parse", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_format", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_tz_convert", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_now_tz", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_is_business_day", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "date_business_days_between", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "date_iso_week", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "date_iso_year", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "duration_parse", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "duration_format", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "duration_format", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "chrono_version", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "from_unixtime", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestampdiff", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "timestampadd", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "adddate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "subdate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "makedate", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "maketime", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_char", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "str_to_date", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "from_days", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "utc_timestamp", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "sysdate", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "timestamp_add", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestamp_sub", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestamp_diff", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "timestamp_trunc", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestamp_micros", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestamp_millis", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "timestamp_seconds", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "datetime_add", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "datetime_sub", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "datetime_diff", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "datetime_trunc", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "parse_date", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "parse_datetime", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "parse_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "format_date", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "format_datetime", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "format_timestamp", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "unix_micros", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "unix_millis", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "unix_seconds", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "date_from_unix_date", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "date_bucket", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "list", @@ -7310,9 +15533,196 @@ "min_duckdb_version": "1.0.0", "prefix": "list", "expansion": "com.tegmentum.ducklink.list", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", - "content_digest": "1f67507d83a385771f4b2b80abf525ab3d4fb5170f07763522f6a5659807c7e5" + "content_digest": "1f67507d83a385771f4b2b80abf525ab3d4fb5170f07763522f6a5659807c7e5", + "functions": [ + { + "name": "array_remove", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "list_length", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "array_min", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "array_max", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "array_sum", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "array_product", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "array_avg", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "DOUBLE" + }, + { + "name": "array_count", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "array_dims", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "array_lower", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "array_upper", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "array_ndims", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "array_positions", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "array_replace", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "arrays_overlap", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "stdsql", @@ -7365,9 +15775,263 @@ "min_duckdb_version": "1.0.0", "prefix": "stdsql", "expansion": "com.tegmentum.ducklink.stdsql", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", - "content_digest": "61a8cef5d5e3972532e0bcd3702f4fcf3d25b3abc18a680ce896ac929424fad2" + "content_digest": "61a8cef5d5e3972532e0bcd3702f4fcf3d25b3abc18a680ce896ac929424fad2", + "functions": [ + { + "name": "space", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "initcap", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "startsWith", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "endsWith", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "lengthUTF8", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "lowerUTF8", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "upperUTF8", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "toString", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "empty", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "notEmpty", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "replaceAll", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "positionUTF8", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + }, + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "BIGINT" + }, + { + "name": "to_bin", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_oct", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "VARCHAR" + }, + { + "name": "to_ascii", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "quote_ident", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "quote_literal", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "quote_nullable", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + }, + { + "name": "get_byte", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + }, + { + "name": "set_byte", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + }, + { + "name": "value", + "type": "BIGINT" + } + ], + "returns": "BIGINT" + } + ] }, { "name": "stats", @@ -7402,9 +16066,56 @@ "min_duckdb_version": "1.0.0", "prefix": "stats", "expansion": "com.tegmentum.ducklink.stats", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", - "content_digest": "03a4a4f6a8f59ac25f839d6986ddad5d33f24b6768f5fd2b804ae2993b3ab61e" + "content_digest": "03a4a4f6a8f59ac25f839d6986ddad5d33f24b6768f5fd2b804ae2993b3ab61e", + "functions": [ + { + "name": "percentile", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "percentile_cont", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "percentile_disc", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + }, + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } + ] }, { "name": "sys_compat", @@ -7440,9 +16151,40 @@ "min_duckdb_version": "1.0.0", "prefix": "sys_compat", "expansion": "com.tegmentum.ducklink.sys_compat", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", - "content_digest": "f3ea0982b0384b55362c380569bebc76a9c3a930e4f03001d5df356f7dbdae2e" + "content_digest": "f3ea0982b0384b55362c380569bebc76a9c3a930e4f03001d5df356f7dbdae2e", + "functions": [ + { + "name": "system_user", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "database", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "schema", + "kind": "scalar", + "arguments": [], + "returns": "VARCHAR" + }, + { + "name": "collation", + "kind": "scalar", + "arguments": [ + { + "name": "value", + "type": "VARCHAR" + } + ], + "returns": "VARCHAR" + } + ] }, { "name": "ggsql", @@ -7470,7 +16212,7 @@ "prefix": "ggsql", "expansion": "com.tegmentum.ducklink.ggsql", "artifact": "artifacts/extensions/ggsql.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", "content_digest": "90f8624ec31724fb9cc07475883dd57080817e64cbbf887dd2cbcf5eb2db861b", "providers": [ @@ -7484,11 +16226,12 @@ "conformance": { "suite": "ggsql@4", "suite_digest": "48ff6b2da8a744ab45ceae52faca754c7f854d65ec41f90965a859d21b5ca256", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } - ] + ], + "functions": [] }, { "name": "dplyr", @@ -7516,7 +16259,7 @@ "prefix": "dplyr", "expansion": "com.tegmentum.ducklink.dplyr", "artifact": "artifacts/extensions/dplyr.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", "content_digest": "1c0d3807e17815c07d31427bc035333b9b3bf383b8af53132b8553ca4fbc28ef", "providers": [ @@ -7530,11 +16273,12 @@ "conformance": { "suite": "dplyr@4", "suite_digest": "73c189bc18a13ad0eec6df00e3f872984b253d652cfa27e218d93f26578cce58", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } - ] + ], + "functions": [] }, { "name": "prql_parser", @@ -7564,7 +16308,7 @@ "prefix": "prql_parser", "expansion": "com.tegmentum.ducklink.prql_parser", "artifact": "artifacts/extensions/prql_parser.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", "content_digest": "181761c2db814b3fd895c9a4bcfeb98c50d0d3191d7bdb563485848104b95525", "providers": [ @@ -7578,11 +16322,12 @@ "conformance": { "suite": "prql_parser@4", "suite_digest": "6719bade3ff2cd734b77e63cbf2a57b88c7f586d76418eed00462f6148b4f235", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } - ] + ], + "functions": [] }, { "name": "talib", @@ -7613,7 +16358,7 @@ "prefix": "talib", "expansion": "com.tegmentum.ducklink.talib", "artifact": "artifacts/extensions/talib.wasm", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", "content_digest": "a0cc83241eb83f5304c61f63d1bbddef5f6e9c2d2aadfda1d8bcaa552d8446ee", "providers": [ @@ -7627,10 +16372,45 @@ "conformance": { "suite": "talib@4", "suite_digest": "c6c03904e744ec9bd6a98f510f8555077dc9ccb95c294ed9416ac9571db36990", - "at": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "at": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "passed": true } } + ], + "functions": [ + { + "name": "sma", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "ema", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + }, + { + "name": "rsi", + "kind": "aggregate", + "arguments": [ + { + "name": "value", + "type": "DOUBLE" + } + ], + "returns": "DOUBLE" + } ] } ], diff --git a/tooling/propagate-wit.py b/tooling/propagate-wit.py index d54acab9..a439a964 100644 --- a/tooling/propagate-wit.py +++ b/tooling/propagate-wit.py @@ -1,22 +1,42 @@ #!/usr/bin/env python3 -"""Propagate the versioned duckdb:extension WIT contract everywhere. - -The canonical contract lives in wit/duckdb-extension/*.wit. Every loadable -component carries its OWN frozen copy of (a subset of) those files under -extensions//wit/, the runtime host carries a copy under -crates/ducklink-runtime/wit/deps/duckdb-extension/, and the standalone/cli/loader -worlds reference the package across deps. A contract bump therefore touches many -files; this tool makes it ONE command. - -The contract version is the single constant CONTRACT_VERSION below. Running this -tool rewrites, in every WIT file under the managed roots: - - 1. the package declaration: package duckdb:extension; - -> package duckdb:extension@; - (an already-versioned package line is re-pinned to CONTRACT_VERSION) - - 2. foreign package references that name the package WITHOUT a version, in - `use` / `import` / `export` positions: +"""Sync the duckdb:extension WIT contract from the upstream canonical source and +propagate the versioned copy everywhere it is consumed inside this repo. + +The single source of truth for the duckdb:extension WIT interfaces lives OUT OF +TREE at `~/git/duckdb-wit/wit/duckdb-extension/*.wit` (path overridable via the +`DUCKDB_WIT_ROOT` env var). ducklink and its sibling `ducklink-extension` both +consume the same upstream files so their contracts stay identical. + +Inside this repo, `wit/duckdb-extension/*.wit` is the LOCAL MIRROR of the +upstream source, AUGMENTED with ducklink's own dispatch-layer WITs +(`storage-dispatch`, `storage-write-dispatch`, `aggregate-incr-dispatch`, +`register-*`, etc.). Upstream duckdb-wit is intentionally the PURE +`duckdb:extension` engine surface (`*-host` interfaces + `callback-dispatch`); +ducklink adds its batched-dispatch layer on top under the same package version. +Every loadable component carries its OWN frozen copy of (a subset of) those +files under `extensions//wit/`; the runtime host carries a copy under +`crates/ducklink-runtime/wit/deps/duckdb-extension/`; the standalone/cli/loader +worlds reference the package across deps. A contract bump therefore touches +many files -- this tool makes it ONE command. + +The contract version is the single constant CONTRACT_VERSION below. Running the +tool performs three phases in order: + + 0. SYNC: copy `${DUCKDB_WIT_ROOT}/wit/duckdb-extension/*.wit` into + `wit/duckdb-extension/` (byte-for-byte) for the files that exist upstream. + Local-only files (ducklink's dispatch-layer WITs, plus `deps.toml` and any + nested `worlds/` files not present upstream) are LEFT UNTOUCHED -- upstream + is a subset of the local contract surface, not a mirror of it. Skip with + `--no-sync` for rewrite-only runs (useful when hacking on the local mirror + before pushing upstream). + + 1. PIN PACKAGE HEADER: in every WIT file under the managed roots, + package duckdb:extension; + -> package duckdb:extension@; + (an already-versioned package line is re-pinned to CONTRACT_VERSION.) + + 2. PIN FOREIGN REFS: foreign package references that name the package WITHOUT + a version, in `use` / `import` / `export` positions, use duckdb:extension/runtime; import duckdb:extension/runtime; -> use duckdb:extension/runtime@; @@ -24,24 +44,49 @@ A foreign reference MUST carry the version or it will not resolve against a versioned dep package (wit resolves by exact package id). -It does NOT touch same-package references (`use types;`, `import runtime;` with -no `duckdb:` prefix) -- those resolve within the versioned package and need no +Same-package references (`use types;`, `import runtime;` with no `duckdb:` +prefix) are left alone -- they resolve within the versioned package and need no suffix. Usage: - tooling/propagate-wit.py # rewrite all managed roots in place - tooling/propagate-wit.py --check # exit 1 if anything would change (CI) + tooling/propagate-wit.py # sync upstream + pin, rewrite in place + tooling/propagate-wit.py --check # exit 1 if anything would change (CI) + tooling/propagate-wit.py --no-sync # rewrite only; skip upstream sync + DUCKDB_WIT_ROOT=/path/to/duckdb-wit \\ + tooling/propagate-wit.py # override upstream path """ from __future__ import annotations import argparse +import filecmp +import os import re +import shutil import sys from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent +# Upstream canonical source of the duckdb:extension WIT interfaces. Overridable +# via env for out-of-tree checkouts (e.g. tegmentum/duckdb-wit at a specific +# tag). Default assumes a sibling checkout of duckdb-wit next to ducklink. +DUCKDB_WIT_ROOT = Path( + os.environ.get("DUCKDB_WIT_ROOT") or (REPO_ROOT.parent / "duckdb-wit") +).resolve() + +UPSTREAM_WIT_DIR = DUCKDB_WIT_ROOT / "wit" / "duckdb-extension" +LOCAL_WIT_MIRROR = REPO_ROOT / "wit" / "duckdb-extension" + +# Relpaths under LOCAL_WIT_MIRROR that are ducklink-authored SUPERSETS of the +# upstream file and must NOT be overwritten during sync. `worlds/duckdb-extension.wit` +# in upstream defines the single pure-engine world; ducklink layers ~15 additional +# worlds on top (storage-capable, index-capable, storage-write, ...). Overwriting +# it would silently break every extension that targets those worlds. +LOCAL_ONLY_OVERRIDES: set[str] = { + "worlds/duckdb-extension.wit", +} + # THE single source of truth for the contract version. Bump this, run the tool, # rebuild both hosts + all components, and the whole catalog moves in lockstep. CONTRACT_VERSION = "4.0.0" @@ -91,15 +136,74 @@ def iter_files() -> list[Path]: return out +def _iter_upstream_files() -> list[Path]: + """Every regular file under UPSTREAM_WIT_DIR, recursive. Preserves relative + paths so nested `worlds/*.wit` stay nested in the mirror.""" + if not UPSTREAM_WIT_DIR.is_dir(): + return [] + out: list[Path] = [] + for p in sorted(UPSTREAM_WIT_DIR.rglob("*")): + if p.is_file(): + out.append(p) + return out + + +def sync_upstream(check: bool) -> list[Path]: + """Copy every file from UPSTREAM_WIT_DIR into LOCAL_WIT_MIRROR + byte-for-byte. Returns the list of local paths that changed (or would + change in --check mode). Identical files are untouched (mtimes preserved + for honest build-cache invalidation). + + Local-only files (ducklink dispatch-layer WITs, `deps.toml`, nested + `worlds/*.wit` not present upstream) are LEFT ALONE. Upstream is the pure + `duckdb:extension` engine surface; the local mirror is a superset that + layers ducklink's dispatch WITs into the same package. Pruning would + delete legitimate ducklink content, so we only add/overwrite files that + exist upstream. + """ + if not UPSTREAM_WIT_DIR.is_dir(): + raise SystemExit( + f"upstream WIT source not found at {UPSTREAM_WIT_DIR} " + f"(set DUCKDB_WIT_ROOT=/path/to/duckdb-wit to override)" + ) + + changed: list[Path] = [] + + for src in _iter_upstream_files(): + rel = src.relative_to(UPSTREAM_WIT_DIR) + if str(rel) in LOCAL_ONLY_OVERRIDES: + continue + dst = LOCAL_WIT_MIRROR / rel + if dst.is_file() and filecmp.cmp(src, dst, shallow=False): + continue + changed.append(dst) + if not check: + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src, dst) + + return changed + + def main() -> int: ap = argparse.ArgumentParser(description=__doc__) ap.add_argument( "--check", action="store_true", - help="do not write; exit 1 if any file is not pinned to the contract version", + help="do not write; exit 1 if any file is out of sync or not pinned to the contract version", + ) + ap.add_argument( + "--no-sync", + action="store_true", + help="skip the upstream sync step (rewrite phase only)", ) args = ap.parse_args() + rel = lambda p: p.relative_to(REPO_ROOT) + + synced: list[Path] = [] + if not args.no_sync: + synced = sync_upstream(check=args.check) + files = iter_files() changed: list[Path] = [] for path in files: @@ -110,23 +214,39 @@ def main() -> int: if not args.check: path.write_text(updated) - rel = lambda p: p.relative_to(REPO_ROOT) if args.check: - if changed: - print(f"contract drift: {len(changed)} file(s) not pinned to @{CONTRACT_VERSION}:") - for p in changed: - print(f" {rel(p)}") + problems = synced + changed + if problems: + if synced: + print(f"upstream drift: {len(synced)} file(s) out of sync with {UPSTREAM_WIT_DIR}:") + for p in synced: + print(f" {rel(p)}") + if changed: + print(f"contract drift: {len(changed)} file(s) not pinned to @{CONTRACT_VERSION}:") + for p in changed: + print(f" {rel(p)}") return 1 - print(f"all {len(files)} WIT files pinned to duckdb:extension@{CONTRACT_VERSION}") + print( + f"all {len(files)} WIT files in sync with {UPSTREAM_WIT_DIR} and pinned to " + f"duckdb:extension@{CONTRACT_VERSION}" + ) return 0 + if not args.no_sync: + if synced: + print(f"synced {len(synced)} file(s) from {UPSTREAM_WIT_DIR}:") + for p in synced: + print(f" {rel(p)}") + else: + print(f"already in sync with {UPSTREAM_WIT_DIR}") + print(f"propagated duckdb:extension@{CONTRACT_VERSION} across {len(files)} WIT file(s)") if changed: print(f"updated {len(changed)} file(s):") for p in changed: print(f" {rel(p)}") else: - print("no changes (already pinned)") + print("no version changes (already pinned)") return 0 diff --git a/tools/catalog-sig-extract/Cargo.toml b/tools/catalog-sig-extract/Cargo.toml new file mode 100644 index 00000000..2af14b99 --- /dev/null +++ b/tools/catalog-sig-extract/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "catalog-sig-extract" +version = "0.1.0" +edition = "2021" +license = "MIT" +publish = false +description = "Load each catalog component and emit its full SQL function signatures (catalog `functions` enrichment)" + +[[bin]] +name = "catalog-sig-extract" +path = "src/main.rs" + +[dependencies] +# The shared wasm-component-loading engine: load_component + the neutral reg::* +# capture model. Same loader the Direction-1 host and the Direction-2 native +# extension use, so signatures match what gets registered. +ducklink-runtime = { path = "../../crates/ducklink-runtime" } +wasmtime = { version = "46.0.1", features = ["component-model", "cache"] } +wasmtime-wasi = "46.0.1" +anyhow = "1" +serde_json = { version = "1", features = ["preserve_order"] } diff --git a/tools/catalog-sig-extract/merge-functions.py b/tools/catalog-sig-extract/merge-functions.py new file mode 100644 index 00000000..b7eedb07 --- /dev/null +++ b/tools/catalog-sig-extract/merge-functions.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +"""Fold the extracted function-signature sidecar into the catalog ADDITIVELY. + +`catalog-sig-extract` (the Rust loader) emits a `{name -> functions[]}` sidecar +JSON. This step inserts each entry's `functions` array into the matching catalog +entry and rewrites the catalog with the SAME serializer the catalog generator +uses (`json.dump(..., indent=2, ensure_ascii=True)` + trailing newline), so that +every pre-existing byte is preserved and the additive `functions` key is the +ONLY change. Run from the ducklink repo root. + + python3 tools/catalog-sig-extract/merge-functions.py \ + --catalog registry/index.json --sidecar functions.json [--check] + + --check verify (don't write): assert the result differs from the original + ONLY by the additive `functions` keys, then exit. +""" +import argparse +import json +import sys + + +def load(path): + with open(path, "r", encoding="utf-8") as f: + return f.read() + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--catalog", default="registry/index.json") + ap.add_argument("--sidecar", required=True) + ap.add_argument("--check", action="store_true") + args = ap.parse_args() + + original_text = load(args.catalog) + catalog = json.loads(original_text) + sidecar = json.loads(load(args.sidecar)) + + entries = catalog.get("extensions") + if not isinstance(entries, list): + print("error: catalog has no `extensions` array", file=sys.stderr) + return 2 + + # Sanity: every name in the original is unique (insertion keyed by name). + names = [e.get("name") for e in entries] + if len(names) != len(set(names)): + print("error: duplicate entry names in catalog", file=sys.stderr) + return 2 + + added = 0 + for e in entries: + fns = sidecar.get(e.get("name")) + if fns is None: + continue + # Additive: append `functions` (insertion order keeps it last). dict + # preserves insertion order in py3.7+, so existing keys are untouched. + e["functions"] = fns + added += 1 + + new_text = json.dumps(catalog, indent=2, ensure_ascii=True) + "\n" + + # Invariant check: parse both and confirm the ONLY delta is additive + # `functions` keys (no field changed, no entry added/removed/reordered). + orig = json.loads(original_text) + new = json.loads(new_text) + assert list(orig.keys()) == list(new.keys()), "top-level keys changed" + for k in orig: + if k == "extensions": + continue + assert orig[k] == new[k], f"top-level field {k!r} changed" + oe, ne = orig["extensions"], new["extensions"] + assert len(oe) == len(ne), "entry count changed" + for o, n in zip(oe, ne): + assert o.get("name") == n.get("name"), "entry order changed" + for kk in o: + assert kk in n and o[kk] == n[kk], f"{o.get('name')}: field {kk!r} changed" + extra = set(n) - set(o) + assert extra <= {"functions"}, f"{o.get('name')}: unexpected new keys {extra}" + + print( + f"[merge-functions] entries={len(ne)} enriched={added} " + f"(additive `functions` only)", + file=sys.stderr, + ) + + if args.check: + print("[merge-functions] --check OK (no write)", file=sys.stderr) + return 0 + + with open(args.catalog, "w", encoding="utf-8") as f: + f.write(new_text) + print(f"[merge-functions] wrote {args.catalog}", file=sys.stderr) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/catalog-sig-extract/src/main.rs b/tools/catalog-sig-extract/src/main.rs new file mode 100644 index 00000000..130a174c --- /dev/null +++ b/tools/catalog-sig-extract/src/main.rs @@ -0,0 +1,335 @@ +//! Enrich `registry/index.json` with a `functions` array per extension entry, +//! carrying full SQL signatures (argument types + return type / output columns). +//! +//! It loads each component with the SAME loader the native extension uses +//! (`ducklink_runtime::load_component`), drains the neutral registration model +//! (`reg::ScalarReg` / `TableReg` / `AggregateReg`), and maps each +//! `reg::LogicalType` to the DuckDB SQL type name that the native extension's +//! `src/reg_duckdb.rs` registers it as (so e.g. `Int64` -> `BIGINT`, not the raw +//! `INT64` describe() token). The `functions` field is ADDITIVE: every other +//! field of every entry is preserved byte-for-byte. +//! +//! Usage: +//! catalog-sig-extract [--catalog ] [--out ] [--report ] +//! --catalog path to registry/index.json (default: registry/index.json) +//! --out write the extracted `{name -> functions[]}` map to this JSON file +//! (the sidecar `merge-functions.py` step folds it into the catalog +//! byte-for-byte; default: dry-run, print coverage only) +//! --report write a coverage report (JSON) to this path +//! +//! NOTE: this tool ONLY EXTRACTS signatures (the part that needs to load wasm). +//! It deliberately does NOT serialize the catalog itself — serde_json emits +//! literal UTF-8 whereas the catalog is `ensure_ascii`-escaped, so the folding +//! is done by `merge-functions.py` (Python `json.dump(..., ensure_ascii=True)`) +//! to preserve every pre-existing byte. Keeping the two steps split is why the +//! additive `functions` key is the ONLY change to the catalog file. + +use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; + +use anyhow::{anyhow, Context, Result}; +use ducklink_runtime::reg; +use ducklink_runtime::{ + load_component_with_dynlink, CallbackRegistry, ConfigError, ExtensionServices, LogField, + LogLevel, PendingRegistrationsData, ProviderRegistry, +}; +use serde_json::{json, Map, Value}; +use wasmtime::component::Component; +use wasmtime::{Config, Engine}; +use wasmtime_wasi::{WasiCtx, WasiCtxBuilder}; + +/// Map a neutral `reg::LogicalType` to the DuckDB SQL type name the native +/// extension registers it as. MIRRORS `src/reg_duckdb.rs`'s +/// `reg::LogicalType -> LogicalTypeId` mapping (BIGINT for Int64, DOUBLE for +/// Float64, etc.). `Decimal` registers as `LogicalTypeHandle::decimal(18, 3)`; +/// `Complex(expr)` registers (as a C-API handle) as VARCHAR but the declared +/// type-expression IS a DuckDB SQL type name, so we surface the declared expr. +fn sql_type_name(lt: ®::LogicalType) -> String { + match lt { + reg::LogicalType::Boolean => "BOOLEAN".to_string(), + reg::LogicalType::Int64 => "BIGINT".to_string(), + reg::LogicalType::Uint64 => "UBIGINT".to_string(), + reg::LogicalType::Float64 => "DOUBLE".to_string(), + reg::LogicalType::Text => "VARCHAR".to_string(), + reg::LogicalType::Blob => "BLOB".to_string(), + reg::LogicalType::Int32 => "INTEGER".to_string(), + reg::LogicalType::Timestamp => "TIMESTAMP".to_string(), + reg::LogicalType::Int8 => "TINYINT".to_string(), + reg::LogicalType::Int16 => "SMALLINT".to_string(), + reg::LogicalType::Uint8 => "UTINYINT".to_string(), + reg::LogicalType::Uint16 => "USMALLINT".to_string(), + reg::LogicalType::Uint32 => "UINTEGER".to_string(), + reg::LogicalType::Float32 => "FLOAT".to_string(), + reg::LogicalType::Date => "DATE".to_string(), + reg::LogicalType::Time => "TIME".to_string(), + // reg_duckdb.rs maps Timestamptz -> LogicalTypeId::TimestampTZ. + reg::LogicalType::Timestamptz => "TIMESTAMP WITH TIME ZONE".to_string(), + reg::LogicalType::Interval => "INTERVAL".to_string(), + reg::LogicalType::Uuid => "UUID".to_string(), + // reg_duckdb.rs: T_DECIMAL -> LogicalTypeHandle::decimal(18, 3). + reg::LogicalType::Decimal => "DECIMAL(18,3)".to_string(), + // The declared type-expression (e.g. "INTEGER[]", "STRUCT(a INTEGER)"). + // reg_duckdb.rs registers it as VARCHAR for dispatch, but the catalog + // should surface the user-visible declared SQL type. + reg::LogicalType::Complex(expr) => expr.clone(), + } +} + +fn arg_json(arg: ®::FuncArg) -> Value { + json!({ + "name": arg.name.clone(), + "type": sql_type_name(&arg.logical), + }) +} + +/// Minimal, no-op services sink (no live DB / config). Mirrors the native +/// extension's `NativeServices`: enough to satisfy a component's `load()`, which +/// only registers functions. +struct NoopServices; + +impl ExtensionServices for NoopServices { + fn provider_version(&mut self) -> Result { + Ok(concat!("catalog-sig-extract/", env!("CARGO_PKG_VERSION")).to_string()) + } + fn list_keys(&mut self, _prefix: Option<&str>) -> Result, ConfigError> { + Ok(Vec::new()) + } + fn get_string(&mut self, _path: &str) -> Result, ConfigError> { + Ok(None) + } + fn get_bool(&mut self, _path: &str) -> Result, ConfigError> { + Ok(None) + } + fn get_i64(&mut self, _path: &str) -> Result, ConfigError> { + Ok(None) + } + fn get_u64(&mut self, _path: &str) -> Result, ConfigError> { + Ok(None) + } + fn get_f64(&mut self, _path: &str) -> Result, ConfigError> { + Ok(None) + } + fn get_bytes(&mut self, _path: &str) -> Result>, ConfigError> { + Ok(None) + } + fn get_string_list(&mut self, _path: &str) -> Result>, ConfigError> { + Ok(None) + } + fn log(&mut self, _level: LogLevel, _message: &str, _target: Option<&str>) {} + fn log_fields(&mut self, _level: LogLevel, _message: &str, _fields: &[LogField]) {} +} + +fn build_engine() -> Result { + let mut config = Config::new(); + config.wasm_component_model(true); + // Components targeting DuckDB may use wasm exceptions; mirror the host. + config.wasm_exceptions(true); + if let Ok(cache) = wasmtime::Cache::from_file(None) { + config.cache(Some(cache)); + } + Engine::new(&config) + .map_err(anyhow::Error::from) + .context("failed to create wasmtime engine") +} + +/// Load one component and emit its `functions` JSON array (scalars, tables, +/// aggregates). Returns the array plus a (scalars, tables, aggregates) count. +fn extract_functions(engine: &Engine, name: &str, path: &Path) -> Result<(Value, (usize, usize, usize))> { + let component = Component::from_file(engine, path) + .map_err(anyhow::Error::from) + .with_context(|| format!("loading component at {}", path.display()))?; + let wasi: WasiCtx = WasiCtxBuilder::new().inherit_env().inherit_stdio().build(); + let callbacks = Arc::new(Mutex::new(CallbackRegistry::new())); + // Supply an EMPTY compose:dynlink provider registry so components that import + // `compose:dynlink/linker@0.1.0` (e.g. mlkmeans, spatialproj) still + // instantiate — they only register their functions at load() time and do not + // call the provider during load, so an empty registry is enough to introspect + // their signatures. Components that don't import the linker are unaffected. + let dynlink_registry = ProviderRegistry::new(engine.clone()); + let mut instance = load_component_with_dynlink( + engine, + &component, + wasi, + Box::new(NoopServices), + callbacks, + name.to_string(), + Some(dynlink_registry), + ) + .map_err(anyhow::Error::from) + .context("running component load()")?; + + let pending: PendingRegistrationsData = instance.drain_pending(); + let mut funcs: Vec = Vec::new(); + + for s in &pending.scalars { + funcs.push(json!({ + "name": s.name, + "kind": "scalar", + "arguments": s.arguments.iter().map(arg_json).collect::>(), + "returns": sql_type_name(&s.returns), + })); + } + for t in &pending.tables { + funcs.push(json!({ + "name": t.name, + "kind": "table", + "arguments": t.arguments.iter().map(arg_json).collect::>(), + "columns": t.columns.iter().map(|c| json!({ + "name": c.name, + "type": sql_type_name(&c.logical), + })).collect::>(), + })); + } + for a in &pending.aggregates { + funcs.push(json!({ + "name": a.name, + "kind": "aggregate", + "arguments": a.arguments.iter().map(arg_json).collect::>(), + "returns": sql_type_name(&a.returns), + })); + } + + let counts = (pending.scalars.len(), pending.tables.len(), pending.aggregates.len()); + Ok((Value::Array(funcs), counts)) +} + +struct Skip { + name: String, + reason: String, +} + +fn main() -> Result<()> { + let mut catalog_path = PathBuf::from("registry/index.json"); + let mut out_path: Option = None; + let mut report_path: Option = None; + let mut args = std::env::args().skip(1); + while let Some(a) = args.next() { + match a.as_str() { + "--catalog" => catalog_path = PathBuf::from(args.next().ok_or_else(|| anyhow!("--catalog needs a value"))?), + "--out" => out_path = Some(PathBuf::from(args.next().ok_or_else(|| anyhow!("--out needs a value"))?)), + "--report" => report_path = Some(PathBuf::from(args.next().ok_or_else(|| anyhow!("--report needs a value"))?)), + other => return Err(anyhow!("unknown argument: {other}")), + } + } + + let catalog_dir = catalog_path + .parent() + .and_then(|p| p.parent()) + .map(Path::to_path_buf) + .unwrap_or_else(|| PathBuf::from(".")); + + let raw = std::fs::read_to_string(&catalog_path) + .with_context(|| format!("reading catalog {}", catalog_path.display()))?; + let catalog: Value = serde_json::from_str(&raw).context("parsing catalog JSON")?; + + let entries = catalog + .get("extensions") + .and_then(Value::as_array) + .ok_or_else(|| anyhow!("catalog has no `extensions` array"))?; + let total = entries.len(); + + let engine = build_engine()?; + + let mut enriched = 0usize; + let mut skips: Vec = Vec::new(); + let mut failures: Vec = Vec::new(); + let mut kind_totals: BTreeMap<&'static str, usize> = BTreeMap::new(); + // name -> functions[]: the sidecar the Python merge step folds into the + // catalog. Insertion-ordered (preserve_order) so it follows entry order. + let mut sidecar = Map::new(); + + for entry in entries.iter() { + let obj = match entry.as_object() { + Some(o) => o, + None => continue, + }; + let name = obj + .get("name") + .and_then(Value::as_str) + .unwrap_or("") + .to_string(); + let source = obj.get("source").and_then(Value::as_str).unwrap_or(""); + let status = obj.get("status").and_then(Value::as_str).unwrap_or(""); + let artifact = obj.get("artifact").and_then(Value::as_str).map(str::to_string); + + // builtin / planned entries have no loadable artifact. + if status == "planned" { + skips.push(Skip { name, reason: "status=planned".to_string() }); + continue; + } + let artifact = match artifact { + Some(a) if !a.is_empty() => a, + _ => { + skips.push(Skip { name, reason: format!("no artifact (source={source})") }); + continue; + } + }; + let art_path = catalog_dir.join(&artifact); + if !art_path.exists() { + skips.push(Skip { name, reason: format!("artifact missing locally: {artifact}") }); + continue; + } + + match extract_functions(&engine, &name, &art_path) { + Ok((funcs, (ns, nt, na))) => { + *kind_totals.entry("scalar").or_default() += ns; + *kind_totals.entry("table").or_default() += nt; + *kind_totals.entry("aggregate").or_default() += na; + sidecar.insert(name, funcs); + enriched += 1; + } + Err(e) => { + let chain: Vec = e.chain().map(|c| c.to_string()).collect(); + failures.push(Skip { name, reason: chain.join(": ") }); + } + } + } + + eprintln!( + "[catalog-sig-extract] total={total} enriched={enriched} skipped={} failed={}", + skips.len(), + failures.len() + ); + eprintln!( + "[catalog-sig-extract] functions: scalar={} table={} aggregate={}", + kind_totals.get("scalar").copied().unwrap_or(0), + kind_totals.get("table").copied().unwrap_or(0), + kind_totals.get("aggregate").copied().unwrap_or(0), + ); + for s in &skips { + eprintln!(" SKIP {}: {}", s.name, s.reason); + } + for f in &failures { + eprintln!(" FAIL {}: {}", f.name, f.reason); + } + + if let Some(op) = &out_path { + let mut out = serde_json::to_string_pretty(&Value::Object(sidecar))?; + out.push('\n'); + std::fs::write(op, out).with_context(|| format!("writing {}", op.display()))?; + eprintln!("[catalog-sig-extract] wrote sidecar {}", op.display()); + } else { + eprintln!("[catalog-sig-extract] dry-run (pass --out to emit the functions sidecar)"); + } + + if let Some(rp) = report_path { + let report = json!({ + "total": total, + "enriched": enriched, + "skipped": skips.iter().map(|s| json!({"name": s.name, "reason": s.reason})).collect::>(), + "failed": failures.iter().map(|f| json!({"name": f.name, "reason": f.reason})).collect::>(), + "function_counts": { + "scalar": kind_totals.get("scalar").copied().unwrap_or(0), + "table": kind_totals.get("table").copied().unwrap_or(0), + "aggregate": kind_totals.get("aggregate").copied().unwrap_or(0), + }, + }); + let mut out = serde_json::to_string_pretty(&report)?; + out.push('\n'); + std::fs::write(&rp, out)?; + eprintln!("[catalog-sig-extract] wrote report {}", rp.display()); + } + + Ok(()) +} diff --git a/website/docs/architecture/columnar-abi.md b/website/docs/architecture/columnar-abi.md index bb338279..528b5631 100644 --- a/website/docs/architecture/columnar-abi.md +++ b/website/docs/architecture/columnar-abi.md @@ -113,7 +113,7 @@ content-addressed digest over the canonical WIT bytes (`witcanon:1`, contract digest is: ``` -a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40 +b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3 ``` Every catalog entry records the digest it was built against (`wit_contract` + diff --git a/website/docs/guides/distribution.md b/website/docs/guides/distribution.md index 27c91ea6..6be2ba1d 100644 --- a/website/docs/guides/distribution.md +++ b/website/docs/guides/distribution.md @@ -38,7 +38,7 @@ entry carries identity and conformance metadata: "description": "...", "exports": ["base32_encode", "..."], "version": "0.1.0", - "wit_contract": "a2ad9764ac971345d6a650b92edbda034b160980acf148d354126f7e6f92ba40", + "wit_contract": "b24dc901568e38e5b05fc0dc535ebaec3c93a9a44c772bb105686032e45e16b3", "wit_contract_version": "4.0.0", "content_digest": "...", "providers": [ diff --git a/wit/duckdb-extension/collation-host.wit b/wit/duckdb-extension/collation-host.wit new file mode 100644 index 00000000..1e62de38 --- /dev/null +++ b/wit/duckdb-extension/collation-host.wit @@ -0,0 +1,27 @@ +package duckdb:extension@4.0.0; + +// Host -> core collation pull. The DuckDB-compiled-to-wasm core IMPORTS this +// interface; the native host PROVIDES it, returning the collations that +// components have declared (via the `collation.register-collation` WIT call). +// This mirrors how the core pulls ATTACH `TYPE` names via +// `storage-host.storage-list-types`. +// +// A collation reuses an already-registered scalar (text -> sort-key text) as +// its transform. The core looks the scalar up by name in the catalog and wraps +// it in a DuckDB collation (CreateCollationInfo), so `ORDER BY x COLLATE name` +// resolves to it. Registration is dynamic (mid-session): the core pulls this +// list lazily before each query and registers each collation it has not yet +// seen, dedup-guarded. +interface collation-host { + // One collation a component declared: its catalog name, the already-registered + // scalar that performs the (text -> sort-key text) transform, and whether the + // collation can be combined with other collations. + record collation-spec { + name: string, + transform-scalar: string, + combinable: bool, + } + + // Enumerate the collations components have declared so far this session. + collation-list: func() -> list; +} diff --git a/wit/duckdb-extension/files-host.wit b/wit/duckdb-extension/files-host.wit new file mode 100644 index 00000000..460d5f65 --- /dev/null +++ b/wit/duckdb-extension/files-host.wit @@ -0,0 +1,28 @@ +package duckdb:extension@4.0.0; + +// httpfs M2. Host -> core file I/O callbacks. The DuckDB-compiled-to-wasm core +// IMPORTS this interface; the native host PROVIDES it and routes each call to +// the files-backend component (e.g. webfs) that registered a files backend, +// driving that component's `file-dispatch` export. This mirrors how the core +// imports `storage-host` for ATTACH foreign-catalog dispatch. +// +// Simple + robust M2 contract (no HTTP Range): the component, on file-open, +// does a single GET of the whole file, caches the bytes, and returns its size. +// file-read slices the cache; file-close drops it. +interface files-host { + // The component-side file handle plus the total size discovered at open. + record file-open-result { + handle: u32, + size: u64, + } + + // Fetch + cache the resource named by `url`; return a file handle + total size. + file-open: func(url: string) -> result; + + // Return up to `len` bytes from the cached resource starting at `offset`. + // A short read at EOF is allowed (returns fewer bytes than requested). + file-read: func(handle: u32, offset: u64, len: u32) -> result, string>; + + // Drop the cache entry for `handle`. + file-close: func(handle: u32) -> result<_, string>; +} diff --git a/wit/duckdb-extension/optimizer-host.wit b/wit/duckdb-extension/optimizer-host.wit new file mode 100644 index 00000000..77700733 --- /dev/null +++ b/wit/duckdb-extension/optimizer-host.wit @@ -0,0 +1,30 @@ +package duckdb:extension@4.0.0; + +use types; + +// Host -> core optimizer pull + dispatch (2.3.0 / v3, additive within major-3). +// The DuckDB-compiled-to-wasm core IMPORTS this; the native host PROVIDES it. +// Mirrors `parser-host`: at optimize time the core flattens the bound logical plan +// into a neutral JSON descriptor (op-type names + params, NOT a by-value +// LogicalOperator tree) and offers it to each declared optimizer rule via +// `call-optimize`. The owning component returns a string->SQL REWRITE the core +// re-plans in place (the `rewrite-query` directive), or none (declined). No plan +// node crosses the boundary by value. +interface optimizer-host { + use types.{duckerror}; + + // One optimizer rule a component declared: a name + the dispatch handle the + // host routes `call-optimize` through to the owning component. + record optimizer-spec { + rule-name: string, + callback-handle: u32, + } + + // Enumerate the optimizer rules components have declared so far this session. + optimizer-list: func() -> list; + + // Offer the flattened plan (`plan-json`) to the rule `handle`. Returns + // `some(rewrite-sql)` if the rule rewrites the query (the core re-plans it in + // place), or `none` if it declines / the directive is not a query rewrite. + call-optimize: func(handle: u32, plan-json: string) -> result, duckerror>; +} diff --git a/wit/duckdb-extension/parser-host.wit b/wit/duckdb-extension/parser-host.wit new file mode 100644 index 00000000..20c8f2db --- /dev/null +++ b/wit/duckdb-extension/parser-host.wit @@ -0,0 +1,29 @@ +package duckdb:extension@4.0.0; + +use types; + +// Host -> core parser pull + dispatch (2.3.0 / v3). The DuckDB-compiled-to-wasm +// core IMPORTS this interface; the native host PROVIDES it. Mirrors +// `pragma-host`: the core pulls the parser extensions components have declared +// (via `parser.register-parser-extension`), and -- when the built-in parser +// rejects a statement -- offers the raw statement text to each, applying the +// string->SQL REWRITE the owning component returns. The component never returns a +// bound parse tree (the by-value WIT recursion wall); only text in, SQL out. +interface parser-host { + use types.{duckerror}; + + // One parser extension a component declared: a name + the dispatch handle the + // host routes `call-parse` through to the owning component. + record parser-spec { + name: string, + callback-handle: u32, + } + + // Enumerate the parser extensions components have declared so far this session. + parser-list: func() -> list; + + // Offer the unrecognized statement `query` to the parser extension `handle`. + // Returns `some(rewrite-sql)` if the component claims + rewrites it, or `none` + // if it declines (the core proceeds to its own parse error). + call-parse: func(handle: u32, query: string) -> result, duckerror>; +} diff --git a/wit/duckdb-extension/pragma-host.wit b/wit/duckdb-extension/pragma-host.wit new file mode 100644 index 00000000..541a614b --- /dev/null +++ b/wit/duckdb-extension/pragma-host.wit @@ -0,0 +1,27 @@ +package duckdb:extension@4.0.0; + +// Host -> core pragma pull (Item 4). The DuckDB-compiled-to-wasm core IMPORTS +// this interface; the native host PROVIDES it, returning the pragmas that +// components have declared (via the existing `runtime.pragma-registry.register-call` +// WIT call). This mirrors `collation-host.collation-list` / `storage-host.storage-list-types`. +// +// KEY DESIGN (avoids re-entrancy): a PRAGMA callback runs MID-QUERY, so the +// component must NOT call back into SQL during the callback. Instead the core +// intercepts `PRAGMA (...)` in its query path, dispatches the pragma +// (callback-dispatch.call-pragma -> the component), and the component RETURNS a +// SQL script as a text value. The core then runs that script on the same +// connection. The component never re-enters SQL. +// +// `callback-handle` is the host-side handle the core passes to +// `callback-dispatch.call-pragma` to dispatch this pragma to the owning component. +interface pragma-host { + // One pragma a component declared: the PRAGMA name the user types + // (`PRAGMA (...)`) and the dispatch handle for callback-dispatch.call-pragma. + record pragma-spec { + name: string, + callback-handle: u32, + } + + // Enumerate the pragmas components have declared so far this session. + pragma-list: func() -> list; +} diff --git a/wit/duckdb-extension/storage-host.wit b/wit/duckdb-extension/storage-host.wit new file mode 100644 index 00000000..6084acc5 --- /dev/null +++ b/wit/duckdb-extension/storage-host.wit @@ -0,0 +1,126 @@ +package duckdb:extension@4.0.0; + +use types; + +// Host -> core storage callbacks. The DuckDB-compiled-to-wasm core IMPORTS this +// interface; the native host PROVIDES it and routes each call to the storage +// component (e.g. sqlitewasm) that registered an ATTACH backend, driving that +// component's `storage-dispatch` export. This mirrors how the core imports +// `callback-dispatch` (call-table etc.) for function dispatch. +// +// M2a needs only attach + table/column enumeration; scan-open/next/close are +// declared for M2b but the core may not call them yet. +interface storage-host { + use types.{duckerror, columndef, duckvalue}; + + type resultset = list>; + + // Comparison pushed into a scan as an AND-ed predicate. Mirrors the backing + // component's storage.compare-op. + enum compare-op { + eq, ne, lt, le, gt, ge, is-null, is-not-null, + } + + // One predicate. `column` indexes the table's FULL column list (not the + // projection). Pushdown is best-effort: the engine re-applies every filter. + record scan-filter { + column: u32, + op: compare-op, + value: duckvalue, // ignored for is-null / is-not-null + } + + // What the engine asks a scan to produce. Mirrors the component's + // storage.scan-request. + // + // When `wants-rowid` is true the guest must append a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (in addition to the projected column cells). DuckDB's UPDATE/DELETE + // physical plans project `COLUMN_IDENTIFIER_ROW_ID` alongside the touched + // columns; the C++ WasmScanInitGlobal detects those slots, strips them + // from `projection` (which stays exclusively real table column indices), + // and sets this flag. `storage-scan-open` on the storage-dispatch side + // carries the same semantic across the host->guest dispatch layer. + record scan-request { + table: string, + projection: list, // column indices to emit, in order; empty = all + filters: list, + limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row + } + + // Enumerate the ATTACH `TYPE` names that components have registered (via + // `register-storage`) so far this session. The core calls this lazily (before + // running queries) and registers a wasm StorageExtension for each type it has + // not yet seen, so `ATTACH ... (TYPE )` can dispatch to that component. + // This replaces the previous hardcoded "sqlitewasm" registration at DB-open. + storage-list-types: func() -> list; + + // Open the foreign catalog named by an ATTACH DSN (a host file path for the + // native host). The host stages the file bytes into the backing component and + // returns the component-side catalog handle. + storage-attach: func(dsn: string) -> result; + + // Enumerate the catalog's base tables. + storage-list-tables: func(catalog: u32) -> result, duckerror>; + + // Enumerate one table's columns (name + duckdb logical type). + storage-table-columns: func(catalog: u32, table: string) -> result, duckerror>; + + // M2b scan surface: engine-driven projection + filter pushdown. + storage-scan-open: func(catalog: u32, request: scan-request) -> result; + storage-scan-next: func(scan: u32, max-rows: u32) -> result; + storage-scan-close: func(scan: u32) -> result; + + // M2c WRITE surface (additive): transactions + DDL + DML. Each call mirrors + // the corresponding entry on the component's `storage-write-dispatch` export; + // the host resolves the (extension, handle) to route to via the same + // `resolve_storage_backend` picker the read-side scan imports use, then + // forwards to the ExtensionInstance write trampolines + // (ducklink-runtime/src/extension.rs `storage_{begin,commit,rollback}_transaction`, + // `storage_{create_table,insert_rows,update_rows,delete_rows}`). + // + // The C++ WasmCatalog `PlanInsert / PlanUpdate / PlanDelete` + + // WasmTransactionManager + WasmSchemaEntry::CreateTable route here through the + // extern-C bridge in `wasm_storage_bridge.h` (wasm_storage_write_*). + + // Open a write transaction on `catalog`; returns a transaction handle. + storage-begin-transaction: func(catalog: u32) -> result; + + // Commit an open write transaction. + storage-commit-transaction: func(txn: u32) -> result<_, duckerror>; + + // Roll back an open write transaction; releases txn state on the component + // side even if it was already rolled back. + storage-rollback-transaction: func(txn: u32) -> result<_, duckerror>; + + // CREATE TABLE within an open transaction. + storage-create-table: func(txn: u32, table: string, + columns: list) -> result<_, duckerror>; + + // Append rows; returns the number of rows inserted. + storage-insert-rows: func(txn: u32, table: string, + rows: list>) -> result; + + // Delete rows by rowid; returns the number deleted. + storage-delete-rows: func(txn: u32, table: string, + rowids: list) -> result; + + // Update rows by rowid (parallel `rowids` and `rows`). Each `rows[i]` is a + // PARTIAL row carrying only the values for the columns being SET; the + // schema-index of each cell is given by the parallel-indexed entry in + // `updated-columns`, so `rows[i][j]` sets the schema column + // `updated-columns[j]` on the row identified by `rowids[i]`. + // + // DuckDB's `LogicalUpdate::columns` is the plan-time list of physical + // schema indices that appear in the `SET` clause; the C++ WasmPhysicalUpdate + // captures those at plan time and forwards them here alongside the child + // DataChunk's SET cells (whose column count is always `updated-columns.len`; + // the trailing chunk column is the row identifier — captured out-of-band as + // `rowids`). The guest may reject an `updated-columns` entry it doesn't + // know how to project on (e.g. a virtual column). Returns the number of + // rows successfully updated. + storage-update-rows: func(txn: u32, table: string, + rowids: list, + updated-columns: list, + rows: list>) -> result; +} diff --git a/wit/duckdb-extension/storage-write-dispatch.wit b/wit/duckdb-extension/storage-write-dispatch.wit index 2617766f..2ecc2cb5 100644 --- a/wit/duckdb-extension/storage-write-dispatch.wit +++ b/wit/duckdb-extension/storage-write-dispatch.wit @@ -38,11 +38,19 @@ interface storage-write-dispatch { table: string, rowids: list) -> result; - // Update rows by row-id (parallel `rowids` / `rows`); returns the number - // updated. + // Update rows by row-id (parallel `rowids` / `rows`). Each `rows[i]` is a + // PARTIAL row that carries ONLY the SET values; the schema-index of each + // cell is given by the parallel-indexed entry in `updated-columns`, so + // `rows[i][j]` sets column `updated-columns[j]` on the row identified by + // `rowids[i]`. Mirrors the storage-host `storage-update-rows` semantic -- + // the ducklink host forwards `LogicalUpdate::columns` (captured at plan + // time by WasmPhysicalUpdate) verbatim as `updated-columns` and the SET + // cells of each child DataChunk as the parallel `rows` payload. Returns + // the number of rows successfully updated. update-rows: func(handle: u32, txn: u32, table: string, rowids: list, + updated-columns: list, rows: list>) -> result; } diff --git a/wit/duckdb-extension/storage.wit b/wit/duckdb-extension/storage.wit index 7f1c4c57..b38f983f 100644 --- a/wit/duckdb-extension/storage.wit +++ b/wit/duckdb-extension/storage.wit @@ -28,11 +28,21 @@ interface storage { } // What the engine asks a scan to produce. + // + // `wants-rowid`, when true, tells the guest to emit a stable per-row s64 + // rowid as the FINAL cell of every row returned by `storage-scan-next` + // (after the projected column cells, which stay in projection order). The + // ducklink CLI's WasmPhysicalUpdate/WasmPhysicalDelete plans project + // `COLUMN_IDENTIFIER_ROW_ID` alongside the touched columns; the C++ + // WasmScanInitGlobal strips those rowid slots from `projection` and sets + // this flag so the guest supplies the rowid values the sink then round- + // trips into `storage-write-dispatch.update-rows` / `.delete-rows`. record scan-request { table: string, projection: list, // column indices to emit, in order; empty = all filters: list, limit: option, // best-effort row cap + wants-rowid: bool, // append s64 rowid as trailing cell of each row } // Called by the component in load() to declare a backend keyed by an ATTACH diff --git a/wit/duckdb-extension/table-stream-host.wit b/wit/duckdb-extension/table-stream-host.wit new file mode 100644 index 00000000..4f265fa2 --- /dev/null +++ b/wit/duckdb-extension/table-stream-host.wit @@ -0,0 +1,69 @@ +package duckdb:extension@4.0.0; + +use types; + +// Host -> core callbacks for a STREAMING + FILTER-PUSHDOWN table function (3.1.0, +// the first additive MINOR off the frozen major-3 baseline). The DuckDB-compiled- +// to-wasm core IMPORTS this interface; the host PROVIDES it and routes each call +// (by the global callback-handle the function was registered with) to the owning +// component's `table-stream-dispatch` export (open-filtered / next / close). +// Mirrors `storage-host` (the proven by-value-safe filter-pushdown bridge), but +// for a NAMED table function with bound argument values instead of a catalog. +interface table-stream-host { + use types.{duckerror, columndef, duckvalue}; + + type resultset = list>; + + // A streaming + filter-pushdown-capable table function a component declared + // (via the component-facing `table-stream.register-filterable-table` marker). + // The core pulls this list lazily (before queries, like collation/optimizer + // sync) and registers a real C++ streaming TableFunction (filter_pushdown = + // true) for each not-yet-seen entry. `arguments` are the positional argument + // types (name informational); `columns` is the emitted schema; `handle` is the + // global routable callback-handle threaded into ts-open-filtered/next/close. + record filterable-table { + name: string, + arguments: list, + columns: list, + handle: u32, + } + + // Enumerate the filterable streaming table functions declared so far. + filterable-table-list: func() -> list; + + // The pushed-down comparator. Mirrors table-stream-dispatch.filter-op. + enum ts-filter-op { + eq, ne, lt, le, gt, ge, is-in, is-null, is-not-null, + } + + // One pushed-down clause. `column` indexes the EMITTED (post-projection) + // schema; `values` carries the constant operand(s) (empty for is-null/ + // is-not-null, one for the scalar comparators, many for is-in). The full filter + // is the AND of all clauses. Best-effort: the engine re-applies every filter. + record ts-filter { + column: u32, + op: ts-filter-op, + values: list, + } + + // Opening a streaming cursor returns an opaque cursor handle plus the emitted + // column schema (after projection). + record ts-open-result { + cursor: u32, + columns: list, + } + + // Open a streaming cursor for the registered table function `handle` with the + // bound `args`, a `projection` (emitted column indices; empty = all), and the + // conjunctive pushed-down `filters`. + ts-open-filtered: func(handle: u32, + args: list, + projection: list, + filters: list) -> result; + + // Pull up to `max-rows` from the cursor; an empty resultset signals EOF. + ts-next: func(handle: u32, cursor: u32, max-rows: u32) -> result; + + // Close the cursor and free its state. + ts-close: func(handle: u32, cursor: u32) -> result; +} diff --git a/wit/standalone/loader-stub.wit b/wit/standalone/loader-stub.wit index ca7e21da..06c4dd8d 100644 --- a/wit/standalone/loader-stub.wit +++ b/wit/standalone/loader-stub.wit @@ -11,6 +11,20 @@ world loader-stub { export duckdb:component/host-extension-loader; export duckdb:component/extension-loader-hooks; export duckdb:extension/callback-dispatch@4.0.0; + // Host->core callbacks the core imports so extension-registered backends can + // service storage (ATTACH), vector indexes, collations, pragmas, parsers, + // optimizers, remote files (httpfs), and filtered table streams. A standalone + // registers no such backends, so each `*-list` enumerator returns empty (the + // core registers nothing) and the per-handle operations are unreachable. The + // engine's built-in local/in-memory functionality is unaffected. + export duckdb:extension/storage-host@4.0.0; + export duckdb:extension/index-host@4.0.0; + export duckdb:extension/collation-host@4.0.0; + export duckdb:extension/pragma-host@4.0.0; + export duckdb:extension/parser-host@4.0.0; + export duckdb:extension/optimizer-host@4.0.0; + export duckdb:extension/files-host@4.0.0; + export duckdb:extension/table-stream-host@4.0.0; // The core imports tvm:memory unconditionally (the >4 GiB spill tier). The // standalone has no 64-bit host to back it, so the stub declines region // creation: the guest's spill bridge then disables TVM and falls back to the