diff --git a/internal/database/schema.go b/internal/database/schema.go index 8a19e54..ae7abe8 100644 --- a/internal/database/schema.go +++ b/internal/database/schema.go @@ -77,6 +77,12 @@ func parseTableNames() ([]string, error) { tables := make(map[string]bool) for scanner.Scan() { line := scanner.Text() + // Skip SQL comments: a doc line like "-- ... declared in CREATE + // TABLE above" would otherwise register a phantom table and fail + // startup verification. + if strings.HasPrefix(strings.TrimSpace(line), "--") { + continue + } matches := pattern.FindStringSubmatch(line) if len(matches) > 1 { tableName := matches[1] diff --git a/internal/database/schema_test.go b/internal/database/schema_test.go new file mode 100644 index 0000000..92fdaec --- /dev/null +++ b/internal/database/schema_test.go @@ -0,0 +1,28 @@ +package database + +import ( + "regexp" + "testing" +) + +// TestParseTableNamesIgnoresComments guards against phantom tables parsed out +// of SQL comments (e.g. "-- ... declared in CREATE TABLE above" once +// registered a table named "above" and crashed startup verification). +func TestParseTableNamesIgnoresComments(t *testing.T) { + tables, err := parseTableNames() + if err != nil { + t.Fatalf("parseTableNames() error: %v", err) + } + if len(tables) == 0 { + t.Fatal("parseTableNames() returned no tables") + } + + for _, name := range tables { + // Every parsed table must correspond to a real CREATE TABLE statement + // at the start of a (non-comment) line. + stmt := regexp.MustCompile(`(?m)^CREATE TABLE (?:IF NOT EXISTS )?(?:\w+\.)?` + regexp.QuoteMeta(name) + `\s`) + if !stmt.MatchString(SchemaFile) { + t.Errorf("parseTableNames() returned phantom table %q with no matching CREATE TABLE statement", name) + } + } +}