grizzle

package module
v0.1.0-rc3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

README

Grizzle

CI Go Reference License

Declarative schema migrations for Go.

Point Grizzle at your plain schema.sql, and it diffs and migrates your database on boot. No numbered migration files (001_init.sql), no external migration binaries inside your production containers.

  • Safe by default: Destructive drops are blocked unless explicitly allowed.
  • Production-safe DDL: Builds PostgreSQL indexes CONCURRENTLY and creates foreign keys as NOT VALID before validating.
  • Cluster-safe: Uses PostgreSQL session advisory locks so multi-pod deployments won't collide.
  • Engine support: PostgreSQL (14–18) and SQLite (3.35+, pure-Go or CGo).
  • Works with sqlc: Share one schema.sql between sqlc and Grizzle.

Quickstart

Embed your desired schema and run Sync on application startup:

-- schema.sql
CREATE TABLE users (
    id         BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    email      VARCHAR(255) NOT NULL UNIQUE,
    full_name  TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_users_created_at ON users (created_at);

Note: Grizzle supports both SERIAL and standard-compliant identity columns, but recommends GENERATED ALWAYS AS IDENTITY for new tables (see SAFETY.md).

package main

import (
	"context"
	"database/sql"
	_ "embed"
	"log"
	"time"

	_ "github.com/jackc/pgx/v5/stdlib"
	"github.com/muandane/grizzle"
)

//go:embed schema.sql
var schemaSQL string

func main() {
	db, err := sql.Open("pgx", "postgres://postgres:secret@localhost:5432/myapp?sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Bring the database in line with schema.sql
	err = grizzle.Sync(context.Background(), db, grizzle.Options{
		SchemaSQL:        schemaSQL,
		AllowDrop:        false, // Fails if the diff would drop columns or tables
		LockTimeout:      5 * time.Second,
		StatementTimeout: 2 * time.Minute,
	})
	if err != nil {
		log.Fatalf("migration failed: %v", err)
	}
}

Need approval gates? Instead of auto-syncing on boot, use grizzle.PlanDiff(...) to generate a migration plan, review the SQL, then grizzle.Apply(..., grizzle.ApplyOpts{ExpectedHash: plan.Hash()}) so apply aborts if the live database drifted.


CLI

Use the CLI for CI drift checks, dry runs, or exporting plans to standard migration tools:

# Preview changes and generate a migration plan
grizzle plan --dsn "$DATABASE_URL" --schema schema.sql --out plan.json

# Apply a generated plan safely
grizzle apply --dsn "$DATABASE_URL" --plan plan.json

# Fail CI if live DB has drifted from schema.sql (exits with code 4)
grizzle check --dsn "$DATABASE_URL" --schema schema.sql

# Convert a plan to Goose migrations if you need an exit hatch
grizzle export --plan plan.json --format goose --out ./migrations
Exit Codes
Code Meaning
0 Success / database is in sync
1 Connection or execution error
2 Blocked by an unaccepted hazard (e.g., unexpected DROP)
3 Plan hash mismatch (live database changed after plan was generated)
4 Schema drift detected (grizzle check)

Supported Features

PostgreSQL (14–18)
Object Category Managed Constructs (Declarative Lifecycle) Protected-Only / Invariant
Tables & Columns CREATE/DROP TABLE, ADD/DROP/RENAME COLUMN, type conversions (USING), nullability, defaults, generated columns (STORED), partitioned tables (declarative attach/detach). Identity/serial sequences (deptype = 'i') preserved; full validation scans flagged; unmanaged tables outside scope untouched.
Indexes & Constraints CREATE INDEX CONCURRENTLY, partial/unique/expression/BRIN/GIN/GiST indexes; Foreign keys (NOT VALID + VALIDATE), CHECK constraints (staged validation, normalized expressions). Primary key / unique constraint backing indexes are managed via table/constraint definition.
Data Types Enums (CREATE/ADD VALUE/RENAME VALUE), Domains (CHECK constraint alteration), Custom Range Types (CREATE/DROP), Composite Types (CREATE/ALTER ATTRIBUTE/DROP). System types; extension-provided types (deptype = 'e'); dropped enum labels emit DROP_ENUM_VALUE critical hazard.
Sequences Standalone CREATE SEQUENCE declared in schema SQL, parameters (INCREMENT, MIN/MAXVALUE, CACHE, CYCLE), ownership (OWNED BY table.col vs NONE), DROP SEQUENCE IF EXISTS. Implicit identity/serial sequences (deptype = 'i'); external unmanaged sequences are never auto-dropped.
Routines & Triggers Functions & Procedures (CREATE OR REPLACE, signature drift drop/recreate), Triggers (per-table trigger defs), User-defined aggregates (CREATE AGGREGATE). Built-in routines; extension-owned functions (deptype = 'e'); window functions (prokind = 'w'); ordered-set / hypothetical aggregates (aggkind != 'd').
Views Views (CREATE OR REPLACE for append-only columns, drop/create for structural alterations), Materialized Views (drop/recreate + refresh). System catalogs / unmanaged views.
Security & Access Row-Level Security (ENABLE/FORCE), RLS Policies (in-place ALTER POLICY for roles/USING/WITH CHECK, drop/create for command), Roles & Grants (via RolesSQL / SchemaSQL). Unmanaged roles; grants to PUBLIC or unmanaged roles are never revoked; marker comment grizzle-managed required to drop roles.
Cluster & Replication Extensions (CREATE EXTENSION), Logical Publications, Subscriptions, Logical Replication Slots, DDL Event Triggers (via CatalogSQL / SchemaSQL). Physical replication slots; unmanaged cluster triggers/publications without grizzle-managed marker comment.

[!NOTE] API & Hash Stability: Options.Renames, Options.ExpandContract, and Options.Backfill API shapes and Plan.Hash() inputs are frozen across the rc line (stable, no longer experimental). Plan hashes remain strictly deterministic across versions. Full catalog queries, hazard taxonomy, and engine details are documented in docs/SPEC.md.

SQLite (3.35+)
  • Tables, columns, foreign keys, CHECK constraints, and generated columns.
  • Automatic 12-step table rebuilds for schema changes SQLite cannot execute in-place via ALTER TABLE.
  • Supports both modernc.org/sqlite (pure Go) and mattn/go-sqlite3 (CGo).
  • SQLite does not support COMMENT ON or Row-Level Security (ENABLE ROW LEVEL SECURITY, CREATE POLICY); comments are ignored (no catalog metadata) and RLS is PostgreSQL-only.

Important Operational Notes

  • PgBouncer / Connection Poolers: Grizzle relies on session-level advisory locks to prevent concurrent migrations. Connect directly to Postgres or use Session Pooling. Do not run migrations through Transaction Pooling.
  • Destructive Changes: Dropping tables/columns requires AllowDrop: true (or --allow-drop in the CLI). See docs/SAFETY.md for full hazard handling.

Examples

Documentation

  • SPEC — Supported SQL constructs and engine details
  • SAFETY — Hazards, data safety rules, and drop policies
  • ARCHITECTURE — Internal planner and execution flow
  • CONTRIBUTING — devenv, hooks, PR checklist
  • CHANGELOG

Current tag: v0.1.0-rc3.

License

Apache 2.0. See LICENSE.

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

Examples

Constants

View Source
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

View Source
const (
	ChangeCreateEnum          = plan.ChangeCreateEnum
	ChangeAlterEnum           = plan.ChangeAlterEnum
	ChangeRenameEnumValue     = plan.ChangeRenameEnumValue
	ChangeDropEnumValue       = plan.ChangeDropEnumValue
	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
	ChangeCreateExtension     = plan.ChangeCreateExtension
	ChangeDropExtension       = plan.ChangeDropExtension
	ChangeEnableRLS           = plan.ChangeEnableRLS
	ChangeDisableRLS          = plan.ChangeDisableRLS
	ChangeForceRLS            = plan.ChangeForceRLS
	ChangeNoForceRLS          = plan.ChangeNoForceRLS
	ChangeCreatePolicy        = plan.ChangeCreatePolicy
	ChangeAlterPolicy         = plan.ChangeAlterPolicy
	ChangeDropPolicy          = plan.ChangeDropPolicy
	ChangeCreateFunction      = plan.ChangeCreateFunction
	ChangeDropFunction        = plan.ChangeDropFunction
	ChangeCreateTrigger       = plan.ChangeCreateTrigger
	ChangeDropTrigger         = plan.ChangeDropTrigger
	ChangeCreateView          = plan.ChangeCreateView
	ChangeDropView            = plan.ChangeDropView
	ChangeRefreshMatView      = plan.ChangeRefreshMatView
	ChangeCreateRangeType     = plan.ChangeCreateRangeType
	ChangeDropRangeType       = plan.ChangeDropRangeType
	ChangeDropRangeRetype     = plan.ChangeDropRangeRetype
	ChangeCreateCompositeType = plan.ChangeCreateCompositeType
	ChangeAlterCompositeType  = plan.ChangeAlterCompositeType
	ChangeDropCompositeType   = plan.ChangeDropCompositeType
	ChangeDropCompositeRetype = plan.ChangeDropCompositeRetype
	ChangeCreateSequence      = plan.ChangeCreateSequence
	ChangeAlterSequence       = plan.ChangeAlterSequence
	ChangeDropSequence        = plan.ChangeDropSequence
)

ChangeType constants

View Source
const (
	HazardDropTable              = plan.HazardDropTable
	HazardDropColumn             = plan.HazardDropColumn
	HazardDropEnumValue          = plan.HazardDropEnumValue
	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
	HazardExtensionPrivilege     = plan.HazardExtensionPrivilege
	HazardDropExtension          = plan.HazardDropExtension
	HazardRLSEnable              = plan.HazardRLSEnable
	HazardDropPolicy             = plan.HazardDropPolicy
	HazardDropFunction           = plan.HazardDropFunction
	HazardSecurityDefiner        = plan.HazardSecurityDefiner
	HazardDropTrigger            = plan.HazardDropTrigger
	HazardDropView               = plan.HazardDropView
	HazardDropDomain             = plan.HazardDropDomain
	HazardDropRangeType          = plan.HazardDropRangeType
	HazardDropCompositeType      = plan.HazardDropCompositeType
	HazardDropSequence           = plan.HazardDropSequence
)

HazardCode constants

View Source
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
)
View Source
const (
	HazardLevelCritical = plan.HazardLevelCritical
	HazardLevelWarning  = plan.HazardLevelWarning
	HazardLevelNotice   = plan.HazardLevelNotice
)

HazardLevel constants

View Source
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
)
View Source
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

View Source
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 CompileSchema cannot compile
	// multiple PostgreSQL schemas in one shadow (SQLite multi-schema uses ATTACH).
	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

	// ErrHistoryRecord is returned when the migration succeeded but the
	// grizzle_history record could not be written (non-fatal; detect with
	// errors.Is).
	ErrHistoryRecord = plan.ErrHistoryRecord
)

Functions

func Apply

func Apply(ctx context.Context, db *sql.DB, p *Plan, opts ApplyOpts) error

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 BuildIdempotentInsert

func BuildIdempotentInsert(table string, columns []string, conflictTarget string, updateColumns ...string) string

BuildIdempotentInsert builds a canonical idempotent INSERT statement skeleton with conflict handling for seed data.

Formats: INSERT INTO "table" ("col1", "col2") VALUES ... ON CONFLICT ...

  • If conflictTarget == "": appends ON CONFLICT DO NOTHING;
  • If conflictTarget != "" and len(updateColumns) == 0: appends ON CONFLICT (<conflictTarget>) DO NOTHING;
  • If conflictTarget != "" and len(updateColumns) > 0: appends ON CONFLICT (<conflictTarget>) DO UPDATE SET <col> = EXCLUDED.<col>, ...;

Standard Idempotent Seed Patterns:

  1. Unconditional ignore (blank conflictTarget): Useful when unique constraints or primary keys should silently prevent duplicates without needing specific target specification. Example: BuildIdempotentInsert("roles", []string{"name"}, "") // Output: INSERT INTO "roles" ("name") VALUES ... ON CONFLICT DO NOTHING;

  2. Targeted ignore (conflictTarget specified, no updateColumns): Ignores conflict on a specific key or unique constraint. Example: BuildIdempotentInsert("users", []string{"id", "email"}, "id") // Output: INSERT INTO "users" ("id", "email") VALUES ... ON CONFLICT (id) DO NOTHING;

  3. Upsert / update on conflict (conflictTarget and updateColumns specified): Updates specified mutable columns from EXCLUDED values on conflict. Example: BuildIdempotentInsert("users", []string{"id", "name", "email"}, "id", "name", "email") // Output: INSERT INTO "users" ("id", "name", "email") VALUES ... ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name, email = EXCLUDED.email;

func Check

func Check(ctx context.Context, db *sql.DB, opts Options) error

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

func GenerateLockID(dbName, schemaName string) int64

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

func Seed(ctx context.Context, db *sql.DB, seedSQL string, opts ...Option) error

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

func SeedHash(seedSQL string) string

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

func Sync(ctx context.Context, db *sql.DB, opts Options) error

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

	// SQLiteAttach maps ATTACH DATABASE schema names to filesystem paths for
	// multi-schema SQLite Apply. Not carried in the plan artifact.
	SQLiteAttach map[string]string

	// LockNamespace specifies the application namespace string used for PostgreSQL advisory locking (defaults to "grizzle").
	LockNamespace string

	// Logger receives structured migration logs during Apply (defaults to no logging).
	// The plan artifact cannot carry a logger, so it is supplied here.
	Logger *slog.Logger

	// Tracer specifies an optional tracer for observing plan application.
	Tracer Tracer
}

ApplyOpts configures verification and execution parameters when applying an approved Plan.

type BackfillFunc

type BackfillFunc func(ctx context.Context, tx *sql.Tx, table, oldCol, newCol string) error

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 ColumnIR

type ColumnIR = schema.Column

ColumnIR represents the intermediate representation of a database column.

type CompositeAttributeIR

type CompositeAttributeIR = schema.CompositeAttribute

CompositeAttributeIR represents the intermediate representation of an attribute in a composite type.

type CompositeTypeIR

type CompositeTypeIR = schema.CompositeType

CompositeTypeIR represents the intermediate representation of a composite type.

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 Dialect

type Dialect string

Dialect specifies the target SQL database dialect.

const (
	// DialectAuto instructs Grizzle to auto-detect the engine from the driver type.
	DialectAuto Dialect = ""
	// DialectPostgres specifies PostgreSQL (14+; CI-tested through 18).
	DialectPostgres Dialect = "postgres"
	// DialectSQLite specifies SQLite (3.35+).
	DialectSQLite Dialect = "sqlite"
)

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

func DryRunVerify(ctx context.Context, db *sql.DB, opts Options) (*DryRunResult, error)

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.

func DryRunVerifyPlan

func DryRunVerifyPlan(ctx context.Context, db *sql.DB, p *Plan, opts ApplyOpts) (*DryRunResult, error)

DryRunVerifyPlan performs a live dry-run of an approved plan artifact. It verifies the artifact hash against ExpectedHash, honors every plan-carried intent field (target schemas, scope, policy, execution semantics), and checks that a re-diff of the live database against the artifact's SchemaSQL still produces the same plan hash — so a tampered or drifted artifact cannot silently verify a different migration. Runtime-only options (logger, tracer, hazards, lock namespace) come from opts.

type EnumIR

type EnumIR = schema.Enum

EnumIR represents the intermediate representation of an enum type.

type ExportArtifact

type ExportArtifact = export.Artifact

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

type ExportFormat = export.Format

ExportFormat defines supported target formats for migration export.

type ExtensionIR

type ExtensionIR = schema.Extension

ExtensionIR represents the intermediate representation of a PostgreSQL extension.

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 Hazard

type Hazard = plan.Hazard

Hazard describes an operation that could cause data loss or service disruption.

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 IndexIR

type IndexIR = schema.Index

IndexIR represents the intermediate representation of a database index.

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.

func LintSeed

func LintSeed(seedSQL string) []LintDiagnostic

LintSeed inspects seed SQL statements for idempotency and safety issues (such as bare INSERTs without conflict guards, TRUNCATE, or unconditional DELETE) and returns deterministically sorted diagnostics.

type LintRule

type LintRule = lint.Rule

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..L013).

type LintSeverity

type LintSeverity = lint.Severity

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

func WithAfterStep(fn StepHook) Option

WithAfterStep registers a hook that runs immediately after each successful plan step.

func WithAfterSync

func WithAfterSync(fn SyncHook) Option

WithAfterSync registers a hook that runs once after all migration steps and history recording succeed.

func WithAllowDrop

func WithAllowDrop(allow bool) Option

WithAllowDrop sets the general drop permission.

func WithBackfill

func WithBackfill(fn BackfillFunc) Option

WithBackfill configures the batch backfill hook function for staged expand migrations. The CLI also installs a hook via --backfill / --backfill-file; a library Backfill wins when both are configured by the caller.

func WithBeforeStep

func WithBeforeStep(fn StepHook) Option

WithBeforeStep registers a hook that runs immediately prior to each plan step.

func WithBeforeSync

func WithBeforeSync(fn SyncHook) Option

WithBeforeSync registers a hook that runs once before any migration steps or locks are executed.

func WithDialect

func WithDialect(d Dialect) Option

WithDialect sets the database dialect.

func WithDryRun

func WithDryRun() Option

WithDryRun enables dry-run mode: the planned SQL is validated against the live database without executing it.

func WithDryRunLockTimeout

func WithDryRunLockTimeout(d time.Duration) Option

WithDryRunLockTimeout sets the lock wait bound for live dry-run verification.

func WithExcludeTables

func WithExcludeTables(tables ...string) Option

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

func WithExpandContract(expand bool) Option

WithExpandContract enables or disables staged expand-and-contract zero-downtime migrations.

func WithIncludeTables

func WithIncludeTables(tables ...string) Option

WithIncludeTables sets included tables.

func WithLockNamespace

func WithLockNamespace(ns string) Option

WithLockNamespace sets the application namespace string for PostgreSQL advisory locks.

func WithLockTimeout

func WithLockTimeout(d time.Duration) Option

WithLockTimeout sets the maximum duration to wait for acquiring locks.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the structured logger.

func WithMaxRetries

func WithMaxRetries(n int) Option

WithMaxRetries sets the maximum retry attempts upon lock timeout conflict (SQLSTATE 55P03).

func WithNonConcurrentIndexes

func WithNonConcurrentIndexes(disabled bool) Option

WithNonConcurrentIndexes controls whether PostgreSQL index creation should run inside the transaction.

func WithRandFloat

func WithRandFloat(fn func() float64) Option

WithRandFloat sets a custom random float function for deterministic backoff jitter in tests.

func WithRenames

func WithRenames(renames map[string]string) Option

WithRenames sets the explicit column rename mapping. Keys are `table.old` or `old`; values are the new column name.

func WithSQLiteAttach

func WithSQLiteAttach(attach map[string]string) Option

WithSQLiteAttach sets the SQLite ATTACH DATABASE map (schema name → path).

func WithSQLiteRebuildBatching

func WithSQLiteRebuildBatching(threshold, batchSize int) Option

WithSQLiteRebuildBatching sets the threshold and batch size for chunked keyset copying during SQLite rebuilds.

func WithSeedForce

func WithSeedForce(force bool) Option

WithSeedForce re-runs the seed even when the same seed hash was already applied.

func WithSeedSQL

func WithSeedSQL(seedSQL string) Option

WithSeedSQL attaches idempotent seed SQL executed after a successful sync.

func WithStatementTimeout

func WithStatementTimeout(d time.Duration) Option

WithStatementTimeout sets the maximum duration for any single migration DDL statement.

func WithStrictScope

func WithStrictScope(strict bool) Option

WithStrictScope enables strict scoping mode requiring non-empty IncludeTables.

func WithTargetSchema

func WithTargetSchema(schema string) Option

WithTargetSchema sets the target schema. Deprecated: Use WithTargetSchemas for multi-schema support.

func WithTargetSchemas

func WithTargetSchemas(schemas ...string) Option

WithTargetSchemas sets the target schemas to manage.

func WithTracer

func WithTracer(t Tracer) Option

WithTracer sets the tracer.

type Options

type Options struct {
	// Dialect explicitly defines the database engine (DialectPostgres or DialectSQLite).
	Dialect Dialect

	// SchemaSQL contains the complete desired state. PostgreSQL role and
	// catalog statements may share this file; they bypass shadow compilation
	// and are merged with the optional side-channel files.
	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).
	// For SQLite, entries other than "main" are ATTACH DATABASE schema names listed in SQLiteAttach.
	TargetSchemas []string

	// SQLiteAttach maps ATTACH DATABASE schema names to filesystem paths.
	// Every TargetSchemas entry other than "main" must appear here; "main" is
	// the primary database already open and must not be listed. Unknown keys,
	// empty paths, and duplicate names are rejected. PostgreSQL ignores this field.
	SQLiteAttach map[string]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

	// AllowRevoke permits privilege revocation when a grant in RolesSQL is
	// removed (access loss). Has no granular override; REVOKE_PRIVILEGE
	// (CRITICAL) still requires AcceptHazards.
	AllowRevoke bool

	// AllowDropRole permits dropping a managed role that left RolesSQL.
	// Has no granular override; DROP_ROLE (CRITICAL) still requires
	// AcceptHazards.
	AllowDropRole bool

	// AllowDropPublication permits dropping a managed publication that
	// left CatalogSQL. Has no granular override; DROP_PUBLICATION
	// (CRITICAL) still requires AcceptHazards.
	AllowDropPublication bool

	// AllowDropEventTrigger permits dropping a managed event trigger that
	// left CatalogSQL. Has no granular override; DROP_EVENT_TRIGGER
	// (CRITICAL) still requires AcceptHazards.
	AllowDropEventTrigger bool

	// AllowDropSubscription permits dropping a managed subscription that
	// left CatalogSQL. Has no granular override; DROP_SUBSCRIPTION
	// (CRITICAL) still requires AcceptHazards. Remote slots are kept
	// (DISABLE + SET slot_name = NONE before DROP).
	AllowDropSubscription bool

	// AllowDropReplicationSlot permits dropping a standalone logical
	// replication slot via explicit SELECT pg_drop_replication_slot.
	// Live-only slots are never swept. DROP_REPLICATION_SLOT (CRITICAL)
	// still requires AcceptHazards. Active slots (active_pid IS NOT NULL)
	// are refused.
	AllowDropReplicationSlot bool

	// Granular drop overrides (nil inherits from AllowDrop):
	AllowDropTable         *bool
	AllowDropColumn        *bool
	AllowDropIndex         *bool
	AllowDropFK            *bool
	AllowDropCheck         *bool
	AllowDropExtension     *bool
	AllowDropFunction      *bool
	AllowDropPolicy        *bool
	AllowDropTrigger       *bool
	AllowDropView          *bool
	AllowDropDomain        *bool
	AllowDropType          *bool
	AllowDropRangeType     *bool
	AllowDropCompositeType *bool
	AllowDropSequence      *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.
	// Keys are `table.old` or `old`; values are the new column name.
	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.
	ExpandContract bool

	// Backfill hook function run outside the DDL lock window in batches during staged expand migration.
	// The CLI installs a hook via --backfill / --backfill-file when --expand-contract is set; a library
	// Backfill still wins when both are configured by the caller.
	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

	// RolesSQL optionally supplies desired roles and privilege grants
	// alongside SchemaSQL. Duplicate role/grant identities in this explicit
	// side-channel override entries extracted from SchemaSQL. Role statements
	// are never shadow-compiled, and schema DDL is not valid here. Managed
	// attributes include LOGIN/NOLOGIN, PASSWORD, VALID UNTIL, CONNECTION
	// LIMIT, INHERIT, CREATEDB, CREATEROLE, and ALTER ROLE SET/RESET.
	// SUPERUSER/REPLICATION/BYPASSRLS are refused. Passwords are compared by
	// server-side hash equality and never written into Step.SQL or plan JSON.
	// PostgreSQL only — ignored on SQLite.
	RolesSQL string

	// CatalogSQL optionally supplies desired cluster-catalog objects alongside
	// SchemaSQL. Duplicate publication/event-trigger names in this explicit
	// side-channel override entries extracted from SchemaSQL. Catalog
	// statements are never shadow-compiled or run inside the shadow
	// transaction, and schema DDL is not valid here. Drops are narrow — only
	// marker-stamped (grizzle-managed) objects are considered. Event triggers
	// reference functions that must exist in SchemaSQL or as live objects.
	// PostgreSQL only — rejected on SQLite.
	CatalogSQL string

	// 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.

func (*Options) Validate

func (o *Options) Validate() error

Validate is the canonical pure validation entry point for Options. It checks SchemaSQL, strict scope, dialect value, target/shadow identifiers, timeout and retry bounds, SQLite rebuild parameters, and multi-schema SQLite rejection. Dialect-specific checks are skipped while Dialect is DialectAuto (prepareOptions detects the dialect then re-validates). Defaults are applied by prepareOptions after Validate succeeds — Validate never mutates Options.

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

type Plan = plan.Plan

Plan is the complete migration plan containing sequenced steps, policy, and hashes.

func ParsePlanJSON

func ParsePlanJSON(data []byte) (*Plan, string, error)

ParsePlanJSON parses a serialized plan JSON string or bytes into a *Plan, returning the recorded plan hash.

func PlanDiff

func PlanDiff(ctx context.Context, db *sql.DB, opts Options) (*Plan, error)

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

type PlanDocument = plan.Document

PlanDocument represents a complete, serialized migration plan artifact including hash, hazards, scope, and options digest.

type PolicyIR

type PolicyIR = schema.Policy

PolicyIR represents the intermediate representation of a row-level security policy.

type PrimaryKeyIR

type PrimaryKeyIR = schema.PrimaryKey

PrimaryKeyIR represents the intermediate representation of a table primary key.

type RangeTypeIR

type RangeTypeIR = schema.RangeType

RangeTypeIR represents the intermediate representation of a range type.

type RoutineIR

type RoutineIR = schema.Routine

RoutineIR represents the intermediate representation of a function or procedure.

type SchemaIR

type SchemaIR = schema.Schema

SchemaIR represents the database-agnostic schema intermediate representation.

func CompileSchema

func CompileSchema(ctx context.Context, db *sql.DB, opts Options) (*SchemaIR, error)

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 SequenceIR

type SequenceIR = schema.Sequence

SequenceIR represents the intermediate representation of a database sequence generator.

type Span

type Span = exec.Span

Span represents an active trace span recorded by a Tracer.

type Step

type Step = plan.Step

Step represents a single atomic migration step to execute.

type StepHook

type StepHook = exec.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

type SyncHook = exec.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 TableIR

type TableIR = schema.Table

TableIR represents the intermediate representation of a database table.

type Tracer

type Tracer = exec.Tracer

Tracer defines the interface for tracing Grizzle lifecycle events.

type TriggerIR

type TriggerIR = schema.Trigger

TriggerIR represents the intermediate representation of a trigger.

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.

type ViewIR

type ViewIR = schema.View

ViewIR represents the intermediate representation of a view or materialized view.

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 backfill between them.
Package main demonstrates zero-downtime expand/contract migrations with Grizzle: a column rename executed in two separately-approved stages with a backfill between them.
full-catalog command
Package main demonstrates Grizzle's full managed surface: extensions, domains, tables with RLS + policies, COMMENT ON, functions, procedures, triggers, and (materialized) views — all declared in one schema.sql and synced in-process on boot.
Package main demonstrates Grizzle's full managed surface: extensions, domains, tables with RLS + policies, COMMENT ON, functions, procedures, triggers, and (materialized) views — all declared in one schema.sql and synced in-process on boot.
postgres-stdlib command
roles-grants command
Package main demonstrates RolesSQL side-channel privilege sync: schema objects live in schema.sql; CREATE ROLE / GRANT statements live in roles.sql.
Package main demonstrates RolesSQL side-channel privilege sync: schema objects live in schema.sql; CREATE ROLE / GRANT statements live in roles.sql.
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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL