Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions internal/migration_acceptance_tests/column_cases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,23 @@ var columnAcceptanceTestCases = []acceptanceTestCase{
`,
},
},
{
name: "Add identity to column with existing default",
oldSchemaDDL: []string{
`
CREATE TABLE foobar(
identity_always BIGINT DEFAULT 5
);
`,
},
newSchemaDDL: []string{
`
CREATE TABLE foobar(
identity_always BIGINT GENERATED ALWAYS AS IDENTITY
);
`,
},
},
{
name: "Alter identity type - to by default",
oldSchemaDDL: []string{
Expand Down
27 changes: 17 additions & 10 deletions pkg/diff/sql_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,23 @@ func (csg *columnSQLVertexGenerator) Alter(diff columnDiff) ([]Statement, error)
})
}

// Drop the default before type conversion. This will allow type conversions
// between incompatible types if the previous column has a default and the new column is dropping its default.
// It also must be dropped before an identity is added to the column, otherwise adding the identity errors
// with "a default already exists."
//
// To keep the code simpler, put dropping the default before updating the column identity AND dropping the default.
// There is an argument to drop the default after removing the not null constraint, since writes will continue to succeed
// on columns migrating from not-null and a default to nullable with no default; however, this would not work
// for the case where an identity is being added to the column.
if len(oldColumn.Default) > 0 && len(newColumn.Default) == 0 {
stmts = append(stmts, Statement{
DDL: fmt.Sprintf("%s DROP DEFAULT", alterColumnPrefix),
Timeout: statementTimeoutDefault,
LockTimeout: lockTimeoutDefault,
})
}

updateIdentityStmts, err := csg.buildUpdateIdentityStatements(oldColumn, newColumn)
if err != nil {
return nil, fmt.Errorf("building update identity statements: %w", err)
Expand All @@ -1197,16 +1214,6 @@ func (csg *columnSQLVertexGenerator) Alter(diff columnDiff) ([]Statement, error)
})
}

if len(oldColumn.Default) > 0 && len(newColumn.Default) == 0 {
// Drop the default before type conversion. This will allow type conversions
// between incompatible types if the previous column has a default and the new column is dropping its default
stmts = append(stmts, Statement{
DDL: fmt.Sprintf("%s DROP DEFAULT", alterColumnPrefix),
Timeout: statementTimeoutDefault,
LockTimeout: lockTimeoutDefault,
})
}

if !strings.EqualFold(oldColumn.Type, newColumn.Type) ||
!strings.EqualFold(oldColumn.Collation.GetFQEscapedName(), newColumn.Collation.GetFQEscapedName()) {
stmts = append(stmts,
Expand Down