7
7
8
8
"gopkg.in/src-d/go-mysql-server.v0/sql"
9
9
"gopkg.in/src-d/go-mysql-server.v0/sql/expression"
10
+ "gopkg.in/src-d/go-mysql-server.v0/sql/plan"
10
11
11
12
"gopkg.in/src-d/go-git.v4/plumbing"
12
13
"gopkg.in/src-d/go-git.v4/plumbing/object"
@@ -39,10 +40,7 @@ var BlobsSchema = sql.Schema{
39
40
var _ sql.PushdownProjectionAndFiltersTable = (* blobsTable )(nil )
40
41
41
42
func newBlobsTable () Indexable {
42
- return & indexableTable {
43
- PushdownTable : new (blobsTable ),
44
- buildIterWithSelectors : blobsIterBuilder ,
45
- }
43
+ return new (blobsTable )
46
44
}
47
45
48
46
var _ Table = (* blobsTable )(nil )
@@ -118,6 +116,50 @@ func (r *blobsTable) WithProjectAndFilters(
118
116
return sql .NewSpanIter (span , iter ), nil
119
117
}
120
118
119
+ // IndexKeyValueIter implements the sql.Indexable interface.
120
+ func (* blobsTable ) IndexKeyValueIter (
121
+ ctx * sql.Context ,
122
+ colNames []string ,
123
+ ) (sql.IndexKeyValueIter , error ) {
124
+ s , ok := ctx .Session .(* Session )
125
+ if ! ok || s == nil {
126
+ return nil , ErrInvalidGitbaseSession .New (ctx .Session )
127
+ }
128
+
129
+ return newBlobsKeyValueIter (s .Pool , colNames ), nil
130
+ }
131
+
132
+ // WithProjectFiltersAndIndex implements sql.Indexable interface.
133
+ func (* blobsTable ) WithProjectFiltersAndIndex (
134
+ ctx * sql.Context ,
135
+ columns , filters []sql.Expression ,
136
+ index sql.IndexValueIter ,
137
+ ) (sql.RowIter , error ) {
138
+ span , ctx := ctx .Span ("gitbase.BlobsTable.WithProjectFiltersAndIndex" )
139
+ s , ok := ctx .Session .(* Session )
140
+ if ! ok || s == nil {
141
+ span .Finish ()
142
+ return nil , ErrInvalidGitbaseSession .New (ctx .Session )
143
+ }
144
+
145
+ session , err := getSession (ctx )
146
+ if err != nil {
147
+ return nil , err
148
+ }
149
+
150
+ var iter sql.RowIter = & blobsIndexIter {
151
+ index : index ,
152
+ pool : session .Pool ,
153
+ readContent : shouldReadContent (columns ),
154
+ }
155
+
156
+ if len (filters ) > 0 {
157
+ iter = plan .NewFilterIter (ctx , expression .JoinAnd (filters ... ), iter )
158
+ }
159
+
160
+ return sql .NewSpanIter (span , iter ), nil
161
+ }
162
+
121
163
func blobsIterBuilder (_ * sql.Context , selectors selectors , columns []sql.Expression ) (RowRepoIter , error ) {
122
164
if len (selectors ["blob_hash" ]) == 0 {
123
165
return & blobIter {readContent : shouldReadContent (columns )}, nil
@@ -138,7 +180,6 @@ type blobIter struct {
138
180
repoID string
139
181
iter * object.BlobIter
140
182
readContent bool
141
- lastHash string
142
183
}
143
184
144
185
func (i * blobIter ) NewIterator (repo * Repository ) (RowRepoIter , error ) {
@@ -150,17 +191,11 @@ func (i *blobIter) NewIterator(repo *Repository) (RowRepoIter, error) {
150
191
return & blobIter {repoID : repo .ID , iter : iter , readContent : i .readContent }, nil
151
192
}
152
193
153
- func (i * blobIter ) Repository () string { return i .repoID }
154
-
155
- func (i * blobIter ) LastObject () string { return i .lastHash }
156
-
157
194
func (i * blobIter ) Next () (sql.Row , error ) {
158
195
o , err := i .iter .Next ()
159
196
if err != nil {
160
197
return nil , err
161
198
}
162
-
163
- i .lastHash = o .Hash .String ()
164
199
return blobToRow (i .repoID , o , i .readContent )
165
200
}
166
201
@@ -177,17 +212,12 @@ type blobsByHashIter struct {
177
212
pos int
178
213
hashes []string
179
214
readContent bool
180
- lastHash string
181
215
}
182
216
183
217
func (i * blobsByHashIter ) NewIterator (repo * Repository ) (RowRepoIter , error ) {
184
- return & blobsByHashIter {repo , 0 , i .hashes , i .readContent , "" }, nil
218
+ return & blobsByHashIter {repo , 0 , i .hashes , i .readContent }, nil
185
219
}
186
220
187
- func (i * blobsByHashIter ) Repository () string { return i .repo .ID }
188
-
189
- func (i * blobsByHashIter ) LastObject () string { return i .lastHash }
190
-
191
221
func (i * blobsByHashIter ) Next () (sql.Row , error ) {
192
222
for {
193
223
if i .pos >= len (i .hashes ) {
@@ -205,7 +235,6 @@ func (i *blobsByHashIter) Next() (sql.Row, error) {
205
235
return nil , err
206
236
}
207
237
208
- i .lastHash = hash .String ()
209
238
return blobToRow (i .repo .ID , blob , i .readContent )
210
239
}
211
240
}
@@ -304,3 +333,112 @@ func shouldReadContent(columns []sql.Expression) bool {
304
333
}
305
334
return false
306
335
}
336
+
337
+ type blobIndexKey struct {
338
+ repository string
339
+ packfile string
340
+ offset int64
341
+ }
342
+
343
+ type blobsKeyValueIter struct {
344
+ iter * objectIter
345
+ columns []string
346
+ }
347
+
348
+ func newBlobsKeyValueIter (pool * RepositoryPool , columns []string ) * blobsKeyValueIter {
349
+ return & blobsKeyValueIter {
350
+ iter : newObjectIter (pool , plumbing .BlobObject ),
351
+ columns : columns ,
352
+ }
353
+ }
354
+
355
+ func (i * blobsKeyValueIter ) Next () ([]interface {}, []byte , error ) {
356
+ obj , err := i .iter .Next ()
357
+ if err != nil {
358
+ return nil , nil , err
359
+ }
360
+
361
+ key , err := encodeIndexKey (blobIndexKey {
362
+ repository : obj .RepositoryID ,
363
+ packfile : obj .Packfile .String (),
364
+ offset : int64 (obj .Offset ),
365
+ })
366
+ if err != nil {
367
+ return nil , nil , err
368
+ }
369
+
370
+ blob , ok := obj .Object .(* object.Blob )
371
+ if ! ok {
372
+ ErrInvalidObjectType .New (obj .Object , "*object.Blob" )
373
+ }
374
+
375
+ row , err := blobToRow (obj .RepositoryID , blob , stringContains (i .columns , "content" ))
376
+ if err != nil {
377
+ return nil , nil , err
378
+ }
379
+
380
+ values , err := rowIndexValues (row , i .columns , BlobsSchema )
381
+ if err != nil {
382
+ return nil , nil , err
383
+ }
384
+
385
+ return values , key , nil
386
+ }
387
+
388
+ func (i * blobsKeyValueIter ) Close () error { return i .iter .Close () }
389
+
390
+ type blobsIndexIter struct {
391
+ index sql.IndexValueIter
392
+ pool * RepositoryPool
393
+ decoder * objectDecoder
394
+ readContent bool
395
+ }
396
+
397
+ func (i * blobsIndexIter ) Next () (sql.Row , error ) {
398
+ data , err := i .index .Next ()
399
+ if err != nil {
400
+ return nil , err
401
+ }
402
+
403
+ var key blobIndexKey
404
+ if err := decodeIndexKey (data , & key ); err != nil {
405
+ return nil , err
406
+ }
407
+
408
+ packfile := plumbing .NewHash (key .packfile )
409
+ if i .decoder == nil || ! i .decoder .equals (key .repository , packfile ) {
410
+ if i .decoder != nil {
411
+ if err := i .decoder .close (); err != nil {
412
+ return nil , err
413
+ }
414
+ }
415
+
416
+ i .decoder , err = newObjectDecoder (i .pool .repositories [key .repository ], packfile )
417
+ if err != nil {
418
+ return nil , err
419
+ }
420
+ }
421
+
422
+ obj , err := i .decoder .get (key .offset )
423
+ if err != nil {
424
+ return nil , err
425
+ }
426
+
427
+ blob , ok := obj .(* object.Blob )
428
+ if ! ok {
429
+ return nil , ErrInvalidObjectType .New (obj , "*object.Blob" )
430
+ }
431
+
432
+ return blobToRow (key .repository , blob , i .readContent )
433
+ }
434
+
435
+ func (i * blobsIndexIter ) Close () error {
436
+ if i .decoder != nil {
437
+ if err := i .decoder .close (); err != nil {
438
+ _ = i .index .Close ()
439
+ return err
440
+ }
441
+ }
442
+
443
+ return i .index .Close ()
444
+ }
0 commit comments