AJ ONeal 0c1eb1f125
feat(skills): add sqlmigrate skill index and per-database skills
Index skill (use-sqlmigrate) plus focused skills for CLI usage, Go
library integration, and per-database conventions (PostgreSQL,
MySQL/MariaDB, SQLite, SQL Server).
2026-04-09 17:08:32 -06:00

1.5 KiB

name, description, depends
name description depends
use-sql-migrate-postgres PostgreSQL migrations with sql-migrate and pgmigrate. Use when setting up PostgreSQL migrations, schema multi-tenancy, or pgx connection for migrations.
use-sqlmigrate

CLI setup

sql-migrate -d ./sql/migrations/ init --sql-command psql

Environment

# .env
PG_URL='postgres://user:pass@localhost:5432/mydb?sslmode=disable'

Go library

import (
    "github.com/jackc/pgx/v5"
    "github.com/therootcompany/golib/database/sqlmigrate"
    "github.com/therootcompany/golib/database/sqlmigrate/pgmigrate"
)

// MUST: use pgx.Connect (single conn), not pgxpool.New
conn, err := pgx.Connect(ctx, pgURL)
defer func() { _ = conn.Close(ctx) }()

runner := pgmigrate.New(conn)
applied, err := sqlmigrate.Latest(ctx, runner, scripts)

Schema multi-tenancy

Each PostgreSQL schema gets its own _migrations table. Tenants are migrated independently.

CLI

PGOPTIONS="-c search_path=tenant123" sql-migrate -d ./sql/migrations/ up | sh

Go library

conn, err := pgx.Connect(ctx, pgURL)
_, err = conn.Exec(ctx, fmt.Sprintf(
    "SET search_path TO %s",
    pgx.Identifier{schema}.Sanitize(),
))
runner := pgmigrate.New(conn)

SQL dialect notes

  • CREATE TABLE IF NOT EXISTS works
  • ON CONFLICT DO NOTHING for idempotent seeds
  • String concatenation: id || CHR(9) || name (used by sync query)
  • Timestamps: TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  • Error code 42P01 = table doesn't exist (handled automatically by pgmigrate)