func (this *builder) buildCoveringJoinScan(secondaries map[datastore.Index]*indexEntry, node *algebra.KeyspaceTerm, op string) (datastore.Index, expression.Covers, error) { if this.cover == nil { for index, _ := range secondaries { return index, nil, nil } } alias := node.Alias() exprs := this.cover.Expressions() outer: for index, entry := range secondaries { for _, expr := range exprs { if !expr.CoveredBy(alias, entry.keys) { continue outer } } covers := make(expression.Covers, len(entry.keys)) for i, key := range entry.keys { covers[i] = expression.NewCover(key) } return index, covers, nil } for index, _ := range secondaries { return index, nil, nil } return nil, nil, errors.NewNoIndexJoinError(node.Alias(), op) }
func (this *builder) buildScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm, limit expression.Expression) ( secondary plan.Operator, primary *plan.PrimaryScan, err error) { var indexes, hintIndexes, otherIndexes []datastore.Index hints := node.Indexes() if hints != nil { indexes, err = allHints(keyspace, hints) hintIndexes = indexes } else { indexes, err = allIndexes(keyspace) otherIndexes = indexes } if err != nil { return } pred := this.where if pred != nil { dnf := NewDNF() pred = pred.Copy() pred, err = dnf.Map(pred) if err != nil { return } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.Expressions{ expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id", false)), } sargables, er := sargableIndexes(indexes, pred, primaryKey, dnf, formalizer) if er != nil { return nil, nil, er } minimals, er := minimalIndexes(sargables, pred) if er != nil { return nil, nil, er } if len(minimals) > 0 { secondary, err = this.buildSecondaryScan(minimals, node, limit) return secondary, nil, err } } primary, err = this.buildPrimaryScan(keyspace, node, limit, hintIndexes, otherIndexes) return nil, primary, err }
func (this *builder) buildCoveringScan(secondaries map[datastore.Index]*indexEntry, node *algebra.KeyspaceTerm, limit expression.Expression) (plan.Operator, error) { if this.cover == nil { return nil, nil } alias := node.Alias() exprs := this.cover.Expressions() id := expression.NewField( expression.NewMeta(expression.NewIdentifier(node.Alias())), expression.NewFieldName("id", false)) outer: for index, entry := range secondaries { keys := entry.keys if !index.IsPrimary() { // Matches execution.spanScan.RunOnce() keys = append(keys, id) } // Use the first available covering index for _, expr := range exprs { if !expr.CoveredBy(alias, keys) { continue outer } } covers := make(expression.Covers, 0, len(keys)) for _, key := range keys { covers = append(covers, expression.NewCover(key)) } scan := plan.NewIndexScan(index, node, entry.spans, false, limit, covers) this.coveringScan = scan if len(entry.spans) > 1 { // Use UnionScan to de-dup multiple spans return plan.NewUnionScan(scan), nil } return scan, nil } return nil, nil }
func (this *builder) buildJoinScan(keyspace datastore.Keyspace, node *algebra.KeyspaceTerm, op string) ( datastore.Index, expression.Covers, error) { indexes, err := allIndexes(keyspace) if err != nil { return nil, nil, err } var pred expression.Expression pred = expression.NewIsNotNull(node.Keys().Copy()) dnf := NewDNF() pred, err = dnf.Map(pred) if err != nil { return nil, nil, err } subset := pred if this.where != nil { subset = expression.NewAnd(subset, this.where.Copy()) subset, err = dnf.Map(subset) if err != nil { return nil, nil, err } } formalizer := expression.NewFormalizer() formalizer.Keyspace = node.Alias() primaryKey := expression.Expressions{ expression.NewField( expression.NewMeta(expression.NewConstant(node.Alias())), expression.NewFieldName("id", false)), } sargables, err := sargableIndexes(indexes, pred, subset, primaryKey, dnf, formalizer) if err != nil { return nil, nil, err } minimals, err := minimalIndexes(sargables, pred) if err != nil { return nil, nil, err } if len(minimals) == 0 { return nil, nil, errors.NewNoIndexJoinError(node.Alias(), op) } return this.buildCoveringJoinScan(minimals, node, op) }