-
Notifications
You must be signed in to change notification settings - Fork 0
migrate_en.md
maoxiaoyue edited this page May 14, 2026
·
1 revision
Scans Go Model struct bun tags, compares against snapshot files, and automatically generates up/down SQL migrations.
After AI modifies Model structs, manually writing SQL migrations is error-prone. Migration Diff lets the framework automatically detect changes and generate correct SQL:
Model struct changes -> Reflect & scan bun tags -> Compare with last snapshot -> Generate SQL
import "github.com/maoxiaoyue/hypgo/pkg/migrate"
type User struct {
bun.BaseModel `bun:"table:users"`
ID int64 `bun:"id,pk,autoincrement"`
Name string `bun:"name,notnull"`
Email string `bun:"email,notnull,unique"`
Bio string `bun:"bio,type:text"`
CreatedAt time.Time `bun:"created_at,notnull,default:current_timestamp"`
}
registry := migrate.NewRegistry()
registry.Register((*User)(nil))// Scan Models -> Extract TableSchema
tables := migrate.ScanModels(registry)
// Load last snapshot
snapshot, _ := migrate.LoadSnapshot(".hyp/schema_snapshot.json")
// Compare -> Generate ChangeSet
changes := migrate.Diff(tables, snapshot)
// Generate SQL
up, down := migrate.GenerateSQL(changes, "postgres")
fmt.Println(up)
// -> ALTER TABLE "users" ADD COLUMN "bio" TEXT;// Save new snapshot
migrate.SaveSnapshot(".hyp/schema_snapshot.json", tables)
// Get migration filenames
upFile, downFile := migrate.MigrationFiles("migrations/")
// -> migrations/20260326_200000_auto.up.sql
// -> migrations/20260326_200000_auto.down.sqlfunc generateMigration() {
// 1. Register all Models
registry := migrate.NewRegistry()
registry.Register(
(*models.User)(nil),
(*models.Post)(nil),
(*models.Comment)(nil),
)
// 2. Scan
tables := migrate.ScanModels(registry)
// 3. Diff
snapshot, _ := migrate.LoadSnapshot(".hyp/schema_snapshot.json")
changes := migrate.Diff(tables, snapshot)
if len(changes) == 0 {
fmt.Println("No changes detected")
return
}
// 4. Display changes
for _, c := range changes {
fmt.Println(c.String())
}
// 5. Generate SQL
up, down := migrate.GenerateSQL(changes, "postgres")
// 6. Save migration files
upFile, downFile := migrate.MigrationFiles("migrations/")
os.WriteFile(upFile, []byte(up), 0644)
os.WriteFile(downFile, []byte(down), 0644)
// 7. Update snapshot
migrate.SaveSnapshot(".hyp/schema_snapshot.json", tables)
}The Scanner extracts field information from struct field bun:"..." tags:
| bun tag | Parsed Result |
|---|---|
bun:"id,pk,autoincrement" |
PrimaryKey=true, AutoIncrement=true |
bun:"name,notnull" |
NotNull=true |
bun:"email,notnull,unique" |
NotNull=true, Unique=true |
bun:"bio,type:text" |
SQLType="text" |
bun:"score,default:0" |
Default="0" |
bun:"table:users,alias:u" |
TableName="users" (BaseModel tag) |
bun:"-" |
Skip this field |
| Change Type | Description |
|---|---|
AddTable |
New table not in snapshot |
DropTable |
Table removed from Models |
AddColumn |
New column added to table |
DropColumn |
Column removed from table |
AlterColumn |
Column attribute changes (type, NotNull, Default, etc.) |
| Feature | PostgreSQL | MySQL |
|---|---|---|
| Identifier quotes | "users" |
`users` |
| Auto-increment PK int64 | BIGSERIAL |
BIGINT AUTO_INCREMENT |
| Auto-increment PK int | SERIAL |
INT AUTO_INCREMENT |
| Float | DOUBLE PRECISION |
DOUBLE |
| Timestamp | TIMESTAMPTZ |
DATETIME |
| ALTER NOT NULL | SET/DROP NOT NULL |
MODIFY COLUMN |
| Go Type | SQL Type |
|---|---|
int64 |
BIGINT |
int, int32
|
INTEGER |
int16 |
SMALLINT |
float64 |
DOUBLE PRECISION / DOUBLE |
float32 |
REAL |
bool |
BOOLEAN |
string |
TEXT |
time.Time |
TIMESTAMPTZ / DATETIME |
If a type:xxx tag is present, the specified SQL type takes priority.
{
"tables": {
"users": {
"name": "users",
"columns": [
{"name": "id", "go_type": "int64", "primary_key": true, "auto_increment": true},
{"name": "name", "go_type": "string", "not_null": true},
{"name": "email", "go_type": "string", "not_null": true, "unique": true}
]
}
}
}pkg/migrate/
├── registry.go ModelRegistry -- Model registration
├── scanner.go ScanModel() -- Reflect & extract bun tags -> TableSchema
├── snapshot.go Snapshot read/write (JSON)
├── diff.go Diff() -- Compare old/new schema -> ChangeSet
├── generator.go GenerateSQL() -- ChangeSet -> SQL (pg/mysql)
└── migrate_test.go 22 unit tests
由 台灣卯小月 用 ❤️ 製作 · MIT License And Wiki is written by Claude
設計文件
套件
- config — 設定
- context — 請求上下文
- router — 路由器
- server — 伺服器
- middleware — 中介層
- websocket — WebSocket
- hidb — 資料庫 ORM
- hidb/cassandra — Cassandra
- logger — 日誌
- json — JSON 處理
- grpc — gRPC
AI 協作工具鏈
- schema — Schema-first 路由
- manifest — 專案 Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — 智慧 Scaffold
- airules — AI Rules
CLI 命令
- hyp 總覽
- hyp new
- hyp api
- hyp run
- hyp restart
- hyp generate
- hyp migrate
- hyp context
- hyp ai-rules
- hyp chkcomment
- hyp impact
- hyp docker
- hyp health
- hyp version
- hyp difflog
Design Docs
Packages
- config — Configuration
- context — Request Context
- router — Router
- server — Server
- middleware — Middleware
- websocket — WebSocket
- hidb — Database ORM
- hidb/cassandra - Cassandra 5.0
- logger — Logger
- json — JSON
- grpc — gRPC
AI Collaboration Toolchain
- schema — Schema-first Routing
- manifest — Project Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — Smart Scaffold
- airules — AI Rules
CLI Commands