func (e *Evaluator) between(v *ast.BetweenExpr) bool { var l, r ast.ExprNode op := opcode.AndAnd if v.Not { // v < lv || v > rv op = opcode.OrOr l = &ast.BinaryOperationExpr{Op: opcode.LT, L: v.Expr, R: v.Left} r = &ast.BinaryOperationExpr{Op: opcode.GT, L: v.Expr, R: v.Right} } else { // v >= lv && v <= rv l = &ast.BinaryOperationExpr{Op: opcode.GE, L: v.Expr, R: v.Left} r = &ast.BinaryOperationExpr{Op: opcode.LE, L: v.Expr, R: v.Right} } ast.MergeChildrenFlags(l, v.Expr, v.Left) ast.MergeChildrenFlags(l, v.Expr, v.Right) ret := &ast.BinaryOperationExpr{Op: op, L: l, R: r} ast.MergeChildrenFlags(ret, l, r) ret.Accept(e) if e.err != nil { return false } v.SetDatum(*ret.GetDatum()) return true }
func (b *planBuilder) buildTablePlanFromJoinPath(path *joinPath) Plan { for _, equiv := range path.eqConds { columnNameExpr := &ast.ColumnNameExpr{} columnNameExpr.Name = &ast.ColumnName{} columnNameExpr.Name.Name = equiv.left.Column.Name columnNameExpr.Name.Table = equiv.left.Table.Name columnNameExpr.Refer = equiv.left columnNameExpr.Type = equiv.left.Expr.GetType() ast.SetFlag(columnNameExpr) condition := &ast.BinaryOperationExpr{L: columnNameExpr, R: equiv.right.Expr, Op: opcode.EQ} ast.MergeChildrenFlags(condition, columnNameExpr, equiv.right.Expr) path.conditions = append(path.conditions, condition) } candidates := b.buildAllAccessMethodsPlan(path) var p Plan var lowestCost float64 for _, can := range candidates { cost := EstimateCost(can) if p == nil { p = can lowestCost = cost } if cost < lowestCost { p = can lowestCost = cost } } return p }
func (b *executorBuilder) joinConditions(conditions []ast.ExprNode) ast.ExprNode { if len(conditions) == 0 { return nil } if len(conditions) == 1 { return conditions[0] } condition := &ast.BinaryOperationExpr{ Op: opcode.AndAnd, L: conditions[0], R: b.joinConditions(conditions[1:]), } ast.MergeChildrenFlags(condition, condition.L, condition.R) return condition }
func (b *planBuilder) buildPlanFromJoinPath(path *joinPath) Plan { if path.table != nil { return b.buildTablePlanFromJoinPath(path) } if path.subquery != nil { return b.buildSubqueryJoinPath(path) } if path.outer != nil { join := &JoinOuter{ Outer: b.buildPlanFromJoinPath(path.outer), Inner: b.buildPlanFromJoinPath(path.inner), } addChild(join, join.Outer) addChild(join, join.Inner) if path.rightJoin { join.SetFields(append(join.Inner.Fields(), join.Outer.Fields()...)) } else { join.SetFields(append(join.Outer.Fields(), join.Inner.Fields()...)) } return join } join := &JoinInner{} for _, in := range path.inners { inPlan := b.buildPlanFromJoinPath(in) join.Inners = append(join.Inners, inPlan) join.fields = append(join.fields, in.resultFields()...) addChild(join, inPlan) } join.Conditions = path.conditions for _, equiv := range path.eqConds { columnNameExpr := &ast.ColumnNameExpr{} columnNameExpr.Name = &ast.ColumnName{} columnNameExpr.Name.Name = equiv.left.Column.Name columnNameExpr.Name.Table = equiv.left.Table.Name columnNameExpr.Refer = equiv.left ast.SetFlag(columnNameExpr) cond := &ast.BinaryOperationExpr{L: columnNameExpr, R: equiv.right.Expr, Op: opcode.EQ} ast.MergeChildrenFlags(cond, columnNameExpr, equiv.right.Expr) join.Conditions = append(join.Conditions, cond) } return join }
// Build subquery join path plan func (b *planBuilder) buildSubqueryJoinPath(path *joinPath) Plan { for _, equiv := range path.eqConds { columnNameExpr := &ast.ColumnNameExpr{} columnNameExpr.Name = &ast.ColumnName{} columnNameExpr.Name.Name = equiv.left.Column.Name columnNameExpr.Name.Table = equiv.left.Table.Name columnNameExpr.Refer = equiv.left columnNameExpr.Type = equiv.left.Expr.GetType() ast.SetFlag(columnNameExpr) condition := &ast.BinaryOperationExpr{L: columnNameExpr, R: equiv.right.Expr, Op: opcode.EQ} ast.MergeChildrenFlags(condition, columnNameExpr, equiv.right.Expr) path.conditions = append(path.conditions, condition) } p := b.build(path.subquery) if len(path.conditions) == 0 { return p } filterPlan := &Filter{Conditions: path.conditions} addChild(filterPlan, p) filterPlan.SetFields(p.Fields()) return filterPlan }