Skip to main content
Version: 0.7.0

Migrations API Reference

Reference for schema creation, schema sync, indexes, foreign keys, and versioned migrations.

Client Schema Helpers

Migrate(ctx context.Context, models ...any) error

Creates missing tables for the given models.

err := client.Migrate(ctx, &User{}, &Order{}, &Product{})

Migrate also creates many-to-many join tables for relations tagged rel:"many_to_many" with an m2m tag.

Sync(ctx context.Context, opts SyncOptions, models ...any) error

Synchronizes existing tables with model metadata.

err := client.Sync(ctx, quark.SyncOptions{}, &User{})

Supported sync operations:

ChangeSupport
Missing tableCalls Migrate unless DryRun is true.
New columnAdds the column.
Renamed columnUses quark:"rename:old_col".
Removed columnDrops only when SafeMigrations is false.
type SyncOptions struct {
DryRun bool
NoTransaction bool
}

CreateIndex(ctx, table, indexName string, columns []string, unique bool) error

Creates a simple index.

err := client.CreateIndex(
ctx,
"users",
"idx_users_email",
[]string{"email"},
true,
)

AddForeignKey(ctx, table, constraintName string, columns []string, refTable string, refColumns []string, onDelete, onUpdate string) error

Adds a foreign key constraint.

err := client.AddForeignKey(
ctx,
"orders",
"fk_orders_user",
[]string{"user_id"},
"users",
[]string{"id"},
"CASCADE",
"",
)

Versioned Migrations

migrate.Register(m *Migration)

Registers a migration in the global migration registry.

migrate.Register(&migrate.Migration{
ID: "202605050001_add_email_index",
Name: "add email index",
Up: func(ctx context.Context, client *quark.Client) error {
return client.CreateIndex(ctx, "users", "idx_users_email", []string{"email"}, true)
},
Down: func(ctx context.Context, client *quark.Client) error {
return client.Exec(ctx, "DROP INDEX idx_users_email")
},
})

Migration IDs are sorted lexicographically. Use timestamp-like IDs.

type Migration struct {
ID string
Name string
Message string
Up func(ctx context.Context, client *quark.Client) error
Down func(ctx context.Context, client *quark.Client) error
}

migrate.Reset()

Clears the migration registry. Intended for tests.

Migrator

migrate.NewMigrator(client *quark.Client) *Migrator

Creates a migrator bound to a client.

migrator := migrate.NewMigrator(client)

The migrator stores applied migration IDs in quark_migrations.

Init(ctx context.Context) error

Creates the migration tracking table if needed.

err := migrator.Init(ctx)

Up(ctx context.Context, steps int) error

Applies pending migrations in ID order.

err := migrator.Up(ctx, 0) // apply all pending
err = migrator.Up(ctx, 2) // apply at most two

UpDryRun(ctx context.Context, steps int) error

Prints pending migrations without executing their Up functions.

err := migrator.UpDryRun(ctx, 0)

Down(ctx context.Context, steps int) error

Reverts applied migrations in reverse ID order.

err := migrator.Down(ctx, 1)

Raw SQL Requirement

migrate.Migrator uses client.Exec for its tracking table changes. Configure the migration client with AllowRawQueries: true:

limits := quark.DefaultLimits()
limits.AllowRawQueries = true

client, err := quark.New("postgres", dsn,
quark.WithLimits(limits),
)

High-level helpers such as Migrate, Sync, CreateIndex, and AddForeignKey do not require AllowRawQueries.