Migrate took the target version as a separate argument, kept in step with the steps by hand:
adding a step without bumping the version constant silently skipped it on existing installs,
while fresh installs got the new tables. The target is now the version after the last step (1
without steps), and the steps must be contiguous, so a forgotten one fails at startup. The
per-store version constants are gone.
Each migration step is now a schema.Migration: schema.Query, schema.Func or schema.Nop for additive
steps, wrapped in schema.Breaking for a breaking one. Migrate derives the store's minimum version
(the version after the newest breaking step, or 1) instead of taking it from a per-store constant,
so a breaking migration cannot be added without raising the minimum. The existing steps are all
marked additive; older code never checks the minimum, so classifying them changes nothing.
#2059 lets older code start on a newer schema, which is only safe while migrations are additive.
For the rare breaking migration, each store now records the oldest schema version whose code still
runs on its schema (min_version in the version table). A breaking migration raises it; older code
then fails at startup with a clear error instead of misreading the data.
- schema.Migrate takes minVersion; every store passes its MinSchemaVersion constant (1: no
breaking migration recorded)
- The version table gets a min_version column (default 1), added in place to existing tables;
older code writes only the version and keeps working on the new table
Extract database operations from Manager into a Store interface with
SQLite and PostgreSQL implementations using a shared commonStore.
Split SQLite migrations into store_sqlite_migrations.go, use shared
schema_version table for PostgreSQL, rename user_user/user_tier tables
to "user"/tier, and wire up database-url in CLI commands.
Consolidate SQLite and Postgres store implementations into a single
commonStore with database-specific SQL queries passed via configuration.
This eliminates ~100 lines of duplicate code while maintaining full
functionality for both backends.
Key changes:
- Move all store methods to commonStore in store.go
- Remove sqliteStore and postgresStore wrapper structs
- Refactor SQLite to use QueryRow() pattern like Postgres
- Pass database-specific queries via storeQueries struct
- Make store types unexported, only expose Store interface
All tests pass for both SQLite and PostgreSQL backends.
- Add SetSubscriptionUpdatedAt to Store interface, remove DB() accessor
- Rename store files to store_sqlite.go and store_postgres.go
- Use camelCase for test function names
- Add tests for upsert field updates and multi-user removal
- Use transaction in setupNewPostgresDB
- Use lowercase "excluded." in PostgreSQL upsert query
Share test logic in store_test.go with thin per-backend wrappers.
Add SetSubscriptionUpdatedAt to both stores, removing the need for
raw SQL and the DB() accessor in tests.