primary.go 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. package btree
  2. import (
  3. "TsDB2/DB/core/index/datapage"
  4. "TsDB2/DB/core/page"
  5. "encoding/binary"
  6. "errors"
  7. "fmt"
  8. "unsafe"
  9. )
  10. // btNode B+ 鏍戣妭鐐?(raw bytes + page.IndexHead 鎸囬拡, 鏃?IndexPage 瀵硅薄)
  11. type btNode struct {
  12. buf []byte // 瀹屾暣椤电紦鍐插尯
  13. info *page.IndexHead // 鎸囧悜 buf 澶撮儴鐨?page.IndexHead 鎸囬拡
  14. entries []byte // buf[page.IndexHeadSize:] 鏉$洰鍖哄煙
  15. }
  16. func (n *btNode) isLeaf() bool { return n.info.IsLeaf == 1 }
  17. func (n *btNode) pageID() uint32 { return n.info.Hdr.PageID }
  18. // btPathEntry 璁板綍 B+ 鏍?descent 璺緞
  19. type btPathEntry struct {
  20. nodePID uint32
  21. childIdx int
  22. }
  23. // btSplitThreshold 璁$畻鍒嗚闃堝€?
  24. func btSplitThreshold() int {
  25. ff := page.BTreeFillFactor
  26. if ff < 50 {
  27. ff = 50
  28. }
  29. if ff > 100 {
  30. ff = 100
  31. }
  32. return int(page.IndexPageSize) * ff / 100
  33. }
  34. // ======================== 鑺傜偣 I/O ========================
  35. func btLoad(handle page.HandleDb, pid uint32) *btNode {
  36. if pid == 0 {
  37. return nil
  38. }
  39. buf := make([]byte, page.IndexPageSize)
  40. if err := handle.ReadPage(pid, buf); err != nil {
  41. return nil
  42. }
  43. info := (*page.IndexHead)(unsafe.Pointer(&buf[0]))
  44. return &btNode{buf: buf, info: info, entries: buf[page.IndexHeadSize:]}
  45. }
  46. func btSave(handle page.HandleDb, n *btNode) {
  47. _ = handle.SavePage(n.info.Hdr.PageID, n.buf)
  48. }
  49. func btNew(handle page.HandleDb, isLeaf bool, entryLen int) *btNode {
  50. pid := handle.NewPage()
  51. buf := make([]byte, page.IndexPageSize)
  52. info := (*page.IndexHead)(unsafe.Pointer(&buf[0]))
  53. info.Hdr.Type = page.IndexDataIndex
  54. info.Hdr.PageID = pid
  55. info.Hdr.UseSize = uint32(page.IndexHeadSize)
  56. info.IndexType = page.IndexTypePrimary
  57. info.EntryLen = uint16(entryLen)
  58. info.Count = 0
  59. if isLeaf {
  60. info.IsLeaf = 1
  61. }
  62. return &btNode{buf: buf, info: info, entries: buf[page.IndexHeadSize:]}
  63. }
  64. // ======================== 鏉$洰鎿嶄綔 ========================
  65. func btEntry(n *btNode, i int) []byte {
  66. el := int(n.info.EntryLen)
  67. return n.entries[i*el : (i+1)*el]
  68. }
  69. func btKey(e []byte) []byte { return e[:len(e)-4] }
  70. func btPID(e []byte) uint32 { return binary.BigEndian.Uint32(e[len(e)-4:]) }
  71. func btSetPID(e []byte, p uint32) { binary.BigEndian.PutUint32(e[len(e)-4:], p) }
  72. func btCmp(a, b []byte) int {
  73. ml := len(a)
  74. if len(b) < ml {
  75. ml = len(b)
  76. }
  77. for i := 0; i < ml; i++ {
  78. if a[i] < b[i] {
  79. return -1
  80. }
  81. if a[i] > b[i] {
  82. return 1
  83. }
  84. }
  85. if len(a) < len(b) {
  86. return -1
  87. }
  88. if len(a) > len(b) {
  89. return 1
  90. }
  91. return 0
  92. }
  93. func btRoute(n *btNode, key []byte) uint32 {
  94. cnt := int(n.info.Count)
  95. if cnt <= 0 {
  96. return 0 // 防御: 空节点不应作为路由节点
  97. }
  98. // 二分查找: 找最后一个 entry.key <= key 的位置 (与二级 B+ 树统一 <= 约定)
  99. left, right := 0, cnt-1
  100. result := 0
  101. for left <= right {
  102. mid := (left + right) / 2
  103. if btCmp(btKey(btEntry(n, mid)), key) <= 0 {
  104. result = mid
  105. left = mid + 1 // 继续向右找
  106. } else {
  107. right = mid - 1
  108. }
  109. }
  110. return btPID(btEntry(n, result))
  111. }
  112. // maxLeafEntries 单个叶节点最大条目数
  113. func maxLeafEntries(entryLen int) int {
  114. threshold := btSplitThreshold()
  115. available := threshold - page.IndexHeadSize
  116. if available <= 0 {
  117. return 1
  118. }
  119. return available / entryLen
  120. }
  121. // BuildFromSorted 从已排序的叶条目批量构建 B+ 树 (自底向上)
  122. // leafEntries: 每个条目 = [key(8B) + dpID(4B BE)], 已按 key 升序排列
  123. // 返回新树根 pageID
  124. //
  125. // 内存优化: 避免逐行 B+ 树搜索 (每次 btLoad 16KB), 改为顺序创建所有节点
  126. func BuildFromSorted(leafEntries [][]byte, handle page.HandleDb) uint32 {
  127. if len(leafEntries) == 0 {
  128. return 0
  129. }
  130. el := 12 // entry len: 8 key + 4 pid
  131. maxPerLeaf := maxLeafEntries(el)
  132. // ---- 构建叶节点层 ----
  133. type childInfo struct {
  134. pid uint32
  135. firstKey []byte // 该子树第一个 key (用于 > 路由)
  136. }
  137. var children []childInfo
  138. var prevLeafPID uint32
  139. // 将条目分组到叶节点 (带链表链接)
  140. for i := 0; i < len(leafEntries); {
  141. end := i + maxPerLeaf
  142. if end > len(leafEntries) {
  143. end = len(leafEntries)
  144. }
  145. leaf := btNew(handle, true, el)
  146. for j := i; j < end; j++ {
  147. src := leafEntries[j]
  148. dst := btEntry(leaf, int(leaf.info.Count))
  149. copy(dst, src)
  150. leaf.info.Count++
  151. leaf.info.Hdr.UseSize += uint32(el)
  152. }
  153. // 设置叶节点链表链接
  154. leaf.info.Hdr.PrePage = prevLeafPID
  155. if prevLeafPID != 0 {
  156. // 更新前一个叶节点的 NextPage
  157. // 注意: 前一个叶节点已经保存, 需要重新加载并更新
  158. // 但我们可以在保存前就设置好 NextPage
  159. }
  160. btSave(handle, leaf)
  161. // 更新前一个叶节点的 NextPage 指向当前叶
  162. if prevLeafPID != 0 {
  163. prevLeaf := btLoad(handle, prevLeafPID)
  164. if prevLeaf != nil {
  165. prevLeaf.info.Hdr.NextPage = leaf.pageID()
  166. btSave(handle, prevLeaf)
  167. }
  168. }
  169. prevLeafPID = leaf.pageID()
  170. children = append(children, childInfo{
  171. pid: leaf.pageID(),
  172. firstKey: leafEntries[i][:8],
  173. })
  174. i = end
  175. }
  176. if len(children) == 1 {
  177. return children[0].pid
  178. }
  179. // ---- 自底向上构建内部节点 ----
  180. // 路由约定 (btRoute): 找最后一个 entry.key <= searchKey
  181. // 内部节点条目: entry[i] = (child[i].firstKey, child[i].pid)
  182. // 即 entry[i].key = 该子树最左叶的第一个 key
  183. intEl := 12
  184. maxPerInt := maxLeafEntries(intEl)
  185. for len(children) > 1 {
  186. var parents []childInfo
  187. for i := 0; i < len(children); {
  188. end := i + maxPerInt
  189. if end > len(children) {
  190. end = len(children)
  191. }
  192. node := btNew(handle, false, intEl)
  193. for j := i; j < end; j++ {
  194. e := make([]byte, intEl)
  195. // 分隔键 = 该 child 的第一个 key
  196. copy(e[:intEl-4], children[j].firstKey)
  197. btSetPID(e, children[j].pid)
  198. dst := btEntry(node, int(node.info.Count))
  199. copy(dst, e)
  200. node.info.Count++
  201. node.info.Hdr.UseSize += uint32(intEl)
  202. }
  203. btSave(handle, node)
  204. parents = append(parents, childInfo{
  205. pid: node.pageID(),
  206. firstKey: children[i].firstKey,
  207. })
  208. i = end
  209. }
  210. children = parents
  211. }
  212. return children[0].pid
  213. }
  214. func btChildIdx(n *btNode, key []byte) int {
  215. el := int(n.info.EntryLen)
  216. cnt := int(n.info.Count)
  217. // 二分查找: 找最后一个 entry.key <= key 的位置 (与二级 B+ 树统一 <= 约定)
  218. left, right := 0, cnt-1
  219. result := 0
  220. for left <= right {
  221. mid := (left + right) / 2
  222. if btCmp(btEntry(n, mid)[:el-4], key) <= 0 {
  223. result = mid
  224. left = mid + 1 // 继续向右找
  225. } else {
  226. right = mid - 1
  227. }
  228. }
  229. return result
  230. }
  231. func btInsEntry(n *btNode, entry []byte, pos int) {
  232. el := int(n.info.EntryLen)
  233. cnt := int(n.info.Count)
  234. for i := cnt; i > pos; i-- {
  235. copy(btEntry(n, i), btEntry(n, i-1))
  236. }
  237. copy(btEntry(n, pos), entry)
  238. n.info.Count++
  239. n.info.Hdr.UseSize += uint32(el)
  240. }
  241. func btRmEntry(n *btNode, pos int) {
  242. el := int(n.info.EntryLen)
  243. cnt := int(n.info.Count)
  244. for i := pos; i < cnt-1; i++ {
  245. copy(btEntry(n, i), btEntry(n, i+1))
  246. }
  247. n.info.Count--
  248. n.info.Hdr.UseSize -= uint32(el)
  249. }
  250. func btLeafFind(n *btNode, key []byte) (int, bool) {
  251. el := int(n.info.EntryLen)
  252. cnt := int(n.info.Count)
  253. for i := 0; i < cnt; i++ {
  254. if btCmp(btEntry(n, i)[:el-4], key) == 0 {
  255. return i, true
  256. }
  257. }
  258. return 0, false
  259. }
  260. func btLeafPos(n *btNode, key []byte) int {
  261. el := int(n.info.EntryLen)
  262. cnt := int(n.info.Count)
  263. for i := 0; i < cnt; i++ {
  264. if btCmp(btEntry(n, i)[:el-4], key) >= 0 {
  265. return i
  266. }
  267. }
  268. return cnt
  269. }
  270. // btLeftmostKey 获取子树最左叶的第一个 key(用于 promoKey)
  271. func btLeftmostKey(handle page.HandleDb, nodePID uint32) []byte {
  272. cur := nodePID
  273. for {
  274. n := btLoad(handle, cur)
  275. if n == nil {
  276. return nil
  277. }
  278. if n.isLeaf() {
  279. if n.info.Count == 0 {
  280. return nil
  281. }
  282. e := btEntry(n, 0)
  283. key := make([]byte, len(btKey(e)))
  284. copy(key, btKey(e))
  285. return key
  286. }
  287. // 非叶节点,继续向左下遍历
  288. cur = btPID(btEntry(n, 0))
  289. }
  290. }
  291. // ======================== B+ 鏍戞悳绱?========================
  292. func BTreePKSearch(rootPID uint32, key []byte, handle page.HandleDb) (uint32, bool) {
  293. if rootPID == 0 {
  294. return 0, false
  295. }
  296. cur := rootPID
  297. for {
  298. n := btLoad(handle, cur)
  299. if n == nil {
  300. return 0, false
  301. }
  302. if n.isLeaf() {
  303. pos, ok := btLeafFind(n, key)
  304. if !ok {
  305. return 0, false
  306. }
  307. return btPID(btEntry(n, pos)), true
  308. }
  309. cur = btRoute(n, key)
  310. }
  311. }
  312. // ======================== B+ 鏍戝彾瀛愯妭鐐瑰畾浣?========================
  313. // BTreeFindLeftmostLeaf 浠庢牴鑺傜偣璺敱鍒版渶宸﹀彾鑺傜偣锛岃繑鍥炲彾鑺傜偣 pageID
  314. func BTreeFindLeftmostLeaf(rootPID uint32, handle page.HandleDb) uint32 {
  315. cur := rootPID
  316. for {
  317. n := btLoad(handle, cur)
  318. if n == nil {
  319. return 0
  320. }
  321. if n.isLeaf() {
  322. return n.info.Hdr.PageID
  323. }
  324. cur = btPID(btEntry(n, 0))
  325. }
  326. }
  327. // BTreeFindRightmostLeaf 浠庢牴鑺傜偣璺敱鍒版渶鍙冲彾鑺傜偣锛岃繑鍥炲彾鑺傜偣 pageID
  328. func BTreeFindRightmostLeaf(rootPID uint32, handle page.HandleDb) uint32 {
  329. cur := rootPID
  330. for {
  331. n := btLoad(handle, cur)
  332. if n == nil {
  333. return 0
  334. }
  335. if n.isLeaf() {
  336. return n.info.Hdr.PageID
  337. }
  338. cur = btPID(btEntry(n, int(n.info.Count)-1))
  339. }
  340. }
  341. // ======================== B+ 鏍戣寖鍥存壂鎻?========================
  342. // BTreePKRangeScan 涓婚敭 B+ 鏍戣寖鍥存壂鎻?
  343. func BTreePKRangeScan(rootPID uint32, handle page.HandleDb,
  344. startKey, endKey []byte, startInc, endInc bool, reverse bool,
  345. callback func(row []byte) bool) error {
  346. if rootPID == 0 {
  347. return nil
  348. }
  349. if !reverse {
  350. // 正向: 路由到 startKey 所在叶, 沿 NextPage 遍历
  351. cur := rootPID
  352. for {
  353. n := btLoad(handle, cur)
  354. if n == nil {
  355. return nil
  356. }
  357. if n.isLeaf() {
  358. break
  359. }
  360. cur = btRoute(n, startKey)
  361. }
  362. for cur != 0 {
  363. n := btLoad(handle, cur)
  364. if n == nil {
  365. break
  366. }
  367. for i := 0; i < int(n.info.Count); i++ {
  368. entry := btEntry(n, i)
  369. key := btKey(entry)
  370. if endKey != nil {
  371. cmp := btCmp(key, endKey)
  372. if cmp > 0 || (cmp == 0 && !endInc) {
  373. return nil
  374. }
  375. }
  376. if startKey != nil {
  377. cmp := btCmp(key, startKey)
  378. if cmp < 0 || (cmp == 0 && !startInc) {
  379. continue
  380. }
  381. }
  382. dpID := btPID(entry)
  383. dp, err := datapage.Load(handle, dpID)
  384. if err != nil {
  385. continue
  386. }
  387. // 每个 B+ 树条目精确匹配一行 (FindRowByIndexKey 按索引键过滤)
  388. if row, ok := dp.FindRowByIndexKey(key, 9); ok {
  389. if !callback(row) {
  390. return nil
  391. }
  392. }
  393. }
  394. cur = n.info.Hdr.NextPage
  395. }
  396. } else {
  397. // 反向: 路由到 endKey 所在叶(或最右叶), 沿 PrePage 遍历
  398. cur := rootPID
  399. if endKey != nil {
  400. for {
  401. n := btLoad(handle, cur)
  402. if n == nil {
  403. return nil
  404. }
  405. if n.isLeaf() {
  406. break
  407. }
  408. cur = btRoute(n, endKey)
  409. }
  410. } else {
  411. cur = BTreeFindRightmostLeaf(rootPID, handle)
  412. }
  413. for cur != 0 {
  414. n := btLoad(handle, cur)
  415. if n == nil {
  416. break
  417. }
  418. for i := int(n.info.Count) - 1; i >= 0; i-- {
  419. entry := btEntry(n, i)
  420. key := btKey(entry)
  421. if startKey != nil {
  422. cmp := btCmp(key, startKey)
  423. if cmp < 0 || (cmp == 0 && !startInc) {
  424. return nil
  425. }
  426. }
  427. if endKey != nil {
  428. cmp := btCmp(key, endKey)
  429. if cmp > 0 || (cmp == 0 && !endInc) {
  430. continue
  431. }
  432. }
  433. dpID := btPID(entry)
  434. dp, err := datapage.Load(handle, dpID)
  435. if err != nil {
  436. continue
  437. }
  438. if row, ok := dp.FindRowByIndexKey(key, 9); ok {
  439. if !callback(row) {
  440. return nil
  441. }
  442. }
  443. }
  444. cur = n.info.Hdr.PrePage
  445. }
  446. }
  447. return nil
  448. }
  449. // ======================== B+ 鏍戞彃鍏?========================
  450. func BTreePKInsert(rootPID uint32, key []byte, dpID uint32, handle page.HandleDb) (uint32, uint32, bool, error) {
  451. if rootPID == 0 {
  452. el := 12
  453. leaf := btNew(handle, true, el)
  454. e := make([]byte, el)
  455. copy(e[:8], key)
  456. btSetPID(e, dpID)
  457. btInsEntry(leaf, e, 0)
  458. btSave(handle, leaf)
  459. return leaf.pageID(), 0, false, nil
  460. }
  461. var path []btPathEntry
  462. cur := rootPID
  463. for {
  464. n := btLoad(handle, cur)
  465. if n == nil {
  466. return rootPID, 0, false, errors.New("load failed")
  467. }
  468. if n.isLeaf() {
  469. pos, found := btLeafFind(n, key)
  470. if found {
  471. return rootPID, btPID(btEntry(n, pos)), true, nil
  472. }
  473. el := 12
  474. ne := make([]byte, el)
  475. copy(ne[:8], key)
  476. btSetPID(ne, dpID)
  477. ip := btLeafPos(n, key)
  478. if int(n.info.Hdr.UseSize)+el <= btSplitThreshold() {
  479. btInsEntry(n, ne, ip)
  480. btSave(handle, n)
  481. return rootPID, 0, false, nil
  482. }
  483. cnt := int(n.info.Count)
  484. total := cnt + 1
  485. all := make([]byte, total*el)
  486. if ip > 0 {
  487. copy(all, n.entries[:ip*el])
  488. }
  489. copy(all[ip*el:], ne)
  490. if cnt > ip {
  491. copy(all[(ip+1)*el:], n.entries[ip*el:cnt*el])
  492. }
  493. mid := total / 2
  494. // <= 路由约定: 左子叶所有 key 必须严格小于右子叶第一个 key (promoKey)
  495. // 如果 all[mid-1].key == all[mid].key, 右移 mid 直到分隔
  496. for mid < total-1 {
  497. if btCmp(all[(mid-1)*el:mid*el-4], all[mid*el:(mid+1)*el-4]) < 0 {
  498. break
  499. }
  500. mid++
  501. }
  502. rl := btNew(handle, true, el)
  503. rc := total - mid
  504. copy(rl.entries, all[mid*el:total*el])
  505. rl.info.Count = uint32(rc)
  506. rl.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(rc*el)
  507. rl.info.Hdr.NextPage = n.info.Hdr.NextPage
  508. rl.info.Hdr.PrePage = n.info.Hdr.PageID
  509. n.info.Hdr.NextPage = rl.info.Hdr.PageID
  510. copy(n.entries, all[:mid*el])
  511. n.info.Count = uint32(mid)
  512. n.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(mid*el)
  513. btSave(handle, n)
  514. btSave(handle, rl)
  515. if rl.info.Hdr.NextPage != 0 {
  516. nl := btLoad(handle, rl.info.Hdr.NextPage)
  517. if nl != nil {
  518. nl.info.Hdr.PrePage = rl.info.Hdr.PageID
  519. btSave(handle, nl)
  520. }
  521. }
  522. // 使用右子树最左叶的第一个 key 作为 promoKey
  523. pk := btLeftmostKey(handle, rl.info.Hdr.PageID)
  524. nr, err := btPromote(handle, rootPID, path, n.info.Hdr.PageID, pk, rl.info.Hdr.PageID)
  525. return nr, 0, false, err
  526. }
  527. ci := btChildIdx(n, key)
  528. cpid := btPID(btEntry(n, ci))
  529. path = append(path, btPathEntry{nodePID: cur, childIdx: ci})
  530. cur = cpid
  531. }
  532. }
  533. func btPromote(handle page.HandleDb, rootPID uint32, path []btPathEntry, leftPID uint32, promoKey []byte, rightPID uint32) (uint32, error) {
  534. if len(path) == 0 {
  535. el := 12
  536. nr := btNew(handle, false, el)
  537. leftKey := btLeftmostKey(handle, leftPID)
  538. le := make([]byte, el)
  539. copy(le[:8], leftKey)
  540. btSetPID(le, leftPID)
  541. re := make([]byte, el)
  542. copy(re[:8], promoKey)
  543. btSetPID(re, rightPID)
  544. btInsEntry(nr, le, 0)
  545. btInsEntry(nr, re, 1)
  546. btSave(handle, nr)
  547. return nr.pageID(), nil
  548. }
  549. pi := len(path) - 1
  550. parent := btLoad(handle, path[pi].nodePID)
  551. if parent == nil {
  552. return rootPID, errors.New("parent load failed")
  553. }
  554. ci := path[pi].childIdx
  555. el := int(parent.info.EntryLen)
  556. // ⭐ FIX: 叶子分裂后, 左子树的最小 key 可能已变化
  557. // 必须更新 parent[ci].key = 左子树的新最小 key
  558. newLeftKey := btLeftmostKey(handle, leftPID)
  559. if newLeftKey == nil {
  560. return rootPID, errors.New("leftmost key failed")
  561. }
  562. // 更新 parent[ci] 的 key 和 PID
  563. copy(btEntry(parent, ci)[:el-4], newLeftKey)
  564. btSetPID(btEntry(parent, ci), leftPID)
  565. // 更新 key 后, parent[ci..] 可能不再有序
  566. // 需要将 parent[ci] 冒泡到正确位置, 然后插入 (promoKey, rightPID)
  567. // 1. 冒泡 parent[ci] 到正确位置 (如果 newLeftKey > parent[ci+1].key)
  568. for i := ci; i+1 < int(parent.info.Count); i++ {
  569. if btCmp(btKey(btEntry(parent, i)), btKey(btEntry(parent, i+1))) <= 0 {
  570. break // 已有序
  571. }
  572. // 交换 parent[i] 和 parent[i+1]
  573. tmp := make([]byte, el)
  574. copy(tmp, btEntry(parent, i))
  575. copy(btEntry(parent, i), btEntry(parent, i+1))
  576. copy(btEntry(parent, i+1), tmp)
  577. }
  578. // 2. 在排序位置插入 (promoKey, rightPID)
  579. newPos := int(parent.info.Count)
  580. for i := ci; i < int(parent.info.Count); i++ {
  581. if btCmp(btKey(btEntry(parent, i)), promoKey) >= 0 {
  582. newPos = i
  583. break
  584. }
  585. }
  586. for i := int(parent.info.Count); i > newPos; i-- {
  587. copy(btEntry(parent, i), btEntry(parent, i-1))
  588. }
  589. ne := make([]byte, el)
  590. copy(ne[:el-4], promoKey)
  591. btSetPID(ne, rightPID)
  592. copy(btEntry(parent, newPos), ne)
  593. parent.info.Count++
  594. parent.info.Hdr.UseSize += uint32(el)
  595. if int(parent.info.Hdr.UseSize)+el <= btSplitThreshold() {
  596. btSave(handle, parent)
  597. return rootPID, nil
  598. }
  599. cnt := int(parent.info.Count)
  600. mid := cnt / 2
  601. rn := btNew(handle, false, el)
  602. rc := cnt - mid
  603. copy(rn.entries, parent.entries[mid*el:cnt*el])
  604. rn.info.Count = uint32(rc)
  605. rn.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(rc*el)
  606. parent.info.Count = uint32(mid)
  607. parent.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(mid*el)
  608. btSave(handle, parent)
  609. btSave(handle, rn)
  610. pk2 := make([]byte, 8)
  611. copy(pk2, btKey(btEntry(rn, 0)))
  612. return btPromote(handle, rootPID, path[:pi], parent.info.Hdr.PageID, pk2, rn.info.Hdr.PageID)
  613. }
  614. // ======================== B+ 鏍戝垹闄?(閫掑綊 + 鍚堝苟/鍊熶綅) ========================
  615. func BTreePKDelete(rootPID uint32, key []byte, handle page.HandleDb) (uint32, uint32, error) {
  616. if rootPID == 0 {
  617. return 0, 0, page.ErrNotFound
  618. }
  619. delDP, err := btDeleteRec(rootPID, key, nil, handle)
  620. if err != nil {
  621. return rootPID, delDP, err
  622. }
  623. n := btLoad(handle, rootPID)
  624. if n != nil && n.info.Count == 0 {
  625. if !n.isLeaf() && n.info.Count == 0 {
  626. return rootPID, delDP, nil
  627. }
  628. }
  629. return rootPID, delDP, nil
  630. }
  631. func btDeleteRec(nodePID uint32, key []byte, path []btPathEntry, handle page.HandleDb) (uint32, error) {
  632. node := btLoad(handle, nodePID)
  633. if node == nil {
  634. return nodePID, page.ErrNotFound
  635. }
  636. el := int(node.info.EntryLen)
  637. if node.isLeaf() {
  638. pos, ok := btLeafFind(node, key)
  639. if !ok {
  640. return nodePID, page.ErrNotFound
  641. }
  642. delDP := btPID(btEntry(node, pos))
  643. btRmEntry(node, pos)
  644. if node.info.Count == 0 && len(path) == 0 {
  645. btSave(handle, node)
  646. return delDP, nil
  647. }
  648. btSave(handle, node)
  649. if len(path) > 0 && node.info.Count > 0 {
  650. btTryMerge(handle, path, node, el)
  651. }
  652. return delDP, nil
  653. }
  654. ci := btChildIdx(node, key)
  655. childPID := btPID(btEntry(node, ci))
  656. newPath := make([]btPathEntry, len(path)+1)
  657. copy(newPath, path)
  658. newPath[len(path)] = btPathEntry{nodePID: nodePID, childIdx: ci}
  659. delDP, err := btDeleteRec(childPID, key, newPath, handle)
  660. if err != nil {
  661. return delDP, err
  662. }
  663. node = btLoad(handle, nodePID)
  664. if node == nil {
  665. return delDP, errors.New("reload node failed")
  666. }
  667. if node.info.Count > 0 {
  668. ci2 := btChildIdx(node, key)
  669. if ci2 >= 0 && ci2 < int(node.info.Count) {
  670. cpID := btPID(btEntry(node, ci2))
  671. child := btLoad(handle, cpID)
  672. if child != nil && child.info.Count == 0 {
  673. btHandleUnderflow(node, ci2, el, handle)
  674. }
  675. }
  676. }
  677. if node.info.Count == 0 {
  678. return delDP, nil
  679. }
  680. btSave(handle, node)
  681. return delDP, nil
  682. }
  683. func btTryMerge(handle page.HandleDb, path []btPathEntry, node *btNode, el int) {
  684. if len(path) == 0 {
  685. return
  686. }
  687. pp := path[len(path)-1].nodePID
  688. parent := btLoad(handle, pp)
  689. if parent == nil {
  690. return
  691. }
  692. ci := -1
  693. for i := 0; i < int(parent.info.Count); i++ {
  694. if btPID(btEntry(parent, i)) == node.info.Hdr.PageID {
  695. ci = i
  696. break
  697. }
  698. }
  699. if ci < 0 {
  700. return
  701. }
  702. if ci > 0 {
  703. leftPID := btPID(btEntry(parent, ci-1))
  704. left := btLoad(handle, leftPID)
  705. if left != nil && left.isLeaf() {
  706. combined := uint32(page.IndexHeadSize) + (left.info.Count+node.info.Count)*uint32(el)
  707. threshold := uint32(btSplitThreshold())
  708. if combined <= threshold {
  709. rc := int(node.info.Count)
  710. copy(left.entries[int(left.info.Count)*el:], node.entries[:rc*el])
  711. left.info.Count += node.info.Count
  712. left.info.Hdr.UseSize += uint32(rc * el)
  713. left.info.Hdr.NextPage = node.info.Hdr.NextPage
  714. btSave(handle, left)
  715. if left.info.Hdr.NextPage != 0 {
  716. nl := btLoad(handle, left.info.Hdr.NextPage)
  717. if nl != nil {
  718. nl.info.Hdr.PrePage = leftPID
  719. btSave(handle, nl)
  720. }
  721. }
  722. btRmEntry(parent, ci)
  723. btSave(handle, parent)
  724. return
  725. }
  726. }
  727. }
  728. if ci < int(parent.info.Count)-1 {
  729. rightPID := btPID(btEntry(parent, ci+1))
  730. right := btLoad(handle, rightPID)
  731. if right != nil && right.isLeaf() {
  732. combined := uint32(page.IndexHeadSize) + (node.info.Count+right.info.Count)*uint32(el)
  733. threshold := uint32(btSplitThreshold())
  734. if combined <= threshold {
  735. rc := int(right.info.Count)
  736. copy(node.entries[int(node.info.Count)*el:], right.entries[:rc*el])
  737. node.info.Count += right.info.Count
  738. node.info.Hdr.UseSize += uint32(rc * el)
  739. node.info.Hdr.NextPage = right.info.Hdr.NextPage
  740. btSave(handle, node)
  741. if node.info.Hdr.NextPage != 0 {
  742. nl := btLoad(handle, node.info.Hdr.NextPage)
  743. if nl != nil {
  744. nl.info.Hdr.PrePage = node.info.Hdr.PageID
  745. btSave(handle, nl)
  746. }
  747. }
  748. btRmEntry(parent, ci+1)
  749. btSave(handle, parent)
  750. return
  751. }
  752. }
  753. }
  754. }
  755. func btHandleUnderflow(parent *btNode, childIdx int, el int, handle page.HandleDb) {
  756. childPID := btPID(btEntry(parent, childIdx))
  757. child := btLoad(handle, childPID)
  758. if child == nil {
  759. return
  760. }
  761. if childIdx > 0 {
  762. leftPID := btPID(btEntry(parent, childIdx-1))
  763. leftSib := btLoad(handle, leftPID)
  764. if leftSib != nil && int(leftSib.info.Count) > 1 {
  765. borrowed := make([]byte, el)
  766. copy(borrowed, btEntry(leftSib, int(leftSib.info.Count)-1))
  767. btRmEntry(leftSib, int(leftSib.info.Count)-1)
  768. btInsEntry(child, borrowed, 0)
  769. copy(btEntry(parent, childIdx)[:8], btKey(btEntry(child, 0)))
  770. btSave(handle, leftSib)
  771. btSave(handle, child)
  772. btSave(handle, parent)
  773. return
  774. }
  775. }
  776. if childIdx < int(parent.info.Count)-1 {
  777. rightPID := btPID(btEntry(parent, childIdx+1))
  778. rightSib := btLoad(handle, rightPID)
  779. if rightSib != nil && int(rightSib.info.Count) > 1 {
  780. borrowed := make([]byte, el)
  781. copy(borrowed, btEntry(rightSib, 0))
  782. btRmEntry(rightSib, 0)
  783. btInsEntry(child, borrowed, int(child.info.Count))
  784. copy(btEntry(parent, childIdx)[:8], btKey(btEntry(rightSib, 0)))
  785. btSave(handle, rightSib)
  786. btSave(handle, child)
  787. btSave(handle, parent)
  788. return
  789. }
  790. }
  791. if childIdx > 0 {
  792. btMergeChildren(handle, parent, childIdx-1, el)
  793. } else if childIdx < int(parent.info.Count)-1 {
  794. btMergeChildren(handle, parent, childIdx, el)
  795. }
  796. }
  797. func btMergeChildren(handle page.HandleDb, parent *btNode, sepIdx int, el int) {
  798. leftPID := btPID(btEntry(parent, sepIdx))
  799. rightPID := btPID(btEntry(parent, sepIdx+1))
  800. left := btLoad(handle, leftPID)
  801. right := btLoad(handle, rightPID)
  802. if left == nil || right == nil {
  803. return
  804. }
  805. if left.isLeaf() {
  806. rc := int(right.info.Count)
  807. copy(left.entries[int(left.info.Count)*el:], right.entries[:rc*el])
  808. left.info.Count += right.info.Count
  809. left.info.Hdr.UseSize += uint32(rc * el)
  810. left.info.Hdr.NextPage = right.info.Hdr.NextPage
  811. } else {
  812. sepEntry := make([]byte, el)
  813. copy(sepEntry, btEntry(parent, sepIdx))
  814. rc := int(right.info.Count)
  815. off := int(left.info.Count) * el
  816. copy(left.entries[off:], sepEntry)
  817. off += el
  818. copy(left.entries[off:], right.entries[:rc*el])
  819. left.info.Count += 1 + right.info.Count
  820. left.info.Hdr.UseSize += uint32((1 + rc) * el)
  821. }
  822. btSave(handle, left)
  823. if left.isLeaf() && left.info.Hdr.NextPage != 0 {
  824. nl := btLoad(handle, left.info.Hdr.NextPage)
  825. if nl != nil {
  826. nl.info.Hdr.PrePage = leftPID
  827. btSave(handle, nl)
  828. }
  829. }
  830. btRmEntry(parent, sepIdx+1)
  831. btSetPID(btEntry(parent, sepIdx), leftPID)
  832. btSave(handle, parent)
  833. }
  834. // ======================== DataPage 鎿嶄綔 ========================
  835. // FindSpaceInLeaf 鍦ㄥ彾鑺傜偣涓壘鍒版湁绌洪棿鐨?DataPage
  836. func FindSpaceInLeaf(handle page.HandleDb, rootPID uint32, rowSize uint32, key []byte) (uint32, bool) {
  837. cur := rootPID
  838. for {
  839. n := btLoad(handle, cur)
  840. if n == nil {
  841. return 0, false
  842. }
  843. if n.isLeaf() {
  844. pos := btLeafPos(n, key)
  845. if pos >= int(n.info.Count) {
  846. pos = int(n.info.Count) - 1
  847. }
  848. if pos < 0 {
  849. return 0, false
  850. }
  851. dpID := btPID(btEntry(n, pos))
  852. dp, err := datapage.Load(handle, dpID)
  853. if err == nil && !dp.IsFull(rowSize) {
  854. return dpID, true
  855. }
  856. if n.info.Hdr.PrePage != 0 {
  857. prevN := btLoad(handle, n.info.Hdr.PrePage)
  858. if prevN != nil && prevN.isLeaf() && prevN.info.Count > 0 {
  859. prevDPID := btPID(btEntry(prevN, int(prevN.info.Count)-1))
  860. prevDP, err := datapage.Load(handle, prevDPID)
  861. if err == nil && !prevDP.IsFull(rowSize) {
  862. return prevDPID, true
  863. }
  864. }
  865. }
  866. if n.info.Hdr.NextPage != 0 {
  867. nextN := btLoad(handle, n.info.Hdr.NextPage)
  868. if nextN != nil && nextN.isLeaf() && nextN.info.Count > 0 {
  869. nextDPID := btPID(btEntry(nextN, 0))
  870. nextDP, err := datapage.Load(handle, nextDPID)
  871. if err == nil && !nextDP.IsFull(rowSize) {
  872. return nextDPID, true
  873. }
  874. }
  875. }
  876. return 0, false
  877. }
  878. cur = btRoute(n, key)
  879. }
  880. }
  881. // FindLastLeafDP 路由到目标叶子, 检查最后一个条目的 DataPage 是否有空间
  882. // 只检查路由目标叶子, 不跨叶子查找 (保证 B+ 树不变性)
  883. func FindLastLeafDP(handle page.HandleDb, rootPID uint32, rowSize uint32, key []byte) (uint32, bool) {
  884. cur := rootPID
  885. for {
  886. n := btLoad(handle, cur)
  887. if n == nil {
  888. return 0, false
  889. }
  890. if n.isLeaf() {
  891. if n.info.Count == 0 {
  892. return 0, false
  893. }
  894. // 检查最后一个条目的 DataPage
  895. lastIdx := int(n.info.Count) - 1
  896. dpID := btPID(btEntry(n, lastIdx))
  897. dp, err := datapage.Load(handle, dpID)
  898. if err == nil && !dp.IsFull(rowSize) {
  899. return dpID, true
  900. }
  901. return 0, false
  902. }
  903. cur = btRoute(n, key)
  904. }
  905. }
  906. // GetDataPageIDs 返回所有 DataPage ID (去重, 用于全表扫描)
  907. func GetDataPageIDs(handle page.HandleDb, rootPID uint32) []uint32 {
  908. if rootPID == 0 {
  909. return nil
  910. }
  911. var dpIDs []uint32
  912. seen := make(map[uint32]bool)
  913. cur := rootPID
  914. for {
  915. n := btLoad(handle, cur)
  916. if n == nil {
  917. break
  918. }
  919. if n.isLeaf() {
  920. break
  921. }
  922. cur = btPID(btEntry(n, 0))
  923. }
  924. for cur != 0 {
  925. n := btLoad(handle, cur)
  926. if n == nil {
  927. break
  928. }
  929. for i := 0; i < int(n.info.Count); i++ {
  930. dpID := btPID(btEntry(n, i))
  931. if !seen[dpID] {
  932. seen[dpID] = true
  933. dpIDs = append(dpIDs, dpID)
  934. }
  935. }
  936. cur = n.info.Hdr.NextPage
  937. }
  938. return dpIDs
  939. }
  940. // ScanAllLeavesForPK 扫描所有叶子查找 pkID(LE)
  941. func ScanAllLeavesForPK(rootPID uint32, handle page.HandleDb, pkKeyBE []byte) ([]byte, bool) {
  942. if rootPID == 0 {
  943. return nil, false
  944. }
  945. cur := rootPID
  946. for {
  947. n := btLoad(handle, cur)
  948. if n == nil {
  949. return nil, false
  950. }
  951. if n.isLeaf() {
  952. break
  953. }
  954. cur = btPID(btEntry(n, 0))
  955. }
  956. for cur != 0 {
  957. n := btLoad(handle, cur)
  958. if n == nil {
  959. break
  960. }
  961. for i := 0; i < int(n.info.Count); i++ {
  962. dpID := btPID(btEntry(n, i))
  963. dp, err := datapage.Load(handle, dpID)
  964. if err == nil {
  965. if rowData, ok := dp.FindRowByPK(pkKeyBE); ok {
  966. return rowData, true
  967. }
  968. }
  969. }
  970. cur = n.info.Hdr.NextPage
  971. }
  972. return nil, false
  973. }
  974. // ScanAndDelete 扫描所有叶子按 indexKey 删除
  975. func ScanAndDelete(rootPID uint32, handle page.HandleDb, indexKey, pkKeyBE []byte) error {
  976. if rootPID == 0 {
  977. return page.ErrNotFound
  978. }
  979. cur := rootPID
  980. for {
  981. n := btLoad(handle, cur)
  982. if n == nil {
  983. return page.ErrNotFound
  984. }
  985. if n.isLeaf() {
  986. break
  987. }
  988. cur = btPID(btEntry(n, 0))
  989. }
  990. for cur != 0 {
  991. n := btLoad(handle, cur)
  992. if n == nil {
  993. break
  994. }
  995. for i := 0; i < int(n.info.Count); i++ {
  996. dpID := btPID(btEntry(n, i))
  997. dp, err := datapage.Load(handle, dpID)
  998. if err == nil {
  999. deleted := false
  1000. if dp.DeleteByIndexKey(indexKey, 8) {
  1001. deleted = true
  1002. } else if dp.DeleteByPK(pkKeyBE) {
  1003. deleted = true
  1004. }
  1005. if deleted {
  1006. if dp.AllDeleted() {
  1007. newRoot, _, err := BTreePKDelete(rootPID, indexKey, handle)
  1008. if err != nil {
  1009. return err
  1010. }
  1011. _ = newRoot
  1012. } else {
  1013. dp.Save()
  1014. }
  1015. return nil
  1016. }
  1017. }
  1018. }
  1019. cur = n.info.Hdr.NextPage
  1020. }
  1021. return page.ErrNotFound
  1022. }
  1023. // ScanAndDeleteByPK 扫描所有叶子按 pkID 删除
  1024. func ScanAndDeleteByPK(rootPID uint32, handle page.HandleDb, pkKeyBE []byte) error {
  1025. if rootPID == 0 {
  1026. return page.ErrNotFound
  1027. }
  1028. cur := rootPID
  1029. for {
  1030. n := btLoad(handle, cur)
  1031. if n == nil {
  1032. return page.ErrNotFound
  1033. }
  1034. if n.isLeaf() {
  1035. break
  1036. }
  1037. cur = btPID(btEntry(n, 0))
  1038. }
  1039. for cur != 0 {
  1040. n := btLoad(handle, cur)
  1041. if n == nil {
  1042. break
  1043. }
  1044. for i := 0; i < int(n.info.Count); i++ {
  1045. dpID := btPID(btEntry(n, i))
  1046. dp, err := datapage.Load(handle, dpID)
  1047. if err == nil {
  1048. if dp.DeleteByPK(pkKeyBE) {
  1049. if dp.AllDeleted() {
  1050. newRoot, _, err := BTreePKDelete(rootPID, pkKeyBE, handle)
  1051. if err != nil {
  1052. return err
  1053. }
  1054. _ = newRoot
  1055. } else {
  1056. dp.Save()
  1057. }
  1058. return nil
  1059. }
  1060. }
  1061. }
  1062. cur = n.info.Hdr.NextPage
  1063. }
  1064. return page.ErrNotFound
  1065. }
  1066. // ScanAndUpdate 扫描所有叶子按 pkID 更新
  1067. func ScanAndUpdate(rootPID uint32, handle page.HandleDb, pkKeyBE, storeRowData []byte) error {
  1068. if rootPID == 0 {
  1069. return page.ErrNotFound
  1070. }
  1071. cur := rootPID
  1072. for {
  1073. n := btLoad(handle, cur)
  1074. if n == nil {
  1075. return page.ErrNotFound
  1076. }
  1077. if n.isLeaf() {
  1078. break
  1079. }
  1080. cur = btPID(btEntry(n, 0))
  1081. }
  1082. for cur != 0 {
  1083. n := btLoad(handle, cur)
  1084. if n == nil {
  1085. break
  1086. }
  1087. for i := 0; i < int(n.info.Count); i++ {
  1088. dpID := btPID(btEntry(n, i))
  1089. dp, err := datapage.Load(handle, dpID)
  1090. if err == nil {
  1091. if err := dp.UpdateByPK(pkKeyBE, storeRowData); err == nil {
  1092. dp.Save()
  1093. return nil
  1094. }
  1095. }
  1096. }
  1097. cur = n.info.Hdr.NextPage
  1098. }
  1099. return page.ErrNotFound
  1100. }
  1101. // BTreeValidate 检查 B+ 树内部节点条目排序
  1102. func BTreeValidate(handle page.HandleDb, rootPID uint32) []string {
  1103. var issues []string
  1104. if rootPID == 0 {
  1105. return issues
  1106. }
  1107. var check func(pid uint32, depth int)
  1108. check = func(pid uint32, depth int) {
  1109. n := btLoad(handle, pid)
  1110. if n == nil {
  1111. issues = append(issues, fmt.Sprintf("d=%d: load fail pid=%d", depth, pid))
  1112. return
  1113. }
  1114. cnt := int(n.info.Count)
  1115. if n.isLeaf() {
  1116. for i := 1; i < cnt; i++ {
  1117. pk := btKey(btEntry(n, i-1))
  1118. ck := btKey(btEntry(n, i))
  1119. if btCmp(pk, ck) >= 0 {
  1120. issues = append(issues, fmt.Sprintf("d=%d leaf=%d: unsorted [%d]>=[%d]", depth, pid, i-1, i))
  1121. }
  1122. }
  1123. return
  1124. }
  1125. for i := 1; i < cnt; i++ {
  1126. pk := btKey(btEntry(n, i-1))
  1127. ck := btKey(btEntry(n, i))
  1128. if btCmp(pk, ck) > 0 {
  1129. issues = append(issues, fmt.Sprintf("d=%d int=%d: UNSORTED [%d]>[%d]", depth, pid, i-1, i))
  1130. }
  1131. }
  1132. for i := 0; i < cnt; i++ {
  1133. childPID := btPID(btEntry(n, i))
  1134. check(childPID, depth+1)
  1135. }
  1136. }
  1137. check(rootPID, 0)
  1138. return issues
  1139. }
  1140. // BTreeTraceSearch 搜索并打印路由路径
  1141. func BTreeTraceSearch(rootPID uint32, key []byte, handle page.HandleDb) {
  1142. if rootPID == 0 {
  1143. fmt.Println("Tree is empty")
  1144. return
  1145. }
  1146. cur := rootPID
  1147. depth := 0
  1148. for {
  1149. n := btLoad(handle, cur)
  1150. if n == nil {
  1151. fmt.Printf(" d=%d: LOAD FAIL pid=%d\n", depth, cur)
  1152. return
  1153. }
  1154. el := int(n.info.EntryLen)
  1155. cnt := int(n.info.Count)
  1156. if n.isLeaf() {
  1157. fk := uint64(0)
  1158. lk := uint64(0)
  1159. if cnt > 0 {
  1160. fk = binary.BigEndian.Uint64(btKey(btEntry(n, 0)))
  1161. lk = binary.BigEndian.Uint64(btKey(btEntry(n, cnt-1)))
  1162. }
  1163. pos, found := btLeafFind(n, key)
  1164. fmt.Printf(" d=%d LEAF pid=%d cnt=%d first=%d last=%d pos=%d found=%v\n",
  1165. depth, cur, cnt, fk, lk, pos, found)
  1166. return
  1167. }
  1168. fmt.Printf(" d=%d INT pid=%d cnt=%d [", depth, cur, cnt)
  1169. for i := 0; i < cnt; i++ {
  1170. k := binary.BigEndian.Uint64(btEntry(n, i)[:el-4])
  1171. p := btPID(btEntry(n, i))
  1172. if i > 0 {
  1173. fmt.Printf(", ")
  1174. }
  1175. if i < 3 || i >= cnt-2 {
  1176. fmt.Printf("(k=%d,p=%d)", k, p)
  1177. } else if i == 3 {
  1178. fmt.Printf("...")
  1179. }
  1180. }
  1181. fmt.Printf("]\n")
  1182. ci := btChildIdx(n, key)
  1183. fmt.Printf(" btChildIdx(%d) = %d\n", binary.BigEndian.Uint64(key), ci)
  1184. cur = btPID(btEntry(n, ci))
  1185. depth++
  1186. }
  1187. }
  1188. // CollectAllPageIDs 收集 B+ 树所有页 ID (包括内部节点和叶子节点)
  1189. // 用于 DropTable 时释放所有 B+ 树占用的页
  1190. func CollectAllPageIDs(handle page.HandleDb, rootPID uint32) []uint32 {
  1191. if rootPID == 0 {
  1192. return nil
  1193. }
  1194. var pages []uint32
  1195. // BFS 遍历所有节点
  1196. queue := []uint32{rootPID}
  1197. for len(queue) > 0 {
  1198. pid := queue[0]
  1199. queue = queue[1:]
  1200. pages = append(pages, pid)
  1201. n := btLoad(handle, pid)
  1202. if n == nil {
  1203. continue
  1204. }
  1205. if !n.isLeaf() {
  1206. // 内部节点: 收集所有子节点
  1207. for i := 0; i < int(n.info.Count); i++ {
  1208. childPID := btPID(btEntry(n, i))
  1209. if childPID != 0 {
  1210. queue = append(queue, childPID)
  1211. }
  1212. }
  1213. }
  1214. }
  1215. return pages
  1216. }