diff --git a/executor/builder.go b/executor/builder.go index 160de575aebc6..93e7822a8730f 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -340,7 +340,7 @@ func (b *executorBuilder) buildUnionScanExec(v *plan.PhysicalUnionScan) Executor case *XSelectTableExec: us.desc = x.desc us.dirty = getDirtyDB(b.ctx).getDirtyTable(x.table.Meta().ID) - us.condition = v.Condition + us.conditions = v.Conditions us.buildAndSortAddedRows(x.table, x.asName) case *XSelectIndexExec: us.desc = x.indexPlan.Desc @@ -353,7 +353,7 @@ func (b *executorBuilder) buildUnionScanExec(v *plan.PhysicalUnionScan) Executor } } us.dirty = getDirtyDB(b.ctx).getDirtyTable(x.table.Meta().ID) - us.condition = v.Condition + us.conditions = v.Conditions us.buildAndSortAddedRows(x.table, x.asName) default: // The mem table will not be written by sql directly, so we can omit the union scan to avoid err reporting. @@ -369,9 +369,9 @@ func (b *executorBuilder) buildMergeJoin(v *plan.PhysicalMergeJoin) Executor { LeftChild(b.build(v.Children()[0])). RightChild(b.build(v.Children()[1])). EqualConditions(v.EqualConditions). - LeftFilter(expression.ComposeCNFCondition(b.ctx, v.LeftConditions...)). - RightFilter(expression.ComposeCNFCondition(b.ctx, v.RightConditions...)). - OtherFilter(expression.ComposeCNFCondition(b.ctx, v.OtherConditions...)). + LeftFilter(v.LeftConditions). + RightFilter(v.RightConditions). + OtherFilter(v.OtherConditions). Schema(v.Schema()). JoinType(v.JoinType). DefaultVals(v.DefaultValues). @@ -401,7 +401,7 @@ func (b *executorBuilder) buildHashJoin(v *plan.PhysicalHashJoin) Executor { } e := &HashJoinExec{ schema: v.Schema(), - otherFilter: expression.ComposeCNFCondition(b.ctx, v.OtherConditions...), + otherFilter: v.OtherConditions, prepared: false, ctx: b.ctx, targetTypes: targetTypes, @@ -409,15 +409,15 @@ func (b *executorBuilder) buildHashJoin(v *plan.PhysicalHashJoin) Executor { defaultValues: v.DefaultValues, } if v.SmallTable == 1 { - e.smallFilter = expression.ComposeCNFCondition(b.ctx, v.RightConditions...) - e.bigFilter = expression.ComposeCNFCondition(b.ctx, v.LeftConditions...) + e.smallFilter = v.RightConditions + e.bigFilter = v.LeftConditions e.smallHashKey = rightHashKey e.bigHashKey = leftHashKey e.leftSmall = false } else { e.leftSmall = true - e.smallFilter = expression.ComposeCNFCondition(b.ctx, v.LeftConditions...) - e.bigFilter = expression.ComposeCNFCondition(b.ctx, v.RightConditions...) + e.smallFilter = v.LeftConditions + e.bigFilter = v.RightConditions e.smallHashKey = leftHashKey e.bigHashKey = rightHashKey } @@ -434,10 +434,10 @@ func (b *executorBuilder) buildHashJoin(v *plan.PhysicalHashJoin) Executor { for i := 0; i < e.concurrency; i++ { ctx := &hashJoinCtx{} if e.bigFilter != nil { - ctx.bigFilter = e.bigFilter.Clone() + ctx.bigFilter = e.bigFilter } if e.otherFilter != nil { - ctx.otherFilter = e.otherFilter.Clone() + ctx.otherFilter = e.otherFilter } ctx.datumBuffer = make([]types.Datum, len(e.bigHashKey)) ctx.hashKeyBuffer = make([]byte, 0, 10000) @@ -458,9 +458,9 @@ func (b *executorBuilder) buildSemiJoin(v *plan.PhysicalHashSemiJoin) *HashSemiJ } e := &HashSemiJoinExec{ schema: v.Schema(), - otherFilter: expression.ComposeCNFCondition(b.ctx, v.OtherConditions...), - bigFilter: expression.ComposeCNFCondition(b.ctx, v.LeftConditions...), - smallFilter: expression.ComposeCNFCondition(b.ctx, v.RightConditions...), + otherFilter: v.OtherConditions, + bigFilter: v.LeftConditions, + smallFilter: v.RightConditions, bigExec: b.build(v.Children()[0]), smallExec: b.build(v.Children()[1]), prepared: false, @@ -649,9 +649,9 @@ func (b *executorBuilder) buildNestedLoopJoin(v *plan.PhysicalHashJoin) *NestedL SmallExec: b.build(v.Children()[1]), BigExec: b.build(v.Children()[0]), Ctx: b.ctx, - BigFilter: expression.ComposeCNFCondition(b.ctx, v.LeftConditions...), - SmallFilter: expression.ComposeCNFCondition(b.ctx, v.RightConditions...), - OtherFilter: expression.ComposeCNFCondition(b.ctx, append(expression.ScalarFuncs2Exprs(v.EqualConditions), v.OtherConditions...)...), + BigFilter: v.LeftConditions, + SmallFilter: v.RightConditions, + OtherFilter: append(expression.ScalarFuncs2Exprs(v.EqualConditions), v.OtherConditions...), schema: v.Schema(), outer: v.JoinType != plan.InnerJoin, defaultValues: v.DefaultValues, @@ -662,9 +662,9 @@ func (b *executorBuilder) buildNestedLoopJoin(v *plan.PhysicalHashJoin) *NestedL BigExec: b.build(v.Children()[1]), leftSmall: true, Ctx: b.ctx, - BigFilter: expression.ComposeCNFCondition(b.ctx, v.RightConditions...), - SmallFilter: expression.ComposeCNFCondition(b.ctx, v.LeftConditions...), - OtherFilter: expression.ComposeCNFCondition(b.ctx, append(expression.ScalarFuncs2Exprs(v.EqualConditions), v.OtherConditions...)...), + BigFilter: v.RightConditions, + SmallFilter: v.LeftConditions, + OtherFilter: append(expression.ScalarFuncs2Exprs(v.EqualConditions), v.OtherConditions...), schema: v.Schema(), outer: v.JoinType != plan.InnerJoin, defaultValues: v.DefaultValues, diff --git a/executor/executor.go b/executor/executor.go index 39b643cd7b61d..9b68a38cd5fb0 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -472,10 +472,9 @@ func (e *TableDualExec) Close() error { // SelectionExec represents a filter executor. type SelectionExec struct { - Src Executor - Condition expression.Expression - ctx context.Context - schema *expression.Schema + Src Executor + ctx context.Context + schema *expression.Schema // scanController will tell whether this selection need to // control the condition of below scan executor. @@ -545,18 +544,11 @@ func (e *SelectionExec) Next() (*Row, error) { if srcRow == nil { return nil, nil } - allMatch := true - for _, cond := range e.Conditions { - match, err := expression.EvalBool(cond, srcRow.Data, e.ctx) - if err != nil { - return nil, errors.Trace(err) - } - if !match { - allMatch = false - break - } + match, err := expression.EvalBool(e.Conditions, srcRow.Data, e.ctx) + if err != nil { + return nil, errors.Trace(err) } - if allMatch { + if match { return srcRow, nil } } diff --git a/executor/join.go b/executor/join.go index 90216af28dd89..4985f87d187de 100644 --- a/executor/join.go +++ b/executor/join.go @@ -42,9 +42,9 @@ type HashJoinExec struct { bigExec Executor prepared bool ctx context.Context - smallFilter expression.Expression - bigFilter expression.Expression - otherFilter expression.Expression + smallFilter []expression.Expression + bigFilter []expression.Expression + otherFilter []expression.Expression schema *expression.Schema outer bool leftSmall bool @@ -75,8 +75,8 @@ type HashJoinExec struct { // hashJoinCtx holds the variables needed to do a hash join in one of many concurrent goroutines. type hashJoinCtx struct { - bigFilter expression.Expression - otherFilter expression.Expression + bigFilter []expression.Expression + otherFilter []expression.Expression // Buffer used for encode hash keys. datumBuffer []types.Datum hashKeyBuffer []byte @@ -228,15 +228,12 @@ func (e *HashJoinExec) prepare() error { break } - matched := true - if e.smallFilter != nil { - matched, err = expression.EvalBool(e.smallFilter, row.Data, e.ctx) - if err != nil { - return errors.Trace(err) - } - if !matched { - continue - } + matched, err := expression.EvalBool(e.smallFilter, row.Data, e.ctx) + if err != nil { + return errors.Trace(err) + } + if !matched { + continue } hasNull, joinKey, err := getJoinKey(sc, e.smallHashKey, row, e.targetTypes, e.hashJoinContexts[0].datumBuffer, nil) if err != nil { @@ -417,18 +414,15 @@ func (e *HashJoinExec) constructMatchedRows(ctx *hashJoinCtx, bigRow *Row) (matc if err != nil { return nil, errors.Trace(err) } - otherMatched := true var matchedRow *Row if e.leftSmall { matchedRow = makeJoinRow(smallRow, bigRow) } else { matchedRow = makeJoinRow(bigRow, smallRow) } - if e.otherFilter != nil { - otherMatched, err = expression.EvalBool(ctx.otherFilter, matchedRow.Data, e.ctx) - if err != nil { - return nil, errors.Trace(err) - } + otherMatched, err := expression.EvalBool(ctx.otherFilter, matchedRow.Data, e.ctx) + if err != nil { + return nil, errors.Trace(err) } if otherMatched { matchedRows = append(matchedRows, matchedRow) @@ -509,9 +503,9 @@ type NestedLoopJoinExec struct { leftSmall bool prepared bool Ctx context.Context - SmallFilter expression.Expression - BigFilter expression.Expression - OtherFilter expression.Expression + SmallFilter []expression.Expression + BigFilter []expression.Expression + OtherFilter []expression.Expression schema *expression.Schema outer bool defaultValues []types.Datum @@ -545,12 +539,9 @@ func (e *NestedLoopJoinExec) fetchBigRow() (*Row, bool, error) { return nil, false, e.BigExec.Close() } - matched := true - if e.BigFilter != nil { - matched, err = expression.EvalBool(e.BigFilter, bigRow.Data, e.Ctx) - if err != nil { - return nil, false, errors.Trace(err) - } + matched, err := expression.EvalBool(e.BigFilter, bigRow.Data, e.Ctx) + if err != nil { + return nil, false, errors.Trace(err) } if matched { return bigRow, true, nil @@ -578,15 +569,9 @@ func (e *NestedLoopJoinExec) prepare() error { return e.SmallExec.Close() } - matched := true - if e.SmallFilter != nil { - matched, err = expression.EvalBool(e.SmallFilter, row.Data, e.Ctx) - if err != nil { - return errors.Trace(err) - } - if !matched { - continue - } + matched, err := expression.EvalBool(e.SmallFilter, row.Data, e.Ctx) + if err != nil { + return errors.Trace(err) } if matched { e.innerRows = append(e.innerRows, row) @@ -621,14 +606,12 @@ func (e *NestedLoopJoinExec) doJoin(bigRow *Row, match bool) ([]*Row, error) { } else { mergedRow = makeJoinRow(bigRow, row) } - if e.OtherFilter != nil { - matched, err := expression.EvalBool(e.OtherFilter, mergedRow.Data, e.Ctx) - if err != nil { - return nil, errors.Trace(err) - } - if !matched { - continue - } + matched, err := expression.EvalBool(e.OtherFilter, mergedRow.Data, e.Ctx) + if err != nil { + return nil, errors.Trace(err) + } + if !matched { + continue } e.resultRows = append(e.resultRows, mergedRow) } @@ -673,9 +656,9 @@ type HashSemiJoinExec struct { bigExec Executor prepared bool ctx context.Context - smallFilter expression.Expression - bigFilter expression.Expression - otherFilter expression.Expression + smallFilter []expression.Expression + bigFilter []expression.Expression + otherFilter []expression.Expression schema *expression.Schema resultRows []*Row // In auxMode, the result row always returns with an extra column which stores a boolean @@ -725,15 +708,12 @@ func (e *HashSemiJoinExec) prepare() error { break } - matched := true - if e.smallFilter != nil { - matched, err = expression.EvalBool(e.smallFilter, row.Data, e.ctx) - if err != nil { - return errors.Trace(err) - } - if !matched { - continue - } + matched, err := expression.EvalBool(e.smallFilter, row.Data, e.ctx) + if err != nil { + return errors.Trace(err) + } + if !matched { + continue } hasNull, hashcode, err := getJoinKey(sc, e.smallHashKey, row, e.targetTypes, make([]types.Datum, len(e.smallHashKey)), nil) if err != nil { @@ -769,14 +749,10 @@ func (e *HashSemiJoinExec) rowIsMatched(bigRow *Row) (matched bool, hasNull bool } // match eq condition for _, smallRow := range rows { - matched = true - if e.otherFilter != nil { - var matchedRow *Row - matchedRow = makeJoinRow(bigRow, smallRow) - matched, err = expression.EvalBool(e.otherFilter, matchedRow.Data, e.ctx) - if err != nil { - return false, false, errors.Trace(err) - } + matchedRow := makeJoinRow(bigRow, smallRow) + matched, err = expression.EvalBool(e.otherFilter, matchedRow.Data, e.ctx) + if err != nil { + return false, false, errors.Trace(err) } if matched { return @@ -795,12 +771,9 @@ func (e *HashSemiJoinExec) fetchBigRow() (*Row, bool, error) { return nil, false, errors.Trace(e.bigExec.Close()) } - matched := true - if e.bigFilter != nil { - matched, err = expression.EvalBool(e.bigFilter, bigRow.Data, e.ctx) - if err != nil { - return nil, false, errors.Trace(err) - } + matched, err := expression.EvalBool(e.bigFilter, bigRow.Data, e.ctx) + if err != nil { + return nil, false, errors.Trace(err) } if matched { return bigRow, true, nil diff --git a/executor/join_test.go b/executor/join_test.go index 9f8b4561cb1a5..33e2d5fdd9c82 100644 --- a/executor/join_test.go +++ b/executor/join_test.go @@ -57,9 +57,9 @@ func (s *testSuite) TestNestedLoopJoin(c *C) { BigExec: bigExec, SmallExec: smallExec, Ctx: mock.NewContext(), - BigFilter: bigFilter, - SmallFilter: smallFilter, - OtherFilter: otherFilter, + BigFilter: []expression.Expression{bigFilter}, + SmallFilter: []expression.Expression{smallFilter}, + OtherFilter: []expression.Expression{otherFilter}, } row, err := join.Next() c.Check(err, IsNil) diff --git a/executor/merge_join.go b/executor/merge_join.go index 02295780e80a8..507a4b6f128c9 100644 --- a/executor/merge_join.go +++ b/executor/merge_join.go @@ -36,8 +36,8 @@ type MergeJoinExec struct { leftJoinKeys []*expression.Column rightJoinKeys []*expression.Column prepared bool - leftFilter expression.Expression - otherFilter expression.Expression + leftFilter []expression.Expression + otherFilter []expression.Expression schema *expression.Schema preserveLeft bool // To preserve left side of the relation as in left outer join cursor int @@ -61,9 +61,9 @@ type joinBuilder struct { leftChild Executor rightChild Executor eqConditions []*expression.ScalarFunction - leftFilter expression.Expression - rightFilter expression.Expression - otherFilter expression.Expression + leftFilter []expression.Expression + rightFilter []expression.Expression + otherFilter []expression.Expression schema *expression.Schema joinType plan.JoinType defaultValues []types.Datum @@ -89,17 +89,17 @@ func (b *joinBuilder) RightChild(exec Executor) *joinBuilder { return b } -func (b *joinBuilder) LeftFilter(expr expression.Expression) *joinBuilder { +func (b *joinBuilder) LeftFilter(expr []expression.Expression) *joinBuilder { b.leftFilter = expr return b } -func (b *joinBuilder) RightFilter(expr expression.Expression) *joinBuilder { +func (b *joinBuilder) RightFilter(expr []expression.Expression) *joinBuilder { b.rightFilter = expr return b } -func (b *joinBuilder) OtherFilter(expr expression.Expression) *joinBuilder { +func (b *joinBuilder) OtherFilter(expr []expression.Expression) *joinBuilder { b.otherFilter = expr return b } @@ -189,7 +189,7 @@ type rowBlockIterator struct { stmtCtx *variable.StatementContext ctx context.Context reader Executor - filter expression.Expression + filter []expression.Expression joinKeys []*expression.Column peekedRow *Row rowCache []*Row diff --git a/executor/union_scan.go b/executor/union_scan.go index 88f0dcdc1bc54..4fa4ed80891ed 100644 --- a/executor/union_scan.go +++ b/executor/union_scan.go @@ -90,9 +90,9 @@ type UnionScanExec struct { Src Executor dirty *dirtyTable // usedIndex is the column offsets of the index which Src executor has used. - usedIndex []int - desc bool - condition expression.Expression + usedIndex []int + desc bool + conditions []expression.Expression addedRows []*Row cursor int @@ -249,14 +249,12 @@ func (us *UnionScanExec) buildAndSortAddedRows(t table.Table, asName *model.CISt newData = append(newData, data[col.Offset]) } } - if us.condition != nil { - matched, err := expression.EvalBool(us.condition, newData, us.ctx) - if err != nil { - return errors.Trace(err) - } - if !matched { - continue - } + matched, err := expression.EvalBool(us.conditions, newData, us.ctx) + if err != nil { + return errors.Trace(err) + } + if !matched { + continue } rowKeyEntry := &RowKeyEntry{Handle: h, Tbl: t} if asName != nil && asName.L != "" { diff --git a/expression/constant_propagation.go b/expression/constant_propagation.go index dbd99075d87c8..e180417aff025 100644 --- a/expression/constant_propagation.go +++ b/expression/constant_propagation.go @@ -174,7 +174,7 @@ func (s *propagateConstantSolver) pickNewEQConds(visited []bool) (retMapper map[ ok := false if col == nil { if con, ok = cond.(*Constant); ok { - value, _ := EvalBool(con, nil, s.ctx) + value, _ := EvalBool([]Expression{con}, nil, s.ctx) if !value { s.setConds2ConstFalse() return nil diff --git a/expression/expression.go b/expression/expression.go index 119aea7ed600b..5548ea9cf867a 100644 --- a/expression/expression.go +++ b/expression/expression.go @@ -74,21 +74,26 @@ type Expression interface { ResolveIndices(schema *Schema) } -// EvalBool evaluates expression to a boolean value. -func EvalBool(expr Expression, row []types.Datum, ctx context.Context) (bool, error) { - data, err := expr.Eval(row) - if err != nil { - return false, errors.Trace(err) - } - if data.IsNull() { - return false, nil - } +// EvalBool evaluates expression list to a boolean value. +func EvalBool(exprList []Expression, row []types.Datum, ctx context.Context) (bool, error) { + for _, expr := range exprList { + data, err := expr.Eval(row) + if err != nil { + return false, errors.Trace(err) + } + if data.IsNull() { + return false, nil + } - i, err := data.ToBool(ctx.GetSessionVars().StmtCtx) - if err != nil { - return false, errors.Trace(err) + i, err := data.ToBool(ctx.GetSessionVars().StmtCtx) + if err != nil { + return false, errors.Trace(err) + } + if i == 0 { + return false, nil + } } - return i != 0, nil + return true, nil } // One stands for a number 1. diff --git a/plan/physical_plan_builder.go b/plan/physical_plan_builder.go index 3cf9b7cabef4a..25c79b9a5c824 100644 --- a/plan/physical_plan_builder.go +++ b/plan/physical_plan_builder.go @@ -259,7 +259,7 @@ func (p *DataSource) tryToConvert2DummyScan(prop *requiredProperty) (*physicalPl for _, cond := range sel.Conditions { if con, ok := cond.(*expression.Constant); ok { - result, err := expression.EvalBool(con, nil, p.ctx) + result, err := expression.EvalBool([]expression.Expression{con}, nil, p.ctx) if err != nil { return nil, errors.Trace(err) } diff --git a/plan/physical_plans.go b/plan/physical_plans.go index 31c922aef389b..da6cdcc647606 100644 --- a/plan/physical_plans.go +++ b/plan/physical_plans.go @@ -306,7 +306,7 @@ func (p *physicalTableSource) tryToAddUnionScan(resultPlan PhysicalPlan) Physica } conditions := append(p.indexFilterConditions, p.tableFilterConditions...) us := PhysicalUnionScan{ - Condition: expression.ComposeCNFCondition(p.ctx, append(conditions, p.AccessCondition...)...), + Conditions: append(conditions, p.AccessCondition...), }.init(p.allocator, p.ctx) us.SetChildren(resultPlan) us.SetSchema(resultPlan.Schema()) @@ -509,7 +509,7 @@ type PhysicalUnionScan struct { *basePlan basePhysicalPlan - Condition expression.Expression + Conditions []expression.Expression } // Cache plan is a physical plan which stores the result of its child node.