// applyConstraints applies the constraints on values specified by constraints // to an expression, simplifying the expression where possible. For example, if // the expression is "a = 1" and the constraint is "a = 1", the expression can // be simplified to "true". If the expression is "a = 1 AND b > 2" and the // constraint is "a = 1", the expression is simplified to "b > 2". // // Note that applyConstraints currently only handles simple cases. func applyIndexConstraints( typedExpr parser.TypedExpr, constraints orIndexConstraints, ) parser.TypedExpr { if len(constraints) != 1 { // We only support simplifying the expressions if there aren't multiple // disjunctions (top-level OR branches). return typedExpr } v := &applyConstraintsVisitor{} expr := typedExpr.(parser.Expr) for _, c := range constraints[0] { v.constraint = c expr, _ = parser.WalkExpr(v, expr) // We can only continue to apply the constraints if the constraints we have // applied so far are equality constraints. There are two cases to // consider: the first is that both the start and end constraints are // equality. if c.start == c.end { if c.start.Operator == parser.EQ { continue } // The second case is that both the start and end constraint are an IN // operator with only a single value. if c.start.Operator == parser.In && len(*c.start.Right.(*parser.DTuple)) == 1 { continue } } break } if expr == parser.DBoolTrue { return nil } return expr.(parser.TypedExpr) }
func (eh *exprHelper) indexToExpr(idx int) parser.Expr { p := &parser.Placeholder{Name: strconv.Itoa(idx)} // Convert Placeholders to IndexedVars v := valArgsConvert{h: &eh.vars, err: nil} expr, _ := parser.WalkExpr(&v, p) return expr }
func (p *planner) collectSubqueryPlans(expr parser.Expr, result []planNode) []planNode { if expr == nil { return result } p.collectSubqueryPlansVisitor = collectSubqueryPlansVisitor{plans: result} _, _ = parser.WalkExpr(&p.collectSubqueryPlansVisitor, expr) return p.collectSubqueryPlansVisitor.plans }
func (p *planner) expandSubqueryPlans(expr parser.Expr) error { if expr == nil { return nil } p.subqueryPlanVisitor = subqueryPlanVisitor{doExpand: true} _, _ = parser.WalkExpr(&p.subqueryPlanVisitor, expr) return p.subqueryPlanVisitor.err }
// Convert the variables in the given expression; the expression must only contain // variables known to the conversion function (exprCheckVars should be used first). func exprConvertVars(expr parser.TypedExpr, conv varConvertFunc) parser.TypedExpr { if expr == nil { return expr } v := varConvertVisitor{justCheck: false, conv: conv} ret, _ := parser.WalkExpr(&v, expr) return ret.(parser.TypedExpr) }
func (p *planner) startSubqueryPlans(expr parser.Expr) error { if expr == nil { return nil } // We also run and pre-evaluate the subqueries during start, // so as to avoid re-running the sub-query for every row // in the results of the surrounding planNode. p.subqueryPlanVisitor = subqueryPlanVisitor{doStart: true, doEval: true} _, _ = parser.WalkExpr(&p.subqueryPlanVisitor, expr) return p.subqueryPlanVisitor.err }
// resolveNames walks the provided expression and resolves all names // using the tableInfo and iVarHelper. func (p *planner) resolveNames( expr parser.Expr, sources multiSourceInfo, ivarHelper parser.IndexedVarHelper, ) (parser.Expr, error) { if expr == nil { return nil, nil } v := &p.nameResolutionVisitor *v = nameResolutionVisitor{ err: nil, sources: sources, colOffsets: make([]int, len(sources)), iVarHelper: ivarHelper, } colOffset := 0 for i, s := range sources { v.colOffsets[i] = colOffset colOffset += len(s.sourceColumns) } expr, _ = parser.WalkExpr(v, expr) return expr, v.err }
// processExpression parses the string expression inside an Expression, // interpreting $0, $1, etc as indexed variables. func processExpression(exprSpec Expression, h *parser.IndexedVarHelper) (parser.TypedExpr, error) { if exprSpec.Expr == "" { return nil, nil } expr, err := parser.ParseExprTraditional(exprSpec.Expr) if err != nil { return nil, err } // Convert Placeholders to IndexedVars v := valArgsConvert{h: h, err: nil} expr, _ = parser.WalkExpr(&v, expr) if v.err != nil { return nil, v.err } // Convert to a fully typed expression. typedExpr, err := parser.TypeCheck(expr, nil, parser.NoTypePreference) if err != nil { return nil, err } return typedExpr, nil }
func (p *planner) replaceSubqueries(expr parser.Expr, columns int) (parser.Expr, error) { p.subqueryVisitor = subqueryVisitor{planner: p, columns: columns} p.subqueryVisitor.path = p.subqueryVisitor.pathBuf[:0] expr, _ = parser.WalkExpr(&p.subqueryVisitor, expr) return expr, p.subqueryVisitor.err }
func (v *postAggExprVisitor) extract(typedExpr parser.TypedExpr) parser.TypedExpr { expr, _ := parser.WalkExpr(v, typedExpr) return expr.(parser.TypedExpr) }