/* Constrain the WHERE condition to reflect the aggregate query. For example: SELECT AVG(v) FROM widget w; is rewritten as: SELECT AVG(v) FROM widget w WHERE v IS NOT NULL; This enables the query to use an index on v. */ func constrainAggregate(cond expression.Expression, aggs map[string]algebra.Aggregate) expression.Expression { var first expression.Expression for _, agg := range aggs { if first == nil { first = agg.Operand() if first == nil { return cond } continue } op := agg.Operand() if op == nil || !first.EquivalentTo(op) { return cond } } if first == nil { return cond } var constraint expression.Expression = expression.NewIsNotNull(first) if cond != nil { constraint = expression.NewAnd(cond, constraint) } return constraint }
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) }