| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- package index
- import (
- "TsDB2/DB/core/index/btree"
- "TsDB2/DB/core/index/datapage"
- "TsDB2/DB/core/page"
- "encoding/binary"
- )
- // PrimaryHandler — 主键 B+ 树索引 (IndexTypePrimary)
- // 存储: storeRow = [pkID(8B LE) + rowData]
- type PrimaryHandler struct{}
- func init() {
- Compose.RegisterHandler(page.IndexTypePrimary, &PrimaryHandler{})
- }
- func (h *PrimaryHandler) Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error) {
- pkBuf := make([]byte, 8)
- binary.BigEndian.PutUint64(pkBuf, pkID)
- storeRowData := append(pkBuf, rowData...)
- // 主键 B+ 树始终以 pkID(8B BE) 为 key, 与 Search/Delete/Update 保持一致
- return h.insertPrebuilt(handle, entryPage, pkBuf, storeRowData)
- }
- // InsertPrebuilt 插入已构建好的 storeRowData (避免重复分配)
- // storeRowData = [pkID(8B BE) + rowData]
- func (h *PrimaryHandler) InsertPrebuilt(handle page.HandleDb, entryPage *uint32, indexKey []byte, storeRowData []byte) (uint32, error) {
- return h.insertPrebuilt(handle, entryPage, indexKey, storeRowData)
- }
- // BuildStoreRow 用复用缓冲区构建 storeRowData = [pkID(8B BE) + rowData]
- // 返回的切片与 buf 共享底层数组, 调用方需立即使用
- func (h *PrimaryHandler) BuildStoreRow(buf []byte, pkID uint64, rowData []byte) []byte {
- binary.BigEndian.PutUint64(buf[:8], pkID)
- copy(buf[8:], rowData)
- return buf[:8+len(rowData)]
- }
- func (h *PrimaryHandler) insertPrebuilt(handle page.HandleDb, entryPage *uint32, indexKey []byte, storeRowData []byte) (uint32, error) {
- rootPID := *entryPage
- rowSize := uint32(len(storeRowData)) + 4 // 4B len prefix + row data
- // 尝试复用 DataPage: 只在路由目标叶子内查找
- if rootPID != 0 {
- if dpID, found := btree.FindLastLeafDP(handle, rootPID, rowSize, indexKey); found {
- dp, err := datapage.Load(handle, dpID)
- if err == nil {
- dp.AppendRow(storeRowData)
- dp.Save()
- newRoot, _, dup, err := btree.BTreePKInsert(rootPID, indexKey, dpID, handle)
- if err != nil {
- return 0, err
- }
- if !dup {
- *entryPage = newRoot
- }
- return newRoot, nil
- }
- }
- }
- // 无可用空间或树为空: 创建新 DataPage
- dp := datapage.New(handle)
- dp.AppendRow(storeRowData)
- dp.Save()
- newRoot, _, _, err := btree.BTreePKInsert(rootPID, indexKey, dp.PageID(), handle)
- if err != nil {
- return 0, err
- }
- *entryPage = newRoot
- return newRoot, nil
- }
- func (h *PrimaryHandler) Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]byte, bool) {
- rootPID := entryPage
- if rootPID == 0 {
- return nil, false
- }
- dpID, found := btree.BTreePKSearch(rootPID, indexKey, handle)
- if !found {
- return nil, false
- }
- dp, err := datapage.Load(handle, dpID)
- if err != nil {
- return nil, false
- }
- return dp.FindRowByIndexKey(indexKey, 9) // skip pkID(8B) + schemaVer(1B)
- }
- func (h *PrimaryHandler) SearchByPK(handle page.HandleDb, entryPage uint32, pkID uint64) ([]byte, bool) {
- rootPID := entryPage
- if rootPID == 0 {
- return nil, false
- }
- pkKeyBE := make([]byte, 8)
- binary.BigEndian.PutUint64(pkKeyBE, pkID)
- dpID, found := btree.BTreePKSearch(rootPID, pkKeyBE, handle)
- if found {
- dp, err := datapage.Load(handle, dpID)
- if err == nil {
- if rowData, ok := dp.FindRowByPK(pkKeyBE); ok {
- return rowData, true
- }
- }
- }
- // 路由失败或未找到, 扫描所有叶子
- return btree.ScanAllLeavesForPK(rootPID, handle, pkKeyBE)
- }
- func (h *PrimaryHandler) Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, keyLen int) error {
- rootPID := *entryPage
- if rootPID == 0 {
- return page.ErrNotFound
- }
- dpID, found := btree.BTreePKSearch(rootPID, indexKey, handle)
- if found {
- dp, err := datapage.Load(handle, dpID)
- if err == nil {
- deleted := false
- if dp.DeleteByIndexKey(indexKey, 8) {
- deleted = true
- } else if dp.DeleteByPK(indexKey) {
- deleted = true
- }
- if deleted {
- if dp.AllDeleted() {
- newRoot, _, err := btree.BTreePKDelete(rootPID, indexKey, handle)
- if err != nil {
- return err
- }
- if newRoot != rootPID {
- *entryPage = newRoot
- }
- if handle.FreePage != nil {
- handle.FreePage(dpID)
- }
- } else {
- dp.Save()
- }
- return nil
- }
- }
- }
- // 索引键路由失败, 扫描所有叶子
- return btree.ScanAndDelete(rootPID, handle, indexKey, indexKey)
- }
- func (h *PrimaryHandler) DeleteByPK(handle page.HandleDb, entryPage *uint32, pkID uint64) error {
- rootPID := *entryPage
- if rootPID == 0 {
- return page.ErrNotFound
- }
- pkKeyBE := make([]byte, 8)
- binary.BigEndian.PutUint64(pkKeyBE, pkID)
- dpID, found := btree.BTreePKSearch(rootPID, pkKeyBE, handle)
- if found {
- dp, err := datapage.Load(handle, dpID)
- if err == nil {
- if dp.DeleteByPK(pkKeyBE) {
- if dp.AllDeleted() {
- newRoot, _, err := btree.BTreePKDelete(rootPID, pkKeyBE, handle)
- if err != nil {
- return err
- }
- if newRoot != rootPID {
- *entryPage = newRoot
- }
- if handle.FreePage != nil {
- handle.FreePage(dpID)
- }
- } else {
- dp.Save()
- }
- return nil
- }
- }
- }
- // 路由失败, 扫描所有叶子
- return btree.ScanAndDeleteByPK(rootPID, handle, pkKeyBE)
- }
- func (h *PrimaryHandler) Update(handle page.HandleDb, entryPage *uint32, oldKey []byte, rowData []byte, pkID uint64, keyLen int) error {
- rootPID := *entryPage
- if rootPID == 0 {
- return page.ErrNotFound
- }
- pkBuf := make([]byte, 8)
- binary.BigEndian.PutUint64(pkBuf, pkID)
- storeRowData := append(pkBuf, rowData...)
- pkKeyBE := make([]byte, 8)
- binary.BigEndian.PutUint64(pkKeyBE, pkID)
- // 先用 B+ 树路由定位 DataPage
- dpID, found := btree.BTreePKSearch(rootPID, pkKeyBE, handle)
- if found {
- dp, err := datapage.Load(handle, dpID)
- if err == nil {
- if err := dp.UpdateByPK(pkKeyBE, storeRowData); err == nil {
- return nil
- }
- }
- }
- // 路由失败, 回退扫描
- return btree.ScanAndUpdate(rootPID, handle, pkKeyBE, storeRowData)
- }
- func (h *PrimaryHandler) GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32 {
- return btree.GetDataPageIDs(handle, entryPage)
- }
- func (h *PrimaryHandler) ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte {
- dp, err := datapage.Load(handle, dpID)
- if err != nil {
- return nil
- }
- return dp.GetAllRows()
- }
- func (h *PrimaryHandler) RangeScan(handle page.HandleDb, entryPage uint32,
- startKey, endKey []byte, startInclusive, endInclusive bool, reverse bool,
- callback func(row []byte) bool) error {
- return btree.BTreePKRangeScan(entryPage, handle, startKey, endKey, startInclusive, endInclusive, reverse, callback)
- }
|