diff --git a/internal/sqlparser/postgresql.go b/internal/sqlparser/postgresql.go index f73cd74..051b3b1 100644 --- a/internal/sqlparser/postgresql.go +++ b/internal/sqlparser/postgresql.go @@ -52,13 +52,15 @@ func (p *postgresParser) ParseSchema(files []string) (*catalog.Catalog, error) { case *pg.Node_AlterEnumStmt: p.handleAlterEnum(cat, n.AlterEnumStmt) case *pg.Node_DropStmt: - p.handleDropStmt(cat, n.DropStmt) + p.handleDrop(cat, n.DropStmt) case *pg.Node_IndexStmt: p.handleCreateIndex(cat, n.IndexStmt) case *pg.Node_CreateExtensionStmt: p.handleCreateExtension(cat, n.CreateExtensionStmt) case *pg.Node_ViewStmt: p.handleCreateView(cat, n.ViewStmt) + case *pg.Node_RenameStmt: + p.handleRename(cat, n.RenameStmt) } } } @@ -586,7 +588,7 @@ func (p *postgresParser) handleCreateExtension(cat *catalog.Catalog, n *pg.Creat schema.Extensions = append(schema.Extensions, n.Extname) } -func (p *postgresParser) handleDropStmt(cat *catalog.Catalog, n *pg.DropStmt) { +func (p *postgresParser) handleDrop(cat *catalog.Catalog, n *pg.DropStmt) { if n == nil { return } @@ -760,6 +762,35 @@ func (p *postgresParser) handleCreateView(cat *catalog.Catalog, n *pg.ViewStmt) }) } +// handleRename processes ALTER TABLE ... RENAME TO / RENAME COLUMN, which +// Postgres represents as a separate RenameStmt node, not an AlterTableCmd. +func (p *postgresParser) handleRename(cat *catalog.Catalog, n *pg.RenameStmt) { + if n == nil || n.Relation == nil { + return + } + + schemaName := n.Relation.Schemaname + if schemaName == "" { + schemaName = cat.DefaultSchema + } + table := p.findTable(cat, schemaName, n.Relation.Relname) + if table == nil { + return + } + + switch n.RenameType { + case pg.ObjectType_OBJECT_TABLE: + table.Name = n.Newname + case pg.ObjectType_OBJECT_COLUMN: + for _, col := range table.Columns { + if col.Name == n.Subname { + col.Name = n.Newname + break + } + } + } +} + // resolveViewColumns extracts column names and types from a CREATE VIEW statement. func (p *postgresParser) resolveViewColumns(cat *catalog.Catalog, n *pg.ViewStmt) []*catalog.Column { if n.Query == nil { diff --git a/internal/sqlparser/postgresql_test.go b/internal/sqlparser/postgresql_test.go index 1f0b975..fa38adf 100644 --- a/internal/sqlparser/postgresql_test.go +++ b/internal/sqlparser/postgresql_test.go @@ -292,6 +292,41 @@ func TestPostgresAlterTable(t *testing.T) { } } +func TestPostgresRenameTableAndColumn(t *testing.T) { + path := writeTemp(t, ` + CREATE TABLE old_name ( + id SERIAL PRIMARY KEY, + bio TEXT NULL + ); + ALTER TABLE old_name RENAME TO new_name; + ALTER TABLE new_name RENAME COLUMN bio TO description; + `) + + p := newPostgresParser() + cat, err := p.ParseSchema([]string{path}) + if err != nil { + t.Fatalf("ParseSchema error: %v", err) + } + + table := cat.Schemas[0].Tables[0] + if table.Name != "new_name" { + t.Fatalf("expected table 'new_name', got %q", table.Name) + } + + found := false + for _, col := range table.Columns { + if col.Name == "description" { + found = true + } + if col.Name == "bio" { + t.Error("column 'bio' should have been renamed to 'description'") + } + } + if !found { + t.Error("expected renamed column 'description' not found") + } +} + func TestPostgresDropTable(t *testing.T) { path := writeTemp(t, ` CREATE TABLE temp_data (id SERIAL PRIMARY KEY, data TEXT);