| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- package index
- import (
- "TsDB2/DB/core/page"
- )
- // ======================== 页 I/O 回调 ========================
- // GlobalBack 页 I/O 回调 (传递给索引规则,由外部实现)
- type GlobalBack struct {
- SavePage func(pagID uint32, data []byte) error
- GetNewPage func(pagID uint32) uint32
- GetDataPage func(pagID uint32, data *[]byte) bool
- PoolGet func(size uint32) []byte
- PoolPut func([]byte)
- Handle page.HandleDb
- }
- // IEntry 索引条目操作接口(操作索引页内的条目字节切片)
- type IEntry interface {
- Compare(a, b []byte) int // 比较判断
- Serialize(e IEntry) []byte // 序列化
- Deserialize(buf []byte) IEntry // 反序列化
- EntryLength() uint16 // 固定条目长度
- Insert(Entries *[]byte, data []byte) error // 插入索引条目
- Search(Entries []byte, key []byte) (uint32, bool) // 查找索引条目
- DataEntry() IDateEntry // 获取数据页操作器
- }
- // IDateEntry 数据页实际操作接口(增删改查真实行数据)
- //
- // 二级索引(Str/Compose):
- // - Insert: 在 IndexPage 条目中写入 [key + PK_ID(8B)]
- // - Search: 二分查找返回 PK_ID 的 8 字节编码(作为 rowData 返回)
- // - Delete: 标记删除条目
- //
- // 主键索引(B+ 树)/ 时序索引:
- // - Insert: 在 DataPage 中写入行数据
- // - Search: 找到 DataPage 返回行数据
- // - Delete: 软删除行数据
- type IDateEntry interface {
- // Insert 插入数据
- // count: 当前页中已有的条目数量(由调用方从 IndexHead.Count 读取)
- // pkID: 主键ID(二级索引存入条目,B+树/时序忽略)
- // rowData: 序列化的行数据(B+树/时序写入 DataPage,二级索引忽略)
- Insert(handle page.HandleDb, indexEntries []byte, entryLen int, count int, key []byte, pkID uint64, rowData []byte) error
- // Search 查找数据
- // 返回值: rowData 对于二级索引是 8 字节 PK_ID 编码,对于 B+树/时序是实际行数据
- Search(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) ([]byte, bool)
- // Update 更新行数据(仅时序索引使用)
- Update(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte, pkID uint64, rowData []byte) error
- // Delete 删除数据
- Delete(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) error
- // CreateDataPage 创建一个新的数据页并写入第一行数据(仅时序索引需要)
- CreateDataPage(handle page.HandleDb, key []byte, rowData []byte) (uint32, error)
- }
- // IndexHandler 高层索引操作接口
- // 每种索引类型实现此接口,封装所有存储细节(B+树路由、扁平链遍历等)
- // Table 层只需遍历 indexMeta.metas 并调用 handler 方法,无需关心索引内部实现
- type IndexHandler interface {
- // Insert 向索引插入数据
- // entryPage: 当前根页ID指针(B+树分裂时可能修改)
- // indexKey: 从行数据提取的索引键; pkID: 自增主键; rowData: 序列化行数据
- // keyLen: 索引键字节长度
- // 返回新的根页ID
- Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error)
- // Search 搜索索引
- // 主键索引: 返回行数据(带pkID前缀), 调用方负责剥离
- // 二级索引: 返回 8字节 BigEndian pkID
- Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]byte, bool)
- // Delete 从索引删除条目
- Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, keyLen int) error
- // Update 更新索引中的行数据
- // oldKey: 旧索引键(定位条目); rowData: 新行数据; pkID: 主键ID
- Update(handle page.HandleDb, entryPage *uint32, oldKey []byte, rowData []byte, pkID uint64, keyLen int) error
- // GetDataPageIDs 返回所有数据页ID (按叶节点顺序, 用于全表扫描)
- GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32
- // ReadDataPageRows 读取数据页中所有未删除的行 (带 pkID(8B LE) 前缀)
- ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte
- // RangeScan 范围扫描
- // startKey/endKey: 范围边界 (nil 表示无下界/上界)
- // startInclusive/endInclusive: 是否包含边界
- // reverse: true 时从右向左反向遍历
- // callback: 每行回调, 返回 false 停止
- // 主键/时序索引: row = [pkID(8B BE) + rowData]
- // 二级索引: row = 8B BigEndian pkID
- RangeScan(handle page.HandleDb, entryPage uint32,
- startKey, endKey []byte,
- startInclusive, endInclusive bool,
- reverse bool,
- callback func(row []byte) bool) error
- }
- type ComposeType struct {
- IndexEntry map[page.IndexType]IEntry
- IndexHandlers map[page.IndexType]IndexHandler
- }
- func (com *ComposeType) register(indexType page.IndexType, entry IEntry) {
- com.IndexEntry[indexType] = entry
- }
- func (com *ComposeType) RegisterHandler(indexType page.IndexType, handler IndexHandler) {
- com.IndexHandlers[indexType] = handler
- }
- func (com *ComposeType) GetEntryHandler(t page.IndexType) (IEntry, bool) {
- if entry, ok := com.IndexEntry[t]; ok {
- return entry, true
- }
- return nil, false
- }
- func (com *ComposeType) GetHandler(t page.IndexType) (IndexHandler, bool) {
- if h, ok := com.IndexHandlers[t]; ok {
- return h, true
- }
- return nil, false
- }
- var Compose = ComposeType{
- IndexEntry: make(map[page.IndexType]IEntry),
- IndexHandlers: make(map[page.IndexType]IndexHandler),
- }
- func init() {
- Compose.register(page.IndexTypeTime, &IndexTimeEntry{})
- Compose.register(page.IndexTypeCompose, &ComposeEntry{})
- // 向后兼容:旧数据库中 IndexTypeStr=3 的索引条目用 ComposeEntry 处理
- Compose.register(page.IndexTypeStr, &ComposeEntry{})
- }
|