composepage.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package composepage
  2. import (
  3. "TsDB2/DB/core/page"
  4. "encoding/binary"
  5. "errors"
  6. "unsafe"
  7. )
  8. // ComposeEntryPage 复合索引操作器
  9. // 不再管理独立的 DataPage,直接在 IndexPage 条目中存储 [composeKey(N*8B) + PK_ID(8B)]
  10. // Search 返回 PK_ID 的 8 字节编码,Table 层再通过 B+ 树解析实际行数据
  11. type ComposeEntryPage struct{}
  12. const pkIDLen = 8
  13. // countBackOffset Count 字段距离 entries 起始位置的偏移
  14. var countBackOffset = int(unsafe.Sizeof(page.PageHdr{})) + 14 - (int(unsafe.Sizeof(page.PageHdr{})) + 6)
  15. // ======================== IDateEntry 接口实现 ========================
  16. // Insert 在 IndexPage 条目中插入 [composeKey + PK_ID(8B)]
  17. func (c *ComposeEntryPage) Insert(handle page.HandleDb, indexEntries []byte, entryLen int, count int, key []byte, pkID uint64, rowData []byte) error {
  18. keyPartLen := entryLen - pkIDLen
  19. n := count
  20. // 二分查找插入位置(按复合 key 排序)
  21. pos := n
  22. left, right := 0, n-1
  23. for left <= right {
  24. mid := (left + right) / 2
  25. entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen]
  26. if compareComposeKey(entryKey, key[:keyPartLen]) >= 0 {
  27. pos = mid
  28. right = mid - 1
  29. } else {
  30. left = mid + 1
  31. }
  32. }
  33. // 移动后续条目腾出空间
  34. if pos < n {
  35. copy(indexEntries[(pos+1)*entryLen:], indexEntries[pos*entryLen:n*entryLen])
  36. }
  37. // 写入新条目 [composeKey + PK_ID(8B)]
  38. entry := indexEntries[pos*entryLen : (pos+1)*entryLen]
  39. copy(entry[:keyPartLen], key[:keyPartLen])
  40. binary.BigEndian.PutUint64(entry[keyPartLen:], pkID)
  41. return nil
  42. }
  43. // Search 二分查找复合 key,返回 PK_ID 的 8 字节编码
  44. func (c *ComposeEntryPage) Search(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) ([]byte, bool) {
  45. keyPartLen := entryLen - pkIDLen
  46. n := len(indexEntries) / entryLen
  47. if n == 0 {
  48. return nil, false
  49. }
  50. left, right := 0, n-1
  51. for left <= right {
  52. mid := (left + right) / 2
  53. entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen]
  54. cmp := compareComposeKey(entryKey, key[:keyPartLen])
  55. if cmp == 0 {
  56. pkIDBytes := indexEntries[mid*entryLen+keyPartLen : mid*entryLen+keyPartLen+pkIDLen]
  57. result := make([]byte, pkIDLen)
  58. copy(result, pkIDBytes)
  59. return result, true
  60. } else if cmp < 0 {
  61. left = mid + 1
  62. } else {
  63. right = mid - 1
  64. }
  65. }
  66. return nil, false
  67. }
  68. // Delete 从 IndexPage 中删除条目
  69. func (c *ComposeEntryPage) Delete(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) error {
  70. keyPartLen := entryLen - pkIDLen
  71. n := len(indexEntries) / entryLen
  72. pos := -1
  73. left, right := 0, n-1
  74. for left <= right {
  75. mid := (left + right) / 2
  76. entryKey := indexEntries[mid*entryLen : mid*entryLen+keyPartLen]
  77. cmp := compareComposeKey(entryKey, key[:keyPartLen])
  78. if cmp == 0 {
  79. pos = mid
  80. break
  81. } else if cmp < 0 {
  82. left = mid + 1
  83. } else {
  84. right = mid - 1
  85. }
  86. }
  87. if pos < 0 {
  88. return errors.New("row not found")
  89. }
  90. // 前移后续条目
  91. if pos < n-1 {
  92. copy(indexEntries[pos*entryLen:], indexEntries[(pos+1)*entryLen:n*entryLen])
  93. }
  94. zeroes := make([]byte, entryLen)
  95. copy(indexEntries[(n-1)*entryLen:n*entryLen], zeroes)
  96. // 更新 Count
  97. countPtr := (*uint32)(unsafe.Add(unsafe.Pointer(&indexEntries[0]), -countBackOffset))
  98. *countPtr--
  99. return nil
  100. }
  101. // Update 复合索引不支持直接更新
  102. func (c *ComposeEntryPage) Update(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte, pkID uint64, rowData []byte) error {
  103. return errors.New("compose index does not support update")
  104. }
  105. // CreateDataPage 复合索引不需要创建数据页
  106. func (c *ComposeEntryPage) CreateDataPage(handle page.HandleDb, key []byte, pkID uint64, rowData []byte) (uint32, error) {
  107. return 0, errors.New("compose index does not create data pages")
  108. }
  109. // ======================== 工具函数 ========================
  110. // compareComposeKey 比较两个复合 key(每个字段 8 字节 BigEndian)
  111. func compareComposeKey(a, b []byte) int {
  112. keyCount := len(a) / 8
  113. for i := 0; i < keyCount; i++ {
  114. va := binary.BigEndian.Uint64(a[i*8:])
  115. vb := binary.BigEndian.Uint64(b[i*8:])
  116. if va < vb {
  117. return -1
  118. }
  119. if va > vb {
  120. return 1
  121. }
  122. }
  123. return 0
  124. }