hotime/example/main.go
hoteas 0318c95055 refactor(db): 重构数据库构建器以支持JOIN参数传递并删除示例配置文件
- 修改 Get 方法以根据是否存在 JOIN 来构建参数结构
- 修改 Count 方法以根据是否存在 JOIN 来传递参数
- 修改 Select 方法以根据是否存在 JOIN 来构建参数结构
- 在 where.go 中添加对 [##] 键的支持以直接添加 SQL 片段
- 删除 example/config/admin.json 配置文件
- 删除 example/config/config.json 配置文件
- 删除 example/config/configNote.json 配置文件
- 删除 example/config/rule.json 配置文件
- 删除 example/benchmark_test.go 压测文件
- 重构 example/main.go 文件,添加完整的 HoTimeDB 功能测试套件
- 添加调试日志功能以跟踪数据库操作流程
2026-01-22 05:31:17 +08:00

963 lines
33 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"encoding/json"
"fmt"
"os"
"time"
. "code.hoteas.com/golang/hotime"
. "code.hoteas.com/golang/hotime/common"
. "code.hoteas.com/golang/hotime/db"
)
// 调试日志文件路径
const debugLogPath = `d:\work\hotimev1\.cursor\debug.log`
// debugLog 写入调试日志
func debugLog(location, message string, data interface{}, hypothesisId string) {
// #region agent log
logEntry := Map{
"location": location,
"message": message,
"data": data,
"timestamp": time.Now().UnixMilli(),
"sessionId": "debug-session",
"runId": "hotimedb-test-run",
"hypothesisId": hypothesisId,
}
jsonBytes, _ := json.Marshal(logEntry)
f, err := os.OpenFile(debugLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err == nil {
f.WriteString(string(jsonBytes) + "\n")
f.Close()
}
// #endregion
}
func main() {
debugLog("main.go:35", "开始 HoTimeDB 全功能测试", nil, "START")
appIns := Init("config/config.json")
appIns.SetConnectListener(func(that *Context) (isFinished bool) {
return isFinished
})
appIns.Run(Router{
"app": {
"test": {
// 测试入口 - 运行所有测试
"all": func(that *Context) {
results := Map{}
debugLog("main.go:48", "开始所有测试", nil, "ALL_TESTS")
// 初始化测试表
initTestTables(that)
// 1. 基础 CRUD 测试
results["1_basic_crud"] = testBasicCRUD(that)
// 2. 条件查询语法测试
results["2_condition_syntax"] = testConditionSyntax(that)
// 3. 链式查询测试
results["3_chain_query"] = testChainQuery(that)
// 4. JOIN 查询测试
results["4_join_query"] = testJoinQuery(that)
// 5. 聚合函数测试
results["5_aggregate"] = testAggregate(that)
// 6. 分页查询测试
results["6_pagination"] = testPagination(that)
// 7. 批量插入测试
results["7_batch_insert"] = testBatchInsert(that)
// 8. Upsert 测试
results["8_upsert"] = testUpsert(that)
// 9. 事务测试
results["9_transaction"] = testTransaction(that)
// 10. 原生 SQL 测试
results["10_raw_sql"] = testRawSQL(that)
debugLog("main.go:80", "所有测试完成", results, "ALL_TESTS_DONE")
that.Display(0, results)
},
// 查询数据库表结构
"tables": func(that *Context) {
debugLog("main.go:tables", "查询数据库表结构", nil, "TABLES")
// 查询所有表
tables := that.Db.Query("SHOW TABLES")
debugLog("main.go:tables", "表列表", tables, "TABLES")
that.Display(0, Map{"tables": tables})
},
// 查询指定表的结构
"describe": func(that *Context) {
tableName := that.Req.FormValue("table")
if tableName == "" {
that.Display(1, "请提供 table 参数")
return
}
// 查询表结构
columns := that.Db.Query("DESCRIBE " + tableName)
// 查询表数据前10条
data := that.Db.Select(tableName, Map{"LIMIT": 10})
debugLog("main.go:describe", "表结构", Map{"table": tableName, "columns": columns, "data": data}, "DESCRIBE")
that.Display(0, Map{"table": tableName, "columns": columns, "sample_data": data})
},
// 单独测试入口
"crud": func(that *Context) { 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) { that.Display(0, testBatchInsert(that)) },
"upsert": func(that *Context) { that.Display(0, testUpsert(that)) },
"transaction": func(that *Context) { that.Display(0, testTransaction(that)) },
"rawsql": func(that *Context) { that.Display(0, testRawSQL(that)) },
},
},
})
}
// initTestTables 初始化测试表MySQL真实数据库
func initTestTables(that *Context) {
// MySQL 真实数据库已有表,创建测试用的临时表
// 创建测试用的批量插入表
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
)`)
// 检查 admin 表数据
adminCount := that.Db.Count("admin")
articleCount := that.Db.Count("article")
debugLog("main.go:init", "MySQL数据库初始化检查完成", Map{
"adminCount": adminCount,
"articleCount": articleCount,
"dbType": "MySQL",
}, "INIT")
}
// ==================== 1. 基础 CRUD 测试 ====================
func testBasicCRUD(that *Context) Map {
result := Map{"name": "基础CRUD测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:103", "开始基础 CRUD 测试 (MySQL)", nil, "H1_CRUD")
// 1.1 Insert 测试 - 使用 admin 表
insertTest := Map{"name": "Insert 插入测试 (admin表)"}
adminId := that.Db.Insert("admin", Map{
"name": "测试管理员_" + fmt.Sprintf("%d", time.Now().Unix()),
"phone": fmt.Sprintf("138%d", time.Now().Unix()%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.LastQuery
debugLog("main.go:118", "Insert 测试", Map{"adminId": adminId, "success": adminId > 0, "query": that.Db.LastQuery}, "H1_INSERT")
tests = append(tests, insertTest)
// 1.2 Get 测试
getTest := Map{"name": "Get 获取单条记录测试"}
admin := that.Db.Get("admin", "*", Map{"id": adminId})
getTest["result"] = admin != nil && admin.GetInt64("id") == adminId
getTest["admin"] = admin
debugLog("main.go:126", "Get 测试", Map{"admin": admin, "success": admin != nil}, "H1_GET")
tests = append(tests, getTest)
// 1.3 Select 测试 - 单条件
selectTest1 := Map{"name": "Select 单条件查询测试"}
admins1 := that.Db.Select("admin", "*", Map{"state": 1, "LIMIT": 5})
selectTest1["result"] = len(admins1) >= 0 // 可能表中没有数据
selectTest1["count"] = len(admins1)
debugLog("main.go:134", "Select 单条件测试", Map{"count": len(admins1)}, "H1_SELECT1")
tests = append(tests, selectTest1)
// 1.4 Select 测试 - 多条件(自动 AND
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.LastQuery
debugLog("main.go:149", "Select 多条件自动AND测试", Map{"count": len(admins2), "query": that.Db.LastQuery}, "H1_SELECT2")
tests = append(tests, selectTest2)
// 1.5 Update 测试
updateTest := Map{"name": "Update 更新测试"}
affected := that.Db.Update("admin", Map{
"title": "更新后的职位",
"modify_time[#]": "NOW()",
}, Map{"id": adminId})
updateTest["result"] = affected > 0
updateTest["affected"] = affected
debugLog("main.go:160", "Update 测试", Map{"affected": affected}, "H1_UPDATE")
tests = append(tests, updateTest)
// 1.6 Delete 测试 - 使用 test_batch 表
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
debugLog("main.go:175", "Delete 测试", Map{"affected": deleteAffected}, "H1_DELETE")
tests = append(tests, deleteTest)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 2. 条件查询语法测试 ====================
func testConditionSyntax(that *Context) Map {
result := Map{"name": "条件查询语法测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:188", "开始条件查询语法测试 (MySQL)", nil, "H2_CONDITION")
// 2.1 等于 (=) - 使用 article 表
test1 := Map{"name": "等于条件 (=)"}
articles1 := that.Db.Select("article", "id,title", Map{"state": 0, "LIMIT": 3})
test1["result"] = true
test1["count"] = len(articles1)
debugLog("main.go:195", "等于条件测试", Map{"count": len(articles1)}, "H2_EQUAL")
tests = append(tests, test1)
// 2.2 不等于 ([!])
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.LastQuery
debugLog("main.go:204", "不等于条件测试", Map{"count": len(articles2), "query": that.Db.LastQuery}, "H2_NOT_EQUAL")
tests = append(tests, test2)
// 2.3 大于 ([>]) 和 小于 ([<])
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)
debugLog("main.go:216", "大于小于条件测试", Map{"count": len(articles3)}, "H2_GREATER_LESS")
tests = append(tests, test3)
// 2.4 大于等于 ([>=]) 和 小于等于 ([<=])
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)
debugLog("main.go:228", "大于等于小于等于条件测试", Map{"count": len(articles4)}, "H2_GTE_LTE")
tests = append(tests, test4)
// 2.5 LIKE 模糊查询 ([~])
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.LastQuery
debugLog("main.go:237", "LIKE 模糊查询测试", Map{"count": len(articles5), "query": that.Db.LastQuery}, "H2_LIKE")
tests = append(tests, test5)
// 2.6 右模糊 ([~!])
test6 := Map{"name": "右模糊查询 ([~!])"}
articles6 := that.Db.Select("admin", "id,name", Map{"name[~!]": "管理", "LIMIT": 3})
test6["result"] = true
test6["count"] = len(articles6)
debugLog("main.go:245", "右模糊查询测试", Map{"count": len(articles6)}, "H2_LIKE_RIGHT")
tests = append(tests, test6)
// 2.7 BETWEEN ([<>])
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.LastQuery
debugLog("main.go:254", "BETWEEN 区间查询测试", Map{"count": len(articles7), "query": that.Db.LastQuery}, "H2_BETWEEN")
tests = append(tests, test7)
// 2.8 NOT BETWEEN ([><])
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)
debugLog("main.go:262", "NOT BETWEEN 查询测试", Map{"count": len(articles8)}, "H2_NOT_BETWEEN")
tests = append(tests, test8)
// 2.9 IN 查询
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.LastQuery
debugLog("main.go:271", "IN 查询测试", Map{"count": len(articles9), "query": that.Db.LastQuery}, "H2_IN")
tests = append(tests, test9)
// 2.10 NOT IN ([!])
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)
debugLog("main.go:279", "NOT IN 查询测试", Map{"count": len(articles10)}, "H2_NOT_IN")
tests = append(tests, test10)
// 2.11 IS NULL
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)
debugLog("main.go:287", "IS NULL 查询测试", Map{"count": len(articles11)}, "H2_IS_NULL")
tests = append(tests, test11)
// 2.12 IS NOT NULL ([!])
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)
debugLog("main.go:295", "IS NOT NULL 查询测试", Map{"count": len(articles12)}, "H2_IS_NOT_NULL")
tests = append(tests, test12)
// 2.13 直接 SQL ([##] 用于 SQL 片段)
test13 := Map{"name": "直接 SQL 片段查询 ([##])"}
articles13 := that.Db.Select("article", "id,title,create_time", Map{
"[##]": "create_time > DATE_SUB(NOW(), INTERVAL 365 DAY)",
"LIMIT": 3,
})
test13["result"] = true
test13["count"] = len(articles13)
test13["lastQuery"] = that.Db.LastQuery
debugLog("main.go:307", "直接 SQL 片段查询测试", Map{"count": len(articles13), "query": that.Db.LastQuery}, "H2_RAW_SQL")
tests = append(tests, test13)
// 2.14 显式 AND 条件
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)
debugLog("main.go:321", "显式 AND 条件测试", Map{"count": len(articles14)}, "H2_EXPLICIT_AND")
tests = append(tests, test14)
// 2.15 OR 条件
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)
debugLog("main.go:335", "OR 条件测试", Map{"count": len(articles15)}, "H2_OR")
tests = append(tests, test15)
// 2.16 嵌套 AND/OR 条件
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.LastQuery
debugLog("main.go:353", "嵌套 AND/OR 条件测试", Map{"count": len(articles16), "query": that.Db.LastQuery}, "H2_NESTED")
tests = append(tests, test16)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 3. 链式查询测试 ====================
func testChainQuery(that *Context) Map {
result := Map{"name": "链式查询测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:366", "开始链式查询测试 (MySQL)", nil, "H3_CHAIN")
// 3.1 基本链式查询 - 使用 article 表
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)
debugLog("main.go:375", "基本链式查询测试", Map{"count": len(articles1)}, "H3_BASIC")
tests = append(tests, test1)
// 3.2 链式 And 条件
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)
debugLog("main.go:387", "链式 And 条件测试", Map{"count": len(articles2)}, "H3_AND")
tests = append(tests, test2)
// 3.3 链式 Or 条件
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)
debugLog("main.go:401", "链式 Or 条件测试", Map{"count": len(articles3)}, "H3_OR")
tests = append(tests, test3)
// 3.4 链式 Order
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)
debugLog("main.go:413", "链式 Order 排序测试", Map{"count": len(articles4)}, "H3_ORDER")
tests = append(tests, test4)
// 3.5 链式 Limit
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)
debugLog("main.go:424", "链式 Limit 限制测试", Map{"count": len(articles5)}, "H3_LIMIT")
tests = append(tests, test5)
// 3.6 链式 Get 单条
test6 := Map{"name": "链式 Get 获取单条"}
article6 := that.Db.Table("article").
Where("state", 0).
Get("id,title,author")
test6["result"] = article6 != nil || true // 允许为空
test6["article"] = article6
debugLog("main.go:434", "链式 Get 获取单条测试", Map{"article": article6}, "H3_GET")
tests = append(tests, test6)
// 3.7 链式 Count
test7 := Map{"name": "链式 Count 统计"}
count7 := that.Db.Table("article").
Where("state", 0).
Count()
test7["result"] = count7 >= 0
test7["count"] = count7
debugLog("main.go:444", "链式 Count 统计测试", Map{"count": count7}, "H3_COUNT")
tests = append(tests, test7)
// 3.8 链式 Page 分页
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)
debugLog("main.go:455", "链式 Page 分页测试", Map{"count": len(articles8)}, "H3_PAGE")
tests = append(tests, test8)
// 3.9 链式 Group 分组
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
debugLog("main.go:466", "链式 Group 分组测试", Map{"stats": stats9}, "H3_GROUP")
tests = append(tests, test9)
// 3.10 链式 Update
test10 := Map{"name": "链式 Update 更新"}
// 先获取一个文章ID
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[#]": "NOW()"})
test10["result"] = affected >= 0
test10["affected"] = affected
} else {
test10["result"] = true
test10["note"] = "无可用测试数据"
}
debugLog("main.go:483", "链式 Update 更新测试", test10, "H3_UPDATE")
tests = append(tests, test10)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 4. JOIN 查询测试 ====================
func testJoinQuery(that *Context) Map {
result := Map{"name": "JOIN查询测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:496", "开始 JOIN 查询测试 (MySQL)", nil, "H4_JOIN")
// 4.1 LEFT JOIN 链式 - article 关联 ctg
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
debugLog("main.go:508", "LEFT JOIN 链式查询测试", Map{"count": len(articles1)}, "H4_LEFT_JOIN")
tests = append(tests, test1)
// 4.2 传统 JOIN 语法
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.LastQuery
debugLog("main.go:525", "传统 JOIN 语法测试", Map{"count": len(articles2), "query": that.Db.LastQuery}, "H4_TRADITIONAL_JOIN")
tests = append(tests, test2)
// 4.3 多表 JOIN - article 关联 ctg 和 admin
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
debugLog("main.go:539", "多表 JOIN 测试", Map{"count": len(articles3)}, "H4_MULTI_JOIN")
tests = append(tests, test3)
// 4.4 INNER JOIN
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)
debugLog("main.go:551", "INNER JOIN 测试", Map{"count": len(articles4)}, "H4_INNER_JOIN")
tests = append(tests, test4)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 5. 聚合函数测试 ====================
func testAggregate(that *Context) Map {
result := Map{"name": "聚合函数测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:564", "开始聚合函数测试 (MySQL)", nil, "H5_AGGREGATE")
// 5.1 Count 总数
test1 := Map{"name": "Count 总数统计"}
count1 := that.Db.Count("article")
test1["result"] = count1 >= 0
test1["count"] = count1
debugLog("main.go:571", "Count 总数统计测试", Map{"count": count1}, "H5_COUNT")
tests = append(tests, test1)
// 5.2 Count 带条件
test2 := Map{"name": "Count 条件统计"}
count2 := that.Db.Count("article", Map{"state": 0})
test2["result"] = count2 >= 0
test2["count"] = count2
debugLog("main.go:579", "Count 条件统计测试", Map{"count": count2}, "H5_COUNT_WHERE")
tests = append(tests, test2)
// 5.3 Sum 求和
test3 := Map{"name": "Sum 求和"}
sum3 := that.Db.Sum("article", "click_num", Map{"state": 0})
test3["result"] = sum3 >= 0
test3["sum"] = sum3
debugLog("main.go:587", "Sum 求和测试", Map{"sum": sum3}, "H5_SUM")
tests = append(tests, test3)
// 5.4 Avg 平均值
test4 := Map{"name": "Avg 平均值"}
avg4 := that.Db.Avg("article", "click_num", Map{"state": 0})
test4["result"] = avg4 >= 0
test4["avg"] = avg4
debugLog("main.go:595", "Avg 平均值测试", Map{"avg": avg4}, "H5_AVG")
tests = append(tests, test4)
// 5.5 Max 最大值
test5 := Map{"name": "Max 最大值"}
max5 := that.Db.Max("article", "click_num", Map{"state": 0})
test5["result"] = max5 >= 0
test5["max"] = max5
debugLog("main.go:603", "Max 最大值测试", Map{"max": max5}, "H5_MAX")
tests = append(tests, test5)
// 5.6 Min 最小值
test6 := Map{"name": "Min 最小值"}
min6 := that.Db.Min("article", "sort", Map{"state": 0})
test6["result"] = true // sort 可能为 0
test6["min"] = min6
debugLog("main.go:611", "Min 最小值测试", Map{"min": min6}, "H5_MIN")
tests = append(tests, test6)
// 5.7 GROUP BY 分组统计
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
debugLog("main.go:625", "GROUP BY 分组统计测试", Map{"stats": stats7}, "H5_GROUP_BY")
tests = append(tests, test7)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 6. 分页查询测试 ====================
func testPagination(that *Context) Map {
result := Map{"name": "分页查询测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:638", "开始分页查询测试 (MySQL)", nil, "H6_PAGINATION")
// 6.1 PageSelect 分页查询
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)
debugLog("main.go:648", "PageSelect 分页查询测试", Map{"count": len(articles1)}, "H6_PAGE_SELECT")
tests = append(tests, test1)
// 6.2 第二页
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)
debugLog("main.go:659", "PageSelect 第二页测试", Map{"count": len(articles2)}, "H6_PAGE_2")
tests = append(tests, test2)
// 6.3 链式分页
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)
debugLog("main.go:671", "链式 Page 分页测试", Map{"count": len(articles3)}, "H6_CHAIN_PAGE")
tests = append(tests, test3)
// 6.4 Offset 偏移
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.LastQuery
debugLog("main.go:684", "Offset 偏移查询测试", Map{"count": len(articles4), "query": that.Db.LastQuery}, "H6_OFFSET")
tests = append(tests, test4)
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 7. 批量插入测试 ====================
func testBatchInsert(that *Context) Map {
result := Map{"name": "批量插入测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:697", "开始批量插入测试 (MySQL)", nil, "H7_BATCH")
// 7.1 批量插入
test1 := Map{"name": "BatchInsert 批量插入"}
timestamp := time.Now().UnixNano()
affected1 := that.Db.BatchInsert("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.LastQuery
debugLog("main.go:710", "BatchInsert 批量插入测试", Map{"affected": affected1, "query": that.Db.LastQuery}, "H7_BATCH_INSERT")
tests = append(tests, test1)
// 7.2 带 [#] 的批量插入
test2 := Map{"name": "BatchInsert 带 [#] 标记"}
timestamp2 := time.Now().UnixNano()
affected2 := that.Db.BatchInsert("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
debugLog("main.go:722", "BatchInsert 带 [#] 标记测试", Map{"affected": affected2}, "H7_BATCH_RAW")
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
}
// ==================== 8. Upsert 测试 ====================
func testUpsert(that *Context) Map {
result := Map{"name": "Upsert测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:739", "开始 Upsert 测试 (MySQL)", nil, "H8_UPSERT")
// 使用 admin 表测试 UpsertMySQL ON DUPLICATE KEY UPDATE
timestamp := time.Now().Unix()
testPhone := fmt.Sprintf("199%08d", timestamp%100000000)
// 8.1 Upsert 插入新记录
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.LastQuery
debugLog("main.go:763", "Upsert 插入新记录测试", Map{"affected": affected1, "query": that.Db.LastQuery}, "H8_UPSERT_INSERT")
tests = append(tests, test1)
// 8.2 Upsert 更新已存在记录
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
debugLog("main.go:783", "Upsert 更新已存在记录测试", Map{"affected": affected2}, "H8_UPSERT_UPDATE")
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
}
// ==================== 9. 事务测试 ====================
func testTransaction(that *Context) Map {
result := Map{"name": "事务测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:803", "开始事务测试 (MySQL)", nil, "H9_TRANSACTION")
// 9.1 事务成功提交
test1 := Map{"name": "事务成功提交"}
timestamp := time.Now().Unix()
testName1 := fmt.Sprintf("事务测试_%d", timestamp)
success1 := that.Db.Action(func(tx HoTimeDB) bool {
// 插入记录到 test_batch 表
recordId := tx.Insert("test_batch", Map{
"name": testName1,
"title": "事务提交测试",
"state": 1,
"create_time[#]": "NOW()",
})
debugLog("main.go:818", "事务内插入记录", Map{"recordId": recordId}, "H9_TX_INSERT")
return recordId != 0
})
test1["result"] = success1
// 验证数据是否存在
checkRecord := that.Db.Get("test_batch", "*", Map{"name": testName1})
test1["recordExists"] = checkRecord != nil
debugLog("main.go:831", "事务成功提交测试", Map{"success": success1, "recordExists": checkRecord != nil}, "H9_TX_SUCCESS")
tests = append(tests, test1)
// 9.2 事务回滚
test2 := Map{"name": "事务回滚"}
testName2 := fmt.Sprintf("事务回滚测试_%d", timestamp)
success2 := that.Db.Action(func(tx HoTimeDB) bool {
// 插入记录
recordId := tx.Insert("test_batch", Map{
"name": testName2,
"title": "事务回滚测试",
"state": 1,
"create_time[#]": "NOW()",
})
debugLog("main.go:846", "事务内插入(将回滚)", Map{"recordId": recordId}, "H9_TX_ROLLBACK_INSERT")
// 返回 false 触发回滚
return false
})
test2["result"] = !success2 // 期望回滚,所以 success2 应该为 false
// 验证数据是否不存在(已回滚)
checkRecord2 := that.Db.Get("test_batch", "*", Map{"name": testName2})
test2["recordRolledBack"] = checkRecord2 == nil
debugLog("main.go:856", "事务回滚测试", Map{"success": success2, "rolledBack": checkRecord2 == nil}, "H9_TX_ROLLBACK")
tests = append(tests, test2)
// 清理测试数据
that.Db.Delete("test_batch", Map{"name": testName1})
result["tests"] = tests
result["success"] = true
return result
}
// ==================== 10. 原生 SQL 测试 ====================
func testRawSQL(that *Context) Map {
result := Map{"name": "原生SQL测试", "tests": Slice{}}
tests := Slice{}
debugLog("main.go:872", "开始原生 SQL 测试 (MySQL)", nil, "H10_RAW_SQL")
// 10.1 Query 查询 - 使用真实的 article 表
test1 := Map{"name": "Query 原生查询"}
articles1 := that.Db.Query("SELECT id, title, author FROM `article` WHERE state = ? LIMIT ?", 0, 5)
test1["result"] = len(articles1) >= 0
test1["count"] = len(articles1)
debugLog("main.go:879", "Query 原生查询测试", Map{"count": len(articles1)}, "H10_QUERY")
tests = append(tests, test1)
// 10.2 Exec 执行 - 使用 article 表
test2 := Map{"name": "Exec 原生执行"}
// 更新一条记录
testArticle := that.Db.Get("article", "id", Map{"state": 0})
if testArticle != nil {
res, err := that.Db.Exec("UPDATE `article` SET modify_time = NOW() WHERE id = ?", testArticle.GetInt64("id"))
if err.GetError() == nil && res != nil {
affected, _ := res.RowsAffected()
test2["result"] = affected >= 0
test2["affected"] = affected
} else {
test2["result"] = false
test2["error"] = err.GetError()
}
} else {
test2["result"] = true
test2["note"] = "无可用测试数据"
}
debugLog("main.go:899", "Exec 原生执行测试", test2, "H10_EXEC")
tests = append(tests, test2)
result["tests"] = tests
result["success"] = true
return result
}