migrator

package
v0.0.0-...-7301b28 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2025 License: GPL-2.0 Imports: 34 Imported by: 1

Documentation

Index

Constants

View Source
const (
	DEFAULT_MIGRATION_DIR      = "./migrations"
	MAGIC_AMOUNT_OF_MIGRATIONS = 3
)
View Source
const (
	MIGRATION_FILE_SUFFIX = ".mig"

	ErrNoChanges errs.Error = "migrations not created, no changes detected."
)
View Source
const (
	// Keys for attrs.Field
	AttrDBTypeKey   = "migrator.db_type"
	AttrUseInDBKey  = "migrator.use_in_db"
	AttrOnDeleteKey = "migrator.on_delete"
	AttrOnUpdateKey = "migrator.on_update"

	// Keys for attrs.ModelMeta
	MetaAllowMigrateKey = "migrator.allow_migrate"

	// The directory where the migration files are stored
	APPVAR_MIGRATION_DIR = "migrator.migration_dir"
)

Variables

This section is empty.

Functions

func CanAutoIncrement

func CanAutoIncrement(field attrs.FieldDefinition) bool

func CheckCanMigrate

func CheckCanMigrate(obj any) bool

func EqualDefaultValue

func EqualDefaultValue(a, b any) bool

func GetFieldType

func GetFieldType(driver driver.Driver, c *Column) string

GetFieldType returns the database type for a field based on the driver and field type.

It first checks if the field has a custom database type defined in its attributes referenced by AttrDBTypeKey, and if not, it uses the registered functions to determine the type.

func NewAppConfig

func NewAppConfig() *migratorAppConfig

func RegisterColumnType

func RegisterColumnType(driver driver.Driver, typ dbtype.Type, fn func(c *Column) string)

RegisterColumnType registers a function to convert a field to a database type for a specific driver and type.

The function will be called with the field as an argument and should return the database type as a string.

func RegisterFileSystem

func RegisterFileSystem(app string, fSys fs.FS) int8

func RegisterSchemaEditor

func RegisterSchemaEditor(driver driver.Driver, fn func() (SchemaEditor, error))

Types

type Action

type Action int

Action is the action to take when the target model is deleted or updated.

const (
	// OnDeleteCascade is the action to cascade the delete to the target model.
	CASCADE Action = iota
	// OnDeleteRestrict is the action to restrict the delete of the target model.
	RESTRICT
	// OnDeleteSetNull is the action to set the field to null when the target model is deleted.
	SET_NULL
)

func (Action) String

func (a Action) String() string

type ActionType

type ActionType int
const (
	ActionCreateTable ActionType = iota + 1
	ActionDropTable
	ActionRenameTable
	ActionAddIndex
	ActionDropIndex
	ActionRenameIndex
	// ActionAlterUniqueTogether
	// ActionAlterIndexTogether
	ActionAddField
	ActionAlterField
	ActionRemoveField
)

func (ActionType) MarshalJSON

func (a ActionType) MarshalJSON() ([]byte, error)

func (ActionType) String

func (a ActionType) String() string

func (*ActionType) UnmarshalJSON

func (a *ActionType) UnmarshalJSON(data []byte) error

type CanColumnDBType

type CanColumnDBType interface {
	DBType(*Column) dbtype.Type
}

type CanMigrate

type CanMigrate interface {
	CanMigrate() bool
}

type CanSQL

type CanSQL[T any] interface {
	SQL(T) (string, []any)
}

type CantMigrate

type CantMigrate struct{}

Embed this struct in your model or fields to indicate that it cannot be migrated.

func (*CantMigrate) CanMigrate

func (c *CantMigrate) CanMigrate() bool

type Changed

type Changed[T any] struct {
	Old T `json:"old,omitempty"`
	New T `json:"new,omitempty"`
}

type Column

type Column struct {
	Table        Table              `json:"-"`
	Field        attrs.Field        `json:"-"`
	Name         string             `json:"name"`
	Column       string             `json:"column"`
	UseInDB      bool               `json:"use_in_db,omitempty"`
	MinLength    int64              `json:"min_length,omitempty"`
	MaxLength    int64              `json:"max_length,omitempty"`
	MinValue     float64            `json:"min_value,omitempty"`
	MaxValue     float64            `json:"max_value,omitempty"`
	Precision    int64              `json:"precision,omitempty"`
	Scale        int64              `json:"scale,omitempty"` // for decimal types
	Unique       bool               `json:"unique,omitempty"`
	Nullable     bool               `json:"nullable,omitempty"`
	Primary      bool               `json:"primary,omitempty"`
	Auto         bool               `json:"auto,omitempty"`
	Default      interface{}        `json:"default"`
	ReverseAlias string             `json:"reverse_alias,omitempty"`
	Rel          *MigrationRelation `json:"relation,omitempty"`
}

func NewTableColumn

func NewTableColumn(table Table, field attrs.Field) Column

func (*Column) DBType

func (c *Column) DBType() dbtype.Type

func (*Column) Equals

func (c *Column) Equals(other *Column) bool

func (*Column) FieldType

func (c *Column) FieldType() reflect.Type

func (*Column) HasDefault

func (c *Column) HasDefault() bool

even zero values are considered valid defaults

func (*Column) String

func (c *Column) String() string

type Dependency

type Dependency struct {
	AppName   string
	ModelName string
	Name      string
}

func (*Dependency) MarshalJSON

func (d *Dependency) MarshalJSON() ([]byte, error)

func (*Dependency) UnmarshalJSON

func (d *Dependency) UnmarshalJSON(data []byte) error

type EngineOption

type EngineOption func(*MigrationEngine)

func EngineOptionApps

func EngineOptionApps(apps ...string) EngineOption

func EngineOptionDirs

func EngineOptionDirs(dirs ...string) EngineOption

type Index

type Index struct {
	Identifier string   `json:"name"`
	Type       string   `json:"type"`
	Fields     []string `json:"columns"`
	Unique     bool     `json:"unique,omitempty"`
	Comment    string   `json:"comment,omitempty"`
	// contains filtered or unexported fields
}

func (Index) Columns

func (i Index) Columns() []Column

func (*Index) Name

func (i *Index) Name() string

func (Index) String

func (i Index) String() string

type IndexDefiner

type IndexDefiner interface {
	DatabaseIndexes(obj attrs.Definer) []Index
}

type MigrationAction

type MigrationAction struct {
	ActionType ActionType            `json:"action"`
	Table      *Changed[*ModelTable] `json:"table,omitempty"`
	Field      *Changed[*Column]     `json:"field,omitempty"`
	Index      *Changed[*Index]      `json:"index,omitempty"`
}

Actions are kept track of to ensure a proper name can be generated for the migration file.

type MigrationAppConfig

type MigrationAppConfig interface {
	django.AppConfig
	GetMigrationFS() fs.FS
}

type MigrationEngine

type MigrationEngine struct {
	// BasePath is the path to the migration directory where migration files are stored.
	//
	// This is used to read and write migration files.
	BasePath string

	// Fake indicates whether the migration engine is in fake mode.
	//
	// If true, the migration engine will not apply any migrations to the database,
	// nor will it write any migration files.
	//
	// It is useful for testing purposes or when you want to see what migrations would be applied without actually applying them.
	Fake bool

	// The path to the directory where the migration files are stored.
	//
	// This is used to load the migration files and apply them to the database.
	Paths []string

	// SchemaEditor is the schema editor used to apply the migrations to the database.
	//
	// This is used to execute SQL commands for creating, modifying, and deleting tables and columns.
	SchemaEditor SchemaEditor

	// MigrationFilesystems is the list of migration filesystems used to load the migration files.
	//
	// It is a map of application names to a slice of fs.FileSystem interfaces.
	MigrationFilesystems map[string]fs.FS

	// Migrations is the list of migration files that have been applied to the database.
	//
	// This is used to keep track of the migrations that have been applied and ensure that they are not applied again.
	Migrations map[string]map[string][]*MigrationFile

	// MigrationLog is the migration log used to log the actions taken by the migration engine.
	//
	// This is used to log the actions taken by the migration engine for debugging and auditing purposes.
	MigrationLog MigrationLog
	// contains filtered or unexported fields
}

func NewMigrationEngine

func NewMigrationEngine(path string, schemaEditor SchemaEditor, opts ...EngineOption) *MigrationEngine

func (*MigrationEngine) Dirs

func (m *MigrationEngine) Dirs() []string

func (*MigrationEngine) GetLastMigration

func (m *MigrationEngine) GetLastMigration(appName, modelName string) *MigrationFile

GetLastMigration returns the last applied migration for the given app and model.

func (*MigrationEngine) Log

func (m *MigrationEngine) Log(action ActionType, file *MigrationFile, table *Changed[*ModelTable], column *Changed[*Column], index *Changed[*Index])

func (*MigrationEngine) MakeMigrations

func (m *MigrationEngine) MakeMigrations(ctx context.Context, apps ...string) error

func (*MigrationEngine) Migrate

func (m *MigrationEngine) Migrate(ctx context.Context, apps ...string) error

func (*MigrationEngine) NeedsToMakeMigrations

func (m *MigrationEngine) NeedsToMakeMigrations(ctx context.Context, apps ...string) ([]*contenttypes.BaseContentType[attrs.Definer], error)

func (*MigrationEngine) NeedsToMigrate

func (m *MigrationEngine) NeedsToMigrate(ctx context.Context, apps ...string) ([]NeedsToMigrateInfo, error)

func (*MigrationEngine) NewMigration

func (e *MigrationEngine) NewMigration(appName, modelName string, newTable *ModelTable, def *contenttypes.BaseContentType[attrs.Definer]) (*MigrationFile, error)

func (*MigrationEngine) ReadMigrations

func (e *MigrationEngine) ReadMigrations(apps ...string) ([]*MigrationFile, error)

ReadMigrations reads the migration files from the specified path and returns a list of migration files.

These migration files are used to apply the migrations to the database.

func (*MigrationEngine) WriteMigration

func (e *MigrationEngine) WriteMigration(migration *MigrationFile) error

WriteMigration writes the migration file to the specified path.

The migration file is used to apply the migrations to the database.

type MigrationEngineConsoleLog

type MigrationEngineConsoleLog struct {
	Prefix string
}

func (*MigrationEngineConsoleLog) Log

func (e *MigrationEngineConsoleLog) Log(action ActionType, file *MigrationFile, table *Changed[*ModelTable], column *Changed[*Column], index *Changed[*Index])

type MigrationFile

type MigrationFile struct {
	// The name of the application for this migration.
	//
	// This is used to identify the application that the migration is for.
	AppName string `json:"-"`

	// The name of the model for this migration.
	//
	// This is used to identify the model that the migration is for.
	ModelName string `json:"-"`

	// The name of the migration file.
	//
	// This is used to identify the migration and apply it in the correct order.
	Name string `json:"-"`

	// The order of the migration file.
	//
	// This is used to ensure that the migrations are applied in the correct order.
	Order int `json:"-"`

	// ContentType is the content type for the model of this migration.
	//
	// This is used to identify the model that the migration is for.
	ContentType *contenttypes.BaseContentType[attrs.Definer] `json:"-"`

	// Dependencies are the migration files that this migration depends on.
	//
	// This is used to ensure that the migrations are applied in the correct order.
	// If a migration file has dependencies, it will not be applied until all of its dependencies have been applied.
	Dependencies []Dependency `json:"dependencies,omitempty"`

	// Lazy dependencies exist in case a relation is lazy loaded - these get special handling to ensure
	// proper dependency management, as the model should be considered "generic", i.e. for defining 2 separate user models,
	// but maintaining the same relation.
	//
	// These lazy dependencies will be loaded using contenttypes.LoadModel().
	LazyDependencies []string `json:"lazy_dependencies,omitempty"`

	// The SQL commands to be executed in the
	// migration file.
	//
	// This is used to apply the migration to the database.
	Table *ModelTable `json:"table"`

	// Actions are the actions that have been taken in this migration file.
	//
	// This is used to keep track of the actions that have been taken in the migration file.
	// These actions are used to generate the migration file name, and can be used to
	// migrate the database to a different state.
	Actions []MigrationAction `json:"actions"`
}

func (*MigrationFile) FileName

func (m *MigrationFile) FileName() string

func (*MigrationFile) GoString

func (m *MigrationFile) GoString() string

func (*MigrationFile) String

func (m *MigrationFile) String() string

type MigrationLog

type MigrationLog interface {
	Log(action ActionType, file *MigrationFile, table *Changed[*ModelTable], column *Changed[*Column], index *Changed[*Index])
}

type MigrationModel

type MigrationModel struct {
	CType        *contenttypes.BaseContentType[attrs.Definer] `json:"content_type"`   // The content type of the model
	LazyModelKey string                                       `json:"lazy_model_key"` // The lazy model key of the model, in case it is a lazy relation.
	// contains filtered or unexported fields
}

func (*MigrationModel) ContentType

func (m *MigrationModel) ContentType() contenttypes.ContentType

func (*MigrationModel) Equals

func (m *MigrationModel) Equals(other *MigrationModel) bool

func (*MigrationModel) Object

func (m *MigrationModel) Object() attrs.Definer

type MigrationRelation

type MigrationRelation struct {
	Type        attrs.RelationType        `json:"type"`                // The type of the relation
	TargetModel *MigrationModel           `json:"model"`               // The target model of the relation
	TargetField attrs.FieldDefinition     `json:"field,omitempty"`     // The field in the target model
	Through     *MigrationRelationThrough `json:"through,omitempty"`   // The through model of the relation
	OnDelete    Action                    `json:"on_delete,omitempty"` // The on delete action of the relation
	OnUpdate    Action                    `json:"on_update,omitempty"` // The on update action of the relation
}

func (*MigrationRelation) Field

func (*MigrationRelation) IsLazy

func (m *MigrationRelation) IsLazy() bool

func (*MigrationRelation) MarshalJSON

func (m *MigrationRelation) MarshalJSON() ([]byte, error)

func (*MigrationRelation) Model

func (m *MigrationRelation) Model() attrs.Definer

func (*MigrationRelation) UnmarshalJSON

func (m *MigrationRelation) UnmarshalJSON(data []byte) error

type MigrationRelationThrough

type MigrationRelationThrough struct {
	Model       *MigrationModel `json:"model"`        // The through model of the relation
	SourceField string          `json:"source_field"` // The source field of the relation
	TargetField string          `json:"target_field"` // The target field of the relation
}

type MigratorAppConfig

type MigratorAppConfig struct {
	django.AppConfig
	MigrationFS fs.FS
}

func (*MigratorAppConfig) Check

func (m *MigratorAppConfig) Check(ctx context.Context, settings django.Settings) []checks.Message

func (*MigratorAppConfig) GetMigrationFS

func (m *MigratorAppConfig) GetMigrationFS() fs.FS

type ModelTable

type ModelTable struct {
	Object attrs.Definer
	Table  string
	Desc   string
	Fields *orderedmap.OrderedMap[string, Column]
	Index  []Index
}

func NewModelTable

func NewModelTable(obj attrs.Definer) *ModelTable

func (*ModelTable) Columns

func (t *ModelTable) Columns() []*Column

func (*ModelTable) Comment

func (t *ModelTable) Comment() string

func (*ModelTable) Diff

func (t *ModelTable) Diff(other *ModelTable) (added, removed []Column, diffs []Changed[Column])

func (*ModelTable) Indexes

func (t *ModelTable) Indexes() []Index

func (*ModelTable) MarshalJSON

func (t *ModelTable) MarshalJSON() ([]byte, error)

func (*ModelTable) Model

func (t *ModelTable) Model() attrs.Definer

func (*ModelTable) ModelName

func (t *ModelTable) ModelName() string

func (*ModelTable) String

func (t *ModelTable) String() string

func (*ModelTable) TableName

func (t *ModelTable) TableName() string

func (*ModelTable) UnmarshalJSON

func (t *ModelTable) UnmarshalJSON(data []byte) error

type NeedsToMigrateInfo

type NeedsToMigrateInfo struct {
	// contains filtered or unexported fields
}

func (*NeedsToMigrateInfo) App

func (*NeedsToMigrateInfo) Migration

func (n *NeedsToMigrateInfo) Migration() *MigrationFile

func (*NeedsToMigrateInfo) Model

func (n *NeedsToMigrateInfo) Model() attrs.Definer

type SchemaEditor

type SchemaEditor interface {
	Setup(ctx context.Context) error
	StartTransaction(ctx context.Context) (drivers.Transaction, error)
	StoreMigration(ctx context.Context, appName string, modelName string, migrationName string) error
	HasMigration(ctx context.Context, appName string, modelName string, migrationName string) (bool, error)
	RemoveMigration(ctx context.Context, appName string, modelName string, migrationName string) error

	Execute(ctx context.Context, query string, args ...any) (sql.Result, error)

	CreateTable(ctx context.Context, table Table, ifNotExists bool) error
	DropTable(ctx context.Context, table Table, ifExists bool) error
	RenameTable(ctx context.Context, table Table, newName string) error

	AddIndex(ctx context.Context, table Table, index Index, ifNotExists bool) error
	DropIndex(ctx context.Context, table Table, index Index, ifExists bool) error
	RenameIndex(ctx context.Context, table Table, oldName string, newName string) error

	AddField(ctx context.Context, table Table, col Column) error
	AlterField(ctx context.Context, table Table, old Column, newCol Column) error
	RemoveField(ctx context.Context, table Table, col Column) error
}

func GetSchemaEditor

func GetSchemaEditor(driver driver.Driver) (SchemaEditor, error)

type Table

type Table interface {
	TableName() string
	Model() attrs.Definer
	Columns() []*Column
	Comment() string
	Indexes() []Index
}

Directories

Path Synopsis
sql
mysql
Package mysql provides a MySQL implementation of the migrator.SchemaEditor interface.
Package mysql provides a MySQL implementation of the migrator.SchemaEditor interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL