@@ -19,11 +19,12 @@ func WrapTxnDatastore(child ds.TxnDatastore, t KeyTransform) *TxnDatastore {
19
19
panic ("child (ds.TxnDatastore) is nil" )
20
20
}
21
21
22
- return & TxnDatastore {child : child , KeyTransform : t }
22
+ return & TxnDatastore {ds : Wrap ( child , t ), child : child , KeyTransform : t }
23
23
}
24
24
25
25
// TxnDatastore keeps a KeyTransform function
26
26
type TxnDatastore struct {
27
+ ds * Datastore
27
28
child ds.TxnDatastore
28
29
29
30
KeyTransform
@@ -45,205 +46,64 @@ func (d *TxnDatastore) Children() []ds.Datastore {
45
46
46
47
// Put stores the given value, transforming the key first.
47
48
func (d * TxnDatastore ) Put (ctx context.Context , key ds.Key , value []byte ) (err error ) {
48
- return d .child .Put (ctx , d .ConvertKey (key ), value )
49
+ return d .ds .Put (ctx , d .ConvertKey (key ), value )
49
50
}
50
51
51
52
// Sync implements Datastore.Sync
52
53
func (d * TxnDatastore ) Sync (ctx context.Context , prefix ds.Key ) error {
53
- return d .child .Sync (ctx , d .ConvertKey (prefix ))
54
+ return d .ds .Sync (ctx , d .ConvertKey (prefix ))
54
55
}
55
56
56
57
// Get returns the value for given key, transforming the key first.
57
58
func (d * TxnDatastore ) Get (ctx context.Context , key ds.Key ) (value []byte , err error ) {
58
- return d .child .Get (ctx , d .ConvertKey (key ))
59
+ return d .ds .Get (ctx , d .ConvertKey (key ))
59
60
}
60
61
61
62
// Has returns whether the datastore has a value for a given key, transforming
62
63
// the key first.
63
64
func (d * TxnDatastore ) Has (ctx context.Context , key ds.Key ) (exists bool , err error ) {
64
- return d .child .Has (ctx , d .ConvertKey (key ))
65
+ return d .ds .Has (ctx , d .ConvertKey (key ))
65
66
}
66
67
67
68
// GetSize returns the size of the value named by the given key, transforming
68
69
// the key first.
69
70
func (d * TxnDatastore ) GetSize (ctx context.Context , key ds.Key ) (size int , err error ) {
70
- return d .child .GetSize (ctx , d .ConvertKey (key ))
71
+ return d .ds .GetSize (ctx , d .ConvertKey (key ))
71
72
}
72
73
73
74
// Delete removes the value for given key
74
75
func (d * TxnDatastore ) Delete (ctx context.Context , key ds.Key ) (err error ) {
75
- return d .child .Delete (ctx , d .ConvertKey (key ))
76
+ return d .ds .Delete (ctx , d .ConvertKey (key ))
76
77
}
77
78
78
79
// Query implements Query, inverting keys on the way back out.
79
80
func (d * TxnDatastore ) Query (ctx context.Context , q dsq.Query ) (dsq.Results , error ) {
80
- nq , cq := d .prepareQuery (q )
81
-
82
- cqr , err := d .child .Query (ctx , cq )
83
- if err != nil {
84
- return nil , err
85
- }
86
-
87
- qr := dsq .ResultsFromIterator (q , dsq.Iterator {
88
- Next : func () (dsq.Result , bool ) {
89
- r , ok := cqr .NextSync ()
90
- if ! ok {
91
- return r , false
92
- }
93
- if r .Error == nil {
94
- r .Entry .Key = d .InvertKey (ds .RawKey (r .Entry .Key )).String ()
95
- }
96
- return r , true
97
- },
98
- Close : func () error {
99
- return cqr .Close ()
100
- },
101
- })
102
- return dsq .NaiveQueryApply (nq , qr ), nil
103
- }
104
-
105
- // Split the query into a child query and a naive query. That way, we can make
106
- // the child datastore do as much work as possible.
107
- func (d * TxnDatastore ) prepareQuery (q dsq.Query ) (naive , child dsq.Query ) {
108
-
109
- // First, put everything in the child query. Then, start taking things
110
- // out.
111
- child = q
112
-
113
- // Always let the child handle the key prefix.
114
- child .Prefix = d .ConvertKey (ds .NewKey (child .Prefix )).String ()
115
-
116
- // Check if the key transform is order-preserving so we can use the
117
- // child datastore's built-in ordering.
118
- orderPreserving := false
119
- switch d .KeyTransform .(type ) {
120
- case PrefixTransform , * PrefixTransform :
121
- orderPreserving = true
122
- }
123
-
124
- // Try to let the child handle ordering.
125
- orders:
126
- for i , o := range child .Orders {
127
- switch o .(type ) {
128
- case dsq.OrderByValue , * dsq.OrderByValue ,
129
- dsq.OrderByValueDescending , * dsq.OrderByValueDescending :
130
- // Key doesn't matter.
131
- continue
132
- case dsq.OrderByKey , * dsq.OrderByKey ,
133
- dsq.OrderByKeyDescending , * dsq.OrderByKeyDescending :
134
- // if the key transform preserves order, we can delegate
135
- // to the child datastore.
136
- if orderPreserving {
137
- // When sorting, we compare with the first
138
- // Order, then, if equal, we compare with the
139
- // second Order, etc. However, keys are _unique_
140
- // so we'll never apply any additional orders
141
- // after ordering by key.
142
- child .Orders = child .Orders [:i + 1 ]
143
- break orders
144
- }
145
- }
146
-
147
- // Can't handle this order under transform, punt it to a naive
148
- // ordering.
149
- naive .Orders = q .Orders
150
- child .Orders = nil
151
- naive .Offset = q .Offset
152
- child .Offset = 0
153
- naive .Limit = q .Limit
154
- child .Limit = 0
155
- break
156
- }
157
-
158
- // Try to let the child handle the filters.
159
-
160
- // don't modify the original filters.
161
- child .Filters = append ([]dsq.Filter (nil ), child .Filters ... )
162
-
163
- for i , f := range child .Filters {
164
- switch f := f .(type ) {
165
- case dsq.FilterValueCompare , * dsq.FilterValueCompare :
166
- continue
167
- case dsq.FilterKeyCompare :
168
- child .Filters [i ] = dsq.FilterKeyCompare {
169
- Op : f .Op ,
170
- Key : d .ConvertKey (ds .NewKey (f .Key )).String (),
171
- }
172
- continue
173
- case * dsq.FilterKeyCompare :
174
- child .Filters [i ] = & dsq.FilterKeyCompare {
175
- Op : f .Op ,
176
- Key : d .ConvertKey (ds .NewKey (f .Key )).String (),
177
- }
178
- continue
179
- case dsq.FilterKeyPrefix :
180
- child .Filters [i ] = dsq.FilterKeyPrefix {
181
- Prefix : d .ConvertKey (ds .NewKey (f .Prefix )).String (),
182
- }
183
- continue
184
- case * dsq.FilterKeyPrefix :
185
- child .Filters [i ] = & dsq.FilterKeyPrefix {
186
- Prefix : d .ConvertKey (ds .NewKey (f .Prefix )).String (),
187
- }
188
- continue
189
- }
190
-
191
- // Not a known filter, defer to the naive implementation.
192
- naive .Filters = q .Filters
193
- child .Filters = nil
194
- naive .Offset = q .Offset
195
- child .Offset = 0
196
- naive .Limit = q .Limit
197
- child .Limit = 0
198
- break
199
- }
200
- return
81
+ return d .ds .Query (ctx , q )
201
82
}
202
83
203
84
func (d * TxnDatastore ) Close () error {
204
- return d .child .Close ()
85
+ return d .ds .Close ()
205
86
}
206
87
207
88
// DiskUsage implements the PersistentTxnDatastore interface.
208
89
func (d * TxnDatastore ) DiskUsage (ctx context.Context ) (uint64 , error ) {
209
- return ds .DiskUsage (ctx , d . child )
90
+ return d . ds .DiskUsage (ctx )
210
91
}
211
92
212
93
func (d * TxnDatastore ) Batch (ctx context.Context ) (ds.Batch , error ) {
213
- bds , ok := d .child .(ds.Batching )
214
- if ! ok {
215
- return nil , ds .ErrBatchUnsupported
216
- }
217
-
218
- childbatch , err := bds .Batch (ctx )
219
- if err != nil {
220
- return nil , err
221
- }
222
- return & transformBatch {
223
- dst : childbatch ,
224
- f : d .ConvertKey ,
225
- }, nil
94
+ return d .ds .Batch (ctx )
226
95
}
227
96
228
97
func (d * TxnDatastore ) Check (ctx context.Context ) error {
229
- if c , ok := d .child .(ds.CheckedDatastore ); ok {
230
- return c .Check (ctx )
231
- }
232
- return nil
98
+ return d .ds .Check (ctx )
233
99
}
234
100
235
101
func (d * TxnDatastore ) Scrub (ctx context.Context ) error {
236
- if c , ok := d .child .(ds.ScrubbedDatastore ); ok {
237
- return c .Scrub (ctx )
238
- }
239
- return nil
102
+ return d .ds .Scrub (ctx )
240
103
}
241
104
242
105
func (d * TxnDatastore ) CollectGarbage (ctx context.Context ) error {
243
- if c , ok := d .child .(ds.GCDatastore ); ok {
244
- return c .CollectGarbage (ctx )
245
- }
246
- return nil
106
+ return d .ds .CollectGarbage (ctx )
247
107
}
248
108
249
109
func (d * TxnDatastore ) NewTransaction (ctx context.Context , readOnly bool ) (ds.Txn , error ) {
0 commit comments