Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: eliminate if null on non null column #7924

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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