Skip to content

Commit 5002d4d

Browse files
committed
Support add datetime with real interval
1 parent 37e8241 commit 5002d4d

File tree

2 files changed

+266
-2
lines changed

2 files changed

+266
-2
lines changed

expression/builtin_time.go

Lines changed: 244 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,21 +217,27 @@ var (
217217
_ builtinFunc = &builtinExtractDurationSig{}
218218
_ builtinFunc = &builtinAddDateStringStringSig{}
219219
_ builtinFunc = &builtinAddDateStringIntSig{}
220+
_ builtinFunc = &builtinAddDateStringRealSig{}
220221
_ builtinFunc = &builtinAddDateStringDecimalSig{}
221222
_ builtinFunc = &builtinAddDateIntStringSig{}
222223
_ builtinFunc = &builtinAddDateIntIntSig{}
224+
_ builtinFunc = &builtinAddDateIntRealSig{}
223225
_ builtinFunc = &builtinAddDateIntDecimalSig{}
224226
_ builtinFunc = &builtinAddDateDatetimeStringSig{}
225227
_ builtinFunc = &builtinAddDateDatetimeIntSig{}
228+
_ builtinFunc = &builtinAddDateDatetimeRealSig{}
226229
_ builtinFunc = &builtinAddDateDatetimeDecimalSig{}
227230
_ builtinFunc = &builtinSubDateStringStringSig{}
228231
_ builtinFunc = &builtinSubDateStringIntSig{}
232+
_ builtinFunc = &builtinSubDateStringRealSig{}
229233
_ builtinFunc = &builtinSubDateStringDecimalSig{}
230234
_ builtinFunc = &builtinSubDateIntStringSig{}
231235
_ builtinFunc = &builtinSubDateIntIntSig{}
236+
_ builtinFunc = &builtinSubDateIntRealSig{}
232237
_ builtinFunc = &builtinSubDateIntDecimalSig{}
233238
_ builtinFunc = &builtinSubDateDatetimeStringSig{}
234239
_ builtinFunc = &builtinSubDateDatetimeIntSig{}
240+
_ builtinFunc = &builtinSubDateDatetimeRealSig{}
235241
_ builtinFunc = &builtinSubDateDatetimeDecimalSig{}
236242
)
237243

@@ -2703,6 +2709,14 @@ func (du *baseDateArithmitical) getIntervalFromInt(ctx sessionctx.Context, args
27032709
return strconv.FormatInt(interval, 10), false, nil
27042710
}
27052711

2712+
func (du *baseDateArithmitical) getIntervalFromReal(ctx sessionctx.Context, args []Expression, row chunk.Row, unit string) (string, bool, error) {
2713+
interval, isNull, err := args[1].EvalReal(ctx, row)
2714+
if isNull || err != nil {
2715+
return "", true, err
2716+
}
2717+
return strconv.FormatFloat(interval, 'f', -1, 64), false, nil
2718+
}
2719+
27062720
func (du *baseDateArithmitical) add(ctx sessionctx.Context, date types.Time, interval string, unit string) (types.Time, bool, error) {
27072721
year, month, day, dur, err := types.ExtractTimeValue(unit, interval)
27082722
if err != nil {
@@ -2783,7 +2797,7 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
27832797
}
27842798

27852799
intervalEvalTp := args[1].GetType().EvalType()
2786-
if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal {
2800+
if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal && intervalEvalTp != types.ETReal {
27872801
intervalEvalTp = types.ETInt
27882802
}
27892803

@@ -2802,6 +2816,11 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28022816
baseBuiltinFunc: bf,
28032817
baseDateArithmitical: newDateArighmeticalUtil(),
28042818
}
2819+
case dateEvalTp == types.ETString && intervalEvalTp == types.ETReal:
2820+
sig = &builtinAddDateStringRealSig{
2821+
baseBuiltinFunc: bf,
2822+
baseDateArithmitical: newDateArighmeticalUtil(),
2823+
}
28052824
case dateEvalTp == types.ETString && intervalEvalTp == types.ETDecimal:
28062825
sig = &builtinAddDateStringDecimalSig{
28072826
baseBuiltinFunc: bf,
@@ -2817,6 +2836,11 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28172836
baseBuiltinFunc: bf,
28182837
baseDateArithmitical: newDateArighmeticalUtil(),
28192838
}
2839+
case dateEvalTp == types.ETInt && intervalEvalTp == types.ETReal:
2840+
sig = &builtinAddDateIntRealSig{
2841+
baseBuiltinFunc: bf,
2842+
baseDateArithmitical: newDateArighmeticalUtil(),
2843+
}
28202844
case dateEvalTp == types.ETInt && intervalEvalTp == types.ETDecimal:
28212845
sig = &builtinAddDateIntDecimalSig{
28222846
baseBuiltinFunc: bf,
@@ -2832,6 +2856,11 @@ func (c *addDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
28322856
baseBuiltinFunc: bf,
28332857
baseDateArithmitical: newDateArighmeticalUtil(),
28342858
}
2859+
case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETReal:
2860+
sig = &builtinAddDateDatetimeRealSig{
2861+
baseBuiltinFunc: bf,
2862+
baseDateArithmitical: newDateArighmeticalUtil(),
2863+
}
28352864
case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETDecimal:
28362865
sig = &builtinAddDateDatetimeDecimalSig{
28372866
baseBuiltinFunc: bf,
@@ -2907,6 +2936,39 @@ func (b *builtinAddDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool,
29072936
return result, isNull || err != nil, err
29082937
}
29092938

2939+
type builtinAddDateStringRealSig struct {
2940+
baseBuiltinFunc
2941+
baseDateArithmitical
2942+
}
2943+
2944+
func (b *builtinAddDateStringRealSig) Clone() builtinFunc {
2945+
newSig := &builtinAddDateStringRealSig{baseDateArithmitical: b.baseDateArithmitical}
2946+
newSig.cloneFrom(&b.baseBuiltinFunc)
2947+
return newSig
2948+
}
2949+
2950+
// evalTime evals ADDDATE(date,INTERVAL expr unit).
2951+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate
2952+
func (b *builtinAddDateStringRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
2953+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
2954+
if isNull || err != nil {
2955+
return types.Time{}, true, err
2956+
}
2957+
2958+
date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit)
2959+
if isNull || err != nil {
2960+
return types.Time{}, true, err
2961+
}
2962+
2963+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
2964+
if isNull || err != nil {
2965+
return types.Time{}, true, err
2966+
}
2967+
2968+
result, isNull, err := b.add(b.ctx, date, interval, unit)
2969+
return result, isNull || err != nil, err
2970+
}
2971+
29102972
type builtinAddDateStringDecimalSig struct {
29112973
baseBuiltinFunc
29122974
baseDateArithmitical
@@ -3006,6 +3068,39 @@ func (b *builtinAddDateIntIntSig) evalTime(row chunk.Row) (types.Time, bool, err
30063068
return result, isNull || err != nil, err
30073069
}
30083070

3071+
type builtinAddDateIntRealSig struct {
3072+
baseBuiltinFunc
3073+
baseDateArithmitical
3074+
}
3075+
3076+
func (b *builtinAddDateIntRealSig) Clone() builtinFunc {
3077+
newSig := &builtinAddDateIntRealSig{baseDateArithmitical: b.baseDateArithmitical}
3078+
newSig.cloneFrom(&b.baseBuiltinFunc)
3079+
return newSig
3080+
}
3081+
3082+
// evalTime evals ADDDATE(date,INTERVAL expr unit).
3083+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate
3084+
func (b *builtinAddDateIntRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
3085+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
3086+
if isNull || err != nil {
3087+
return types.Time{}, true, err
3088+
}
3089+
3090+
date, isNull, err := b.getDateFromInt(b.ctx, b.args, row, unit)
3091+
if isNull || err != nil {
3092+
return types.Time{}, true, err
3093+
}
3094+
3095+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
3096+
if isNull || err != nil {
3097+
return types.Time{}, true, err
3098+
}
3099+
3100+
result, isNull, err := b.add(b.ctx, date, interval, unit)
3101+
return result, isNull || err != nil, err
3102+
}
3103+
30093104
type builtinAddDateIntDecimalSig struct {
30103105
baseBuiltinFunc
30113106
baseDateArithmitical
@@ -3105,6 +3200,39 @@ func (b *builtinAddDateDatetimeIntSig) evalTime(row chunk.Row) (types.Time, bool
31053200
return result, isNull || err != nil, err
31063201
}
31073202

3203+
type builtinAddDateDatetimeRealSig struct {
3204+
baseBuiltinFunc
3205+
baseDateArithmitical
3206+
}
3207+
3208+
func (b *builtinAddDateDatetimeRealSig) Clone() builtinFunc {
3209+
newSig := &builtinAddDateDatetimeRealSig{baseDateArithmitical: b.baseDateArithmitical}
3210+
newSig.cloneFrom(&b.baseBuiltinFunc)
3211+
return newSig
3212+
}
3213+
3214+
// evalTime evals ADDDATE(date,INTERVAL expr unit).
3215+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate
3216+
func (b *builtinAddDateDatetimeRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
3217+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
3218+
if isNull || err != nil {
3219+
return types.Time{}, true, err
3220+
}
3221+
3222+
date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, row, unit)
3223+
if isNull || err != nil {
3224+
return types.Time{}, true, err
3225+
}
3226+
3227+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
3228+
if isNull || err != nil {
3229+
return types.Time{}, true, err
3230+
}
3231+
3232+
result, isNull, err := b.add(b.ctx, date, interval, unit)
3233+
return result, isNull || err != nil, err
3234+
}
3235+
31083236
type builtinAddDateDatetimeDecimalSig struct {
31093237
baseBuiltinFunc
31103238
baseDateArithmitical
@@ -3153,7 +3281,7 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
31533281
}
31543282

31553283
intervalEvalTp := args[1].GetType().EvalType()
3156-
if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal {
3284+
if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal && intervalEvalTp != types.ETReal {
31573285
intervalEvalTp = types.ETInt
31583286
}
31593287

@@ -3172,6 +3300,11 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
31723300
baseBuiltinFunc: bf,
31733301
baseDateArithmitical: newDateArighmeticalUtil(),
31743302
}
3303+
case dateEvalTp == types.ETString && intervalEvalTp == types.ETReal:
3304+
sig = &builtinSubDateStringRealSig{
3305+
baseBuiltinFunc: bf,
3306+
baseDateArithmitical: newDateArighmeticalUtil(),
3307+
}
31753308
case dateEvalTp == types.ETString && intervalEvalTp == types.ETDecimal:
31763309
sig = &builtinSubDateStringDecimalSig{
31773310
baseBuiltinFunc: bf,
@@ -3187,6 +3320,11 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
31873320
baseBuiltinFunc: bf,
31883321
baseDateArithmitical: newDateArighmeticalUtil(),
31893322
}
3323+
case dateEvalTp == types.ETInt && intervalEvalTp == types.ETReal:
3324+
sig = &builtinSubDateIntRealSig{
3325+
baseBuiltinFunc: bf,
3326+
baseDateArithmitical: newDateArighmeticalUtil(),
3327+
}
31903328
case dateEvalTp == types.ETInt && intervalEvalTp == types.ETDecimal:
31913329
sig = &builtinSubDateIntDecimalSig{
31923330
baseBuiltinFunc: bf,
@@ -3202,6 +3340,11 @@ func (c *subDateFunctionClass) getFunction(ctx sessionctx.Context, args []Expres
32023340
baseBuiltinFunc: bf,
32033341
baseDateArithmitical: newDateArighmeticalUtil(),
32043342
}
3343+
case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETReal:
3344+
sig = &builtinSubDateDatetimeRealSig{
3345+
baseBuiltinFunc: bf,
3346+
baseDateArithmitical: newDateArighmeticalUtil(),
3347+
}
32053348
case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETDecimal:
32063349
sig = &builtinSubDateDatetimeDecimalSig{
32073350
baseBuiltinFunc: bf,
@@ -3277,6 +3420,39 @@ func (b *builtinSubDateStringIntSig) evalTime(row chunk.Row) (types.Time, bool,
32773420
return result, isNull || err != nil, err
32783421
}
32793422

3423+
type builtinSubDateStringRealSig struct {
3424+
baseBuiltinFunc
3425+
baseDateArithmitical
3426+
}
3427+
3428+
func (b *builtinSubDateStringRealSig) Clone() builtinFunc {
3429+
newSig := &builtinSubDateStringRealSig{baseDateArithmitical: b.baseDateArithmitical}
3430+
newSig.cloneFrom(&b.baseBuiltinFunc)
3431+
return newSig
3432+
}
3433+
3434+
// evalTime evals SUBDATE(date,INTERVAL expr unit).
3435+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate
3436+
func (b *builtinSubDateStringRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
3437+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
3438+
if isNull || err != nil {
3439+
return types.Time{}, true, err
3440+
}
3441+
3442+
date, isNull, err := b.getDateFromString(b.ctx, b.args, row, unit)
3443+
if isNull || err != nil {
3444+
return types.Time{}, true, err
3445+
}
3446+
3447+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
3448+
if isNull || err != nil {
3449+
return types.Time{}, true, err
3450+
}
3451+
3452+
result, isNull, err := b.sub(b.ctx, date, interval, unit)
3453+
return result, isNull || err != nil, err
3454+
}
3455+
32803456
type builtinSubDateStringDecimalSig struct {
32813457
baseBuiltinFunc
32823458
baseDateArithmitical
@@ -3374,6 +3550,39 @@ func (b *builtinSubDateIntIntSig) evalTime(row chunk.Row) (types.Time, bool, err
33743550
return result, isNull || err != nil, err
33753551
}
33763552

3553+
type builtinSubDateIntRealSig struct {
3554+
baseBuiltinFunc
3555+
baseDateArithmitical
3556+
}
3557+
3558+
func (b *builtinSubDateIntRealSig) Clone() builtinFunc {
3559+
newSig := &builtinSubDateIntRealSig{baseDateArithmitical: b.baseDateArithmitical}
3560+
newSig.cloneFrom(&b.baseBuiltinFunc)
3561+
return newSig
3562+
}
3563+
3564+
// evalTime evals SUBDATE(date,INTERVAL expr unit).
3565+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate
3566+
func (b *builtinSubDateIntRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
3567+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
3568+
if isNull || err != nil {
3569+
return types.Time{}, true, err
3570+
}
3571+
3572+
date, isNull, err := b.getDateFromInt(b.ctx, b.args, row, unit)
3573+
if isNull || err != nil {
3574+
return types.Time{}, true, err
3575+
}
3576+
3577+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
3578+
if isNull || err != nil {
3579+
return types.Time{}, true, err
3580+
}
3581+
3582+
result, isNull, err := b.sub(b.ctx, date, interval, unit)
3583+
return result, isNull || err != nil, err
3584+
}
3585+
33773586
type builtinSubDateDatetimeStringSig struct {
33783587
baseBuiltinFunc
33793588
baseDateArithmitical
@@ -3473,6 +3682,39 @@ func (b *builtinSubDateDatetimeIntSig) evalTime(row chunk.Row) (types.Time, bool
34733682
return result, isNull || err != nil, err
34743683
}
34753684

3685+
type builtinSubDateDatetimeRealSig struct {
3686+
baseBuiltinFunc
3687+
baseDateArithmitical
3688+
}
3689+
3690+
func (b *builtinSubDateDatetimeRealSig) Clone() builtinFunc {
3691+
newSig := &builtinSubDateDatetimeRealSig{baseDateArithmitical: b.baseDateArithmitical}
3692+
newSig.cloneFrom(&b.baseBuiltinFunc)
3693+
return newSig
3694+
}
3695+
3696+
// evalTime evals SUBDATE(date,INTERVAL expr unit).
3697+
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate
3698+
func (b *builtinSubDateDatetimeRealSig) evalTime(row chunk.Row) (types.Time, bool, error) {
3699+
unit, isNull, err := b.args[2].EvalString(b.ctx, row)
3700+
if isNull || err != nil {
3701+
return types.Time{}, true, err
3702+
}
3703+
3704+
date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, row, unit)
3705+
if isNull || err != nil {
3706+
return types.Time{}, true, err
3707+
}
3708+
3709+
interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, row, unit)
3710+
if isNull || err != nil {
3711+
return types.Time{}, true, err
3712+
}
3713+
3714+
result, isNull, err := b.sub(b.ctx, date, interval, unit)
3715+
return result, isNull || err != nil, err
3716+
}
3717+
34763718
type builtinSubDateDatetimeDecimalSig struct {
34773719
baseBuiltinFunc
34783720
baseDateArithmitical

expression/integration_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4267,3 +4267,25 @@ func (s *testIntegrationSuite) TestTimestampDatumEncode(c *C) {
42674267
))
42684268
tk.MustQuery(`select * from t where b = (select max(b) from t)`).Check(testkit.Rows(`1 2019-04-29 11:56:12`))
42694269
}
4270+
4271+
func (s *testIntegrationSuite) TestDateTimeAddReal(c *C) {
4272+
tk := testkit.NewTestKit(c, s.store)
4273+
defer s.cleanEnv(c)
4274+
4275+
cases := []struct {
4276+
sql string
4277+
result string
4278+
}{
4279+
{`SELECT "1900-01-01 00:00:00" + INTERVAL 1.123456789e3 SECOND;`, "1900-01-01 00:18:43.456789"},
4280+
{`SELECT 19000101000000 + INTERVAL 1.123456789e3 SECOND;`, "1900-01-01 00:18:43.456789"},
4281+
{`select date("1900-01-01") + interval 1.123456789e3 second;`, "1900-01-01 00:18:43.456789"},
4282+
{`SELECT "1900-01-01 00:18:43.456789" - INTERVAL 1.123456789e3 SECOND;`, "1900-01-01 00:00:00"},
4283+
{`SELECT 19000101001843.456789 - INTERVAL 1.123456789e3 SECOND;`, "1900-01-01 00:00:00"},
4284+
{`select date("1900-01-01") - interval 1.123456789e3 second;`, "1899-12-31 23:41:16.543211"},
4285+
{`select 19000101000000 - interval 1.123456789e3 second;`, "1899-12-31 23:41:16.543211"},
4286+
}
4287+
4288+
for _, c := range cases {
4289+
tk.MustQuery(c.sql).Check(testkit.Rows(c.result))
4290+
}
4291+
}

0 commit comments

Comments
 (0)