Skip to content

Commit

Permalink
executor: fix incorrect result produced by addtime() or subtime() fun…
Browse files Browse the repository at this point in the history
…ction when using the date type (#57337)

close #56861
  • Loading branch information
xzhangxian1008 authored Nov 20, 2024
1 parent 2ce67f8 commit 2ff351d
Show file tree
Hide file tree
Showing 7 changed files with 1,057 additions and 64 deletions.
97 changes: 87 additions & 10 deletions pkg/expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -4738,7 +4738,7 @@ func getBf4TimeAddSub(ctx BuildContext, funcName string, args []Expression) (tp1
case mysql.TypeDuration:
argTp1, retTp = types.ETDuration, types.ETDuration
case mysql.TypeDate:
argTp1, retTp = types.ETDuration, types.ETString
argTp1, retTp = types.ETDatetime, types.ETString
default:
argTp1, retTp = types.ETString, types.ETString
}
Expand Down Expand Up @@ -4969,11 +4969,20 @@ func (b *builtinAddDatetimeAndDurationSig) evalTime(ctx EvalContext, row chunk.R
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}

if arg0.IsZero() {
return types.ZeroDatetime, true, nil
}

arg1, isNull, err := b.args[1].EvalDuration(ctx, row)
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}
result, err := arg0.Add(typeCtx(ctx), arg1)
if err != nil {
return types.ZeroDatetime, true, err
}

return result, err != nil, err
}

Expand All @@ -4997,6 +5006,11 @@ func (b *builtinAddDatetimeAndStringSig) evalTime(ctx EvalContext, row chunk.Row
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}

if arg0.IsZero() {
return types.ZeroDatetime, true, nil
}

s, isNull, err := b.args[1].EvalString(ctx, row)
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
Expand All @@ -5014,6 +5028,10 @@ func (b *builtinAddDatetimeAndStringSig) evalTime(ctx EvalContext, row chunk.Row
return types.ZeroDatetime, true, err
}
result, err := arg0.Add(tc, arg1)
if err != nil {
return types.ZeroDatetime, true, err
}

return result, err != nil, err
}

Expand Down Expand Up @@ -5255,15 +5273,26 @@ func (b *builtinAddDateAndDurationSig) Clone() builtinFunc {
// evalString evals a builtinAddDurationAndDurationSig.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime
func (b *builtinAddDateAndDurationSig) evalString(ctx EvalContext, row chunk.Row) (string, bool, error) {
arg0, isNull, err := b.args[0].EvalDuration(ctx, row)
arg0, isNull, err := b.args[0].EvalTime(ctx, row)
if isNull || err != nil {
return "", isNull, err
}

if arg0.IsZero() {
return "", true, nil
}

arg1, isNull, err := b.args[1].EvalDuration(ctx, row)
if isNull || err != nil {
return "", isNull, err
}
result, err := arg0.Add(arg1)

arg0.SetType(mysql.TypeDatetime)
result, err := arg0.Add(typeCtx(ctx), arg1)
if err != nil {
return "", true, err
}

return result.String(), err != nil, err
}

Expand All @@ -5283,10 +5312,15 @@ func (b *builtinAddDateAndStringSig) Clone() builtinFunc {
// evalString evals a builtinAddDateAndStringSig.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime
func (b *builtinAddDateAndStringSig) evalString(ctx EvalContext, row chunk.Row) (string, bool, error) {
arg0, isNull, err := b.args[0].EvalDuration(ctx, row)
arg0, isNull, err := b.args[0].EvalTime(ctx, row)
if isNull || err != nil {
return "", isNull, err
}

if arg0.IsZero() {
return "", true, nil
}

s, isNull, err := b.args[1].EvalString(ctx, row)
if isNull || err != nil {
return "", isNull, err
Expand All @@ -5303,7 +5337,13 @@ func (b *builtinAddDateAndStringSig) evalString(ctx EvalContext, row chunk.Row)
}
return "", true, err
}
result, err := arg0.Add(arg1)

arg0.SetType(mysql.TypeDatetime)
result, err := arg0.Add(tc, arg1)
if err != nil {
return "", true, err
}

return result.String(), err != nil, err
}

Expand Down Expand Up @@ -5970,12 +6010,21 @@ func (b *builtinSubDatetimeAndDurationSig) evalTime(ctx EvalContext, row chunk.R
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}

if arg0.IsZero() {
return types.ZeroDatetime, true, nil
}

arg1, isNull, err := b.args[1].EvalDuration(ctx, row)
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}
tc := typeCtx(ctx)
result, err := arg0.Add(tc, arg1.Neg())
if err != nil {
return types.ZeroDatetime, true, err
}

return result, err != nil, err
}

Expand All @@ -5999,6 +6048,11 @@ func (b *builtinSubDatetimeAndStringSig) evalTime(ctx EvalContext, row chunk.Row
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
}

if arg0.IsZero() {
return types.ZeroDatetime, true, nil
}

s, isNull, err := b.args[1].EvalString(ctx, row)
if isNull || err != nil {
return types.ZeroDatetime, isNull, err
Expand All @@ -6016,6 +6070,10 @@ func (b *builtinSubDatetimeAndStringSig) evalTime(ctx EvalContext, row chunk.Row
return types.ZeroDatetime, true, err
}
result, err := arg0.Add(tc, arg1.Neg())
if err != nil {
return types.ZeroDatetime, true, err
}

return result, err != nil, err
}

Expand Down Expand Up @@ -6263,15 +6321,26 @@ func (b *builtinSubDateAndDurationSig) Clone() builtinFunc {
// evalString evals a builtinSubDateAndDurationSig.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime
func (b *builtinSubDateAndDurationSig) evalString(ctx EvalContext, row chunk.Row) (string, bool, error) {
arg0, isNull, err := b.args[0].EvalDuration(ctx, row)
arg0, isNull, err := b.args[0].EvalTime(ctx, row)
if isNull || err != nil {
return "", isNull, err
}

if arg0.IsZero() {
return "", true, nil
}

arg1, isNull, err := b.args[1].EvalDuration(ctx, row)
if isNull || err != nil {
return "", isNull, err
}
result, err := arg0.Sub(arg1)

arg0.SetType(mysql.TypeDatetime)
result, err := arg0.Add(typeCtx(ctx), arg1.Neg())
if err != nil {
return "", true, err
}

return result.String(), err != nil, err
}

Expand All @@ -6291,10 +6360,15 @@ func (b *builtinSubDateAndStringSig) Clone() builtinFunc {
// evalString evals a builtinSubDateAndStringSig.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime
func (b *builtinSubDateAndStringSig) evalString(ctx EvalContext, row chunk.Row) (string, bool, error) {
arg0, isNull, err := b.args[0].EvalDuration(ctx, row)
arg0, isNull, err := b.args[0].EvalTime(ctx, row)
if isNull || err != nil {
return "", isNull, err
}

if arg0.IsZero() {
return "", true, nil
}

s, isNull, err := b.args[1].EvalString(ctx, row)
if isNull || err != nil {
return "", isNull, err
Expand All @@ -6311,11 +6385,14 @@ func (b *builtinSubDateAndStringSig) evalString(ctx EvalContext, row chunk.Row)
}
return "", true, err
}
result, err := arg0.Sub(arg1)

arg0.SetType(mysql.TypeDatetime)
result, err := arg0.Add(tc, arg1.Neg())
if err != nil {
return "", true, err
}
return result.String(), false, nil

return result.String(), err != nil, err
}

type timeFormatFunctionClass struct {
Expand Down
Loading

0 comments on commit 2ff351d

Please sign in to comment.