Skip to main content
The Rust SDK is in alpha — expect breaking API changes between releases. Function-only extensions and custom types (encode, decode, compare, hash) are supported. Aggregates, prerun(), VarArgs, system and status variables, keyring access, and the column storage ABI are C++-only today — use the C++ SDK if you need any of those.
This page is a reference for the villagesql crate API. For the getting started tutorial, see Creating Extensions in Rust. For custom types, see Custom Types in Rust.

InValue

InValue is the enum the server passes for each function argument. Your function receives args: &[InValue] and must check each argument before using its value.
Always match on Null explicitly. Calling .unwrap() or pattern-matching only the value variants is a bug — SQL NULL is a normal input, not an error.

VdfReturn

VdfReturn is what your function returns to the server. Construct it with one of the associated functions: Warning vs error: Use warning for user-input validation failures where continuing with the rest of the result set makes sense. In strict mode, MySQL promotes warnings to errors on INSERT and UPDATE. Use error for conditions where proceeding is unsafe — corrupt stored data, internal invariant violations. A fatal error aborts the entire statement.

extension! macro

extension! generates the VEF entry points the server calls when loading your VEB file. It must appear exactly once in the crate.
Both sections are optional. A pure-function extension omits types:; a type-only extension omits funcs:. An empty extension! block (no funcs, no types) is valid but produces an extension that does nothing.

func! macro

func! declares a SQL-callable function. Four forms (no parameters, buffer_size only, deterministic only, both):
The buffer_size parameter requires the villagesql crate 0.0.2 or later. The current crates.io release (0.0.1) doesn’t expose it — until 0.0.2 ships, use the forms without buffer_size.
Type constants for use in func!:

custom_type! macro

custom_type! registers a new column type. type_name, persisted_length, max_decode_buffer_length, encode, decode, and compare are required. hash and default are optional but recommended.
The default field is not a column default value — it’s a startup probe. The server calls encode(default) when loading the extension to verify the callback works. If encode returns Err for the default, the extension fails to load.

custom! macro

villagesql::custom!("type_name") references a custom type by name in a func! declaration:
Use it anywhere a villagesql::Type::* would appear in a parameter list or return type position. The string must match the type_name declared in the corresponding custom_type!.

manifest.json fields

Every extension needs a manifest.json alongside its Cargo.toml:
name validation rules: must start with a letter, end with a letter or digit, max 64 characters. An invalid manifest causes INSTALL EXTENSION to fail.