Documentation
¶
Overview ¶
Package grizzle provides declarative, in-process database schema automigration for Go.
Grizzle synchronizes PostgreSQL and SQLite database schemas directly from standard schema.sql DDL definitions on application startup, eliminating sequence file collisions, manual migration versioning, and external CLI/Docker runtime dependencies.
Core Concepts ¶
- Declarative Schema: Write standard SQL DDL (schema.sql) as the single source of truth.
- In-Process Execution: Runs natively within your Go binary without needing external CLI binaries.
- Shadow Sandbox: Replays and validates desired schema state inside a temporary shadow schema or SQLite in-memory sandbox.
- Deterministic Diff: Pure schema comparison detecting missing tables, columns, indexes, constraints, and types.
- Safe Execution: Dedicated advisory locking, multi-node contention retry, hazard gating, and transactional execution.
- Zero-Downtime Operations: Safe non-transactional enum expansions (PostgreSQL ALTER TYPE ... ADD VALUE) and concurrent index generation.
Subpackages & Modules ¶
- griztest: Testing primitives (MustSync, MustPlan, Reset) for effortless test database setup and teardown.
- otelgrizzle: Optional OpenTelemetry tracing integration (github.com/muandane/grizzle/otelgrizzle).
Basic Usage ¶
db, err := sql.Open("pgx", os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
defer db.Close()
err = grizzle.Sync(ctx, db, grizzle.Options{
SchemaSQL: schemaSQL,
})
if err != nil {
log.Fatalf("migration failed: %v", err)
}
Index ¶
- Constants
- Variables
- func Apply(ctx context.Context, db *sql.DB, p *Plan, opts ApplyOpts) error
- func Check(ctx context.Context, db *sql.DB, opts Options) error
- func GenerateLockID(dbName, schemaName string) int64
- func LintFormatGitHub(w io.Writer, diags []LintDiagnostic) error
- func LintFormatJSON(w io.Writer, diags []LintDiagnostic) error
- func LintFormatText(w io.Writer, diags []LintDiagnostic) error
- func LintHasErrors(diags []LintDiagnostic) bool
- func Seed(ctx context.Context, db *sql.DB, seedSQL string, opts ...Option) error
- func SeedHash(seedSQL string) string
- func Sync(ctx context.Context, db *sql.DB, opts Options) error
- type ApplyOpts
- type BackfillFunc
- type ChangeType
- type CheckConstraintIR
- type ColumnIR
- type DependencyRef
- type DestructiveViolationError
- type Dialect
- type DriftError
- type DropPolicy
- type DryRunResult
- type EnumIR
- type ExportArtifact
- type ExportFormat
- type ForeignKeyIR
- type GeneratedColumn
- type Hazard
- type HazardCode
- type HazardError
- type HazardLevel
- type HookContext
- type IndexIR
- type LintDiagnostic
- type LintRule
- type LintSeverity
- type Option
- func WithAcceptHazards(hazards ...plan.HazardCode) Option
- func WithAfterStep(fn StepHook) Option
- func WithAfterSync(fn SyncHook) Option
- func WithAllowDrop(allow bool) Option
- func WithBackfill(fn BackfillFunc) Option
- func WithBeforeStep(fn StepHook) Option
- func WithBeforeSync(fn SyncHook) Option
- func WithDialect(d Dialect) Option
- func WithDryRun() Option
- func WithDryRunLockTimeout(d time.Duration) Option
- func WithExcludeTables(tables ...string) Option
- func WithExecuteHooksInDryRun() Option
- func WithExpandContract(expand bool) Option
- func WithIncludeTables(tables ...string) Option
- func WithLockNamespace(ns string) Option
- func WithLockTimeout(d time.Duration) Option
- func WithLogger(l *slog.Logger) Option
- func WithMaxRetries(n int) Option
- func WithNonConcurrentIndexes(disabled bool) Option
- func WithRandFloat(fn func() float64) Option
- func WithRenames(renames map[string]string) Option
- func WithSQLiteRebuildBatching(threshold, batchSize int) Option
- func WithSeedForce(force bool) Option
- func WithSeedSQL(seedSQL string) Option
- func WithStatementTimeout(d time.Duration) Option
- func WithStrictScope(strict bool) Option
- func WithTargetSchema(schema string) Option
- func WithTargetSchemas(schemas ...string) Option
- func WithTracer(t Tracer) Option
- type Options
- type PartitionKey
- type PartitionOf
- type PartitionStrategy
- type Plan
- type PlanDocument
- type PrimaryKeyIR
- type SchemaIR
- type ScopeDocument
- type Span
- type Step
- type StepHook
- type SyncHook
- type TableIR
- type Tracer
- type UnmanagedKind
- type UnmanagedObject
Examples ¶
Constants ¶
const ( // PartitionStrategyRange indicates range-based partitioning. PartitionStrategyRange = schema.PartitionStrategyRange // PartitionStrategyList indicates list-based partitioning. PartitionStrategyList = schema.PartitionStrategyList // PartitionStrategyHash indicates hash-based partitioning. PartitionStrategyHash = schema.PartitionStrategyHash )
PartitionStrategy constants
const ( ChangeCreateEnum = plan.ChangeCreateEnum ChangeAlterEnum = plan.ChangeAlterEnum ChangeCreateTable = plan.ChangeCreateTable ChangeDropTable = plan.ChangeDropTable ChangeAddColumn = plan.ChangeAddColumn ChangeDropColumn = plan.ChangeDropColumn ChangeAlterColumn = plan.ChangeAlterColumn ChangeCreateIndex = plan.ChangeCreateIndex ChangeDropIndex = plan.ChangeDropIndex ChangeAddFK = plan.ChangeAddFK ChangeDropFK = plan.ChangeDropFK ChangeAddCheck = plan.ChangeAddCheck ChangeDropCheck = plan.ChangeDropCheck ChangeValidateConstraint = plan.ChangeValidateConstraint ChangeRenameColumn = plan.ChangeRenameColumn ChangeAttachPartition = plan.ChangeAttachPartition ChangeDetachPartition = plan.ChangeDetachPartition )
ChangeType constants
const ( HazardDropTable = plan.HazardDropTable HazardDropColumn = plan.HazardDropColumn HazardTypeNarrow = plan.HazardTypeNarrow HazardNotNullNoDefault = plan.HazardNotNullNoDefault HazardIndexBuild = plan.HazardIndexBuild HazardDropIndex = plan.HazardDropIndex HazardDropFK = plan.HazardDropFK HazardDropCheck = plan.HazardDropCheck HazardCheckValidateScan = plan.HazardCheckValidateScan HazardRenameAmbiguous = plan.HazardRenameAmbiguous HazardUnmanagedDependency = plan.HazardUnmanagedDependency HazardGeneratedRewrite = plan.HazardGeneratedRewrite HazardPartitionAttachScan = plan.HazardPartitionAttachScan HazardPartitionPendingDetach = plan.HazardPartitionPendingDetach )
HazardCode constants
const ( // UnmanagedView indicates a standard SQL VIEW. UnmanagedView = schema.UnmanagedView // UnmanagedMaterialized indicates a MATERIALIZED VIEW. UnmanagedMaterialized = schema.UnmanagedMaterialized // UnmanagedTrigger indicates a database trigger attached to a table. UnmanagedTrigger = schema.UnmanagedTrigger // UnmanagedFunction indicates a stored procedure or function. UnmanagedFunction = schema.UnmanagedFunction // UnmanagedSequence indicates an unmanaged database sequence. UnmanagedSequence = schema.UnmanagedSequence // UnmanagedEnum indicates an unmanaged custom enum type. UnmanagedEnum = schema.UnmanagedEnum // UnmanagedDomain indicates an unmanaged domain type. UnmanagedDomain = schema.UnmanagedDomain )
const ( HazardLevelCritical = plan.HazardLevelCritical HazardLevelWarning = plan.HazardLevelWarning HazardLevelNotice = plan.HazardLevelNotice )
HazardLevel constants
const ( // ExportFormatSQL targets raw SQL files with transaction markers. ExportFormatSQL = export.FormatSQL // ExportFormatGoose targets Goose-compatible migration files. ExportFormatGoose = export.FormatGoose // ExportFormatAtlas targets Atlas-compatible migration files. ExportFormatAtlas = export.FormatAtlas )
const ( // LintSeverityError marks a structural anti-pattern that must be fixed. LintSeverityError = lint.SeverityError // LintSeverityWarning marks a recommendation that may be ignored deliberately. LintSeverityWarning = lint.SeverityWarning // LintSeverityInfo marks a stylistic suggestion with no correctness impact. LintSeverityInfo = lint.SeverityInfo )
Variables ¶
var ( // ErrEmptySchema is returned when the provided SchemaSQL string is empty or contains only whitespace. ErrEmptySchema = plan.ErrEmptySchema // ErrDestructiveBlocked is returned when a destructive operation (such as DROP TABLE or DROP COLUMN) // is rejected by the configured drop safety policy. ErrDestructiveBlocked = plan.ErrDestructiveBlocked // ErrLockAcquisition is returned when acquiring the database advisory lock fails or times out. ErrLockAcquisition = plan.ErrLockAcquisition // ErrCompilationFailed is returned when the user's schema.sql fails to compile/execute inside the shadow schema. ErrCompilationFailed = plan.ErrCompilationFailed // ErrExecutionFailed is returned when applying the planned DDL migration steps to the target schema fails. ErrExecutionFailed = plan.ErrExecutionFailed // ErrInspectionFailed is returned when inspecting the schema metadata fails. ErrInspectionFailed = plan.ErrInspectionFailed // ErrUnsupportedDialect is returned when an unrecognized database driver or dialect is provided. ErrUnsupportedDialect = plan.ErrUnsupportedDialect // ErrHazardBlocked is returned when a migration plan contains critical hazards not explicitly accepted in AcceptHazards. ErrHazardBlocked = plan.ErrHazardBlocked // ErrPlanDrift is returned when the approved plan hash differs from the recomputed plan hash after lock acquisition. ErrPlanDrift = plan.ErrPlanDrift // ErrDrift is returned by Check when the live database schema differs from the desired schema. ErrDrift = plan.ErrDrift // ErrLockTimeout is returned when an advisory lock cannot be acquired within the configured lock timeout. ErrLockTimeout = plan.ErrLockTimeout // ErrInvalidOptions is returned when provided Options fail validation. ErrInvalidOptions = plan.ErrInvalidOptions // ErrStrictScope is returned when StrictScope is enabled but no IncludeTables are specified. ErrStrictScope = plan.ErrStrictScope // ErrPartitionConversion is returned when attempting to convert a regular table to a partitioned table or vice versa in-place. ErrPartitionConversion = plan.ErrPartitionConversion // ErrUnsupportedMultiSchema is returned when multiple schemas are configured on SQLite. ErrUnsupportedMultiSchema = plan.ErrUnsupportedMultiSchema // ErrPartitionKeyNotInUnique is returned when a primary key or unique constraint on a partitioned table does not include all partition key columns. ErrPartitionKeyNotInUnique = plan.ErrPartitionKeyNotInUnique // ErrAfterSyncFailed is returned when the AfterSync hook fails after the migration steps have already committed. ErrAfterSyncFailed = plan.ErrAfterSyncFailed // ErrSeedFailed is returned when seed SQL execution fails; the seed // transaction is rolled back and the schema is left intact. ErrSeedFailed = plan.ErrSeedFailed )
Functions ¶
func Apply ¶
Apply applies an approved migration plan to the database. If ExpectedHash is provided and the plan recomputed post-lock differs, Apply aborts with ErrPlanDrift.
func Check ¶
Check inspects the live database and returns ErrDrift (wrapped in DriftError) if the schema differs from the desired schema specified in opts.SchemaSQL. It is strictly read-only, never modifies the database, and never auto-fixes drift.
func GenerateLockID ¶
GenerateLockID produces a deterministic 64-bit integer lock ID from db and schema names.
func LintFormatGitHub ¶
func LintFormatGitHub(w io.Writer, diags []LintDiagnostic) error
LintFormatGitHub renders diagnostics as GitHub Actions annotations.
func LintFormatJSON ¶
func LintFormatJSON(w io.Writer, diags []LintDiagnostic) error
LintFormatJSON renders diagnostics as a JSON array.
func LintFormatText ¶
func LintFormatText(w io.Writer, diags []LintDiagnostic) error
LintFormatText renders diagnostics as human-readable text.
func LintHasErrors ¶
func LintHasErrors(diags []LintDiagnostic) bool
LintHasErrors reports whether any diagnostic has severity ERROR.
func Seed ¶
Seed executes idempotent seed SQL against the database. The seed runs in a single transaction: either the whole script commits with an 'applied' grizzle_history record keyed by the seed's content hash, or nothing persists. If the same seed hash was already applied and force is false, the seed is skipped. Forced re-runs execute the script again, so seed scripts should tolerate re-execution (IF NOT EXISTS, ON CONFLICT...).
Dialect and target schema are taken from opts (auto-detected when unset).
func SeedHash ¶
SeedHash returns the deterministic sha256 identity of a seed script. Leading and trailing whitespace is ignored so reformatted-but-identical seeds do not re-run.
func Sync ¶
Sync synchronizes the target database schema to match the desired state in opts.SchemaSQL.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"log"
"github.com/muandane/grizzle"
_ "modernc.org/sqlite"
)
func main() {
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
log.Fatalf("failed to open database: %v", err)
}
defer func() { _ = db.Close() }()
schema := `
CREATE TABLE users (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL
);`
err = grizzle.Sync(context.Background(), db, grizzle.Options{
Dialect: grizzle.DialectSQLite,
SchemaSQL: schema,
})
if err != nil {
log.Fatalf("sync failed: %v", err)
}
var count int
_ = db.QueryRow("SELECT count(*) FROM users;").Scan(&count)
fmt.Printf("Users table exists with row count: %d\n", count)
}
Output: Users table exists with row count: 0
Types ¶
type ApplyOpts ¶
type ApplyOpts struct {
// ExpectedHash is the approved plan hash. If non-empty, Apply recomputes the plan after
// acquiring the lock and verifies the recomputed hash matches ExpectedHash.
// If it does not match, Apply aborts with ErrPlanDrift.
ExpectedHash string
// AcceptHazards specifies explicitly accepted critical hazards.
AcceptHazards []HazardCode
// Backfill hook function run outside the DDL lock window in batches during staged expand migration.
Backfill BackfillFunc
// BeforeSync runs once before any migration steps or locks are executed.
BeforeSync SyncHook
// AfterSync runs once after all migration steps and history recording succeed.
AfterSync SyncHook
// BeforeStep executes immediately prior to executing each plan step.
BeforeStep StepHook
// AfterStep executes immediately following the successful execution of each plan step.
AfterStep StepHook
// SQLiteRebuildThreshold defines the row count threshold above which SQLite table rebuilds
// chunk data copying by keyset. Defaults to 100000.
SQLiteRebuildThreshold int
// SQLiteRebuildBatchSize defines the chunk size when copying data in batches during SQLite table rebuilds.
// Defaults to 10000.
SQLiteRebuildBatchSize int
// LockNamespace specifies the application namespace string used for PostgreSQL advisory locking (defaults to "grizzle").
LockNamespace string
// Tracer specifies an optional tracer for observing plan application.
Tracer Tracer
}
ApplyOpts configures verification and execution parameters when applying an approved Plan.
type BackfillFunc ¶
BackfillFunc defines the hook function signature for batch backfilling columns outside the DDL lock window.
type ChangeType ¶
type ChangeType = plan.ChangeType
ChangeType describes the classification of a schema change.
type CheckConstraintIR ¶
type CheckConstraintIR = schema.CheckConstraint
CheckConstraintIR represents the intermediate representation of a CHECK constraint.
type DependencyRef ¶
type DependencyRef = schema.DependencyRef
DependencyRef represents a reference to a table or column that an unmanaged object depends on.
type DestructiveViolationError ¶
type DestructiveViolationError = plan.DestructiveViolationError
DestructiveViolationError reports all destructive steps that were rejected by the active safety policy.
type DriftError ¶
type DriftError = plan.DriftError
DriftError reports unapplied differences between the live schema and the desired schema.
type DropPolicy ¶
type DropPolicy = plan.DropPolicy
DropPolicy defines the safety behavior for destructive drops.
type DryRunResult ¶
type DryRunResult = exec.DryRunResult
DryRunResult reports the outcome of a live dry-run verification.
func DryRunVerify ¶
DryRunVerify executes a live dry-run rollback against the target database: the planned DDL runs against real data inside transactions that are unconditionally rolled back, so constraints, casts, and check expressions are verified without persisting any change. Non-transactional steps (CREATE INDEX CONCURRENTLY, ALTER TYPE ... ADD VALUE, DETACH PARTITION CONCURRENTLY) are skipped and reported in DryRunResult.UnverifiedNonTx. No records are written to grizzle_history, and hooks do not run unless opts.ExecuteHooksInDryRun is set.
type ExportArtifact ¶
ExportArtifact represents a generated migration file ready to be saved.
func Export ¶
func Export(p *Plan, format ExportFormat, version string, timestamp ...time.Time) ([]ExportArtifact, error)
Export serializes the given plan into migration files for the requested tool format.
type ExportFormat ¶
ExportFormat defines supported target formats for migration export.
type ForeignKeyIR ¶
type ForeignKeyIR = schema.ForeignKey
ForeignKeyIR represents the intermediate representation of a foreign key relationship.
type GeneratedColumn ¶
type GeneratedColumn = schema.GeneratedColumn
GeneratedColumn describes a computed or generated column.
type HazardCode ¶
type HazardCode = plan.HazardCode
HazardCode identifies the specific type of migration hazard detected.
type HazardError ¶
type HazardError = plan.HazardError
HazardError reports all critical hazards that were not explicitly accepted.
type HazardLevel ¶
type HazardLevel = plan.HazardLevel
HazardLevel indicates the severity of potential data loss or downtime.
type HookContext ¶
type HookContext = exec.HookContext
HookContext provides invocation context and database access for a step hook. DBTX is bound to the executor of the pending step: a *sql.Tx for transactional groups or a *sql.Conn for non-transactional steps.
type LintDiagnostic ¶
type LintDiagnostic = lint.Diagnostic
LintDiagnostic is a single static lint finding against a schema element.
func LintSchema ¶
func LintSchema(s *SchemaIR, rules ...LintRule) []LintDiagnostic
LintSchema runs rules (defaulting to DefaultLintRules) against the compiled schema IR and returns deterministically sorted diagnostics.
type LintRule ¶
LintRule is a pure check executed against the desired schema IR.
func DefaultLintRules ¶
func DefaultLintRules() []LintRule
DefaultLintRules returns the built-in lint rule set (L001..L004).
type LintSeverity ¶
LintSeverity indicates how strongly a lint diagnostic should block a release.
type Option ¶
type Option func(*Options)
Option represents a functional option for configuring Options.
func WithAcceptHazards ¶
func WithAcceptHazards(hazards ...plan.HazardCode) Option
WithAcceptHazards configures explicitly accepted critical hazard codes.
func WithAfterStep ¶
WithAfterStep registers a hook that runs immediately after each successful plan step.
func WithAfterSync ¶
WithAfterSync registers a hook that runs once after all migration steps and history recording succeed.
func WithAllowDrop ¶
WithAllowDrop sets the general drop permission.
func WithBackfill ¶
func WithBackfill(fn BackfillFunc) Option
WithBackfill configures the batch backfill hook function for staged expand migrations.
Experimental: backfill batching semantics (batch size, ordering, error handling) may change before the 1.0 release. There is no CLI equivalent; backfill is library-only.
func WithBeforeStep ¶
WithBeforeStep registers a hook that runs immediately prior to each plan step.
func WithBeforeSync ¶
WithBeforeSync registers a hook that runs once before any migration steps or locks are executed.
func WithDryRun ¶
func WithDryRun() Option
WithDryRun enables dry-run mode: the planned SQL is validated against the live database without executing it.
func WithDryRunLockTimeout ¶
WithDryRunLockTimeout sets the lock wait bound for live dry-run verification.
func WithExcludeTables ¶
WithExcludeTables sets excluded tables and glob patterns.
func WithExecuteHooksInDryRun ¶
func WithExecuteHooksInDryRun() Option
WithExecuteHooksInDryRun allows BeforeStep/AfterStep hooks to run during live dry-run verification.
func WithExpandContract ¶
WithExpandContract enables or disables staged expand-and-contract zero-downtime migrations.
Experimental: staged expand-and-contract plans are under active development; the contract phase and hazard surface may change before the 1.0 release.
func WithIncludeTables ¶
WithIncludeTables sets included tables.
func WithLockNamespace ¶
WithLockNamespace sets the application namespace string for PostgreSQL advisory locks.
func WithLockTimeout ¶
WithLockTimeout sets the maximum duration to wait for acquiring locks.
func WithMaxRetries ¶
WithMaxRetries sets the maximum retry attempts upon lock timeout conflict (SQLSTATE 55P03).
func WithNonConcurrentIndexes ¶
WithNonConcurrentIndexes controls whether PostgreSQL index creation should run inside the transaction.
func WithRandFloat ¶
WithRandFloat sets a custom random float function for deterministic backoff jitter in tests.
func WithRenames ¶
WithRenames sets the explicit column rename mapping.
Experimental: the rename mapping format and RENAME_AMBIGUOUS semantics may change before the 1.0 release.
func WithSQLiteRebuildBatching ¶
WithSQLiteRebuildBatching sets the threshold and batch size for chunked keyset copying during SQLite rebuilds.
func WithSeedForce ¶
WithSeedForce re-runs the seed even when the same seed hash was already applied.
func WithSeedSQL ¶
WithSeedSQL attaches idempotent seed SQL executed after a successful sync.
func WithStatementTimeout ¶
WithStatementTimeout sets the maximum duration for any single migration DDL statement.
func WithStrictScope ¶
WithStrictScope enables strict scoping mode requiring non-empty IncludeTables.
func WithTargetSchema ¶
WithTargetSchema sets the target schema. Deprecated: Use WithTargetSchemas for multi-schema support.
func WithTargetSchemas ¶
WithTargetSchemas sets the target schemas to manage.
type Options ¶
type Options struct {
// Dialect explicitly defines the database engine (DialectPostgres or DialectSQLite).
Dialect Dialect
// SchemaSQL contains the complete DDL representing the desired state.
SchemaSQL string
// TargetSchema is the schema to manage (defaults to "public" for Postgres, "main" for SQLite).
// Deprecated: Use TargetSchemas for multi-schema support.
TargetSchema string
// TargetSchemas specifies the database schemas to manage (defaults to [TargetSchema] or ["public"] for Postgres).
TargetSchemas []string
// ShadowSchema is the temporary schema name used for validation (defaults to "_grizzle_shadow").
ShadowSchema string
// AllowDrop permits all destructive operations when set to true.
// Defaults to false for zero data loss.
AllowDrop bool
// Granular drop overrides (nil inherits from AllowDrop):
AllowDropTable *bool
AllowDropColumn *bool
AllowDropIndex *bool
AllowDropFK *bool
AllowDropCheck *bool
// ExcludeTables defines table names or glob patterns (e.g. "spatial_ref_sys", "asynq_*")
// that Grizzle will never manage, alter, or drop.
ExcludeTables []string
// IncludeTables limits Grizzle's management scope to only the specified tables or patterns.
IncludeTables []string
// StrictScope requires IncludeTables to be non-empty. When true and IncludeTables is empty,
// operations fail immediately with ErrStrictScope.
// Strongly recommended for production environments to avoid accidental alterations or drops
// of untracked tables.
StrictScope bool
// AcceptHazards lists critical hazard codes that are explicitly approved to execute.
// Critical hazards not present in this list will cause Apply to fail with ErrHazardBlocked.
AcceptHazards []plan.HazardCode
// NonConcurrentIndexes opts out of emitting CONCURRENTLY for PostgreSQL index creation/drops.
// When true, index operations are created inside the transaction.
NonConcurrentIndexes bool
// LockNamespace specifies the application namespace string used for PostgreSQL advisory locking (defaults to "grizzle").
LockNamespace string
// LockID is an optional explicit 64-bit integer used for the PostgreSQL advisory lock (pg_advisory_xact_lock).
// If 0, Grizzle derives 2-int per-schema advisory locks using (hash32(LockNamespace), hash32(schema)).
LockID int64
// LockTimeout specifies the maximum time to wait when acquiring locks (defaults to 5s).
LockTimeout time.Duration
// StatementTimeout specifies the maximum execution time for any single DDL statement (defaults to 5m).
StatementTimeout time.Duration
// MaxRetries specifies the number of retry attempts upon lock timeout (SQLSTATE 55P03, defaults to 3).
MaxRetries int
// RandFloat provides an optional random source func returning in [0.0, 1.0) for deterministic jitter in tests.
RandFloat func() float64
// Renames maps old column names to new column names (e.g. "users.old_col": "new_col" or "old_col": "new_col")
// to explicitly disambiguate column renames instead of treating them as DROP + ADD.
//
// Experimental: the rename mapping format and RENAME_AMBIGUOUS semantics
// may change before the 1.0 release.
Renames map[string]string
// ExpandContract enables staged expand-and-contract zero-downtime migrations (ZDM).
// In expand mode, renamed or modified columns are added alongside existing columns,
// delaying destructive drops to a later, separately approved plan.
//
// Experimental: staged expand-and-contract plans are under active development;
// the contract phase and hazard surface may change before the 1.0 release.
ExpandContract bool
// Backfill hook function run outside the DDL lock window in batches during staged expand migration.
//
// Experimental: backfill batching semantics (batch size, ordering, error
// handling) may change before the 1.0 release. There is no CLI equivalent;
// backfill is library-only.
Backfill BackfillFunc
// BeforeSync runs once before any migration steps or locks are executed.
// If it returns an error, the migration aborts before any DDL runs and no
// history record is written.
BeforeSync SyncHook
// AfterSync runs once after all migration steps and history recording succeed.
// If it returns an error, the DDL has already committed; the error is
// wrapped with ErrAfterSyncFailed.
AfterSync SyncHook
// BeforeStep executes immediately prior to executing each plan step.
// If it returns an error, the pending step is not executed; in a
// transactional group the transaction is rolled back and history records
// the failure with error "before_step hook: ...".
BeforeStep StepHook
// AfterStep executes immediately following the successful execution of each
// plan step. If it returns an error in a transactional group, the
// transaction is rolled back (reverting the step); in a non-transactional
// group the step has already committed and history records "partial".
AfterStep StepHook
// DryRun returns the planned SQL statements without executing them on the live database.
DryRun bool
// DryRunLockTimeout bounds how long live dry-run verification waits on
// table locks before failing fast (defaults to 2s).
DryRunLockTimeout time.Duration
// ExecuteHooksInDryRun allows BeforeStep/AfterStep hooks to run during
// live dry-run verification. Defaults to false to avoid accidental
// external side effects (webhooks, message publishing, etc.).
ExecuteHooksInDryRun bool
// SeedSQL contains idempotent data-seed SQL executed after a successful
// sync (Sync DDL → AfterSync → Seed). The seed runs in a single
// transaction and is skipped when the same seed (by content hash) was
// already applied, unless SeedForce is set.
SeedSQL string
// SeedForce re-runs the seed even when the same seed hash was already
// applied.
SeedForce bool
// SQLiteRebuildThreshold defines the row count threshold above which SQLite table rebuilds
// chunk data copying by keyset to prevent journal memory exhaustion.
// Defaults to 100000. Set to 0 to disable batching.
SQLiteRebuildThreshold int
// SQLiteRebuildBatchSize defines the chunk size when copying data in batches during SQLite table rebuilds.
// Defaults to 10000.
SQLiteRebuildBatchSize int
// Logger accepts a structured logger (*slog.Logger) for migration events.
Logger *slog.Logger
// Tracer specifies an optional tracer (OpenTelemetry or custom) for observing migrations.
Tracer Tracer
}
Options configures the schema synchronization process.
type PartitionKey ¶
type PartitionKey = schema.PartitionKey
PartitionKey defines how a partitioned table is divided.
type PartitionOf ¶
type PartitionOf = schema.PartitionOf
PartitionOf defines the relationship of a partition table to its parent partitioned table.
type PartitionStrategy ¶
type PartitionStrategy = schema.PartitionStrategy
PartitionStrategy represents the partitioning method used by a partitioned table.
type Plan ¶
Plan is the complete migration plan containing sequenced steps, policy, and hashes.
func ParsePlanJSON ¶
ParsePlanJSON parses a serialized plan JSON string or bytes into a *Plan, returning the recorded plan hash.
func PlanDiff ¶
PlanDiff inspects the live database and computes the planned migration steps without applying them.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"log"
"github.com/muandane/grizzle"
_ "modernc.org/sqlite"
)
func main() {
db, err := sql.Open("sqlite", ":memory:")
if err != nil {
log.Fatalf("failed to open database: %v", err)
}
defer func() { _ = db.Close() }()
schema := `
CREATE TABLE products (
id INTEGER PRIMARY KEY,
sku TEXT NOT NULL UNIQUE,
price INTEGER NOT NULL DEFAULT 0
);`
plan, err := grizzle.PlanDiff(context.Background(), db, grizzle.Options{
Dialect: grizzle.DialectSQLite,
SchemaSQL: schema,
})
if err != nil {
log.Fatalf("plan diff failed: %v", err)
}
fmt.Printf("Plan steps to execute: %d\n", len(plan.Steps))
}
Output: Plan steps to execute: 1
type PlanDocument ¶
PlanDocument represents a complete, serialized migration plan artifact including hash, hazards, scope, and options digest.
type PrimaryKeyIR ¶
type PrimaryKeyIR = schema.PrimaryKey
PrimaryKeyIR represents the intermediate representation of a table primary key.
type SchemaIR ¶
SchemaIR represents the database-agnostic schema intermediate representation.
func CompileSchema ¶
CompileSchema compiles opts.SchemaSQL into the desired SchemaIR without diffing or executing anything. For PostgreSQL the compilation happens in the shadow schema inside an always-rolled-back transaction (requires a connection to the target database); for SQLite it happens in an in-memory database, making it fully offline.
type ScopeDocument ¶
type ScopeDocument = plan.ScopeDocument
ScopeDocument represents the scope section of a plan document.
type StepHook ¶
StepHook executes custom imperative code immediately before or after each plan step. Hooks must be idempotent: if a later step fails and the migration is retried or resumed after partial execution, hooks may be invoked again.
type SyncHook ¶
SyncHook executes custom imperative code once before or after the entire synchronization. It receives a dedicated connection (not a transaction) because the execution may contain non-transactional statements.
type UnmanagedKind ¶
type UnmanagedKind = schema.UnmanagedKind
UnmanagedKind represents the category of an unmanaged database object.
type UnmanagedObject ¶
type UnmanagedObject = schema.UnmanagedObject
UnmanagedObject represents an unmanaged database object detected during introspection.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
grizzle
command
Package main implements the grizzle CLI.
|
Package main implements the grizzle CLI. |
|
examples
|
|
|
expand-contract
command
Package main demonstrates zero-downtime expand/contract migrations with Grizzle: a column rename executed in two separately-approved stages with a library-side backfill between them.
|
Package main demonstrates zero-downtime expand/contract migrations with Grizzle: a column rename executed in two separately-approved stages with a library-side backfill between them. |
|
postgres-pgxpool
command
|
|
|
postgres-stdlib
command
|
|
|
sqlc-workflow
command
|
|
|
sqlc-workflow/db
Package db provides type-safe database queries.
|
Package db provides type-safe database queries. |
|
sqlite-embedded
command
|
|
|
Package griztest provides testing utilities and ergonomic primitives for testing applications powered by Grizzle schema migrations.
|
Package griztest provides testing utilities and ergonomic primitives for testing applications powered by Grizzle schema migrations. |
|
internal
|
|
|
dialect
Package dialect defines the interface for database-specific introspection, DDL rendering, and transactional locking behaviors.
|
Package dialect defines the interface for database-specific introspection, DDL rendering, and transactional locking behaviors. |
|
dialect/postgres
Package postgres implements PostgreSQL-specific introspection, DDL rendering, advisory locking, and shadow schema compilation.
|
Package postgres implements PostgreSQL-specific introspection, DDL rendering, advisory locking, and shadow schema compilation. |
|
dialect/sqlite
Package sqlite implements SQLite-specific schema introspection, in-memory shadow validation, and the 12-step table rebuild engine.
|
Package sqlite implements SQLite-specific schema introspection, in-memory shadow validation, and the 12-step table rebuild engine. |
|
diff
Package diff performs pure relational comparison between live and desired database schemas.
|
Package diff performs pure relational comparison between live and desired database schemas. |
|
exec
Package exec coordinates statement execution, transactional locking, and safety policy enforcement.
|
Package exec coordinates statement execution, transactional locking, and safety policy enforcement. |
|
history
Package history manages migration history records and schema drift tracking.
|
Package history manages migration history records and schema drift tracking. |
|
lint
Package lint provides static, database-free linting of a desired schema IR.
|
Package lint provides static, database-free linting of a desired schema IR. |
|
plan
Package plan models migration steps, execution plans, safety policies, and hazard detection.
|
Package plan models migration steps, execution plans, safety policies, and hazard detection. |
|
schema
Package schema defines the pure, engine-agnostic relational schema representation (Table, Column, Index, Constraint, Schema) and normalization logic.
|
Package schema defines the pure, engine-agnostic relational schema representation (Table, Column, Index, Constraint, Schema) and normalization logic. |
|
scope
Package scope handles table filtering and unmanaged-table boundaries (PostGIS, background queues, and user-specified include/exclude patterns).
|
Package scope handles table filtering and unmanaged-table boundaries (PostGIS, background queues, and user-specified include/exclude patterns). |
|
testutil
Package testutil provides shared test infrastructure for integration tests.
|
Package testutil provides shared test infrastructure for integration tests. |
|
otelgrizzle
module
|