Skip to content

Commit

Permalink
Reduce duplication in CREATE TABLE and ADD COLUMN
Browse files Browse the repository at this point in the history
There is a lot of duplication between the `CREATE TABLE` and `ALTER
TABLE ADD COLUMN` conversion code.

Reduce the duplication by having the ALTER TABLE ADD COLUMN conversion
code and the CREATE TABLE conversion code use the same
`convertColumnDef` function, which handles the conversion of a column
definition to a `migrations.Column` struct along with the conversion of
the column constraints.
  • Loading branch information
andrew-farries committed Jan 2, 2025
1 parent cef3018 commit 8e57056
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 96 deletions.
106 changes: 11 additions & 95 deletions pkg/sql2pgroll/alter_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,108 +406,24 @@ func convertAlterTableAddColumn(stmt *pgq.AlterTableStmt, cmd *pgq.AlterTableCmd
return nil, nil
}

columnDef := cmd.GetDef().GetColumnDef()
if !canConvertColumnDef(columnDef) {
return nil, nil
}

columnType, err := pgq.DeparseTypeName(columnDef.GetTypeName())
qualifiedName := getQualifiedRelationName(stmt.GetRelation())
column, err := convertColumnDef(qualifiedName, cmd.GetDef().GetColumnDef())
if err != nil {
return nil, fmt.Errorf("failed to deparse type name: %w", err)
return nil, fmt.Errorf("error converting column definition: %w", err)
}

operation := &migrations.OpAddColumn{
Column: migrations.Column{
Name: columnDef.GetColname(),
Type: columnType,
Nullable: true,
},
Table: getQualifiedRelationName(stmt.GetRelation()),
Up: PlaceHolderSQL,
}

if len(columnDef.GetConstraints()) > 0 {
for _, constraint := range columnDef.GetConstraints() {
switch constraint.GetConstraint().GetContype() {
case pgq.ConstrType_CONSTR_NULL:
operation.Column.Nullable = true
case pgq.ConstrType_CONSTR_NOTNULL:
operation.Column.Nullable = false
case pgq.ConstrType_CONSTR_PRIMARY:
operation.Column.Pk = true
operation.Column.Nullable = false
case pgq.ConstrType_CONSTR_UNIQUE:
operation.Column.Unique = true
case pgq.ConstrType_CONSTR_CHECK:
raw, err := pgq.DeparseExpr(constraint.GetConstraint().GetRawExpr())
if err != nil {
return nil, fmt.Errorf("failed to deparse raw expression: %w", err)
}
operation.Column.Check = &migrations.CheckConstraint{
Constraint: raw,
Name: constraint.GetConstraint().GetConname(),
}
case pgq.ConstrType_CONSTR_DEFAULT:
defaultExpr := constraint.GetConstraint().GetRawExpr()
def, err := extractDefault(defaultExpr)
if err != nil {
return nil, err
}
if !def.IsNull() {
v := def.MustGet()
operation.Column.Default = &v
}
case pgq.ConstrType_CONSTR_FOREIGN:
onDelete, err := parseOnDeleteAction(constraint.GetConstraint().GetFkDelAction())
if err != nil {
return nil, err
}
fk := &migrations.ForeignKeyReference{
Name: constraint.GetConstraint().GetConname(),
OnDelete: onDelete,
Column: constraint.GetConstraint().GetPkAttrs()[0].GetString_().GetSval(),
Table: getQualifiedRelationName(constraint.GetConstraint().GetPktable()),
}
operation.Column.References = fk
}
}
if column == nil {
return nil, nil
}

return operation, nil
return &migrations.OpAddColumn{
Column: *column,
Table: qualifiedName,
Up: PlaceHolderSQL,
}, nil
}

func canConvertAddColumn(cmd *pgq.AlterTableCmd) bool {
if cmd.GetMissingOk() {
return false
}
for _, constraint := range cmd.GetDef().GetColumnDef().GetConstraints() {
switch constraint.GetConstraint().GetContype() {
case pgq.ConstrType_CONSTR_DEFAULT,
pgq.ConstrType_CONSTR_NULL,
pgq.ConstrType_CONSTR_NOTNULL,
pgq.ConstrType_CONSTR_PRIMARY,
pgq.ConstrType_CONSTR_UNIQUE,
pgq.ConstrType_CONSTR_FOREIGN,
pgq.ConstrType_CONSTR_CHECK:
switch constraint.GetConstraint().GetFkUpdAction() {
case "r", "c", "n", "d":
// RESTRICT, CASCADE, SET NULL, SET DEFAULT
return false
case "a":
// NO ACTION, the default
break
}
case pgq.ConstrType_CONSTR_ATTR_DEFERRABLE,
pgq.ConstrType_CONSTR_ATTR_DEFERRED,
pgq.ConstrType_CONSTR_IDENTITY,
pgq.ConstrType_CONSTR_GENERATED:
return false
case pgq.ConstrType_CONSTR_ATTR_NOT_DEFERRABLE, pgq.ConstrType_CONSTR_ATTR_IMMEDIATE:
break
}
}

return true
return !cmd.GetMissingOk()
}

func convertAlterTableDropColumn(stmt *pgq.AlterTableStmt, cmd *pgq.AlterTableCmd) (migrations.Operation, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql2pgroll/expect/add_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ var AddColumnOp6 = &migrations.OpAddColumn{
Nullable: true,
Check: &migrations.CheckConstraint{
Constraint: "bar > 0",
Name: "",
Name: "foo_bar_check",
},
},
}
Expand Down

0 comments on commit 8e57056

Please sign in to comment.