main.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. package main
  2. import (
  3. "TsDB2/DB"
  4. "TsDB2/DB/core/page"
  5. "fmt"
  6. "os"
  7. "strings"
  8. "time"
  9. )
  10. // ========== 数据模型 ==========
  11. type User struct {
  12. DB.BaseModel
  13. Name string `tsdb:"32byte"`
  14. Age int64 `tsdb:"8byte"`
  15. Score int64 `tsdb:"8byte"`
  16. Dept string `tsdb:"16byte"`
  17. }
  18. type Order struct {
  19. DB.BaseModel
  20. UserID int64 `tsdb:"8byte"`
  21. Amount int64 `tsdb:"8byte"`
  22. Status int64 `tsdb:"8byte"`
  23. }
  24. var db *DB.DB
  25. var passed, failed int
  26. func check(msg string, ok bool) {
  27. if ok {
  28. passed++
  29. fmt.Printf(" ✅ %s\n", msg)
  30. } else {
  31. failed++
  32. fmt.Printf(" ❌ %s\n", msg)
  33. }
  34. }
  35. func section(title string) {
  36. fmt.Printf("\n%s %s\n", strings.Repeat("=", 50), title)
  37. }
  38. func main() {
  39. os.Remove("feature_demo.db")
  40. os.Remove("feature_demo.db.wal")
  41. fmt.Println(strings.Repeat("=", 60))
  42. fmt.Println(" TsDB2 全功能综合测试")
  43. fmt.Println(" 涵盖: 表/索引/CRUD/事务/WAL/BufferPool/提交策略/恢复")
  44. fmt.Println(strings.Repeat("=", 60))
  45. // ============================================================
  46. // 1. 数据库打开与配置
  47. // ============================================================
  48. section("1. 数据库配置与打开")
  49. var err error
  50. db, err = DB.Open("feature_demo.db")
  51. check("OpenDB", err == nil)
  52. // 配置参数
  53. db.SetBufferPoolCapacity(200) // 200 页 = 3.2MB
  54. db.SetDirtyThreshold(50) // 50 页脏页阈值
  55. db.SetAutoCommitDelay(500 * time.Millisecond) // 500ms 防抖
  56. db.SetCommitPreset("online") // 在线业务预设
  57. fmt.Println(" ✅ 配置: BufferPool=200页, DirtyThreshold=50页, Debounce=500ms, Preset=online")
  58. passed++
  59. // ============================================================
  60. // 2. 表创建 (UseTable 自动建表)
  61. // ============================================================
  62. section("2. 表创建 (泛型 UseTable)")
  63. userTbl, err := DB.UseTable[User](db, "users")
  64. check("UseTable[User] (自动建表+主键索引)", err == nil)
  65. orderTbl, err := DB.UseTable[Order](db, "orders")
  66. check("UseTable[Order] (自动建表+主键索引)", err == nil)
  67. // 重复调用应自动同步 schema (不报错)
  68. userTbl2, err := DB.UseTable[User](db, "users")
  69. check("重复 UseTable[User] 自动同步 schema", err == nil && userTbl2 != nil)
  70. // ============================================================
  71. // 3. 二级索引创建
  72. // ============================================================
  73. section("3. 二级索引创建")
  74. userCore, _ := db.CoreDB().FindTable("users")
  75. _, err = userCore.CreateIndex("idx_age", page.IndexTypeBTree, []byte{2}) // Age
  76. check("CreateIndex idx_age (B+树)", err == nil)
  77. _, err = userCore.CreateIndex("idx_dept", page.IndexTypeBTree, []byte{4}) // Dept
  78. check("CreateIndex idx_dept (B+树)", err == nil)
  79. orderCore, _ := db.CoreDB().FindTable("orders")
  80. _, err = orderCore.CreateIndex("idx_status", page.IndexTypeBTree, []byte{3}) // Status
  81. check("CreateIndex idx_status (B+树)", err == nil)
  82. // ============================================================
  83. // 4. 基础 CRUD
  84. // ============================================================
  85. section("4. 基础 CRUD")
  86. // INSERT
  87. for i := 1; i <= 20; i++ {
  88. err := userTbl.Insert(&User{
  89. Name: fmt.Sprintf("User%03d", i),
  90. Age: int64(20 + i%30),
  91. Score: int64(50 + i*3),
  92. Dept: fmt.Sprintf("D%d", i%5),
  93. })
  94. if err != nil {
  95. fmt.Printf(" ❌ Insert(%d): %v\n", i, err)
  96. failed++
  97. }
  98. }
  99. fmt.Println(" ✅ Insert 20 行 (ID=1~20)")
  100. passed++
  101. // FIND (精确查找)
  102. u, err := userTbl.Find(5)
  103. if err == nil && u != nil {
  104. fmt.Printf(" ✅ Find(5): Name=%s Age=%d Score=%d Dept=%s\n", u.Name, u.Age, u.Score, u.Dept)
  105. passed++
  106. } else {
  107. fmt.Println(" ❌ Find(5) 失败")
  108. failed++
  109. }
  110. // UPDATE
  111. err = userTbl.Update(&User{
  112. BaseModel: DB.BaseModel{ID: 5},
  113. Score: 999,
  114. })
  115. check("Update(5) Score=999", err == nil)
  116. u, _ = userTbl.Find(5)
  117. if u != nil && u.Score == 999 {
  118. fmt.Printf(" ✅ 验证更新: Score=%d\n", u.Score)
  119. passed++
  120. } else {
  121. fmt.Println(" ❌ 更新验证失败")
  122. failed++
  123. }
  124. // DELETE
  125. err = userTbl.Delete(10)
  126. check("Delete(10)", err == nil)
  127. _, err = userTbl.Find(10)
  128. check("验证删除: ID=10 不存在", err != nil)
  129. // ============================================================
  130. // 5. 条件查询 (Where / OrderBy / Limit / Offset)
  131. // ============================================================
  132. section("5. 条件查询")
  133. // WHERE 等值
  134. users, err := userTbl.Where("Age", "=", int64(25)).Find()
  135. if err == nil {
  136. fmt.Printf(" ✅ WHERE Age=25: %d 行\n", len(users))
  137. passed++
  138. } else {
  139. fmt.Printf(" ❌ WHERE Age=25: %v\n", err)
  140. failed++
  141. }
  142. // WHERE 范围 (AND)
  143. users, err = userTbl.Where("Age", ">=", int64(20)).Where("Age", "<=", int64(25)).Find()
  144. if err == nil {
  145. fmt.Printf(" ✅ WHERE Age>=20 AND Age<=25: %d 行\n", len(users))
  146. passed++
  147. } else {
  148. fmt.Printf(" ❌ WHERE 范围: %v\n", err)
  149. failed++
  150. }
  151. // WHERE 大于
  152. users, err = userTbl.Where("Age", ">", int64(40)).Find()
  153. if err == nil {
  154. fmt.Printf(" ✅ WHERE Age>40: %d 行\n", len(users))
  155. passed++
  156. } else {
  157. fmt.Printf(" ❌ WHERE Age>40: %v\n", err)
  158. failed++
  159. }
  160. // LIKE
  161. users, err = userTbl.Where("Name", "like", "User%").Find()
  162. if err == nil {
  163. fmt.Printf(" ✅ WHERE Name LIKE 'User%%': %d 行\n", len(users))
  164. passed++
  165. } else {
  166. fmt.Printf(" ❌ LIKE: %v\n", err)
  167. failed++
  168. }
  169. // != (NOT)
  170. users, err = userTbl.Where("Age", "!=", int64(25)).Find()
  171. if err == nil {
  172. fmt.Printf(" ✅ WHERE Age!=25: %d 行\n", len(users))
  173. passed++
  174. } else {
  175. fmt.Printf(" ❌ NOT: %v\n", err)
  176. failed++
  177. }
  178. // ============================================================
  179. // 6. 排序 + 分页
  180. // ============================================================
  181. section("6. 排序 + 分页")
  182. users, err = userTbl.OrderBy("Age", true).Limit(5).Find()
  183. if err == nil && len(users) == 5 {
  184. fmt.Println(" ✅ ORDER BY Age DESC LIMIT 5:")
  185. for i, u := range users {
  186. fmt.Printf(" [%d] Name=%s Age=%d Score=%d\n", i+1, u.Name, u.Age, u.Score)
  187. }
  188. passed++
  189. } else {
  190. fmt.Printf(" ❌ 排序分页: err=%v rows=%d\n", err, len(users))
  191. failed++
  192. }
  193. users, err = userTbl.OrderBy("Age", false).Offset(5).Limit(5).Find()
  194. if err == nil && len(users) == 5 {
  195. fmt.Println(" ✅ ORDER BY Age ASC OFFSET 5 LIMIT 5:")
  196. for i, u := range users {
  197. fmt.Printf(" [%d] Name=%s Age=%d Score=%d\n", i+1, u.Name, u.Age, u.Score)
  198. }
  199. passed++
  200. } else {
  201. fmt.Printf(" ❌ OFFSET 分页: err=%v rows=%d\n", err, len(users))
  202. failed++
  203. }
  204. // ============================================================
  205. // 7. 聚合查询
  206. // ============================================================
  207. section("7. 聚合查询")
  208. cnt, err := userTbl.Query().Count()
  209. if err == nil {
  210. fmt.Printf(" ✅ COUNT(*): %d\n", cnt)
  211. passed++
  212. } else {
  213. fmt.Printf(" ❌ COUNT: %v\n", err)
  214. failed++
  215. }
  216. cnt, err = userTbl.Where("Age", "=", int64(25)).Count()
  217. if err == nil {
  218. fmt.Printf(" ✅ COUNT WHERE Age=25: %d\n", cnt)
  219. passed++
  220. } else {
  221. fmt.Printf(" ❌ COUNT WHERE: %v\n", err)
  222. failed++
  223. }
  224. // ============================================================
  225. // 8. Scan 流式遍历
  226. // ============================================================
  227. section("8. Scan 流式遍历")
  228. // Scan callback: return true=继续, false=停止
  229. scanCount := 0
  230. err = userTbl.Query().Limit(10).Scan(func(u *User) bool {
  231. scanCount++
  232. return true // 继续扫描
  233. })
  234. if err == nil && scanCount == 10 {
  235. fmt.Printf(" ✅ Scan LIMIT 10: 遍历 %d 行\n", scanCount)
  236. passed++
  237. } else {
  238. fmt.Printf(" ❌ Scan: err=%v count=%d\n", err, scanCount)
  239. failed++
  240. }
  241. // ============================================================
  242. // 9. 事务 - 提交
  243. // ============================================================
  244. section("9. 事务 - 提交")
  245. txn := db.BeginTransaction()
  246. // 事务内插入 (使用同一个 tbl 对象)
  247. for i := 21; i <= 30; i++ {
  248. err := userTbl.Insert(&User{
  249. Name: fmt.Sprintf("Txn%03d", i),
  250. Age: int64(30 + i%10),
  251. Score: int64(70 + i),
  252. Dept: fmt.Sprintf("D%d", i%4),
  253. })
  254. if err != nil {
  255. fmt.Printf(" ❌ 事务内 Insert(%d): %v\n", i, err)
  256. failed++
  257. }
  258. }
  259. fmt.Println(" ✅ 事务内插入 10 行 (ID=21~30)")
  260. passed++
  261. // 事务内更新
  262. err = userTbl.Update(&User{
  263. BaseModel: DB.BaseModel{ID: 21},
  264. Score: 8888,
  265. })
  266. check("事务内 Update(21) Score=8888", err == nil)
  267. // 事务内删除
  268. err = userTbl.Delete(25)
  269. check("事务内 Delete(25)", err == nil)
  270. err = txn.Commit()
  271. check("Transaction.Commit()", err == nil)
  272. // 验证
  273. u, err = userTbl.Find(21)
  274. if err == nil && u != nil && u.Score == 8888 {
  275. fmt.Printf(" ✅ 提交后验证: ID=21 Score=%d\n", u.Score)
  276. passed++
  277. } else {
  278. fmt.Println(" ❌ 提交后验证: ID=21 不正确")
  279. failed++
  280. }
  281. _, err = userTbl.Find(25)
  282. check("提交后验证: ID=25 已删除", err != nil)
  283. // ============================================================
  284. // 10. 事务 - 回滚
  285. // ============================================================
  286. section("10. 事务 - 回滚")
  287. txn2 := db.BeginTransaction()
  288. for i := 31; i <= 40; i++ {
  289. userTbl.Insert(&User{
  290. Name: fmt.Sprintf("Rb%03d", i),
  291. Age: int64(20),
  292. Score: int64(0),
  293. Dept: "X",
  294. })
  295. }
  296. fmt.Println(" ✅ 事务内插入 10 行 (ID=31~40)")
  297. passed++
  298. err = txn2.Rollback()
  299. check("Transaction.Rollback()", err == nil)
  300. // 回滚后 ID=31 应不存在 (需要重开后验证, 内存中可能还有残留)
  301. // 先标记, 后面重开后验证
  302. fmt.Println(" ⏳ 回滚后数据验证将在重开后进行")
  303. // ============================================================
  304. // 11. WAL + Commit 持久化
  305. // ============================================================
  306. section("11. WAL + Commit 持久化")
  307. err = db.Commit()
  308. check("DB.Commit() (WAL 写入)", err == nil)
  309. // ============================================================
  310. // 12. 多表操作
  311. // ============================================================
  312. section("12. 多表操作")
  313. for i := 1; i <= 10; i++ {
  314. orderTbl.Insert(&Order{
  315. UserID: int64(i*2 - 1),
  316. Amount: int64(100 + i*50),
  317. Status: int64(i % 3),
  318. })
  319. }
  320. fmt.Println(" ✅ orders 表插入 10 行")
  321. passed++
  322. orders, err := orderTbl.Where("Status", "=", int64(0)).Find()
  323. if err == nil {
  324. fmt.Printf(" ✅ orders WHERE Status=0: %d 行\n", len(orders))
  325. passed++
  326. } else {
  327. fmt.Printf(" ❌ orders 查询: %v\n", err)
  328. failed++
  329. }
  330. // ============================================================
  331. // 13. DropTable
  332. // ============================================================
  333. section("13. DropTable")
  334. err = db.DropTable("orders")
  335. check("DropTable orders", err == nil)
  336. orderCore2, _ := db.CoreDB().FindTable("orders")
  337. check("orders 表已不存在", orderCore2 == nil)
  338. userCore2, _ := db.CoreDB().FindTable("users")
  339. check("users 表不受影响", userCore2 != nil)
  340. // ============================================================
  341. // 14. 关闭 + 重开验证持久化
  342. // ============================================================
  343. section("14. 关闭 + 重开验证持久化")
  344. err = db.Close()
  345. check("DB.Close()", err == nil)
  346. db, err = DB.Open("feature_demo.db")
  347. check("重新打开数据库", err == nil)
  348. userTbl, _ = DB.UseTable[User](db, "users")
  349. u, err = userTbl.Find(1)
  350. if err == nil && u != nil {
  351. fmt.Printf(" ✅ 重开后 Find(1): Name=%s Age=%d\n", u.Name, u.Age)
  352. passed++
  353. } else {
  354. fmt.Println(" ❌ 重开后 Find(1) 失败")
  355. failed++
  356. }
  357. u, err = userTbl.Find(5)
  358. if err == nil && u.Score == 999 {
  359. fmt.Printf(" ✅ 重开后 Find(5): Score=%d (更新持久化)\n", u.Score)
  360. passed++
  361. } else {
  362. fmt.Println(" ❌ 重开后 Find(5) Score 不正确")
  363. failed++
  364. }
  365. _, err = userTbl.Find(10)
  366. check("重开后 ID=10 (已删除) 不存在", err != nil)
  367. // 验证事务提交的数据
  368. u, err = userTbl.Find(21)
  369. if err == nil && u.Score == 8888 {
  370. fmt.Printf(" ✅ 重开后 Find(21) (事务提交+更新): Score=%d\n", u.Score)
  371. passed++
  372. } else {
  373. fmt.Println(" ❌ 重开后 Find(21) 失败或数据不正确")
  374. failed++
  375. }
  376. _, err = userTbl.Find(25)
  377. check("重开后 ID=25 (事务内删除) 不存在", err != nil)
  378. // 验证回滚的数据不存在
  379. _, err = userTbl.Find(31)
  380. check("重开后 ID=31 (回滚) 不存在", err != nil)
  381. // ============================================================
  382. // 15. 防抖自动提交验证
  383. // ============================================================
  384. section("15. 防抖自动提交")
  385. // 重新打开一个干净的数据库来测试自动提交
  386. db.Close()
  387. os.Remove("feature_demo.db")
  388. os.Remove("feature_demo.db.wal")
  389. db, _ = DB.Open("feature_demo.db")
  390. db.SetAutoCommitDelay(500 * time.Millisecond)
  391. userTbl, _ = DB.UseTable[User](db, "users")
  392. for i := 1; i <= 10; i++ {
  393. userTbl.Insert(&User{
  394. Name: fmt.Sprintf("Auto%03d", i),
  395. Age: int64(25),
  396. Score: int64(100),
  397. Dept: "AUTO",
  398. })
  399. }
  400. fmt.Println(" ✅ 插入 10 行, 等待防抖自动提交 (500ms)...")
  401. time.Sleep(1500 * time.Millisecond)
  402. db.Close()
  403. db, _ = DB.Open("feature_demo.db")
  404. userTbl, _ = DB.UseTable[User](db, "users")
  405. u, err = userTbl.Find(5)
  406. if err == nil && u != nil {
  407. fmt.Printf(" ✅ 防抖自动提交后重开: ID=5 存在 (Name=%s)\n", u.Name)
  408. passed++
  409. } else {
  410. fmt.Println(" ❌ 防抖自动提交失败: ID=5 不存在")
  411. failed++
  412. }
  413. // ============================================================
  414. // 16. LockTable 机制
  415. // ============================================================
  416. section("16. LockTable 机制")
  417. db.LockWrites()
  418. fmt.Println(" ✅ LockWrites() 成功")
  419. passed++
  420. db.UnlockWrites()
  421. fmt.Println(" ✅ UnlockWrites() 成功")
  422. passed++
  423. // ============================================================
  424. // 17. 提交策略预设对比
  425. // ============================================================
  426. section("17. 提交策略预设")
  427. presets := []string{"batch", "online", "safe"}
  428. for _, p := range presets {
  429. db.SetCommitPreset(p)
  430. fmt.Printf(" ✅ Preset '%s' 设置成功\n", p)
  431. passed++
  432. }
  433. // ============================================================
  434. // 18. BatchInsert
  435. // ============================================================
  436. section("18. 批量插入 (BatchInsert)")
  437. batchUsers := make([]*User, 10)
  438. for i := 0; i < 10; i++ {
  439. batchUsers[i] = &User{
  440. Name: fmt.Sprintf("Batch%03d", i+51),
  441. Age: int64(30 + i),
  442. Score: int64(200 + i),
  443. Dept: "BATCH",
  444. }
  445. }
  446. err = userTbl.BatchInsert(batchUsers)
  447. check("BatchInsert 10 行", err == nil)
  448. // ============================================================
  449. // 19. First 查询
  450. // ============================================================
  451. section("19. First 查询")
  452. first, err := userTbl.Where("Age", ">=", int64(20)).OrderBy("Age", false).First()
  453. if err == nil && first != nil {
  454. fmt.Printf(" ✅ First(): Name=%s Age=%d\n", first.Name, first.Age)
  455. passed++
  456. } else {
  457. fmt.Printf(" ❌ First(): %v\n", err)
  458. failed++
  459. }
  460. // ============================================================
  461. // 20. FindAll
  462. // ============================================================
  463. section("20. FindAll")
  464. all, err := userTbl.FindAll()
  465. if err == nil {
  466. fmt.Printf(" ✅ FindAll(): %d 行\n", len(all))
  467. passed++
  468. } else {
  469. fmt.Printf(" ❌ FindAll(): %v\n", err)
  470. failed++
  471. }
  472. // ============================================================
  473. // 最终汇总
  474. // ============================================================
  475. fmt.Println()
  476. fmt.Println(strings.Repeat("=", 60))
  477. fmt.Printf(" 测试结果: %d 通过, %d 失败\n", passed, failed)
  478. if failed == 0 {
  479. fmt.Println(" 🎉 全部通过!")
  480. } else {
  481. fmt.Printf(" ⚠️ %d 项失败\n", failed)
  482. }
  483. fmt.Println(strings.Repeat("=", 60))
  484. db.Close()
  485. os.Remove("feature_demo.db")
  486. os.Remove("feature_demo.db.wal")
  487. }