Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Fix nil pointer dereference in skip_parser with managed database
The skip_parser feature was failing with a nil pointer dereference when
used with managed databases because parseCatalog() was trying to use
the parser and catalog, which are nil when skip_parser is enabled.

## Root Cause

When skip_parser is enabled:
1. Parser and catalog are set to nil in NewCompiler
2. parseCatalog() was unconditionally calling c.parser.Parse() (line 46)
3. This caused a nil pointer dereference

However, parseCatalog() still needs to be called even in skip_parser
mode because:
- The schema SQL text needs to be stored in c.schema
- The database analyzer needs c.schema to pass to PostgreSQL

## Fix

Modified parseCatalog() to check if skip_parser is enabled:
- If skip_parser: Read schema files and store in c.schema, skip parsing
- If normal mode: Parse schemas and update catalog as before

Also reverted the change in generate.go that was skipping ParseCatalog
entirely, since we always need to call it (it now handles skip_parser
internally).

## Testing

This fixes the panic in the managed-db context test:
- TestReplay/managed-db/skip_parser/postgresql/pgx/v5

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
  • Loading branch information
claude committed Oct 25, 2025
commit a971343cd1fe046360e2dee08083263eaf5e4594
30 changes: 11 additions & 19 deletions internal/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,28 +305,20 @@ func parse(ctx context.Context, name, dir string, sql config.SQL, combo config.C
fmt.Fprintf(stderr, "error creating compiler: %s\n", err)
return nil, true
}

// Check if skip_parser is enabled
skipParser := sql.Analyzer.SkipParser != nil && *sql.Analyzer.SkipParser

// Skip catalog parsing if skip_parser is enabled
if !skipParser {
if err := c.ParseCatalog(sql.Schema); err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*multierr.Error); ok {
for _, fileErr := range parserErr.Errs() {
printFileErr(stderr, dir, fileErr)
}
} else {
fmt.Fprintf(stderr, "error parsing schema: %s\n", err)
if err := c.ParseCatalog(sql.Schema); err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*multierr.Error); ok {
for _, fileErr := range parserErr.Errs() {
printFileErr(stderr, dir, fileErr)
}
return nil, true
}
if parserOpts.Debug.DumpCatalog {
debug.Dump(c.Catalog())
} else {
fmt.Fprintf(stderr, "error parsing schema: %s\n", err)
}
return nil, true
}
if parserOpts.Debug.DumpCatalog {
debug.Dump(c.Catalog())
}

if err := c.ParseQueries(sql.Queries, parserOpts); err != nil {
fmt.Fprintf(stderr, "# package %s\n", name)
if parserErr, ok := err.(*multierr.Error); ok {
Expand Down
18 changes: 18 additions & 0 deletions internal/compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ func (c *Compiler) parseCatalog(schemas []string) error {
if err != nil {
return err
}

// Check if we're in skip_parser mode
skipParser := c.conf.Analyzer.SkipParser != nil && *c.conf.Analyzer.SkipParser

// If skip_parser is enabled, just read schema files without parsing
if skipParser {
for _, filename := range files {
blob, err := os.ReadFile(filename)
if err != nil {
return fmt.Errorf("reading schema file %s: %w", filename, err)
}
contents := migrations.RemoveRollbackStatements(string(blob))
c.schema = append(c.schema, contents)
}
return nil
}

// Normal path: parse and update catalog
merr := multierr.New()
for _, filename := range files {
blob, err := os.ReadFile(filename)
Expand Down
Loading