main.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. package main
  2. import (
  3. "TsDB2/DB"
  4. "TsDB2/DB/core/page"
  5. "fmt"
  6. "os"
  7. "time"
  8. )
  9. // ========== 数据模型 ==========
  10. type Employee struct {
  11. DB.BaseModel
  12. Name string `tsdb:"32byte"`
  13. Age int64 `tsdb:"8byte"`
  14. Score int64 `tsdb:"8byte"`
  15. Dept string `tsdb:"16byte"`
  16. }
  17. type Order struct {
  18. DB.BaseModel
  19. EmployeeID int64 `tsdb:"8byte"`
  20. Amount int64 `tsdb:"8byte"`
  21. Status int64 `tsdb:"8byte"`
  22. }
  23. const dbPath = "fulltest.db"
  24. const N = 100_000
  25. func main() {
  26. os.Remove(dbPath)
  27. passed := 0
  28. failed := 0
  29. check := func(name string, ok bool, detail string) {
  30. if ok {
  31. passed++
  32. fmt.Printf(" ✅ %s\n", name)
  33. } else {
  34. failed++
  35. fmt.Printf(" ❌ %s — %s\n", name, detail)
  36. }
  37. }
  38. // =============================================
  39. fmt.Println("========== 1. 打开数据库 + 建表 ==========")
  40. // =============================================
  41. db, err := DB.Open(dbPath)
  42. if err != nil {
  43. panic(err)
  44. }
  45. // 禁用自动提交, 手动控制 Commit 时机 (百万行插入时避免中间 Commit)
  46. db.SetAutoCommitDelay(0)
  47. empTbl, err := DB.UseTable[Employee](db, "employee")
  48. if err != nil {
  49. panic(err)
  50. }
  51. // 创建二级索引: age (B+树)
  52. empCore, _ := db.CoreDB().FindTable("employee")
  53. empCore.CreateIndex("idx_age", page.IndexTypeBTree, []byte{2}) // field index 2 = Age
  54. empCore.CreateIndex("idx_dept", page.IndexTypeBTree, []byte{4}) // field index 4 = Dept
  55. orderTbl, err := DB.UseTable[Order](db, "order")
  56. if err != nil {
  57. panic(err)
  58. }
  59. orderCore, _ := db.CoreDB().FindTable("order")
  60. orderCore.CreateIndex("idx_status", page.IndexTypeBTree, []byte{3}) // Status
  61. fmt.Println(" 表 employee: ID + Name(32byte) + Age(8byte) + Score(8byte) + Dept(16byte)")
  62. fmt.Println(" 索引: pk_employee, idx_age, idx_dept")
  63. fmt.Println(" 表 order: ID + EmployeeID(8byte) + Amount(8byte) + Status(8byte)")
  64. fmt.Println(" 索引: pk_order, idx_status")
  65. // =============================================
  66. fmt.Println("\n========== 2. 批量插入 100万行 ==========")
  67. // =============================================
  68. depts := []string{"Eng", "Sales", "HR", "Fin", "Ops"}
  69. t0 := time.Now()
  70. for i := 1; i <= N; i++ {
  71. err := empTbl.Insert(&Employee{
  72. Name: fmt.Sprintf("Emp%07d", i),
  73. Age: int64(20 + (i % 50)),
  74. Score: int64(i % 1000),
  75. Dept: depts[i%5],
  76. })
  77. if err != nil {
  78. panic(fmt.Sprintf("insert row %d: %v", i, err))
  79. }
  80. if i%20000 == 0 {
  81. fmt.Printf(" 已插入 %d 行 (%.1fs)\n", i, time.Since(t0).Seconds())
  82. }
  83. }
  84. // 手动 Commit 所有数据
  85. fmt.Println(" 插入完成, 开始 Commit...")
  86. t1 := time.Now()
  87. if err := db.Commit(); err != nil {
  88. panic(err)
  89. }
  90. insertTime := time.Since(t0)
  91. fmt.Printf(" ✅ 插入 %d 行 + Commit 完成, 耗时 %.1fs (Commit %.1fs)\n", N, insertTime.Seconds(), time.Since(t1).Seconds())
  92. // =============================================
  93. fmt.Println("\n========== 3. 主键查询 ==========")
  94. // =============================================
  95. // 精确查找
  96. row, err := empTbl.Find(1)
  97. check("PK 精确查找 id=1", err == nil && row.Name == "Emp0000001",
  98. fmt.Sprintf("err=%v name=%s", err, row.Name))
  99. row, err = empTbl.Find(uint64(N / 2))
  100. rn := ""
  101. if row != nil {
  102. rn = row.Name
  103. }
  104. check(fmt.Sprintf("PK 精确查找 id=%d", N/2), err == nil && row != nil && row.Name == fmt.Sprintf("Emp%07d", N/2),
  105. fmt.Sprintf("err=%v name=%s", err, rn))
  106. row, err = empTbl.Find(uint64(N))
  107. rn = ""
  108. if row != nil {
  109. rn = row.Name
  110. }
  111. check(fmt.Sprintf("PK 精确查找 id=%d", N), err == nil && row != nil && row.Name == fmt.Sprintf("Emp%07d", N),
  112. fmt.Sprintf("err=%v name=%s", err, rn))
  113. // =============================================
  114. fmt.Println("\n========== 4. 条件查询 ==========")
  115. // =============================================
  116. // WHERE age = 25
  117. t2 := time.Now()
  118. rows, err := empTbl.Where("Age", "=", int64(25)).Find()
  119. check("WHERE Age=25", err == nil && len(rows) > 0,
  120. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  121. fmt.Printf(" 返回 %d 行, 耗时 %.3fs\n", len(rows), time.Since(t2).Seconds())
  122. // WHERE age > 60
  123. t2 = time.Now()
  124. rows, err = empTbl.Where("Age", ">", int64(60)).Find()
  125. check("WHERE Age>60", err == nil && len(rows) > 0,
  126. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  127. fmt.Printf(" 返回 %d 行, 耗时 %.3fs\n", len(rows), time.Since(t2).Seconds())
  128. // WHERE age >= 20 AND age <= 25
  129. t2 = time.Now()
  130. rows, err = empTbl.Where("Age", ">=", int64(20)).Where("Age", "<=", int64(25)).Find()
  131. check("WHERE Age>=20 AND Age<=25", err == nil && len(rows) > 0,
  132. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  133. fmt.Printf(" 返回 %d 行, 耗时 %.3fs\n", len(rows), time.Since(t2).Seconds())
  134. // WHERE score = 999
  135. t2 = time.Now()
  136. rows, err = empTbl.Where("Score", "=", int64(999)).Find()
  137. check("WHERE Score=999 (全表扫描)", err == nil && len(rows) > 0,
  138. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  139. fmt.Printf(" 返回 %d 行, 耗时 %.3fs\n", len(rows), time.Since(t2).Seconds())
  140. // =============================================
  141. fmt.Println("\n========== 5. 排序 + 分页 ==========")
  142. // =============================================
  143. // ORDER BY Age ASC LIMIT 10
  144. t2 = time.Now()
  145. rows, err = empTbl.OrderBy("Age").Limit(10).Find()
  146. check("ORDER BY Age ASC LIMIT 10", err == nil && len(rows) == 10,
  147. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  148. if len(rows) >= 2 {
  149. check(" 排序正确 (前2行 Age 递增)", rows[0].Age <= rows[1].Age,
  150. fmt.Sprintf("age[0]=%d age[1]=%d", rows[0].Age, rows[1].Age))
  151. }
  152. fmt.Printf(" 耗时 %.3fs\n", time.Since(t2).Seconds())
  153. // ORDER BY Age DESC LIMIT 5
  154. rows, err = empTbl.OrderBy("Age", true).Limit(5).Find()
  155. check("ORDER BY Age DESC LIMIT 5", err == nil && len(rows) == 5,
  156. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  157. if len(rows) >= 2 {
  158. check(" 排序正确 (前2行 Age 递减)", rows[0].Age >= rows[1].Age,
  159. fmt.Sprintf("age[0]=%d age[1]=%d", rows[0].Age, rows[1].Age))
  160. }
  161. // OFFSET + LIMIT
  162. rows, err = empTbl.OrderBy("Age").Offset(100).Limit(5).Find()
  163. check("ORDER BY Age OFFSET 100 LIMIT 5", err == nil && len(rows) == 5,
  164. fmt.Sprintf("err=%v count=%d", err, len(rows)))
  165. // =============================================
  166. fmt.Println("\n========== 6. 聚合查询 ==========")
  167. // =============================================
  168. t2 = time.Now()
  169. cnt, err := empTbl.Count()
  170. check("COUNT(*)", err == nil && cnt == int64(N),
  171. fmt.Sprintf("err=%v count=%d", err, cnt))
  172. fmt.Printf(" COUNT=%d, 耗时 %.3fs\n", cnt, time.Since(t2).Seconds())
  173. // =============================================
  174. fmt.Println("\n========== 7. 第二张表: 插入 + 关联查询 ==========")
  175. // =============================================
  176. orderN := 10_000
  177. t2 = time.Now()
  178. for i := 1; i <= orderN; i++ {
  179. err := orderTbl.Insert(&Order{
  180. EmployeeID: int64(1 + (i % N)),
  181. Amount: int64(100 + (i % 500)),
  182. Status: int64(i % 4), // 0=pending 1=done 2=cancel 3=refund
  183. })
  184. if err != nil {
  185. panic(err)
  186. }
  187. if i%5000 == 0 {
  188. fmt.Printf(" 已插入 %d 行 (%.1fs)\n", i, time.Since(t2).Seconds())
  189. }
  190. }
  191. db.Commit()
  192. fmt.Printf(" ✅ 插入 %d 行 Order + Commit, 耗时 %.1fs\n", orderN, time.Since(t2).Seconds())
  193. // 查 order 的 status
  194. rows2, _ := orderTbl.Where("Status", "=", int64(0)).Find()
  195. fmt.Printf(" Order WHERE Status=0: %d 行\n", len(rows2))
  196. check("Order WHERE Status=0", len(rows2) > 0, "should have results")
  197. // =============================================
  198. fmt.Println("\n========== 8. 更新操作 ==========")
  199. // =============================================
  200. // 更新 id=1 的 employee
  201. t2 = time.Now()
  202. err = empTbl.Update(&Employee{
  203. BaseModel: DB.BaseModel{ID: 1},
  204. Name: "Updated_Emp0000001",
  205. Age: 99,
  206. Score: 0,
  207. Dept: "VIP",
  208. })
  209. check("UPDATE id=1", err == nil, fmt.Sprintf("err=%v", err))
  210. db.Commit()
  211. // 验证更新
  212. row, err = empTbl.Find(1)
  213. check("UPDATE 后验证", err == nil && row.Name == "Updated_Emp0000001" && row.Age == 99,
  214. fmt.Sprintf("err=%v name=%s age=%d", err, row.Name, row.Age))
  215. fmt.Printf(" 更新+Commit 耗时 %.3fs\n", time.Since(t2).Seconds())
  216. // =============================================
  217. fmt.Println("\n========== 9. 删除操作 ==========")
  218. // =============================================
  219. // 删除 id=2
  220. t2 = time.Now()
  221. err = empTbl.Delete(2)
  222. check("DELETE id=2", err == nil, fmt.Sprintf("err=%v", err))
  223. db.Commit()
  224. // 验证删除
  225. _, err = empTbl.Find(2)
  226. check("DELETE 后验证 (应找不到)", err != nil, "should not find id=2")
  227. // 删除 id=3~12 (10行)
  228. for i := 3; i <= 12; i++ {
  229. empTbl.Delete(uint64(i))
  230. }
  231. db.Commit()
  232. cnt, _ = empTbl.Count()
  233. check("DELETE 11行后 COUNT", cnt == int64(N-11),
  234. fmt.Sprintf("expected %d, got %d", N-11, cnt))
  235. fmt.Printf(" 删除+Commit 耗时 %.3fs\n", time.Since(t2).Seconds())
  236. // =============================================
  237. fmt.Println("\n========== 10. 关闭 + 重开验证持久化 ==========")
  238. // =============================================
  239. db.Close()
  240. db2, err := DB.Open(dbPath)
  241. if err != nil {
  242. panic(err)
  243. }
  244. db2.SetAutoCommitDelay(0) // 手动模式
  245. empTbl2, _ := DB.UseTable[Employee](db2, "employee")
  246. orderTbl2, _ := DB.UseTable[Order](db2, "order")
  247. cnt, _ = empTbl2.Count()
  248. check("重开后 employee COUNT", cnt == int64(N-11),
  249. fmt.Sprintf("expected %d, got %d", N-11, cnt))
  250. cnt2, _ := orderTbl2.Count()
  251. check("重开后 order COUNT", cnt2 == int64(orderN),
  252. fmt.Sprintf("expected %d, got %d", orderN, cnt2))
  253. // 验证更新持久化
  254. row, _ = empTbl2.Find(1)
  255. check("重开后 UPDATE 持久化", row.Name == "Updated_Emp0000001" && row.Age == 99,
  256. fmt.Sprintf("name=%s age=%d", row.Name, row.Age))
  257. // 验证删除持久化
  258. _, err = empTbl2.Find(2)
  259. check("重开后 DELETE 持久化", err != nil, "id=2 should be deleted")
  260. // =============================================
  261. fmt.Println("\n========== 11. 防抖自动提交测试 ==========")
  262. // =============================================
  263. db2.SetAutoCommitDelay(500 * time.Millisecond)
  264. // 插入几行, 等自动提交
  265. for i := N + 1; i <= N+100; i++ {
  266. empTbl2.Insert(&Employee{
  267. Name: fmt.Sprintf("Auto%04d", i-N), Age: 30, Score: 50, Dept: "Auto",
  268. })
  269. }
  270. fmt.Println(" 插入 100 行, 等待防抖自动提交 (500ms)...")
  271. time.Sleep(1 * time.Second)
  272. // 关闭再重开验证
  273. db2.Close()
  274. db3, _ := DB.Open(dbPath)
  275. empTbl3, _ := DB.UseTable[Employee](db3, "employee")
  276. cnt, _ = empTbl3.Count()
  277. expected := int64(N - 11 + 100)
  278. check("防抖自动提交后重开 COUNT", cnt == expected,
  279. fmt.Sprintf("expected %d, got %d", expected, cnt))
  280. db3.Close()
  281. // =============================================
  282. fmt.Println("\n========== 12. 删除表 + 空闲页回收 ==========")
  283. // =============================================
  284. db4, _ := DB.Open(dbPath)
  285. db4.SetAutoCommitDelay(0)
  286. // 记录删除前的空闲页数
  287. beforeFree := db4.CoreDB().DebugFreePageCount()
  288. fmt.Printf(" 删除表前 FreePageCount=%d\n", beforeFree)
  289. // 删除 order 表
  290. err = db4.DropTable("order")
  291. check("DropTable order", err == nil, fmt.Sprintf("err=%v", err))
  292. db4.Commit()
  293. afterFree := db4.CoreDB().DebugFreePageCount()
  294. fmt.Printf(" 删除表后 FreePageCount=%d (回收 %d 页)\n", afterFree, afterFree-beforeFree)
  295. check("删除表后空闲页增加", afterFree > beforeFree,
  296. fmt.Sprintf("before=%d after=%d", beforeFree, afterFree))
  297. // 验证 order 表已不存在
  298. _, ok := db4.CoreDB().FindTable("order")
  299. check("order 表已不存在", !ok, "order table should not exist")
  300. // employee 表仍正常
  301. empTbl4, _ := DB.UseTable[Employee](db4, "employee")
  302. cnt, _ = empTbl4.Count()
  303. check("employee 表不受影响", cnt == expected,
  304. fmt.Sprintf("expected %d, got %d", expected, cnt))
  305. db4.Close()
  306. // =============================================
  307. fmt.Printf("\n============================================\n")
  308. fmt.Printf("测试结果: %d 通过, %d 失败\n", passed, failed)
  309. if failed == 0 {
  310. fmt.Println("🎉 全部通过!")
  311. } else {
  312. fmt.Printf("⚠️ 有 %d 项失败\n", failed)
  313. }
  314. }