Skip to content

Commit

Permalink
planner/core, expression: don't pushdown filters contains set or get …
Browse files Browse the repository at this point in the history
…var (#8412) (#8454)
  • Loading branch information
zz-jason committed Nov 29, 2018
1 parent 8461a95 commit a9c77f1
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 8 deletions.
8 changes: 4 additions & 4 deletions expression/chunk_executor.go
Expand Up @@ -27,15 +27,15 @@ import (
// Vectorizable checks whether a list of expressions can employ vectorized execution.
func Vectorizable(exprs []Expression) bool {
for _, expr := range exprs {
if hasUnVectorizableFunc(expr) {
if HasGetSetVarFunc(expr) {
return false
}
}
return true
}

// hasUnVectorizableFunc checks whether an expression contains functions that can not utilize the vectorized execution.
func hasUnVectorizableFunc(expr Expression) bool {
// HasGetSetVarFunc checks whether an expression contains SetVar/GetVar function.
func HasGetSetVarFunc(expr Expression) bool {
scalaFunc, ok := expr.(*ScalarFunction)
if !ok {
return false
Expand All @@ -44,7 +44,7 @@ func hasUnVectorizableFunc(expr Expression) bool {
return true
}
for _, arg := range scalaFunc.GetArgs() {
if hasUnVectorizableFunc(arg) {
if HasGetSetVarFunc(arg) {
return true
}
}
Expand Down
73 changes: 73 additions & 0 deletions expression/integration_test.go
Expand Up @@ -3404,3 +3404,76 @@ func (s *testIntegrationSuite) TestValuesInNonInsertStmt(c *C) {
res := tk.MustQuery(`select values(a), values(b), values(c), values(d), values(e), values(f), values(g) from t;`)
res.Check(testkit.Rows(`<nil> <nil> <nil> <nil> <nil> <nil> <nil>`))
}

func (s *testIntegrationSuite) TestUserVarMockWindFunc(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec(`use test;`)
tk.MustExec(`drop table if exists t;`)
tk.MustExec(`create table t (a int, b varchar (20), c varchar (20));`)
tk.MustExec(`insert into t values
(1,'key1-value1','insert_order1'),
(1,'key1-value2','insert_order2'),
(1,'key1-value3','insert_order3'),
(1,'key1-value4','insert_order4'),
(1,'key1-value5','insert_order5'),
(1,'key1-value6','insert_order6'),
(2,'key2-value1','insert_order1'),
(2,'key2-value2','insert_order2'),
(2,'key2-value3','insert_order3'),
(2,'key2-value4','insert_order4'),
(2,'key2-value5','insert_order5'),
(2,'key2-value6','insert_order6'),
(3,'key3-value1','insert_order1'),
(3,'key3-value2','insert_order2'),
(3,'key3-value3','insert_order3'),
(3,'key3-value4','insert_order4'),
(3,'key3-value5','insert_order5'),
(3,'key3-value6','insert_order6');
`)
tk.MustExec(`SET @LAST_VAL := NULL;`)
tk.MustExec(`SET @ROW_NUM := 0;`)

tk.MustQuery(`select * from (
SELECT a,
@ROW_NUM := IF(a = @LAST_VAL, @ROW_NUM + 1, 1) AS ROW_NUM,
@LAST_VAL := a AS LAST_VAL,
b,
c
FROM (select * from t where a in (1, 2, 3) ORDER BY a, c) t1
) t2
where t2.ROW_NUM < 2;
`).Check(testkit.Rows(
`1 1 1 key1-value1 insert_order1`,
`2 1 2 key2-value1 insert_order1`,
`3 1 3 key3-value1 insert_order1`,
))

tk.MustQuery(`select * from (
SELECT a,
@ROW_NUM := IF(a = @LAST_VAL, @ROW_NUM + 1, 1) AS ROW_NUM,
@LAST_VAL := a AS LAST_VAL,
b,
c
FROM (select * from t where a in (1, 2, 3) ORDER BY a, c) t1
) t2;
`).Check(testkit.Rows(
`1 1 1 key1-value1 insert_order1`,
`1 2 1 key1-value2 insert_order2`,
`1 3 1 key1-value3 insert_order3`,
`1 4 1 key1-value4 insert_order4`,
`1 5 1 key1-value5 insert_order5`,
`1 6 1 key1-value6 insert_order6`,
`2 1 2 key2-value1 insert_order1`,
`2 2 2 key2-value2 insert_order2`,
`2 3 2 key2-value3 insert_order3`,
`2 4 2 key2-value4 insert_order4`,
`2 5 2 key2-value5 insert_order5`,
`2 6 2 key2-value6 insert_order6`,
`3 1 3 key3-value1 insert_order1`,
`3 2 3 key3-value2 insert_order2`,
`3 3 3 key3-value3 insert_order3`,
`3 4 3 key3-value4 insert_order4`,
`3 5 3 key3-value5 insert_order5`,
`3 6 3 key3-value6 insert_order6`,
))
}
30 changes: 26 additions & 4 deletions plan/predicate_push_down.go
Expand Up @@ -50,9 +50,24 @@ func (p *baseLogicalPlan) PredicatePushDown(predicates []expression.Expression)
return nil, p.self
}

func splitSetGetVarFunc(filters []expression.Expression) ([]expression.Expression, []expression.Expression) {
canBePushDown := make([]expression.Expression, 0, len(filters))
canNotBePushDown := make([]expression.Expression, 0, len(filters))
for _, expr := range filters {
if expression.HasGetSetVarFunc(expr) {
canNotBePushDown = append(canNotBePushDown, expr)
} else {
canBePushDown = append(canBePushDown, expr)
}
}
return canBePushDown, canNotBePushDown
}

// PredicatePushDown implements LogicalPlan PredicatePushDown interface.
func (p *LogicalSelection) PredicatePushDown(predicates []expression.Expression) ([]expression.Expression, LogicalPlan) {
retConditions, child := p.children[0].PredicatePushDown(append(p.Conditions, predicates...))
canBePushDown, canNotBePushDown := splitSetGetVarFunc(p.Conditions)
retConditions, child := p.children[0].PredicatePushDown(append(canBePushDown, predicates...))
retConditions = append(canNotBePushDown, retConditions...)
if len(retConditions) > 0 {
p.Conditions = expression.PropagateConstant(p.ctx, retConditions)
return nil, p
Expand Down Expand Up @@ -292,11 +307,18 @@ func isNullRejected(ctx sessionctx.Context, schema *expression.Schema, expr expr

// PredicatePushDown implements LogicalPlan PredicatePushDown interface.
func (p *LogicalProjection) PredicatePushDown(predicates []expression.Expression) (ret []expression.Expression, retPlan LogicalPlan) {
var push = make([]expression.Expression, 0, p.Schema().Len())
canBePushed := make([]expression.Expression, 0, len(predicates))
canNotBePushed := make([]expression.Expression, 0, len(predicates))
for _, cond := range predicates {
push = append(push, expression.ColumnSubstitute(cond, p.Schema(), p.Exprs))
newFilter := expression.ColumnSubstitute(cond, p.Schema(), p.Exprs)
if !expression.HasGetSetVarFunc(newFilter) {
canBePushed = append(canBePushed, expression.ColumnSubstitute(cond, p.Schema(), p.Exprs))
} else {
canNotBePushed = append(canNotBePushed, cond)
}
}
return p.baseLogicalPlan.PredicatePushDown(push)
remained, child := p.baseLogicalPlan.PredicatePushDown(canBePushed)
return append(remained, canNotBePushed...), child
}

// PredicatePushDown implements LogicalPlan PredicatePushDown interface.
Expand Down

0 comments on commit a9c77f1

Please sign in to comment.