What changed, and why it matters
This commit adds a new automated test that checks whether database migration files are correctly named, uniquely numbered, and match the project's internal migration list. It does not change any production code or fix a live bug; it only adds a safety check to catch human errors during future development.
No security action required. Treat as a normal quality-assurance/test-coverage change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change introduces TestMigrationConfigConsistency in sqldb/migrations_test.go. The test inspects embedded SQL schema files under sqlc/migrations, parses their 6-digit zero-padded version prefixes, and validates that: (1) migration file names follow the expected format, (2) no two files share the same schema version, (3) every schema-advancing migration in GetMigrations() has a matching .up.sql file, (4) no two configured migrations claim the same schema version, and (5) migration versions are sequential starting from 1. It is purely a test/migration-consistency guard.
Changed components
sqldb/migrations_test.goInspect captured patch +97 / −0
diff --git a/sqldb/migrations_test.go b/sqldb/migrations_test.go
index 68f1114..399afb1 100644
--- a/sqldb/migrations_test.go
+++ b/sqldb/migrations_test.go
@@ -616,3 +616,100 @@ func TestMigrationSucceedsAfterDirtyStateMigrationFailure19RC1(t *testing.T) {
require.False(t, dirty)
})
}
+
+// TestMigrationConfigConsistency verifies that the migration configuration in
+// migrationConfig is consistent with the actual SQL schema files embedded in
+// the binary. This catches version collisions (e.g. two migrations claiming
+// the same schema version) and missing schema files.
+func TestMigrationConfigConsistency(t *testing.T) {
+ t.Parallel()
+
+ migrations := GetMigrations()
+ require.NotEmpty(t, migrations)
+
+ // Build a set of schema versions that have actual .up.sql files in
+ // the embedded filesystem.
+ embeddedFiles, err := sqlSchemas.ReadDir("sqlc/migrations")
+ require.NoError(t, err)
+
+ fileSchemaVersions := make(map[int]string)
+ for _, f := range embeddedFiles {
+ if f.IsDir() {
+ continue
+ }
+
+ var version int
+ _, err := fmt.Sscanf(f.Name(), "%06d_", &version)
+ require.NoError(t, err, "schema migration file %q is "+
+ "missing a valid numeric prefix (expected "+
+ "format: 000XXX_name.up.sql)", f.Name())
+
+ // Enforce the 6-digit zero-padded naming convention
+ // for consistent directory listing order.
+ expectedPrefix := fmt.Sprintf("%06d_", version)
+ require.True(t,
+ len(f.Name()) > len(expectedPrefix) &&
+ f.Name()[:len(expectedPrefix)] == expectedPrefix,
+ "schema migration file %q should use 6-digit "+
+ "zero-padded prefix %q", f.Name(),
+ expectedPrefix)
+
+ // Verify no two files share the same numeric prefix.
+ if existing, ok := fileSchemaVersions[version]; ok {
+ t.Fatalf("duplicate schema file version %06d: "+
+ "%q and %q", version, existing, f.Name())
+ }
+
+ fileSchemaVersions[version] = f.Name()
+ }
+
+ // Track seen versions to detect duplicates.
+ seenVersions := make(map[int]string)
+ seenSchemaVersions := make(map[int]string)
+
+ for _, m := range migrations {
+ // 1. Verify no duplicate global versions.
+ if existing, ok := seenVersions[m.Version]; ok {
+ t.Fatalf("duplicate global version %d: %q and %q",
+ m.Version, existing, m.Name)
+ }
+ seenVersions[m.Version] = m.Name
+
+ // 2. For schema migrations (those that advance the schema
+ // version), verify a corresponding .up.sql file exists
+ // and no two config entries claim the same schema version
+ // with different file prefixes.
+ prevSchema := 0
+ if m.Version > 1 {
+ prevSchema = migrations[m.Version-2].SchemaVersion
+ }
+
+ // A migration advances the schema if its SchemaVersion is
+ // higher than the previous migration's SchemaVersion.
+ if m.SchemaVersion > prevSchema {
+ _, hasFile := fileSchemaVersions[m.SchemaVersion]
+ require.True(t, hasFile,
+ "migration %q (version %d) declares "+
+ "SchemaVersion=%d but no %06d_*.up.sql"+
+ " file exists in the embedded FS",
+ m.Name, m.Version, m.SchemaVersion,
+ m.SchemaVersion)
+
+ if existing, ok := seenSchemaVersions[m.SchemaVersion]; ok {
+ t.Fatalf("duplicate schema version %d: "+
+ "%q and %q", m.SchemaVersion,
+ existing, m.Name)
+ }
+ seenSchemaVersions[m.SchemaVersion] = m.Name
+ }
+ }
+
+ // 3. Verify versions are sequential starting from 1.
+ for i, m := range migrations {
+ require.Equal(t, i+1, m.Version,
+ "migration %q has version %d but expected %d "+
+ "(migrations must be sequential)",
+ m.Name, m.Version, i+1)
+ }
+
+}
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.