Skip to content

Commit

Permalink
planner: eliminate if null on non null column (#7924)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhexuany authored Oct 17, 2018
1 parent 732233a commit 6e525f9
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
37 changes: 37 additions & 0 deletions cmd/explaintest/r/explain_easy.result
Original file line number Diff line number Diff line change
Expand Up @@ -385,3 +385,40 @@ Projection_5 8000.00 root test.ta.a
└─TableReader_9 10000.00 root data:TableScan_8
└─TableScan_8 10000.00 cop table:ta, range:[-inf,+inf], keep order:false, stats:pseudo
rollback;
drop table if exists t;
create table t(a int, nb int not null, nc int not null);
explain select ifnull(a, 0) from t;
id count task operator info
Projection_3 10000.00 root ifnull(test.t.a, 0)
└─TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select ifnull(nb, 0) from t;
id count task operator info
TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select ifnull(nb, 0), ifnull(nc, 0) from t;
id count task operator info
TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select ifnull(a, 0), ifnull(nb, 0) from t;
id count task operator info
Projection_3 10000.00 root ifnull(test.t.a, 0), test.t.nb
└─TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select ifnull(nb, 0), ifnull(nb, 0) from t;
id count task operator info
Projection_3 10000.00 root test.t.nb, test.t.nb
└─TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select 1+ifnull(nb, 0) from t;
id count task operator info
Projection_3 10000.00 root plus(1, test.t.nb)
└─TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
explain select 1+ifnull(a, 0) from t;
id count task operator info
Projection_3 10000.00 root plus(1, ifnull(test.t.a, 0))
└─TableReader_5 10000.00 root data:TableScan_4
└─TableScan_4 10000.00 cop table:t, range:[-inf,+inf], keep order:false, stats:pseudo
drop table if exists t;
drop table if exists t;
12 changes: 12 additions & 0 deletions cmd/explaintest/t/explain_easy.test
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,15 @@ begin;
insert tb values ('1');
explain select * from ta where a = 1;
rollback;

# https://github.com/pingcap/tidb/issues/7918
drop table if exists t;
create table t(a int, nb int not null, nc int not null);
explain select ifnull(a, 0) from t;
explain select ifnull(nb, 0) from t;
explain select ifnull(nb, 0), ifnull(nc, 0) from t;
explain select ifnull(a, 0), ifnull(nb, 0) from t;
explain select ifnull(nb, 0), ifnull(nb, 0) from t;
explain select 1+ifnull(nb, 0) from t;
explain select 1+ifnull(a, 0) from t;
drop table if exists t;
32 changes: 32 additions & 0 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,37 @@ func (b *PlanBuilder) buildProjectionField(id, position int, field *ast.SelectFi
}
}

func eliminateIfNullOnNotNullCol(p LogicalPlan, expr expression.Expression) expression.Expression {
ds, isDs := p.(*DataSource)
if !isDs {
return expr
}

scalarExpr, isScalarFunc := expr.(*expression.ScalarFunction)
if !isScalarFunc {
return expr
}
exprChildren := scalarExpr.GetArgs()
for i := 0; i < len(exprChildren); i++ {
exprChildren[i] = eliminateIfNullOnNotNullCol(p, exprChildren[i])
}

if scalarExpr.FuncName.L != ast.Ifnull {
return expr
}
colRef, isColRef := exprChildren[0].(*expression.Column)
if !isColRef {
return expr
}

colInfo := model.FindColumnInfo(ds.Columns, colRef.ColName.L)
if !mysql.HasNotNullFlag(colInfo.Flag) {
return expr
}

return colRef
}

// buildProjection returns a Projection plan and non-aux columns length.
func (b *PlanBuilder) buildProjection(p LogicalPlan, fields []*ast.SelectField, mapper map[*ast.AggregateFuncExpr]int) (LogicalPlan, int, error) {
b.optFlag |= flagEliminateProjection
Expand All @@ -585,6 +616,7 @@ func (b *PlanBuilder) buildProjection(p LogicalPlan, fields []*ast.SelectField,
oldLen := 0
for _, field := range fields {
newExpr, np, err := b.rewrite(field.Expr, p, mapper, true)
newExpr = eliminateIfNullOnNotNullCol(p, newExpr)
if err != nil {
return nil, 0, errors.Trace(err)
}
Expand Down

0 comments on commit 6e525f9

Please sign in to comment.