16496a8dc0
补齐多接口流程联调与控制台体验,并落地仓内 Doc-Driven+TDD 总规则与文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
810 lines
24 KiB
Go
810 lines
24 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
. "code.hoteas.com/golang/hotime"
|
|
. "code.hoteas.com/golang/hotime/common"
|
|
. "code.hoteas.com/golang/hotime/db"
|
|
)
|
|
|
|
// initTestTables 根据数据库类型初始化测试表
|
|
func initTestTables(that *Context) {
|
|
switch that.Db.Type {
|
|
case "dm", "dameng":
|
|
// 用 COUNT(*) 直接探查表可访问性,而非 USER_TABLES(后者受 schema 错配影响)
|
|
exists := that.Db.Query(`SELECT COUNT(*) as cnt FROM "test_batch"`)
|
|
if len(exists) == 0 {
|
|
that.Db.Exec(`CREATE TABLE "test_batch" (
|
|
"id" INT IDENTITY(1,1) PRIMARY KEY,
|
|
"name" VARCHAR(100),
|
|
"title" VARCHAR(200),
|
|
"state" INT DEFAULT 0,
|
|
"create_time" TIMESTAMP
|
|
)`)
|
|
}
|
|
default:
|
|
that.Db.Exec(`CREATE TABLE IF NOT EXISTS test_batch (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(100),
|
|
title VARCHAR(200),
|
|
state INT DEFAULT 0,
|
|
create_time DATETIME
|
|
)`)
|
|
}
|
|
|
|
_ = that.Db.Count("admin")
|
|
_ = that.Db.Count("article")
|
|
}
|
|
|
|
// nowFunc 返回当前数据库的 NOW() 函数表达式
|
|
func nowFunc(that *Context) string {
|
|
return "NOW()"
|
|
}
|
|
|
|
// ExpectDemoCtr 用于展示 result 结构校验的各种场景
|
|
var ExpectDemoCtr = Ctr{
|
|
"string_result": func(that *Context) {
|
|
that.Display(0, "操作成功")
|
|
},
|
|
"number_result": func(that *Context) {
|
|
that.Display(0, 42)
|
|
},
|
|
"float_result": func(that *Context) {
|
|
that.Display(0, 3.14)
|
|
},
|
|
"bool_result": func(that *Context) {
|
|
that.Display(0, true)
|
|
},
|
|
"map_result": func(that *Context) {
|
|
that.Display(0, Map{
|
|
"id": 1, "name": "示例商品", "price": 19.9, "in_stock": true,
|
|
})
|
|
},
|
|
"nested_result": func(that *Context) {
|
|
that.Display(0, Map{
|
|
"id": 100, "title": "测试订单",
|
|
"customer": Map{"id": 1, "name": "张三", "phone": "13800138000"},
|
|
"items": Slice{
|
|
Map{"id": 1, "goods_name": "苹果", "quantity": 5, "price": 3.5},
|
|
Map{"id": 2, "goods_name": "香蕉", "quantity": 10, "price": 2.0},
|
|
},
|
|
"extra": Map{
|
|
"delivery": Map{"address": "XX路1号", "fee": 5},
|
|
},
|
|
})
|
|
},
|
|
"slice_result": func(that *Context) {
|
|
that.Display(0, Slice{
|
|
Map{"id": 1, "name": "标签A"},
|
|
Map{"id": 2, "name": "标签B"},
|
|
})
|
|
},
|
|
"error_demo": func(that *Context) {
|
|
name := that.Req.FormValue("name")
|
|
if name == "" {
|
|
that.Display(3, "名称不能为空")
|
|
return
|
|
}
|
|
that.Display(0, Map{"id": 1, "name": name, "created": true})
|
|
},
|
|
"no_expect": func(that *Context) {
|
|
that.Display(0, Map{"id": 1, "data": "无预期校验"})
|
|
},
|
|
"verify_demo": func(that *Context) {
|
|
name := that.Req.FormValue("name")
|
|
if name == "" {
|
|
that.Display(3, "名称不能为空")
|
|
return
|
|
}
|
|
initTestTables(that)
|
|
id := that.Db.Insert("test_batch", Map{"name": name, "title": "verify_demo", "state": 0})
|
|
that.Display(0, Map{"id": id, "name": name})
|
|
},
|
|
}
|
|
|
|
// TestCtr 通用 ORM 测试控制器(数据库无关)
|
|
var TestCtr = Ctr{
|
|
"test": func(that *Context) {
|
|
that.Display(2, "dsadasd")
|
|
},
|
|
|
|
"all": func(that *Context) {
|
|
results := Map{}
|
|
initTestTables(that)
|
|
|
|
results["1_basic_crud"] = testBasicCRUD(that)
|
|
results["2_condition_syntax"] = testConditionSyntax(that)
|
|
results["3_chain_query"] = testChainQuery(that)
|
|
results["4_join_query"] = testJoinQuery(that)
|
|
results["5_aggregate"] = testAggregate(that)
|
|
results["6_pagination"] = testPagination(that)
|
|
results["7_batch_insert"] = testInserts(that)
|
|
results["8_upsert"] = testUpsert(that)
|
|
results["9_transaction"] = testTransaction(that)
|
|
|
|
that.Display(0, results)
|
|
},
|
|
|
|
"crud": func(that *Context) { initTestTables(that); that.Display(0, testBasicCRUD(that)) },
|
|
"condition": func(that *Context) { that.Display(0, testConditionSyntax(that)) },
|
|
"chain": func(that *Context) { that.Display(0, testChainQuery(that)) },
|
|
"join": func(that *Context) { that.Display(0, testJoinQuery(that)) },
|
|
"aggregate": func(that *Context) { that.Display(0, testAggregate(that)) },
|
|
"pagination": func(that *Context) { that.Display(0, testPagination(that)) },
|
|
"batch": func(that *Context) { initTestTables(that); that.Display(0, testInserts(that)) },
|
|
"upsert": func(that *Context) { that.Display(0, testUpsert(that)) },
|
|
"transaction": func(that *Context) { initTestTables(that); that.Display(0, testTransaction(that)) },
|
|
}
|
|
|
|
func testBasicCRUD(that *Context) Map {
|
|
result := Map{"name": "基础CRUD测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
now := nowFunc(that)
|
|
|
|
insertTest := Map{"name": "Insert 插入测试 (admin表)"}
|
|
uniq := time.Now().UnixNano()
|
|
adminId := that.Db.Insert("admin", Map{
|
|
"name": "测试管理员_" + fmt.Sprintf("%d", uniq),
|
|
"phone": fmt.Sprintf("139%08d", uniq%100000000),
|
|
"state": 1,
|
|
"password": "test123456",
|
|
"role_id": 1,
|
|
"title": "测试职位",
|
|
"create_time[#]": now,
|
|
"modify_time[#]": now,
|
|
})
|
|
insertTest["result"] = adminId > 0
|
|
insertTest["adminId"] = adminId
|
|
insertTest["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, insertTest)
|
|
|
|
getTest := Map{"name": "Get 获取单条记录测试"}
|
|
admin := that.Db.Get("admin", "*", Map{"id": adminId})
|
|
getTest["result"] = admin != nil && admin.GetInt64("id") == adminId
|
|
getTest["admin"] = admin
|
|
tests = append(tests, getTest)
|
|
|
|
selectTest1 := Map{"name": "Select 单条件查询测试"}
|
|
admins1 := that.Db.Select("admin", "*", Map{"state": 1, "LIMIT": 5})
|
|
selectTest1["result"] = len(admins1) >= 0
|
|
selectTest1["count"] = len(admins1)
|
|
tests = append(tests, selectTest1)
|
|
|
|
selectTest2 := Map{"name": "Select 多条件自动AND测试"}
|
|
admins2 := that.Db.Select("admin", "*", Map{
|
|
"state": 1,
|
|
"role_id[>]": 0,
|
|
"ORDER": "id DESC",
|
|
"LIMIT": 5,
|
|
})
|
|
selectTest2["result"] = true
|
|
selectTest2["count"] = len(admins2)
|
|
selectTest2["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, selectTest2)
|
|
|
|
updateTest := Map{"name": "Update 更新测试"}
|
|
affected := that.Db.Update("admin", Map{
|
|
"title": "更新后的职位",
|
|
"modify_time[#]": now,
|
|
}, Map{"id": adminId})
|
|
updateTest["result"] = affected > 0
|
|
updateTest["affected"] = affected
|
|
tests = append(tests, updateTest)
|
|
|
|
deleteTest := Map{"name": "Delete 删除测试"}
|
|
tempId := that.Db.Insert("test_batch", Map{
|
|
"name": "临时删除测试",
|
|
"title": "测试标题",
|
|
"state": 1,
|
|
"create_time[#]": now,
|
|
})
|
|
deleteAffected := that.Db.Delete("test_batch", Map{"id": tempId})
|
|
deleteTest["result"] = deleteAffected > 0
|
|
deleteTest["affected"] = deleteAffected
|
|
tests = append(tests, deleteTest)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testConditionSyntax(that *Context) Map {
|
|
result := Map{"name": "条件查询语法测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
test1 := Map{"name": "等于条件 (=)"}
|
|
articles1 := that.Db.Select("article", "id,title", Map{"state": 0, "LIMIT": 3})
|
|
test1["result"] = true
|
|
test1["count"] = len(articles1)
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "不等于条件 ([!])"}
|
|
articles2 := that.Db.Select("article", "id,title,state", Map{"state[!]": -1, "LIMIT": 3})
|
|
test2["result"] = true
|
|
test2["count"] = len(articles2)
|
|
test2["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test2)
|
|
|
|
test3 := Map{"name": "大于小于条件 ([>], [<])"}
|
|
articles3 := that.Db.Select("article", "id,title,click_num", Map{
|
|
"click_num[>]": 0,
|
|
"click_num[<]": 100000,
|
|
"LIMIT": 3,
|
|
})
|
|
test3["result"] = true
|
|
test3["count"] = len(articles3)
|
|
tests = append(tests, test3)
|
|
|
|
test4 := Map{"name": "大于等于小于等于条件 ([>=], [<=])"}
|
|
articles4 := that.Db.Select("article", "id,title,sort", Map{
|
|
"sort[>=]": 0,
|
|
"sort[<=]": 100,
|
|
"LIMIT": 3,
|
|
})
|
|
test4["result"] = true
|
|
test4["count"] = len(articles4)
|
|
tests = append(tests, test4)
|
|
|
|
test5 := Map{"name": "LIKE 模糊查询 ([~])"}
|
|
articles5 := that.Db.Select("article", "id,title", Map{"title[~]": "新闻", "LIMIT": 3})
|
|
test5["result"] = true
|
|
test5["count"] = len(articles5)
|
|
test5["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test5)
|
|
|
|
test6 := Map{"name": "右模糊查询 ([~!])"}
|
|
articles6 := that.Db.Select("admin", "id,name", Map{"name[~!]": "管理", "LIMIT": 3})
|
|
test6["result"] = true
|
|
test6["count"] = len(articles6)
|
|
tests = append(tests, test6)
|
|
|
|
test7 := Map{"name": "BETWEEN 区间查询 ([<>])"}
|
|
articles7 := that.Db.Select("article", "id,title,click_num", Map{"click_num[<>]": Slice{0, 1000}, "LIMIT": 3})
|
|
test7["result"] = true
|
|
test7["count"] = len(articles7)
|
|
test7["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test7)
|
|
|
|
test8 := Map{"name": "NOT BETWEEN 查询 ([><])"}
|
|
articles8 := that.Db.Select("article", "id,title,sort", Map{"sort[><]": Slice{-10, 0}, "LIMIT": 3})
|
|
test8["result"] = true
|
|
test8["count"] = len(articles8)
|
|
tests = append(tests, test8)
|
|
|
|
test9 := Map{"name": "IN 查询"}
|
|
articles9 := that.Db.Select("article", "id,title", Map{"id": Slice{1, 2, 3, 4, 5}, "LIMIT": 5})
|
|
test9["result"] = true
|
|
test9["count"] = len(articles9)
|
|
test9["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test9)
|
|
|
|
test10 := Map{"name": "NOT IN 查询 ([!])"}
|
|
articles10 := that.Db.Select("article", "id,title", Map{"id[!]": Slice{1, 2, 3}, "LIMIT": 5})
|
|
test10["result"] = true
|
|
test10["count"] = len(articles10)
|
|
tests = append(tests, test10)
|
|
|
|
test11 := Map{"name": "IS NULL 查询"}
|
|
articles11 := that.Db.Select("article", "id,title,img", Map{"img": nil, "LIMIT": 3})
|
|
test11["result"] = true
|
|
test11["count"] = len(articles11)
|
|
tests = append(tests, test11)
|
|
|
|
test12 := Map{"name": "IS NOT NULL 查询 ([!])"}
|
|
articles12 := that.Db.Select("article", "id,title,create_time", Map{"create_time[!]": nil, "LIMIT": 3})
|
|
test12["result"] = true
|
|
test12["count"] = len(articles12)
|
|
tests = append(tests, test12)
|
|
|
|
// SQL 片段查询根据数据库类型适配
|
|
test13 := Map{"name": "直接 SQL 片段查询 ([##])"}
|
|
var sqlFragment string
|
|
switch that.Db.Type {
|
|
case "dm", "dameng":
|
|
sqlFragment = "\"create_time\" > DATEADD(DAY, -365, NOW())"
|
|
default:
|
|
sqlFragment = "create_time > DATE_SUB(NOW(), INTERVAL 365 DAY)"
|
|
}
|
|
articles13 := that.Db.Select("article", "id,title,create_time", Map{
|
|
"[##]": sqlFragment,
|
|
"LIMIT": 3,
|
|
})
|
|
test13["result"] = true
|
|
test13["count"] = len(articles13)
|
|
test13["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test13)
|
|
|
|
test14 := Map{"name": "显式 AND 条件"}
|
|
articles14 := that.Db.Select("article", "id,title,state,click_num", Map{
|
|
"AND": Map{
|
|
"state": 0,
|
|
"click_num[>=]": 0,
|
|
},
|
|
"LIMIT": 3,
|
|
})
|
|
test14["result"] = true
|
|
test14["count"] = len(articles14)
|
|
tests = append(tests, test14)
|
|
|
|
test15 := Map{"name": "OR 条件"}
|
|
articles15 := that.Db.Select("article", "id,title,sort,click_num", Map{
|
|
"OR": Map{
|
|
"sort": 0,
|
|
"click_num[>]": 10,
|
|
},
|
|
"LIMIT": 5,
|
|
})
|
|
test15["result"] = true
|
|
test15["count"] = len(articles15)
|
|
tests = append(tests, test15)
|
|
|
|
test16 := Map{"name": "嵌套 AND/OR 条件"}
|
|
articles16 := that.Db.Select("article", "id,title,sort,state", Map{
|
|
"AND": Map{
|
|
"state": 0,
|
|
"OR": Map{
|
|
"sort[>=]": 0,
|
|
"click_num[>]": 0,
|
|
},
|
|
},
|
|
"LIMIT": 5,
|
|
})
|
|
test16["result"] = true
|
|
test16["count"] = len(articles16)
|
|
test16["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test16)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testChainQuery(that *Context) Map {
|
|
result := Map{"name": "链式查询测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
test1 := Map{"name": "基本链式查询 Table().Where().Select()"}
|
|
articles1 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Select("id,title,author")
|
|
test1["result"] = len(articles1) >= 0
|
|
test1["count"] = len(articles1)
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "链式 And 条件"}
|
|
articles2 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
And("click_num[>=]", 0).
|
|
And("sort[>=]", 0).
|
|
Select("id,title,click_num")
|
|
test2["result"] = len(articles2) >= 0
|
|
test2["count"] = len(articles2)
|
|
tests = append(tests, test2)
|
|
|
|
test3 := Map{"name": "链式 Or 条件"}
|
|
articles3 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Or(Map{
|
|
"sort": 0,
|
|
"click_num[>]": 10,
|
|
}).
|
|
Select("id,title,sort,click_num")
|
|
test3["result"] = len(articles3) >= 0
|
|
test3["count"] = len(articles3)
|
|
tests = append(tests, test3)
|
|
|
|
test4 := Map{"name": "链式 Order 排序"}
|
|
articles4 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Order("create_time DESC", "id ASC").
|
|
Limit(0, 5).
|
|
Select("id,title,create_time")
|
|
test4["result"] = len(articles4) >= 0
|
|
test4["count"] = len(articles4)
|
|
tests = append(tests, test4)
|
|
|
|
test5 := Map{"name": "链式 Limit 限制"}
|
|
articles5 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Limit(0, 3).
|
|
Select("id,title")
|
|
test5["result"] = len(articles5) <= 3
|
|
test5["count"] = len(articles5)
|
|
tests = append(tests, test5)
|
|
|
|
test6 := Map{"name": "链式 Get 获取单条"}
|
|
article6 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Get("id,title,author")
|
|
test6["result"] = article6 != nil || true
|
|
test6["article"] = article6
|
|
tests = append(tests, test6)
|
|
|
|
test7 := Map{"name": "链式 Count 统计"}
|
|
count7 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Count()
|
|
test7["result"] = count7 >= 0
|
|
test7["count"] = count7
|
|
tests = append(tests, test7)
|
|
|
|
test8 := Map{"name": "链式 Page 分页"}
|
|
articles8 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Page(1, 5).
|
|
Select("id,title")
|
|
test8["result"] = len(articles8) <= 5
|
|
test8["count"] = len(articles8)
|
|
tests = append(tests, test8)
|
|
|
|
test9 := Map{"name": "链式 Group 分组"}
|
|
stats9 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Group("ctg_id").
|
|
Select("ctg_id, COUNT(*) as cnt")
|
|
test9["result"] = len(stats9) >= 0
|
|
test9["stats"] = stats9
|
|
tests = append(tests, test9)
|
|
|
|
test10 := Map{"name": "链式 Update 更新"}
|
|
testArticle := that.Db.Table("article").Where("state", 0).Get("id")
|
|
if testArticle != nil {
|
|
affected := that.Db.Table("article").
|
|
Where("id", testArticle.GetInt64("id")).
|
|
Update(Map{"modify_time[#]": nowFunc(that)})
|
|
test10["result"] = affected >= 0
|
|
test10["affected"] = affected
|
|
} else {
|
|
test10["result"] = true
|
|
test10["note"] = "无可用测试数据"
|
|
}
|
|
tests = append(tests, test10)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testJoinQuery(that *Context) Map {
|
|
result := Map{"name": "JOIN查询测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
test1 := Map{"name": "LEFT JOIN 链式查询"}
|
|
articles1 := that.Db.Table("article").
|
|
LeftJoin("ctg", "article.ctg_id = ctg.id").
|
|
Where("article.state", 0).
|
|
Limit(0, 5).
|
|
Select("article.id, article.title, ctg.name as ctg_name")
|
|
test1["result"] = len(articles1) >= 0
|
|
test1["count"] = len(articles1)
|
|
test1["data"] = articles1
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "传统 JOIN 语法"}
|
|
articles2 := that.Db.Select("article",
|
|
Slice{
|
|
Map{"[>]ctg": "article.ctg_id = ctg.id"},
|
|
},
|
|
"article.id, article.title, ctg.name as ctg_name",
|
|
Map{
|
|
"article.state": 0,
|
|
"LIMIT": 5,
|
|
})
|
|
test2["result"] = len(articles2) >= 0
|
|
test2["count"] = len(articles2)
|
|
test2["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test2)
|
|
|
|
test3 := Map{"name": "多表 JOIN"}
|
|
articles3 := that.Db.Table("article").
|
|
LeftJoin("ctg", "article.ctg_id = ctg.id").
|
|
LeftJoin("admin", "article.admin_id = admin.id").
|
|
Where("article.state", 0).
|
|
Limit(0, 5).
|
|
Select("article.id, article.title, ctg.name as ctg_name, admin.name as admin_name")
|
|
test3["result"] = len(articles3) >= 0
|
|
test3["count"] = len(articles3)
|
|
test3["data"] = articles3
|
|
tests = append(tests, test3)
|
|
|
|
test4 := Map{"name": "INNER JOIN"}
|
|
articles4 := that.Db.Table("article").
|
|
InnerJoin("ctg", "article.ctg_id = ctg.id").
|
|
Where("ctg.state", 0).
|
|
Limit(0, 5).
|
|
Select("article.id, article.title, ctg.name as ctg_name")
|
|
test4["result"] = len(articles4) >= 0
|
|
test4["count"] = len(articles4)
|
|
tests = append(tests, test4)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testAggregate(that *Context) Map {
|
|
result := Map{"name": "聚合函数测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
test1 := Map{"name": "Count 总数统计"}
|
|
count1 := that.Db.Count("article")
|
|
test1["result"] = count1 >= 0
|
|
test1["count"] = count1
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "Count 条件统计"}
|
|
count2 := that.Db.Count("article", Map{"state": 0})
|
|
test2["result"] = count2 >= 0
|
|
test2["count"] = count2
|
|
tests = append(tests, test2)
|
|
|
|
test3 := Map{"name": "Sum 求和 (单字段名)"}
|
|
sum3 := that.Db.Sum("article", "click_num", Map{"state": 0})
|
|
test3["result"] = sum3 >= 0
|
|
test3["sum"] = sum3
|
|
test3["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test3)
|
|
|
|
test4 := Map{"name": "Avg 平均值 (单字段名)"}
|
|
avg4 := that.Db.Avg("article", "click_num", Map{"state": 0})
|
|
test4["result"] = avg4 >= 0
|
|
test4["avg"] = avg4
|
|
test4["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test4)
|
|
|
|
test5 := Map{"name": "Max 最大值 (单字段名)"}
|
|
max5 := that.Db.Max("article", "click_num", Map{"state": 0})
|
|
test5["result"] = max5 >= 0
|
|
test5["max"] = max5
|
|
test5["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test5)
|
|
|
|
test6 := Map{"name": "Min 最小值 (单字段名)"}
|
|
min6 := that.Db.Min("article", "sort", Map{"state": 0})
|
|
test6["result"] = true
|
|
test6["min"] = min6
|
|
test6["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test6)
|
|
|
|
test7 := Map{"name": "GROUP BY 分组统计"}
|
|
stats7 := that.Db.Select("article",
|
|
"ctg_id, COUNT(*) as article_count, AVG(click_num) as avg_clicks, SUM(click_num) as total_clicks",
|
|
Map{
|
|
"state": 0,
|
|
"GROUP": "ctg_id",
|
|
"ORDER": "article_count DESC",
|
|
"LIMIT": 10,
|
|
})
|
|
test7["result"] = len(stats7) >= 0
|
|
test7["stats"] = stats7
|
|
tests = append(tests, test7)
|
|
|
|
test8 := Map{"name": "Sum 求和 (table.column 格式)"}
|
|
sum8 := that.Db.Sum("article", "article.click_num", Map{"state": 0})
|
|
test8["result"] = sum8 >= 0
|
|
test8["sum"] = sum8
|
|
test8["match_single_field"] = sum8 == sum3
|
|
test8["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test8)
|
|
|
|
test9 := Map{"name": "聚合函数一致性验证"}
|
|
avg9 := that.Db.Avg("article", "article.click_num", Map{"state": 0})
|
|
max10 := that.Db.Max("article", "article.click_num", Map{"state": 0})
|
|
min11 := that.Db.Min("article", "article.sort", Map{"state": 0})
|
|
allMatch := (sum8 == sum3) && (avg9 == avg4) && (max10 == max5) && (min11 == min6)
|
|
test9["result"] = allMatch
|
|
test9["summary"] = fmt.Sprintf("Sum: %v=%v, Avg: %v=%v, Max: %v=%v, Min: %v=%v",
|
|
sum3, sum8, avg4, avg9, max5, max10, min6, min11)
|
|
tests = append(tests, test9)
|
|
|
|
joinSlice := Slice{
|
|
Map{"[>]ctg": "article.ctg_id = ctg.id"},
|
|
}
|
|
test10 := Map{"name": "Sum 带 JOIN (table.column 格式)"}
|
|
sum10 := that.Db.Sum("article", "article.click_num", joinSlice, Map{"article.state": 0})
|
|
test10["result"] = sum10 >= 0
|
|
test10["sum"] = sum10
|
|
test10["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test10)
|
|
|
|
test11 := Map{"name": "Count 带 JOIN"}
|
|
count11 := that.Db.Count("article", joinSlice, Map{"article.state": 0})
|
|
test11["result"] = count11 >= 0
|
|
test11["count"] = count11
|
|
test11["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test11)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testPagination(that *Context) Map {
|
|
result := Map{"name": "分页查询测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
|
|
test1 := Map{"name": "PageSelect 分页查询"}
|
|
articles1 := that.Db.Page(1, 5).PageSelect("article", "*", Map{
|
|
"state": 0,
|
|
"ORDER": "id DESC",
|
|
})
|
|
test1["result"] = len(articles1) <= 5
|
|
test1["count"] = len(articles1)
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "PageSelect 第二页"}
|
|
articles2 := that.Db.Page(2, 5).PageSelect("article", "*", Map{
|
|
"state": 0,
|
|
"ORDER": "id DESC",
|
|
})
|
|
test2["result"] = len(articles2) <= 5
|
|
test2["count"] = len(articles2)
|
|
tests = append(tests, test2)
|
|
|
|
test3 := Map{"name": "链式 Page 分页"}
|
|
articles3 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Order("id DESC").
|
|
Page(1, 3).
|
|
Select("id,title,author")
|
|
test3["result"] = len(articles3) <= 3
|
|
test3["count"] = len(articles3)
|
|
tests = append(tests, test3)
|
|
|
|
test4 := Map{"name": "Offset 偏移查询"}
|
|
articles4 := that.Db.Table("article").
|
|
Where("state", 0).
|
|
Limit(3).
|
|
Offset(2).
|
|
Select("id,title")
|
|
test4["result"] = len(articles4) <= 3
|
|
test4["count"] = len(articles4)
|
|
test4["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test4)
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testInserts(that *Context) Map {
|
|
result := Map{"name": "批量插入测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
now := nowFunc(that)
|
|
|
|
test1 := Map{"name": "Inserts 批量插入"}
|
|
timestamp := time.Now().UnixNano()
|
|
affected1 := that.Db.Inserts("test_batch", []Map{
|
|
{"name": fmt.Sprintf("批量测试1_%d", timestamp), "title": "标题1", "state": 1},
|
|
{"name": fmt.Sprintf("批量测试2_%d", timestamp), "title": "标题2", "state": 1},
|
|
{"name": fmt.Sprintf("批量测试3_%d", timestamp), "title": "标题3", "state": 1},
|
|
})
|
|
test1["result"] = affected1 >= 0
|
|
test1["affected"] = affected1
|
|
test1["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "Inserts 带 [#] 标记"}
|
|
timestamp2 := time.Now().UnixNano()
|
|
affected2 := that.Db.Inserts("test_batch", []Map{
|
|
{"name": fmt.Sprintf("带时间测试1_%d", timestamp2), "title": "标题带时间1", "state": 1, "create_time[#]": now},
|
|
{"name": fmt.Sprintf("带时间测试2_%d", timestamp2), "title": "标题带时间2", "state": 1, "create_time[#]": now},
|
|
})
|
|
test2["result"] = affected2 >= 0
|
|
test2["affected"] = affected2
|
|
tests = append(tests, test2)
|
|
|
|
that.Db.Delete("test_batch", Map{"name[~]": fmt.Sprintf("_%d", timestamp)})
|
|
that.Db.Delete("test_batch", Map{"name[~]": fmt.Sprintf("_%d", timestamp2)})
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testUpsert(that *Context) Map {
|
|
result := Map{"name": "Upsert测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
now := nowFunc(that)
|
|
|
|
timestamp := time.Now().Unix()
|
|
testPhone := fmt.Sprintf("199%08d", timestamp%100000000)
|
|
|
|
test1 := Map{"name": "Upsert 插入新记录 (admin表)"}
|
|
affected1 := that.Db.Upsert("admin",
|
|
Map{
|
|
"name": "Upsert测试管理员",
|
|
"phone": testPhone,
|
|
"state": 1,
|
|
"password": "test123",
|
|
"role_id": 1,
|
|
"title": "测试职位",
|
|
"create_time[#]": now,
|
|
"modify_time[#]": now,
|
|
},
|
|
Slice{"phone"},
|
|
Slice{"name", "state", "title", "modify_time"},
|
|
)
|
|
test1["result"] = affected1 >= 0
|
|
test1["affected"] = affected1
|
|
test1["lastQuery"] = that.Db.GetLastQuery()
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "Upsert 更新已存在记录"}
|
|
affected2 := that.Db.Upsert("admin",
|
|
Map{
|
|
"name": "Upsert更新后管理员",
|
|
"phone": testPhone,
|
|
"state": 1,
|
|
"password": "updated123",
|
|
"role_id": 2,
|
|
"title": "更新后职位",
|
|
"create_time[#]": now,
|
|
"modify_time[#]": now,
|
|
},
|
|
Slice{"phone"},
|
|
Slice{"name", "title", "role_id", "modify_time"},
|
|
)
|
|
test2["result"] = affected2 >= 0
|
|
test2["affected"] = affected2
|
|
tests = append(tests, test2)
|
|
|
|
updatedAdmin := that.Db.Get("admin", "*", Map{"phone": testPhone})
|
|
test2["updatedAdmin"] = updatedAdmin
|
|
|
|
that.Db.Delete("admin", Map{"phone": testPhone})
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|
|
|
|
func testTransaction(that *Context) Map {
|
|
result := Map{"name": "事务测试", "tests": Slice{}}
|
|
tests := Slice{}
|
|
now := nowFunc(that)
|
|
|
|
timestamp := time.Now().Unix()
|
|
testName1 := fmt.Sprintf("事务测试_%d", timestamp)
|
|
|
|
test1 := Map{"name": "事务成功提交"}
|
|
success1 := that.Db.Action(func(tx HoTimeDB) bool {
|
|
recordId := tx.Insert("test_batch", Map{
|
|
"name": testName1,
|
|
"title": "事务提交测试",
|
|
"state": 1,
|
|
"create_time[#]": now,
|
|
})
|
|
return recordId != 0
|
|
})
|
|
test1["result"] = success1
|
|
checkRecord := that.Db.Get("test_batch", "*", Map{"name": testName1})
|
|
test1["recordExists"] = checkRecord != nil
|
|
tests = append(tests, test1)
|
|
|
|
test2 := Map{"name": "事务回滚"}
|
|
testName2 := fmt.Sprintf("事务回滚测试_%d", timestamp)
|
|
success2 := that.Db.Action(func(tx HoTimeDB) bool {
|
|
_ = tx.Insert("test_batch", Map{
|
|
"name": testName2,
|
|
"title": "事务回滚测试",
|
|
"state": 1,
|
|
"create_time[#]": now,
|
|
})
|
|
return false
|
|
})
|
|
test2["result"] = !success2
|
|
checkRecord2 := that.Db.Get("test_batch", "*", Map{"name": testName2})
|
|
test2["recordRolledBack"] = checkRecord2 == nil
|
|
tests = append(tests, test2)
|
|
|
|
that.Db.Delete("test_batch", Map{"name": testName1})
|
|
|
|
result["tests"] = tests
|
|
result["success"] = true
|
|
return result
|
|
}
|