SQL
drift.Backbone.SQL(name): a per-slice SQLite database, addressed by the name you declared in the Driftfile.
Signatures
Query(sql string, args ...any) ([]map[string]any, error) // SELECT → rows as maps
Execute(sql string, args ...any) (SQLResult, error) // INSERT/UPDATE/DELETE + DDL
Begin() (SQLTx, error)
type SQLResult struct { RowsAffected, LastInsertID int64 }
type SQLTx struct { ... } // Query · Execute · Commit() · Rollback()Execute runs DDL too (CREATE TABLE…). Arguments are positional placeholders (?), bound safely. Never string-concatenate SQL.
Transactions
Begin() returns a separate handle carrying a server-issued token. Statements join the transaction only when you run them on that handle. Anything run on the database itself executes outside it.
tx, _ := drift.Backbone.SQL("app").Begin()
if _, err := tx.Execute("UPDATE accounts SET balance = balance - ? WHERE id = ?", 100, 1); err != nil {
tx.Rollback()
return err
}
tx.Execute("UPDATE accounts SET balance = balance + ? WHERE id = ?", 100, 2)
tx.Commit()An idle SQLTx is rolled back after 30 seconds.
A janitor sweeps every 5, so commit or roll back promptly. A single statement over 64 KiB is rejected with
413, and a token used against a different database name with 400.SQL is the one primitive with no local implementation.
The zero-dependency SDKs bundle no SQL engine, so
drift.Backbone.SQL(…) has nothing to talk to under drift atomic run. Exercise that path against a deployed slice, or use drift project run, which boots the real runtime.