/* Fully qualify identifiers for each of the constituent fields in the merge source statement. */ func (this *MergeSource) Formalize() (f *expression.Formalizer, err error) { if this.from != nil { _, err = this.from.Formalize(expression.NewFormalizer()) if err != nil { return } } if this.query != nil { err = this.query.Formalize() if err != nil { return } } keyspace := this.Alias() if keyspace == "" { return nil, fmt.Errorf("MergeSource missing alias.") } f = expression.NewFormalizer() f.Keyspace = keyspace f.Allowed.SetField(keyspace, keyspace) return }
/* Qualify all identifiers for the parent expression. Checks for duplicate aliases. */ func (this *SubqueryTerm) Formalize(parent *expression.Formalizer) (f *expression.Formalizer, err error) { err = this.subquery.Formalize() if err != nil { return } alias := this.Alias() if alias == "" { err = errors.NewError(nil, "FROM term must have a name or alias.") return } _, ok := parent.Allowed.Field(alias) if ok { err = errors.NewError(nil, fmt.Sprintf("Duplicate subquery alias %s.", alias)) return nil, err } allowed := value.NewScopeValue(make(map[string]interface{}), parent.Allowed) allowed.SetField(alias, alias) f = expression.NewFormalizer() f.Keyspace = alias f.Allowed = allowed return }
/* Qualify all identifiers for the parent expression. Checks for duplicate aliases. */ func (this *KeyspaceTerm) Formalize(parent *expression.Formalizer) (f *expression.Formalizer, err error) { keyspace := this.Alias() if keyspace == "" { err = errors.NewError(nil, "FROM term must have a name or alias.") return } if this.keys != nil { _, err = this.keys.Accept(parent) if err != nil { return } } _, ok := parent.Allowed.Field(keyspace) if ok { err = errors.NewError(nil, fmt.Sprintf("Duplicate subquery alias %s.", keyspace)) return nil, err } allowed := value.NewScopeValue(make(map[string]interface{}), parent.Allowed) allowed.SetField(keyspace, keyspace) f = expression.NewFormalizer() f.Keyspace = keyspace f.Allowed = allowed return }
/* Fully qualify identifiers for each of the constituent clauses in the upsert statement. */ func (this *Upsert) Formalize() (err error) { if this.values != nil { f := expression.NewFormalizer() err = this.values.MapExpressions(f) if err != nil { return } } if this.query != nil { err = this.query.Formalize() if err != nil { return } } f, err := this.keyspace.Formalize() if err != nil { return err } if this.returning != nil { _, err = this.returning.Formalize(f) } return }
/* This method fully qualifies the identifiers for each term in the result expression. It disallows duplicate alias and exempts explicit aliases from being formalized. */ func (this *Projection) Formalize(in *expression.Formalizer) (f *expression.Formalizer, err error) { // Disallow duplicate aliases aliases := make(map[string]bool, len(this.terms)) for _, term := range this.terms { if term.alias == "" { continue } if aliases[term.alias] { return nil, fmt.Errorf("Duplicate result alias %s.", term.alias) } aliases[term.alias] = true } f = expression.NewFormalizer() f.Allowed = in.Allowed.Copy() f.Keyspace = in.Keyspace err = this.MapExpressions(f) if err != nil { return } // Exempt explicit aliases from being formalized for _, term := range this.terms { if term.as != "" { f.Allowed.SetField(term.as, term.as) } } return }
/* Fully qualify identifiers for each of the constituent clauses in the delete statement. */ func (this *Delete) Formalize() (err error) { f, err := this.keyspace.Formalize() if err != nil { return err } empty := expression.NewFormalizer() if this.keys != nil { _, err = this.keys.Accept(empty) if err != nil { return } } if this.where != nil { this.where, err = f.Map(this.where) if err != nil { return } } if this.limit != nil { _, err = this.limit.Accept(empty) if err != nil { return } } if this.returning != nil { _, err = this.returning.Formalize(f) } return }
/* Fully qualify identifiers for each of the constituent clauses in the merge statement. */ func (this *Merge) Formalize() (err error) { kf, err := this.keyspace.Formalize() if err != nil { return err } sf, err := this.source.Formalize() if err != nil { return err } this.key, err = sf.Map(this.key) if err != nil { return err } if kf.Keyspace == sf.Keyspace { return fmt.Errorf("Duplicate alias %s.", kf.Keyspace) } f := expression.NewFormalizer() f.Allowed.SetField(kf.Keyspace, kf.Keyspace) f.Allowed.SetField(sf.Keyspace, sf.Keyspace) err = this.actions.MapExpressions(f) if err != nil { return } if this.limit != nil { _, err = this.limit.Accept(expression.NewFormalizer()) if err != nil { return } } if this.returning != nil { _, err = this.returning.Formalize(kf) } return }
/* Fully qualifies the identifiers in the first and second sub-result using the input parent. */ func (this *setOp) Formalize(parent *expression.Formalizer) (f *expression.Formalizer, err error) { _, err = this.first.Formalize(parent) if err != nil { return nil, err } _, err = this.second.Formalize(parent) if err != nil { return nil, err } return expression.NewFormalizer(), nil }
/* Qualify identifiers for the keyspace. It also makes sure that the keyspace term contains a name or alias. */ func (this *KeyspaceRef) Formalize() (f *expression.Formalizer, err error) { keyspace := this.Alias() if keyspace == "" { err = errors.NewError(nil, "Keyspace term must have a name or alias.") return } allowed := value.NewValue(make(map[string]interface{})) allowed.SetField(keyspace, keyspace) f = expression.NewFormalizer() f.Keyspace = keyspace f.Allowed = allowed return }
/* This method calls FormalizeSubquery to qualify all the children of the query, and returns an error if any. */ func (this *Select) Formalize() (err error) { return this.FormalizeSubquery(expression.NewFormalizer()) }
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) }