migrate

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package cydb provides automatic table creation based on Go struct definitions.

This package implements a GORM-like AutoMigrate functionality that can automatically create database tables based on struct field definitions and cydb tags. When tables already exist, it will add any missing columns to match the struct definition.

The package supports multiple database types (MySQL, PostgreSQL, SQLite, Oracle) through a dialect-based architecture. Each database type has its own implementation for SQL generation, field type mapping, and constraint handling.

Supported databases (all implement MigrationDialect interface): - MySQL - PostgreSQL - SQLite - Oracle

Usage:

Define your model structs with cydb tags for single-column constraints:

type User struct {
	ID        int       `cydb:"column:id;type:int;primary_key;auto_increment"`
	Name      string    `cydb:"column:name;type:varchar;size:100;not_null"`
	Email     string    `cydb:"column:email;type:varchar;size:255;unique;not_null"`
	Age       int       `cydb:"column:age;type:int;default:0"`
	CreatedAt time.Time `cydb:"column:created_at;type:timestamp;default_current_time"`
	UpdatedAt time.Time `cydb:"column:updated_at;type:timestamp;update_current_time"`
}

// For standard types, use type:bigint instead of type:int64
// PostgreSQL will automatically use BIGSERIAL for auto_increment with bigint
type Product struct {
	ID    int64  `cydb:"column:id;type:bigint;primary_key;auto_increment"`
	Name  string `cydb:"column:name;type:varchar;not_null"` // size defaults to 255
}

type Order struct {
	ID       int  `cydb:"column:id;primary_key"`
	UserID   int  `cydb:"column:user_id;type:int;not_null"`
	OrgID    int  `cydb:"column:org_id;type:int;not_null"`
	Amount   float64 `cydb:"column:amount;type:decimal;precision:10;scale:2;not_null"`
	Status   string  `cydb:"column:status;type:varchar;size:50;default:pending"`
}

// Implement TableNameProvider interface for custom table name
func (Order) TableName() string {
	return "orders"
}

// Implement CompositeForeignKeyProvider interface for composite foreign keys
func (Order) CompositeForeignKeys() []cydb.CompositeForeignKey {
	return []cydb.CompositeForeignKey{
		{
			Name:              "fk_order_user_org",
			Columns:           []string{"user_id", "org_id"},
			ReferencedTable:   "user_orgs",
			ReferencedColumns: []string{"user_id", "org_id"},
			OnDelete:          "CASCADE",
			OnUpdate:          "CASCADE",
		},
	}
}

// Implement CompositeIndexProvider interface for composite indexes
func (Order) CompositeIndexes() []cydb.CompositeIndex {
	return []cydb.CompositeIndex{
		{Name: "idx_user_org", Columns: []string{"user_id", "org_id"}, Unique: false},
	}
}

// Implement FieldMappingProvider interface for handling column renames
func (Order) FieldMappings() []cydb.FieldMapping {
	return []cydb.FieldMapping{
		{OldColumnName: "user_id", NewColumnName: "uid"},
		{OldColumnName: "org_id", NewColumnName: "organization_id"},
	}
}

Then use AutoMigrate to create tables or add missing columns:

db := &DBCli{...} // your database client
err := db.AutoMigrate(&User{}, &Order{})
if err != nil {
	log.Fatal(err)
}

AutoMigrate will: - Create tables that don't exist with all columns from the struct - For existing tables:

  • Rename columns according to field mappings
  • Add missing columns
  • Drop unused columns (if WithDropColumns(true) is specified, considers field mappings to avoid dropping renamed columns)
  • Sync primary keys, indexes, and constraints (unless WithoutSync(true) is specified)

Note: WithoutSync(true) only skips constraint synchronization. Column deletion (if enabled) and field mappings are always applied regardless of WithoutSync setting.

AutoMigrate Options:

All options are optional and only affect the current migration call.

Customize type defaults (applied to types without explicit size/precision in struct tags):

// Set default varchar size to 100 (default: 255)
db.AutoMigrate(&User{}, WithVarcharSize(100))

// Set default char size (default: 1)
db.AutoMigrate(&User{}, WithCharSize(10))

// Set default decimal precision and scale (default: 10, 2)
db.AutoMigrate(&Order{},
	WithDecimalPrecision(15),
	WithDecimalScale(4),
)

// Set default varbinary size (default: 255)
db.AutoMigrate(&Document{}, WithVarbinarySize(50000))

Control constraint synchronization when table exists:

// Skip syncing constraints (only add missing columns)
// This also skips GetTableInfo call, improving performance for large tables
db.AutoMigrate(&User{}, WithoutSync(true))

Control column deletion:

// Drop columns that exist in database but not in struct (default: false, safe mode)
// Considers field mappings to avoid dropping renamed columns
// If a column fails to drop, continues with other columns (some databases may not support dropping)
db.AutoMigrate(&User{}, WithDropColumns(true))

Combine multiple options:

db.AutoMigrate(&User{},
	WithVarcharSize(100),
	WithDecimalPrecision(12),
	WithoutSync(true),
	WithDropColumns(true),
)

Standard Type System:

The package supports database-agnostic standard types that are automatically converted to database-specific types. This allows you to write portable code that works across all supported databases.

Available standard types: - String: varchar, text, char, longtext - Integer: tinyint, smallint, int, bigint - Unsigned: utinyint, usmallint, uint, ubigint - Float: float, double, decimal - Time: date, time, datetime, timestamp - Other: bool, varbinary, blob, json, jsonb

Parameters with defaults (can be omitted): - varchar: size defaults to 255 - char: size defaults to 1 - varbinary: size defaults to 255 - decimal: precision defaults to 10, scale defaults to 2

Example with standard types:

type User struct {
	ID       int64   `cydb:"column:id;type:bigint;primary_key;auto_increment"`
	Username string  `cydb:"column:username;type:varchar;size:50"`
	Bio      string  `cydb:"column:bio;type:text"`
	Price    float64 `cydb:"column:price;type:decimal;precision:10;scale:2"`
	Birthday time.Time `cydb:"column:birthday;type:date"`
	Active   bool    `cydb:"column:active;type:bool"`
	Email    string  `cydb:"column:email;type:varchar"` // size defaults to 255
}

Limitations: - Does not modify existing column definitions (type, constraints, etc.) - Does not delete columns by default (use WithDropColumns(true) to enable) - Does not modify or delete existing indexes (only syncs new ones) - Column renames must be defined in FieldMappings before the first migration

Supported cydb tag options:

Column definition:

  • column:name - specify column name (required)
  • type:datatype - specify standard type or SQL data type (optional) If omitted, type is inferred from Go field type by the database dialect Examples: varchar, text, int, bigint, decimal, date, bool, etc. See Standard Type System section for complete list

Size/Precision (optional, have built-in defaults that can be overridden with WithXX options): - size:length - specify size for varchar, char, varbinary types (built-in defaults: 255, 1, 255) - precision:n - specify precision for decimal type (built-in default: 10) - scale:n - specify scale for decimal type (built-in default: 2)

Constraints:

  • primary_key - mark field as primary key
  • auto_increment - mark field as auto-increment (MySQL: AUTO_INCREMENT, PostgreSQL: SERIAL/BIGSERIAL, SQLite: AUTOINCREMENT, Oracle: SEQUENCE+TRIGGER)
  • unique - add unique constraint
  • not_null - add NOT NULL constraint
  • index - create an index on the field
  • foreign_key:table:column - add foreign key constraint (single column)

Default values: - default:value - set default value (without quotes, e.g., default:0, default:pending) - default_current_time - set DEFAULT CURRENT_TIMESTAMP (for creation time) - update_current_time - set to update to current timestamp on every update

Foreign key actions (used with foreign_key): - on_delete:action - specify ON DELETE action (CASCADE, SET NULL, RESTRICT, NO ACTION) - on_update:action - specify ON UPDATE action (CASCADE, SET NULL, RESTRICT, NO ACTION)

For composite foreign keys, composite indexes, and field mappings, implement the corresponding interfaces: - TableNameProvider - provide custom table name - CompositeForeignKeyProvider - define multi-column foreign key constraints - CompositeIndexProvider - define multi-column indexes - FieldMappingProvider - define column name mappings for renames

Important Notes:

  • Foreign key constraints are database-specific and may have different syntax across database types. The implementation handles these differences through dialects.
  • When using WithDropColumns(true), ensure FieldMappings are correct before running migration to avoid accidentally deleting renamed columns.
  • WithoutSync(true) skips constraint synchronization but still applies field mappings and column deletion (if enabled). Use it for performance optimization when you know constraints are already in sync.

Index

Constants

View Source
const (
	// String types
	TypeVarchar  def.StandardFieldType = def.TypeVarchar
	TypeText     def.StandardFieldType = def.TypeText
	TypeChar     def.StandardFieldType = def.TypeChar
	TypeLongtext def.StandardFieldType = def.TypeLongtext

	// Integer types
	TypeTinyint  def.StandardFieldType = def.TypeTinyint
	TypeSmallint def.StandardFieldType = def.TypeSmallint
	TypeInt      def.StandardFieldType = def.TypeInt
	TypeBigint   def.StandardFieldType = def.TypeBigint

	// Unsigned integer types
	TypeUtinyint  def.StandardFieldType = def.TypeUtinyint
	TypeUsmallint def.StandardFieldType = def.TypeUsmallint
	TypeUint      def.StandardFieldType = def.TypeUint
	TypeUbigint   def.StandardFieldType = def.TypeUbigint

	// Floating point types
	TypeFloat   def.StandardFieldType = def.TypeFloat
	TypeDouble  def.StandardFieldType = def.TypeDouble
	TypeDecimal def.StandardFieldType = def.TypeDecimal

	// Time types
	TypeDate      def.StandardFieldType = def.TypeDate
	TypeTime      def.StandardFieldType = def.TypeTime
	TypeDatetime  def.StandardFieldType = def.TypeDatetime
	TypeTimestamp def.StandardFieldType = def.TypeTimestamp

	// Boolean type
	TypeBool def.StandardFieldType = def.TypeBool

	// Binary types
	TypeVarbinary def.StandardFieldType = def.TypeVarbinary
	TypeBlob      def.StandardFieldType = def.TypeBlob

	// JSON types
	TypeJSON  def.StandardFieldType = def.TypeJSON
	TypeJSONB def.StandardFieldType = def.TypeJSONB

	// Raw JSON type (for json.RawMessage)
	TypeRawJSON def.StandardFieldType = def.TypeRawJSON
)

Standard type constants for database-agnostic type definitions

These constants represent database-agnostic types that are automatically converted to database-specific types by each dialect. This allows you to write portable code that works across different databases without worrying about database-specific syntax.

Usage in struct tags:

Basic usage (using default size/precision):

type User struct {
	ID       int64  `cydb:"column:id;type:bigint;primary_key"`
	Username string `cydb:"column:username;type:varchar"`           // Uses default size (255)
	Bio      string `cydb:"column:bio;type:text"`                   // No size limit
	Active   bool   `cydb:"column:active;type:bool"`
}

With size specification:

type Product struct {
	Name        string `cydb:"column:name;type:varchar;size:100"`
	Description string `cydb:"column:description;type:varchar;size:500"`
	Data        []byte `cydb:"column:data;type:varbinary;size:10000"`
}

With precision and scale (for decimal):

type Order struct {
	Price    float64 `cydb:"column:price;type:decimal;precision:10;scale:2"`
	Discount float64 `cydb:"column:discount;type:decimal;precision:8;scale:3"`
}

With default values:

type Article struct {
	Title     string    `cydb:"column:title;type:varchar;size:255;not_null"`
	Status    string    `cydb:"column:status;type:varchar;size:20;default:draft"`
	CreatedAt time.Time `cydb:"column:created_at;type:datetime;default_current_time"`
	UpdatedAt time.Time `cydb:"column:updated_at;type:timestamp;update_current_time"`
}

Type conversion examples:

MySQL:

  • varchar → VARCHAR(255)
  • varchar;size:100 → VARCHAR(100)
  • decimal;precision:10;scale:2 → DECIMAL(10,2)
  • date → DATE
  • bool → TINYINT(1)

PostgreSQL:

  • varchar → VARCHAR(255)
  • varchar;size:100 → VARCHAR(100)
  • decimal;precision:10;scale:2 → DECIMAL(10,2)
  • date → DATE
  • bool → BOOLEAN

SQLite:

  • varchar → TEXT
  • varchar;size:100 → TEXT (SQLite doesn't enforce size)
  • decimal;precision:10;scale:2 → REAL
  • date → TEXT
  • bool → INTEGER

Oracle:

  • varchar → VARCHAR2(255)
  • varchar;size:100 → VARCHAR2(100)
  • decimal;precision:10;scale:2 → NUMBER(10,2)
  • date → DATE
  • bool → NUMBER(1)

Variables

This section is empty.

Functions

func AutoMigrate

func AutoMigrate(d def.DatabaseClient, model any, opts ...AutoMigrateOption) error

func ColumnTypesMatch

func ColumnTypesMatch(dialect dialect.MigrationDialect, current, desired schema.FieldInfo) bool

ColumnTypesMatch checks if two column types are equivalent using dialect-specific normalization

func MigrateFromFolder

func MigrateFromFolder(d def.DatabaseClient, pm *MigrateSQLParam, migrationsPath string) error

func ToMigrationTableInfo

func ToMigrationTableInfo(t def.TableInfo, opts ...ToMigrationTableInfoOption) def.TableInfo

Types

type AutoMigrateOption

type AutoMigrateOption func(*AutoMigrateOptions)

AutoMigrateOption is a function type for setting AutoMigrate options

func WithCharSize

func WithCharSize(size int) AutoMigrateOption

WithCharSize sets the default char size for this migration

func WithDecimalPrecision

func WithDecimalPrecision(precision int) AutoMigrateOption

WithDecimalPrecision sets the default decimal precision for this migration

func WithDecimalScale

func WithDecimalScale(scale int) AutoMigrateOption

WithDecimalScale sets the default decimal scale for this migration

func WithDropColumns

func WithDropColumns(drop bool) AutoMigrateOption

WithDropColumns returns an option to drop columns that exist in database but not in struct By default, columns are not dropped (safe mode)

func WithTableName

func WithTableName(tableName string) AutoMigrateOption

func WithVarbinarySize

func WithVarbinarySize(size int) AutoMigrateOption

WithVarbinarySize sets the default varbinary size for this migration

func WithVarcharSize

func WithVarcharSize(size int) AutoMigrateOption

WithVarcharSize sets the default varchar size for this migration

func WithoutSync

func WithoutSync(skip bool) AutoMigrateOption

WithoutSync returns an option to skip syncing constraints when table exists When table exists, only add missing columns, don't sync indexes or foreign keys

type AutoMigrateOptions

type AutoMigrateOptions struct {
	TypeDefaults TypeDefaults // Type defaults for this migration
	SkipSync     bool         // Skip syncing constraints (indexes, foreign keys) when table exists
	DropColumns  bool         // Drop columns that exist in database but not in struct (default: false)
	TableName    string       // Table name for this migration
}

AutoMigrateOptions defines options for AutoMigrate operation

type CompositeForeignKeyProvider

type CompositeForeignKeyProvider interface {
	CompositeForeignKeys() []schema.CompositeForeignKey
}

CompositeForeignKeyProvider provides composite foreign key definitions for a model

type CompositeIndexProvider

type CompositeIndexProvider interface {
	CompositeIndexes() []schema.CompositeIndex
}

CompositeIndexProvider provides composite index definitions for a model

type CompositePrimaryKeyProvider

type CompositePrimaryKeyProvider interface {
	CompositePrimaryKey() []string
}

CompositePrimaryKeyProvider provides composite primary key definition for a model Use this when you need a primary key composed of multiple columns Example:

func (ConfigObject) CompositePrimaryKey() []string {
    return []string{"config_key", "config_namespace", "config_group"}
}

type FieldMappingProvider

type FieldMappingProvider interface {
	// FieldMappings returns a slice of field mappings for column renames
	// Each mapping specifies an old column name and its new name
	// Example:
	//   return []FieldMapping{
	//       {OldColumnName: "user_id", NewColumnName: "uid"},
	//       {OldColumnName: "org_id", NewColumnName: "organization_id"},
	//   }
	FieldMappings() []schema.FieldMapping
}

FieldMappingProvider provides field name mappings for handling column renames This is useful when you want to rename existing columns in the database For example, if a column was named 'user_id' and you want to rename it to 'uid'

type ForeignKeyInfo

type ForeignKeyInfo = schema.ForeignKeyInfo

type ForeignKeyMapping

type ForeignKeyMapping struct {
	OldReferencedTable  string
	OldReferencedColumn string
	NewReferencedTable  string
	NewReferencedColumn string
}

type MigrateByStruct

type MigrateByStruct struct {
	Cli def.DatabaseClient
}

func (*MigrateByStruct) AutoMigrate

func (d *MigrateByStruct) AutoMigrate(model any, opts ...AutoMigrateOption) error

AutoMigrate creates tables for the given models if they don't exist, or adds missing columns if they do exist Supports optional parameters via WithXX functions for one-time overrides All SQL statements are executed within a transaction for consistency

Example:

db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, WithVarcharSize(100))
db.AutoMigrate(&User{}, WithoutSync(true))  // Only add columns, don't sync constraints

func (*MigrateByStruct) AutoMigrateTable

func (d *MigrateByStruct) AutoMigrateTable(tableInfo *schema.MigrationTableInfo, opts ...AutoMigrateOption) error

func (*MigrateByStruct) ReadSQLFile

func (d *MigrateByStruct) ReadSQLFile(r io.Reader, callback dialect.FuncSQLStmtCallback, options ...func(*dialect.ReadSQLFileOptions)) error

ReadSQLFile reads SQL statements from a reader and calls the callback for each statement

type MigrateFileFunc

type MigrateFileFunc func(pm *MigrateSQLParam) *MigrateSQLParam

func WithIgnoreError

func WithIgnoreError(ignoreError bool) MigrateFileFunc

func WithMigrateFileFunc

func WithMigrateFileFunc(f *embed.FS) MigrateFileFunc

func WithServiceOwner

func WithServiceOwner(serviceOwner string) MigrateFileFunc

type MigrateSQLParam

type MigrateSQLParam struct {
	FS           *embed.FS
	IgnoreError  bool
	ServiceOwner string
}

type OffsetTable

type OffsetTable struct {
	Id        string `cydb:"column:id;type:varchar;size:100;primary_key"`
	AppliedAt string `cydb:"column:applied_at;type:timestamp"`
	// contains filtered or unexported fields
}

func (*OffsetTable) GetTableName

func (o *OffsetTable) GetTableName() string

type TableNameProvider

type TableNameProvider interface {
	TableName() string
}

TableNameProvider provides custom table name for a model

type ToMigrationTableInfoOption

type ToMigrationTableInfoOption func(*ToMigrationTableInfoOptions)

ToMigrationTableInfoOption is a function type for setting ToMigrationTableInfo options.

func WithForeignKeyMappings

func WithForeignKeyMappings(mappings []ForeignKeyMapping) ToMigrationTableInfoOption

WithForeignKeyMappings provides a list of foreign key mappings and enables foreign key processing.

func WithForeignKeys

func WithForeignKeys(include bool) ToMigrationTableInfoOption

WithForeignKeys sets whether to include foreign keys during conversion. By default, they are ignored.

func WithNewTableName

func WithNewTableName(name string) ToMigrationTableInfoOption

WithNewTableName sets a new table name for the migration info.

type ToMigrationTableInfoOptions

type ToMigrationTableInfoOptions struct {
	NewTableName       string
	IgnoreForeignKeys  bool
	ForeignKeyMappings []ForeignKeyMapping
}

ToMigrationTableInfoOptions defines options for the ToMigrationTableInfo conversion.

type TypeDefaults

type TypeDefaults struct {
	VarcharSize      int // Default size for varchar type (0 = use 255)
	CharSize         int // Default size for char type (0 = use 1)
	VarbinarySize    int // Default size for varbinary type (0 = use 255)
	DecimalPrecision int // Default precision for decimal type (0 = use 10)
	DecimalScale     int // Default scale for decimal type (0 = use 2)
}

TypeDefaults defines default values for database types

func DefaultTypeDefaults

func DefaultTypeDefaults() TypeDefaults

DefaultTypeDefaults returns the default type configuration

func (TypeDefaults) GetCharSize

func (t TypeDefaults) GetCharSize() int

GetCharSize returns the char size, using default if not set

func (TypeDefaults) GetDecimalPrecision

func (t TypeDefaults) GetDecimalPrecision() int

GetDecimalPrecision returns the decimal precision, using default if not set

func (TypeDefaults) GetDecimalScale

func (t TypeDefaults) GetDecimalScale() int

GetDecimalScale returns the decimal scale, using default if not set

func (TypeDefaults) GetVarbinarySize

func (t TypeDefaults) GetVarbinarySize() int

GetVarbinarySize returns the varbinary size, using default if not set

func (TypeDefaults) GetVarcharSize

func (t TypeDefaults) GetVarcharSize() int

GetVarcharSize returns the varchar size, using default if not set

Jump to

Keyboard shortcuts

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