-
Notifications
You must be signed in to change notification settings - Fork 19
/
kvschema.go
163 lines (150 loc) · 4.62 KB
/
kvschema.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Code generated by "kvschema"; DO NOT EDIT.
package docs
import (
"github.com/google/note-maps/kv"
)
// Txn provides entities, components, and indexes backed by a key-value store.
type Txn struct{ kv.Partitioned }
func New(t kv.Txn) Txn { return Txn{kv.Partitioned{t, 0}} }
// SetDocument sets the Document associated with e to v.
//
// Corresponding indexes are updated.
func (s Txn) SetDocument(e kv.Entity, v *Document) error {
key := make(kv.Prefix, 8+2+8)
s.Partition.EncodeAt(key)
DocumentPrefix.EncodeAt(key[8:])
e.EncodeAt(key[10:])
var old Document
if err := s.Get(key, old.Decode); err != nil {
return err
}
if err := s.Set(key, v.Encode()); err != nil {
return err
}
// A prefix buffer for all index keys.
prefix := kv.ConcatByteSlices(key, kv.Component(0).Encode())
kv.Entity(0).EncodeAt(prefix[10:])
var es kv.EntitySlice
// Update Title index
TitlePrefix.EncodeAt(prefix[18:])
for _, iv := range old.IndexTitle() {
k := kv.ConcatByteSlices(prefix, iv.Encode())
if err := s.Get(k, es.Decode); err != nil {
return err
}
if es.Remove(e) {
if err := s.Set(k, es.Encode()); err != nil {
return err
}
}
}
for _, iv := range v.IndexTitle() {
k := kv.ConcatByteSlices(prefix, iv.Encode())
if err := s.Get(k, es.Decode); err != nil {
return err
}
if es.Insert(e) {
if err := s.Set(k, es.Encode()); err != nil {
return err
}
}
}
return nil
}
// DeleteDocument deletes the Document associated with e.
//
// Corresponding indexes are updated.
func (s Txn) DeleteDocument(e kv.Entity) error {
key := make(kv.Prefix, 8+2+8)
s.Partition.EncodeAt(key)
DocumentPrefix.EncodeAt(key[8:])
e.EncodeAt(key[10:])
var old Document
if err := s.Get(key, old.Decode); err != nil {
return err
}
if err := s.Delete(key); err != nil {
return err
}
prefix := kv.ConcatByteSlices(key, kv.Component(0).Encode())
kv.Entity(0).EncodeAt(prefix[10:])
var es kv.EntitySlice
// Update Title index
TitlePrefix.EncodeAt(prefix[18:])
for _, iv := range old.IndexTitle() {
k := kv.ConcatByteSlices(prefix, iv.Encode())
if err := s.Get(k, es.Decode); err != nil {
return err
}
if es.Remove(e) {
if err := s.Set(k, es.Encode()); err != nil {
return err
}
}
}
return nil
}
// GetDocument returns the Document associated with e.
//
// If no Document has been explicitly set for e, and GetDocument will return
// the result of decoding a Document from an empty slice of bytes.
func (s Txn) GetDocument(e kv.Entity) (Document, error) {
var v Document
vs, err := s.GetDocumentSlice([]kv.Entity{e})
if len(vs) >= 1 {
v = vs[0]
}
return v, err
}
// GetDocumentSlice returns a Document for each entity in es.
//
// If no Document has been explicitly set for an entity, and the result will
// be a Document that has been decoded from an empty slice of bytes.
func (s Txn) GetDocumentSlice(es []kv.Entity) ([]Document, error) {
result := make([]Document, len(es))
key := make(kv.Prefix, 8+2+8)
s.Partition.EncodeAt(key)
DocumentPrefix.EncodeAt(key[8:])
for i, e := range es {
e.EncodeAt(key[10:])
err := s.Get(key, (&result[i]).Decode)
if err != nil {
return nil, err
}
}
return result, nil
}
// AllDocumentEntities returns the first n entities that have a Document, beginning
// with the first entity greater than or equal to *start.
//
// A nil start value will be interpreted as a pointer to zero.
//
// A value of n less than or equal to zero will be interpretted as the largest
// possible value.
func (s Txn) AllDocumentEntities(start *kv.Entity, n int) (es []kv.Entity, err error) {
return s.AllComponentEntities(DocumentPrefix, start, n)
}
// EntitiesMatchingDocumentTitle returns entities with Document values that return a matching kv.String from their IndexTitle method.
//
// The returned EntitySlice is already sorted.
func (s Txn) EntitiesMatchingDocumentTitle(v kv.String) (kv.EntitySlice, error) {
key := make(kv.Prefix, 8+2+8+2)
s.Partition.EncodeAt(key)
DocumentPrefix.EncodeAt(key[8:])
kv.Entity(0).EncodeAt(key[10:])
TitlePrefix.EncodeAt(key[18:])
key = append(key, v.Encode()...)
var es kv.EntitySlice
return es, s.Get(key, es.Decode)
}
// EntitiesByDocumentTitle returns entities with
// Document values ordered by the kv.String values from their
// IndexTitle method.
//
// Reading begins at cursor, and ends when the length of the returned Entity
// slice is less than n. When reading is not complete, cursor is updated such
// that using it in a subequent call to ByTitle would return next n
// entities.
func (s Txn) EntitiesByDocumentTitle(cursor *kv.IndexCursor, n int) (es []kv.Entity, err error) {
return s.EntitiesByComponentIndex(DocumentPrefix, TitlePrefix, cursor, n)
}