Skip to content

Commit 1bc58f4

Browse files
erjiaqingzz-jason
authored andcommitted
planner: fix wrong DATE/DATETIME comparison in BETWEEN function (#10313) (#10407)
1 parent 2766837 commit 1bc58f4

File tree

3 files changed

+18
-7
lines changed

3 files changed

+18
-7
lines changed

expression/builtin_compare.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,8 @@ func temporalWithDateAsNumEvalType(argTp *types.FieldType) (argEvalType types.Ev
380380
return
381381
}
382382

383-
// getCmpTp4MinMax gets compare type for GREATEST and LEAST.
384-
func getCmpTp4MinMax(args []Expression) (argTp types.EvalType) {
383+
// GetCmpTp4MinMax gets compare type for GREATEST and LEAST and BETWEEN (mainly for datetime).
384+
func GetCmpTp4MinMax(args []Expression) (argTp types.EvalType) {
385385
datetimeFound, isAllStr := false, true
386386
cmpEvalType, isStr, isTemporalWithDate := temporalWithDateAsNumEvalType(args[0].GetType())
387387
if !isStr {
@@ -422,7 +422,7 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre
422422
if err = c.verifyArgs(args); err != nil {
423423
return nil, errors.Trace(err)
424424
}
425-
tp, cmpAsDatetime := getCmpTp4MinMax(args), false
425+
tp, cmpAsDatetime := GetCmpTp4MinMax(args), false
426426
if tp == types.ETDatetime {
427427
cmpAsDatetime = true
428428
tp = types.ETString
@@ -616,7 +616,7 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi
616616
if err = c.verifyArgs(args); err != nil {
617617
return nil, errors.Trace(err)
618618
}
619-
tp, cmpAsDatetime := getCmpTp4MinMax(args), false
619+
tp, cmpAsDatetime := GetCmpTp4MinMax(args), false
620620
if tp == types.ETDatetime {
621621
cmpAsDatetime = true
622622
tp = types.ETString

planner/core/expression_rewriter.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"github.com/pingcap/tidb/sessionctx"
2929
"github.com/pingcap/tidb/sessionctx/variable"
3030
"github.com/pingcap/tidb/types"
31-
"github.com/pingcap/tidb/types/parser_driver"
31+
driver "github.com/pingcap/tidb/types/parser_driver"
3232
"github.com/pingcap/tidb/util/chunk"
3333
)
3434

@@ -1197,11 +1197,20 @@ func (er *expressionRewriter) betweenToExpression(v *ast.BetweenExpr) {
11971197
if er.err != nil {
11981198
return
11991199
}
1200+
1201+
expr, lexp, rexp := er.ctxStack[stkLen-3], er.ctxStack[stkLen-2], er.ctxStack[stkLen-1]
1202+
1203+
if expression.GetCmpTp4MinMax([]expression.Expression{expr, lexp, rexp}) == types.ETDatetime {
1204+
expr = expression.WrapWithCastAsTime(er.ctx, expr, types.NewFieldType(mysql.TypeDatetime))
1205+
lexp = expression.WrapWithCastAsTime(er.ctx, lexp, types.NewFieldType(mysql.TypeDatetime))
1206+
rexp = expression.WrapWithCastAsTime(er.ctx, rexp, types.NewFieldType(mysql.TypeDatetime))
1207+
}
1208+
12001209
var op string
12011210
var l, r expression.Expression
1202-
l, er.err = expression.NewFunction(er.ctx, ast.GE, &v.Type, er.ctxStack[stkLen-3], er.ctxStack[stkLen-2])
1211+
l, er.err = expression.NewFunction(er.ctx, ast.GE, &v.Type, expr, lexp)
12031212
if er.err == nil {
1204-
r, er.err = expression.NewFunction(er.ctx, ast.LE, &v.Type, er.ctxStack[stkLen-3], er.ctxStack[stkLen-1])
1213+
r, er.err = expression.NewFunction(er.ctx, ast.LE, &v.Type, expr, rexp)
12051214
}
12061215
op = ast.LogicAnd
12071216
if er.err != nil {

planner/core/expression_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ func (s *testExpressionSuite) TestBetween(c *C) {
7070
tests := []testCase{
7171
{exprStr: "1 between 2 and 3", resultStr: "0"},
7272
{exprStr: "1 not between 2 and 3", resultStr: "1"},
73+
{exprStr: "'2001-04-10 12:34:56' between cast('2001-01-01 01:01:01' as datetime) and '01-05-01'", resultStr: "1"},
74+
{exprStr: "20010410123456 between cast('2001-01-01 01:01:01' as datetime) and 010501", resultStr: "0"},
7375
}
7476
s.runTests(c, tests)
7577
}

0 commit comments

Comments
 (0)