diff --git a/expression/constant_test.go b/expression/constant_test.go index b788363c97972..acd1240b4aaad 100644 --- a/expression/constant_test.go +++ b/expression/constant_test.go @@ -258,6 +258,15 @@ func (*testExpressionSuite) TestConstraintPropagation(c *C) { }, result: "0", }, + { + solver: newConstraintSolver(ruleColumnLTConst), + // col1 < '2018-12-11' and to_days(col1) > 737999 => false + conditions: []Expression{ + newFunction(ast.LT, col1, newDate(2018, 12, 11)), + newFunction(ast.GT, newFunction(ast.ToDays, col1), newLonglong(737999)), + }, + result: "0", + }, } for _, tt := range tests { ctx := mock.NewContext() diff --git a/expression/constraint_propagation.go b/expression/constraint_propagation.go index f30ba13590150..317d403d5b21a 100644 --- a/expression/constraint_propagation.go +++ b/expression/constraint_propagation.go @@ -174,11 +174,21 @@ func ruleColumnEQConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { } } -// ruleColumnGTConst propagates the "column > const" condition. +// ruleColumnLTConst propagates the "column > const" condition. func ruleColumnGTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { + ruleColumnXXConst(ctx, i, j, exprs, ast.GT, ast.LT, ast.GE) +} + +// ruleColumnLTConst propagates the "column < const" condition. +func ruleColumnLTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { + ruleColumnXXConst(ctx, i, j, exprs, ast.LT, ast.GT, ast.LE) +} + +// ruleColumnXXConst propagates the "column OP const" condition, where op may be '>' and '<' +func ruleColumnXXConst(ctx sessionctx.Context, i, j int, exprs *exprSet, GT string, LT string, GE string) { cond := exprs.data[i] f1, ok := cond.(*ScalarFunction) - if !ok || f1.FuncName.L != ast.GT { + if !ok || f1.FuncName.L != GT { return } var col1 *Column @@ -199,7 +209,7 @@ func ruleColumnGTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { } // col > c1, col > c2, c1 > c2 => col > c1 - if f2.FuncName.L == ast.GT { + if f2.FuncName.L == GT { col2, ok := f2.GetArgs()[0].(*Column) if !ok || !col1.Equal(ctx, col2) { return @@ -212,7 +222,7 @@ func ruleColumnGTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { return } - v, isNull, err := compareConstant(ctx, ast.GT, con1, con2) + v, isNull, err := compareConstant(ctx, GT, con1, con2) if err != nil { log.Warn(err) return @@ -232,7 +242,7 @@ func ruleColumnGTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { // Prove: // col > c1, f is monotonous => f(col) > f(c1) // f(col) > f(c1), f(col) < c2, f(c1) >= c2 => false - if f2.FuncName.L == ast.LT { + if f2.FuncName.L == LT { con2, ok := f2.GetArgs()[1].(*Constant) if !ok { return @@ -267,7 +277,7 @@ func ruleColumnGTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { if !col1.Equal(ctx, col2) { return } - v, isNull, err := compareConstant(ctx, ast.GE, fc1, con2) + v, isNull, err := compareConstant(ctx, GE, fc1, con2) if err != nil { log.Warn(err) return @@ -292,79 +302,3 @@ func compareConstant(ctx sessionctx.Context, fn string, c1, c2 Expression) (int6 } return cmp.EvalInt(ctx, chunk.Row{}) } - -// ruleColumnLTConst propagates the "column < const" condition. -func ruleColumnLTConst(ctx sessionctx.Context, i, j int, exprs *exprSet) { - cond := exprs.data[i] - f1, ok := cond.(*ScalarFunction) - if !ok || f1.FuncName.L != ast.LT { - return - } - var col1 *Column - var con1 *Constant - col1, ok = f1.GetArgs()[0].(*Column) - if !ok { - return - } - con1, ok = f1.GetArgs()[1].(*Constant) - if !ok { - return - } - - expr := exprs.data[j] - f2, ok := expr.(*ScalarFunction) - if !ok { - return - } - // col < c1, col < c2, c1 < c2 => col < c1 - if f2.FuncName.L == ast.LT { - col2, ok := f2.GetArgs()[0].(*Column) - if !ok || !col1.Equal(ctx, col2) { - return - } - con2, ok := f2.GetArgs()[1].(*Constant) - if !ok { - return - } - if !con1.RetType.Equal(con2.RetType) { - return - } - - v, isNull, err := compareConstant(ctx, ast.LT, con1, con2) - if err != nil { - log.Warn(err) - return - } - if !isNull && v > 0 { - exprs.tombstone[j] = true - } - return - } - - // col < c1, col > c2, c1 <= c2 => false - if f2.FuncName.L == ast.GT { - col2, ok := f2.GetArgs()[0].(*Column) - if !ok || !col1.Equal(ctx, col2) { - return - } - con2, ok := f2.GetArgs()[1].(*Constant) - if !ok { - return - } - - if !con1.RetType.Equal(con2.RetType) { - return - } - - v, isNull, err := compareConstant(ctx, ast.LE, con1, con2) - if err != nil { - log.Warn(err) - return - } - if !isNull && v > 0 { - exprs.SetConstFalse() - } - return - } - return -} diff --git a/go.mod b/go.mod index c1ed756e0b4b8..08135b2bc61e1 100644 --- a/go.mod +++ b/go.mod @@ -47,7 +47,7 @@ require ( github.com/pingcap/errors v0.11.0 github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20181105061835-1b5d69cd1d26 - github.com/pingcap/parser v0.0.0-20181210061630-27e9d3e251d4 + github.com/pingcap/parser v0.0.0-20181211024540-4e6d047fcaae github.com/pingcap/pd v2.1.0-rc.4+incompatible github.com/pingcap/tidb-tools v0.0.0-20181112132202-4860a0d5de03 github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 diff --git a/go.sum b/go.sum index 6a8c51c3ac0a9..be57fc9899053 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,8 @@ github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e h1:P73/4dPCL96rG github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= github.com/pingcap/kvproto v0.0.0-20181105061835-1b5d69cd1d26 h1:JK4VLNYbSn36QSbCnqALi2ySXdH0DfcMssT/zmLf4Ls= github.com/pingcap/kvproto v0.0.0-20181105061835-1b5d69cd1d26/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk= -github.com/pingcap/parser v0.0.0-20181210061630-27e9d3e251d4 h1:2rCHDk4h8VZw0fiC2CFJffOlXU3iMuz1kOt5wTMCemY= -github.com/pingcap/parser v0.0.0-20181210061630-27e9d3e251d4/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20181211024540-4e6d047fcaae h1:RD98+89F/yakFLnztEL4Pi9f+RkOAm2vgRJcB1p6tTw= +github.com/pingcap/parser v0.0.0-20181211024540-4e6d047fcaae/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/tidb-tools v0.0.0-20181112132202-4860a0d5de03 h1:xVuo5U+l6XAWHsb+xhkZ8zz3jerIwDfCHAO6kR2Kaog=