package main // ============================================================ // db-history.go - Schema 版本声明与字段映射 // 这是整个迁移引擎的“数据源”,记录每个版本的完整 Schema 定义。 // 迁移工具通过对比当前 Schema 与目标 Schema 的差异来决定迁移路径。 // ============================================================ // SchemaVersionDef 记录一个 Schema 版本的完整字段定义 type SchemaVersionDef struct { Version string // 如 "v1", "v2", "v3" TableName string // 表名,如 "proxies" Columns map[string]ColumnDef // 字段名 → 字段定义 } // ColumnDef 描述一个字段的结构 type ColumnDef struct { Type string // 如 "INTEGER", "TEXT", "BOOLEAN" NotNull bool // 是否 NOT NULL Default string // 默认值表达式(如 "0"、"'CHANGE_ME'") Primary bool // 是否主键 } // schemaHistory 存储所有已知的 Schema 版本(从旧到新排列) // 每个版本记录的是“完整的表结构”,而不是增量变更。 // 新增版本时,在这里追加一条记录即可。 var schemaHistory = []SchemaVersionDef{ // v1:初始版本(frpc-console 1.0) { Version: "v1", TableName: "proxies", Columns: map[string]ColumnDef{ "id": {Type: "INTEGER", Primary: true}, "name": {Type: "TEXT", NotNull: true}, "type": {Type: "TEXT", NotNull: true, Default: "'tcp'"}, "local_ip": {Type: "TEXT", NotNull: true}, "local_port": {Type: "INTEGER", NotNull: true}, "remote_port": {Type: "INTEGER", NotNull: true}, "enabled": {Type: "INTEGER", NotNull: true, Default: "1"}, "created_at": {Type: "DATETIME", Default: "CURRENT_TIMESTAMP"}, "updated_at": {Type: "DATETIME", Default: "CURRENT_TIMESTAMP"}, }, }, // v2:当前版本(frpc-console 2.0 LTS) // 注意:wire_protocol_v2 是全局配置(global_config),不在 proxies 表中 { Version: "v2", TableName: "proxies", Columns: map[string]ColumnDef{ "id": {Type: "INTEGER", Primary: true}, "name": {Type: "TEXT", NotNull: true}, "type": {Type: "TEXT", NotNull: true, Default: "'tcp'"}, "local_ip": {Type: "TEXT", NotNull: true}, "local_port": {Type: "INTEGER", NotNull: true}, "remote_port": {Type: "INTEGER", NotNull: true}, "enabled": {Type: "INTEGER", NotNull: true, Default: "1"}, "created_at": {Type: "DATETIME", Default: "CURRENT_TIMESTAMP"}, "updated_at": {Type: "DATETIME", Default: "CURRENT_TIMESTAMP"}, }, }, // v3:未来版本(规划中) // 示例:新增隧道分组、流量统计等字段 // { // Version: "v3", // TableName: "proxies", // Columns: map[string]ColumnDef{ // // ... 完整字段定义 // }, // }, } // getSchemaDef 根据版本号获取 Schema 定义 func getSchemaDef(version string) *SchemaVersionDef { for _, def := range schemaHistory { if def.Version == version { return &def } } return nil } // getLatestSchemaDef 获取最新的 Schema 版本定义 func getLatestSchemaDef() *SchemaVersionDef { if len(schemaHistory) == 0 { return nil } return &schemaHistory[len(schemaHistory)-1] } // schemaVersionsEqual 判断两个 Schema 版本是否完全相同 func schemaVersionsEqual(v1, v2 *SchemaVersionDef) bool { if v1 == nil || v2 == nil { return false } if v1.TableName != v2.TableName { return false } if len(v1.Columns) != len(v2.Columns) { return false } for name, col1 := range v1.Columns { col2, ok := v2.Columns[name] if !ok { return false } if col1.Type != col2.Type || col1.NotNull != col2.NotNull || col1.Default != col2.Default { return false } } return true }