database/sqlmigrate: allow optional schema prefix in INSERT INTO _migrations

Update idFromInsert regex to match schema-qualified table references
such as INSERT INTO authz._migrations, in addition to the existing
unqualified INSERT INTO _migrations form.
This commit is contained in:
AJ ONeal 2026-04-17 02:30:41 -06:00
parent 02fef67e53
commit 17bbc881a9
No known key found for this signature in database
2 changed files with 16 additions and 2 deletions

View File

@ -65,9 +65,9 @@ type Migrator interface {
}
// idFromInsert extracts the hex ID from an INSERT INTO _migrations line.
// Matches: INSERT INTO _migrations (name, id) VALUES ('...', '<hex>');
// Matches: INSERT INTO [schema.]_migrations (name, id) VALUES ('...', '<hex>');
var idFromInsert = regexp.MustCompile(
`(?i)INSERT\s+INTO\s+_migrations\s*\(\s*name\s*,\s*id\s*\)\s*VALUES\s*\(\s*'[^']*'\s*,\s*'([0-9a-fA-F]+)'\s*\)`,
`(?i)INSERT\s+INTO\s+(?:\w+\.)?_migrations\s*\(\s*name\s*,\s*id\s*\)\s*VALUES\s*\(\s*'[^']*'\s*,\s*'([0-9a-fA-F]+)'\s*\)`,
)
// Collect reads .up.sql and .down.sql files from fsys under subpath,

View File

@ -107,6 +107,20 @@ func TestCollect(t *testing.T) {
}
})
t.Run("parses ID from schema-prefixed INSERT", func(t *testing.T) {
fsys := fstest.MapFS{
"001_init.up.sql": {Data: []byte("CREATE TABLE authz._migrations (id CHAR(8) PRIMARY KEY, name VARCHAR(80));\nINSERT INTO authz._migrations (name, id) VALUES ('001_init', 'abcd1234');")},
"001_init.down.sql": {Data: []byte("DROP TABLE authz._migrations;")},
}
ddls, err := sqlmigrate.Collect(fsys, ".")
if err != nil {
t.Fatal(err)
}
if ddls[0].ID != "abcd1234" {
t.Errorf("ID = %q, want %q", ddls[0].ID, "abcd1234")
}
})
t.Run("no ID when no INSERT", func(t *testing.T) {
fsys := fstest.MapFS{
"001_init.up.sql": {Data: []byte("CREATE TABLE a;")},