Пример #1
0
// 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
}
Пример #2
0
// 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
}
Пример #3
0
// 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
}
Пример #4
0
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
}
Пример #5
0
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
}
Пример #6
0
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
}
Пример #7
0
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
}
Пример #8
0
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
}
Пример #9
0
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
}
Пример #10
0
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
}
Пример #11
0
// 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
}
Пример #12
0
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
}
Пример #13
0
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
}
Пример #14
0
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
}
Пример #15
0
// 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
}
Пример #16
0
// 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
}
Пример #17
0
// 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
}
Пример #18
0
// 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
}
Пример #19
0
func extractAggregateFuncs(expr parser.Expr) (parser.Expr, []*aggregateFunc, error) {
	v := extractAggregatesVisitor{}
	expr = parser.WalkExpr(&v, expr)
	return expr, v.funcs, v.err
}
Пример #20
0
func (q *qvalue) Walk(v parser.Visitor) {
	q.datum = parser.WalkExpr(v, q.datum).(parser.Datum)
}
Пример #21
0
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
}
Пример #22
0
func (v *extractAggregatesVisitor) run(expr parser.Expr) (parser.Expr, []*aggregateFunc, error) {
	*v = extractAggregatesVisitor{}
	expr = parser.WalkExpr(v, expr)
	return expr, v.funcs, v.err
}
Пример #23
0
// 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)
}
Пример #24
0
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
}
Пример #25
0
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
}
Пример #26
0
// 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
}
Пример #27
0
// 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
}
Пример #28
0
// 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
}
Пример #29
0
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
}
Пример #30
0
func checkAggregateExpr(expr parser.Expr) error {
	v := checkAggregateVisitor{}
	_ = parser.WalkExpr(&v, expr)
	return v.err
}