Expand description
§spg-embedded
Ergonomic embedded-mode entry point for SPG. Wraps the
spg-engine execution layer for in-process applications
that don’t want to spin up a TCP listener / fork to the
spg-server binary.
§Quick start
use spg_embedded::Database;
// On-disk, durable. WAL fsynced per commit; auto-checkpoint
// at 4 MiB WAL by default.
let mut db = Database::open_path("/data/app.db").unwrap();
db.execute("CREATE TABLE users (id INT NOT NULL, name TEXT)").unwrap();
db.execute("INSERT INTO users VALUES (1, 'alice')").unwrap();
let rows = db.query("SELECT name FROM users WHERE id = 1").unwrap();
for row in &rows {
println!("{:?}", row);
}§Production checklist (v7.5)
- Persistence:
Database::open_path(p)writes a crash-consistent WAL + periodic checkpoint snapshot. The on-disk format is byte-identical to whatspg-serverproduces, so a database can move between modes without conversion. - Durability: every
execute()that mutates callsfsyncbefore returningOk. There is no group commit in embedded mode — every commit pays one fsync. If you need batch throughput, wrap multiple statements inDatabase::with_transactionwhich fsyncs only at commit. - Concurrency:
DatabaseisSendbut notSync. Share across threads viaArc<Mutex<Database>>. The single-writer model is intentional — see STABILITY § A1. - Background work:
Database::spawn_background_freezermoves cold rows to disk-resident segments while you keep serving requests. It runs in a dedicated thread; drop the returnedFreezerHandle(or callstop()) for clean shutdown. - Errors: all public enums (
EngineError,QueryResult,Value) are#[non_exhaustive]. Match them with a wildcard arm so future v7.x releases can add variants without breaking your code.
§Panic contract
- No
execute()/query()call panics on user input. Malformed SQL, type mismatches, missing tables — all returnErr(EngineError::…). If you observe a panic on a user-controlled string, that is a bug; file an issue. - The library panics only on internal invariant
violations (e.g., catalog snapshot magic mismatch, WAL
record CRC sentinel corruption that survived the boot-
time validation). These represent silent disk corruption
and an unwind would leak inconsistent state, so the
release profile uses
panic = abort— your host process dies fast rather than continuing on poisoned data. - If you cannot tolerate
panic = abort, build with--profile release-dbg(keeps unwind tables) and usestd::panic::catch_unwindat your application boundary.
§Why a separate crate?
spg-engine is no_std-compatible (vendored alloc-only).
The embedded-mode entry point uses std (filesystem,
threading), so it lives in its own crate to keep the
no_std boundary clean.
Macros§
- spg_row
- v7.3.0 — declarative macro that generates
FromSpgRowimpl for a user struct. Avoids proc-macro deps (syn/quote/proc-macro2) so the workspace’s 0-deps policy holds; the trade-off vs#[derive(SpgRow)]is that the macro takes the entire struct definition (fields + types) as input rather than annotating an existing struct.
Structs§
- Column
Schema - Database
- Embedded SPG database handle. Owns an
Engine+ provides ergonomic wrappers aroundexecuteandquery. Drops the engine onDrop— no WAL flush / fsync, because v6.10.3 is in-memory only. - Embedded
Metrics - v7.7.5 — observability snapshot returned by
Database::metrics. Plain data, no allocations beyond what the struct itself takes; cheap to construct and cheap to serialise. - Engine
- Freezer
Handle - v7.2.1 — handle returned by
spawn_background_freezer. Drop signals the worker thread to wind down + joins it, so aDatabase(or its sharedArc<Mutex<Database>>) can safely drop after the handle does. - Freezer
Options - v7.2.1 — knobs for
Database::spawn_background_freezer. - Statement
- v7.16.0 — handle for a parsed-and-planned SQL statement.
Hand off to
Database::execute_prepared/Database::query_preparedwith a&[Value]slice carrying the bind parameters (PG-style$1,$2, … positional). Cheap toClone; the underlying AST is shared by handle copies and cloned per bind call by the engine’s executor.
Enums§
- Data
Type - Runtime type tags.
Vector { dim, encoding }/Varchar(max)/Char(size)are parameterised; the parameter travels with both the column schema and the on-wire serialised representation. - Engine
Error - All errors the engine can return.
- Parsed
Statement - Query
Result - Result of executing one statement.
- Value
- A row-cell value, including SQL
NULL.Floatusesf64; NaN compares non-equal to itself (PG behaviour) —PartialEqis derived so callers must opt into NaN-aware comparison if they need stronger guarantees.
Traits§
- From
SpgRow - v6.10.3 — trait that maps a row’s columns onto a user
struct’s fields. v7.3.0 ships the
spg_row!declarative macro that generatesimpl FromSpgRow for YourStructfrom a struct definition (no proc-macro, no syn/quote/ proc-macro2 deps — the workspace’s “0 external deps” policy holds). - From
SpgValue - v7.3.0 — per-column decoder used by
spg_row!. Surface covers every numeric / text / bytes / bool variant inValue, plusOption<T>for nullable columns.
Functions§
- revert_
wal_ to_ seq - v7.7.6 — replay the first
to_seqrecords of the WAL atwal_pathinto a fresh engine and write the resulting catalog snapshot toout_db_path. Same semantics asspg revert --wal … --to-seq N --out …from the CLI: