migrate

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

operations.go defines the Operation interface and all 10 concrete migration operation types used by the makemigrations Go migration framework.

Package migrate provides the runtime library for the makemigrations Go migration framework. Generated migration files import this package and call Register() in their init() functions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildProviderFromType added in v1.0.0

func BuildProviderFromType(dbType string) (providers.Provider, error)

BuildProviderFromType creates a Provider from a database type string. It delegates to providers.NewProvider which supports all registered database types (postgresql, mysql, sqlite, sqlserver, etc.).

func EnvOr

func EnvOr(name, defaultVal string) string

EnvOr returns the value of the named environment variable, or defaultVal if the variable is not set or empty.

func FormatLiteral added in v1.0.0

func FormatLiteral(v any) string

FormatLiteral converts a Go value into a SQL literal string suitable for embedding directly in a SQL statement. It is used by UpsertData.Up to pre-format row values before passing them to the provider's GenerateUpsert. DefaultRef values are NOT handled here — they are resolved in UpsertData.Up before FormatLiteral is called.

Supported types:

  • nil → NULL
  • string → 'value' (single quotes escaped as ”)
  • bool → TRUE / FALSE
  • int variants → decimal literal
  • uint variants → decimal literal
  • float32/float64 → decimal literal (strconv.FormatFloat, 'f' format)
  • time.Time → 'YYYY-MM-DD HH:MM:SS'
  • fmt.Stringer → quoted using the Stringer output
  • everything else → quoted using fmt.Sprintf("%v")

func Register

func Register(m *Migration)

Register adds a migration to the global registry. Called by each generated migration file's init() function. Panics on duplicates.

func RenderDAGASCII

func RenderDAGASCII(out *DAGOutput) string

RenderDAGASCII produces a human-readable ASCII tree of the migration graph. It uses box-drawing characters to show parent->child relationships.

func SortedKeys added in v1.0.0

func SortedKeys(m map[string]any) []string

SortedKeys returns the keys of the map in alphabetical order. Used by UpsertData.Up to establish a consistent column ordering across rows.

Types

type AddField

type AddField struct {
	Table      string
	Field      Field
	SchemaOnly bool // when true, Up/Down return no SQL; Mutate still runs
}

AddField is a migration operation that adds a new column to an existing table. When SchemaOnly is true the operation advances the in-memory schema state (via Mutate) but does not execute any SQL, allowing the schema state to be seeded from an existing database without running ALTER TABLE ADD COLUMN.

func (*AddField) Describe

func (op *AddField) Describe() string

Describe returns a human-readable description of this operation.

func (*AddField) Down

func (op *AddField) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the DROP COLUMN SQL to reverse the addition. Returns empty string when SchemaOnly is set.

func (*AddField) IsDestructive

func (op *AddField) IsDestructive() bool

IsDestructive returns false — adding a column is not destructive.

func (*AddField) Mutate

func (op *AddField) Mutate(state *SchemaState) error

Mutate adds the new field to the table's entry in SchemaState.

func (*AddField) TableName

func (op *AddField) TableName() string

TableName returns the name of the table being altered.

func (*AddField) TypeName

func (op *AddField) TypeName() string

TypeName returns the operation type identifier.

func (*AddField) Up

func (op *AddField) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the ADD COLUMN SQL statement, or returns empty string when SchemaOnly is set. The field default is resolved against the active defaults map before being passed to the provider.

type AddIndex

type AddIndex struct {
	Table string
	Index Index
}

AddIndex is a migration operation that adds an index to an existing table.

func (*AddIndex) Describe

func (op *AddIndex) Describe() string

Describe returns a human-readable description of this operation.

func (*AddIndex) Down

func (op *AddIndex) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the DROP INDEX SQL to reverse the index creation.

func (*AddIndex) IsDestructive

func (op *AddIndex) IsDestructive() bool

IsDestructive returns false — adding an index is not destructive.

func (*AddIndex) Mutate

func (op *AddIndex) Mutate(state *SchemaState) error

Mutate adds the index to the table's entry in SchemaState.

func (*AddIndex) TableName

func (op *AddIndex) TableName() string

TableName returns the name of the table being indexed.

func (*AddIndex) TypeName

func (op *AddIndex) TypeName() string

TypeName returns the operation type identifier.

func (*AddIndex) Up

func (op *AddIndex) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the CREATE INDEX SQL statement.

type AlterField

type AlterField struct {
	Table    string
	OldField Field
	NewField Field
}

AlterField is a migration operation that modifies an existing column's definition.

func (*AlterField) Describe

func (op *AlterField) Describe() string

Describe returns a human-readable description of this operation.

func (*AlterField) Down

func (op *AlterField) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the ALTER COLUMN SQL to restore the original field definition. If the provider implements TableRecreationProvider (e.g. SQLite), the full current table definition is passed so the provider can recreate the table. Field defaults are resolved against the active defaults map before use.

func (*AlterField) IsDestructive

func (op *AlterField) IsDestructive() bool

IsDestructive returns false — altering a column is not considered destructive (though data conversion may fail at the database level for incompatible types).

func (*AlterField) Mutate

func (op *AlterField) Mutate(state *SchemaState) error

Mutate replaces the field in the table's entry in SchemaState.

func (*AlterField) TableName

func (op *AlterField) TableName() string

TableName returns the name of the table being altered.

func (*AlterField) TypeName

func (op *AlterField) TypeName() string

TypeName returns the operation type identifier.

func (*AlterField) Up

func (op *AlterField) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the ALTER COLUMN SQL to apply the new field definition. If the provider implements TableRecreationProvider (e.g. SQLite), the full current table definition is passed so the provider can recreate the table. Field defaults are resolved against the active defaults map before use.

type App

type App struct {
	// contains filtered or unexported fields
}

App is the CLI application embedded in each compiled migration binary.

func NewApp

func NewApp(cfg Config) *App

NewApp creates a new App with the given configuration. It uses the global registry by default.

func NewAppWithRegistry

func NewAppWithRegistry(cfg Config, reg *Registry) *App

NewAppWithRegistry creates a new App with the given configuration and a specific registry. This is primarily useful for testing.

func (*App) Run

func (a *App) Run(args []string) error

Run executes the CLI with the given arguments.

type Config

type Config struct {
	DatabaseType string // postgresql, mysql, sqlserver, sqlite
	DatabaseURL  string // full DSN — overrides individual fields if set
	DBHost       string
	DBPort       string
	DBUser       string
	DBPassword   string
	DBName       string
	DBSSLMode    string
}

Config holds database connection configuration for the migration binary. All fields default to environment variables if not set explicitly.

type CreateTable

type CreateTable struct {
	Name       string
	Fields     []Field
	Indexes    []Index
	SchemaOnly bool // when true, Up/Down return no SQL; Mutate still runs
}

CreateTable is a migration operation that creates a new database table with the specified fields and indexes. When SchemaOnly is true the operation advances the in-memory schema state (via Mutate) but does not execute any SQL, allowing the schema state to be seeded from an existing database without re-running CREATE TABLE.

func (*CreateTable) Describe

func (op *CreateTable) Describe() string

Describe returns a human-readable description of this operation.

func (*CreateTable) Down

func (op *CreateTable) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the DROP TABLE CASCADE SQL to reverse the creation. Uses GenerateDropTableCascade so that any dependent objects (e.g. foreign key constraints from other tables) are automatically removed, preventing ordering failures when multiple CreateTable operations are rolled back together. Returns empty string when SchemaOnly is set.

func (*CreateTable) IsDestructive

func (op *CreateTable) IsDestructive() bool

IsDestructive returns false — creating a table is not destructive.

func (*CreateTable) Mutate

func (op *CreateTable) Mutate(state *SchemaState) error

Mutate adds the new table to the SchemaState.

func (*CreateTable) TableName

func (op *CreateTable) TableName() string

TableName returns the name of the table being created.

func (*CreateTable) TypeName

func (op *CreateTable) TypeName() string

TypeName returns the operation type identifier.

func (*CreateTable) Up

func (op *CreateTable) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the CREATE TABLE SQL statement, or returns empty string when SchemaOnly is set. Field defaults are resolved against the active defaults map before being passed to the provider.

type DAGOutput

type DAGOutput struct {
	Migrations  []MigrationSummary `json:"migrations"`
	Roots       []string           `json:"roots"`
	Leaves      []string           `json:"leaves"`
	HasBranches bool               `json:"has_branches"`
	SchemaState *SchemaState       `json:"schema_state"`
}

DAGOutput is the JSON-serialisable representation of the full migration graph. This is what the compiled migration binary emits via the `dag --format json` command.

type DefaultRef added in v1.0.0

type DefaultRef string

DefaultRef is a string type that marks a row value as a reference to a named schema default rather than a literal value. When UpsertData.Up encounters a DefaultRef it resolves the key through the active defaults map (set by the SetDefaults operation) and emits the resolved SQL expression verbatim — without quoting it as a string literal.

If the key is not present in the defaults map, the key itself is emitted as a raw SQL expression (useful for calling built-in functions directly, e.g. DefaultRef("NOW()") or DefaultRef("gen_random_uuid()")).

Example:

&m.UpsertData{
    Table:        "items",
    ConflictKeys: []string{"code"},
    Rows: []map[string]any{
        {"id": m.DefaultRef("uuid"), "code": "AU", "name": "Australia"},
    },
}

With SetDefaults{"uuid": "uuid_generate_v4()"} active this produces:

INSERT INTO "items" ("code", "id", "name")
VALUES ('AU', uuid_generate_v4(), 'Australia')
ON CONFLICT ("code") DO UPDATE SET ...

type DropField

type DropField struct {
	Table      string
	Field      string
	SchemaOnly bool // when true, Up/Down return no SQL; Mutate still runs
}

DropField is a migration operation that removes a column from an existing table. When SchemaOnly is true the operation advances the in-memory schema state (via Mutate) but does not execute any SQL against the database, allowing the developer to acknowledge a removal in the schema definition without immediately dropping the live column.

func (*DropField) Describe

func (op *DropField) Describe() string

Describe returns a human-readable description of this operation.

func (*DropField) Down

func (op *DropField) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down reconstructs the ADD COLUMN SQL by reading the field's pre-drop state. Returns empty string when SchemaOnly is set. The field default is resolved against the active defaults map before being passed to the provider.

func (*DropField) IsDestructive

func (op *DropField) IsDestructive() bool

IsDestructive returns true — dropping a column causes data loss.

func (*DropField) Mutate

func (op *DropField) Mutate(state *SchemaState) error

Mutate removes the field from the table's entry in SchemaState.

func (*DropField) TableName

func (op *DropField) TableName() string

TableName returns the name of the table being altered.

func (*DropField) TypeName

func (op *DropField) TypeName() string

TypeName returns the operation type identifier.

func (*DropField) Up

func (op *DropField) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the DROP COLUMN SQL statement, or returns empty string when SchemaOnly is set.

type DropIndex

type DropIndex struct {
	Table string
	Index string
}

DropIndex is a migration operation that removes an index from an existing table.

func (*DropIndex) Describe

func (op *DropIndex) Describe() string

Describe returns a human-readable description of this operation.

func (*DropIndex) Down

func (op *DropIndex) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down reconstructs the CREATE INDEX SQL by reading the index's pre-drop state.

func (*DropIndex) IsDestructive

func (op *DropIndex) IsDestructive() bool

IsDestructive returns false — dropping an index is not considered destructive.

func (*DropIndex) Mutate

func (op *DropIndex) Mutate(state *SchemaState) error

Mutate removes the index from the table's entry in SchemaState.

func (*DropIndex) TableName

func (op *DropIndex) TableName() string

TableName returns the name of the table whose index is being dropped.

func (*DropIndex) TypeName

func (op *DropIndex) TypeName() string

TypeName returns the operation type identifier.

func (*DropIndex) Up

func (op *DropIndex) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the DROP INDEX SQL statement.

type DropTable

type DropTable struct {
	Name       string
	SchemaOnly bool // when true, Up/Down return no SQL; Mutate still runs
}

DropTable is a migration operation that drops an existing database table. When SchemaOnly is true the operation advances the in-memory schema state (via Mutate) but does not execute any SQL against the database, allowing the developer to acknowledge a removal in the schema definition without immediately dropping the live table.

func (*DropTable) Describe

func (op *DropTable) Describe() string

Describe returns a human-readable description of this operation.

func (*DropTable) Down

func (op *DropTable) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down reconstructs the CREATE TABLE SQL by reading the table's pre-drop state. Returns empty string when SchemaOnly is set.

func (*DropTable) IsDestructive

func (op *DropTable) IsDestructive() bool

IsDestructive returns true — dropping a table causes data loss.

func (*DropTable) Mutate

func (op *DropTable) Mutate(state *SchemaState) error

Mutate removes the table from the SchemaState.

func (*DropTable) TableName

func (op *DropTable) TableName() string

TableName returns the name of the table being dropped.

func (*DropTable) TypeName

func (op *DropTable) TypeName() string

TypeName returns the operation type identifier.

func (*DropTable) Up

func (op *DropTable) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the DROP TABLE SQL statement, or returns empty string when SchemaOnly is set.

type Field

type Field struct {
	Name       string      `json:"name"`
	Type       string      `json:"type"` // varchar, text, integer, uuid, boolean, timestamp, foreign_key, etc.
	PrimaryKey bool        `json:"primary_key,omitempty"`
	Nullable   bool        `json:"nullable,omitempty"`
	Default    string      `json:"default,omitempty"`     // default reference name e.g. "new_uuid", "now", "true"
	Length     int         `json:"length,omitempty"`      // for varchar
	Precision  int         `json:"precision,omitempty"`   // for decimal/numeric
	Scale      int         `json:"scale,omitempty"`       // for decimal/numeric
	AutoCreate bool        `json:"auto_create,omitempty"` // auto-set on row creation (created_at)
	AutoUpdate bool        `json:"auto_update,omitempty"` // auto-set on row update (updated_at)
	ForeignKey *ForeignKey `json:"foreign_key,omitempty"`
	ManyToMany *ManyToMany `json:"many_to_many,omitempty"`
}

Field represents a database column definition used in migration operations.

type ForeignKey

type ForeignKey struct {
	Table    string `json:"table"`
	OnDelete string `json:"on_delete,omitempty"`
	OnUpdate string `json:"on_update,omitempty"`
}

ForeignKey represents a foreign key constraint.

type Graph

type Graph struct {
	// contains filtered or unexported fields
}

Graph is a directed acyclic graph (DAG) of migrations. Each node represents one migration; edges represent dependencies.

func BuildGraph

func BuildGraph(reg *Registry) (*Graph, error)

BuildGraph constructs a Graph from a Registry. Returns an error if any dependency is missing or if a cycle is detected.

func (*Graph) DetectBranches

func (g *Graph) DetectBranches() [][]string

DetectBranches returns groups of leaf migration names when there are multiple leaves (indicating concurrent development branches). Returns empty slice if the graph is linear.

func (*Graph) HasBranches

func (g *Graph) HasBranches() bool

HasBranches returns true if the graph contains any branching structure. This includes divergent branches (multiple leaves) and diamond topologies where a node has more than one child, even if the branches later converge.

func (*Graph) Leaves

func (g *Graph) Leaves() []string

Leaves returns names of migrations that no other migration depends on (no children).

func (*Graph) Linearize

func (g *Graph) Linearize() ([]*Migration, error)

Linearize returns all migrations in topological order using Kahn's algorithm. Deterministic: nodes at the same level are sorted by name.

func (*Graph) ReconstructState

func (g *Graph) ReconstructState() (*SchemaState, error)

ReconstructState replays all operations in topological order to produce the full schema state as it would exist after all registered migrations have run.

func (*Graph) Roots

func (g *Graph) Roots() []string

Roots returns names of migrations with no dependencies (no parents).

func (*Graph) ToDAGOutput

func (g *Graph) ToDAGOutput() (*DAGOutput, error)

ToDAGOutput builds a DAGOutput from this graph, including the reconstructed schema state.

type Index

type Index struct {
	Name   string   `json:"name"`
	Fields []string `json:"fields"`
	Unique bool     `json:"unique,omitempty"`
}

Index represents a database index definition.

type ManyToMany

type ManyToMany struct {
	Table string `json:"table"`
}

ManyToMany represents a many-to-many relationship via junction table.

type Migration

type Migration struct {
	Name         string      `json:"name"`               // Unique identifier e.g. "0001_initial"
	Dependencies []string    `json:"dependencies"`       // Names of migrations this depends on
	Operations   []Operation `json:"-"`                  // Ordered list of schema operations to apply
	Replaces     []string    `json:"replaces,omitempty"` // For squashed migrations: names of migrations this replaces
}

Migration represents a single database migration with its name, dependencies, and operations.

type MigrationRecorder

type MigrationRecorder struct {
	// contains filtered or unexported fields
}

MigrationRecorder manages the makemigrations_history table. It records which migrations have been applied to the database.

func NewMigrationRecorder

func NewMigrationRecorder(db *sql.DB, p providers.Provider) *MigrationRecorder

NewMigrationRecorder creates a new MigrationRecorder using the given db connection and provider. The provider supplies the database-specific DDL and placeholder style.

func (*MigrationRecorder) EnsureTable

func (r *MigrationRecorder) EnsureTable() error

EnsureTable creates the makemigrations_history table if it does not exist. The DDL is supplied by the provider so it is correct for the target database.

func (*MigrationRecorder) Fake

func (r *MigrationRecorder) Fake(name string) error

Fake inserts a migration name without executing any SQL. Used to mark migrations as applied when the database already has the schema.

func (*MigrationRecorder) GetApplied

func (r *MigrationRecorder) GetApplied() (map[string]bool, error)

GetApplied returns a set of migration names that have been applied.

func (*MigrationRecorder) RecordApplied

func (r *MigrationRecorder) RecordApplied(name string) error

RecordApplied inserts a migration name into the history table.

func (*MigrationRecorder) RecordRolledBack

func (r *MigrationRecorder) RecordRolledBack(name string) error

RecordRolledBack removes a migration name from the history table.

type MigrationSummary

type MigrationSummary struct {
	Name         string             `json:"name"`
	Dependencies []string           `json:"dependencies"`
	Operations   []OperationSummary `json:"operations"`
}

MigrationSummary is a JSON-serialisable summary of a single migration.

type Operation

type Operation interface {
	// Up generates the forward SQL for this operation.
	Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)
	// Down generates the reverse SQL to undo this operation.
	Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)
	// Mutate applies this operation to the given SchemaState, updating the
	// in-memory schema representation during migration graph traversal.
	Mutate(state *SchemaState) error
	// Describe returns a human-readable description of the operation.
	Describe() string
	// TypeName returns the operation type identifier (e.g. "create_table").
	TypeName() string
	// TableName returns the primary table this operation acts on, or "" for RunSQL.
	TableName() string
	// IsDestructive returns true if this operation may cause data loss.
	IsDestructive() bool
}

Operation is the interface all migration operations must implement. Each operation can generate forward (Up) and reverse (Down) SQL, mutate the in-memory SchemaState for graph traversal, and describe itself for display. Up/Down method names align with the CLI commands `./migrate up` / `./migrate down`.

type OperationSummary

type OperationSummary struct {
	Type        string `json:"type"`
	Table       string `json:"table,omitempty"`
	Description string `json:"description"`
}

OperationSummary is a JSON-serialisable summary of a single operation.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry stores all registered migrations, preserving insertion order.

func GlobalRegistry

func GlobalRegistry() *Registry

GlobalRegistry returns the global registry. Used by app.go to build the migration graph.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty Registry. Used for testing; generated migration files use the global registry.

func (*Registry) All

func (r *Registry) All() []*Migration

All returns all registered migrations in insertion order.

func (*Registry) Get

func (r *Registry) Get(name string) (*Migration, bool)

Get returns a migration by name, and a boolean indicating whether it was found.

func (*Registry) Register

func (r *Registry) Register(m *Migration)

Register adds a migration to this registry. Panics on duplicate names.

func (*Registry) Resolve added in v1.0.0

func (r *Registry) Resolve(name string) (string, error)

Resolve validates that name matches a registered migration exactly and returns it. Returns an error if no migration with that exact name is registered. Exact matching is required so that "fake 0002" is rejected when multiple migrations share the same numeric prefix (e.g. 0002_add_users, 0002_add_orders).

type RenameField

type RenameField struct {
	Table   string
	OldName string
	NewName string
}

RenameField is a migration operation that renames a column in an existing table.

func (*RenameField) Describe

func (op *RenameField) Describe() string

Describe returns a human-readable description of this operation.

func (*RenameField) Down

func (op *RenameField) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the reverse RENAME COLUMN SQL to restore the original name.

func (*RenameField) IsDestructive

func (op *RenameField) IsDestructive() bool

IsDestructive returns false — renaming a column is not destructive.

func (*RenameField) Mutate

func (op *RenameField) Mutate(state *SchemaState) error

Mutate updates the field name in the table's entry in SchemaState.

func (*RenameField) TableName

func (op *RenameField) TableName() string

TableName returns the name of the table being altered.

func (*RenameField) TypeName

func (op *RenameField) TypeName() string

TypeName returns the operation type identifier.

func (*RenameField) Up

func (op *RenameField) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the RENAME COLUMN SQL statement.

type RenameTable

type RenameTable struct{ OldName, NewName string }

RenameTable is a migration operation that renames an existing database table.

func (*RenameTable) Describe

func (op *RenameTable) Describe() string

Describe returns a human-readable description of this operation.

func (*RenameTable) Down

func (op *RenameTable) Down(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Down generates the reverse RENAME TABLE SQL to restore the original name.

func (*RenameTable) IsDestructive

func (op *RenameTable) IsDestructive() bool

IsDestructive returns false — renaming a table is not destructive.

func (*RenameTable) Mutate

func (op *RenameTable) Mutate(state *SchemaState) error

Mutate updates the SchemaState to reflect the renamed table.

func (*RenameTable) TableName

func (op *RenameTable) TableName() string

TableName returns the old (pre-rename) table name.

func (*RenameTable) TypeName

func (op *RenameTable) TypeName() string

TypeName returns the operation type identifier.

func (*RenameTable) Up

func (op *RenameTable) Up(p providers.Provider, state *SchemaState, defaults map[string]string) (string, error)

Up generates the RENAME TABLE SQL statement.

type RunOptions added in v1.0.0

type RunOptions struct {
	// WarnOnMissingDrop causes drop operations that fail because the target
	// object does not exist to print a warning and continue rather than stop.
	WarnOnMissingDrop bool
}

RunOptions controls optional behaviour for Up and Down.

type RunSQL

type RunSQL struct {
	// ForwardSQL is the raw SQL to execute on Up (forward migration).
	ForwardSQL string
	// BackwardSQL is the raw SQL to execute on Down (reverse migration).
	BackwardSQL string
	// SchemaOnly marks the operation as applied without executing any SQL.
	// Use this when the underlying schema already exists in the database.
	SchemaOnly bool
}

RunSQL is a migration operation that executes raw SQL for forward and reverse migrations. ForwardSQL and BackwardSQL field names are used (not Forward/Backward) to avoid conflict with the Up/Down method names on the Operation interface. When SchemaOnly is true the operation is recorded as applied but no SQL is sent to the database — useful when the schema is already in place.

func (*RunSQL) Describe

func (op *RunSQL) Describe() string

Describe returns a human-readable description of this operation.

func (*RunSQL) Down

func (op *RunSQL) Down(_ providers.Provider, _ *SchemaState, _ map[string]string) (string, error)

Down returns the BackwardSQL string, or empty string when SchemaOnly is set.

func (*RunSQL) IsDestructive

func (op *RunSQL) IsDestructive() bool

IsDestructive returns false — RunSQL destructiveness depends on the SQL content.

func (*RunSQL) Mutate

func (op *RunSQL) Mutate(_ *SchemaState) error

Mutate is a no-op for RunSQL — raw SQL does not alter the SchemaState.

func (*RunSQL) TableName

func (op *RunSQL) TableName() string

TableName returns an empty string — RunSQL does not target a specific table.

func (*RunSQL) TypeName

func (op *RunSQL) TypeName() string

TypeName returns the operation type identifier.

func (*RunSQL) Up

func (op *RunSQL) Up(_ providers.Provider, _ *SchemaState, _ map[string]string) (string, error)

Up returns the ForwardSQL string, or empty string when SchemaOnly is set.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner executes migrations against a database in topological order.

func NewRunner

func NewRunner(graph *Graph, provider providers.Provider, db *sql.DB, recorder *MigrationRecorder) *Runner

NewRunner creates a Runner using the given graph, provider, db, and recorder.

func (*Runner) Down

func (r *Runner) Down(steps int, to string, opts RunOptions) error

Down rolls back migrations. If steps > 0, rolls back that many. If to is set, rolls back until that migration name is reached (exclusive).

func (*Runner) ShowSQL

func (r *Runner) ShowSQL() error

ShowSQL prints all pending migration SQL without executing it.

func (*Runner) Status

func (r *Runner) Status() error

Status prints migration status: applied vs pending.

func (*Runner) Up

func (r *Runner) Up(to string, opts RunOptions) error

Up applies all pending migrations in topological order. If to is non-empty, stops after applying the named migration.

type SchemaState

type SchemaState struct {
	Tables       map[string]*TableState `json:"tables"`
	Defaults     map[string]string      `json:"defaults,omitempty"`      // active DB-type defaults from SetDefaults operations
	TypeMappings map[string]string      `json:"type_mappings,omitempty"` // active provider's type mappings from SetTypeMappings operations
}

SchemaState holds the in-memory representation of the database schema at a specific point in the migration graph. Operations call Mutate() to update it as they are applied during graph traversal.

func NewSchemaState

func NewSchemaState() *SchemaState

NewSchemaState returns an empty SchemaState.

func (*SchemaState) AddField

func (s *SchemaState) AddField(tableName string, field Field) error

AddField appends a field to an existing table. Returns error if the field name already exists.

func (*SchemaState) AddIndex

func (s *SchemaState) AddIndex(tableName string, index Index) error

AddIndex appends an index to an existing table. Returns error if the index name already exists.

func (*SchemaState) AddTable

func (s *SchemaState) AddTable(name string, fields []Field, indexes []Index) error

AddTable adds a new table. Returns error if the table already exists. The fields and indexes slices are copied so that subsequent mutations to the state (e.g. DropField) do not corrupt the caller's original slice.

func (*SchemaState) AlterField

func (s *SchemaState) AlterField(tableName string, newField Field) error

AlterField replaces a field (matched by name) in an existing table.

func (*SchemaState) DropField

func (s *SchemaState) DropField(tableName, fieldName string) error

DropField removes a named field from an existing table.

func (*SchemaState) DropIndex

func (s *SchemaState) DropIndex(tableName, indexName string) error

DropIndex removes a named index from an existing table.

func (*SchemaState) DropTable

func (s *SchemaState) DropTable(name string) error

DropTable removes a table. Returns error if the table does not exist.

func (*SchemaState) RenameField

func (s *SchemaState) RenameField(tableName, oldName, newName string) error

RenameField renames a field within an existing table.

func (*SchemaState) RenameTable

func (s *SchemaState) RenameTable(oldName, newName string) error

RenameTable renames a table. Returns error if old name does not exist or new name already exists.

func (*SchemaState) SetDefaults added in v1.0.0

func (s *SchemaState) SetDefaults(defaults map[string]string)

SetDefaults updates the active schema defaults map on the state. Called by SetDefaults operations during migration traversal.

func (*SchemaState) SetTypeMappings added in v1.0.0

func (s *SchemaState) SetTypeMappings(m map[string]string)

SetTypeMappings updates the active type mappings on the state. Called by SetTypeMappings operations during migration traversal.

type SetDefaults added in v1.0.0

type SetDefaults struct {
	Defaults map[string]string
}

SetDefaults is a migration operation that records the active schema defaults (e.g. {"uuid": "uuid_generate_v4()"}) into the SchemaState so that subsequent operations can resolve symbolic default references at runtime. It emits no SQL — its sole purpose is to update the in-memory state.

func (*SetDefaults) Describe added in v1.0.0

func (op *SetDefaults) Describe() string

Describe returns a human-readable description of this operation.

func (*SetDefaults) Down added in v1.0.0

func (op *SetDefaults) Down(_ providers.Provider, _ *SchemaState, _ map[string]string) (string, error)

Down returns empty string — SetDefaults emits no SQL.

func (*SetDefaults) IsDestructive added in v1.0.0

func (op *SetDefaults) IsDestructive() bool

IsDestructive returns false — setting defaults is not destructive.

func (*SetDefaults) Mutate added in v1.0.0

func (op *SetDefaults) Mutate(state *SchemaState) error

Mutate updates the active schema defaults on the SchemaState.

func (*SetDefaults) TableName added in v1.0.0

func (op *SetDefaults) TableName() string

TableName returns "" — SetDefaults does not target a specific table.

func (*SetDefaults) TypeName added in v1.0.0

func (op *SetDefaults) TypeName() string

TypeName returns the operation type identifier.

func (*SetDefaults) Up added in v1.0.0

Up returns empty string — SetDefaults emits no SQL.

type SetTypeMappings added in v1.0.0

type SetTypeMappings struct {
	TypeMappings map[string]string
}

SetTypeMappings is a migration operation that records the active schema type mappings for the target database provider. It emits no SQL — its only effect is updating SchemaState.TypeMappings so that subsequent operations and the runner use the correct type overrides when generating SQL via ConvertFieldType.

func (*SetTypeMappings) Describe added in v1.0.0

func (op *SetTypeMappings) Describe() string

Describe returns a human-readable description.

func (*SetTypeMappings) Down added in v1.0.0

Down returns empty string — SetTypeMappings emits no SQL.

func (*SetTypeMappings) IsDestructive added in v1.0.0

func (op *SetTypeMappings) IsDestructive() bool

IsDestructive returns false — SetTypeMappings is always non-destructive.

func (*SetTypeMappings) Mutate added in v1.0.0

func (op *SetTypeMappings) Mutate(state *SchemaState) error

Mutate applies the type mappings to the schema state.

func (*SetTypeMappings) TableName added in v1.0.0

func (op *SetTypeMappings) TableName() string

TableName returns "" — SetTypeMappings does not target a specific table.

func (*SetTypeMappings) TypeName added in v1.0.0

func (op *SetTypeMappings) TypeName() string

TypeName returns the operation type identifier.

func (*SetTypeMappings) Up added in v1.0.0

Up returns empty string — SetTypeMappings emits no SQL.

type TableState

type TableState struct {
	Name    string  `json:"name"`
	Fields  []Field `json:"fields"`
	Indexes []Index `json:"indexes"`
}

TableState holds the state of a single table.

type UpsertData added in v1.0.0

type UpsertData struct {
	// Table is the target table name.
	Table string
	// ConflictKeys lists the column names used to detect conflicts (primary key
	// or unique constraint columns). Used in ON CONFLICT / MERGE ON / DELETE WHERE.
	ConflictKeys []string
	// Rows is the data to upsert. All rows must have the same keys. Values are
	// formatted as SQL literals via FormatLiteral, supporting nil, string, bool,
	// integer, float, and time.Time types.
	Rows []map[string]any
}

UpsertData is a migration operation that inserts or updates rows in a table. It is designed for seeding reference data (e.g. country codes, status enums, configuration rows) as part of a migration.

The operation generates database-appropriate upsert SQL via the active provider:

  • PostgreSQL/AuroraDSQL: INSERT … ON CONFLICT … DO UPDATE SET
  • MySQL/TiDB/StarRocks: INSERT … ON DUPLICATE KEY UPDATE
  • SQLite/Turso: INSERT … ON CONFLICT … DO UPDATE SET
  • SQL Server/Vertica: MERGE INTO … USING … WHEN MATCHED / NOT MATCHED
  • Redshift: DELETE … ; INSERT …
  • ClickHouse: INSERT (dedup via ReplacingMergeTree)
  • YDB: UPSERT INTO …

Column order in the generated SQL is determined by sorting the keys of the first row alphabetically, so all rows must contain the same set of keys.

Rollback (Down) deletes each row by matching on ConflictKeys.

func (*UpsertData) Describe added in v1.0.0

func (op *UpsertData) Describe() string

Describe returns a human-readable description of this operation.

func (*UpsertData) Down added in v1.0.0

func (op *UpsertData) Down(p providers.Provider, _ *SchemaState, _ map[string]string) (string, error)

Down generates DELETE statements that remove each upserted row by matching on the ConflictKeys. Returns empty string when Rows or ConflictKeys is empty.

func (*UpsertData) IsDestructive added in v1.0.0

func (op *UpsertData) IsDestructive() bool

IsDestructive returns false — upserting seed data is not considered destructive.

func (*UpsertData) Mutate added in v1.0.0

func (op *UpsertData) Mutate(_ *SchemaState) error

Mutate is a no-op — UpsertData does not alter the schema state.

func (*UpsertData) TableName added in v1.0.0

func (op *UpsertData) TableName() string

TableName returns the target table name.

func (*UpsertData) TypeName added in v1.0.0

func (op *UpsertData) TypeName() string

TypeName returns the operation type identifier.

func (*UpsertData) Up added in v1.0.0

func (op *UpsertData) Up(p providers.Provider, _ *SchemaState, defaults map[string]string) (string, error)

Up generates the upsert SQL by delegating to the provider's GenerateUpsert. Returns empty string when Rows is empty.

DefaultRef values in rows are resolved through the defaults map: if the key is present, the resolved SQL expression is emitted verbatim (not quoted); if not, the DefaultRef string itself is used as a raw SQL expression.

Jump to

Keyboard shortcuts

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