9 Commits

Author SHA1 Message Date
65432d7c29
database/sqlmigrate/pgmigrate: add Schema field for qualified _migrations table
Add Schema string field to Migrator. When set, Applied() constructs a
schema-qualified table name via pgx.Identifier.Sanitize() rather than
the bare "_migrations". New() signature is unchanged.

Usage:
    runner := pgmigrate.New(conn)
    runner.Schema = "authz"
2026-04-17 03:53:32 -06:00
aebef71a95
test(sqlmigrate): add ordering, end-to-end, rollback, and dialect-specific tests
Across all four backends:

- TestAppliedOrdering: insert rows out of order, verify Applied()
  returns them sorted by name. Guards against the ORDER BY clause
  being dropped or the query returning rows in arbitrary order.
- TestEndToEndCycle: Collect → Up → Applied → Down → Applied via
  the sqlmigrate orchestrator with real migration files. Catches
  wiring bugs between Migrator and orchestrator that the in-package
  mockMigrator tests cannot.
- TestDMLRollback: multi-statement DML migration where the last
  statement fails, verifies earlier INSERTs are rolled back. MySQL
  note: DML-only because MySQL implicitly commits DDL.

Dialect-specific:

- mymigrate TestMultiStatementsRequired: strip multiStatements=true
  from the DSN, verify ExecUp fails with a clear error mentioning
  multiStatements (rather than silently running only the first
  statement of a multi-statement migration).
- litemigrate TestForeignKeyEnforcement: verifies FK constraints
  are enforced when the DSN includes _pragma=foreign_keys(1).

Test fixture fix: cleanup closures now use context.Background()
instead of the test context. t.Context() is canceled before
t.Cleanup runs, so DB cleanup silently failed. Previously the
_migrations cleanup appeared to work because the next test's
connect() re-ran DROP TABLE at setup, but domain tables (test_*)
leaked across runs. New tests also pre-clean at setup for
self-healing after interrupted runs.
2026-04-10 01:07:58 -06:00
3402b60bc6
fix(sqlmigrate): defensive table-missing check at rows.Err() across backends
Apply the same lazy-error pattern fix to all backends, plus regression
tests that catch the bug.

pgmigrate is the confirmed-broken case (pgx/v5's Conn.Query is lazy and
surfaces 42P01 at rows.Err() once the prepared statement cache is primed).
The defensive check at rows.Err() is also added to mymigrate and msmigrate
in case their drivers exhibit similar behavior in some configurations.

litemigrate is refactored to probe sqlite_master with errors.Is(sql.ErrNoRows)
instead of string-matching the error message — SQLite returns the generic
SQLITE_ERROR code for "no such table" so a typed-error approach isn't
possible at the driver layer; the probe lets us use idiomatic errors.Is.

Tests:
- litemigrate: in-memory SQLite, runs on every go test (no infra)
- pgmigrate:   PG_TEST_URL env-gated; verified against real Postgres,
               TestAppliedAfterDropTable reproduces the agent's exact error
               message ("reading rows: ... 42P01") without the fix
- mymigrate:   MYSQL_TEST_DSN env-gated
- msmigrate:   MSSQL_TEST_URL env-gated; verified against real SQL Server

Each backend has four cases: missing table, populated table, empty table,
and table-dropped-after-cache-primed (the lazy-error scenario).
2026-04-10 00:15:06 -06:00
e11b228765
fix(pgmigrate): handle 42P01 surfaced lazily at rows.Err()
pgx/v5's Conn.Query is lazy — when the queried table doesn't exist,
the 42P01 error doesn't surface at Query() time, it surfaces at
rows.Err() after the iteration loop. The original code only checked
for 42P01 at the Query() site, so first-run migrations against an
empty database failed with:

    reading rows: ERROR: relation "_migrations" does not exist (SQLSTATE 42P01)

Apply the typed-error check at both sites via a shared helper.
2026-04-10 00:01:55 -06:00
d5d1df060f fix(pgmigrate): take *pgx.Conn instead of *pgxpool.Pool
Migrations run sequentially on a single connection — a pool adds
unnecessary complexity and forces callers to create one. This also
drops the puddle/v2 and x/sync transitive dependencies.
2026-04-09 10:56:47 -06:00
5783d4fc7a
ref(backends): update all backends and sql-migrate to sqlmigrate v1.0.2
ExecUp/ExecDown now take (ctx, Migration, sql string) instead of
(ctx, Migration) with embedded Up/Down fields. Applied returns
[]Migration instead of []AppliedMigration.

- pgmigrate, mymigrate, litemigrate, msmigrate: new interface, v1.0.2 dep
- shmigrate: v1.0.2 dep, remove temporary replace directive
- cmd/sql-migrate: v1.0.2 dep
2026-04-09 03:27:35 -06:00
9614dea7df fix(pgmigrate): update sqlmigrate dep to v1.0.1, replace nolint with explicit throwaway 2026-04-09 02:35:42 -06:00
a8bc605ebf
fix(pgmigrate): update sqlmigrate dependency to v1.0.1 2026-04-09 02:20:36 -06:00
b5d9c7fab7
feat(pgmigrate): add PostgreSQL backend for sqlmigrate 2026-04-09 02:14:40 -06:00