package composepage import ( "TsDB2/DB/core/page" "encoding/binary" "errors" "unsafe" ) // ComposeEntryPage 复合索引操作器 // 不再管理独立的 DataPage,直接在 IndexPage 条目中存储 [composeKey(N*8B) + PK_ID(8B)] // Search 返回 PK_ID 的 8 字节编码,Table 层再通过 B+ 树解析实际行数据 type ComposeEntryPage struct{} const pkIDLen = 8 // countBackOffset Count 字段距离 entries 起始位置的偏移 var countBackOffset = int(unsafe.Sizeof(page.PageHdr{})) + 14 - (int(unsafe.Sizeof(page.PageHdr{})) + 6) // ======================== IDateEntry 接口实现 ======================== // Insert 在 IndexPage 条目中插入 [composeKey + PK_ID(8B)] func (c *ComposeEntryPage) Insert(handle page.HandleDb, indexEntries []byte, entryLen int, count int, key []byte, pkID uint64, rowData []byte) error { keyPartLen := entryLen - pkIDLen n := count // 二分查找插入位置(按复合 key 排序) pos := n left, right := 0, n-1 for left <= right { mid := (left + right) / 2 entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen] if compareComposeKey(entryKey, key[:keyPartLen]) >= 0 { pos = mid right = mid - 1 } else { left = mid + 1 } } // 移动后续条目腾出空间 if pos < n { copy(indexEntries[(pos+1)*entryLen:], indexEntries[pos*entryLen:n*entryLen]) } // 写入新条目 [composeKey + PK_ID(8B)] entry := indexEntries[pos*entryLen : (pos+1)*entryLen] copy(entry[:keyPartLen], key[:keyPartLen]) binary.BigEndian.PutUint64(entry[keyPartLen:], pkID) return nil } // Search 二分查找复合 key,返回 PK_ID 的 8 字节编码 func (c *ComposeEntryPage) Search(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) ([]byte, bool) { keyPartLen := entryLen - pkIDLen n := len(indexEntries) / entryLen if n == 0 { return nil, false } left, right := 0, n-1 for left <= right { mid := (left + right) / 2 entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen] cmp := compareComposeKey(entryKey, key[:keyPartLen]) if cmp == 0 { pkIDBytes := indexEntries[mid*entryLen+keyPartLen : mid*entryLen+keyPartLen+pkIDLen] result := make([]byte, pkIDLen) copy(result, pkIDBytes) return result, true } else if cmp < 0 { left = mid + 1 } else { right = mid - 1 } } return nil, false } // Delete 从 IndexPage 中删除条目 func (c *ComposeEntryPage) Delete(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) error { keyPartLen := entryLen - pkIDLen n := len(indexEntries) / entryLen pos := -1 left, right := 0, n-1 for left <= right { mid := (left + right) / 2 entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen] cmp := compareComposeKey(entryKey, key[:keyPartLen]) if cmp == 0 { pos = mid break } else if cmp < 0 { left = mid + 1 } else { right = mid - 1 } } if pos < 0 { return errors.New("row not found") } // 前移后续条目 if pos < n-1 { copy(indexEntries[pos*entryLen:], indexEntries[(pos+1)*entryLen:n*entryLen]) } zeroes := make([]byte, entryLen) copy(indexEntries[(n-1)*entryLen:n*entryLen], zeroes) // 更新 Count countAddr := uintptr(unsafe.Pointer(&indexEntries[0])) - uintptr(countBackOffset) countPtr := (*uint32)(unsafe.Pointer(countAddr)) *countPtr-- return nil } // Update 复合索引不支持直接更新 func (c *ComposeEntryPage) Update(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte, pkID uint64, rowData []byte) error { return errors.New("compose index does not support update") } // CreateDataPage 复合索引不需要创建数据页 func (c *ComposeEntryPage) CreateDataPage(handle page.HandleDb, key []byte, rowData []byte) (uint32, error) { return 0, errors.New("compose index does not create data pages") } // ======================== 工具函数 ======================== // compareComposeKey 比较两个复合 key(每个字段 8 字节 BigEndian) func compareComposeKey(a, b []byte) int { keyCount := len(a) / 8 for i := 0; i < keyCount; i++ { va := binary.BigEndian.Uint64(a[i*8:]) vb := binary.BigEndian.Uint64(b[i*8:]) if va < vb { return -1 } if va > vb { return 1 } } return 0 }