-
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.sql
func 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
設計文件
套件
- 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