Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and use a table cleanup assertion function #493

Merged
merged 2 commits into from
Nov 26, 2024
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
18 changes: 4 additions & 14 deletions pkg/migrations/op_change_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,14 @@ func TestChangeColumnType(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `rating` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "reviews", migrations.TemporaryName("rating"))

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reviews", "rating"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reviews", migrations.TemporaryName("rating")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "reviews", migrations.TriggerName("reviews", "rating"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "reviews", migrations.TriggerName("reviews", migrations.TemporaryName("rating")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "reviews", "rating")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
newVersionSchema := roll.VersionedSchemaName(schema, "02_change_type")

// The new (temporary) `rating` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "reviews", migrations.TemporaryName("rating"))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "reviews", "rating")

// The `rating` column in the new view must have the correct type.
ColumnMustHaveType(t, db, newVersionSchema, "reviews", "rating", "integer")
Expand Down
26 changes: 26 additions & 0 deletions pkg/migrations/op_common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,32 @@ func MustSelect(t *testing.T, db *sql.DB, schema, version, table string) []map[s
return res
}

// TableMustBeCleanedUp asserts that the `columns` on `table` in `schema` have
// been cleaned up after migration rollback or completion. This means:
// - The temporary columns should not exist on the underlying table.
// - The up functions for the columns no longer exist.
// - The down functions for the columns no longer exist.
// - The up triggers for the columns no longer exist.
// - The down triggers for the columns no longer exist.
func TableMustBeCleanedUp(t *testing.T, db *sql.DB, schema, table string, columns ...string) {
andrew-farries marked this conversation as resolved.
Show resolved Hide resolved
t.Helper()

for _, column := range columns {
// The temporary column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, table, migrations.TemporaryName(column))

// The up function for the column no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName(table, column))
// The down function for the column no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName(table, migrations.TemporaryName(column)))

// The up trigger for the column no longer exists.
TriggerMustNotExist(t, db, schema, table, migrations.TriggerName(table, column))
// The down trigger for the column no longer exists.
TriggerMustNotExist(t, db, schema, table, migrations.TriggerName(table, migrations.TemporaryName(column)))
}
}

func mustSetSearchPath(t *testing.T, db *sql.DB, schema string) {
t.Helper()

Expand Down
43 changes: 14 additions & 29 deletions pkg/migrations/op_create_constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ func TestCreateConstraint(t *testing.T) {
IndexMustNotExist(t, db, schema, "users", "uniue_name")

// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "name")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "name")

// Inserting values into the new schema that violate uniqueness should fail.
MustInsert(t, db, schema, "02_create_constraint", "users", map[string]string{
Expand Down Expand Up @@ -161,11 +161,11 @@ func TestCreateConstraint(t *testing.T) {
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "name")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "name")

// Inserting values into the new schema that violate the check constraint should fail.
MustNotInsert(t, db, schema, "02_create_constraint", "users", map[string]string{
Expand Down Expand Up @@ -250,8 +250,8 @@ func TestCreateConstraint(t *testing.T) {
IndexMustNotExist(t, db, schema, "users", "unique_name_email")

// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
tableCleanedUp(t, db, schema, "users", "email")
TableMustBeCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "email")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Complete is a no-op.
Expand Down Expand Up @@ -334,13 +334,13 @@ func TestCreateConstraint(t *testing.T) {
// The check constraint must not exists on the table.
CheckConstraintMustNotExist(t, db, schema, "users", "check_name_email")
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
tableCleanedUp(t, db, schema, "users", "email")
TableMustBeCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "email")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "users", "name")
tableCleanedUp(t, db, schema, "users", "email")
TableMustBeCleanedUp(t, db, schema, "users", "name")
TableMustBeCleanedUp(t, db, schema, "users", "email")

// Inserting values into the new schema that the violate the check constraint must fail.
MustNotInsert(t, db, schema, "02_create_constraint", "users", map[string]string{
Expand Down Expand Up @@ -474,13 +474,13 @@ func TestCreateConstraint(t *testing.T) {
// The check constraint must not exists on the table.
CheckConstraintMustNotExist(t, db, schema, "reports", "fk_users")
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "reports", "users_id")
tableCleanedUp(t, db, schema, "reports", "users_zip")
TableMustBeCleanedUp(t, db, schema, "reports", "users_id")
TableMustBeCleanedUp(t, db, schema, "reports", "users_zip")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Functions, triggers and temporary columns are dropped.
tableCleanedUp(t, db, schema, "reports", "users_id")
tableCleanedUp(t, db, schema, "reports", "users_zip")
TableMustBeCleanedUp(t, db, schema, "reports", "users_id")
TableMustBeCleanedUp(t, db, schema, "reports", "users_zip")

// Inserting values into the new schema that the violate the check constraint must fail.
MustNotInsert(t, db, schema, "02_create_constraint", "reports", map[string]string{
Expand Down Expand Up @@ -683,18 +683,3 @@ func TestCreateConstraint(t *testing.T) {
},
})
}

func tableCleanedUp(t *testing.T, db *sql.DB, schema, table, column string) {
// The new, temporary column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, table, migrations.TemporaryName(column))

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName(table, column))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName(table, migrations.TemporaryName(column)))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, table, migrations.TriggerName(table, column))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, table, migrations.TriggerName(table, migrations.TemporaryName(column)))
}
68 changes: 12 additions & 56 deletions pkg/migrations/op_drop_constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,8 @@ func TestDropConstraint(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `title` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "posts", migrations.TemporaryName("title"))

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", "title"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", migrations.TemporaryName("title")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", "title"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", migrations.TemporaryName("title")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "posts", "title")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Inserting a row that does not meet the check constraint into the new view works.
Expand All @@ -134,15 +124,8 @@ func TestDropConstraint(t *testing.T) {
{"id": 5, "title": "e"},
}, rows)

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", "title"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", migrations.TemporaryName("title")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", "title"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", migrations.TemporaryName("title")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "posts", "title")
},
},
{
Expand Down Expand Up @@ -332,18 +315,8 @@ func TestDropConstraint(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `user_id` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "posts", migrations.TemporaryName("user_id"))

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", "user_id"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", migrations.TemporaryName("user_id")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", "user_id"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", migrations.TemporaryName("user_id")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "posts", "user_id")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `user_id` column should not exist on the underlying table.
Expand All @@ -364,15 +337,8 @@ func TestDropConstraint(t *testing.T) {
{"id": 5, "title": "another post by an unknown user", "user_id": 4},
}, rows)

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", "user_id"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("posts", migrations.TemporaryName("user_id")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", "user_id"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "posts", migrations.TriggerName("posts", migrations.TemporaryName("user_id")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "posts", "user_id")
},
},
{
Expand Down Expand Up @@ -430,22 +396,12 @@ func TestDropConstraint(t *testing.T) {
})
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `name` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "users", migrations.TemporaryName("name"))

// The up function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("users", "name"))
// The down function no longer exists.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("users", migrations.TemporaryName("name")))

// The up trigger no longer exists.
TriggerMustNotExist(t, db, schema, "users", migrations.TriggerName("users", "name"))
// The down trigger no longer exists.
TriggerMustNotExist(t, db, schema, "users", migrations.TriggerName("users", migrations.TemporaryName("name")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "users", "name")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// The new (temporary) `name` column should not exist on the underlying table.
ColumnMustNotExist(t, db, schema, "users", migrations.TemporaryName("name"))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "users", "name")

// Inserting a row that does not meet the unique constraint into the new view works.
MustInsert(t, db, schema, "02_drop_unique_constraint", "users", map[string]string{
Expand Down
63 changes: 6 additions & 57 deletions pkg/migrations/op_drop_multicolumn_constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,25 +124,8 @@ func TestDropMultiColumnConstraint(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The temporary columns no longer exist.
ColumnMustNotExist(t, db, schema, "products", migrations.TemporaryName("price"))
ColumnMustNotExist(t, db, schema, "products", migrations.TemporaryName("discount"))

// The up functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", "price"))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", "discount"))

// The down functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", migrations.TemporaryName("price")))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", migrations.TemporaryName("discount")))

// The up triggers no longer exist.
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", "price"))
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", "discount"))

// The down triggers no longer exist.
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", migrations.TemporaryName("price")))
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", migrations.TemporaryName("discount")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "products", "price", "discount")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Inserting a row into the new schema that violates the check constraint succeeds.
Expand Down Expand Up @@ -257,25 +240,8 @@ func TestDropMultiColumnConstraint(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The temporary columns no longer exist.
ColumnMustNotExist(t, db, schema, "products", migrations.TemporaryName("name"))
ColumnMustNotExist(t, db, schema, "products", migrations.TemporaryName("description"))

// The up functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", "name"))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", "description"))

// The down functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", migrations.TemporaryName("name")))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("products", migrations.TemporaryName("description")))

// The up triggers no longer exist.
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", "name"))
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", "description"))

// The down triggers no longer exist.
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", migrations.TemporaryName("name")))
TriggerMustNotExist(t, db, schema, "products", migrations.TriggerName("products", migrations.TemporaryName("description")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "products", "name", "description")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Inserting a row into the new schema that violates the unique constraint succeeds.
Expand Down Expand Up @@ -423,25 +389,8 @@ func TestDropMultiColumnConstraint(t *testing.T) {
}, rows)
},
afterRollback: func(t *testing.T, db *sql.DB, schema string) {
// The temporary columns no longer exist.
ColumnMustNotExist(t, db, schema, "reports", migrations.TemporaryName("user_id"))
ColumnMustNotExist(t, db, schema, "reports", migrations.TemporaryName("user_zip"))

// The up functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reports", "user_id"))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reports", "user_zip"))

// The down functions no longer exist.
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reports", migrations.TemporaryName("user_id")))
FunctionMustNotExist(t, db, schema, migrations.TriggerFunctionName("reports", migrations.TemporaryName("user_zip")))

// The up triggers no longer exist.
TriggerMustNotExist(t, db, schema, "reports", migrations.TriggerName("reports", "user_id"))
TriggerMustNotExist(t, db, schema, "reports", migrations.TriggerName("reports", "user_zip"))

// The down triggers no longer exist.
TriggerMustNotExist(t, db, schema, "reports", migrations.TriggerName("reports", migrations.TemporaryName("user_id")))
TriggerMustNotExist(t, db, schema, "reports", migrations.TriggerName("reports", migrations.TemporaryName("user_zip")))
// The table is cleaned up; temporary columns, trigger functions and triggers no longer exist.
TableMustBeCleanedUp(t, db, schema, "reports", "user_id", "user_zip")
},
afterComplete: func(t *testing.T, db *sql.DB, schema string) {
// Inserting a row that violates the FK constraint into the new schema succeeds.
Expand Down
Loading