// Sorted range view over an i64 node property column: the lazily built,// snapshot-cached primitive behind selective range scans (dates and other// ordered i64 keys), the ordered complement of the equality property// index. Entries sort by (value, node id), so any value interval is one// contiguous window answered by two binary searches and returned as a// zero-copy id slice.package chickpeasimport ()// RangeIndex is a sorted view of an i64 node property column: Window// answers value intervals with a zero-copy slice of node ids. The zero// value is an empty index.typeRangeIndexstruct { vals []int64 ids []uint32}// ColRangeIndex resolves the sorted range view for a node property key,// building it on first use and caching it on the snapshot for the// snapshot's lifetime (the posIndex/LabelDense policy: memory stays// proportional to the column's entry count, ~12 bytes each). ok is false// when the key has no node column or the column is not i64.func ( *Snapshot) ( string) (RangeIndex, bool) { , := .PropertyKey()if ! {returnRangeIndex{}, false } , := .columns[]if ! || .Dtype() != DtypeI64 {returnRangeIndex{}, false } .rangeMu.Lock() , := .rangeIndex[] .rangeMu.Unlock()if {return , true } := buildRangeIndex() .rangeMu.Lock()defer .rangeMu.Unlock()if , := .rangeIndex[]; {return , true } .rangeIndex[] = return , true}// buildRangeIndex collects the column's (value, id) pairs and sorts them// by value then id, so equal-valued runs enumerate in ascending id order.func buildRangeIndex( Column) RangeIndex { := .Len() := make([]int64, 0, ) := make([]uint32, 0, )switch c := .(type) {casedenseI64Col:for , := range { = append(, ) = append(, uint32()) }casesparseI64Col: = append(, .vals...) = append(, .ids...)default:for , := range .Entries() {if , := .I64(); { = append(, ) = append(, ) } } } := make([]int, len())for := range { [] = }slices.SortFunc(, func(, int) int {switch {case [] != []:if [] < [] {return -1 }return1case [] < []:return -1case [] > []:return1 }return0 }) := make([]int64, len()) := make([]uint32, len())for , := range { [], [] = [], [] }returnRangeIndex{vals: , ids: }}// Len is the number of indexed entries (nodes carrying the key).func ( RangeIndex) () int { returnlen(.ids) }// Window is the node ids whose value lies in the interval [lo, hi] with// per-bound inclusivity, as a zero-copy slice ordered by (value, id).// Pass math.MinInt64/math.MaxInt64 with inclusive bounds for a half- or// unbounded interval. An empty or inverted interval is an empty slice.func ( RangeIndex) (, int64, , bool) []uint32 { := .lowerBound(, ) := .upperBound(, )if >= {returnnil }return .ids[:]}// lowerBound is the first slot at or above the lower bound.func ( RangeIndex) ( int64, bool) int {if { , := slices.BinarySearch(.vals, )return }if == math.MaxInt64 {returnlen(.vals) } , := slices.BinarySearch(.vals, +1)return}// upperBound is the slot just past the upper bound.func ( RangeIndex) ( int64, bool) int {if ! { , := slices.BinarySearch(.vals, )return }if == math.MaxInt64 {returnlen(.vals) } , := slices.BinarySearch(.vals, +1)return}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.