func (this *ExpressionSargable) isConstant(e ast.Expression) bool { _, err := e.Accept(this.constantChecker) if err == nil { return true } return false }
func (this *ExpressionSargable) matchesIndex(e ast.Expression) bool { _, err := e.Accept(this.equivalenceChecker) if err == nil { return true } return false }
func CanIUseThisIndexForThisWhereClause(index catalog.RangeIndex, where ast.Expression, bucket string) (bool, plan.ScanRanges, ast.Expression, error) { // convert the index key to formal notation indexKeyFormal, err := IndexKeyInFormalNotation(index.Key(), bucket) if err != nil { return false, nil, nil, err } // put the where clause into conjunctive normal form ennf := ast.NewExpressionNNF() whereNNF, err := where.Accept(ennf) if err != nil { return false, nil, nil, err } ecnf := ast.NewExpressionCNF() whereCNF, err := whereNNF.Accept(ecnf) if err != nil { return false, nil, nil, err } switch whereCNF := whereCNF.(type) { case *ast.AndOperator: // this is an and, we can try to satisfy individual operands found := false rranges := plan.ScanRanges{} for _, oper := range whereCNF.Operands { // see if the where clause expression is sargable with respect to the index key es := NewExpressionSargable(indexKeyFormal[0]) oper.Accept(es) if es.IsSargable() { found = true for _, ran := range es.ScanRanges() { rranges = MergeRanges(rranges, ran) clog.To(planner.CHANNEL, "now ranges are: %v", rranges) } } } if found { return true, rranges, nil, nil } default: // not an and, we must satisfy the whole expression // see if the where clause expression is sargable with respect to the index key es := NewExpressionSargable(indexKeyFormal[0]) whereCNF.Accept(es) if es.IsSargable() { return true, es.ScanRanges(), nil, nil } } // cannot use this index return false, nil, nil, nil }