// Helper function to perform a primary index scan on the given keyspace. Returns a map of // all primary key names. func doPrimaryIndexScan(t *testing.T, b datastore.Keyspace) (m map[string]bool, excp errors.Error) { conn := datastore.NewIndexConnection(&testingContext{t}) m = map[string]bool{} nitems, excp := b.Count() if excp != nil { t.Fatalf("failed to get keyspace count") return } indexers, excp := b.Indexers() if excp != nil { t.Fatalf("failed to retrieve indexers") return } pindexes, excp := indexers[0].PrimaryIndexes() if excp != nil || len(pindexes) < 1 { t.Fatalf("failed to retrieve primary indexes") return } idx := pindexes[0] go idx.ScanEntries(nitems, datastore.UNBOUNDED, nil, conn) for { v, ok := <-conn.EntryChannel() if !ok { // Channel closed => Scan complete return } m[v.PrimaryKey] = true } }
func (this *builder) selectPrimaryScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm) (Operator, error) { indexers, err := keyspace.Indexers() if err != nil { return nil, err } var primary datastore.PrimaryIndex for _, indexer := range indexers { indexes, err := indexer.PrimaryIndexes() if err != nil { return nil, err } for _, index := range indexes { state, _, er := index.State() if er != nil { return nil, er } if state != datastore.ONLINE { primary = index continue } scan := NewPrimaryScan(index, node) return scan, nil } } if primary == nil { return nil, fmt.Errorf( "No primary index on keyspace %s. Use CREATE PRIMARY INDEX to create one.", keyspace.Name()) } return nil, fmt.Errorf("Primary index %s not online.", primary.Name()) }
// Helper function to scan the primary index of given keyspace with given span func doIndexScan(t *testing.T, b datastore.Keyspace, span *datastore.Span) ( e []*datastore.IndexEntry, excp errors.Error) { conn := datastore.NewIndexConnection(&testingContext{t}) e = []*datastore.IndexEntry{} nitems, excp := b.Count() if excp != nil { t.Fatalf("failed to get keyspace count") return } indexers, excp := b.Indexers() if excp != nil { t.Fatalf("failed to retrieve indexers") return } idx, excp := indexers[0].IndexByName("#primary") if excp != nil { t.Fatalf("failed to retrieve primary index") return } go idx.Scan(span, false, nitems, datastore.UNBOUNDED, nil, conn) for { entry, ok := <-conn.EntryChannel() if !ok { return } e = append(e, entry) } return }
func (this *builder) selectScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm) (Operator, error) { if this.where == nil { return this.selectPrimaryScan(keyspace, node) } nnf := planner.NewNNF() where := this.where.Copy() where, err := nnf.Map(where) if err != nil { return nil, err } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id")) indexers, err := keyspace.Indexers() if err != nil { return nil, err } indexes := make([]datastore.Index, 0, len(indexers)*16) primaryIndexes := make(map[datastore.Index]bool, len(indexers)*2) for _, indexer := range indexers { idxs, err := indexer.Indexes() if err != nil { return nil, err } indexes = append(indexes, idxs...) primaryIdxs, err := indexer.PrimaryIndexes() if err != nil { return nil, err } for _, p := range primaryIdxs { primaryIndexes[p] = true } } unfiltered := make(map[datastore.Index]expression.Expression, len(indexes)) filtered := make(map[datastore.Index]expression.Expression, len(indexes)) for _, index := range indexes { state, _, er := index.State() if er != nil { return nil, er } if state != datastore.ONLINE { continue } var key expression.Expression if primaryIndexes[index] { key = primaryKey } else { rangeKey := index.RangeKey() if len(rangeKey) == 0 || rangeKey[0] == nil { // Index not rangeable continue } key := rangeKey[0].Copy() key, err = formalizer.Map(key) if err != nil { return nil, err } key, err = nnf.Map(key) if err != nil { return nil, err } } if !planner.SargableFor(where, key) { // Index not applicable continue } indexCond := index.Condition() if indexCond == nil { unfiltered[index] = key continue } indexCond = indexCond.Copy() indexCond, err = formalizer.Map(indexCond) if err != nil { return nil, err } indexCond, err = nnf.Map(indexCond) if err != nil { return nil, err } if planner.SubsetOf(where, indexCond) { // Index condition satisfies query condition filtered[index] = key break } } var indexMap map[datastore.Index]expression.Expression if len(filtered) > 0 { indexMap = filtered } else if len(unfiltered) > 0 { indexMap = unfiltered } for index, key := range indexMap { spans := planner.SargFor(where, key) var scan Operator scan = NewIndexScan(index, node, spans, false, math.MaxInt64) if len(spans) > 1 { // Use UnionScan to de-dup multiple spans scan = NewUnionScan(scan) } return scan, err } return this.selectPrimaryScan(keyspace, node) }