@@ -2748,6 +2748,18 @@ func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, int
27482748 return date , false , nil
27492749}
27502750
2751+ func (du * baseDateArithmitical ) addDuration (ctx sessionctx.Context , d types.Duration , interval string , unit string ) (types.Duration , bool , error ) {
2752+ dur , err := types .ExtractDurationValue (unit , interval )
2753+ if err != nil {
2754+ return types .ZeroDuration , true , handleInvalidTimeError (ctx , err )
2755+ }
2756+ retDur , err := d .Add (dur )
2757+ if err != nil {
2758+ return types .ZeroDuration , true , err
2759+ }
2760+ return retDur , false , nil
2761+ }
2762+
27512763func (du * baseDateArithmitical ) sub (ctx sessionctx.Context , date types.Time , interval string , unit string ) (types.Time , bool , error ) {
27522764 year , month , day , nano , err := types .ParseDurationValue (unit , interval )
27532765 if err := handleInvalidTimeError (ctx , err ); err != nil {
@@ -2791,7 +2803,7 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
27912803 }
27922804
27932805 dateEvalTp := args [0 ].GetType ().EvalType ()
2794- if dateEvalTp != types .ETString && dateEvalTp != types .ETInt {
2806+ if dateEvalTp != types .ETString && dateEvalTp != types .ETInt && dateEvalTp != types . ETDuration {
27952807 dateEvalTp = types .ETDatetime
27962808 }
27972809
@@ -2801,8 +2813,35 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28012813 }
28022814
28032815 argTps := []types.EvalType {dateEvalTp , intervalEvalTp , types .ETString }
2804- bf := newBaseBuiltinFuncWithTp (ctx , args , types .ETDatetime , argTps ... )
2805- bf .tp .Flen , bf .tp .Decimal = mysql .MaxDatetimeFullWidth , types .UnspecifiedLength
2816+ var bf baseBuiltinFunc
2817+ if dateEvalTp == types .ETDuration {
2818+ unit , _ , err := args [2 ].EvalString (ctx , chunk.Row {})
2819+ if err != nil {
2820+ return nil , err
2821+ }
2822+ internalFsp := 0
2823+ switch unit {
2824+ // If the unit has micro second, then the fsp must be the MaxFsp.
2825+ case "MICROSECOND" , "SECOND_MICROSECOND" , "MINUTE_MICROSECOND" , "HOUR_MICROSECOND" , "DAY_MICROSECOND" :
2826+ internalFsp = types .MaxFsp
2827+ // If the unit is second, the fsp is related with the arg[1]'s.
2828+ case "SECOND" :
2829+ internalFsp = types .MaxFsp
2830+ if intervalEvalTp != types .ETString {
2831+ internalFsp = mathutil .Min (args [1 ].GetType ().Decimal , types .MaxFsp )
2832+ }
2833+ // Otherwise, the fsp should be 0.
2834+ }
2835+ bf = newBaseBuiltinFuncWithTp (ctx , args , types .ETDuration , argTps ... )
2836+ arg0Dec , err := getExpressionFsp (ctx , args [0 ])
2837+ if err != nil {
2838+ return nil , err
2839+ }
2840+ bf .tp .Flen , bf .tp .Decimal = mysql .MaxDurationWidthWithFsp , mathutil .Max (arg0Dec , internalFsp )
2841+ } else {
2842+ bf = newBaseBuiltinFuncWithTp (ctx , args , types .ETDatetime , argTps ... )
2843+ bf .tp .Flen , bf .tp .Decimal = mysql .MaxDatetimeFullWidth , types .UnspecifiedLength
2844+ }
28062845
28072846 switch {
28082847 case dateEvalTp == types .ETString && intervalEvalTp == types .ETString :
@@ -2865,6 +2904,21 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28652904 baseBuiltinFunc : bf ,
28662905 baseDateArithmitical : newDateArighmeticalUtil (),
28672906 }
2907+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETString :
2908+ sig = & builtinAddDateDurationStringSig {
2909+ baseBuiltinFunc : bf ,
2910+ baseDateArithmitical : newDateArighmeticalUtil (),
2911+ }
2912+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETInt :
2913+ sig = & builtinAddDateDurationIntSig {
2914+ baseBuiltinFunc : bf ,
2915+ baseDateArithmitical : newDateArighmeticalUtil (),
2916+ }
2917+ case dateEvalTp == types .ETDuration && intervalEvalTp == types .ETDecimal :
2918+ sig = & builtinAddDateDurationDecimalSig {
2919+ baseBuiltinFunc : bf ,
2920+ baseDateArithmitical : newDateArighmeticalUtil (),
2921+ }
28682922 }
28692923 return sig , nil
28702924}
@@ -3265,6 +3319,79 @@ func (b *builtinAddDateDatetimeDecimalSig) evalTime(row chunk.Row) (types.Time,
32653319 return result , isNull || err != nil , err
32663320}
32673321
3322+ type builtinAddDateDurationStringSig struct {
3323+ baseBuiltinFunc
3324+ baseDateArithmitical
3325+ }
3326+
3327+ func (b * builtinAddDateDurationStringSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3328+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3329+ if isNull || err != nil {
3330+ return types .ZeroDuration , true , err
3331+ }
3332+
3333+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3334+ if isNull || err != nil {
3335+ return types .ZeroDuration , true , err
3336+ }
3337+
3338+ interval , isNull , err := b .getIntervalFromString (b .ctx , b .args , row , unit )
3339+ if isNull || err != nil {
3340+ return types .ZeroDuration , true , err
3341+ }
3342+
3343+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3344+ return result , isNull || err != nil , err
3345+ }
3346+
3347+ type builtinAddDateDurationIntSig struct {
3348+ baseBuiltinFunc
3349+ baseDateArithmitical
3350+ }
3351+
3352+ func (b * builtinAddDateDurationIntSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3353+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3354+ if isNull || err != nil {
3355+ return types .ZeroDuration , true , err
3356+ }
3357+
3358+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3359+ if isNull || err != nil {
3360+ return types .ZeroDuration , true , err
3361+ }
3362+ interval , isNull , err := b .getIntervalFromInt (b .ctx , b .args , row , unit )
3363+ if isNull || err != nil {
3364+ return types .ZeroDuration , true , err
3365+ }
3366+
3367+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3368+ return result , isNull || err != nil , err
3369+ }
3370+
3371+ type builtinAddDateDurationDecimalSig struct {
3372+ baseBuiltinFunc
3373+ baseDateArithmitical
3374+ }
3375+
3376+ func (b * builtinAddDateDurationDecimalSig ) evalDuration (row chunk.Row ) (types.Duration , bool , error ) {
3377+ unit , isNull , err := b .args [2 ].EvalString (b .ctx , row )
3378+ if isNull || err != nil {
3379+ return types .ZeroDuration , true , err
3380+ }
3381+
3382+ dur , isNull , err := b .args [0 ].EvalDuration (b .ctx , row )
3383+ if isNull || err != nil {
3384+ return types .ZeroDuration , true , err
3385+ }
3386+ interval , isNull , err := b .getIntervalFromDecimal (b .ctx , b .args , row , unit )
3387+ if isNull || err != nil {
3388+ return types .ZeroDuration , true , err
3389+ }
3390+
3391+ result , isNull , err := b .addDuration (b .ctx , dur , interval , unit )
3392+ return result , isNull || err != nil , err
3393+ }
3394+
32683395type subDateFunctionClass struct {
32693396 baseFunctionClass
32703397}
0 commit comments