Documentation
¶
Overview ¶
Package sqlstore owns Starport's relational storage contract. It is the SQL twin of internal/storage: where that package pairs an embedded Badger store with a Valkey connect for shared state, this one pairs an embedded SQLite database that rides the binary with a network SQL connect for a multi-node deployment. Relational concepts — identity, teams, grants, account templates — keep their repositories on this contract and never name a driver or a dialect themselves.
The embedded backend uses a pure-Go SQLite driver, so the single-binary install story holds: no cgo, no system library, no separate database process. The package also owns the schema: every migration lives in the embedded migrations directory here, and Migrate applies them in order, once each, recording what it applied. No other package writes schema.
Index ¶
- Constants
- Variables
- type Config
- type DB
- func (db *DB) ActivateRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, ...) (resultErr error)
- func (db *DB) ActivateRelationalImportAt(ctx context.Context, snapshot SQLiteSnapshot, ...) error
- func (db *DB) Bind(query string) string
- func (db *DB) CheckActivatedRelationalImportAt(ctx context.Context, snapshot SQLiteSnapshot, ...) error
- func (db *DB) CheckFresh(ctx context.Context) error
- func (db *DB) CheckImportBarrier(ctx context.Context) error
- func (db *DB) CheckRelationalImportPosition(ctx context.Context, original SQLiteSnapshot, ...) (resultErr error)
- func (db *DB) CheckSchemaCurrent(ctx context.Context) error
- func (db *DB) CheckUnreleasedRelationalImport(ctx context.Context, original SQLiteSnapshot, ...) (resultErr error)
- func (db *DB) ClaimPopulatedRelational(ctx context.Context, expected SQLiteSnapshot, census RelationalRecoveryCensus, ...) (resultErr error)
- func (db *DB) Dialect() string
- func (db *DB) GuardRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, ...) (resultErr error)
- func (db *DB) ImportRelational(ctx context.Context, source string, expected SQLiteSnapshot, scratch string, ...) (resultErr error)
- func (db *DB) ImportRelationalOnce(ctx context.Context, source string, expected SQLiteSnapshot, scratch string, ...) error
- func (db *DB) Migrate(ctx context.Context) error
- func (db *DB) Ping(ctx context.Context) error
- func (db *DB) PrepareImportSchema(ctx context.Context) error
- func (db *DB) ReconcileMySQLMigration(ctx context.Context, decision MigrationReconciliation) error
- func (db *DB) ReconcileRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, ...) (resultErr error)
- func (db *DB) RecoveryTargetSHA256(ctx context.Context, config Config) (string, error)
- func (db *DB) ReplayRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, ...) (digest string, resultErr error)
- func (db *DB) SnapshotRelational(ctx context.Context, destination string) (SQLiteSnapshotResult, error)
- func (db *DB) SnapshotRelationalImport(ctx context.Context, destination string, original SQLiteSnapshot, ...) (SQLiteSnapshotResult, error)
- func (db *DB) SnapshotSQLite(ctx context.Context, destination string) (SQLiteSnapshotResult, error)
- func (db *DB) WithFreshSchema(ctx context.Context, initialize func(*sql.Tx) error) error
- type MigrationReconciliation
- type MySQLConfig
- type PostgresConfig
- type RecoveryStartupState
- type RelationalImportIdentity
- type RelationalRecoveryCensus
- type RelationalReplayPosition
- type RelationalReplayStep
- type RelationalSnapshotView
- func (v *RelationalSnapshotView) Close() error
- func (v *RelationalSnapshotView) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
- func (v *RelationalSnapshotView) QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
- func (v *RelationalSnapshotView) RecoveryCensus(ctx context.Context) (result RelationalRecoveryCensus, resultErr error)
- type SQLiteConfig
- type SQLiteSnapshot
- type SQLiteSnapshotResult
Constants ¶
const ( // TypeSQLite is the embedded backend: a database file beside the // deployment's other data, created on first open. An empty path keeps // the database in memory, which is the development runtime's choice. TypeSQLite = "sqlite" // TypePostgres is the PostgreSQL connect for a multi-node deployment, // the relational counterpart of the Valkey connect. TypePostgres = "postgres" // TypeMySQL is the MySQL connect for a multi-node deployment. TypeMySQL = "mysql" )
Relational backend type constants.
const QualifiedPostgreSQLVersion = "16.15"
QualifiedPostgreSQLVersion is the PostgreSQL release that the real-backend qualification covers. CI pins the same release by image digest, and TestQualifiedPostgreSQLVersion compares a real service against it. Another release is UNVERIFIED until a qualification run records it here.
Variables ¶
var ( // ErrUnknownType is returned when the configuration names a backend // this package does not serve. ErrUnknownType = errors.New("unknown sqlstore type") // ErrClosed is returned when an operation reaches a closed store. ErrClosed = errors.New("sqlstore closed") // ErrSchemaBehind is returned when a store lacks a migration of this binary. ErrSchemaBehind = errors.New("relational schema is behind this binary") )
Common errors returned by sqlstore operations.
var ErrAuditCounterUnrepresentable = errors.New("MySQL cannot preserve an exhausted audit allocation counter")
ErrAuditCounterUnrepresentable refuses a target that could reuse an exhausted audit ID.
var ErrGuardDeadline = errors.New("relational import guard requires a context deadline")
ErrGuardDeadline refuses an import guard without a context deadline.
var ErrImportRestricted = errors.New("relational import requires deployment recovery before startup")
ErrImportRestricted keeps an imported SQL database unavailable to ordinary startup.
var ErrMigrationRecoveryRequired = errors.New("SQL migration requires reconciliation")
ErrMigrationRecoveryRequired reports a MySQL migration with uncertain schema changes.
var ErrNotFresh = errors.New("storage is not fresh; use the migration or recovery procedure")
ErrNotFresh refuses initialization over existing or uncertain application state.
var ErrPopulatedBackend = errors.New("populated relational claim requires PostgreSQL or MySQL")
ErrPopulatedBackend refuses a populated claim on a backend without in-place adoption.
var ErrPopulatedCensus = errors.New("live relational rows differ from the captured recovery census")
ErrPopulatedCensus refuses a populated claim when the live rows differ from the captured census.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
Type string `env:"TYPE,default=sqlite"`
SQLite SQLiteConfig `env:",prefix=SQLITE_"`
Postgres PostgresConfig `env:",prefix=POSTGRES_"`
MySQL MySQLConfig `env:",prefix=MYSQL_"`
}
Config selects and configures a relational backend, the way storage.Config selects a key-value one.
type DB ¶
DB is one open relational store. It embeds the standard connection pool, so a repository reads and writes through database/sql, and it names the dialect for the rare statement that cannot be written once for every backend.
func Open ¶
Open creates a relational store from the configuration. It follows the Go convention internal/storage.Open set: validate, then dispatch on the type.
func (*DB) ActivateRelationalImport ¶ added in v1.3.0
func (db *DB) ActivateRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, decisionSHA256 string, approve func(context.Context, *sql.Conn) error) (resultErr error)
ActivateRelationalImport commits final domain approval, its receipt, and import barrier removal together. The coordinator must first verify history and fencing. approve must use only conn for SQL writes and must not commit or change schema. Exact retries verify completion without repeating approval or changing later data.
func (*DB) ActivateRelationalImportAt ¶ added in v1.3.0
func (db *DB) ActivateRelationalImportAt(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, position RelationalReplayPosition, decisionSHA256 string, approve func(context.Context, *sql.Conn) error) error
ActivateRelationalImportAt binds barrier release to the exact final replay position. The transaction checks the retained cursor before and after the approval callback. Exact retries preserve later SQL changes without repeating the callback.
func (*DB) Bind ¶
Bind rewrites ? placeholders into the dialect's form. PostgreSQL numbers its placeholders. The other engines take ? as written. A repository on this contract writes its statements once with ? and binds per dialect.
func (*DB) CheckActivatedRelationalImportAt ¶ added in v1.3.0
func (db *DB) CheckActivatedRelationalImportAt(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, position RelationalReplayPosition, decisionSHA256 string) error
CheckActivatedRelationalImportAt verifies the exact retained native activation. It does not approve admission. It preserves all later domain changes and withdrawals.
func (*DB) CheckFresh ¶ added in v1.3.0
CheckFresh refuses existing application records before schema migration.
func (*DB) CheckImportBarrier ¶ added in v1.3.0
CheckImportBarrier refuses a partial or unapproved SQL restore after schema initialization. Malformed markers also refuse startup. This method never approves or removes a barrier.
func (*DB) CheckRelationalImportPosition ¶ added in v1.3.0
func (db *DB) CheckRelationalImportPosition(ctx context.Context, original SQLiteSnapshot, identity RelationalImportIdentity, position RelationalReplayPosition) (resultErr error)
CheckRelationalImportPosition verifies current closed ownership without changing state. It does not prove external fencing or complete independent history.
func (*DB) CheckSchemaCurrent ¶ added in v1.3.0
CheckSchemaCurrent refuses a store that lacks an embedded migration or that records a migration this binary does not know. It changes nothing, so a write path can refuse instead of migrating.
func (*DB) CheckUnreleasedRelationalImport ¶ added in v1.3.0
func (db *DB) CheckUnreleasedRelationalImport(ctx context.Context, original SQLiteSnapshot, identity RelationalImportIdentity) (resultErr error)
CheckUnreleasedRelationalImport verifies the original closed claim at any replay position. It creates no record and never releases or repairs an import barrier.
func (*DB) ClaimPopulatedRelational ¶ added in v1.3.0
func (db *DB) ClaimPopulatedRelational(ctx context.Context, expected SQLiteSnapshot, census RelationalRecoveryCensus, scratch string, identity RelationalImportIdentity, restrict func(context.Context, *sql.Conn) error) (resultErr error)
ClaimPopulatedRelational installs the import barrier on a populated PostgreSQL or MySQL database in place. The live rows must equal the captured census of expected in every class. The claim copies no rows. It retires the current activation and replay rows, keeps every historical receipt, and writes one closure receipt. restrict runs in the same transaction. Exact retries verify the closure receipt and do not repeat restrict. Scratch must be an existing private directory. The caller must fence every target writer.
func (*DB) GuardRelationalImport ¶ added in v1.3.0
func (db *DB) GuardRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, position RelationalReplayPosition, callback func(context.Context, *sql.Conn) error) (resultErr error)
GuardRelationalImport holds native migration ownership and a transaction at an exact closed import position. The callback must use only conn for SQL work, without a nested transaction, commit, or schema change. The caller must bound non-SQL work by the context deadline and retain receipts for independent commits. A returned error does not undo an independent KV commit or prove that SQL completion failed. This guard never advances replay or removes the import barrier.
func (*DB) ImportRelational ¶ added in v1.3.0
func (db *DB) ImportRelational(ctx context.Context, source string, expected SQLiteSnapshot, scratch string, restrict func(context.Context, *sql.Conn) error) (resultErr error)
ImportRelational copies a verified image into an empty, migrated target database. The caller must fence every target writer and stop schema changes before import. restrict must close restored permission gates in the same transaction before commit. This operation does not change application configuration or approve recovery.
func (*DB) ImportRelationalOnce ¶ added in v1.3.0
func (db *DB) ImportRelationalOnce(ctx context.Context, source string, expected SQLiteSnapshot, scratch string, identity RelationalImportIdentity, restrict func(context.Context, *sql.Conn) error) error
ImportRelationalOnce retains a startup barrier in the same transaction as imported records. Exact retries validate the source and receipt without repeating restrictions. The caller must fence target writers. A receipt does not verify later target mutations.
func (*DB) Migrate ¶
Migrate applies pending schema files under database migration ownership. SQLite and PostgreSQL commit each file with its completion record. MySQL retains an intent before DDL and refuses automatic retries after partial failure.
func (*DB) PrepareImportSchema ¶ added in v1.3.0
PrepareImportSchema initializes empty target tables or accepts a current schema. It never upgrades populated state. All writers and other schema owners must remain fenced. The importer separately checks emptiness or the exact retained import receipt.
func (*DB) ReconcileMySQLMigration ¶ added in v1.3.0
func (db *DB) ReconcileMySQLMigration(ctx context.Context, decision MigrationReconciliation) error
ReconcileMySQLMigration records verified repair without executing migration SQL. The operator must first establish the declared outcome from the schema and data. An exact operation retry is idempotent. Changed decisions require another operation ID.
func (*DB) ReconcileRelationalImport ¶ added in v1.3.0
func (db *DB) ReconcileRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, step, evidenceSHA256 string, apply func(context.Context, *sql.Conn) error) (resultErr error)
ReconcileRelationalImport commits one domain repair and its immutable receipt. It requires the exact import barrier and retains that barrier after success. apply must use conn without committing, changing schema, or opening admission. The owner must validate current domain state after an exact receipt retry.
func (*DB) RecoveryTargetSHA256 ¶ added in v1.3.0
RecoveryTargetSHA256 binds connection routes and the selected database namespace. It excludes credentials and does not prove physical server continuity.
func (*DB) ReplayRelationalImport ¶ added in v1.3.0
func (db *DB) ReplayRelationalImport(ctx context.Context, snapshot SQLiteSnapshot, identity RelationalImportIdentity, step RelationalReplayStep, apply func(context.Context, *sql.Conn) error) (digest string, resultErr error)
ReplayRelationalImport commits an ordered domain transition and its receipt atomically. apply must use conn without committing, changing schema, or touching recovery controls. The coordinator must fence writers and validate the final domain state before activation. Exact retries return their original receipt without repeating earlier mutations.
func (*DB) SnapshotRelational ¶ added in v1.3.0
func (db *DB) SnapshotRelational(ctx context.Context, destination string) (SQLiteSnapshotResult, error)
SnapshotRelational exports the current logical schema into a portable SQLite image. The caller must stop cross-store writes and retain the result in the deployment manifest. This method does not change the source schema or approve recovered permissions.
func (*DB) SnapshotRelationalImport ¶ added in v1.3.0
func (db *DB) SnapshotRelationalImport(ctx context.Context, destination string, original SQLiteSnapshot, identity RelationalImportIdentity, position RelationalReplayPosition) (SQLiteSnapshotResult, error)
SnapshotRelationalImport captures a closed import at its exact replay position. Writers must remain fenced. The result preserves native import controls for inspection. Failure returns no valid snapshot receipt and never releases the import barrier.
func (*DB) SnapshotSQLite ¶ added in v1.3.0
SnapshotSQLite publishes a consistent SQLite image into a new private directory. The directory contains starport.db and snapshot.json. Existing destinations remain untouched. The deployment coordinator must stop cross-store writes before this operation.
func (*DB) WithFreshSchema ¶ added in v1.3.0
WithFreshSchema holds application tables against writes while initialize runs. The caller must stop all application processes and schema changes beforehand. Only migration metadata may exist. A failed callback rolls back SQL changes.
type MigrationReconciliation ¶ added in v1.3.0
type MigrationReconciliation struct {
OperationID string
Name string
Digest string
Outcome string
Actor string
EvidenceSHA256 string
}
MigrationReconciliation records an operator's independently verified DDL outcome. Applied means all effects exist. Reverted means all effects of the attempt are absent. The caller authorizes the administrator and retains the evidence bytes.
type MySQLConfig ¶
type MySQLConfig struct {
// DSN is a go-sql-driver DSN such as
// user:password@tcp(host:3306)/starport.
DSN string `env:"DSN"`
}
MySQLConfig configures the MySQL connect.
type PostgresConfig ¶
type PostgresConfig struct {
// URL is a postgres:// connection URL, database and credentials
// included.
URL string `env:"URL"`
}
PostgresConfig configures the PostgreSQL connect.
type RecoveryStartupState ¶ added in v1.3.0
type RecoveryStartupState struct {
Activated bool
ClaimSHA256 string
DecisionSHA256 string
ReceiptSHA256 string
}
RecoveryStartupState reports checked native recovery controls. It grants no activation authority. Current replay consistency does not establish the originally approved final position.
func InspectRecoveryStartup ¶ added in v1.3.0
func InspectRecoveryStartup(ctx context.Context, config Config, deployment string) (state RecoveryStartupState, resultErr error)
InspectRecoveryStartup reads existing selected SQL state before application effects. It creates no database or schema and does not migrate or repair recovery records. Missing schema permits first boot only when no retained recovery schema exists.
type RelationalImportIdentity ¶ added in v1.3.0
type RelationalImportIdentity struct {
OperationID string `json:"operation_id"`
RestrictionID string `json:"restriction_id"`
}
RelationalImportIdentity binds an import to its operation and recovery policy. RestrictionID must identify the complete callback policy, including its selected epoch.
type RelationalRecoveryCensus ¶ added in v1.3.0
type RelationalRecoveryCensus struct {
DomainSHA256 string `json:"domain_sha256"`
WitnessSHA256 string `json:"witness_sha256"`
ControlSHA256 string `json:"control_sha256"`
RevisionSHA256 string `json:"revision_sha256"`
DomainRows int64 `json:"domain_rows"`
WitnessRows int64 `json:"witness_rows"`
ControlRows int64 `json:"control_rows"`
RevisionRows int64 `json:"revision_rows"`
AuditHighWater int64 `json:"audit_high_water"`
}
RelationalRecoveryCensus separates portable domain rows from native recovery controls. Every row contributes to one digest. These diagnostics grant no recovery authority.
type RelationalReplayPosition ¶ added in v1.3.0
type RelationalReplayPosition struct {
Sequence int64 `json:"sequence"`
ReceiptSHA256 string `json:"receipt_sha256"`
}
RelationalReplayPosition selects an exact retained replay cursor. The zero value selects imported state before the first replay step.
type RelationalReplayStep ¶ added in v1.3.0
type RelationalReplayStep struct {
Sequence int64 `json:"sequence"`
PreviousSHA256 string `json:"previous_sha256"`
EvidenceSHA256 string `json:"evidence_sha256"`
TransitionSHA256 string `json:"transition_sha256"`
}
RelationalReplayStep binds an ordered domain transition to independent evidence. The domain owner derives TransitionSHA256 from its complete canonical typed input. A digest binds bytes. It does not establish provenance or complete history.
type RelationalSnapshotView ¶ added in v1.3.0
type RelationalSnapshotView struct {
// contains filtered or unexported fields
}
RelationalSnapshotView owns a verified private copy of a portable SQL image. Its connection is immutable and read-only. It exposes no transaction or write methods.
func OpenRelationalSnapshot ¶ added in v1.3.0
func OpenRelationalSnapshot(ctx context.Context, source string, expected SQLiteSnapshot, scratch string) (_ *RelationalSnapshotView, resultErr error)
OpenRelationalSnapshot verifies bytes and the complete schema before exposing records. Scratch must be an existing private directory. Close removes only the owned copy.
func (*RelationalSnapshotView) Close ¶ added in v1.3.0
func (v *RelationalSnapshotView) Close() error
Close releases connections and removes only the directory with the captured identity.
func (*RelationalSnapshotView) QueryContext ¶ added in v1.3.0
func (v *RelationalSnapshotView) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryContext reads the immutable copy through SQLite's read-only connection.
func (*RelationalSnapshotView) QueryRowContext ¶ added in v1.3.0
func (v *RelationalSnapshotView) QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
QueryRowContext reads one row from the immutable copy.
func (*RelationalSnapshotView) RecoveryCensus ¶ added in v1.3.0
func (v *RelationalSnapshotView) RecoveryCensus(ctx context.Context) (result RelationalRecoveryCensus, resultErr error)
RecoveryCensus streams the complete compiled row contract from an immutable image. It preserves original native controls as separate facts that need owner validation.
type SQLiteConfig ¶
type SQLiteConfig struct {
// Path is the database file. An empty path opens an in-memory
// database that lives and dies with the process.
Path string `env:"PATH"`
}
SQLiteConfig configures the embedded backend.
type SQLiteSnapshot ¶ added in v1.3.0
type SQLiteSnapshot struct {
Format string `json:"format"`
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
}
SQLiteSnapshot identifies a complete database image, including committed WAL data. The deployment manifest must bind this identity to the other persistent stores.
type SQLiteSnapshotResult ¶ added in v1.3.0
type SQLiteSnapshotResult struct {
Snapshot SQLiteSnapshot
Published bool
}
SQLiteSnapshotResult reports publication separately from the final directory sync. Published can be true with an error when durability remains uncertain.
func RestoreSQLiteSnapshot ¶ added in v1.3.0
func RestoreSQLiteSnapshot(ctx context.Context, destination, source string, expected SQLiteSnapshot) (SQLiteSnapshotResult, error)
RestoreSQLiteSnapshot verifies an image and publishes it into a new private directory. This imports bytes only. It does not approve recovery or select the database for a running gateway. The caller must fence old writers and reconcile independent history before admission.
Source Files
¶
- connect.go
- fresh.go
- import_schema.go
- migrate.go
- migration_mysql.go
- migration_owner.go
- migration_reconcile.go
- open.go
- qualified.go
- recovery_startup.go
- recovery_target.go
- relational_activation.go
- relational_copy.go
- relational_guard.go
- relational_import.go
- relational_import_receipt.go
- relational_inspection.go
- relational_populated.go
- relational_reconciliation.go
- relational_recovery_census.go
- relational_replay.go
- relational_schema.go
- relational_snapshot.go
- relational_view.go
- sqlite_snapshot.go
- sqlstore.go