Skip to content

WASM Procedures: Language SDKs

Part of: WASM Procedures User Guide


LanguagePublished SDK
Go (TinyGo)github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm
RustNone. The heliosdb-sdk crate named in older pages does not exist on crates.io.
JavaScript / AssemblyScriptNone. @heliosdb/wasm-sdk does not exist on npm.
PythonNone. heliosdb-wasm-sdk does not exist on PyPI.

Go SDK

The Go SDK is the Go module github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm (Apache-2.0, no dependencies). Procedures are compiled with TinyGo 0.34 or later.

Setup

Terminal window
go mod init my-procedure
go get github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm@latest
PackagePurpose
github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm/heliosdbHost functions: SQL statements, transactions, key-value writes, logging
github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm/heliosdbtestIn-memory fake host for go test

How Go procedures run

  • A procedure is an exported function whose parameters and results are WASM scalars (int32, int64, float32, float64). Return a status code or a number, and write richer results to a table.
  • Export it with TinyGo’s //export directive. The host calls exported functions directly and does not run _start or _initialize.
  • Build with -target=wasm-unknown -gc=conservative. The host links only its own env functions and no WASI, so -target=wasip1 modules (and modules from the standard Go toolchain) fail to instantiate.
  • Keep package-level state static (constants and literals), and avoid init() functions with side effects.
  • SQL has no bind parameters at the ABI level, so build literals with heliosdb.Quote, heliosdb.QuoteIdent and heliosdb.Int64.
  • Procedures run statements but cannot read result rows. The host functions that return rows write them to a host-chosen address in the module’s memory, so the SDK does not expose them. Use INSERT ... SELECT or UPDATE ... FROM to work with data inside SQL.

Basic Procedure

package main
import "github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm/heliosdb"
//export apply_discount
func applyDiscount(priceCents int64, percent int32) int64 {
if percent <= 0 {
return priceCents
}
if percent >= 100 {
return 0
}
return priceCents - priceCents*int64(percent)/100
}
//export deactivate_stale_users
func deactivateStaleUsers(days int32) int64 {
n, err := heliosdb.Exec("UPDATE users SET active = false WHERE last_seen < NOW() - INTERVAL '" +
heliosdb.Int64(int64(days)) + " days'")
if err != nil {
heliosdb.LogError("deactivate_stale_users: " + err.Error())
return -1
}
return n // rows affected
}
func main() {}

Transactions and Error Handling

package main
import "github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm/heliosdb"
//export record_order
func recordOrder(customerID, amountCents int64) int32 {
if amountCents <= 0 {
heliosdb.LogWarn("record_order: amount must be positive")
return -1
}
// WithTx commits when the function returns nil and rolls back otherwise.
err := heliosdb.WithTx(func(heliosdb.Tx) error {
if _, err := heliosdb.Exec("INSERT INTO orders (customer_id, amount_cents) VALUES (" +
heliosdb.Int64(customerID) + ", " + heliosdb.Int64(amountCents) + ")"); err != nil {
return err
}
_, err := heliosdb.Exec("UPDATE customers SET order_count = order_count + 1 WHERE id = " +
heliosdb.Int64(customerID))
return err
})
if err != nil {
// *heliosdb.HostError carries the host's return code.
heliosdb.LogError("record_order: " + err.Error())
return -1
}
return 0
}
func main() {}

heliosdb.StorageWrite(key, value) writes to the host key-value store.

Testing

Procedures are ordinary Go functions, so they can be unit-tested natively with the fake host:

package main
import (
"testing"
"github.com/HeliosDatabase/HeliosDB-SDKs/sdks/go/wasm/heliosdbtest"
)
func TestRecordOrder(t *testing.T) {
fake := heliosdbtest.Install(t)
if rc := recordOrder(7, 1999); rc != 0 {
t.Fatalf("rc = %d", rc)
}
if len(fake.SQL) != 2 {
t.Fatalf("sql = %v", fake.SQL)
}
}
func TestRecordOrderRollsBack(t *testing.T) {
fake := heliosdbtest.Install(t)
fake.FailSQL("UPDATE")
if rc := recordOrder(7, 1999); rc != -1 {
t.Fatalf("rc = %d", rc)
}
if fake.Tx[len(fake.Tx)-1].Op != "rollback" {
t.Fatal("expected rollback")
}
}

Build:

Terminal window
# Run unit tests (native, no WASM runtime needed)
go test ./...
# Build the procedure module
tinygo build -target=wasm-unknown -gc=conservative -opt=z -no-debug -o procedure.wasm .

The SDK repository also has an ABI conformance suite. It builds an example procedure with TinyGo, checks every import against the host’s env functions, and runs the procedure the way the host does.

Other languages

There are no published Rust, JavaScript/AssemblyScript or Python SDKs. A module written in any language that compiles to a core WebAssembly module (with no WASI imports) can import the host functions directly from the env module. See Host Functions for their signatures.


Navigation: