gizdb:migrate
Bounded migration commands use the public DAL actor and its transaction owner.
import * as Migrate from "gizdb:migrate";Types
Backfill
type Backfill = { source: string; keys: Vec<Typed.Slot>; inputs: Vec<Typed.Slot>; target: string; outputs: Vec<Typed.Slot>; mode: string; transform: (row: Vec<Value>) => Result<Vec<Value>, DbError> effects {fail}; }Inputs and outputs start with the complete primary key, in storage order. The transform is pure. It can run again after an uncommitted batch fails. insert moves rows to a new table; update fills non-key columns in place.
source:stringkeys:Vec<M79.Slot>inputs:Vec<M79.Slot>target:stringoutputs:Vec<M79.Slot>mode:stringtransform:(row: Vec<M80.Value>) => _gizlang_sdk_core.Result<Vec<M80.Value>, M81.DbError> effects { fail }
Step
type Step = | { kind: "schema"; statements: Vec<Statement>; } | { kind: "data"; backfill: Backfill; } | { kind: "contract"; statements: Vec<Statement>; }The schema planner's caller supplies lowered statements. This executor does not derive a second schema. Only an explicit final contract can remove a column.
schemadatacontract
Migration
type Migration = { id: string; digest: bytes; steps: Vec<Step>; }The caller supplies a stable 32-byte digest of the complete plan and transform. Function values have no stable serialization. Reusing a digest after editing a transform violates this declaration.
id:stringdigest:bytessteps:Vec<M83.Step>
Limits
type Limits = { rows: i64; bytes: i64; batches: i64; }bytes bounds retained source pages and the encoded input, output and progress values of each batch. The DAL owns SQL/WAL allocation admission separately. batches=0 runs until completion; a positive value pauses after that many data commits.
rows:i64bytes:i64batches:i64
Progress
type Progress = { id: string; step: i64; lastKey: string; rows: i64; state: string; digest: bytes; }Where a migration stands: its step, the last key it moved, the rows so far, its state and its plan's digest.
id:stringstep:i64lastKey:stringrows:i64state:stringdigest:bytes
Report
type Report = { progress: Progress; batches: i64; paused: bool; }What a run did: the progress it reached, its batches, and whether it paused at Limits.batches.
progress:M83.Progressbatches:i64paused:bool
Functions
status
function status(connection: Connection, id: string): Option<Progress> throws DbErrorMissing metadata or an unknown id returns none. Other failures remain errors.
Effects: fail, io.
apply
function apply(connection: Connection, migration: Migration, limits: Limits): Report throws DbErrorEach committed batch and its cursor are one actor write transaction. A fresh frontier is taken BEFORE progress and source reads. apply fences that frontier in the actor before it writes. Therefore every accepted transform used the row's current state at commit. A concurrent commit returns conflict; resume rereads progress and the failed batch. No stale value or progress is published.
Guarantee: per-row commit-time conversion, not a continuously maintained projection. Edits/inserts/deletes behind lastKey are not replayed. Same-table updates preserve fields outside outputs. Applications must maintain converted fields on subsequent writes before an explicit contract is safe. General online catch-up needs durable change delivery acknowledged in the SAME write as migration progress. Connection.changes currently publishes its checkpoint separately; it cannot provide that crash guarantee through this boundary. Transform evaluation can repeat; committed data batches cannot repeat.
Effects: fail, read, write, console, io.