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
- func AutoMigrate(d def.DatabaseClient, model any, opts ...AutoMigrateOption) error
- func ColumnTypesMatch(dialect dialect.MigrationDialect, current, desired schema.FieldInfo) bool
- func MigrateFromFolder(d def.DatabaseClient, pm *MigrateSQLParam, migrationsPath string) error
- func ToMigrationTableInfo(t def.TableInfo, opts ...ToMigrationTableInfoOption) def.TableInfo
- type AutoMigrateOption
- func WithCharSize(size int) AutoMigrateOption
- func WithDecimalPrecision(precision int) AutoMigrateOption
- func WithDecimalScale(scale int) AutoMigrateOption
- func WithDropColumns(drop bool) AutoMigrateOption
- func WithTableName(tableName string) AutoMigrateOption
- func WithVarbinarySize(size int) AutoMigrateOption
- func WithVarcharSize(size int) AutoMigrateOption
- func WithoutSync(skip bool) AutoMigrateOption
- type AutoMigrateOptions
- type CompositeForeignKeyProvider
- type CompositeIndexProvider
- type CompositePrimaryKeyProvider
- type FieldMappingProvider
- type ForeignKeyInfo
- type ForeignKeyMapping
- type MigrateByStruct
- type MigrateFileFunc
- type MigrateSQLParam
- type OffsetTable
- type TableNameProvider
- type ToMigrationTableInfoOption
- type ToMigrationTableInfoOptions
- type TypeDefaults
Constants ¶
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 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 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