Skip to main content

Configuration

Everything has a sensible default, and everything can be swapped out through migrate.Config, which you pass to Main or Up.

FieldDefaultPurpose
DirmigrationsThe folder
VersionsDir, CodeDirversions, codeThe two folders inside it
FS, EmbeddednoneRead from go:embed, always, or when the folder is missing
SourcefilesReplace storage entirely
PerDialectoffKeep each dialect's files in Dir/<dialect>
Name, Parse0001_name.up.sqlWrite and read file names, with migrate.Timestamped built in
Renderschema.ScriptReplace how a plan becomes SQL
HistoryTable, HistorySchemaant_migrationsWhere applied migrations are recorded
DSNnoneThe fallback after --dsn and DATABASE_URL
SkipnoneVersions to leave unapplied
OutOfOrderoffLet an older pending migration run
IgnorenoneNames for drift to overlook, such as legacy_* or users.handmade_idx
NoLockoffTurn off the migration lock
SeedHooksoffRun model hooks while seeding
Out, OnApplyquiet in UpProgress text, and a callback per migration

Storage​

Source lists migrations from anywhere, such as a table or an object store. Implement Store as well for the commands that write.

type Source interface {
List(ctx context.Context) ([]migrate.Migration, error)
Snapshot(ctx context.Context) ([]byte, error)
}

File names​

Name chooses a new file's name, and Parse reads a version and name back.

SQL​

Render receives the plan, as data, and can wrap the default.

config := migrate.Config{
Render: func(plan *schema.Plan, d schema.Dialect) (string, error) {
text, err := schema.Script(d, plan)

return "SET lock_timeout = '5s';\n\n" + text, err
},
}