Write custom SQL functions (VDFs) for VillageSQL in safe Rust. The SDK handles all FFI marshaling so you work entirely in ordinary Rust types.
Docs: VillageSQL documentation · Writing Rust extensions · Install VillageSQL Server
| Crate | Description |
|---|---|
villagesql |
Safe Rust SDK for writing VDF extension functions |
cargo-vsql |
Cargo subcommand for packaging and testing extensions |
villagesql-sys |
Raw FFI bindings (used internally by villagesql) |
- Rust toolchain (stable, 1.87+)
cargo-vsqlinstalled (see cargo-vsql README)- VillageSQL build directory (for
installandtestcommands)
cargo install cargo-vsqlThe fastest way is the vsql-extension-template-rust template — it scaffolds the Cargo.toml, manifest.json, source layout, and a CI workflow for you:
cargo install cargo-generate
cargo generate --git https://github.com/villagesql/vsql-extension-template-rustOr set it up by hand
cargo new --lib my-extension
cd my-extension
cargo add villagesqlThen add to Cargo.toml, so Cargo builds a shared library the server can load:
[lib]
crate-type = ["cdylib"]use villagesql::{InValue, VdfReturn};
fn my_func(args: &[InValue]) -> VdfReturn {
match args.first() {
Some(InValue::String(s)) => VdfReturn::string(s.to_uppercase()),
Some(InValue::Null) | None => VdfReturn::null(),
_ => VdfReturn::error("my_func: expected a STRING argument"),
}
}
villagesql::extension! {
funcs: [
villagesql::func!(my_func, "my_func", [villagesql::Type::String] -> villagesql::Type::String),
]
}Create manifest.json next to Cargo.toml:
{
"name": "my-extension",
"version": "0.1.0",
"description": "What your extension does",
"author": "Your Name",
"license": "GPL-2.0"
}Run cargo vsql commands from inside your extension directory (not the workspace root).
export VillageSQL_BUILD_DIR=/path/to/villagesql/build
cargo vsql install
cargo vsql testFor the full API reference see the villagesql README. For all cargo vsql commands see the cargo-vsql README.
Reusable GitHub Actions workflows for building, testing, and packaging Rust VillageSQL extensions live in villagesql/extension-actions. The vsql-extension-template-rust template wires them up by default.
examples/vsql_rot13— minimal string function; a good starting templateexamples/vsql_rational— custom type (n/drational numbers) with arithmetic VDFs, demonstratingcustom_type!,InValue::Custom, andVdfReturn::binary