#8971·turso

Feature request: Rust API for registering user-defined SQL functions

Author: mcmah309Created Sep 12, 2026Updated Sep 17, 2026

Motivation

When using Turso as an embedded database from Rust, it would be useful to register a Rust function with a connection and invoke it from SQL.

For example:

rust
let conn = /* ... */;

conn.create_scalar_function("handle_user_change", |user_id: i64| {
    // Run application-defined Rust code.
    handle_user_change(user_id)?;
    Ok(())
})?;

Then SQL could call that function directly:

sql
CREATE TRIGGER user_updated
AFTER UPDATE ON users
BEGIN
    SELECT handle_user_change(NEW.id);
END;

Another strong use case for this is validating or transforming data using host code. This would provide a simple way for an embedded Turso database to call into its Rust host process when database changes occur.

Proposed API

Something conceptually similar to rusqlite::Connection::create_scalar_function:

rust
conn.create_scalar_function(
    "my_function",
    /* flags/options */,
    |ctx| {
        // Read SQL arguments and return a SQL value.
    },
)?;

The exact API does not need to match rusqlite, but ideally it would support:

  • registering a Rust function on a connection
  • typed or ergonomic access to SQL arguments
  • returning SQLite/Turso values
  • deterministic / non-deterministic flags where applicable

Why not just use an outbox / CDC?

An outbox table or CDC works well when the desired behavior is asynchronous or is needed after a transaction. Otherwise, polling an outbox introduces an additional asynchronous boundary that is not otherwise necessary.

Prior art

SQLite exposes this functionality through sqlite3_create_function, and Rust libraries such as rusqlite expose it as a safe Rust API.

Question

  • Should we support asynchronous scalar functions?