Skip to content

WASM Procedures: Host Functions

Part of: WASM Procedures User Guide


Module requirements

  • Imports come from the env module. The host’s linker defines only the functions below. It does not provide WASI, so a module that imports wasi_snapshot_preview1 fails to instantiate with an unknown-import error.
  • The module exports its linear memory as memory. The host reads and writes arguments through it.
  • Procedures are exported functions with scalar parameters and results (i32, i64, f32, f64). The host calls them directly and does not run _start or _initialize.
  • Strings are passed as a pointer and a byte length into the module’s memory, and must be valid UTF-8.

Database and storage functions

Import (env)SignatureReturns
heliosdb_execute(stmt_ptr i32, stmt_len i32) -> i64Rows affected (>= 0). -1 invalid UTF-8, -2 execution failed, -3 memory access error.
heliosdb_begin_tx() -> i64Transaction id (> 0). -1 could not start, -2 too many concurrent transactions.
heliosdb_commit_tx(tx_id i64) -> i320 success. 1 unknown id, 2 already committed or rolled back, 3 commit failed.
heliosdb_rollback_tx(tx_id i64) -> i320 success. 1 unknown id, 2 already committed or rolled back.
heliosdb_storage_write(key_ptr i32, key_len i32, value_ptr i32, value_len i32) -> i320 success. 1 invalid UTF-8 key, 2 write failed, 3 memory access error.
heliosdb_log(level i32, msg_ptr i32, msg_len i32) -> i320 success. 1 invalid UTF-8, 2 level outside 0 (trace) to 4 (error), 3 memory access error.

Functions that return data

Import (env)SignatureNotes
heliosdb_query(query_ptr i32, query_len i32, result_ptr_out i32, result_len_out i32) -> i32Runs a query and serialises the result as JSON ({"columns": [...], "rows": [[...]], "row_count": N}). It writes the result’s address and length to the two *_out locations.
heliosdb_storage_read(key_ptr i32, key_len i32, value_ptr_out i32, value_len_out i32) -> i32Reads a key-value entry the same way. 2 means the key was not found.
heliosdb_fetch_rows(result_handle i64, buffer_ptr i32, buffer_len i32, rows_fetched_ptr i32) -> i32Cursor-style row fetch.
heliosdb_emit_event(type_ptr i32, type_len i32, payload_ptr i32, payload_len i32) -> i32Validates a JSON event payload. Events are not yet delivered to triggers.

Calling the functions from Go

The Go SDK wraps the safe functions:

Go APIHost import
heliosdb.Exec(sql) (int64, error)heliosdb_execute
heliosdb.Begin(), Tx.Commit(), Tx.Rollback(), heliosdb.WithTx(fn)heliosdb_begin_tx, heliosdb_commit_tx, heliosdb_rollback_tx
heliosdb.StorageWrite(key, value)heliosdb_storage_write
heliosdb.Log(level, msg), LogInfo, LogWarn, LogError, …heliosdb_log
//export archive_order
func archiveOrder(orderID int64) int32 {
err := heliosdb.WithTx(func(heliosdb.Tx) error {
id := heliosdb.Int64(orderID)
if _, err := heliosdb.Exec("INSERT INTO orders_archive SELECT * FROM orders WHERE id = " + id); err != nil {
return err
}
_, err := heliosdb.Exec("DELETE FROM orders WHERE id = " + id)
return err
})
if err != nil {
heliosdb.LogError("archive_order: " + err.Error())
return -1
}
return 0
}

Calling the functions from other languages

Declare the imports with the signatures above. For example, in Rust:

#[link(wasm_import_module = "env")]
extern "C" {
fn heliosdb_execute(stmt_ptr: i32, stmt_len: i32) -> i64;
fn heliosdb_log(level: i32, msg_ptr: i32, msg_len: i32) -> i32;
}
#[no_mangle]
pub extern "C" fn touch_user(id: i64) -> i32 {
let sql = format!("UPDATE users SET seen_at = NOW() WHERE id = {id}");
let n = unsafe { heliosdb_execute(sql.as_ptr() as i32, sql.len() as i32) };
if n < 0 { -1 } else { 0 }
}

Build such modules for wasm32-unknown-unknown, not a WASI target.


Navigation: