@@ -2727,6 +2727,18 @@ func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, int
27272727 return date , false , nil
27282728}
27292729
2730+ func (du * baseDateArithmitical ) addDuration (ctx sessionctx.Context , d types.Duration , interval string , unit string ) (types.Duration , bool , error ) {
2731+ dur , err := types .ExtractDurationValue (unit , interval )
2732+ if err != nil {
2733+ return types .ZeroDuration , true , handleInvalidTimeError (ctx , err )
2734+ }
2735+ retDur , err := d .Add (dur )
2736+ if err != nil {
2737+ return types .ZeroDuration , true , err
2738+ }
2739+ return retDur , false , nil
2740+ }
2741+
27302742func (du * baseDateArithmitical ) sub (ctx sessionctx.Context , date types.Time , interval string , unit string ) (types.Time , bool , error ) {
27312743 year , month , day , nano , err := types .ParseDurationValue (unit , interval )
27322744 if err := handleInvalidTimeError (ctx , err ); err != nil {
@@ -2770,7 +2782,7 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
27702782 }
27712783
27722784 dateEvalTp := args [0 ].GetType ().EvalType ()
2773- if dateEvalTp != types .ETString && dateEvalTp != types .ETInt {
2785+ if dateEvalTp != types .ETString && dateEvalTp != types .ETInt && dateEvalTp != types . ETDuration {
27742786 dateEvalTp = types .ETDatetime
27752787 }
27762788
@@ -2780,8 +2792,35 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
27802792 }
27812793
27822794 argTps := []types.EvalType {dateEvalTp , intervalEvalTp , types .ETString }
2783- bf := newBaseBuiltinFuncWithTp (ctx , args , types .ETDatetime , argTps ... )
2784- bf .tp .Flen , bf .tp .Decimal = mysql .MaxDatetimeFullWidth , types .UnspecifiedLength
2795+ var bf baseBuiltinFunc
2796+ if dateEvalTp == types .ETDuration {
2797+ unit , _ , err := args [2 ].EvalString (ctx , chunk.Row {})
2798+ if err != nil {
2799+ return nil , err
2800+ }
2801+ internalFsp := 0
2802+ switch unit {
2803+ // If the unit has micro second, then the fsp must be the MaxFsp.
2804+ case "MICROSECOND" , "SECOND_MICROSECOND" , "MINUTE_MICROSECOND" , "HOUR_MICROSECOND" , "DAY_MICROSECOND" :
2805+ internalFsp = types .MaxFsp
2806+ // If the unit is second, the fsp is related with the arg[1]'s.
2807+ case "SECOND" :
2808+ internalFsp = types .MaxFsp
2809+ if intervalEvalTp != types .ETString {
2810+ internalFsp = mathutil .Min (args [1 ].GetType ().Decimal , types .MaxFsp )
2811+ }
2812+ // Otherwise, the fsp should be 0.
2813+ }
2814+ bf = newBaseBuiltinFuncWithTp (ctx , args , types .ETDuration , argTps ... )
2815+ arg0Dec , err := getExpressionFsp (ctx , args [0 ])
2816+ if err != nil {
2817+ return nil , err
2818+ }
2819+ bf .tp .Flen , bf .tp .Decimal = mysql .MaxDurationWidthWithFsp , mathutil .Max (arg0Dec , internalFsp )
2820+ } else {
2821+ bf = newBaseBuiltinFuncWithTp (ctx , args , types .ETDatetime , argTps ... )
2822+ bf .tp .Flen , bf .tp .Decimal = mysql .MaxDatetimeFullWidth , types .UnspecifiedLength
2823+ }
27852824
27862825 switch {
27872826 case dateEvalTp == types .ETString && intervalEvalTp == types .ETString :
@@ -2844,6 +2883,21 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28442883 baseBuiltinFunc : bf ,
28452884 baseDateArithmitical : newDateArighmeticalUtil (),
28462885 }
2886+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETString :
2887+ sig = & builtinAddDateDurationStringSig {
2888+ baseBuiltinFunc : bf ,
2889+ baseDateArithmitical : newDateArighmeticalUtil (),
2890+ }
2891+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETInt :
2892+ sig = & builtinAddDateDurationIntSig {
2893+ baseBuiltinFunc : bf ,
2894+ baseDateArithmitical : newDateArighmeticalUtil (),
2895+ }
2896+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETDecimal :
2897+ sig = & builtinAddDateDurationDecimalSig {
2898+ baseBuiltinFunc : bf ,
2899+ baseDateArithmitical : newDateArighmeticalUtil (),
2900+ }
28472901 }
28482902 return sig , nil
28492903}
@@ -3244,6 +3298,79 @@ func (b *builtinAddDateDatetimeDecimalSig) evalTime(row chunk.Row) (types.Time,
32443298 return result , isNull || err != nil , errors .Trace (err )
32453299}
32463300
3301+ type builtinAddDateDurationStringSig struct {
3302+ baseBuiltinFunc
3303+ baseDateArithmitical
3304+ }
3305+
3306+ func (b * builtinAddDateDurationStringSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3307+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3308+ if isNull || err != nil {
3309+ return types .ZeroDuration , true , err
3310+ }
3311+
3312+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3313+ if isNull || err != nil {
3314+ return types .ZeroDuration , true , err
3315+ }
3316+
3317+ interval , isNull , err := b .getIntervalFromString (b .ctx , b .args , row , unit )
3318+ if isNull || err != nil {
3319+ return types .ZeroDuration , true , err
3320+ }
3321+
3322+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3323+ return result , isNull || err != nil , err
3324+ }
3325+
3326+ type builtinAddDateDurationIntSig struct {
3327+ baseBuiltinFunc
3328+ baseDateArithmitical
3329+ }
3330+
3331+ func (b * builtinAddDateDurationIntSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3332+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3333+ if isNull || err != nil {
3334+ return types .ZeroDuration , true , err
3335+ }
3336+
3337+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3338+ if isNull || err != nil {
3339+ return types .ZeroDuration , true , err
3340+ }
3341+ interval , isNull , err := b .getIntervalFromInt (b .ctx , b .args , row , unit )
3342+ if isNull || err != nil {
3343+ return types .ZeroDuration , true , err
3344+ }
3345+
3346+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3347+ return result , isNull || err != nil , err
3348+ }
3349+
3350+ type builtinAddDateDurationDecimalSig struct {
3351+ baseBuiltinFunc
3352+ baseDateArithmitical
3353+ }
3354+
3355+ func (b * builtinAddDateDurationDecimalSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3356+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3357+ if isNull || err != nil {
3358+ return types .ZeroDuration , true , err
3359+ }
3360+
3361+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3362+ if isNull || err != nil {
3363+ return types .ZeroDuration , true , err
3364+ }
3365+ interval , isNull , err := b .getIntervalFromDecimal (b .ctx , b .args , row , unit )
3366+ if isNull || err != nil {
3367+ return types .ZeroDuration , true , err
3368+ }
3369+
3370+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3371+ return result , isNull || err != nil , err
3372+ }
3373+
32473374type subDateFunctionClass struct {
32483375 baseFunctionClass
32493376}
0 commit comments