Documentation
¶
Overview ¶
Package kit provides Grizzle's migration tooling: schema snapshots, diffing, SQL generation, and schema push. It is the Go equivalent of Drizzle Kit.
Typical usage (library mode — user writes their own migrate entrypoint):
snap := kit.FromDefs(schema.Users, schema.Realms) sql := kit.GenerateCreateSQL(schema.Users, schema.Realms) // Push to DB (introspects current state, diffs, applies changes): err := kit.Push(ctx, pool, schema.Users, schema.Realms)
Index ¶
- Constants
- func AllChangeSQL(snap Snapshot, changes []Change) []string
- func AllChangeSQLMySQL(snap Snapshot, changes []Change) []string
- func AllChangeSQLSQLite(snap Snapshot, changes []Change) []string
- func ChecksumSQL(stmts []string) string
- func DescribeChanges(changes []Change) string
- func GenerateChangeSQL(snap Snapshot, c Change) []string
- func GenerateChangeSQLMySQL(snap Snapshot, c Change) []string
- func GenerateChangeSQLSQLite(snap Snapshot, c Change) []string
- func GenerateCreateSQL(tables ...pg.TableDefiner) string
- func GenerateCreateSQLMySQL(tables ...pg.TableDefiner) string
- func GenerateCreateSQLSQLite(tables ...pg.TableDefiner) string
- func SaveJSON(snap Snapshot, path string) error
- type Change
- type ChangeKind
- type MigrateResult
- func Migrate(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (MigrateResult, error)
- func MigrateMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (MigrateResult, error)
- func MigrateSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (MigrateResult, error)
- type MigrationRecord
- type PushResult
- func DryRun(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (PushResult, error)
- func DryRunMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
- func DryRunSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
- func Push(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (PushResult, error)
- func PushMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
- func PushSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
- type Snapshot
- type StatusResult
- func Status(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (StatusResult, error)
- func StatusMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (StatusResult, error)
- func StatusSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (StatusResult, error)
- type TableSnap
Constants ¶
const MigrationsTable = "_grizzle_migrations"
MigrationsTable is the name of the history table Grizzle creates to track applied migrations.
Variables ¶
This section is empty.
Functions ¶
func AllChangeSQL ¶
AllChangeSQL returns all SQL statements for all changes in order.
func AllChangeSQLMySQL ¶
AllChangeSQLMySQL returns all MySQL SQL statements for all changes in order.
func AllChangeSQLSQLite ¶
AllChangeSQLSQLite returns all SQLite SQL statements for all changes in order. Includes SQL comment stubs for changes that SQLite cannot apply directly (ALTER COLUMN type/nullability/untranslatable-default changes).
func ChecksumSQL ¶
ChecksumSQL returns the SHA-256 hex digest of the concatenated SQL statements. The checksum is order-sensitive and is stored in the migrations history table.
func DescribeChanges ¶
DescribeChanges produces a short human-readable summary of the change list, e.g. "create_table: users; add_column: posts.title; drop_column: posts.body"
func GenerateChangeSQL ¶
GenerateChangeSQL translates a single Change into one or more SQL statements. The caller is responsible for ordering (Diff() already returns changes in a safe application order for common cases).
func GenerateChangeSQLMySQL ¶
GenerateChangeSQLMySQL translates a single Change into MySQL SQL statements.
func GenerateChangeSQLSQLite ¶
GenerateChangeSQLSQLite translates a single Change into SQLite SQL statements.
func GenerateCreateSQL ¶
func GenerateCreateSQL(tables ...pg.TableDefiner) string
GenerateCreateSQL returns the full SQL to create all given tables from scratch, including separate CREATE INDEX statements. Statements are separated by ";\n". It accepts tables from any dialect via the TableDefiner interface.
func GenerateCreateSQLMySQL ¶
func GenerateCreateSQLMySQL(tables ...pg.TableDefiner) string
GenerateCreateSQLMySQL returns CREATE TABLE statements using MySQL syntax. It accepts tables from any dialect via the TableDefiner interface; the DDL is always rendered in MySQL syntax regardless of origin dialect.
func GenerateCreateSQLSQLite ¶
func GenerateCreateSQLSQLite(tables ...pg.TableDefiner) string
GenerateCreateSQLSQLite returns CREATE TABLE + CREATE INDEX statements for SQLite. Unlike the PostgreSQL version, schemas are ignored (SQLite has no schema namespace; ATTACH DATABASE is the SQLite equivalent). It accepts tables from any dialect via the TableDefiner interface.
Types ¶
type Change ¶
type Change struct {
Kind ChangeKind
TableName string // qualified name
// Set for column-level changes.
OldCol *pg.ColumnDef
NewCol *pg.ColumnDef
// Set for constraint-level changes.
Constraint *pg.Constraint
}
Change represents a single schema mutation — the unit that SQL generation works from.
func Diff ¶
Diff computes the ordered list of Changes needed to transition from the old snapshot to the new snapshot. Pass EmptySnapshot() as old when targeting a fresh database.
Ordering is deterministic:
- Create new tables (so FK references resolve).
- Alter existing tables (columns first, then constraints).
- Drop removed constraints.
- Drop removed tables.
Output is sorted for determinism: within each phase, changes are sorted by table name. Within a single table, changes are emitted in slice order (added/modified columns first, then dropped columns, then added/dropped constraints). No secondary sort by change kind or column name is applied.
func SQLiteApplyableChanges ¶
SQLiteApplyableChanges filters a change list to only those that SQLite can actually execute. Changes that require a full table rebuild (ALTER COLUMN type or nullability) and default changes where the translated expression is empty (e.g. gen_random_uuid()) are removed.
Use this when deciding whether a migration has real work to do, so that untranslatable schema differences do not cause infinite spurious migrations.
type ChangeKind ¶
type ChangeKind string
ChangeKind identifies the type of schema change.
const ( ChangeCreateTable ChangeKind = "create_table" ChangeDropTable ChangeKind = "drop_table" ChangeAddColumn ChangeKind = "add_column" ChangeDropColumn ChangeKind = "drop_column" ChangeAlterColumnType ChangeKind = "alter_column_type" ChangeAlterColumnNull ChangeKind = "alter_column_nullable" ChangeAlterColumnDefault ChangeKind = "alter_column_default" ChangeRenameColumn ChangeKind = "rename_column" ChangeAddConstraint ChangeKind = "add_constraint" ChangeDropConstraint ChangeKind = "drop_constraint" )
type MigrateResult ¶
type MigrateResult struct {
AlreadyCurrent bool // true when no changes were needed
Changes []Change
SQL []string
Checksum string
}
MigrateResult contains the outcome of a Migrate call.
func Migrate ¶
func Migrate(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (MigrateResult, error)
Migrate is like Push but records the applied SQL in the _grizzle_migrations history table. Calling Migrate twice with an unchanged schema is a no-op. It accepts tables from any dialect via the TableDefiner interface.
result, err := kit.Migrate(ctx, pool, schema.Users, schema.Realms)
func MigrateMySQL ¶
func MigrateMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (MigrateResult, error)
MigrateMySQL is like PushMySQL but records the applied SQL in the _grizzle_migrations history table. Calling MigrateMySQL twice with an unchanged schema is a no-op. It accepts tables from any dialect via the TableDefiner interface.
func MigrateSQLite ¶
func MigrateSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (MigrateResult, error)
MigrateSQLite is like PushSQLite but records the applied SQL in the _grizzle_migrations history table. It accepts tables from any dialect via the TableDefiner interface.
type MigrationRecord ¶
type MigrationRecord struct {
ID int64 `db:"id"`
AppliedAt time.Time `db:"applied_at"`
Checksum string `db:"checksum"` // SHA-256 hex of the SQL batch
SQLBatch string `db:"sql_batch"` // full SQL that was applied
Description string `db:"description"` // human-readable summary of changes
}
MigrationRecord is a row in the history table.
func LoadHistory ¶
LoadHistory returns all rows from _grizzle_migrations in chronological order. Returns an empty slice (not an error) if the table does not exist yet.
type PushResult ¶
PushResult contains the outcome of a Push operation.
func DryRun ¶
func DryRun(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (PushResult, error)
DryRun is like Push but does not apply changes — it only computes and returns what would be run. It accepts tables from any dialect via the TableDefiner interface.
func DryRunMySQL ¶
func DryRunMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
DryRunMySQL is like PushMySQL but does not apply changes — it only computes and returns what would be run. It accepts tables from any dialect via the TableDefiner interface.
func DryRunSQLite ¶
func DryRunSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
DryRunSQLite is like PushSQLite but does not apply changes. It accepts tables from any dialect via the TableDefiner interface.
func Push ¶
func Push(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (PushResult, error)
Push inspects the live database, diffs it against the provided table definitions, and applies all necessary DDL changes in a single transaction. It accepts tables from any dialect via the TableDefiner interface.
Example:
result, err := kit.Push(ctx, pool, schema.Users, schema.Realms)
for _, stmt := range result.SQL {
fmt.Println(stmt)
}
func PushMySQL ¶
func PushMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
PushMySQL inspects the live MySQL database, diffs it against the provided table definitions, and applies all necessary DDL changes in a transaction. It accepts tables from any dialect via the TableDefiner interface.
func PushSQLite ¶
func PushSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (PushResult, error)
PushSQLite inspects the live SQLite database, diffs it against the provided table definitions, and applies all necessary DDL changes. It accepts tables from any dialect via the TableDefiner interface.
Note: SQLite does not support ALTER COLUMN (type, nullability, or default changes). Such changes will produce SQL comment stubs; apply them by rebuilding the affected table manually.
type Snapshot ¶
type Snapshot struct {
Version string `json:"version"`
CreatedAt time.Time `json:"created_at"`
Tables map[string]*TableSnap `json:"tables"` // keyed by qualified table name
}
Snapshot is a serializable, point-in-time representation of a database schema. It is saved to disk as JSON and used to compute incremental diffs.
func EmptySnapshot ¶
func EmptySnapshot() Snapshot
EmptySnapshot returns an empty snapshot representing a blank database.
func FromDefs ¶
func FromDefs(tables ...pg.TableDefiner) Snapshot
FromDefs builds a Snapshot from a set of dialect-agnostic TableDefiner values. This is the normal way to capture your schema definition. It accepts tables from any dialect (pg, mysql, sqlite).
type StatusResult ¶
type StatusResult struct {
Applied []MigrationRecord // rows in _grizzle_migrations (oldest first)
Pending []Change // changes not yet applied
SQL []string // SQL that would apply the pending changes
}
StatusResult is returned by Status — it shows what is recorded vs. what the live schema looks like.
func Status ¶
func Status(ctx context.Context, pool *pgxpool.Pool, tables ...pg.TableDefiner) (StatusResult, error)
Status reports the applied migration history and any pending changes without modifying the database. It accepts tables from any dialect via the TableDefiner interface.
status, err := kit.Status(ctx, pool, schema.Users, schema.Realms)
for _, r := range status.Applied {
fmt.Printf("[%s] %s\n", r.AppliedAt.Format(time.RFC3339), r.Description)
}
if len(status.Pending) > 0 {
fmt.Println("Pending changes:", len(status.Pending))
}
func StatusMySQL ¶
func StatusMySQL(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (StatusResult, error)
StatusMySQL reports the applied migration history and any pending changes for a MySQL database without modifying it. It accepts tables from any dialect via the TableDefiner interface.
func StatusSQLite ¶
func StatusSQLite(ctx context.Context, db *sql.DB, tables ...pg.TableDefiner) (StatusResult, error)
StatusSQLite reports the applied migration history and any pending changes for a SQLite database without modifying it. It accepts tables from any dialect via the TableDefiner interface.
type TableSnap ¶
type TableSnap struct {
Name string `json:"name"`
Schema string `json:"schema,omitempty"`
Columns []pg.ColumnDef `json:"columns"`
Constraints []pg.Constraint `json:"constraints,omitempty"`
}
TableSnap is the snapshot of a single table.
func (*TableSnap) QualifiedName ¶
QualifiedName returns the schema-qualified name used as the map key.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package introspect reads a live PostgreSQL database and returns a kit.Snapshot representing its current schema.
|
Package introspect reads a live PostgreSQL database and returns a kit.Snapshot representing its current schema. |