diff options
Diffstat (limited to 'vendor/github.com/uptrace/bun/migrate/operations.go')
-rw-r--r-- | vendor/github.com/uptrace/bun/migrate/operations.go | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/vendor/github.com/uptrace/bun/migrate/operations.go b/vendor/github.com/uptrace/bun/migrate/operations.go new file mode 100644 index 000000000..7b749c5a0 --- /dev/null +++ b/vendor/github.com/uptrace/bun/migrate/operations.go @@ -0,0 +1,340 @@ +package migrate + +import ( + "fmt" + + "github.com/uptrace/bun/migrate/sqlschema" +) + +// Operation encapsulates the request to change a database definition +// and knowns which operation can revert it. +// +// It is useful to define "monolith" Operations whenever possible, +// even though they a dialect may require several distinct steps to apply them. +// For example, changing a primary key involves first dropping the old constraint +// before generating the new one. Yet, this is only an implementation detail and +// passing a higher-level ChangePrimaryKeyOp will give the dialect more information +// about the applied change. +// +// Some operations might be irreversible due to technical limitations. Returning +// a *comment from GetReverse() will add an explanatory note to the generate migation file. +// +// To declare dependency on another Operation, operations should implement +// { DependsOn(Operation) bool } interface, which Changeset will use to resolve dependencies. +type Operation interface { + GetReverse() Operation +} + +// CreateTableOp creates a new table in the schema. +// +// It does not report dependency on any other migration and may be executed first. +// Make sure the dialect does not include FOREIGN KEY constraints in the CREATE TABLE +// statement, as those may potentially reference not-yet-existing columns/tables. +type CreateTableOp struct { + TableName string + Model interface{} +} + +var _ Operation = (*CreateTableOp)(nil) + +func (op *CreateTableOp) GetReverse() Operation { + return &DropTableOp{TableName: op.TableName} +} + +// DropTableOp drops a database table. This operation is not reversible. +type DropTableOp struct { + TableName string +} + +var _ Operation = (*DropTableOp)(nil) + +func (op *DropTableOp) DependsOn(another Operation) bool { + drop, ok := another.(*DropForeignKeyOp) + return ok && drop.ForeignKey.DependsOnTable(op.TableName) +} + +// GetReverse for a DropTable returns a no-op migration. Logically, CreateTable is the reverse, +// but DropTable does not have the table's definition to create one. +func (op *DropTableOp) GetReverse() Operation { + c := comment(fmt.Sprintf("WARNING: \"DROP TABLE %s\" cannot be reversed automatically because table definition is not available", op.TableName)) + return &c +} + +// RenameTableOp renames the table. Changing the "schema" part of the table's FQN (moving tables between schemas) is not allowed. +type RenameTableOp struct { + TableName string + NewName string +} + +var _ Operation = (*RenameTableOp)(nil) + +func (op *RenameTableOp) GetReverse() Operation { + return &RenameTableOp{ + TableName: op.NewName, + NewName: op.TableName, + } +} + +// RenameColumnOp renames a column in the table. If the changeset includes a rename operation +// for the column's table, it should be executed first. +type RenameColumnOp struct { + TableName string + OldName string + NewName string +} + +var _ Operation = (*RenameColumnOp)(nil) + +func (op *RenameColumnOp) GetReverse() Operation { + return &RenameColumnOp{ + TableName: op.TableName, + OldName: op.NewName, + NewName: op.OldName, + } +} + +func (op *RenameColumnOp) DependsOn(another Operation) bool { + rename, ok := another.(*RenameTableOp) + return ok && op.TableName == rename.NewName +} + +// AddColumnOp adds a new column to the table. +type AddColumnOp struct { + TableName string + ColumnName string + Column sqlschema.Column +} + +var _ Operation = (*AddColumnOp)(nil) + +func (op *AddColumnOp) GetReverse() Operation { + return &DropColumnOp{ + TableName: op.TableName, + ColumnName: op.ColumnName, + Column: op.Column, + } +} + +// DropColumnOp drop a column from the table. +// +// While some dialects allow DROP CASCADE to drop dependent constraints, +// explicit handling on constraints is preferred for transparency and debugging. +// DropColumnOp depends on DropForeignKeyOp, DropPrimaryKeyOp, and ChangePrimaryKeyOp +// if any of the constraints is defined on this table. +type DropColumnOp struct { + TableName string + ColumnName string + Column sqlschema.Column +} + +var _ Operation = (*DropColumnOp)(nil) + +func (op *DropColumnOp) GetReverse() Operation { + return &AddColumnOp{ + TableName: op.TableName, + ColumnName: op.ColumnName, + Column: op.Column, + } +} + +func (op *DropColumnOp) DependsOn(another Operation) bool { + switch drop := another.(type) { + case *DropForeignKeyOp: + return drop.ForeignKey.DependsOnColumn(op.TableName, op.ColumnName) + case *DropPrimaryKeyOp: + return op.TableName == drop.TableName && drop.PrimaryKey.Columns.Contains(op.ColumnName) + case *ChangePrimaryKeyOp: + return op.TableName == drop.TableName && drop.Old.Columns.Contains(op.ColumnName) + } + return false +} + +// AddForeignKey adds a new FOREIGN KEY constraint. +type AddForeignKeyOp struct { + ForeignKey sqlschema.ForeignKey + ConstraintName string +} + +var _ Operation = (*AddForeignKeyOp)(nil) + +func (op *AddForeignKeyOp) TableName() string { + return op.ForeignKey.From.TableName +} + +func (op *AddForeignKeyOp) DependsOn(another Operation) bool { + switch another := another.(type) { + case *RenameTableOp: + return op.ForeignKey.DependsOnTable(another.TableName) || op.ForeignKey.DependsOnTable(another.NewName) + case *CreateTableOp: + return op.ForeignKey.DependsOnTable(another.TableName) + } + return false +} + +func (op *AddForeignKeyOp) GetReverse() Operation { + return &DropForeignKeyOp{ + ForeignKey: op.ForeignKey, + ConstraintName: op.ConstraintName, + } +} + +// DropForeignKeyOp drops a FOREIGN KEY constraint. +type DropForeignKeyOp struct { + ForeignKey sqlschema.ForeignKey + ConstraintName string +} + +var _ Operation = (*DropForeignKeyOp)(nil) + +func (op *DropForeignKeyOp) TableName() string { + return op.ForeignKey.From.TableName +} + +func (op *DropForeignKeyOp) GetReverse() Operation { + return &AddForeignKeyOp{ + ForeignKey: op.ForeignKey, + ConstraintName: op.ConstraintName, + } +} + +// AddUniqueConstraintOp adds new UNIQUE constraint to the table. +type AddUniqueConstraintOp struct { + TableName string + Unique sqlschema.Unique +} + +var _ Operation = (*AddUniqueConstraintOp)(nil) + +func (op *AddUniqueConstraintOp) GetReverse() Operation { + return &DropUniqueConstraintOp{ + TableName: op.TableName, + Unique: op.Unique, + } +} + +func (op *AddUniqueConstraintOp) DependsOn(another Operation) bool { + switch another := another.(type) { + case *AddColumnOp: + return op.TableName == another.TableName && op.Unique.Columns.Contains(another.ColumnName) + case *RenameTableOp: + return op.TableName == another.NewName + case *DropUniqueConstraintOp: + // We want to drop the constraint with the same name before adding this one. + return op.TableName == another.TableName && op.Unique.Name == another.Unique.Name + default: + return false + } + +} + +// DropUniqueConstraintOp drops a UNIQUE constraint. +type DropUniqueConstraintOp struct { + TableName string + Unique sqlschema.Unique +} + +var _ Operation = (*DropUniqueConstraintOp)(nil) + +func (op *DropUniqueConstraintOp) DependsOn(another Operation) bool { + if rename, ok := another.(*RenameTableOp); ok { + return op.TableName == rename.NewName + } + return false +} + +func (op *DropUniqueConstraintOp) GetReverse() Operation { + return &AddUniqueConstraintOp{ + TableName: op.TableName, + Unique: op.Unique, + } +} + +// ChangeColumnTypeOp set a new data type for the column. +// The two types should be such that the data can be auto-casted from one to another. +// E.g. reducing VARCHAR lenght is not possible in most dialects. +// AutoMigrator does not enforce or validate these rules. +type ChangeColumnTypeOp struct { + TableName string + Column string + From sqlschema.Column + To sqlschema.Column +} + +var _ Operation = (*ChangeColumnTypeOp)(nil) + +func (op *ChangeColumnTypeOp) GetReverse() Operation { + return &ChangeColumnTypeOp{ + TableName: op.TableName, + Column: op.Column, + From: op.To, + To: op.From, + } +} + +// DropPrimaryKeyOp drops the table's PRIMARY KEY. +type DropPrimaryKeyOp struct { + TableName string + PrimaryKey sqlschema.PrimaryKey +} + +var _ Operation = (*DropPrimaryKeyOp)(nil) + +func (op *DropPrimaryKeyOp) GetReverse() Operation { + return &AddPrimaryKeyOp{ + TableName: op.TableName, + PrimaryKey: op.PrimaryKey, + } +} + +// AddPrimaryKeyOp adds a new PRIMARY KEY to the table. +type AddPrimaryKeyOp struct { + TableName string + PrimaryKey sqlschema.PrimaryKey +} + +var _ Operation = (*AddPrimaryKeyOp)(nil) + +func (op *AddPrimaryKeyOp) GetReverse() Operation { + return &DropPrimaryKeyOp{ + TableName: op.TableName, + PrimaryKey: op.PrimaryKey, + } +} + +func (op *AddPrimaryKeyOp) DependsOn(another Operation) bool { + switch another := another.(type) { + case *AddColumnOp: + return op.TableName == another.TableName && op.PrimaryKey.Columns.Contains(another.ColumnName) + } + return false +} + +// ChangePrimaryKeyOp changes the PRIMARY KEY of the table. +type ChangePrimaryKeyOp struct { + TableName string + Old sqlschema.PrimaryKey + New sqlschema.PrimaryKey +} + +var _ Operation = (*AddPrimaryKeyOp)(nil) + +func (op *ChangePrimaryKeyOp) GetReverse() Operation { + return &ChangePrimaryKeyOp{ + TableName: op.TableName, + Old: op.New, + New: op.Old, + } +} + +// comment denotes an Operation that cannot be executed. +// +// Operations, which cannot be reversed due to current technical limitations, +// may return &comment with a helpful message from their GetReverse() method. +// +// Chnagelog should skip it when applying operations or output as log message, +// and write it as an SQL comment when creating migration files. +type comment string + +var _ Operation = (*comment)(nil) + +func (c *comment) GetReverse() Operation { return c } |