ientry.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package index
  2. import (
  3. "TsDB2/DB/core/page"
  4. )
  5. // ======================== 页 I/O 回调 ========================
  6. // GlobalBack 页 I/O 回调 (传递给索引规则,由外部实现)
  7. type GlobalBack struct {
  8. SavePage func(pagID uint32, data []byte) error
  9. GetNewPage func(pagID uint32) uint32
  10. GetDataPage func(pagID uint32, data *[]byte) bool
  11. PoolGet func(size uint32) []byte
  12. PoolPut func([]byte)
  13. Handle page.HandleDb
  14. }
  15. // IEntry 索引条目操作接口(操作索引页内的条目字节切片)
  16. type IEntry interface {
  17. Compare(a, b []byte) int // 比较判断
  18. Serialize(e IEntry) []byte // 序列化
  19. Deserialize(buf []byte) IEntry // 反序列化
  20. EntryLength() uint16 // 固定条目长度
  21. Insert(Entries *[]byte, data []byte) error // 插入索引条目
  22. Search(Entries []byte, key []byte) (uint32, bool) // 查找索引条目
  23. DataEntry() IDateEntry // 获取数据页操作器
  24. }
  25. // IDateEntry 数据页实际操作接口(增删改查真实行数据)
  26. //
  27. // 二级索引(Str/Compose):
  28. // - Insert: 在 IndexPage 条目中写入 [key + PK_ID(8B)]
  29. // - Search: 二分查找返回 PK_ID 的 8 字节编码(作为 rowData 返回)
  30. // - Delete: 标记删除条目
  31. //
  32. // 主键索引(B+ 树)/ 时序索引:
  33. // - Insert: 在 DataPage 中写入行数据
  34. // - Search: 找到 DataPage 返回行数据
  35. // - Delete: 软删除行数据
  36. type IDateEntry interface {
  37. // Insert 插入数据
  38. // count: 当前页中已有的条目数量(由调用方从 IndexHead.Count 读取)
  39. // pkID: 主键ID(二级索引存入条目,B+树/时序忽略)
  40. // rowData: 序列化的行数据(B+树/时序写入 DataPage,二级索引忽略)
  41. Insert(handle page.HandleDb, indexEntries []byte, entryLen int, count int, key []byte, pkID uint64, rowData []byte) error
  42. // Search 查找数据
  43. // 返回值: rowData 对于二级索引是 8 字节 PK_ID 编码,对于 B+树/时序是实际行数据
  44. Search(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) ([]byte, bool)
  45. // Update 更新行数据(仅时序索引使用)
  46. Update(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte, pkID uint64, rowData []byte) error
  47. // Delete 删除数据
  48. Delete(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) error
  49. // CreateDataPage 创建一个新的数据页并写入第一行数据(仅时序索引需要)
  50. CreateDataPage(handle page.HandleDb, key []byte, rowData []byte) (uint32, error)
  51. }
  52. // IndexHandler 高层索引操作接口
  53. // 每种索引类型实现此接口,封装所有存储细节(B+树路由、扁平链遍历等)
  54. // Table 层只需遍历 indexMeta.metas 并调用 handler 方法,无需关心索引内部实现
  55. type IndexHandler interface {
  56. // Insert 向索引插入数据
  57. // entryPage: 当前根页ID指针(B+树分裂时可能修改)
  58. // indexKey: 从行数据提取的索引键; pkID: 自增主键; rowData: 序列化行数据
  59. // keyLen: 索引键字节长度
  60. // 返回新的根页ID
  61. Insert(handle page.HandleDb, entryPage *uint32, indexKey []byte, pkID uint64, rowData []byte, keyLen int) (uint32, error)
  62. // Search 搜索索引
  63. // 主键索引: 返回行数据(带pkID前缀), 调用方负责剥离
  64. // 二级索引: 返回 8字节 BigEndian pkID
  65. Search(handle page.HandleDb, entryPage uint32, indexKey []byte, keyLen int) ([]byte, bool)
  66. // Delete 从索引删除条目
  67. Delete(handle page.HandleDb, entryPage *uint32, indexKey []byte, keyLen int) error
  68. // Update 更新索引中的行数据
  69. // oldKey: 旧索引键(定位条目); rowData: 新行数据; pkID: 主键ID
  70. Update(handle page.HandleDb, entryPage *uint32, oldKey []byte, rowData []byte, pkID uint64, keyLen int) error
  71. // GetDataPageIDs 返回所有数据页ID (按叶节点顺序, 用于全表扫描)
  72. GetDataPageIDs(handle page.HandleDb, entryPage uint32) []uint32
  73. // ReadDataPageRows 读取数据页中所有未删除的行 (带 pkID(8B LE) 前缀)
  74. ReadDataPageRows(handle page.HandleDb, dpID uint32) [][]byte
  75. // RangeScan 范围扫描
  76. // startKey/endKey: 范围边界 (nil 表示无下界/上界)
  77. // startInclusive/endInclusive: 是否包含边界
  78. // reverse: true 时从右向左反向遍历
  79. // callback: 每行回调, 返回 false 停止
  80. // 主键/时序索引: row = [pkID(8B BE) + rowData]
  81. // 二级索引: row = 8B BigEndian pkID
  82. RangeScan(handle page.HandleDb, entryPage uint32,
  83. startKey, endKey []byte,
  84. startInclusive, endInclusive bool,
  85. reverse bool,
  86. callback func(row []byte) bool) error
  87. }
  88. type ComposeType struct {
  89. IndexEntry map[page.IndexType]IEntry
  90. IndexHandlers map[page.IndexType]IndexHandler
  91. }
  92. func (com *ComposeType) register(indexType page.IndexType, entry IEntry) {
  93. com.IndexEntry[indexType] = entry
  94. }
  95. func (com *ComposeType) RegisterHandler(indexType page.IndexType, handler IndexHandler) {
  96. com.IndexHandlers[indexType] = handler
  97. }
  98. func (com *ComposeType) GetEntryHandler(t page.IndexType) (IEntry, bool) {
  99. if entry, ok := com.IndexEntry[t]; ok {
  100. return entry, true
  101. }
  102. return nil, false
  103. }
  104. func (com *ComposeType) GetHandler(t page.IndexType) (IndexHandler, bool) {
  105. if h, ok := com.IndexHandlers[t]; ok {
  106. return h, true
  107. }
  108. return nil, false
  109. }
  110. var Compose = ComposeType{
  111. IndexEntry: make(map[page.IndexType]IEntry),
  112. IndexHandlers: make(map[page.IndexType]IndexHandler),
  113. }
  114. func init() {
  115. Compose.register(page.IndexTypeTime, &IndexTimeEntry{})
  116. Compose.register(page.IndexTypeCompose, &ComposeEntry{})
  117. // 向后兼容:旧数据库中 IndexTypeStr=3 的索引条目用 ComposeEntry 处理
  118. Compose.register(page.IndexTypeStr, &ComposeEntry{})
  119. }