/* 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 } err = this.MapExpressions(in) if err != nil { return } if len(aliases) > 0 { f = in.Copy() } else { f = in } // Exempt explicit aliases from being formalized for _, term := range this.terms { if term.as != "" { f.Allowed().SetField(term.as, term.as) } } return }
func sargableIndexes(indexes []datastore.Index, pred expression.Expression, primaryKey expression.Expressions, dnf *DNF, formalizer *expression.Formalizer) ( map[datastore.Index]*indexEntry, error) { var err error var keys expression.Expressions sargables := make(map[datastore.Index]*indexEntry, len(indexes)) for _, index := range indexes { if index.IsPrimary() { keys = primaryKey } else { keys = index.RangeKey() keys = keys.Copy() for i, key := range keys { key = key.Copy() key, err = formalizer.Map(key) if err != nil { return nil, err } key, err = dnf.Map(key) if err != nil { return nil, err } keys[i] = key } } cond := index.Condition() if cond != nil { cond = cond.Copy() cond, err = formalizer.Map(cond) if err != nil { return nil, err } cond, err = dnf.Map(cond) if err != nil { return nil, err } if !SubsetOf(pred, cond) { continue } } n := SargableFor(pred, keys) if n > 0 { sargables[index] = &indexEntry{keys, keys[0:n], cond, nil} } } return sargables, nil }
/* This method qualifies identifiers for all the constituent clauses, namely the subresult, order, limit and offset within a subquery. For the subresult of the subquery, call Formalize, for the order by clause call MapExpressions, for limit and offset call Accept. */ func (this *Select) FormalizeSubquery(parent *expression.Formalizer) error { f, err := this.subresult.Formalize(parent) if err != nil { return err } this.correlated = this.subresult.IsCorrelated() if this.order != nil { err = this.order.MapExpressions(f) if err != nil { return err } if !this.correlated { // Determine if this is a correlated subquery immediate := f.Allowed.GetValue().Fields() for ident, _ := range f.Identifiers { if _, ok := immediate[ident]; !ok { this.correlated = true break } } } } if this.limit == nil && this.offset == nil { return err } if !this.correlated { prevIdentifiers := parent.Identifiers defer parent.SetIdentifiers(prevIdentifiers) parent.SetIdentifiers(make(map[string]bool)) } if this.limit != nil { _, err = this.limit.Accept(parent) if err != nil { return err } } if this.offset != nil { _, err = this.offset.Accept(parent) if err != nil { return err } } if !this.correlated { this.correlated = len(parent.Identifiers) > 0 } return err }
/* 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.NewNoTermNameError("FROM", "plan.subquery.requires_name_or_alias") return } _, ok := parent.Allowed().Field(alias) if ok { err = errors.NewDuplicateAliasError("subquery", alias, "plan.subquery.duplicate_alias") return nil, err } f = expression.NewFormalizer(alias, parent) return }
/* This method qualifies identifiers for all the constituent clauses, namely the by, letting and having expressions by mapping them. */ func (this *Group) Formalize(f *expression.Formalizer) (*expression.Formalizer, error) { var err error if this.by != nil { for i, b := range this.by { this.by[i], err = f.Map(b) if err != nil { return nil, err } } } if this.letting != nil { _, err = f.PushBindings(this.letting) if err != nil { return nil, err } } if this.having != nil { this.having, err = f.Map(this.having) if err != nil { return nil, err } } return f, nil }
/* Qualify all identifiers for the parent expression. Checks is a nest alias exists and if it is a duplicate alias. */ func (this *IndexNest) Formalize(parent *expression.Formalizer) (f *expression.Formalizer, err error) { f, err = this.left.Formalize(parent) if err != nil { return } _, ok := f.Allowed.Field(this.keyFor) if !ok { err = errors.NewUnknownForError("NEST", this.keyFor, "plan.nest.unknown_for") return nil, err } alias := this.Alias() if alias == "" { err = errors.NewNoTermNameError("NEST", "plan.nest.requires_name_or_alias") return nil, err } _, ok = f.Allowed.Field(alias) if ok { err = errors.NewDuplicateAliasError("NEST", alias, "plan.nest.duplicate_alias") return nil, err } f.Allowed.SetField(alias, alias) f.Keyspace = "" var p *expression.Formalizer if parent != nil { p = parent.Copy() } else { p = expression.NewFormalizer() } p.Allowed.SetField(alias, alias) this.right.keys, err = p.Map(this.right.keys) 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.NewNoTermNameError("FROM", "plan.keyspace.requires_name_or_alias") return } f = expression.NewFormalizer("", parent) if this.keys != nil { _, err = this.keys.Accept(f) if err != nil { return } } _, ok := parent.Allowed().Field(keyspace) if ok { err = errors.NewDuplicateAliasError("subquery", keyspace, "plan.keyspace.duplicate_alias") return nil, err } f.SetKeyspace(keyspace) return }
/* Fully qualify identifiers for the update-for clause, the path and value expressions in the SET clause. */ func (this *SetTerm) Formalize(f *expression.Formalizer) (err error) { if this.updateFor != nil { sv, err := f.PushBindings(this.updateFor.bindings) if err != nil { return err } defer f.PopBindings(sv) } path, err := f.Map(this.path) if err != nil { return err } this.path = path.(expression.Path) this.value, err = f.Map(this.value) return }