// 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 applyConstraints(expr parser.Expr, constraints indexConstraints) parser.Expr { v := &applyConstraintsVisitor{} for _, c := range constraints { 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.DBool(true) { return nil } return expr }
// 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 applyConstraints(expr parser.Expr, constraints orIndexConstraints) parser.Expr { if len(constraints) != 1 { // We only support simplifying the expressions if there aren't multiple // disjunctions (top-level OR branches). return expr } v := &applyConstraintsVisitor{} 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.DBool(true) { return nil } return expr }
// countVars counts how many *QualifiedName and *qvalue nodes are in an expression. func countVars(expr parser.Expr) (numQNames, numQValues int) { v := countVarsVisitor{} if expr != nil { parser.WalkExpr(&v, expr) } return v.numQNames, v.numQValues }
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 }
func (q *qvalue) Walk(v parser.Visitor) parser.Expr { e, _ := parser.WalkExpr(v, q.datum) // Typically Walk implementations are not supposed to modify nodes in-place, in order to // preserve the original transaction statement and expressions. However, `qvalue` is our type // (which we have "stiched" into an expression) so we aren't modifying an original expression. q.datum = e.(parser.Datum) return q }
func (s *selectNode) resolveQNames(expr parser.Expr) (parser.Expr, *roachpb.Error) { if expr == nil { return expr, nil } v := qnameVisitor{selNode: s} expr = parser.WalkExpr(&v, expr) return expr, v.pErr }
func (n *scanNode) resolveQNames(expr parser.Expr) (parser.Expr, error) { if expr == nil { return expr, nil } v := qnameVisitor{scanNode: n} expr = parser.WalkExpr(&v, expr) return expr, v.err }
func (p *planner) aggregateInWhere(where *parser.Where) bool { if where != nil { defer p.isAggregateVisitor.reset() _ = parser.WalkExpr(&p.isAggregateVisitor, where.Expr) if p.isAggregateVisitor.aggregated { return true } } return false }
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 }
// 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 applyConstraints(expr parser.Expr, constraints indexConstraints) parser.Expr { v := &applyConstraintsVisitor{} for _, c := range constraints { v.constraint = c expr = parser.WalkExpr(v, expr) } if expr == parser.DBool(true) { return nil } return expr }
func (p *planner) isAggregate(n *parser.Select) bool { if n.Having != nil || len(n.GroupBy) > 0 { return true } for _, target := range n.Exprs { _ = parser.WalkExpr(&p.isAggregateVisitor, target.Expr) if p.isAggregateVisitor.aggregated { return true } } return false }
func resolveQNames(table *tableInfo, qvals qvalMap, expr parser.Expr) (parser.Expr, error) { if expr == nil { return expr, nil } v := qnameVisitor{ qt: qvalResolver{ table: table, qvals: qvals, }, } expr = parser.WalkExpr(&v, expr) return expr, v.err }
func isAggregateExprs(n *parser.Select) bool { if n.Having != nil || len(n.GroupBy) > 0 { return true } v := isAggregateVisitor{} for _, target := range n.Exprs { _ = parser.WalkExpr(&v, target.Expr) if v.aggregated { return true } } return false }
// resolveQNames walks the provided expression and resolves all qualified // names using the tableInfo and qvalMap. The function takes an optional // qnameVisitor to provide the caller the option of avoiding an allocation. func resolveQNames(expr parser.Expr, table *tableInfo, qvals qvalMap, v *qnameVisitor) (parser.Expr, error) { if expr == nil { return expr, nil } if v == nil { v = new(qnameVisitor) } *v = qnameVisitor{ qt: qvalResolver{ table: table, qvals: qvals, }, } expr, _ = parser.WalkExpr(v, expr) return expr, v.err }
// Check if exprs use aggregation and if they are valid. // An expression is valid if: // - it is an aggregate expression, or // - it appears verbatim in groupBy, or // - it is not a qvalue, and all of its subexpressions (as defined by // its Walk implementation) are valid // NB: "verbatim" above is defined using a string-equality comparison // as an approximation of a recursive tree-equality comparison. // // For example: // Invalid: `SELECT k, SUM(v) FROM kv` // - `k` is unaggregated and does not appear in the (missing) GROUP BY. // Valid: `SELECT k, SUM(v) FROM kv GROUP BY k` // Also valid: `SELECT UPPER(k), SUM(v) FROM kv GROUP BY UPPER(k)` // - `UPPER(k)` appears in GROUP BY. // Also valid: `SELECT UPPER(k), SUM(v) FROM kv GROUP BY k` // - `k` appears in GROUP BY, so `UPPER(k)` is OK, but... // Invalid: `SELECT k, SUM(v) FROM kv GROUP BY UPPER(k)` // - `k` does not appear in GROUP BY; UPPER(k) does nothing to help here. func checkAggregateExprs(groupBy parser.GroupBy, exprs []parser.Expr) error { v := checkAggregateVisitor{} // TODO(dt): consider other ways of comparing expression trees. v.groupStrs = make(map[string]struct{}, len(groupBy)) for i := range groupBy { v.groupStrs[groupBy[i].String()] = struct{}{} } for _, expr := range exprs { _ = parser.WalkExpr(&v, expr) if v.aggrErr != nil { return v.aggrErr } } return nil }
// resolveQNames walks the provided expression and resolves all qualified // names using the tableInfo and qvalMap. The function takes an optional // qnameVisitor to provide the caller the option of avoiding an allocation. func resolveQNames( expr parser.Expr, sources multiSourceInfo, qvals qvalMap, v *qnameVisitor, ) (parser.Expr, error) { if expr == nil { return expr, nil } if v == nil { v = new(qnameVisitor) } *v = qnameVisitor{ qt: qvalResolver{ sources: sources, qvals: qvals, }, } 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) { expr, err := parser.ParseExprTraditional(exprSpec.Expr) if err != nil { return nil, err } // Convert ValArgs 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, nil) if err != nil { return nil, err } return typedExpr, nil }
func extractAggregateFuncs(expr parser.Expr) (parser.Expr, []*aggregateFunc, error) { v := extractAggregatesVisitor{} expr = parser.WalkExpr(&v, expr) return expr, v.funcs, v.err }
func (q *qvalue) Walk(v parser.Visitor) { q.datum = parser.WalkExpr(v, q.datum).(parser.Datum) }
func (p *planner) expandSubqueries(expr parser.Expr, columns int) (parser.Expr, *roachpb.Error) { p.subqueryVisitor = subqueryVisitor{planner: p, columns: columns} expr = parser.WalkExpr(&p.subqueryVisitor, expr) return expr, p.subqueryVisitor.pErr }
func (v *extractAggregatesVisitor) run(expr parser.Expr) (parser.Expr, []*aggregateFunc, error) { *v = extractAggregatesVisitor{} expr = parser.WalkExpr(v, expr) return expr, v.funcs, v.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 { v := varConvertVisitor{justCheck: false, conv: conv} ret, _ := parser.WalkExpr(&v, expr) return ret.(parser.TypedExpr) }
func (p *planner) expandSubqueries(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 *extractAggregatesVisitor) run(n *groupNode, expr parser.Expr) (parser.Expr, error) { *v = extractAggregatesVisitor{n: n} expr = parser.WalkExpr(v, expr) return expr, v.err }
// Walk implements the Expr interface. func (q *qvalue) Walk(v parser.Visitor) parser.Expr { if e, changed := parser.WalkExpr(v, q.datum); changed { return &qvalue{datum: e.(parser.Datum), colRef: q.colRef} } return q }
// isConst returns true if the expression contains only constant values // (i.e. it does not contain a DReference). func isConst(expr parser.Expr) bool { v := isConstVisitor{isConst: true} expr = parser.WalkExpr(&v, expr) return v.isConst }
// Extract aggregateFuncs from exprs that use aggregation and check if they are valid. // An expression is valid if: // - it is an aggregate expression, or // - it appears verbatim in groupBy, or // - it is not a qvalue, and all of its subexpressions (as defined by // its Walk implementation) are valid // NB: "verbatim" above is defined using a string-equality comparison // as an approximation of a recursive tree-equality comparison. // // For example: // Invalid: `SELECT k, SUM(v) FROM kv` // - `k` is unaggregated and does not appear in the (missing) GROUP BY. // Valid: `SELECT k, SUM(v) FROM kv GROUP BY k` // Also valid: `SELECT UPPER(k), SUM(v) FROM kv GROUP BY UPPER(k)` // - `UPPER(k)` appears in GROUP BY. // Also valid: `SELECT UPPER(k), SUM(v) FROM kv GROUP BY k` // - `k` appears in GROUP BY, so `UPPER(k)` is OK, but... // Invalid: `SELECT k, SUM(v) FROM kv GROUP BY UPPER(k)` // - `k` does not appear in GROUP BY; UPPER(k) does nothing to help here. func (v extractAggregatesVisitor) extract(expr parser.Expr) (parser.Expr, error) { expr = parser.WalkExpr(&v, expr) return expr, v.err }
func (v *extractAggregatesVisitor) Visit(expr parser.Expr, pre bool) (parser.Visitor, parser.Expr) { if !pre || v.err != nil { return nil, expr } // This expression is in the GROUP BY - switch to the copy that will accept // qvalues for this and any subtrees. if _, ok := v.groupStrs[expr.String()]; ok && v.groupedCopy != nil { v = v.groupedCopy } switch t := expr.(type) { case *parser.FuncExpr: if len(t.Name.Indirect) > 0 { break } if impl, ok := aggregates[strings.ToLower(string(t.Name.Base))]; ok { if len(t.Exprs) != 1 { // Type checking has already run on these expressions thus // if an aggregate function of the wrong arity gets here, // something has gone really wrong. panic(fmt.Sprintf("%s has %d arguments (expected 1)", t.Name.Base, len(t.Exprs))) } defer v.subAggregateVisitor.reset() _ = parser.WalkExpr(&v.subAggregateVisitor, t.Exprs[0]) if v.subAggregateVisitor.aggregated { v.err = fmt.Errorf("aggregate function calls cannot be nested under %s", t.Name) return v, expr } f := &aggregateFunc{ expr: t, arg: t.Exprs[0], create: impl, group: v.n, buckets: make(map[string]aggregateImpl), } if t.Type == parser.Distinct { f.seen = make(map[string]struct{}) } v.n.funcs = append(v.n.funcs, f) return nil, f } case *qvalue: if v.groupedCopy != nil { v.err = fmt.Errorf("column \"%s\" must appear in the GROUP BY clause or be used in an aggregate function", t.colRef.get().Name) return v, expr } f := &aggregateFunc{ expr: t, arg: t, create: newIdentAggregate, group: v.n, buckets: make(map[string]aggregateImpl), } v.n.funcs = append(v.n.funcs, f) return nil, f } return v, expr }
func checkAggregateExpr(expr parser.Expr) error { v := checkAggregateVisitor{} _ = parser.WalkExpr(&v, expr) return v.err }