compose_varwidth_test.go 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package core
  2. import "testing"
  3. import "git.ycl.pub/yl32940/TsDB2/DB/core/page"
  4. import "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  5. // TestVarWidthComposeCorrectness 非 8 字节分量的复合索引 (SBT B+ 树) 端到端正确性:
  6. func TestVarWidthComposeCorrectness(t *testing.T) {
  7. db := fixOpenDB(t)
  8. tbl, err := db.CreateTable("t", []types.FieldInfo{
  9. {FieldType: types.FieldType_Uint64, FieldName: []byte("id")},
  10. {FieldType: types.FieldType_Decimal, FieldName: []byte("amt"), Flag: 2}, // 18B
  11. {FieldType: types.FieldType_Year, FieldName: []byte("yr")}, // 2B
  12. })
  13. if err != nil {
  14. t.Fatal(err)
  15. }
  16. if _, err := tbl.CreateIndex("pk", page.IndexTypePrimary, []byte{0}); err != nil {
  17. t.Fatal(err)
  18. }
  19. // 复合索引 (amt, yr): keyLen = 18+2 = 20, 非 8 对齐
  20. if _, err := tbl.CreateIndex("idx_ay", page.IndexTypeCompose, []byte{1, 2}); err != nil {
  21. t.Fatal(err)
  22. }
  23. // 造数据: amt 在尾部字节不同 (1.01 vs 1.02 在 18B 编码的尾部有差异)
  24. type row struct {
  25. id uint64
  26. amt string
  27. yr uint16
  28. }
  29. rows := []row{}
  30. for i := 1; i <= 300; i++ {
  31. r := row{id: uint64(i), amt: "1.01", yr: uint16(2000 + i%50)}
  32. if i%2 == 0 {
  33. r.amt = "2.50"
  34. }
  35. if i%3 == 0 {
  36. r.amt = "12345.67"
  37. }
  38. rows = append(rows, r)
  39. }
  40. for _, r := range rows {
  41. amt, err := types.ParseDecimal(r.amt)
  42. if err != nil {
  43. t.Fatal(err)
  44. }
  45. if _, err := tbl.InsertRowWithID(r.id, []types.FieldValue{
  46. {FieldName: []byte("id"), Value: r.id},
  47. {FieldName: []byte("amt"), Value: amt},
  48. {FieldName: []byte("yr"), Value: r.yr},
  49. }); err != nil {
  50. t.Fatal(err)
  51. }
  52. }
  53. if err := db.Commit(); err != nil {
  54. t.Fatal(err)
  55. }
  56. // 等值查 amt=2.50: 与全表过滤比对
  57. amt250, _ := types.ParseDecimal("2.50")
  58. want := 0
  59. for _, r := range rows {
  60. if r.amt == "2.50" {
  61. want++
  62. }
  63. }
  64. n, err := tbl.Query().Where(Eq("amt", amt250, 0)).Count()
  65. if err != nil || n != int64(want) {
  66. t.Fatalf("等值 amt=2.50: 索引 count=%d err=%v, 全表过滤 %d", n, err, want)
  67. }
  68. // 复合等值 amt=2.50 AND yr=2002
  69. want2 := 0
  70. for _, r := range rows {
  71. if r.amt == "2.50" && r.yr == 2002 {
  72. want2++
  73. }
  74. }
  75. yrVal := uint16(2002)
  76. n, err = tbl.Query().Where(And(Eq("amt", amt250, 0), Eq("yr", yrVal, 0))).Count()
  77. if err != nil || n != int64(want2) {
  78. t.Fatalf("复合等值 amt+yr: 索引 count=%d err=%v, 全表过滤 %d", n, err, want2)
  79. }
  80. // 范围查 amt ∈ [2.00, 3.00]
  81. lo, _ := types.ParseDecimal("2.00")
  82. hi, _ := types.ParseDecimal("3.00")
  83. want3 := 0
  84. for _, r := range rows {
  85. if r.amt == "2.50" {
  86. want3++
  87. }
  88. }
  89. n, err = tbl.Query().Where(And(Ge("amt", lo, 0), Le("amt", hi, 0))).Count()
  90. if err != nil || n != int64(want3) {
  91. t.Fatalf("范围 amt∈[2,3]: 索引 count=%d err=%v, 全表过滤 %d", n, err, want3)
  92. }
  93. t.Logf("非 8 字节分量复合索引端到端正确: 等值/复合等值/范围全部与全表过滤一致")
  94. }