release: simcu::orm 1.2.1 — README 清理(去除 EF 对照、补充 @Index 索引注解)、迁移生成索引说明、包描述与版本更新
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
* let m1 = gen.ensure("20250801000000_AddAge", "新增 age 列", "snapshot.json", models1)
|
||||
* migrator.migrate([m1])
|
||||
*
|
||||
* 限制(v1):不支持主键/自增属性变更(抛异常提示手写迁移);不生成索引(模型无索引注解)。
|
||||
* 索引:模型字段用 @Index 标注即生成 CREATE [UNIQUE] INDEX(down 自动 DROP INDEX)。
|
||||
* 限制(v1):不支持主键/自增属性变更(抛异常提示手写迁移)。
|
||||
*/
|
||||
|
||||
package simcu::orm.migrations
|
||||
@@ -36,6 +37,13 @@ public class MigrationGenerator {
|
||||
for (model in models) {
|
||||
upOps.add(createTableOp(model))
|
||||
downOps.add(dropTableOp(model.tableName))
|
||||
// 索引随建表一并创建:down 先 DROP INDEX 再 DROP TABLE(setPresets 已逆序处理)
|
||||
for (op in createIndexOpsFor(model)) {
|
||||
upOps.add(op)
|
||||
}
|
||||
for (op in dropIndexOpsFor(model)) {
|
||||
downOps.add(op)
|
||||
}
|
||||
}
|
||||
setPresets(m, upOps, downOps)
|
||||
m
|
||||
@@ -50,11 +58,17 @@ public class MigrationGenerator {
|
||||
let oldByName = indexByTable(oldModels)
|
||||
let newByName = indexByTable(newModels)
|
||||
|
||||
// 1. 新增表 → CreateTable
|
||||
// 1. 新增表 → CreateTable(含索引)
|
||||
for (n in newModels) {
|
||||
if (!oldByName.contains(n.tableName)) {
|
||||
upOps.add(createTableOp(n))
|
||||
downOps.add(dropTableOp(n.tableName))
|
||||
for (op in createIndexOpsFor(n)) {
|
||||
upOps.add(op)
|
||||
}
|
||||
for (op in dropIndexOpsFor(n)) {
|
||||
downOps.add(op)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2. 已有表 → 列增删改
|
||||
@@ -196,6 +210,78 @@ public class MigrationGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 索引增删改
|
||||
diffIndexes(upOps, downOps, old, cur)
|
||||
}
|
||||
|
||||
/// 索引 diff:按 indexName 匹配,处理新增/删除/变更(变更 = up 先 DROP 再 CREATE,down 反之)
|
||||
private static func diffIndexes(upOps: ArrayList<MigrationOperation>, downOps: ArrayList<MigrationOperation>,
|
||||
old: EntityModel, cur: EntityModel): Unit {
|
||||
var oldIdx = HashMap<String, PropertyModel>()
|
||||
for (p in old.properties) {
|
||||
if (p.isIndex) {
|
||||
oldIdx[p.indexName] = p
|
||||
}
|
||||
}
|
||||
var curIdx = HashMap<String, PropertyModel>()
|
||||
for (p in cur.properties) {
|
||||
if (p.isIndex) {
|
||||
curIdx[p.indexName] = p
|
||||
}
|
||||
}
|
||||
// 新增 / 变更
|
||||
for (p in cur.properties) {
|
||||
if (!p.isIndex) {
|
||||
continue
|
||||
}
|
||||
if (let Some(op) <- oldIdx.get(p.indexName)) {
|
||||
if (!sameIndex(op, p)) {
|
||||
upOps.add(dropIndexOp(cur.tableName, p.indexName))
|
||||
downOps.add(createIndexOp(old.tableName, op))
|
||||
upOps.add(createIndexOp(cur.tableName, p))
|
||||
downOps.add(dropIndexOp(old.tableName, p.indexName))
|
||||
}
|
||||
} else {
|
||||
upOps.add(createIndexOp(cur.tableName, p))
|
||||
downOps.add(dropIndexOp(cur.tableName, p.indexName))
|
||||
}
|
||||
}
|
||||
// 删除
|
||||
for (p in old.properties) {
|
||||
if (!p.isIndex) {
|
||||
continue
|
||||
}
|
||||
if (!curIdx.contains(p.indexName)) {
|
||||
upOps.add(dropIndexOp(old.tableName, p.indexName))
|
||||
downOps.add(createIndexOp(old.tableName, p))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func sameIndex(a: PropertyModel, b: PropertyModel): Bool {
|
||||
a.columnName == b.columnName && a.indexUnique == b.indexUnique
|
||||
}
|
||||
|
||||
/// 该模型所有索引列 → CREATE INDEX op(up 用)
|
||||
private static func createIndexOpsFor(model: EntityModel): ArrayList<MigrationOperation> {
|
||||
let ops = ArrayList<MigrationOperation>()
|
||||
for (p in model.properties) {
|
||||
if (p.isIndex) {
|
||||
ops.add(createIndexOp(model.tableName, p))
|
||||
}
|
||||
}
|
||||
ops
|
||||
}
|
||||
|
||||
/// 该模型所有索引列 → DROP INDEX op(down 用,与 createIndexOpsFor 同序)
|
||||
private static func dropIndexOpsFor(model: EntityModel): ArrayList<MigrationOperation> {
|
||||
let ops = ArrayList<MigrationOperation>()
|
||||
for (p in model.properties) {
|
||||
if (p.isIndex) {
|
||||
ops.add(dropIndexOp(model.tableName, p.indexName))
|
||||
}
|
||||
}
|
||||
ops
|
||||
}
|
||||
|
||||
private static func sameColumn(a: PropertyModel, b: PropertyModel): Bool {
|
||||
@@ -275,4 +361,20 @@ public class MigrationGenerator {
|
||||
op.column = Some(columnDefinition(p))
|
||||
op
|
||||
}
|
||||
|
||||
private static func createIndexOp(table: String, p: PropertyModel): MigrationOperation {
|
||||
let op = MigrationOperation(MigrationOperationKind.CreateIndex)
|
||||
op.tableName = table
|
||||
op.indexName = p.indexName
|
||||
op.unique = p.indexUnique
|
||||
op.columnNames.add(p.columnName)
|
||||
op
|
||||
}
|
||||
|
||||
private static func dropIndexOp(table: String, indexName: String): MigrationOperation {
|
||||
let op = MigrationOperation(MigrationOperationKind.DropIndex)
|
||||
op.tableName = table
|
||||
op.indexName = indexName
|
||||
op
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ public class DdlFactory {
|
||||
if (op.unique) {
|
||||
sb.append("UNIQUE ")
|
||||
}
|
||||
sb.append("INDEX ${dialect.quoteName(op.indexName)} ON ${dialect.quoteName(op.tableName)} (")
|
||||
sb.append("INDEX IF NOT EXISTS ${dialect.quoteName(op.indexName)} ON ${dialect.quoteName(op.tableName)} (")
|
||||
var first = true
|
||||
for (c in op.columnNames) {
|
||||
if (!first) {
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
* // 模型变更后:快照存在 → 载入旧模型 diff,并覆盖保存新快照
|
||||
* gen.ensure("20250801000000_AddAge", "新增 age 列", "snapshot.json", models1)
|
||||
*
|
||||
* 快照 JSON 结构(版本 2,较 v1 新增 enum 标记):
|
||||
* {"version":2,"models":[{"table":"users","columns":[
|
||||
* 快照 JSON 结构(版本 3,较 v2 新增索引标记 idx/ixName/ixUnique):
|
||||
* {"version":3,"models":[{"table":"users","columns":[
|
||||
* {"name":"id","column":"id","type":"Int64","key":true,"auto":true,
|
||||
* "client":false,"required":false,"maxLen":0,"enum":false}]}]}
|
||||
* "client":false,"required":false,"maxLen":0,"enum":false,
|
||||
* "idx":false,"ixName":"","ixUnique":false}]}]}
|
||||
*/
|
||||
|
||||
package simcu::orm.migrations
|
||||
@@ -30,7 +31,7 @@ public class ModelSnapshot {
|
||||
/// 快照内的轻量模型列表
|
||||
public var models: ArrayList<EntityModel> = ArrayList()
|
||||
/// 快照格式版本
|
||||
public static let formatVersion: Int64 = 2
|
||||
public static let formatVersion: Int64 = 3
|
||||
|
||||
public init() {}
|
||||
|
||||
@@ -51,6 +52,9 @@ public class ModelSnapshot {
|
||||
lp.maxLength = p.maxLength
|
||||
lp.typeNameOverride = p.typeName()
|
||||
lp.isEnum = p.isEnum
|
||||
lp.isIndex = p.isIndex
|
||||
lp.indexName = p.indexName
|
||||
lp.indexUnique = p.indexUnique
|
||||
lm.properties.add(lp)
|
||||
}
|
||||
if (let Some(kp) <- m.keyProperty) {
|
||||
@@ -90,6 +94,9 @@ public class ModelSnapshot {
|
||||
co["required"] = JBool(p.isRequired)
|
||||
co["maxLen"] = JNumber("${p.maxLength}")
|
||||
co["enum"] = JBool(p.isEnum)
|
||||
co["idx"] = JBool(p.isIndex)
|
||||
co["ixName"] = JString(p.indexName)
|
||||
co["ixUnique"] = JBool(p.indexUnique)
|
||||
cols.add(JObject(co))
|
||||
}
|
||||
mo["columns"] = JArray(cols)
|
||||
@@ -126,6 +133,9 @@ public class ModelSnapshot {
|
||||
lp.isRequired = getBool(co, "required")
|
||||
lp.maxLength = getLong(co, "maxLen")
|
||||
lp.isEnum = getBool(co, "enum")
|
||||
lp.isIndex = getBool(co, "idx")
|
||||
lp.indexName = getString(co, "ixName")
|
||||
lp.indexUnique = getBool(co, "ixUnique")
|
||||
if (lp.isKey) {
|
||||
lm.keyProperty = Some(lp)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user