| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package index
- import (
- "TsDB2/DB/index/btree"
- "TsDB2/DB/page"
- "encoding/binary"
- )
- func init() {
- Compose.RegisterHandler(page.IndexTypeStr, &StrBTreeHandler{})
- }
- // StrBTreeHandler — 字符串二级索引 (IndexTypeStr)
- // 叶子条目: [key(keyLen) + PKID(8B BE)]
- // 使用 B+ 树结构替代扁平链表,支持 O(log n) 插入/查询
- type StrBTreeHandler struct{}
- func (h *StrBTreeHandler) Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error) {
- // 保护:截断 indexKey 防止越界
- if len(indexKey) > keyLen {
- indexKey = indexKey[:keyLen]
- }
- entry := make([]byte, keyLen+8)
- copy(entry[:keyLen], indexKey)
- binary.BigEndian.PutUint64(entry[keyLen:], pkID)
- rootPID := *entryPage
- newRoot, err := btree.StrBTInsert(rootPID, entry, handle)
- if err != nil {
- return 0, err
- }
- *entryPage = newRoot
- return newRoot, nil
- }
- func (h *StrBTreeHandler) Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]byte, bool) {
- rootPID := entryPage
- if rootPID == 0 {
- return nil, false
- }
- pkID, found := btree.StrBTSearch(rootPID, indexKey[:keyLen], handle)
- if !found {
- return nil, false
- }
- pkBuf := make([]byte, 8)
- binary.BigEndian.PutUint64(pkBuf, pkID)
- return pkBuf, true
- }
- func (h *StrBTreeHandler) Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, keyLen int) error {
- // 二级索引删除:需要同时匹配 key + pkID
- rootPID := *entryPage
- if rootPID == 0 {
- return page.ErrNotFound
- }
- // 先搜索获取 pkID(假设是精确匹配场景)
- pkIDBuf, found := h.Search(handle, rootPID, indexKey, keyLen)
- if !found {
- return page.ErrNotFound
- }
- pkID := binary.BigEndian.Uint64(pkIDBuf)
- // 调用底层删除(同时匹配 key + pkID),使用正确的 keyLen
- actualKeyLen := len(indexKey)
- if actualKeyLen > keyLen {
- actualKeyLen = keyLen
- }
- newRoot, err := btree.StrBTDeleteWithPKID(rootPID, indexKey[:actualKeyLen], pkID, handle)
- if err != nil {
- return err
- }
- *entryPage = newRoot
- return nil
- }
- func (h *StrBTreeHandler) Update(handle page.HandleDb, entryPage *uint32, oldKey []byte, rowData []byte, pkID uint64, keyLen int) error {
- // 二级索引 Update: 先删旧条目, 再插新条目
- // 注意:这里 oldKey 是旧索引键,但接口限制无法传入 newKey
- // IndexMetaPage.UpdateByKey 应该传入正确的 newKey 作为 oldKey 参数
- if err := h.Delete(handle, entryPage, oldKey, keyLen); err != nil {
- return err
- }
- // 保护:截断防止越界
- actualKeyLen := len(oldKey)
- if actualKeyLen > keyLen {
- actualKeyLen = keyLen
- }
- _, err := h.Insert(handle, entryPage, oldKey[:actualKeyLen], pkID, rowData, keyLen)
- return err
- }
- // SearchAll 查找相同 key 下的所有 pkID
- func (h *StrBTreeHandler) SearchAll(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]uint64, bool) {
- rootPID := entryPage
- if rootPID == 0 {
- return nil, false
- }
- return btree.StrBTSearchAll(rootPID, indexKey[:keyLen], handle)
- }
- func (h *StrBTreeHandler) GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32 {
- // 二级索引没有 DataPage, 返回空
- return nil
- }
- func (h *StrBTreeHandler) ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte {
- // 二级索引没有 DataPage
- return nil
- }
- func (h *StrBTreeHandler) RangeScan(handle page.HandleDb, entryPage uint32,
- startKey, endKey []byte, startInclusive, endInclusive bool, reverse bool,
- callback func(row []byte) bool) error {
- return btree.StrBTRangeScan(entryPage, handle, startKey, endKey, startInclusive, endInclusive, reverse, callback)
- }
|