str_handler.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package index
  2. import (
  3. "TsDB2/DB/index/btree"
  4. "TsDB2/DB/page"
  5. "encoding/binary"
  6. )
  7. func init() {
  8. Compose.RegisterHandler(page.IndexTypeStr, &StrBTreeHandler{})
  9. }
  10. // StrBTreeHandler — 字符串二级索引 (IndexTypeStr)
  11. // 叶子条目: [key(keyLen) + PKID(8B BE)]
  12. // 使用 B+ 树结构替代扁平链表,支持 O(log n) 插入/查询
  13. type StrBTreeHandler struct{}
  14. func (h *StrBTreeHandler) Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error) {
  15. // 保护:截断 indexKey 防止越界
  16. if len(indexKey) > keyLen {
  17. indexKey = indexKey[:keyLen]
  18. }
  19. entry := make([]byte, keyLen+8)
  20. copy(entry[:keyLen], indexKey)
  21. binary.BigEndian.PutUint64(entry[keyLen:], pkID)
  22. rootPID := *entryPage
  23. newRoot, err := btree.StrBTInsert(rootPID, entry, handle)
  24. if err != nil {
  25. return 0, err
  26. }
  27. *entryPage = newRoot
  28. return newRoot, nil
  29. }
  30. func (h *StrBTreeHandler) Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]byte, bool) {
  31. rootPID := entryPage
  32. if rootPID == 0 {
  33. return nil, false
  34. }
  35. pkID, found := btree.StrBTSearch(rootPID, indexKey[:keyLen], handle)
  36. if !found {
  37. return nil, false
  38. }
  39. pkBuf := make([]byte, 8)
  40. binary.BigEndian.PutUint64(pkBuf, pkID)
  41. return pkBuf, true
  42. }
  43. func (h *StrBTreeHandler) Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, keyLen int) error {
  44. // 二级索引删除:需要同时匹配 key + pkID
  45. rootPID := *entryPage
  46. if rootPID == 0 {
  47. return page.ErrNotFound
  48. }
  49. // 先搜索获取 pkID(假设是精确匹配场景)
  50. pkIDBuf, found := h.Search(handle, rootPID, indexKey, keyLen)
  51. if !found {
  52. return page.ErrNotFound
  53. }
  54. pkID := binary.BigEndian.Uint64(pkIDBuf)
  55. // 调用底层删除(同时匹配 key + pkID),使用正确的 keyLen
  56. actualKeyLen := len(indexKey)
  57. if actualKeyLen > keyLen {
  58. actualKeyLen = keyLen
  59. }
  60. newRoot, err := btree.StrBTDeleteWithPKID(rootPID, indexKey[:actualKeyLen], pkID, handle)
  61. if err != nil {
  62. return err
  63. }
  64. *entryPage = newRoot
  65. return nil
  66. }
  67. func (h *StrBTreeHandler) Update(handle page.HandleDb, entryPage *uint32, oldKey []byte, rowData []byte, pkID uint64, keyLen int) error {
  68. // 二级索引 Update: 先删旧条目, 再插新条目
  69. // 注意:这里 oldKey 是旧索引键,但接口限制无法传入 newKey
  70. // IndexMetaPage.UpdateByKey 应该传入正确的 newKey 作为 oldKey 参数
  71. if err := h.Delete(handle, entryPage, oldKey, keyLen); err != nil {
  72. return err
  73. }
  74. // 保护:截断防止越界
  75. actualKeyLen := len(oldKey)
  76. if actualKeyLen > keyLen {
  77. actualKeyLen = keyLen
  78. }
  79. _, err := h.Insert(handle, entryPage, oldKey[:actualKeyLen], pkID, rowData, keyLen)
  80. return err
  81. }
  82. // SearchAll 查找相同 key 下的所有 pkID
  83. func (h *StrBTreeHandler) SearchAll(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]uint64, bool) {
  84. rootPID := entryPage
  85. if rootPID == 0 {
  86. return nil, false
  87. }
  88. return btree.StrBTSearchAll(rootPID, indexKey[:keyLen], handle)
  89. }
  90. func (h *StrBTreeHandler) GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32 {
  91. // 二级索引没有 DataPage, 返回空
  92. return nil
  93. }
  94. func (h *StrBTreeHandler) ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte {
  95. // 二级索引没有 DataPage
  96. return nil
  97. }
  98. func (h *StrBTreeHandler) RangeScan(handle page.HandleDb, entryPage uint32,
  99. startKey, endKey []byte, startInclusive, endInclusive bool, reverse bool,
  100. callback func(row []byte) bool) error {
  101. return btree.StrBTRangeScan(entryPage, handle, startKey, endKey, startInclusive, endInclusive, reverse, callback)
  102. }