From 1d7367951d8152db63fd8c4240d231a4834a42a5 Mon Sep 17 00:00:00 2001 From: Kenan Yao Date: Fri, 12 Oct 2018 19:09:28 +0800 Subject: [PATCH 1/3] expression: maintain `DeferredExpr` in aggressive constant folding. --- expression/constant_fold.go | 17 +++++++++++------ expression/constant_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/expression/constant_fold.go b/expression/constant_fold.go index 0553b2c8c0c2a..beaaa695ee65f 100644 --- a/expression/constant_fold.go +++ b/expression/constant_fold.go @@ -15,6 +15,7 @@ package expression import ( "github.com/pingcap/tidb/ast" + "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" log "github.com/sirupsen/logrus" ) @@ -118,10 +119,10 @@ func foldConstant(expr Expression) (Expression, bool) { return expr, isDeferredConst } if value.IsNull() { - return &Constant{Value: value, RetType: x.RetType}, false + return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst } if isTrue, err := value.ToBool(sc); err == nil && isTrue == 0 { - return &Constant{Value: value, RetType: x.RetType}, false + return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst } return expr, isDeferredConst } @@ -130,10 +131,7 @@ func foldConstant(expr Expression) (Expression, bool) { log.Warnf("fold constant %s: %s", x.ExplainInfo(), err.Error()) return expr, isDeferredConst } - if isDeferredConst { - return &Constant{Value: value, RetType: x.RetType, DeferredExpr: x}, true - } - return &Constant{Value: value, RetType: x.RetType}, false + return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst case *Constant: if x.DeferredExpr != nil { value, err := x.DeferredExpr.Eval(chunk.Row{}) @@ -146,3 +144,10 @@ func foldConstant(expr Expression) (Expression, bool) { } return expr, false } + +func foldedConstForScalarFunc(value types.Datum, sf *ScalarFunction, isDeferred bool) *Constant { + if isDeferred { + return &Constant{Value: value, RetType: sf.RetType, DeferredExpr: sf} + } + return &Constant{Value: value, RetType: sf.RetType} +} diff --git a/expression/constant_test.go b/expression/constant_test.go index a2f4376afeeb2..bda66eb8b3f46 100644 --- a/expression/constant_test.go +++ b/expression/constant_test.go @@ -202,3 +202,31 @@ func (*testExpressionSuite) TestConstantFolding(c *C) { c.Assert(newConds.String(), Equals, tt.result, Commentf("different for expr %s", tt.condition)) } } + +func (*testExpressionSuite) TestDeferredExprNullConstantFold(c *C) { + defer testleak.AfterTest(c)() + nullConst := &Constant{ + Value: types.NewDatum(nil), + RetType: types.NewFieldType(mysql.TypeTiny), + DeferredExpr: Null, + } + tests := []struct { + condition Expression + deferred string + }{ + { + condition: newFunction(ast.LT, newColumn(0), nullConst), + deferred: "lt(test.t.0, )", + }, + } + for _, tt := range tests { + comment := Commentf("different for expr %s", tt.condition) + sf, ok := tt.condition.(*ScalarFunction) + c.Assert(ok, IsTrue, comment) + sf.GetCtx().GetSessionVars().StmtCtx.InNullRejectCheck = true + newConds := FoldConstant(tt.condition) + newConst, ok := newConds.(*Constant) + c.Assert(ok, IsTrue, comment) + c.Assert(newConst.DeferredExpr.String(), Equals, tt.deferred, comment) + } +} From e8704c70814b29c994b2875d3d6f027af8a62a98 Mon Sep 17 00:00:00 2001 From: Kenan Yao Date: Fri, 12 Oct 2018 20:24:24 +0800 Subject: [PATCH 2/3] address comments --- expression/constant_fold.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/expression/constant_fold.go b/expression/constant_fold.go index beaaa695ee65f..2a3c065970d88 100644 --- a/expression/constant_fold.go +++ b/expression/constant_fold.go @@ -119,10 +119,16 @@ func foldConstant(expr Expression) (Expression, bool) { return expr, isDeferredConst } if value.IsNull() { - return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst + if isDeferredConst { + return &Constant{Value: value, RetType: x.RetType, DeferredExpr: x}, true + } + return &Constant{Value: value, RetType: x.RetType}, false } if isTrue, err := value.ToBool(sc); err == nil && isTrue == 0 { - return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst + if isDeferredConst { + return &Constant{Value: value, RetType: x.RetType, DeferredExpr: x}, true + } + return &Constant{Value: value, RetType: x.RetType}, false } return expr, isDeferredConst } @@ -131,7 +137,10 @@ func foldConstant(expr Expression) (Expression, bool) { log.Warnf("fold constant %s: %s", x.ExplainInfo(), err.Error()) return expr, isDeferredConst } - return foldedConstForScalarFunc(value, x, isDeferredConst), isDeferredConst + if isDeferredConst { + return &Constant{Value: value, RetType: x.RetType, DeferredExpr: x}, true + } + return &Constant{Value: value, RetType: x.RetType}, false case *Constant: if x.DeferredExpr != nil { value, err := x.DeferredExpr.Eval(chunk.Row{}) @@ -144,10 +153,3 @@ func foldConstant(expr Expression) (Expression, bool) { } return expr, false } - -func foldedConstForScalarFunc(value types.Datum, sf *ScalarFunction, isDeferred bool) *Constant { - if isDeferred { - return &Constant{Value: value, RetType: sf.RetType, DeferredExpr: sf} - } - return &Constant{Value: value, RetType: sf.RetType} -} From 1dbbfe00fd7a107256ef1fa9ad56da7038a8644b Mon Sep 17 00:00:00 2001 From: Kenan Yao Date: Fri, 12 Oct 2018 20:25:45 +0800 Subject: [PATCH 3/3] remove import --- expression/constant_fold.go | 1 - 1 file changed, 1 deletion(-) diff --git a/expression/constant_fold.go b/expression/constant_fold.go index 2a3c065970d88..0f7e85fa18ba9 100644 --- a/expression/constant_fold.go +++ b/expression/constant_fold.go @@ -15,7 +15,6 @@ package expression import ( "github.com/pingcap/tidb/ast" - "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" log "github.com/sirupsen/logrus" )