-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.go
94 lines (80 loc) · 2.1 KB
/
index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package edb
import (
"bytes"
"fmt"
"reflect"
"sort"
)
type IndexRow struct {
IndexOrd uint64
Index *Index
KeyRaw []byte
KeyBuf []byte
ValueRaw []byte
ValueBuf []byte
}
type IndexBuilder struct {
ts *tableState
rows indexRows
rowsBuf indexRows
key []byte
}
func makeIndexBuilder(ts *tableState, keyRaw []byte) IndexBuilder {
indexRowsBuf := indexRowsPool.Get().(indexRows)
return IndexBuilder{
ts: ts,
rows: indexRowsBuf,
rowsBuf: indexRowsBuf,
key: keyRaw,
}
}
func (b *IndexBuilder) Add(idx *Index, value any) *IndexRow {
valueVal := reflect.ValueOf(value)
if idx.table != b.ts.table {
panic(fmt.Errorf("%s: attempted to add entry to another table's index %s", b.ts.table.Name(), idx.FullName()))
}
if at, et := valueVal.Type(), idx.keyType(); at != et {
panic(fmt.Errorf("%s: attempted to add index entry with incorrect type %v, expected %v", idx.FullName(), at, et))
}
keyBuf := keyBytesPool.Get().([]byte)
keyEnc := flatEncoder{buf: keyBuf}
idx.keyEnc.encodeInto(&keyEnc, valueVal)
var valueRaw []byte
var valueBuf []byte
if idx.isUnique {
valueBuf = indexValueBytesPool.Get().([]byte)
valueEnc := flatEncoder{buf: valueBuf}
valueEnc.begin()
valueEnc.append(b.key)
valueRaw = valueEnc.finalize()
} else {
valueRaw = emptyIndexValue
keyEnc.begin()
keyEnc.buf = appendRaw(keyEnc.buf, b.key)
}
indexOrd := b.ts.indexOrdinal(idx)
b.rows = append(b.rows, IndexRow{indexOrd, idx, keyEnc.finalize(), keyBuf, valueRaw, valueBuf})
return &b.rows[len(b.rows)-1]
}
func (b *IndexBuilder) release(tx *Tx) {
for _, row := range b.rows {
keyBytesPool.Put(row.KeyBuf[:0])
if row.ValueBuf != nil {
tx.addIndexValueBuf(row.ValueBuf)
}
}
indexRowsPool.Put(b.rowsBuf[:0])
}
func (b *IndexBuilder) finalize() {
sort.Sort(b.rows)
}
type indexRows []IndexRow
func (a indexRows) Len() int { return len(a) }
func (a indexRows) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a indexRows) Less(i, j int) bool {
lp, rp := a[i].Index.pos, a[j].Index.pos
if lp != rp {
return lp < rp
}
return bytes.Compare(a[i].KeyRaw, a[j].KeyRaw) < 0
}