From 974e667004020deb0e053ca5632867069b053848 Mon Sep 17 00:00:00 2001 From: Star <> Date: Mon, 8 Jul 2024 17:27:04 +0800 Subject: [PATCH] db.makeDB use text format --- README.md | 87 ++++++++++++++++++++ db/MakeTable.go | 163 +++++++++++++++++++++++++++++++++++++ db/db.go | 39 ++++++--- tests/TestDB.txt | 9 ++ tests/db_tests/dao_init.js | 10 ++- 5 files changed, 296 insertions(+), 12 deletions(-) create mode 100644 tests/TestDB.txt diff --git a/README.md b/README.md index 3dd3106..bb6ccb8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,89 @@ # plugins +## db.makeDB 根据简化的数据结构描述自动生成数据库表结构(自动比对,增量更新) + +``` +// Account 账号 + +User // 用户 +id c12 PK // 用户ID +phone v20 U // 手机号 +password v80 n // 密码 +salt v50 // 随机密码 +name v100 n // 名称 +serverKey v200 // 服务密钥 +isValid b // 是否有效 + +Device // 设备 +id v30 PK // 设备ID +userId c12 // 当前用户 +salt v50 // 随机密码 +secretTime dt // 密钥生成时间 + +// Log 日志 + +LoginLog // 登录日志 +id ubi AI // 登录ID +way v20 // 登录途径(verifyCode/autoLogin/oneClickLogin) +userId c12 I // 当前用户 +deviceId v30 I // 设备ID +time dt I // 登录时间 +userAgent v200 // 设备信息 +requestId v20 // 请求ID +sessionId v20 // 会话ID +successful b // 是否成功 +message v1024 // 登录处理失败的信息 +``` + +## db.makeDB 缩写对照表 + +### types + +``` +c => char +v => varchar +dt => datetime +d => date +tm => time +i => int +ui => int unsigned +ti => tinyint +uti => tinyint unsigned +b => tinyint unsigned +bi => bigint +ubi => bigint unsigned +f => float +uf => float unsigned +ff => double +uff => double unsigned +si => smallint +usi => smallint unsigned +mi => middleint +umi => middleint unsigned +t => text +bb => blob +``` + +### indexes + +``` +PK => PRIMARY KEY NOT NULL +AI => PRIMARY KEY AUTOINCREMENT NOT NULL +I => index +U => unique +TI => fulltext +``` + +### defaults + +``` +ct => CURRENT_TIMESTAMP +ctu => CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +``` + +### null set + +``` +n => NULL +nn => NOT NULL +``` diff --git a/db/MakeTable.go b/db/MakeTable.go index 11a6d2e..af5fa4a 100644 --- a/db/MakeTable.go +++ b/db/MakeTable.go @@ -180,6 +180,169 @@ func MakeER(groups []ERGroup, outputFile *string, tplFile *string, ctx *plugin.C return err } +func ConvertTextToER(text string) []ERGroup { + tablesByGroup := make([]ERGroup, 0) + var lastGroup *ERGroup + lastTableName := "" + var lastTable *TableStruct + lastTableComment := "" + splitter := regexp.MustCompile(`\s+`) + wnMatcher := regexp.MustCompile(`^([a-zA-Z]+)([0-9]+)$`) + for _, line := range strings.Split(text, "\n") { + line = strings.TrimSpace(line) + lc := strings.SplitN(line, "//", 2) + comment := "" + if len(lc) == 2 { + line = strings.TrimSpace(lc[0]) + comment = strings.TrimSpace(lc[1]) + } + if line == "" { + if comment != "" { + commentA := strings.SplitN(comment, " ", 2) + if len(commentA) == 1 { + commentA = append(commentA, "") + } + //lastGroupName = comment + lastGroup = &ERGroup{ + Group: commentA[0], + Comment: commentA[1], + Tables: make([]TableStruct, 0), + } + tablesByGroup = append(tablesByGroup, *lastGroup) + lastGroup = &tablesByGroup[len(tablesByGroup)-1] + } + continue + } + + a := splitter.Split(line, 10) + if len(a) == 1 { + lastTableName = a[0] + lastTableComment = comment + lastTable = &TableStruct{ + Name: lastTableName, + Comment: lastTableComment, + Fields: make([]TableField, 0), + } + if lastGroup == nil { + lastGroup = &ERGroup{ + Group: "Default", + Tables: make([]TableStruct, 0), + } + tablesByGroup = append(tablesByGroup, *lastGroup) + lastGroup = &tablesByGroup[len(tablesByGroup)-1] + } + lastGroup.Tables = append(lastGroup.Tables, *lastTable) + lastTable = &lastGroup.Tables[len(lastGroup.Tables)-1] + } else if lastTableName != "" { + field := TableField{ + Name: a[0], + Type: "", + Index: "", + IndexGroup: "", + Default: "", + Comment: comment, + Null: "NOT NULL", + Extra: "", + } + + for i := 1; i < len(a); i++ { + wn := wnMatcher.FindStringSubmatch(a[i]) + tag := a[i] + size := 0 + if wn != nil { + tag = wn[1] + size = u.Int(wn[2]) + } + switch tag { + case "PK": + field.Index = "pk" + field.Null = "NOT NULL" + case "I": + field.Index = "index" + case "AI": + field.Extra = "AUTO_INCREMENT" + field.Index = "pk" + case "TI": + field.Index = "fulltext" + case "U": + field.Index = "unique" + case "ct": + field.Default = "CURRENT_TIMESTAMP" + case "ctu": + field.Default = "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" + case "n": + field.Null = "NULL" + case "nn": + field.Null = "NOT NULL" + case "c": + field.Type = "char" + case "v": + field.Type = "varchar" + case "dt": + field.Type = "datetime" + case "d": + field.Type = "date" + case "tm": + field.Type = "time" + case "i": + field.Type = "int" + case "ui": + field.Type = "int unsigned" + case "ti": + field.Type = "tinyint" + case "uti": + field.Type = "tinyint unsigned" + case "b": + field.Type = "tinyint unsigned" + case "bi": + field.Type = "bigint" + case "ubi": + field.Type = "bigint unsigned" + case "f": + field.Type = "float" + case "uf": + field.Type = "float unsigned" + case "ff": + field.Type = "double" + case "uff": + field.Type = "double unsigned" + case "si": + field.Type = "smallint" + case "usi": + field.Type = "smallint unsigned" + case "mi": + field.Type = "middleint" + case "umi": + field.Type = "middleint unsigned" + case "t": + field.Type = "text" + case "bb": + field.Type = "blob" + default: + } + + if size > 0 { + switch tag { + case "I": + // 索引分组 + field.Index = "index" + field.IndexGroup = u.String(size) + case "U": + // 唯一索引分组 + field.Index = "unique" + field.IndexGroup = u.String(size) + default: + // 带长度的类型 + field.Type += fmt.Sprintf("(%d)", size) + } + } + } + lastTable.Fields = append(lastTable.Fields, field) + } + } + return tablesByGroup +} + func MakeTable(conn *db.DB, table *TableStruct, ctx *plugin.Context) ([]string, error) { logger := ctx.GetInject("*log.Logger").(*log.Logger) //fmt.Println(u.JsonP(ddlKeyMatcher.FindAllStringSubmatch("(`key`,id, `name` )", 100)), "====================") diff --git a/db/db.go b/db/db.go index 716b891..60491f0 100644 --- a/db/db.go +++ b/db/db.go @@ -73,9 +73,11 @@ configs: "destroy": DefaultDestroy, "exec": DefaultExec, "insert": DefaultInsert, - "make": DefaultMake, + "makeDB": DefaultMakeDBByText, + "makeDBBy": DefaultMakeDBByObject, "makeDao": DefaultMakeDao, - "makeER": DefaultMakeER, + "makeER": DefaultMakeERByText, + "makeERBy": DefaultMakeERByObject, "makeId": DefaultMakeId, "query": DefaultQuery, "query1": DefaultQuery1, @@ -125,9 +127,15 @@ func InKeys(numArgs int) string { return fmt.Sprintf("(%s)", strings.Join(a, ",")) } -// Make 创建表格,如果表格已经存在则更新表结构 -// Make return 已执行的SQL列表 -func (db *DB) Make(groups []ERGroup, ctx *plugin.Context) ([]string, error) { +// MakeDB 创建或更新数据库 +// MakeDB return 已执行的SQL列表 +func (db *DB) MakeDB(dbDesc string, ctx *plugin.Context) ([]string, error) { + return db.MakeDBBy(ConvertTextToER(dbDesc), ctx) +} + +// MakeDBBy 创建或更新数据库 +// MakeDBBy return 已执行的SQL列表 +func (db *DB) MakeDBBy(groups []ERGroup, ctx *plugin.Context) ([]string, error) { outSql := make([]string, 0) for _, group := range groups { for _, table := range group.Tables { @@ -143,7 +151,12 @@ func (db *DB) Make(groups []ERGroup, ctx *plugin.Context) ([]string, error) { } // MakeER 创建ER图 -func (db *DB) MakeER(groups []ERGroup, outputFile *string, tplFile *string, ctx *plugin.Context) error { +func (db *DB) MakeER(dbDesc string, outputFile *string, tplFile *string, ctx *plugin.Context) error { + return MakeER(ConvertTextToER(dbDesc), outputFile, tplFile, ctx) +} + +// MakeERBy 创建ER图 +func (db *DB) MakeERBy(groups []ERGroup, outputFile *string, tplFile *string, ctx *plugin.Context) error { return MakeER(groups, outputFile, tplFile, ctx) } @@ -462,14 +475,20 @@ func DefaultReplace(ctx *plugin.Context, table string, data map[string]interface func DefaultUpdate(ctx *plugin.Context, table string, data map[string]interface{}, wheres string, args ...interface{}) (ExecResult, error) { return GetDB(ctx, nil).Update(table, data, wheres, args...) } -func DefaultMake(ctx *plugin.Context, groups []ERGroup) ([]string, error) { - return GetDB(ctx, nil).Make(groups, ctx) +func DefaultMakeDBByText(ctx *plugin.Context, dbDesc string) ([]string, error) { + return GetDB(ctx, nil).MakeDB(dbDesc, ctx) +} +func DefaultMakeDBByObject(ctx *plugin.Context, groups []ERGroup) ([]string, error) { + return GetDB(ctx, nil).MakeDBBy(groups, ctx) } func DefaultMakeDao(ctx *plugin.Context, outputPath *string, conf *DaoConfig) error { return GetDB(ctx, nil).MakeDao(outputPath, conf, ctx) } -func DefaultMakeER(ctx *plugin.Context, groups []ERGroup, outputFile *string, tplFile *string) error { - return GetDB(ctx, nil).MakeER(groups, outputFile, tplFile, ctx) +func DefaultMakeERByText(ctx *plugin.Context, dbDesc string, outputFile *string, tplFile *string) error { + return GetDB(ctx, nil).MakeER(dbDesc, outputFile, tplFile, ctx) +} +func DefaultMakeERByObject(ctx *plugin.Context, groups []ERGroup, outputFile *string, tplFile *string) error { + return GetDB(ctx, nil).MakeERBy(groups, outputFile, tplFile, ctx) } func DefaultMakeId(ctx *plugin.Context, table string, idField string, idSize uint) (string, error) { return GetDB(ctx, nil).MakeId(table, idField, idSize) diff --git a/tests/TestDB.txt b/tests/TestDB.txt new file mode 100644 index 0000000..bdecc3a --- /dev/null +++ b/tests/TestDB.txt @@ -0,0 +1,9 @@ +// account 账号相关 + +user // 用户表 +id i AI // 用户编号 +name v30 // 姓名 +phone v20 U // 手机号 +addDate dt I // 创建时间 +version i I // 数据版本号 +isValid i // 是否有效(1-启用,0-禁用) diff --git a/tests/db_tests/dao_init.js b/tests/db_tests/dao_init.js index 7c41b0f..9fe803f 100644 --- a/tests/db_tests/dao_init.js +++ b/tests/db_tests/dao_init.js @@ -1,7 +1,13 @@ import db from "apigo.cc/apigo/plugins/db" import file from "apigo.cc/apigo/plugins/file" -let testDBDesc = file.loadYaml('./TestDB.yml') -db.make(testDBDesc) +let testDBDesc = file.read('./TestDB.txt') +db.makeDB(testDBDesc) db.makeDao("db_tests") db.makeER(testDBDesc) + +// let testDBDesc = file.loadYaml('./TestDB.yml') +// console.info(db.makeDBBy(testDBDesc)) +// db.makeDao("db_tests") +// db.makeERBy(testDBDesc) +