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 }
// inorder traversal of the AST to get JS expression out of it func (this *JsStatement) Visit(e ast.Expression) (ast.Expression, error) { switch expr := e.(type) { case *ast.DotMemberOperator: if this.js.Len() == 0 { this.js.WriteString("doc.") } _, err := expr.Left.Accept(this) if err != nil { return nil, err } this.js.WriteString(".") _, err = expr.Right.Accept(this) if err != nil { return nil, err } case *ast.BracketMemberOperator: if this.js.Len() == 0 { this.js.WriteString("doc.") } _, err := expr.Left.Accept(this) if err != nil { return nil, err } this.js.WriteString("[") _, err = expr.Right.Accept(this) if err != nil { return nil, err } this.js.WriteString("]") case *ast.Property: if this.js.Len() == 0 { this.js.WriteString("doc.") } this.js.WriteString(expr.Path) case *ast.LiteralNumber: this.js.WriteString(fmt.Sprintf("%v", expr.Val)) case *ast.LiteralString: this.js.WriteString(expr.Val) default: return e, errors.New("Expression is not supported by indexing currently: " + e.String()) } return e, nil }
func (this *BaseOperator) Evaluate(e ast.Expression, item *dparval.Value) (*dparval.Value, error) { // first ensure the query is avaliable item.SetAttachment("query", this.query) return e.Evaluate(item) }
func (this *ExpressionSargable) evaluateConstant(e ast.Expression) (*dparval.Value, error) { return e.Evaluate(dparval.NewValue(map[string]interface{}{})) }