github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_time.go (about) 1 // Copyright 2020 The ql Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSES/QL-LICENSE file. 4 5 // Copyright 2020 WHTCORPS INC, Inc. 6 // 7 // Licensed under the Apache License, Version 2.0 (the "License"); 8 // you may not use this file except in compliance with the License. 9 // You may obtain a copy of the License at 10 // 11 // http://www.apache.org/licenses/LICENSE-2.0 12 // 13 // Unless required by applicable law or agreed to in writing, software 14 // distributed under the License is distributed on an "AS IS" BASIS, 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 package memex 19 20 import ( 21 "fmt" 22 "math" 23 "regexp" 24 "strconv" 25 "strings" 26 "time" 27 28 "github.com/cznic/mathutil" 29 "github.com/whtcorpsinc/errors" 30 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 31 "github.com/whtcorpsinc/BerolinaSQL/terror" 32 "github.com/whtcorpsinc/milevadb/stochastikctx" 33 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 34 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 35 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle" 36 "github.com/whtcorpsinc/milevadb/types" 37 "github.com/whtcorpsinc/milevadb/soliton/chunk" 38 "github.com/whtcorpsinc/milevadb/soliton/logutil" 39 "github.com/whtcorpsinc/fidelpb/go-fidelpb" 40 "go.uber.org/zap" 41 ) 42 43 const ( // GET_FORMAT first argument. 44 dateFormat = "DATE" 45 datetimeFormat = "DATETIME" 46 timestampFormat = "TIMESTAMP" 47 timeFormat = "TIME" 48 ) 49 50 const ( // GET_FORMAT location. 51 usaLocation = "USA" 52 jisLocation = "JIS" 53 isoLocation = "ISO" 54 eurLocation = "EUR" 55 internalLocation = "INTERNAL" 56 ) 57 58 var ( 59 // durationPattern checks whether a string matchs the format of duration. 60 durationPattern = regexp.MustCompile(`^\s*[-]?(((\d{1,2}\s+)?0*\d{0,3}(:0*\d{1,2}){0,2})|(\d{1,7}))?(\.\d*)?\s*$`) 61 62 // timestampPattern checks whether a string matchs the format of timestamp. 63 timestampPattern = regexp.MustCompile(`^\s*0*\d{1,4}([^\d]0*\d{1,2}){2}\s+(0*\d{0,2}([^\d]0*\d{1,2}){2})?(\.\d*)?\s*$`) 64 65 // datePattern determine whether to match the format of date. 66 datePattern = regexp.MustCompile(`^\s*((0*\d{1,4}([^\d]0*\d{1,2}){2})|(\d{2,4}(\d{2}){2}))\s*$`) 67 ) 68 69 var ( 70 _ functionClass = &dateFunctionClass{} 71 _ functionClass = &dateLiteralFunctionClass{} 72 _ functionClass = &dateDiffFunctionClass{} 73 _ functionClass = &timeDiffFunctionClass{} 74 _ functionClass = &dateFormatFunctionClass{} 75 _ functionClass = &hourFunctionClass{} 76 _ functionClass = &minuteFunctionClass{} 77 _ functionClass = &secondFunctionClass{} 78 _ functionClass = µSecondFunctionClass{} 79 _ functionClass = &monthFunctionClass{} 80 _ functionClass = &monthNameFunctionClass{} 81 _ functionClass = &nowFunctionClass{} 82 _ functionClass = &dayNameFunctionClass{} 83 _ functionClass = &dayOfMonthFunctionClass{} 84 _ functionClass = &dayOfWeekFunctionClass{} 85 _ functionClass = &dayOfYearFunctionClass{} 86 _ functionClass = &weekFunctionClass{} 87 _ functionClass = &weekDayFunctionClass{} 88 _ functionClass = &weekOfYearFunctionClass{} 89 _ functionClass = &yearFunctionClass{} 90 _ functionClass = &yearWeekFunctionClass{} 91 _ functionClass = &fromUnixTimeFunctionClass{} 92 _ functionClass = &getFormatFunctionClass{} 93 _ functionClass = &strToDateFunctionClass{} 94 _ functionClass = &sysDateFunctionClass{} 95 _ functionClass = ¤tDateFunctionClass{} 96 _ functionClass = ¤tTimeFunctionClass{} 97 _ functionClass = &timeFunctionClass{} 98 _ functionClass = &timeLiteralFunctionClass{} 99 _ functionClass = &utcDateFunctionClass{} 100 _ functionClass = &utcTimestampFunctionClass{} 101 _ functionClass = &extractFunctionClass{} 102 _ functionClass = &unixTimestampFunctionClass{} 103 _ functionClass = &addTimeFunctionClass{} 104 _ functionClass = &convertTzFunctionClass{} 105 _ functionClass = &makeDateFunctionClass{} 106 _ functionClass = &makeTimeFunctionClass{} 107 _ functionClass = &periodAddFunctionClass{} 108 _ functionClass = &periodDiffFunctionClass{} 109 _ functionClass = &quarterFunctionClass{} 110 _ functionClass = &secToTimeFunctionClass{} 111 _ functionClass = &subTimeFunctionClass{} 112 _ functionClass = &timeFormatFunctionClass{} 113 _ functionClass = &timeToSecFunctionClass{} 114 _ functionClass = ×tampAddFunctionClass{} 115 _ functionClass = &toDaysFunctionClass{} 116 _ functionClass = &toSecondsFunctionClass{} 117 _ functionClass = &utcTimeFunctionClass{} 118 _ functionClass = ×tampFunctionClass{} 119 _ functionClass = ×tampLiteralFunctionClass{} 120 _ functionClass = &lastDayFunctionClass{} 121 _ functionClass = &addDateFunctionClass{} 122 _ functionClass = &subDateFunctionClass{} 123 ) 124 125 var ( 126 _ builtinFuncNew = &builtinUnixTimestampIntSig{} 127 ) 128 129 var ( 130 _ builtinFunc = &builtinDateSig{} 131 _ builtinFunc = &builtinDateLiteralSig{} 132 _ builtinFunc = &builtinDateDiffSig{} 133 _ builtinFunc = &builtinNullTimeDiffSig{} 134 _ builtinFunc = &builtinTimeStringTimeDiffSig{} 135 _ builtinFunc = &builtinDurationStringTimeDiffSig{} 136 _ builtinFunc = &builtinDurationDurationTimeDiffSig{} 137 _ builtinFunc = &builtinStringTimeTimeDiffSig{} 138 _ builtinFunc = &builtinStringDurationTimeDiffSig{} 139 _ builtinFunc = &builtinStringStringTimeDiffSig{} 140 _ builtinFunc = &builtinTimeTimeTimeDiffSig{} 141 _ builtinFunc = &builtinDateFormatSig{} 142 _ builtinFunc = &builtinHourSig{} 143 _ builtinFunc = &builtinMinuteSig{} 144 _ builtinFunc = &builtinSecondSig{} 145 _ builtinFunc = &builtinMicroSecondSig{} 146 _ builtinFunc = &builtinMonthSig{} 147 _ builtinFunc = &builtinMonthNameSig{} 148 _ builtinFunc = &builtinNowWithArgSig{} 149 _ builtinFunc = &builtinNowWithoutArgSig{} 150 _ builtinFunc = &builtinDayNameSig{} 151 _ builtinFunc = &builtinDayOfMonthSig{} 152 _ builtinFunc = &builtinDayOfWeekSig{} 153 _ builtinFunc = &builtinDayOfYearSig{} 154 _ builtinFunc = &builtinWeekWithModeSig{} 155 _ builtinFunc = &builtinWeekWithoutModeSig{} 156 _ builtinFunc = &builtinWeekDaySig{} 157 _ builtinFunc = &builtinWeekOfYearSig{} 158 _ builtinFunc = &builtinYearSig{} 159 _ builtinFunc = &builtinYearWeekWithModeSig{} 160 _ builtinFunc = &builtinYearWeekWithoutModeSig{} 161 _ builtinFunc = &builtinGetFormatSig{} 162 _ builtinFunc = &builtinSysDateWithFspSig{} 163 _ builtinFunc = &builtinSysDateWithoutFspSig{} 164 _ builtinFunc = &builtinCurrentDateSig{} 165 _ builtinFunc = &builtinCurrentTime0ArgSig{} 166 _ builtinFunc = &builtinCurrentTime1ArgSig{} 167 _ builtinFunc = &builtinTimeSig{} 168 _ builtinFunc = &builtinTimeLiteralSig{} 169 _ builtinFunc = &builtinUTCDateSig{} 170 _ builtinFunc = &builtinUTCTimestampWithArgSig{} 171 _ builtinFunc = &builtinUTCTimestampWithoutArgSig{} 172 _ builtinFunc = &builtinAddDatetimeAndDurationSig{} 173 _ builtinFunc = &builtinAddDatetimeAndStringSig{} 174 _ builtinFunc = &builtinAddTimeDateTimeNullSig{} 175 _ builtinFunc = &builtinAddStringAndDurationSig{} 176 _ builtinFunc = &builtinAddStringAndStringSig{} 177 _ builtinFunc = &builtinAddTimeStringNullSig{} 178 _ builtinFunc = &builtinAddDurationAndDurationSig{} 179 _ builtinFunc = &builtinAddDurationAndStringSig{} 180 _ builtinFunc = &builtinAddTimeDurationNullSig{} 181 _ builtinFunc = &builtinAddDateAndDurationSig{} 182 _ builtinFunc = &builtinAddDateAndStringSig{} 183 _ builtinFunc = &builtinSubDatetimeAndDurationSig{} 184 _ builtinFunc = &builtinSubDatetimeAndStringSig{} 185 _ builtinFunc = &builtinSubTimeDateTimeNullSig{} 186 _ builtinFunc = &builtinSubStringAndDurationSig{} 187 _ builtinFunc = &builtinSubStringAndStringSig{} 188 _ builtinFunc = &builtinSubTimeStringNullSig{} 189 _ builtinFunc = &builtinSubDurationAndDurationSig{} 190 _ builtinFunc = &builtinSubDurationAndStringSig{} 191 _ builtinFunc = &builtinSubTimeDurationNullSig{} 192 _ builtinFunc = &builtinSubDateAndDurationSig{} 193 _ builtinFunc = &builtinSubDateAndStringSig{} 194 _ builtinFunc = &builtinUnixTimestampCurrentSig{} 195 _ builtinFunc = &builtinUnixTimestampIntSig{} 196 _ builtinFunc = &builtinUnixTimestamFIDelecSig{} 197 _ builtinFunc = &builtinConvertTzSig{} 198 _ builtinFunc = &builtinMakeDateSig{} 199 _ builtinFunc = &builtinMakeTimeSig{} 200 _ builtinFunc = &builtinPeriodAddSig{} 201 _ builtinFunc = &builtinPeriodDiffSig{} 202 _ builtinFunc = &builtinQuarterSig{} 203 _ builtinFunc = &builtinSecToTimeSig{} 204 _ builtinFunc = &builtinTimeToSecSig{} 205 _ builtinFunc = &builtinTimestampAddSig{} 206 _ builtinFunc = &builtinToDaysSig{} 207 _ builtinFunc = &builtinToSecondsSig{} 208 _ builtinFunc = &builtinUTCTimeWithArgSig{} 209 _ builtinFunc = &builtinUTCTimeWithoutArgSig{} 210 _ builtinFunc = &builtinTimestamp1ArgSig{} 211 _ builtinFunc = &builtinTimestamp2ArgsSig{} 212 _ builtinFunc = &builtinTimestampLiteralSig{} 213 _ builtinFunc = &builtinLastDaySig{} 214 _ builtinFunc = &builtinStrToDateDateSig{} 215 _ builtinFunc = &builtinStrToDateDatetimeSig{} 216 _ builtinFunc = &builtinStrToDateDurationSig{} 217 _ builtinFunc = &builtinFromUnixTime1ArgSig{} 218 _ builtinFunc = &builtinFromUnixTime2ArgSig{} 219 _ builtinFunc = &builtinExtractDatetimeSig{} 220 _ builtinFunc = &builtinExtractDurationSig{} 221 _ builtinFunc = &builtinAddDateStringStringSig{} 222 _ builtinFunc = &builtinAddDateStringIntSig{} 223 _ builtinFunc = &builtinAddDateStringRealSig{} 224 _ builtinFunc = &builtinAddDateStringDecimalSig{} 225 _ builtinFunc = &builtinAddDateIntStringSig{} 226 _ builtinFunc = &builtinAddDateIntIntSig{} 227 _ builtinFunc = &builtinAddDateIntRealSig{} 228 _ builtinFunc = &builtinAddDateIntDecimalSig{} 229 _ builtinFunc = &builtinAddDateDatetimeStringSig{} 230 _ builtinFunc = &builtinAddDateDatetimeIntSig{} 231 _ builtinFunc = &builtinAddDateDatetimeRealSig{} 232 _ builtinFunc = &builtinAddDateDatetimeDecimalSig{} 233 _ builtinFunc = &builtinSubDateStringStringSig{} 234 _ builtinFunc = &builtinSubDateStringIntSig{} 235 _ builtinFunc = &builtinSubDateStringRealSig{} 236 _ builtinFunc = &builtinSubDateStringDecimalSig{} 237 _ builtinFunc = &builtinSubDateIntStringSig{} 238 _ builtinFunc = &builtinSubDateIntIntSig{} 239 _ builtinFunc = &builtinSubDateIntRealSig{} 240 _ builtinFunc = &builtinSubDateIntDecimalSig{} 241 _ builtinFunc = &builtinSubDateDatetimeStringSig{} 242 _ builtinFunc = &builtinSubDateDatetimeIntSig{} 243 _ builtinFunc = &builtinSubDateDatetimeRealSig{} 244 _ builtinFunc = &builtinSubDateDatetimeDecimalSig{} 245 ) 246 247 func convertTimeToMysqlTime(t time.Time, fsp int8, roundMode types.RoundMode) (types.Time, error) { 248 var tr time.Time 249 var err error 250 if roundMode == types.ModeTruncate { 251 tr, err = types.TruncateFrac(t, fsp) 252 } else { 253 tr, err = types.RoundFrac(t, fsp) 254 } 255 if err != nil { 256 return types.ZeroTime, err 257 } 258 259 return types.NewTime(types.FromGoTime(tr), allegrosql.TypeDatetime, fsp), nil 260 } 261 262 type dateFunctionClass struct { 263 baseFunctionClass 264 } 265 266 func (c *dateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 267 if err := c.verifyArgs(args); err != nil { 268 return nil, err 269 } 270 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETDatetime) 271 if err != nil { 272 return nil, err 273 } 274 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeDate, 10, 0 275 sig := &builtinDateSig{bf} 276 sig.setPbCode(fidelpb.ScalarFuncSig_Date) 277 return sig, nil 278 } 279 280 type builtinDateSig struct { 281 baseBuiltinFunc 282 } 283 284 func (b *builtinDateSig) Clone() builtinFunc { 285 newSig := &builtinDateSig{} 286 newSig.cloneFrom(&b.baseBuiltinFunc) 287 return newSig 288 } 289 290 // evalTime evals DATE(expr). 291 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date 292 func (b *builtinDateSig) evalTime(event chunk.Event) (types.Time, bool, error) { 293 expr, isNull, err := b.args[0].EvalTime(b.ctx, event) 294 if isNull || err != nil { 295 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 296 } 297 298 if expr.IsZero() { 299 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, expr.String())) 300 } 301 302 expr.SetCoreTime(types.FromDate(expr.Year(), expr.Month(), expr.Day(), 0, 0, 0, 0)) 303 expr.SetType(allegrosql.TypeDate) 304 return expr, false, nil 305 } 306 307 type dateLiteralFunctionClass struct { 308 baseFunctionClass 309 } 310 311 func (c *dateLiteralFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 312 if err := c.verifyArgs(args); err != nil { 313 return nil, err 314 } 315 con, ok := args[0].(*Constant) 316 if !ok { 317 panic("Unexpected parameter for date literal") 318 } 319 dt, err := con.Eval(chunk.Event{}) 320 if err != nil { 321 return nil, err 322 } 323 str := dt.GetString() 324 if !datePattern.MatchString(str) { 325 return nil, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, str) 326 } 327 tm, err := types.ParseDate(ctx.GetStochastikVars().StmtCtx, str) 328 if err != nil { 329 return nil, err 330 } 331 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, []Expression{}, types.ETDatetime) 332 if err != nil { 333 return nil, err 334 } 335 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeDate, 10, 0 336 sig := &builtinDateLiteralSig{bf, tm} 337 return sig, nil 338 } 339 340 type builtinDateLiteralSig struct { 341 baseBuiltinFunc 342 literal types.Time 343 } 344 345 func (b *builtinDateLiteralSig) Clone() builtinFunc { 346 newSig := &builtinDateLiteralSig{literal: b.literal} 347 newSig.cloneFrom(&b.baseBuiltinFunc) 348 return newSig 349 } 350 351 // evalTime evals DATE 'stringLit'. 352 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-literals.html 353 func (b *builtinDateLiteralSig) evalTime(event chunk.Event) (types.Time, bool, error) { 354 mode := b.ctx.GetStochastikVars().ALLEGROSQLMode 355 if mode.HasNoZeroDateMode() && b.literal.IsZero() { 356 return b.literal, true, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, b.literal.String()) 357 } 358 if mode.HasNoZeroInDateMode() && (b.literal.InvalidZero() && !b.literal.IsZero()) { 359 return b.literal, true, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, b.literal.String()) 360 } 361 return b.literal, false, nil 362 } 363 364 type dateDiffFunctionClass struct { 365 baseFunctionClass 366 } 367 368 func (c *dateDiffFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 369 if err := c.verifyArgs(args); err != nil { 370 return nil, err 371 } 372 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime, types.ETDatetime) 373 if err != nil { 374 return nil, err 375 } 376 sig := &builtinDateDiffSig{bf} 377 sig.setPbCode(fidelpb.ScalarFuncSig_DateDiff) 378 return sig, nil 379 } 380 381 type builtinDateDiffSig struct { 382 baseBuiltinFunc 383 } 384 385 func (b *builtinDateDiffSig) Clone() builtinFunc { 386 newSig := &builtinDateDiffSig{} 387 newSig.cloneFrom(&b.baseBuiltinFunc) 388 return newSig 389 } 390 391 // evalInt evals a builtinDateDiffSig. 392 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_datediff 393 func (b *builtinDateDiffSig) evalInt(event chunk.Event) (int64, bool, error) { 394 lhs, isNull, err := b.args[0].EvalTime(b.ctx, event) 395 if isNull || err != nil { 396 return 0, true, handleInvalidTimeError(b.ctx, err) 397 } 398 rhs, isNull, err := b.args[1].EvalTime(b.ctx, event) 399 if isNull || err != nil { 400 return 0, true, handleInvalidTimeError(b.ctx, err) 401 } 402 if invalidLHS, invalidRHS := lhs.InvalidZero(), rhs.InvalidZero(); invalidLHS || invalidRHS { 403 if invalidLHS { 404 err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, lhs.String())) 405 } 406 if invalidRHS { 407 err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, rhs.String())) 408 } 409 return 0, true, err 410 } 411 return int64(types.DateDiff(lhs.CoreTime(), rhs.CoreTime())), false, nil 412 } 413 414 type timeDiffFunctionClass struct { 415 baseFunctionClass 416 } 417 418 func (c *timeDiffFunctionClass) getArgEvalTp(fieldTp *types.FieldType) types.EvalType { 419 argTp := types.ETString 420 switch tp := fieldTp.EvalType(); tp { 421 case types.ETDuration, types.ETDatetime, types.ETTimestamp: 422 argTp = tp 423 } 424 return argTp 425 } 426 427 func (c *timeDiffFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 428 if err := c.verifyArgs(args); err != nil { 429 return nil, err 430 } 431 432 arg0FieldTp, arg1FieldTp := args[0].GetType(), args[1].GetType() 433 arg0Tp, arg1Tp := c.getArgEvalTp(arg0FieldTp), c.getArgEvalTp(arg1FieldTp) 434 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, arg0Tp, arg1Tp) 435 if err != nil { 436 return nil, err 437 } 438 439 arg0Dec, err := getExpressionFsp(ctx, args[0]) 440 if err != nil { 441 return nil, err 442 } 443 arg1Dec, err := getExpressionFsp(ctx, args[1]) 444 if err != nil { 445 return nil, err 446 } 447 bf.tp.Decimal = mathutil.Max(arg0Dec, arg1Dec) 448 449 var sig builtinFunc 450 // arg0 and arg1 must be the same time type(compatible), or timediff will return NULL. 451 // TODO: we don't really need Duration type, actually in MyALLEGROSQL, it use Time class to represent 452 // all the time type, and use filed type to distinguish datetime, date, timestamp or time(duration). 453 // With the duration type, we are hard to port all the MyALLEGROSQL behavior. 454 switch arg0Tp { 455 case types.ETDuration: 456 switch arg1Tp { 457 case types.ETDuration: 458 sig = &builtinDurationDurationTimeDiffSig{bf} 459 sig.setPbCode(fidelpb.ScalarFuncSig_DurationDurationTimeDiff) 460 case types.ETDatetime, types.ETTimestamp: 461 sig = &builtinNullTimeDiffSig{bf} 462 sig.setPbCode(fidelpb.ScalarFuncSig_NullTimeDiff) 463 default: 464 sig = &builtinDurationStringTimeDiffSig{bf} 465 sig.setPbCode(fidelpb.ScalarFuncSig_DurationStringTimeDiff) 466 } 467 case types.ETDatetime, types.ETTimestamp: 468 switch arg1Tp { 469 case types.ETDuration: 470 sig = &builtinNullTimeDiffSig{bf} 471 sig.setPbCode(fidelpb.ScalarFuncSig_NullTimeDiff) 472 case types.ETDatetime, types.ETTimestamp: 473 sig = &builtinTimeTimeTimeDiffSig{bf} 474 sig.setPbCode(fidelpb.ScalarFuncSig_TimeTimeTimeDiff) 475 default: 476 sig = &builtinTimeStringTimeDiffSig{bf} 477 sig.setPbCode(fidelpb.ScalarFuncSig_TimeStringTimeDiff) 478 } 479 default: 480 switch arg1Tp { 481 case types.ETDuration: 482 sig = &builtinStringDurationTimeDiffSig{bf} 483 sig.setPbCode(fidelpb.ScalarFuncSig_StringDurationTimeDiff) 484 case types.ETDatetime, types.ETTimestamp: 485 sig = &builtinStringTimeTimeDiffSig{bf} 486 sig.setPbCode(fidelpb.ScalarFuncSig_StringTimeTimeDiff) 487 default: 488 sig = &builtinStringStringTimeDiffSig{bf} 489 sig.setPbCode(fidelpb.ScalarFuncSig_StringStringTimeDiff) 490 } 491 } 492 return sig, nil 493 } 494 495 type builtinDurationDurationTimeDiffSig struct { 496 baseBuiltinFunc 497 } 498 499 func (b *builtinDurationDurationTimeDiffSig) Clone() builtinFunc { 500 newSig := &builtinDurationDurationTimeDiffSig{} 501 newSig.cloneFrom(&b.baseBuiltinFunc) 502 return newSig 503 } 504 505 // evalDuration evals a builtinDurationDurationTimeDiffSig. 506 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 507 func (b *builtinDurationDurationTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 508 lhs, isNull, err := b.args[0].EvalDuration(b.ctx, event) 509 if isNull || err != nil { 510 return d, isNull, err 511 } 512 513 rhs, isNull, err := b.args[1].EvalDuration(b.ctx, event) 514 if isNull || err != nil { 515 return d, isNull, err 516 } 517 518 d, isNull, err = calculateDurationTimeDiff(b.ctx, lhs, rhs) 519 return d, isNull, err 520 } 521 522 type builtinTimeTimeTimeDiffSig struct { 523 baseBuiltinFunc 524 } 525 526 func (b *builtinTimeTimeTimeDiffSig) Clone() builtinFunc { 527 newSig := &builtinTimeTimeTimeDiffSig{} 528 newSig.cloneFrom(&b.baseBuiltinFunc) 529 return newSig 530 } 531 532 // evalDuration evals a builtinTimeTimeTimeDiffSig. 533 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 534 func (b *builtinTimeTimeTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 535 lhs, isNull, err := b.args[0].EvalTime(b.ctx, event) 536 if isNull || err != nil { 537 return d, isNull, err 538 } 539 540 rhs, isNull, err := b.args[1].EvalTime(b.ctx, event) 541 if isNull || err != nil { 542 return d, isNull, err 543 } 544 545 sc := b.ctx.GetStochastikVars().StmtCtx 546 d, isNull, err = calculateTimeDiff(sc, lhs, rhs) 547 return d, isNull, err 548 } 549 550 type builtinDurationStringTimeDiffSig struct { 551 baseBuiltinFunc 552 } 553 554 func (b *builtinDurationStringTimeDiffSig) Clone() builtinFunc { 555 newSig := &builtinDurationStringTimeDiffSig{} 556 newSig.cloneFrom(&b.baseBuiltinFunc) 557 return newSig 558 } 559 560 // evalDuration evals a builtinDurationStringTimeDiffSig. 561 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 562 func (b *builtinDurationStringTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 563 lhs, isNull, err := b.args[0].EvalDuration(b.ctx, event) 564 if isNull || err != nil { 565 return d, isNull, err 566 } 567 568 rhsStr, isNull, err := b.args[1].EvalString(b.ctx, event) 569 if isNull || err != nil { 570 return d, isNull, err 571 } 572 573 sc := b.ctx.GetStochastikVars().StmtCtx 574 rhs, _, isDuration, err := convertStringToDuration(sc, rhsStr, int8(b.tp.Decimal)) 575 if err != nil || !isDuration { 576 return d, true, err 577 } 578 579 d, isNull, err = calculateDurationTimeDiff(b.ctx, lhs, rhs) 580 return d, isNull, err 581 } 582 583 type builtinStringDurationTimeDiffSig struct { 584 baseBuiltinFunc 585 } 586 587 func (b *builtinStringDurationTimeDiffSig) Clone() builtinFunc { 588 newSig := &builtinStringDurationTimeDiffSig{} 589 newSig.cloneFrom(&b.baseBuiltinFunc) 590 return newSig 591 } 592 593 // evalDuration evals a builtinStringDurationTimeDiffSig. 594 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 595 func (b *builtinStringDurationTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 596 lhsStr, isNull, err := b.args[0].EvalString(b.ctx, event) 597 if isNull || err != nil { 598 return d, isNull, err 599 } 600 601 rhs, isNull, err := b.args[1].EvalDuration(b.ctx, event) 602 if isNull || err != nil { 603 return d, isNull, err 604 } 605 606 sc := b.ctx.GetStochastikVars().StmtCtx 607 lhs, _, isDuration, err := convertStringToDuration(sc, lhsStr, int8(b.tp.Decimal)) 608 if err != nil || !isDuration { 609 return d, true, err 610 } 611 612 d, isNull, err = calculateDurationTimeDiff(b.ctx, lhs, rhs) 613 return d, isNull, err 614 } 615 616 // calculateTimeDiff calculates interval difference of two types.Time. 617 func calculateTimeDiff(sc *stmtctx.StatementContext, lhs, rhs types.Time) (d types.Duration, isNull bool, err error) { 618 d = lhs.Sub(sc, &rhs) 619 d.Duration, err = types.TruncateOverflowMyALLEGROSQLTime(d.Duration) 620 if types.ErrTruncatedWrongVal.Equal(err) { 621 err = sc.HandleTruncate(err) 622 } 623 return d, err != nil, err 624 } 625 626 // calculateDurationTimeDiff calculates interval difference of two types.Duration. 627 func calculateDurationTimeDiff(ctx stochastikctx.Context, lhs, rhs types.Duration) (d types.Duration, isNull bool, err error) { 628 d, err = lhs.Sub(rhs) 629 if err != nil { 630 return d, true, err 631 } 632 633 d.Duration, err = types.TruncateOverflowMyALLEGROSQLTime(d.Duration) 634 if types.ErrTruncatedWrongVal.Equal(err) { 635 sc := ctx.GetStochastikVars().StmtCtx 636 err = sc.HandleTruncate(err) 637 } 638 return d, err != nil, err 639 } 640 641 type builtinTimeStringTimeDiffSig struct { 642 baseBuiltinFunc 643 } 644 645 func (b *builtinTimeStringTimeDiffSig) Clone() builtinFunc { 646 newSig := &builtinTimeStringTimeDiffSig{} 647 newSig.cloneFrom(&b.baseBuiltinFunc) 648 return newSig 649 } 650 651 // evalDuration evals a builtinTimeStringTimeDiffSig. 652 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 653 func (b *builtinTimeStringTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 654 lhs, isNull, err := b.args[0].EvalTime(b.ctx, event) 655 if isNull || err != nil { 656 return d, isNull, err 657 } 658 659 rhsStr, isNull, err := b.args[1].EvalString(b.ctx, event) 660 if isNull || err != nil { 661 return d, isNull, err 662 } 663 664 sc := b.ctx.GetStochastikVars().StmtCtx 665 _, rhs, isDuration, err := convertStringToDuration(sc, rhsStr, int8(b.tp.Decimal)) 666 if err != nil || isDuration { 667 return d, true, err 668 } 669 670 d, isNull, err = calculateTimeDiff(sc, lhs, rhs) 671 return d, isNull, err 672 } 673 674 type builtinStringTimeTimeDiffSig struct { 675 baseBuiltinFunc 676 } 677 678 func (b *builtinStringTimeTimeDiffSig) Clone() builtinFunc { 679 newSig := &builtinStringTimeTimeDiffSig{} 680 newSig.cloneFrom(&b.baseBuiltinFunc) 681 return newSig 682 } 683 684 // evalDuration evals a builtinStringTimeTimeDiffSig. 685 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 686 func (b *builtinStringTimeTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 687 lhsStr, isNull, err := b.args[0].EvalString(b.ctx, event) 688 if isNull || err != nil { 689 return d, isNull, err 690 } 691 692 rhs, isNull, err := b.args[1].EvalTime(b.ctx, event) 693 if isNull || err != nil { 694 return d, isNull, err 695 } 696 697 sc := b.ctx.GetStochastikVars().StmtCtx 698 _, lhs, isDuration, err := convertStringToDuration(sc, lhsStr, int8(b.tp.Decimal)) 699 if err != nil || isDuration { 700 return d, true, err 701 } 702 703 d, isNull, err = calculateTimeDiff(sc, lhs, rhs) 704 return d, isNull, err 705 } 706 707 type builtinStringStringTimeDiffSig struct { 708 baseBuiltinFunc 709 } 710 711 func (b *builtinStringStringTimeDiffSig) Clone() builtinFunc { 712 newSig := &builtinStringStringTimeDiffSig{} 713 newSig.cloneFrom(&b.baseBuiltinFunc) 714 return newSig 715 } 716 717 // evalDuration evals a builtinStringStringTimeDiffSig. 718 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 719 func (b *builtinStringStringTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 720 lhs, isNull, err := b.args[0].EvalString(b.ctx, event) 721 if isNull || err != nil { 722 return d, isNull, err 723 } 724 725 rhs, isNull, err := b.args[1].EvalString(b.ctx, event) 726 if isNull || err != nil { 727 return d, isNull, err 728 } 729 730 sc := b.ctx.GetStochastikVars().StmtCtx 731 fsp := int8(b.tp.Decimal) 732 lhsDur, lhsTime, lhsIsDuration, err := convertStringToDuration(sc, lhs, fsp) 733 if err != nil { 734 return d, true, err 735 } 736 737 rhsDur, rhsTime, rhsIsDuration, err := convertStringToDuration(sc, rhs, fsp) 738 if err != nil { 739 return d, true, err 740 } 741 742 if lhsIsDuration != rhsIsDuration { 743 return d, true, nil 744 } 745 746 if lhsIsDuration { 747 d, isNull, err = calculateDurationTimeDiff(b.ctx, lhsDur, rhsDur) 748 } else { 749 d, isNull, err = calculateTimeDiff(sc, lhsTime, rhsTime) 750 } 751 752 return d, isNull, err 753 } 754 755 type builtinNullTimeDiffSig struct { 756 baseBuiltinFunc 757 } 758 759 func (b *builtinNullTimeDiffSig) Clone() builtinFunc { 760 newSig := &builtinNullTimeDiffSig{} 761 newSig.cloneFrom(&b.baseBuiltinFunc) 762 return newSig 763 } 764 765 // evalDuration evals a builtinNullTimeDiffSig. 766 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff 767 func (b *builtinNullTimeDiffSig) evalDuration(event chunk.Event) (d types.Duration, isNull bool, err error) { 768 return d, true, nil 769 } 770 771 // convertStringToDuration converts string to duration, it return types.Time because in some case 772 // it will converts string to datetime. 773 func convertStringToDuration(sc *stmtctx.StatementContext, str string, fsp int8) (d types.Duration, t types.Time, 774 isDuration bool, err error) { 775 if n := strings.IndexByte(str, '.'); n >= 0 { 776 lenStrFsp := len(str[n+1:]) 777 if lenStrFsp <= int(types.MaxFsp) { 778 fsp = mathutil.MaxInt8(int8(lenStrFsp), fsp) 779 } 780 } 781 return types.StrToDuration(sc, str, fsp) 782 } 783 784 type dateFormatFunctionClass struct { 785 baseFunctionClass 786 } 787 788 func (c *dateFormatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 789 if err := c.verifyArgs(args); err != nil { 790 return nil, err 791 } 792 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETDatetime, types.ETString) 793 if err != nil { 794 return nil, err 795 } 796 // worst case: formatMask=%r%r%r...%r, each %r takes 11 characters 797 bf.tp.Flen = (args[1].GetType().Flen + 1) / 2 * 11 798 sig := &builtinDateFormatSig{bf} 799 sig.setPbCode(fidelpb.ScalarFuncSig_DateFormatSig) 800 return sig, nil 801 } 802 803 type builtinDateFormatSig struct { 804 baseBuiltinFunc 805 } 806 807 func (b *builtinDateFormatSig) Clone() builtinFunc { 808 newSig := &builtinDateFormatSig{} 809 newSig.cloneFrom(&b.baseBuiltinFunc) 810 return newSig 811 } 812 813 // evalString evals a builtinDateFormatSig. 814 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format 815 func (b *builtinDateFormatSig) evalString(event chunk.Event) (string, bool, error) { 816 t, isNull, err := b.args[0].EvalTime(b.ctx, event) 817 if isNull || err != nil { 818 return "", isNull, handleInvalidTimeError(b.ctx, err) 819 } 820 formatMask, isNull, err := b.args[1].EvalString(b.ctx, event) 821 if isNull || err != nil { 822 return "", isNull, err 823 } 824 // MyALLEGROSQL compatibility, #11203 825 // If format mask is 0 then return 0 without warnings 826 if formatMask == "0" { 827 return "0", false, nil 828 } 829 830 if t.InvalidZero() { 831 // MyALLEGROSQL compatibility, #11203 832 // 0 | 0.0 should be converted to null without warnings 833 n, err := t.ToNumber().ToInt() 834 isOriginalIntOrDecimalZero := err == nil && n == 0 835 // Args like "0000-00-00", "0000-00-00 00:00:00" set Fsp to 6 836 isOriginalStringZero := t.Fsp() > 0 837 if isOriginalIntOrDecimalZero && !isOriginalStringZero { 838 return "", true, nil 839 } 840 return "", true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 841 } 842 843 res, err := t.DateFormat(formatMask) 844 return res, isNull, err 845 } 846 847 type fromDaysFunctionClass struct { 848 baseFunctionClass 849 } 850 851 func (c *fromDaysFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 852 if err := c.verifyArgs(args); err != nil { 853 return nil, err 854 } 855 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETInt) 856 if err != nil { 857 return nil, err 858 } 859 bf.tp.Flen, bf.tp.Decimal = 10, 0 860 sig := &builtinFromDaysSig{bf} 861 sig.setPbCode(fidelpb.ScalarFuncSig_FromDays) 862 return sig, nil 863 } 864 865 type builtinFromDaysSig struct { 866 baseBuiltinFunc 867 } 868 869 func (b *builtinFromDaysSig) Clone() builtinFunc { 870 newSig := &builtinFromDaysSig{} 871 newSig.cloneFrom(&b.baseBuiltinFunc) 872 return newSig 873 } 874 875 // evalTime evals FROM_DAYS(N). 876 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_from-days 877 func (b *builtinFromDaysSig) evalTime(event chunk.Event) (types.Time, bool, error) { 878 n, isNull, err := b.args[0].EvalInt(b.ctx, event) 879 if isNull || err != nil { 880 return types.ZeroTime, true, err 881 } 882 883 return types.TimeFromDays(n), false, nil 884 } 885 886 type hourFunctionClass struct { 887 baseFunctionClass 888 } 889 890 func (c *hourFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 891 if err := c.verifyArgs(args); err != nil { 892 return nil, err 893 } 894 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDuration) 895 if err != nil { 896 return nil, err 897 } 898 bf.tp.Flen, bf.tp.Decimal = 3, 0 899 sig := &builtinHourSig{bf} 900 sig.setPbCode(fidelpb.ScalarFuncSig_Hour) 901 return sig, nil 902 } 903 904 type builtinHourSig struct { 905 baseBuiltinFunc 906 } 907 908 func (b *builtinHourSig) Clone() builtinFunc { 909 newSig := &builtinHourSig{} 910 newSig.cloneFrom(&b.baseBuiltinFunc) 911 return newSig 912 } 913 914 // evalInt evals HOUR(time). 915 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_hour 916 func (b *builtinHourSig) evalInt(event chunk.Event) (int64, bool, error) { 917 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 918 // ignore error and return NULL 919 if isNull || err != nil { 920 return 0, true, nil 921 } 922 return int64(dur.Hour()), false, nil 923 } 924 925 type minuteFunctionClass struct { 926 baseFunctionClass 927 } 928 929 func (c *minuteFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 930 if err := c.verifyArgs(args); err != nil { 931 return nil, err 932 } 933 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDuration) 934 if err != nil { 935 return nil, err 936 } 937 bf.tp.Flen, bf.tp.Decimal = 2, 0 938 sig := &builtinMinuteSig{bf} 939 sig.setPbCode(fidelpb.ScalarFuncSig_Minute) 940 return sig, nil 941 } 942 943 type builtinMinuteSig struct { 944 baseBuiltinFunc 945 } 946 947 func (b *builtinMinuteSig) Clone() builtinFunc { 948 newSig := &builtinMinuteSig{} 949 newSig.cloneFrom(&b.baseBuiltinFunc) 950 return newSig 951 } 952 953 // evalInt evals MINUTE(time). 954 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_minute 955 func (b *builtinMinuteSig) evalInt(event chunk.Event) (int64, bool, error) { 956 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 957 // ignore error and return NULL 958 if isNull || err != nil { 959 return 0, true, nil 960 } 961 return int64(dur.Minute()), false, nil 962 } 963 964 type secondFunctionClass struct { 965 baseFunctionClass 966 } 967 968 func (c *secondFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 969 if err := c.verifyArgs(args); err != nil { 970 return nil, err 971 } 972 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDuration) 973 if err != nil { 974 return nil, err 975 } 976 bf.tp.Flen, bf.tp.Decimal = 2, 0 977 sig := &builtinSecondSig{bf} 978 sig.setPbCode(fidelpb.ScalarFuncSig_Second) 979 return sig, nil 980 } 981 982 type builtinSecondSig struct { 983 baseBuiltinFunc 984 } 985 986 func (b *builtinSecondSig) Clone() builtinFunc { 987 newSig := &builtinSecondSig{} 988 newSig.cloneFrom(&b.baseBuiltinFunc) 989 return newSig 990 } 991 992 // evalInt evals SECOND(time). 993 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_second 994 func (b *builtinSecondSig) evalInt(event chunk.Event) (int64, bool, error) { 995 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 996 // ignore error and return NULL 997 if isNull || err != nil { 998 return 0, true, nil 999 } 1000 return int64(dur.Second()), false, nil 1001 } 1002 1003 type microSecondFunctionClass struct { 1004 baseFunctionClass 1005 } 1006 1007 func (c *microSecondFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1008 if err := c.verifyArgs(args); err != nil { 1009 return nil, err 1010 } 1011 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDuration) 1012 if err != nil { 1013 return nil, err 1014 } 1015 bf.tp.Flen, bf.tp.Decimal = 6, 0 1016 sig := &builtinMicroSecondSig{bf} 1017 sig.setPbCode(fidelpb.ScalarFuncSig_MicroSecond) 1018 return sig, nil 1019 } 1020 1021 type builtinMicroSecondSig struct { 1022 baseBuiltinFunc 1023 } 1024 1025 func (b *builtinMicroSecondSig) Clone() builtinFunc { 1026 newSig := &builtinMicroSecondSig{} 1027 newSig.cloneFrom(&b.baseBuiltinFunc) 1028 return newSig 1029 } 1030 1031 // evalInt evals MICROSECOND(expr). 1032 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_microsecond 1033 func (b *builtinMicroSecondSig) evalInt(event chunk.Event) (int64, bool, error) { 1034 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 1035 // ignore error and return NULL 1036 if isNull || err != nil { 1037 return 0, true, nil 1038 } 1039 return int64(dur.MicroSecond()), false, nil 1040 } 1041 1042 type monthFunctionClass struct { 1043 baseFunctionClass 1044 } 1045 1046 func (c *monthFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1047 if err := c.verifyArgs(args); err != nil { 1048 return nil, err 1049 } 1050 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1051 if err != nil { 1052 return nil, err 1053 } 1054 bf.tp.Flen, bf.tp.Decimal = 2, 0 1055 sig := &builtinMonthSig{bf} 1056 sig.setPbCode(fidelpb.ScalarFuncSig_Month) 1057 return sig, nil 1058 } 1059 1060 type builtinMonthSig struct { 1061 baseBuiltinFunc 1062 } 1063 1064 func (b *builtinMonthSig) Clone() builtinFunc { 1065 newSig := &builtinMonthSig{} 1066 newSig.cloneFrom(&b.baseBuiltinFunc) 1067 return newSig 1068 } 1069 1070 // evalInt evals MONTH(date). 1071 // see: https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_month 1072 func (b *builtinMonthSig) evalInt(event chunk.Event) (int64, bool, error) { 1073 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1074 1075 if isNull || err != nil { 1076 return 0, true, handleInvalidTimeError(b.ctx, err) 1077 } 1078 1079 if date.IsZero() { 1080 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() { 1081 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1082 } 1083 return 0, false, nil 1084 } 1085 1086 return int64(date.Month()), false, nil 1087 } 1088 1089 // monthNameFunctionClass see https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_monthname 1090 type monthNameFunctionClass struct { 1091 baseFunctionClass 1092 } 1093 1094 func (c *monthNameFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1095 if err := c.verifyArgs(args); err != nil { 1096 return nil, err 1097 } 1098 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETDatetime) 1099 if err != nil { 1100 return nil, err 1101 } 1102 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 1103 bf.tp.Flen = 10 1104 sig := &builtinMonthNameSig{bf} 1105 sig.setPbCode(fidelpb.ScalarFuncSig_MonthName) 1106 return sig, nil 1107 } 1108 1109 type builtinMonthNameSig struct { 1110 baseBuiltinFunc 1111 } 1112 1113 func (b *builtinMonthNameSig) Clone() builtinFunc { 1114 newSig := &builtinMonthNameSig{} 1115 newSig.cloneFrom(&b.baseBuiltinFunc) 1116 return newSig 1117 } 1118 1119 func (b *builtinMonthNameSig) evalString(event chunk.Event) (string, bool, error) { 1120 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 1121 if isNull || err != nil { 1122 return "", true, handleInvalidTimeError(b.ctx, err) 1123 } 1124 mon := arg.Month() 1125 if (arg.IsZero() && b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode()) || mon < 0 || mon > len(types.MonthNames) { 1126 return "", true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 1127 } else if mon == 0 || arg.IsZero() { 1128 return "", true, nil 1129 } 1130 return types.MonthNames[mon-1], false, nil 1131 } 1132 1133 type dayNameFunctionClass struct { 1134 baseFunctionClass 1135 } 1136 1137 func (c *dayNameFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1138 if err := c.verifyArgs(args); err != nil { 1139 return nil, err 1140 } 1141 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETDatetime) 1142 if err != nil { 1143 return nil, err 1144 } 1145 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 1146 bf.tp.Flen = 10 1147 sig := &builtinDayNameSig{bf} 1148 sig.setPbCode(fidelpb.ScalarFuncSig_DayName) 1149 return sig, nil 1150 } 1151 1152 type builtinDayNameSig struct { 1153 baseBuiltinFunc 1154 } 1155 1156 func (b *builtinDayNameSig) Clone() builtinFunc { 1157 newSig := &builtinDayNameSig{} 1158 newSig.cloneFrom(&b.baseBuiltinFunc) 1159 return newSig 1160 } 1161 1162 func (b *builtinDayNameSig) evalIndex(event chunk.Event) (int64, bool, error) { 1163 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 1164 if isNull || err != nil { 1165 return 0, isNull, err 1166 } 1167 if arg.InvalidZero() { 1168 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 1169 } 1170 // Monday is 0, ... Sunday = 6 in MyALLEGROSQL 1171 // but in go, Sunday is 0, ... Saturday is 6 1172 // w will do a conversion. 1173 res := (int64(arg.Weekday()) + 6) % 7 1174 return res, false, nil 1175 } 1176 1177 // evalString evals a builtinDayNameSig. 1178 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayname 1179 func (b *builtinDayNameSig) evalString(event chunk.Event) (string, bool, error) { 1180 idx, isNull, err := b.evalIndex(event) 1181 if isNull || err != nil { 1182 return "", isNull, err 1183 } 1184 return types.WeekdayNames[idx], false, nil 1185 } 1186 1187 func (b *builtinDayNameSig) evalReal(event chunk.Event) (float64, bool, error) { 1188 idx, isNull, err := b.evalIndex(event) 1189 if isNull || err != nil { 1190 return 0, isNull, err 1191 } 1192 return float64(idx), false, nil 1193 } 1194 1195 func (b *builtinDayNameSig) evalInt(event chunk.Event) (int64, bool, error) { 1196 idx, isNull, err := b.evalIndex(event) 1197 if isNull || err != nil { 1198 return 0, isNull, err 1199 } 1200 return idx, false, nil 1201 } 1202 1203 type dayOfMonthFunctionClass struct { 1204 baseFunctionClass 1205 } 1206 1207 func (c *dayOfMonthFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1208 if err := c.verifyArgs(args); err != nil { 1209 return nil, err 1210 } 1211 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1212 if err != nil { 1213 return nil, err 1214 } 1215 bf.tp.Flen = 2 1216 sig := &builtinDayOfMonthSig{bf} 1217 sig.setPbCode(fidelpb.ScalarFuncSig_DayOfMonth) 1218 return sig, nil 1219 } 1220 1221 type builtinDayOfMonthSig struct { 1222 baseBuiltinFunc 1223 } 1224 1225 func (b *builtinDayOfMonthSig) Clone() builtinFunc { 1226 newSig := &builtinDayOfMonthSig{} 1227 newSig.cloneFrom(&b.baseBuiltinFunc) 1228 return newSig 1229 } 1230 1231 // evalInt evals a builtinDayOfMonthSig. 1232 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayofmonth 1233 func (b *builtinDayOfMonthSig) evalInt(event chunk.Event) (int64, bool, error) { 1234 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 1235 if isNull || err != nil { 1236 return 0, true, handleInvalidTimeError(b.ctx, err) 1237 } 1238 if arg.IsZero() { 1239 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() { 1240 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 1241 } 1242 return 0, false, nil 1243 } 1244 return int64(arg.Day()), false, nil 1245 } 1246 1247 type dayOfWeekFunctionClass struct { 1248 baseFunctionClass 1249 } 1250 1251 func (c *dayOfWeekFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1252 if err := c.verifyArgs(args); err != nil { 1253 return nil, err 1254 } 1255 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1256 if err != nil { 1257 return nil, err 1258 } 1259 bf.tp.Flen = 1 1260 sig := &builtinDayOfWeekSig{bf} 1261 sig.setPbCode(fidelpb.ScalarFuncSig_DayOfWeek) 1262 return sig, nil 1263 } 1264 1265 type builtinDayOfWeekSig struct { 1266 baseBuiltinFunc 1267 } 1268 1269 func (b *builtinDayOfWeekSig) Clone() builtinFunc { 1270 newSig := &builtinDayOfWeekSig{} 1271 newSig.cloneFrom(&b.baseBuiltinFunc) 1272 return newSig 1273 } 1274 1275 // evalInt evals a builtinDayOfWeekSig. 1276 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayofweek 1277 func (b *builtinDayOfWeekSig) evalInt(event chunk.Event) (int64, bool, error) { 1278 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 1279 if isNull || err != nil { 1280 return 0, true, handleInvalidTimeError(b.ctx, err) 1281 } 1282 if arg.InvalidZero() { 1283 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 1284 } 1285 // 1 is Sunday, 2 is Monday, .... 7 is Saturday 1286 return int64(arg.Weekday() + 1), false, nil 1287 } 1288 1289 type dayOfYearFunctionClass struct { 1290 baseFunctionClass 1291 } 1292 1293 func (c *dayOfYearFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1294 if err := c.verifyArgs(args); err != nil { 1295 return nil, err 1296 } 1297 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1298 if err != nil { 1299 return nil, err 1300 } 1301 bf.tp.Flen = 3 1302 sig := &builtinDayOfYearSig{bf} 1303 sig.setPbCode(fidelpb.ScalarFuncSig_DayOfYear) 1304 return sig, nil 1305 } 1306 1307 type builtinDayOfYearSig struct { 1308 baseBuiltinFunc 1309 } 1310 1311 func (b *builtinDayOfYearSig) Clone() builtinFunc { 1312 newSig := &builtinDayOfYearSig{} 1313 newSig.cloneFrom(&b.baseBuiltinFunc) 1314 return newSig 1315 } 1316 1317 // evalInt evals a builtinDayOfYearSig. 1318 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayofyear 1319 func (b *builtinDayOfYearSig) evalInt(event chunk.Event) (int64, bool, error) { 1320 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 1321 if isNull || err != nil { 1322 return 0, isNull, handleInvalidTimeError(b.ctx, err) 1323 } 1324 if arg.InvalidZero() { 1325 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 1326 } 1327 1328 return int64(arg.YearDay()), false, nil 1329 } 1330 1331 type weekFunctionClass struct { 1332 baseFunctionClass 1333 } 1334 1335 func (c *weekFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1336 if err := c.verifyArgs(args); err != nil { 1337 return nil, err 1338 } 1339 1340 argTps := []types.EvalType{types.ETDatetime} 1341 if len(args) == 2 { 1342 argTps = append(argTps, types.ETInt) 1343 } 1344 1345 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...) 1346 if err != nil { 1347 return nil, err 1348 } 1349 1350 bf.tp.Flen, bf.tp.Decimal = 2, 0 1351 1352 var sig builtinFunc 1353 if len(args) == 2 { 1354 sig = &builtinWeekWithModeSig{bf} 1355 sig.setPbCode(fidelpb.ScalarFuncSig_WeekWithMode) 1356 } else { 1357 sig = &builtinWeekWithoutModeSig{bf} 1358 sig.setPbCode(fidelpb.ScalarFuncSig_WeekWithoutMode) 1359 } 1360 return sig, nil 1361 } 1362 1363 type builtinWeekWithModeSig struct { 1364 baseBuiltinFunc 1365 } 1366 1367 func (b *builtinWeekWithModeSig) Clone() builtinFunc { 1368 newSig := &builtinWeekWithModeSig{} 1369 newSig.cloneFrom(&b.baseBuiltinFunc) 1370 return newSig 1371 } 1372 1373 // evalInt evals WEEK(date, mode). 1374 // see: https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_week 1375 func (b *builtinWeekWithModeSig) evalInt(event chunk.Event) (int64, bool, error) { 1376 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1377 1378 if isNull || err != nil { 1379 return 0, true, handleInvalidTimeError(b.ctx, err) 1380 } 1381 1382 if date.IsZero() { 1383 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1384 } 1385 1386 mode, isNull, err := b.args[1].EvalInt(b.ctx, event) 1387 if isNull || err != nil { 1388 return 0, isNull, err 1389 } 1390 1391 week := date.Week(int(mode)) 1392 return int64(week), false, nil 1393 } 1394 1395 type builtinWeekWithoutModeSig struct { 1396 baseBuiltinFunc 1397 } 1398 1399 func (b *builtinWeekWithoutModeSig) Clone() builtinFunc { 1400 newSig := &builtinWeekWithoutModeSig{} 1401 newSig.cloneFrom(&b.baseBuiltinFunc) 1402 return newSig 1403 } 1404 1405 // evalInt evals WEEK(date). 1406 // see: https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_week 1407 func (b *builtinWeekWithoutModeSig) evalInt(event chunk.Event) (int64, bool, error) { 1408 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1409 1410 if isNull || err != nil { 1411 return 0, true, handleInvalidTimeError(b.ctx, err) 1412 } 1413 1414 if date.IsZero() { 1415 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1416 } 1417 1418 mode := 0 1419 modeStr, ok := b.ctx.GetStochastikVars().GetSystemVar(variable.DefaultWeekFormat) 1420 if ok && modeStr != "" { 1421 mode, err = strconv.Atoi(modeStr) 1422 if err != nil { 1423 return 0, true, handleInvalidTimeError(b.ctx, types.ErrInvalidWeekModeFormat.GenWithStackByArgs(modeStr)) 1424 } 1425 } 1426 1427 week := date.Week(mode) 1428 return int64(week), false, nil 1429 } 1430 1431 type weekDayFunctionClass struct { 1432 baseFunctionClass 1433 } 1434 1435 func (c *weekDayFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1436 if err := c.verifyArgs(args); err != nil { 1437 return nil, err 1438 } 1439 1440 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1441 if err != nil { 1442 return nil, err 1443 } 1444 bf.tp.Flen = 1 1445 1446 sig := &builtinWeekDaySig{bf} 1447 sig.setPbCode(fidelpb.ScalarFuncSig_WeekDay) 1448 return sig, nil 1449 } 1450 1451 type builtinWeekDaySig struct { 1452 baseBuiltinFunc 1453 } 1454 1455 func (b *builtinWeekDaySig) Clone() builtinFunc { 1456 newSig := &builtinWeekDaySig{} 1457 newSig.cloneFrom(&b.baseBuiltinFunc) 1458 return newSig 1459 } 1460 1461 // evalInt evals WEEKDAY(date). 1462 func (b *builtinWeekDaySig) evalInt(event chunk.Event) (int64, bool, error) { 1463 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1464 if isNull || err != nil { 1465 return 0, true, handleInvalidTimeError(b.ctx, err) 1466 } 1467 1468 if date.IsZero() { 1469 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1470 } 1471 1472 return int64(date.Weekday()+6) % 7, false, nil 1473 } 1474 1475 type weekOfYearFunctionClass struct { 1476 baseFunctionClass 1477 } 1478 1479 func (c *weekOfYearFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1480 if err := c.verifyArgs(args); err != nil { 1481 return nil, err 1482 } 1483 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1484 if err != nil { 1485 return nil, err 1486 } 1487 bf.tp.Flen, bf.tp.Decimal = 2, 0 1488 sig := &builtinWeekOfYearSig{bf} 1489 sig.setPbCode(fidelpb.ScalarFuncSig_WeekOfYear) 1490 return sig, nil 1491 } 1492 1493 type builtinWeekOfYearSig struct { 1494 baseBuiltinFunc 1495 } 1496 1497 func (b *builtinWeekOfYearSig) Clone() builtinFunc { 1498 newSig := &builtinWeekOfYearSig{} 1499 newSig.cloneFrom(&b.baseBuiltinFunc) 1500 return newSig 1501 } 1502 1503 // evalInt evals WEEKOFYEAR(date). 1504 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_weekofyear 1505 func (b *builtinWeekOfYearSig) evalInt(event chunk.Event) (int64, bool, error) { 1506 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1507 1508 if isNull || err != nil { 1509 return 0, true, handleInvalidTimeError(b.ctx, err) 1510 } 1511 1512 if date.IsZero() { 1513 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1514 } 1515 1516 week := date.Week(3) 1517 return int64(week), false, nil 1518 } 1519 1520 type yearFunctionClass struct { 1521 baseFunctionClass 1522 } 1523 1524 func (c *yearFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1525 if err := c.verifyArgs(args); err != nil { 1526 return nil, err 1527 } 1528 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 1529 if err != nil { 1530 return nil, err 1531 } 1532 bf.tp.Flen, bf.tp.Decimal = 4, 0 1533 sig := &builtinYearSig{bf} 1534 sig.setPbCode(fidelpb.ScalarFuncSig_Year) 1535 return sig, nil 1536 } 1537 1538 type builtinYearSig struct { 1539 baseBuiltinFunc 1540 } 1541 1542 func (b *builtinYearSig) Clone() builtinFunc { 1543 newSig := &builtinYearSig{} 1544 newSig.cloneFrom(&b.baseBuiltinFunc) 1545 return newSig 1546 } 1547 1548 // evalInt evals YEAR(date). 1549 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_year 1550 func (b *builtinYearSig) evalInt(event chunk.Event) (int64, bool, error) { 1551 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1552 1553 if isNull || err != nil { 1554 return 0, true, handleInvalidTimeError(b.ctx, err) 1555 } 1556 1557 if date.IsZero() { 1558 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() { 1559 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1560 } 1561 return 0, false, nil 1562 } 1563 return int64(date.Year()), false, nil 1564 } 1565 1566 type yearWeekFunctionClass struct { 1567 baseFunctionClass 1568 } 1569 1570 func (c *yearWeekFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1571 if err := c.verifyArgs(args); err != nil { 1572 return nil, err 1573 } 1574 argTps := []types.EvalType{types.ETDatetime} 1575 if len(args) == 2 { 1576 argTps = append(argTps, types.ETInt) 1577 } 1578 1579 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, argTps...) 1580 if err != nil { 1581 return nil, err 1582 } 1583 1584 bf.tp.Flen, bf.tp.Decimal = 6, 0 1585 1586 var sig builtinFunc 1587 if len(args) == 2 { 1588 sig = &builtinYearWeekWithModeSig{bf} 1589 sig.setPbCode(fidelpb.ScalarFuncSig_YearWeekWithMode) 1590 } else { 1591 sig = &builtinYearWeekWithoutModeSig{bf} 1592 sig.setPbCode(fidelpb.ScalarFuncSig_YearWeekWithoutMode) 1593 } 1594 return sig, nil 1595 } 1596 1597 type builtinYearWeekWithModeSig struct { 1598 baseBuiltinFunc 1599 } 1600 1601 func (b *builtinYearWeekWithModeSig) Clone() builtinFunc { 1602 newSig := &builtinYearWeekWithModeSig{} 1603 newSig.cloneFrom(&b.baseBuiltinFunc) 1604 return newSig 1605 } 1606 1607 // evalInt evals YEARWEEK(date,mode). 1608 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_yearweek 1609 func (b *builtinYearWeekWithModeSig) evalInt(event chunk.Event) (int64, bool, error) { 1610 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1611 if isNull || err != nil { 1612 return 0, isNull, handleInvalidTimeError(b.ctx, err) 1613 } 1614 if date.IsZero() { 1615 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1616 } 1617 1618 mode, isNull, err := b.args[1].EvalInt(b.ctx, event) 1619 if err != nil { 1620 return 0, true, err 1621 } 1622 if isNull { 1623 mode = 0 1624 } 1625 1626 year, week := date.YearWeek(int(mode)) 1627 result := int64(week + year*100) 1628 if result < 0 { 1629 return int64(math.MaxUint32), false, nil 1630 } 1631 return result, false, nil 1632 } 1633 1634 type builtinYearWeekWithoutModeSig struct { 1635 baseBuiltinFunc 1636 } 1637 1638 func (b *builtinYearWeekWithoutModeSig) Clone() builtinFunc { 1639 newSig := &builtinYearWeekWithoutModeSig{} 1640 newSig.cloneFrom(&b.baseBuiltinFunc) 1641 return newSig 1642 } 1643 1644 // evalInt evals YEARWEEK(date). 1645 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_yearweek 1646 func (b *builtinYearWeekWithoutModeSig) evalInt(event chunk.Event) (int64, bool, error) { 1647 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 1648 if isNull || err != nil { 1649 return 0, true, handleInvalidTimeError(b.ctx, err) 1650 } 1651 1652 if date.InvalidZero() { 1653 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 1654 } 1655 1656 year, week := date.YearWeek(0) 1657 result := int64(week + year*100) 1658 if result < 0 { 1659 return int64(math.MaxUint32), false, nil 1660 } 1661 return result, false, nil 1662 } 1663 1664 type fromUnixTimeFunctionClass struct { 1665 baseFunctionClass 1666 } 1667 1668 func (c *fromUnixTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 1669 if err = c.verifyArgs(args); err != nil { 1670 return nil, err 1671 } 1672 1673 retTp, argTps := types.ETDatetime, make([]types.EvalType, 0, len(args)) 1674 argTps = append(argTps, types.ETDecimal) 1675 if len(args) == 2 { 1676 retTp = types.ETString 1677 argTps = append(argTps, types.ETString) 1678 } 1679 1680 isArg0Str := args[0].GetType().EvalType() == types.ETString 1681 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, retTp, argTps...) 1682 if err != nil { 1683 return nil, err 1684 } 1685 1686 if len(args) > 1 { 1687 bf.tp.Flen = args[1].GetType().Flen 1688 sig = &builtinFromUnixTime2ArgSig{bf} 1689 sig.setPbCode(fidelpb.ScalarFuncSig_FromUnixTime2Arg) 1690 return sig, nil 1691 } 1692 1693 // Calculate the time fsp. 1694 bf.tp.Decimal = int(types.MaxFsp) 1695 if !isArg0Str { 1696 if args[0].GetType().Decimal != types.UnspecifiedLength { 1697 bf.tp.Decimal = mathutil.Min(bf.tp.Decimal, args[0].GetType().Decimal) 1698 } 1699 } 1700 1701 sig = &builtinFromUnixTime1ArgSig{bf} 1702 sig.setPbCode(fidelpb.ScalarFuncSig_FromUnixTime1Arg) 1703 return sig, nil 1704 } 1705 1706 func evalFromUnixTime(ctx stochastikctx.Context, fsp int8, unixTimeStamp *types.MyDecimal) (res types.Time, isNull bool, err error) { 1707 // 0 <= unixTimeStamp <= INT32_MAX 1708 if unixTimeStamp.IsNegative() { 1709 return res, true, nil 1710 } 1711 integralPart, err := unixTimeStamp.ToInt() 1712 if err != nil && !terror.ErrorEqual(err, types.ErrTruncated) { 1713 return res, true, err 1714 } 1715 if integralPart > int64(math.MaxInt32) { 1716 return res, true, nil 1717 } 1718 // Split the integral part and fractional part of a decimal timestamp. 1719 // e.g. for timestamp 12345.678, 1720 // first get the integral part 12345, 1721 // then (12345.678 - 12345) * (10^9) to get the decimal part and convert it to nanosecond precision. 1722 integerDecimalTp := new(types.MyDecimal).FromInt(integralPart) 1723 fracDecimalTp := new(types.MyDecimal) 1724 err = types.DecimalSub(unixTimeStamp, integerDecimalTp, fracDecimalTp) 1725 if err != nil { 1726 return res, true, err 1727 } 1728 nano := new(types.MyDecimal).FromInt(int64(time.Second)) 1729 x := new(types.MyDecimal) 1730 err = types.DecimalMul(fracDecimalTp, nano, x) 1731 if err != nil { 1732 return res, true, err 1733 } 1734 fractionalPart, err := x.ToInt() // here fractionalPart is result multiplying the original fractional part by 10^9. 1735 if err != nil && !terror.ErrorEqual(err, types.ErrTruncated) { 1736 return res, true, err 1737 } 1738 if fsp < 0 { 1739 fsp = types.MaxFsp 1740 } 1741 1742 sc := ctx.GetStochastikVars().StmtCtx 1743 tmp := time.Unix(integralPart, fractionalPart).In(sc.TimeZone) 1744 t, err := convertTimeToMysqlTime(tmp, fsp, types.ModeHalfEven) 1745 if err != nil { 1746 return res, true, err 1747 } 1748 return t, false, nil 1749 } 1750 1751 type builtinFromUnixTime1ArgSig struct { 1752 baseBuiltinFunc 1753 } 1754 1755 func (b *builtinFromUnixTime1ArgSig) Clone() builtinFunc { 1756 newSig := &builtinFromUnixTime1ArgSig{} 1757 newSig.cloneFrom(&b.baseBuiltinFunc) 1758 return newSig 1759 } 1760 1761 // evalTime evals a builtinFromUnixTime1ArgSig. 1762 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_from-unixtime 1763 func (b *builtinFromUnixTime1ArgSig) evalTime(event chunk.Event) (res types.Time, isNull bool, err error) { 1764 unixTimeStamp, isNull, err := b.args[0].EvalDecimal(b.ctx, event) 1765 if err != nil || isNull { 1766 return res, isNull, err 1767 } 1768 return evalFromUnixTime(b.ctx, int8(b.tp.Decimal), unixTimeStamp) 1769 } 1770 1771 type builtinFromUnixTime2ArgSig struct { 1772 baseBuiltinFunc 1773 } 1774 1775 func (b *builtinFromUnixTime2ArgSig) Clone() builtinFunc { 1776 newSig := &builtinFromUnixTime2ArgSig{} 1777 newSig.cloneFrom(&b.baseBuiltinFunc) 1778 return newSig 1779 } 1780 1781 // evalString evals a builtinFromUnixTime2ArgSig. 1782 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_from-unixtime 1783 func (b *builtinFromUnixTime2ArgSig) evalString(event chunk.Event) (res string, isNull bool, err error) { 1784 format, isNull, err := b.args[1].EvalString(b.ctx, event) 1785 if isNull || err != nil { 1786 return "", true, err 1787 } 1788 unixTimeStamp, isNull, err := b.args[0].EvalDecimal(b.ctx, event) 1789 if err != nil || isNull { 1790 return "", isNull, err 1791 } 1792 t, isNull, err := evalFromUnixTime(b.ctx, int8(b.tp.Decimal), unixTimeStamp) 1793 if isNull || err != nil { 1794 return "", isNull, err 1795 } 1796 res, err = t.DateFormat(format) 1797 return res, err != nil, err 1798 } 1799 1800 type getFormatFunctionClass struct { 1801 baseFunctionClass 1802 } 1803 1804 func (c *getFormatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 1805 if err := c.verifyArgs(args); err != nil { 1806 return nil, err 1807 } 1808 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETString) 1809 if err != nil { 1810 return nil, err 1811 } 1812 bf.tp.Flen = 17 1813 sig := &builtinGetFormatSig{bf} 1814 sig.setPbCode(fidelpb.ScalarFuncSig_GetFormat) 1815 return sig, nil 1816 } 1817 1818 type builtinGetFormatSig struct { 1819 baseBuiltinFunc 1820 } 1821 1822 func (b *builtinGetFormatSig) Clone() builtinFunc { 1823 newSig := &builtinGetFormatSig{} 1824 newSig.cloneFrom(&b.baseBuiltinFunc) 1825 return newSig 1826 } 1827 1828 // evalString evals a builtinGetFormatSig. 1829 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_get-format 1830 func (b *builtinGetFormatSig) evalString(event chunk.Event) (string, bool, error) { 1831 t, isNull, err := b.args[0].EvalString(b.ctx, event) 1832 if isNull || err != nil { 1833 return "", isNull, err 1834 } 1835 l, isNull, err := b.args[1].EvalString(b.ctx, event) 1836 if isNull || err != nil { 1837 return "", isNull, err 1838 } 1839 1840 res := b.getFormat(t, l) 1841 return res, false, nil 1842 } 1843 1844 type strToDateFunctionClass struct { 1845 baseFunctionClass 1846 } 1847 1848 func (c *strToDateFunctionClass) getRetTp(ctx stochastikctx.Context, arg Expression) (tp byte, fsp int8) { 1849 tp = allegrosql.TypeDatetime 1850 if _, ok := arg.(*Constant); !ok { 1851 return tp, types.MaxFsp 1852 } 1853 strArg := WrapWithCastAsString(ctx, arg) 1854 format, isNull, err := strArg.EvalString(ctx, chunk.Event{}) 1855 if err != nil || isNull { 1856 return 1857 } 1858 1859 isDuration, isDate := types.GetFormatType(format) 1860 if isDuration && !isDate { 1861 tp = allegrosql.TypeDuration 1862 } else if !isDuration && isDate { 1863 tp = allegrosql.TypeDate 1864 } 1865 if strings.Contains(format, "%f") { 1866 fsp = types.MaxFsp 1867 } 1868 return 1869 } 1870 1871 // getFunction see https://dev.allegrosql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date 1872 func (c *strToDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 1873 if err := c.verifyArgs(args); err != nil { 1874 return nil, err 1875 } 1876 retTp, fsp := c.getRetTp(ctx, args[1]) 1877 switch retTp { 1878 case allegrosql.TypeDate: 1879 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETString, types.ETString) 1880 if err != nil { 1881 return nil, err 1882 } 1883 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeDate, allegrosql.MaxDateWidth, int(types.MinFsp) 1884 sig = &builtinStrToDateDateSig{bf} 1885 sig.setPbCode(fidelpb.ScalarFuncSig_StrToDateDate) 1886 case allegrosql.TypeDatetime: 1887 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETString, types.ETString) 1888 if err != nil { 1889 return nil, err 1890 } 1891 if fsp == types.MinFsp { 1892 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDatetimeWidthNoFsp, int(types.MinFsp) 1893 } else { 1894 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDatetimeWidthWithFsp, int(types.MaxFsp) 1895 } 1896 sig = &builtinStrToDateDatetimeSig{bf} 1897 sig.setPbCode(fidelpb.ScalarFuncSig_StrToDateDatetime) 1898 case allegrosql.TypeDuration: 1899 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETString, types.ETString) 1900 if err != nil { 1901 return nil, err 1902 } 1903 if fsp == types.MinFsp { 1904 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthNoFsp, int(types.MinFsp) 1905 } else { 1906 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthWithFsp, int(types.MaxFsp) 1907 } 1908 sig = &builtinStrToDateDurationSig{bf} 1909 sig.setPbCode(fidelpb.ScalarFuncSig_StrToDateDuration) 1910 } 1911 return sig, nil 1912 } 1913 1914 type builtinStrToDateDateSig struct { 1915 baseBuiltinFunc 1916 } 1917 1918 func (b *builtinStrToDateDateSig) Clone() builtinFunc { 1919 newSig := &builtinStrToDateDateSig{} 1920 newSig.cloneFrom(&b.baseBuiltinFunc) 1921 return newSig 1922 } 1923 1924 func (b *builtinStrToDateDateSig) evalTime(event chunk.Event) (types.Time, bool, error) { 1925 date, isNull, err := b.args[0].EvalString(b.ctx, event) 1926 if isNull || err != nil { 1927 return types.ZeroTime, isNull, err 1928 } 1929 format, isNull, err := b.args[1].EvalString(b.ctx, event) 1930 if isNull || err != nil { 1931 return types.ZeroTime, isNull, err 1932 } 1933 var t types.Time 1934 sc := b.ctx.GetStochastikVars().StmtCtx 1935 succ := t.StrToDate(sc, date, format) 1936 if !succ { 1937 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 1938 } 1939 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) { 1940 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 1941 } 1942 t.SetType(allegrosql.TypeDate) 1943 t.SetFsp(types.MinFsp) 1944 return t, false, nil 1945 } 1946 1947 type builtinStrToDateDatetimeSig struct { 1948 baseBuiltinFunc 1949 } 1950 1951 func (b *builtinStrToDateDatetimeSig) Clone() builtinFunc { 1952 newSig := &builtinStrToDateDatetimeSig{} 1953 newSig.cloneFrom(&b.baseBuiltinFunc) 1954 return newSig 1955 } 1956 1957 func (b *builtinStrToDateDatetimeSig) evalTime(event chunk.Event) (types.Time, bool, error) { 1958 date, isNull, err := b.args[0].EvalString(b.ctx, event) 1959 if isNull || err != nil { 1960 return types.ZeroTime, isNull, err 1961 } 1962 format, isNull, err := b.args[1].EvalString(b.ctx, event) 1963 if isNull || err != nil { 1964 return types.ZeroTime, isNull, err 1965 } 1966 var t types.Time 1967 sc := b.ctx.GetStochastikVars().StmtCtx 1968 succ := t.StrToDate(sc, date, format) 1969 if !succ { 1970 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 1971 } 1972 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) { 1973 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 1974 } 1975 t.SetType(allegrosql.TypeDatetime) 1976 t.SetFsp(int8(b.tp.Decimal)) 1977 return t, false, nil 1978 } 1979 1980 type builtinStrToDateDurationSig struct { 1981 baseBuiltinFunc 1982 } 1983 1984 func (b *builtinStrToDateDurationSig) Clone() builtinFunc { 1985 newSig := &builtinStrToDateDurationSig{} 1986 newSig.cloneFrom(&b.baseBuiltinFunc) 1987 return newSig 1988 } 1989 1990 // evalDuration 1991 // TODO: If the NO_ZERO_DATE or NO_ZERO_IN_DATE ALLEGROALLEGROSQL mode is enabled, zero dates or part of dates are disallowed. 1992 // In that case, STR_TO_DATE() returns NULL and generates a warning. 1993 func (b *builtinStrToDateDurationSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 1994 date, isNull, err := b.args[0].EvalString(b.ctx, event) 1995 if isNull || err != nil { 1996 return types.Duration{}, isNull, err 1997 } 1998 format, isNull, err := b.args[1].EvalString(b.ctx, event) 1999 if isNull || err != nil { 2000 return types.Duration{}, isNull, err 2001 } 2002 var t types.Time 2003 sc := b.ctx.GetStochastikVars().StmtCtx 2004 succ := t.StrToDate(sc, date, format) 2005 if !succ { 2006 return types.Duration{}, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 2007 } 2008 if b.ctx.GetStochastikVars().ALLEGROSQLMode.HasNoZeroDateMode() && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) { 2009 return types.Duration{}, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())) 2010 } 2011 t.SetFsp(int8(b.tp.Decimal)) 2012 dur, err := t.ConvertToDuration() 2013 return dur, err != nil, err 2014 } 2015 2016 type sysDateFunctionClass struct { 2017 baseFunctionClass 2018 } 2019 2020 func (c *sysDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2021 if err := c.verifyArgs(args); err != nil { 2022 return nil, err 2023 } 2024 var argTps = make([]types.EvalType, 0) 2025 if len(args) == 1 { 2026 argTps = append(argTps, types.ETInt) 2027 } 2028 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) 2029 if err != nil { 2030 return nil, err 2031 } 2032 bf.tp.Flen, bf.tp.Decimal = 19, 0 2033 2034 var sig builtinFunc 2035 if len(args) == 1 { 2036 sig = &builtinSysDateWithFspSig{bf} 2037 sig.setPbCode(fidelpb.ScalarFuncSig_SysDateWithFsp) 2038 } else { 2039 sig = &builtinSysDateWithoutFspSig{bf} 2040 sig.setPbCode(fidelpb.ScalarFuncSig_SysDateWithoutFsp) 2041 } 2042 return sig, nil 2043 } 2044 2045 type builtinSysDateWithFspSig struct { 2046 baseBuiltinFunc 2047 } 2048 2049 func (b *builtinSysDateWithFspSig) Clone() builtinFunc { 2050 newSig := &builtinSysDateWithFspSig{} 2051 newSig.cloneFrom(&b.baseBuiltinFunc) 2052 return newSig 2053 } 2054 2055 // evalTime evals SYSDATE(fsp). 2056 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_sysdate 2057 func (b *builtinSysDateWithFspSig) evalTime(event chunk.Event) (d types.Time, isNull bool, err error) { 2058 fsp, isNull, err := b.args[0].EvalInt(b.ctx, event) 2059 if isNull || err != nil { 2060 return types.ZeroTime, isNull, err 2061 } 2062 2063 loc := b.ctx.GetStochastikVars().Location() 2064 now := time.Now().In(loc) 2065 result, err := convertTimeToMysqlTime(now, int8(fsp), types.ModeHalfEven) 2066 if err != nil { 2067 return types.ZeroTime, true, err 2068 } 2069 return result, false, nil 2070 } 2071 2072 type builtinSysDateWithoutFspSig struct { 2073 baseBuiltinFunc 2074 } 2075 2076 func (b *builtinSysDateWithoutFspSig) Clone() builtinFunc { 2077 newSig := &builtinSysDateWithoutFspSig{} 2078 newSig.cloneFrom(&b.baseBuiltinFunc) 2079 return newSig 2080 } 2081 2082 // evalTime evals SYSDATE(). 2083 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_sysdate 2084 func (b *builtinSysDateWithoutFspSig) evalTime(event chunk.Event) (d types.Time, isNull bool, err error) { 2085 tz := b.ctx.GetStochastikVars().Location() 2086 now := time.Now().In(tz) 2087 result, err := convertTimeToMysqlTime(now, 0, types.ModeHalfEven) 2088 if err != nil { 2089 return types.ZeroTime, true, err 2090 } 2091 return result, false, nil 2092 } 2093 2094 type currentDateFunctionClass struct { 2095 baseFunctionClass 2096 } 2097 2098 func (c *currentDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2099 if err := c.verifyArgs(args); err != nil { 2100 return nil, err 2101 } 2102 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime) 2103 if err != nil { 2104 return nil, err 2105 } 2106 bf.tp.Flen, bf.tp.Decimal = 10, 0 2107 sig := &builtinCurrentDateSig{bf} 2108 return sig, nil 2109 } 2110 2111 type builtinCurrentDateSig struct { 2112 baseBuiltinFunc 2113 } 2114 2115 func (b *builtinCurrentDateSig) Clone() builtinFunc { 2116 newSig := &builtinCurrentDateSig{} 2117 newSig.cloneFrom(&b.baseBuiltinFunc) 2118 return newSig 2119 } 2120 2121 // evalTime evals CURDATE(). 2122 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_curdate 2123 func (b *builtinCurrentDateSig) evalTime(event chunk.Event) (d types.Time, isNull bool, err error) { 2124 tz := b.ctx.GetStochastikVars().Location() 2125 nowTs, err := getStmtTimestamp(b.ctx) 2126 if err != nil { 2127 return types.ZeroTime, true, err 2128 } 2129 year, month, day := nowTs.In(tz).Date() 2130 result := types.NewTime(types.FromDate(year, int(month), day, 0, 0, 0, 0), allegrosql.TypeDate, 0) 2131 return result, false, nil 2132 } 2133 2134 type currentTimeFunctionClass struct { 2135 baseFunctionClass 2136 } 2137 2138 func (c *currentTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 2139 if err = c.verifyArgs(args); err != nil { 2140 return nil, err 2141 } 2142 2143 if len(args) == 0 { 2144 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration) 2145 if err != nil { 2146 return nil, err 2147 } 2148 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthNoFsp, int(types.MinFsp) 2149 sig = &builtinCurrentTime0ArgSig{bf} 2150 sig.setPbCode(fidelpb.ScalarFuncSig_CurrentTime0Arg) 2151 return sig, nil 2152 } 2153 // args[0] must be a constant which should not be null. 2154 _, ok := args[0].(*Constant) 2155 fsp := int64(types.MaxFsp) 2156 if ok { 2157 fsp, _, err = args[0].EvalInt(ctx, chunk.Event{}) 2158 if err != nil { 2159 return nil, err 2160 } 2161 if fsp > int64(types.MaxFsp) { 2162 return nil, errors.Errorf("Too-big precision %v specified for 'curtime'. Maximum is %v.", fsp, types.MaxFsp) 2163 } else if fsp < int64(types.MinFsp) { 2164 return nil, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) 2165 } 2166 } 2167 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETInt) 2168 if err != nil { 2169 return nil, err 2170 } 2171 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthWithFsp, int(fsp) 2172 sig = &builtinCurrentTime1ArgSig{bf} 2173 sig.setPbCode(fidelpb.ScalarFuncSig_CurrentTime1Arg) 2174 return sig, nil 2175 } 2176 2177 type builtinCurrentTime0ArgSig struct { 2178 baseBuiltinFunc 2179 } 2180 2181 func (b *builtinCurrentTime0ArgSig) Clone() builtinFunc { 2182 newSig := &builtinCurrentTime0ArgSig{} 2183 newSig.cloneFrom(&b.baseBuiltinFunc) 2184 return newSig 2185 } 2186 2187 func (b *builtinCurrentTime0ArgSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 2188 tz := b.ctx.GetStochastikVars().Location() 2189 nowTs, err := getStmtTimestamp(b.ctx) 2190 if err != nil { 2191 return types.Duration{}, true, err 2192 } 2193 dur := nowTs.In(tz).Format(types.TimeFormat) 2194 res, err := types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, dur, types.MinFsp) 2195 if err != nil { 2196 return types.Duration{}, true, err 2197 } 2198 return res, false, nil 2199 } 2200 2201 type builtinCurrentTime1ArgSig struct { 2202 baseBuiltinFunc 2203 } 2204 2205 func (b *builtinCurrentTime1ArgSig) Clone() builtinFunc { 2206 newSig := &builtinCurrentTime1ArgSig{} 2207 newSig.cloneFrom(&b.baseBuiltinFunc) 2208 return newSig 2209 } 2210 2211 func (b *builtinCurrentTime1ArgSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 2212 fsp, _, err := b.args[0].EvalInt(b.ctx, event) 2213 if err != nil { 2214 return types.Duration{}, true, err 2215 } 2216 tz := b.ctx.GetStochastikVars().Location() 2217 nowTs, err := getStmtTimestamp(b.ctx) 2218 if err != nil { 2219 return types.Duration{}, true, err 2220 } 2221 dur := nowTs.In(tz).Format(types.TimeFSPFormat) 2222 res, err := types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, dur, int8(fsp)) 2223 if err != nil { 2224 return types.Duration{}, true, err 2225 } 2226 return res, false, nil 2227 } 2228 2229 type timeFunctionClass struct { 2230 baseFunctionClass 2231 } 2232 2233 func (c *timeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2234 err := c.verifyArgs(args) 2235 if err != nil { 2236 return nil, err 2237 } 2238 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETString) 2239 if err != nil { 2240 return nil, err 2241 } 2242 bf.tp.Decimal, err = getExpressionFsp(ctx, args[0]) 2243 if err != nil { 2244 return nil, err 2245 } 2246 sig := &builtinTimeSig{bf} 2247 sig.setPbCode(fidelpb.ScalarFuncSig_Time) 2248 return sig, nil 2249 } 2250 2251 type builtinTimeSig struct { 2252 baseBuiltinFunc 2253 } 2254 2255 func (b *builtinTimeSig) Clone() builtinFunc { 2256 newSig := &builtinTimeSig{} 2257 newSig.cloneFrom(&b.baseBuiltinFunc) 2258 return newSig 2259 } 2260 2261 // evalDuration evals a builtinTimeSig. 2262 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time. 2263 func (b *builtinTimeSig) evalDuration(event chunk.Event) (res types.Duration, isNull bool, err error) { 2264 expr, isNull, err := b.args[0].EvalString(b.ctx, event) 2265 if isNull || err != nil { 2266 return res, isNull, err 2267 } 2268 2269 fsp := 0 2270 if idx := strings.Index(expr, "."); idx != -1 { 2271 fsp = len(expr) - idx - 1 2272 } 2273 2274 var tmpFsp int8 2275 if tmpFsp, err = types.CheckFsp(fsp); err != nil { 2276 return res, isNull, err 2277 } 2278 fsp = int(tmpFsp) 2279 2280 sc := b.ctx.GetStochastikVars().StmtCtx 2281 res, err = types.ParseDuration(sc, expr, int8(fsp)) 2282 if types.ErrTruncatedWrongVal.Equal(err) { 2283 err = sc.HandleTruncate(err) 2284 } 2285 return res, isNull, err 2286 } 2287 2288 type timeLiteralFunctionClass struct { 2289 baseFunctionClass 2290 } 2291 2292 func (c *timeLiteralFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2293 if err := c.verifyArgs(args); err != nil { 2294 return nil, err 2295 } 2296 con, ok := args[0].(*Constant) 2297 if !ok { 2298 panic("Unexpected parameter for time literal") 2299 } 2300 dt, err := con.Eval(chunk.Event{}) 2301 if err != nil { 2302 return nil, err 2303 } 2304 str := dt.GetString() 2305 if !isDuration(str) { 2306 return nil, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, str) 2307 } 2308 duration, err := types.ParseDuration(ctx.GetStochastikVars().StmtCtx, str, types.GetFsp(str)) 2309 if err != nil { 2310 return nil, err 2311 } 2312 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, []Expression{}, types.ETDuration) 2313 if err != nil { 2314 return nil, err 2315 } 2316 bf.tp.Flen, bf.tp.Decimal = 10, int(duration.Fsp) 2317 if int(duration.Fsp) > 0 { 2318 bf.tp.Flen += 1 + int(duration.Fsp) 2319 } 2320 sig := &builtinTimeLiteralSig{bf, duration} 2321 return sig, nil 2322 } 2323 2324 type builtinTimeLiteralSig struct { 2325 baseBuiltinFunc 2326 duration types.Duration 2327 } 2328 2329 func (b *builtinTimeLiteralSig) Clone() builtinFunc { 2330 newSig := &builtinTimeLiteralSig{duration: b.duration} 2331 newSig.cloneFrom(&b.baseBuiltinFunc) 2332 return newSig 2333 } 2334 2335 // evalDuration evals TIME 'stringLit'. 2336 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-literals.html 2337 func (b *builtinTimeLiteralSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 2338 return b.duration, false, nil 2339 } 2340 2341 type utcDateFunctionClass struct { 2342 baseFunctionClass 2343 } 2344 2345 func (c *utcDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2346 if err := c.verifyArgs(args); err != nil { 2347 return nil, err 2348 } 2349 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime) 2350 if err != nil { 2351 return nil, err 2352 } 2353 bf.tp.Flen, bf.tp.Decimal = 10, 0 2354 sig := &builtinUTCDateSig{bf} 2355 return sig, nil 2356 } 2357 2358 type builtinUTCDateSig struct { 2359 baseBuiltinFunc 2360 } 2361 2362 func (b *builtinUTCDateSig) Clone() builtinFunc { 2363 newSig := &builtinUTCDateSig{} 2364 newSig.cloneFrom(&b.baseBuiltinFunc) 2365 return newSig 2366 } 2367 2368 // evalTime evals UTC_DATE, UTC_DATE(). 2369 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-date 2370 func (b *builtinUTCDateSig) evalTime(event chunk.Event) (types.Time, bool, error) { 2371 nowTs, err := getStmtTimestamp(b.ctx) 2372 if err != nil { 2373 return types.ZeroTime, true, err 2374 } 2375 year, month, day := nowTs.UTC().Date() 2376 result := types.NewTime(types.FromGoTime(time.Date(year, month, day, 0, 0, 0, 0, time.UTC)), allegrosql.TypeDate, types.UnspecifiedFsp) 2377 return result, false, nil 2378 } 2379 2380 type utcTimestampFunctionClass struct { 2381 baseFunctionClass 2382 } 2383 2384 func getFlenAndDecimal4UTCTimestampAndNow(ctx stochastikctx.Context, arg Expression) (flen, decimal int) { 2385 if constant, ok := arg.(*Constant); ok { 2386 fsp, isNull, err := constant.EvalInt(ctx, chunk.Event{}) 2387 if isNull || err != nil || fsp > int64(types.MaxFsp) { 2388 decimal = int(types.MaxFsp) 2389 } else if fsp < int64(types.MinFsp) { 2390 decimal = int(types.MinFsp) 2391 } else { 2392 decimal = int(fsp) 2393 } 2394 } 2395 if decimal > 0 { 2396 flen = 19 + 1 + decimal 2397 } else { 2398 flen = 19 2399 } 2400 return flen, decimal 2401 } 2402 2403 func (c *utcTimestampFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2404 if err := c.verifyArgs(args); err != nil { 2405 return nil, err 2406 } 2407 argTps := make([]types.EvalType, 0, 1) 2408 if len(args) == 1 { 2409 argTps = append(argTps, types.ETInt) 2410 } 2411 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) 2412 if err != nil { 2413 return nil, err 2414 } 2415 2416 if len(args) == 1 { 2417 bf.tp.Flen, bf.tp.Decimal = getFlenAndDecimal4UTCTimestampAndNow(bf.ctx, args[0]) 2418 } else { 2419 bf.tp.Flen, bf.tp.Decimal = 19, 0 2420 } 2421 2422 var sig builtinFunc 2423 if len(args) == 1 { 2424 sig = &builtinUTCTimestampWithArgSig{bf} 2425 sig.setPbCode(fidelpb.ScalarFuncSig_UTCTimestampWithArg) 2426 } else { 2427 sig = &builtinUTCTimestampWithoutArgSig{bf} 2428 sig.setPbCode(fidelpb.ScalarFuncSig_UTCTimestampWithoutArg) 2429 } 2430 return sig, nil 2431 } 2432 2433 func evalUTCTimestampWithFsp(ctx stochastikctx.Context, fsp int8) (types.Time, bool, error) { 2434 nowTs, err := getStmtTimestamp(ctx) 2435 if err != nil { 2436 return types.ZeroTime, true, err 2437 } 2438 result, err := convertTimeToMysqlTime(nowTs.UTC(), fsp, types.ModeHalfEven) 2439 if err != nil { 2440 return types.ZeroTime, true, err 2441 } 2442 return result, false, nil 2443 } 2444 2445 type builtinUTCTimestampWithArgSig struct { 2446 baseBuiltinFunc 2447 } 2448 2449 func (b *builtinUTCTimestampWithArgSig) Clone() builtinFunc { 2450 newSig := &builtinUTCTimestampWithArgSig{} 2451 newSig.cloneFrom(&b.baseBuiltinFunc) 2452 return newSig 2453 } 2454 2455 // evalTime evals UTC_TIMESTAMP(fsp). 2456 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-timestamp 2457 func (b *builtinUTCTimestampWithArgSig) evalTime(event chunk.Event) (types.Time, bool, error) { 2458 num, isNull, err := b.args[0].EvalInt(b.ctx, event) 2459 if err != nil { 2460 return types.ZeroTime, true, err 2461 } 2462 2463 if !isNull && num > int64(types.MaxFsp) { 2464 return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v.", num, types.MaxFsp) 2465 } 2466 if !isNull && num < int64(types.MinFsp) { 2467 return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", num) 2468 } 2469 2470 result, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(num)) 2471 return result, isNull, err 2472 } 2473 2474 type builtinUTCTimestampWithoutArgSig struct { 2475 baseBuiltinFunc 2476 } 2477 2478 func (b *builtinUTCTimestampWithoutArgSig) Clone() builtinFunc { 2479 newSig := &builtinUTCTimestampWithoutArgSig{} 2480 newSig.cloneFrom(&b.baseBuiltinFunc) 2481 return newSig 2482 } 2483 2484 // evalTime evals UTC_TIMESTAMP(). 2485 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-timestamp 2486 func (b *builtinUTCTimestampWithoutArgSig) evalTime(event chunk.Event) (types.Time, bool, error) { 2487 result, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(0)) 2488 return result, isNull, err 2489 } 2490 2491 type nowFunctionClass struct { 2492 baseFunctionClass 2493 } 2494 2495 func (c *nowFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 2496 if err := c.verifyArgs(args); err != nil { 2497 return nil, err 2498 } 2499 argTps := make([]types.EvalType, 0, 1) 2500 if len(args) == 1 { 2501 argTps = append(argTps, types.ETInt) 2502 } 2503 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) 2504 if err != nil { 2505 return nil, err 2506 } 2507 2508 if len(args) == 1 { 2509 bf.tp.Flen, bf.tp.Decimal = getFlenAndDecimal4UTCTimestampAndNow(bf.ctx, args[0]) 2510 } else { 2511 bf.tp.Flen, bf.tp.Decimal = 19, 0 2512 } 2513 2514 var sig builtinFunc 2515 if len(args) == 1 { 2516 sig = &builtinNowWithArgSig{bf} 2517 sig.setPbCode(fidelpb.ScalarFuncSig_NowWithArg) 2518 } else { 2519 sig = &builtinNowWithoutArgSig{bf} 2520 sig.setPbCode(fidelpb.ScalarFuncSig_NowWithoutArg) 2521 } 2522 return sig, nil 2523 } 2524 2525 func evalNowWithFsp(ctx stochastikctx.Context, fsp int8) (types.Time, bool, error) { 2526 nowTs, err := getStmtTimestamp(ctx) 2527 if err != nil { 2528 return types.ZeroTime, true, err 2529 } 2530 2531 // In MyALLEGROSQL's implementation, now() will truncate the result instead of rounding it. 2532 // Results below are from MyALLEGROSQL 5.7, which can prove it. 2533 // allegrosql> select now(6), now(3), now(); 2534 // +----------------------------+-------------------------+---------------------+ 2535 // | now(6) | now(3) | now() | 2536 // +----------------------------+-------------------------+---------------------+ 2537 // | 2020-03-25 15:57:56.612966 | 2020-03-25 15:57:56.612 | 2020-03-25 15:57:56 | 2538 // +----------------------------+-------------------------+---------------------+ 2539 result, err := convertTimeToMysqlTime(nowTs, fsp, types.ModeTruncate) 2540 if err != nil { 2541 return types.ZeroTime, true, err 2542 } 2543 2544 err = result.ConvertTimeZone(time.Local, ctx.GetStochastikVars().Location()) 2545 if err != nil { 2546 return types.ZeroTime, true, err 2547 } 2548 2549 return result, false, nil 2550 } 2551 2552 type builtinNowWithArgSig struct { 2553 baseBuiltinFunc 2554 } 2555 2556 func (b *builtinNowWithArgSig) Clone() builtinFunc { 2557 newSig := &builtinNowWithArgSig{} 2558 newSig.cloneFrom(&b.baseBuiltinFunc) 2559 return newSig 2560 } 2561 2562 // evalTime evals NOW(fsp) 2563 // see: https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_now 2564 func (b *builtinNowWithArgSig) evalTime(event chunk.Event) (types.Time, bool, error) { 2565 fsp, isNull, err := b.args[0].EvalInt(b.ctx, event) 2566 2567 if err != nil { 2568 return types.ZeroTime, true, err 2569 } 2570 2571 if isNull { 2572 fsp = 0 2573 } else if fsp > int64(types.MaxFsp) { 2574 return types.ZeroTime, true, errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v.", fsp, types.MaxFsp) 2575 } else if fsp < int64(types.MinFsp) { 2576 return types.ZeroTime, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) 2577 } 2578 2579 result, isNull, err := evalNowWithFsp(b.ctx, int8(fsp)) 2580 return result, isNull, err 2581 } 2582 2583 type builtinNowWithoutArgSig struct { 2584 baseBuiltinFunc 2585 } 2586 2587 func (b *builtinNowWithoutArgSig) Clone() builtinFunc { 2588 newSig := &builtinNowWithoutArgSig{} 2589 newSig.cloneFrom(&b.baseBuiltinFunc) 2590 return newSig 2591 } 2592 2593 // evalTime evals NOW() 2594 // see: https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_now 2595 func (b *builtinNowWithoutArgSig) evalTime(event chunk.Event) (types.Time, bool, error) { 2596 result, isNull, err := evalNowWithFsp(b.ctx, int8(0)) 2597 return result, isNull, err 2598 } 2599 2600 type extractFunctionClass struct { 2601 baseFunctionClass 2602 } 2603 2604 func (c *extractFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 2605 if err = c.verifyArgs(args); err != nil { 2606 return nil, err 2607 } 2608 2609 datetimeUnits := map[string]struct{}{ 2610 "DAY": {}, 2611 "WEEK": {}, 2612 "MONTH": {}, 2613 "QUARTER": {}, 2614 "YEAR": {}, 2615 "DAY_MICROSECOND": {}, 2616 "DAY_SECOND": {}, 2617 "DAY_MINUTE": {}, 2618 "DAY_HOUR": {}, 2619 "YEAR_MONTH": {}, 2620 } 2621 isDatetimeUnit := true 2622 args[0] = WrapWithCastAsString(ctx, args[0]) 2623 if _, isCon := args[0].(*Constant); isCon { 2624 unit, _, err1 := args[0].EvalString(ctx, chunk.Event{}) 2625 if err1 != nil { 2626 return nil, err1 2627 } 2628 _, isDatetimeUnit = datetimeUnits[unit] 2629 } 2630 var bf baseBuiltinFunc 2631 if isDatetimeUnit { 2632 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETDatetime) 2633 if err != nil { 2634 return nil, err 2635 } 2636 sig = &builtinExtractDatetimeSig{bf} 2637 sig.setPbCode(fidelpb.ScalarFuncSig_ExtractDatetime) 2638 } else { 2639 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETDuration) 2640 if err != nil { 2641 return nil, err 2642 } 2643 sig = &builtinExtractDurationSig{bf} 2644 sig.setPbCode(fidelpb.ScalarFuncSig_ExtractDuration) 2645 } 2646 return sig, nil 2647 } 2648 2649 type builtinExtractDatetimeSig struct { 2650 baseBuiltinFunc 2651 } 2652 2653 func (b *builtinExtractDatetimeSig) Clone() builtinFunc { 2654 newSig := &builtinExtractDatetimeSig{} 2655 newSig.cloneFrom(&b.baseBuiltinFunc) 2656 return newSig 2657 } 2658 2659 // evalInt evals a builtinExtractDatetimeSig. 2660 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_extract 2661 func (b *builtinExtractDatetimeSig) evalInt(event chunk.Event) (int64, bool, error) { 2662 unit, isNull, err := b.args[0].EvalString(b.ctx, event) 2663 if isNull || err != nil { 2664 return 0, isNull, err 2665 } 2666 dt, isNull, err := b.args[1].EvalTime(b.ctx, event) 2667 if isNull || err != nil { 2668 return 0, isNull, err 2669 } 2670 res, err := types.ExtractDatetimeNum(&dt, unit) 2671 return res, err != nil, err 2672 } 2673 2674 type builtinExtractDurationSig struct { 2675 baseBuiltinFunc 2676 } 2677 2678 func (b *builtinExtractDurationSig) Clone() builtinFunc { 2679 newSig := &builtinExtractDurationSig{} 2680 newSig.cloneFrom(&b.baseBuiltinFunc) 2681 return newSig 2682 } 2683 2684 // evalInt evals a builtinExtractDurationSig. 2685 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_extract 2686 func (b *builtinExtractDurationSig) evalInt(event chunk.Event) (int64, bool, error) { 2687 unit, isNull, err := b.args[0].EvalString(b.ctx, event) 2688 if isNull || err != nil { 2689 return 0, isNull, err 2690 } 2691 dur, isNull, err := b.args[1].EvalDuration(b.ctx, event) 2692 if isNull || err != nil { 2693 return 0, isNull, err 2694 } 2695 res, err := types.ExtractDurationNum(&dur, unit) 2696 return res, err != nil, err 2697 } 2698 2699 // baseDateArithmitical is the base class for all "builtinAddDateXXXSig" and "builtinSubDateXXXSig", 2700 // which provides parameter getter and date arithmetical calculate functions. 2701 type baseDateArithmitical struct { 2702 // intervalRegexp is "*Regexp" used to extract string interval for "DAY" unit. 2703 intervalRegexp *regexp.Regexp 2704 } 2705 2706 func newDateArighmeticalUtil() baseDateArithmitical { 2707 return baseDateArithmitical{ 2708 intervalRegexp: regexp.MustCompile(`-?[\d]+`), 2709 } 2710 } 2711 2712 func (du *baseDateArithmitical) getDateFromString(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (types.Time, bool, error) { 2713 dateStr, isNull, err := args[0].EvalString(ctx, event) 2714 if isNull || err != nil { 2715 return types.ZeroTime, true, err 2716 } 2717 2718 dateTp := allegrosql.TypeDate 2719 if !types.IsDateFormat(dateStr) || types.IsClockUnit(unit) { 2720 dateTp = allegrosql.TypeDatetime 2721 } 2722 2723 sc := ctx.GetStochastikVars().StmtCtx 2724 date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp) 2725 return date, err != nil, handleInvalidTimeError(ctx, err) 2726 } 2727 2728 func (du *baseDateArithmitical) getDateFromInt(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (types.Time, bool, error) { 2729 dateInt, isNull, err := args[0].EvalInt(ctx, event) 2730 if isNull || err != nil { 2731 return types.ZeroTime, true, err 2732 } 2733 2734 sc := ctx.GetStochastikVars().StmtCtx 2735 date, err := types.ParseTimeFromInt64(sc, dateInt) 2736 if err != nil { 2737 return types.ZeroTime, true, handleInvalidTimeError(ctx, err) 2738 } 2739 2740 dateTp := allegrosql.TypeDate 2741 if date.Type() == allegrosql.TypeDatetime || date.Type() == allegrosql.TypeTimestamp || types.IsClockUnit(unit) { 2742 dateTp = allegrosql.TypeDatetime 2743 } 2744 date.SetType(dateTp) 2745 return date, false, nil 2746 } 2747 2748 func (du *baseDateArithmitical) getDateFromDatetime(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (types.Time, bool, error) { 2749 date, isNull, err := args[0].EvalTime(ctx, event) 2750 if isNull || err != nil { 2751 return types.ZeroTime, true, err 2752 } 2753 2754 dateTp := allegrosql.TypeDate 2755 if date.Type() == allegrosql.TypeDatetime || date.Type() == allegrosql.TypeTimestamp || types.IsClockUnit(unit) { 2756 dateTp = allegrosql.TypeDatetime 2757 } 2758 date.SetType(dateTp) 2759 return date, false, nil 2760 } 2761 2762 func (du *baseDateArithmitical) getIntervalFromString(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (string, bool, error) { 2763 interval, isNull, err := args[1].EvalString(ctx, event) 2764 if isNull || err != nil { 2765 return "", true, err 2766 } 2767 // unit "DAY" and "HOUR" has to be specially handled. 2768 if toLower := strings.ToLower(unit); toLower == "day" || toLower == "hour" { 2769 if strings.ToLower(interval) == "true" { 2770 interval = "1" 2771 } else if strings.ToLower(interval) == "false" { 2772 interval = "0" 2773 } else { 2774 interval = du.intervalRegexp.FindString(interval) 2775 } 2776 } 2777 return interval, false, nil 2778 } 2779 2780 func (du *baseDateArithmitical) getIntervalFromDecimal(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (string, bool, error) { 2781 decimal, isNull, err := args[1].EvalDecimal(ctx, event) 2782 if isNull || err != nil { 2783 return "", true, err 2784 } 2785 interval := decimal.String() 2786 2787 switch strings.ToUpper(unit) { 2788 case "HOUR_MINUTE", "MINUTE_SECOND", "YEAR_MONTH", "DAY_HOUR", "DAY_MINUTE", 2789 "DAY_SECOND", "DAY_MICROSECOND", "HOUR_MICROSECOND", "HOUR_SECOND", "MINUTE_MICROSECOND", "SECOND_MICROSECOND": 2790 neg := false 2791 if interval != "" && interval[0] == '-' { 2792 neg = true 2793 interval = interval[1:] 2794 } 2795 switch strings.ToUpper(unit) { 2796 case "HOUR_MINUTE", "MINUTE_SECOND": 2797 interval = strings.Replace(interval, ".", ":", -1) 2798 case "YEAR_MONTH": 2799 interval = strings.Replace(interval, ".", "-", -1) 2800 case "DAY_HOUR": 2801 interval = strings.Replace(interval, ".", " ", -1) 2802 case "DAY_MINUTE": 2803 interval = "0 " + strings.Replace(interval, ".", ":", -1) 2804 case "DAY_SECOND": 2805 interval = "0 00:" + strings.Replace(interval, ".", ":", -1) 2806 case "DAY_MICROSECOND": 2807 interval = "0 00:00:" + interval 2808 case "HOUR_MICROSECOND": 2809 interval = "00:00:" + interval 2810 case "HOUR_SECOND": 2811 interval = "00:" + strings.Replace(interval, ".", ":", -1) 2812 case "MINUTE_MICROSECOND": 2813 interval = "00:" + interval 2814 case "SECOND_MICROSECOND": 2815 /* keep interval as original decimal */ 2816 } 2817 if neg { 2818 interval = "-" + interval 2819 } 2820 case "SECOND": 2821 // interval is already like the %f format. 2822 default: 2823 // YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, MICROSECOND 2824 castExpr := WrapWithCastAsString(ctx, WrapWithCastAsInt(ctx, args[1])) 2825 interval, isNull, err = castExpr.EvalString(ctx, event) 2826 if isNull || err != nil { 2827 return "", true, err 2828 } 2829 } 2830 2831 return interval, false, nil 2832 } 2833 2834 func (du *baseDateArithmitical) getIntervalFromInt(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (string, bool, error) { 2835 interval, isNull, err := args[1].EvalInt(ctx, event) 2836 if isNull || err != nil { 2837 return "", true, err 2838 } 2839 return strconv.FormatInt(interval, 10), false, nil 2840 } 2841 2842 func (du *baseDateArithmitical) getIntervalFromReal(ctx stochastikctx.Context, args []Expression, event chunk.Event, unit string) (string, bool, error) { 2843 interval, isNull, err := args[1].EvalReal(ctx, event) 2844 if isNull || err != nil { 2845 return "", true, err 2846 } 2847 return strconv.FormatFloat(interval, 'f', args[1].GetType().Decimal, 64), false, nil 2848 } 2849 2850 func (du *baseDateArithmitical) add(ctx stochastikctx.Context, date types.Time, interval string, unit string) (types.Time, bool, error) { 2851 year, month, day, nano, err := types.ParseDurationValue(unit, interval) 2852 if err := handleInvalidTimeError(ctx, err); err != nil { 2853 return types.ZeroTime, true, err 2854 } 2855 2856 goTime, err := date.GoTime(time.Local) 2857 if err := handleInvalidTimeError(ctx, err); err != nil { 2858 return types.ZeroTime, true, err 2859 } 2860 2861 goTime = goTime.Add(time.Duration(nano)) 2862 goTime = types.AddDate(year, month, day, goTime) 2863 2864 if goTime.Nanosecond() == 0 { 2865 date.SetFsp(0) 2866 } else { 2867 date.SetFsp(6) 2868 } 2869 2870 if goTime.Year() < 0 || goTime.Year() > 9999 { 2871 return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) 2872 } 2873 2874 date.SetCoreTime(types.FromGoTime(goTime)) 2875 overflow, err := types.DateTimeIsOverflow(ctx.GetStochastikVars().StmtCtx, date) 2876 if err := handleInvalidTimeError(ctx, err); err != nil { 2877 return types.ZeroTime, true, err 2878 } 2879 if overflow { 2880 return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) 2881 } 2882 return date, false, nil 2883 } 2884 2885 func (du *baseDateArithmitical) addDuration(ctx stochastikctx.Context, d types.Duration, interval string, unit string) (types.Duration, bool, error) { 2886 dur, err := types.ExtractDurationValue(unit, interval) 2887 if err != nil { 2888 return types.ZeroDuration, true, handleInvalidTimeError(ctx, err) 2889 } 2890 retDur, err := d.Add(dur) 2891 if err != nil { 2892 return types.ZeroDuration, true, err 2893 } 2894 return retDur, false, nil 2895 } 2896 2897 func (du *baseDateArithmitical) subDuration(ctx stochastikctx.Context, d types.Duration, interval string, unit string) (types.Duration, bool, error) { 2898 dur, err := types.ExtractDurationValue(unit, interval) 2899 if err != nil { 2900 return types.ZeroDuration, true, handleInvalidTimeError(ctx, err) 2901 } 2902 retDur, err := d.Sub(dur) 2903 if err != nil { 2904 return types.ZeroDuration, true, err 2905 } 2906 return retDur, false, nil 2907 } 2908 2909 func (du *baseDateArithmitical) sub(ctx stochastikctx.Context, date types.Time, interval string, unit string) (types.Time, bool, error) { 2910 year, month, day, nano, err := types.ParseDurationValue(unit, interval) 2911 if err := handleInvalidTimeError(ctx, err); err != nil { 2912 return types.ZeroTime, true, err 2913 } 2914 year, month, day, nano = -year, -month, -day, -nano 2915 2916 goTime, err := date.GoTime(time.Local) 2917 if err := handleInvalidTimeError(ctx, err); err != nil { 2918 return types.ZeroTime, true, err 2919 } 2920 2921 duration := time.Duration(nano) 2922 goTime = goTime.Add(duration) 2923 goTime = types.AddDate(year, month, day, goTime) 2924 2925 if goTime.Nanosecond() == 0 { 2926 date.SetFsp(0) 2927 } else { 2928 date.SetFsp(6) 2929 } 2930 2931 if goTime.Year() < 0 || goTime.Year() > 9999 { 2932 return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) 2933 } 2934 2935 date.SetCoreTime(types.FromGoTime(goTime)) 2936 overflow, err := types.DateTimeIsOverflow(ctx.GetStochastikVars().StmtCtx, date) 2937 if err := handleInvalidTimeError(ctx, err); err != nil { 2938 return types.ZeroTime, true, err 2939 } 2940 if overflow { 2941 return types.ZeroTime, true, handleInvalidTimeError(ctx, types.ErrDatetimeFunctionOverflow.GenWithStackByArgs("datetime")) 2942 } 2943 return date, false, nil 2944 } 2945 2946 func (du *baseDateArithmitical) vecGetDateFromInt(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 2947 n := input.NumEvents() 2948 buf, err := b.bufSlabPredictor.get(types.ETInt, n) 2949 if err != nil { 2950 return err 2951 } 2952 defer b.bufSlabPredictor.put(buf) 2953 if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil { 2954 return err 2955 } 2956 2957 result.ResizeTime(n, false) 2958 result.MergeNulls(buf) 2959 dates := result.Times() 2960 i64s := buf.Int64s() 2961 sc := b.ctx.GetStochastikVars().StmtCtx 2962 isClockUnit := types.IsClockUnit(unit) 2963 for i := 0; i < n; i++ { 2964 if result.IsNull(i) { 2965 continue 2966 } 2967 2968 date, err := types.ParseTimeFromInt64(sc, i64s[i]) 2969 if err != nil { 2970 err = handleInvalidTimeError(b.ctx, err) 2971 if err != nil { 2972 return err 2973 } 2974 result.SetNull(i, true) 2975 continue 2976 } 2977 2978 dateTp := allegrosql.TypeDate 2979 if date.Type() == allegrosql.TypeDatetime || date.Type() == allegrosql.TypeTimestamp || isClockUnit { 2980 dateTp = allegrosql.TypeDatetime 2981 } 2982 date.SetType(dateTp) 2983 dates[i] = date 2984 } 2985 return nil 2986 } 2987 2988 func (du *baseDateArithmitical) vecGetDateFromString(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 2989 n := input.NumEvents() 2990 buf, err := b.bufSlabPredictor.get(types.ETString, n) 2991 if err != nil { 2992 return err 2993 } 2994 defer b.bufSlabPredictor.put(buf) 2995 if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { 2996 return err 2997 } 2998 2999 result.ResizeTime(n, false) 3000 result.MergeNulls(buf) 3001 dates := result.Times() 3002 sc := b.ctx.GetStochastikVars().StmtCtx 3003 isClockUnit := types.IsClockUnit(unit) 3004 for i := 0; i < n; i++ { 3005 if result.IsNull(i) { 3006 continue 3007 } 3008 3009 dateStr := buf.GetString(i) 3010 dateTp := allegrosql.TypeDate 3011 if !types.IsDateFormat(dateStr) || isClockUnit { 3012 dateTp = allegrosql.TypeDatetime 3013 } 3014 3015 date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp) 3016 if err != nil { 3017 err = handleInvalidTimeError(b.ctx, err) 3018 if err != nil { 3019 return err 3020 } 3021 result.SetNull(i, true) 3022 } else { 3023 dates[i] = date 3024 } 3025 3026 } 3027 return nil 3028 } 3029 3030 func (du *baseDateArithmitical) vecGetDateFromDatetime(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 3031 n := input.NumEvents() 3032 result.ResizeTime(n, false) 3033 if err := b.args[0].VecEvalTime(b.ctx, input, result); err != nil { 3034 return err 3035 } 3036 3037 dates := result.Times() 3038 isClockUnit := types.IsClockUnit(unit) 3039 for i := 0; i < n; i++ { 3040 if result.IsNull(i) { 3041 continue 3042 } 3043 3044 dateTp := allegrosql.TypeDate 3045 if dates[i].Type() == allegrosql.TypeDatetime || dates[i].Type() == allegrosql.TypeTimestamp || isClockUnit { 3046 dateTp = allegrosql.TypeDatetime 3047 } 3048 dates[i].SetType(dateTp) 3049 } 3050 return nil 3051 } 3052 3053 func (du *baseDateArithmitical) vecGetIntervalFromString(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 3054 n := input.NumEvents() 3055 buf, err := b.bufSlabPredictor.get(types.ETString, n) 3056 if err != nil { 3057 return err 3058 } 3059 defer b.bufSlabPredictor.put(buf) 3060 if err := b.args[1].VecEvalString(b.ctx, input, buf); err != nil { 3061 return err 3062 } 3063 3064 amendInterval := func(val string) string { 3065 return val 3066 } 3067 if unitLower := strings.ToLower(unit); unitLower == "day" || unitLower == "hour" { 3068 amendInterval = func(val string) string { 3069 if intervalLower := strings.ToLower(val); intervalLower == "true" { 3070 return "1" 3071 } else if intervalLower == "false" { 3072 return "0" 3073 } 3074 return du.intervalRegexp.FindString(val) 3075 } 3076 } 3077 3078 result.ReserveString(n) 3079 for i := 0; i < n; i++ { 3080 if buf.IsNull(i) { 3081 result.AppendNull() 3082 continue 3083 } 3084 3085 result.AppendString(amendInterval(buf.GetString(i))) 3086 } 3087 return nil 3088 } 3089 3090 func (du *baseDateArithmitical) vecGetIntervalFromDecimal(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 3091 n := input.NumEvents() 3092 buf, err := b.bufSlabPredictor.get(types.ETDecimal, n) 3093 if err != nil { 3094 return err 3095 } 3096 defer b.bufSlabPredictor.put(buf) 3097 if err := b.args[1].VecEvalDecimal(b.ctx, input, buf); err != nil { 3098 return err 3099 } 3100 3101 isCompoundUnit := false 3102 amendInterval := func(val string, event *chunk.Event) (string, bool, error) { 3103 return val, false, nil 3104 } 3105 switch unitUpper := strings.ToUpper(unit); unitUpper { 3106 case "HOUR_MINUTE", "MINUTE_SECOND", "YEAR_MONTH", "DAY_HOUR", "DAY_MINUTE", 3107 "DAY_SECOND", "DAY_MICROSECOND", "HOUR_MICROSECOND", "HOUR_SECOND", "MINUTE_MICROSECOND", "SECOND_MICROSECOND": 3108 isCompoundUnit = true 3109 switch strings.ToUpper(unit) { 3110 case "HOUR_MINUTE", "MINUTE_SECOND": 3111 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3112 return strings.Replace(val, ".", ":", -1), false, nil 3113 } 3114 case "YEAR_MONTH": 3115 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3116 return strings.Replace(val, ".", "-", -1), false, nil 3117 } 3118 case "DAY_HOUR": 3119 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3120 return strings.Replace(val, ".", " ", -1), false, nil 3121 } 3122 case "DAY_MINUTE": 3123 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3124 return "0 " + strings.Replace(val, ".", ":", -1), false, nil 3125 } 3126 case "DAY_SECOND": 3127 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3128 return "0 00:" + strings.Replace(val, ".", ":", -1), false, nil 3129 } 3130 case "DAY_MICROSECOND": 3131 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3132 return "0 00:00:" + val, false, nil 3133 } 3134 case "HOUR_MICROSECOND": 3135 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3136 return "00:00:" + val, false, nil 3137 } 3138 case "HOUR_SECOND": 3139 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3140 return "00:" + strings.Replace(val, ".", ":", -1), false, nil 3141 } 3142 case "MINUTE_MICROSECOND": 3143 amendInterval = func(val string, _ *chunk.Event) (string, bool, error) { 3144 return "00:" + val, false, nil 3145 } 3146 case "SECOND_MICROSECOND": 3147 /* keep interval as original decimal */ 3148 } 3149 case "SECOND": 3150 /* keep interval as original decimal */ 3151 default: 3152 // YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, MINUTE, MICROSECOND 3153 castExpr := WrapWithCastAsString(b.ctx, WrapWithCastAsInt(b.ctx, b.args[1])) 3154 amendInterval = func(_ string, event *chunk.Event) (string, bool, error) { 3155 interval, isNull, err := castExpr.EvalString(b.ctx, *event) 3156 return interval, isNull || err != nil, err 3157 } 3158 } 3159 3160 result.ReserveString(n) 3161 decs := buf.Decimals() 3162 for i := 0; i < n; i++ { 3163 if buf.IsNull(i) { 3164 result.AppendNull() 3165 continue 3166 } 3167 3168 interval := decs[i].String() 3169 event := input.GetEvent(i) 3170 isNeg := false 3171 if isCompoundUnit && interval != "" && interval[0] == '-' { 3172 isNeg = true 3173 interval = interval[1:] 3174 } 3175 interval, isNull, err := amendInterval(interval, &event) 3176 if err != nil { 3177 return err 3178 } 3179 if isNull { 3180 result.AppendNull() 3181 continue 3182 } 3183 if isCompoundUnit && isNeg { 3184 interval = "-" + interval 3185 } 3186 result.AppendString(interval) 3187 } 3188 return nil 3189 } 3190 3191 func (du *baseDateArithmitical) vecGetIntervalFromInt(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 3192 n := input.NumEvents() 3193 buf, err := b.bufSlabPredictor.get(types.ETInt, n) 3194 if err != nil { 3195 return err 3196 } 3197 defer b.bufSlabPredictor.put(buf) 3198 if err := b.args[1].VecEvalInt(b.ctx, input, buf); err != nil { 3199 return err 3200 } 3201 3202 result.ReserveString(n) 3203 i64s := buf.Int64s() 3204 for i := 0; i < n; i++ { 3205 if buf.IsNull(i) { 3206 result.AppendNull() 3207 } else { 3208 result.AppendString(strconv.FormatInt(i64s[i], 10)) 3209 } 3210 } 3211 return nil 3212 } 3213 3214 func (du *baseDateArithmitical) vecGetIntervalFromReal(b *baseBuiltinFunc, input *chunk.Chunk, unit string, result *chunk.DeferredCauset) error { 3215 n := input.NumEvents() 3216 buf, err := b.bufSlabPredictor.get(types.ETReal, n) 3217 if err != nil { 3218 return err 3219 } 3220 defer b.bufSlabPredictor.put(buf) 3221 if err := b.args[1].VecEvalReal(b.ctx, input, buf); err != nil { 3222 return err 3223 } 3224 3225 result.ReserveString(n) 3226 f64s := buf.Float64s() 3227 prec := b.args[1].GetType().Decimal 3228 for i := 0; i < n; i++ { 3229 if buf.IsNull(i) { 3230 result.AppendNull() 3231 } else { 3232 result.AppendString(strconv.FormatFloat(f64s[i], 'f', prec, 64)) 3233 } 3234 } 3235 return nil 3236 } 3237 3238 type addDateFunctionClass struct { 3239 baseFunctionClass 3240 } 3241 3242 func (c *addDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 3243 if err = c.verifyArgs(args); err != nil { 3244 return nil, err 3245 } 3246 3247 dateEvalTp := args[0].GetType().EvalType() 3248 if dateEvalTp != types.ETString && dateEvalTp != types.ETInt && dateEvalTp != types.ETDuration { 3249 dateEvalTp = types.ETDatetime 3250 } 3251 3252 intervalEvalTp := args[1].GetType().EvalType() 3253 if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal && intervalEvalTp != types.ETReal { 3254 intervalEvalTp = types.ETInt 3255 } 3256 3257 argTps := []types.EvalType{dateEvalTp, intervalEvalTp, types.ETString} 3258 var bf baseBuiltinFunc 3259 if dateEvalTp == types.ETDuration { 3260 unit, _, err := args[2].EvalString(ctx, chunk.Event{}) 3261 if err != nil { 3262 return nil, err 3263 } 3264 internalFsp := 0 3265 switch unit { 3266 // If the unit has micro second, then the fsp must be the MaxFsp. 3267 case "MICROSECOND", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", "HOUR_MICROSECOND", "DAY_MICROSECOND": 3268 internalFsp = int(types.MaxFsp) 3269 // If the unit is second, the fsp is related with the arg[1]'s. 3270 case "SECOND": 3271 internalFsp = int(types.MaxFsp) 3272 if intervalEvalTp != types.ETString { 3273 internalFsp = mathutil.Min(args[1].GetType().Decimal, int(types.MaxFsp)) 3274 } 3275 // Otherwise, the fsp should be 0. 3276 } 3277 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, argTps...) 3278 if err != nil { 3279 return nil, err 3280 } 3281 arg0Dec, err := getExpressionFsp(ctx, args[0]) 3282 if err != nil { 3283 return nil, err 3284 } 3285 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthWithFsp, mathutil.Max(arg0Dec, internalFsp) 3286 } else { 3287 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) 3288 if err != nil { 3289 return nil, err 3290 } 3291 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDatetimeFullWidth, types.UnspecifiedLength 3292 } 3293 3294 switch { 3295 case dateEvalTp == types.ETString && intervalEvalTp == types.ETString: 3296 sig = &builtinAddDateStringStringSig{ 3297 baseBuiltinFunc: bf, 3298 baseDateArithmitical: newDateArighmeticalUtil(), 3299 } 3300 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateStringString) 3301 case dateEvalTp == types.ETString && intervalEvalTp == types.ETInt: 3302 sig = &builtinAddDateStringIntSig{ 3303 baseBuiltinFunc: bf, 3304 baseDateArithmitical: newDateArighmeticalUtil(), 3305 } 3306 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateStringInt) 3307 case dateEvalTp == types.ETString && intervalEvalTp == types.ETReal: 3308 sig = &builtinAddDateStringRealSig{ 3309 baseBuiltinFunc: bf, 3310 baseDateArithmitical: newDateArighmeticalUtil(), 3311 } 3312 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateStringReal) 3313 case dateEvalTp == types.ETString && intervalEvalTp == types.ETDecimal: 3314 sig = &builtinAddDateStringDecimalSig{ 3315 baseBuiltinFunc: bf, 3316 baseDateArithmitical: newDateArighmeticalUtil(), 3317 } 3318 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateStringDecimal) 3319 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETString: 3320 sig = &builtinAddDateIntStringSig{ 3321 baseBuiltinFunc: bf, 3322 baseDateArithmitical: newDateArighmeticalUtil(), 3323 } 3324 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateIntString) 3325 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETInt: 3326 sig = &builtinAddDateIntIntSig{ 3327 baseBuiltinFunc: bf, 3328 baseDateArithmitical: newDateArighmeticalUtil(), 3329 } 3330 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateIntInt) 3331 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETReal: 3332 sig = &builtinAddDateIntRealSig{ 3333 baseBuiltinFunc: bf, 3334 baseDateArithmitical: newDateArighmeticalUtil(), 3335 } 3336 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateIntReal) 3337 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETDecimal: 3338 sig = &builtinAddDateIntDecimalSig{ 3339 baseBuiltinFunc: bf, 3340 baseDateArithmitical: newDateArighmeticalUtil(), 3341 } 3342 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateIntDecimal) 3343 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETString: 3344 sig = &builtinAddDateDatetimeStringSig{ 3345 baseBuiltinFunc: bf, 3346 baseDateArithmitical: newDateArighmeticalUtil(), 3347 } 3348 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDatetimeString) 3349 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETInt: 3350 sig = &builtinAddDateDatetimeIntSig{ 3351 baseBuiltinFunc: bf, 3352 baseDateArithmitical: newDateArighmeticalUtil(), 3353 } 3354 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDatetimeInt) 3355 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETReal: 3356 sig = &builtinAddDateDatetimeRealSig{ 3357 baseBuiltinFunc: bf, 3358 baseDateArithmitical: newDateArighmeticalUtil(), 3359 } 3360 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDatetimeReal) 3361 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETDecimal: 3362 sig = &builtinAddDateDatetimeDecimalSig{ 3363 baseBuiltinFunc: bf, 3364 baseDateArithmitical: newDateArighmeticalUtil(), 3365 } 3366 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDatetimeDecimal) 3367 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETString: 3368 sig = &builtinAddDateDurationStringSig{ 3369 baseBuiltinFunc: bf, 3370 baseDateArithmitical: newDateArighmeticalUtil(), 3371 } 3372 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDurationString) 3373 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETInt: 3374 sig = &builtinAddDateDurationIntSig{ 3375 baseBuiltinFunc: bf, 3376 baseDateArithmitical: newDateArighmeticalUtil(), 3377 } 3378 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDurationInt) 3379 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETReal: 3380 sig = &builtinAddDateDurationRealSig{ 3381 baseBuiltinFunc: bf, 3382 baseDateArithmitical: newDateArighmeticalUtil(), 3383 } 3384 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDurationReal) 3385 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETDecimal: 3386 sig = &builtinAddDateDurationDecimalSig{ 3387 baseBuiltinFunc: bf, 3388 baseDateArithmitical: newDateArighmeticalUtil(), 3389 } 3390 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateDurationDecimal) 3391 } 3392 return sig, nil 3393 } 3394 3395 type builtinAddDateStringStringSig struct { 3396 baseBuiltinFunc 3397 baseDateArithmitical 3398 } 3399 3400 func (b *builtinAddDateStringStringSig) Clone() builtinFunc { 3401 newSig := &builtinAddDateStringStringSig{baseDateArithmitical: b.baseDateArithmitical} 3402 newSig.cloneFrom(&b.baseBuiltinFunc) 3403 return newSig 3404 } 3405 3406 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3407 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3408 func (b *builtinAddDateStringStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3409 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3410 if isNull || err != nil { 3411 return types.ZeroTime, true, err 3412 } 3413 3414 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 3415 if isNull || err != nil { 3416 return types.ZeroTime, true, err 3417 } 3418 3419 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 3420 if isNull || err != nil { 3421 return types.ZeroTime, true, err 3422 } 3423 3424 result, isNull, err := b.add(b.ctx, date, interval, unit) 3425 return result, isNull || err != nil, err 3426 } 3427 3428 type builtinAddDateStringIntSig struct { 3429 baseBuiltinFunc 3430 baseDateArithmitical 3431 } 3432 3433 func (b *builtinAddDateStringIntSig) Clone() builtinFunc { 3434 newSig := &builtinAddDateStringIntSig{baseDateArithmitical: b.baseDateArithmitical} 3435 newSig.cloneFrom(&b.baseBuiltinFunc) 3436 return newSig 3437 } 3438 3439 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3440 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3441 func (b *builtinAddDateStringIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3442 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3443 if isNull || err != nil { 3444 return types.ZeroTime, true, err 3445 } 3446 3447 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 3448 if isNull || err != nil { 3449 return types.ZeroTime, true, err 3450 } 3451 3452 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 3453 if isNull || err != nil { 3454 return types.ZeroTime, true, err 3455 } 3456 3457 result, isNull, err := b.add(b.ctx, date, interval, unit) 3458 return result, isNull || err != nil, err 3459 } 3460 3461 type builtinAddDateStringRealSig struct { 3462 baseBuiltinFunc 3463 baseDateArithmitical 3464 } 3465 3466 func (b *builtinAddDateStringRealSig) Clone() builtinFunc { 3467 newSig := &builtinAddDateStringRealSig{baseDateArithmitical: b.baseDateArithmitical} 3468 newSig.cloneFrom(&b.baseBuiltinFunc) 3469 return newSig 3470 } 3471 3472 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3473 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3474 func (b *builtinAddDateStringRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3475 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3476 if isNull || err != nil { 3477 return types.ZeroTime, true, err 3478 } 3479 3480 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 3481 if isNull || err != nil { 3482 return types.ZeroTime, true, err 3483 } 3484 3485 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 3486 if isNull || err != nil { 3487 return types.ZeroTime, true, err 3488 } 3489 3490 result, isNull, err := b.add(b.ctx, date, interval, unit) 3491 return result, isNull || err != nil, err 3492 } 3493 3494 type builtinAddDateStringDecimalSig struct { 3495 baseBuiltinFunc 3496 baseDateArithmitical 3497 } 3498 3499 func (b *builtinAddDateStringDecimalSig) Clone() builtinFunc { 3500 newSig := &builtinAddDateStringDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 3501 newSig.cloneFrom(&b.baseBuiltinFunc) 3502 return newSig 3503 } 3504 3505 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3506 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3507 func (b *builtinAddDateStringDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3508 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3509 if isNull || err != nil { 3510 return types.ZeroTime, true, err 3511 } 3512 3513 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 3514 if isNull || err != nil { 3515 return types.ZeroTime, true, err 3516 } 3517 3518 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 3519 if isNull || err != nil { 3520 return types.ZeroTime, true, err 3521 } 3522 3523 result, isNull, err := b.add(b.ctx, date, interval, unit) 3524 return result, isNull || err != nil, err 3525 } 3526 3527 type builtinAddDateIntStringSig struct { 3528 baseBuiltinFunc 3529 baseDateArithmitical 3530 } 3531 3532 func (b *builtinAddDateIntStringSig) Clone() builtinFunc { 3533 newSig := &builtinAddDateIntStringSig{baseDateArithmitical: b.baseDateArithmitical} 3534 newSig.cloneFrom(&b.baseBuiltinFunc) 3535 return newSig 3536 } 3537 3538 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3539 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3540 func (b *builtinAddDateIntStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3541 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3542 if isNull || err != nil { 3543 return types.ZeroTime, true, err 3544 } 3545 3546 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 3547 if isNull || err != nil { 3548 return types.ZeroTime, true, err 3549 } 3550 3551 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 3552 if isNull || err != nil { 3553 return types.ZeroTime, true, err 3554 } 3555 3556 result, isNull, err := b.add(b.ctx, date, interval, unit) 3557 return result, isNull || err != nil, err 3558 } 3559 3560 type builtinAddDateIntIntSig struct { 3561 baseBuiltinFunc 3562 baseDateArithmitical 3563 } 3564 3565 func (b *builtinAddDateIntIntSig) Clone() builtinFunc { 3566 newSig := &builtinAddDateIntIntSig{baseDateArithmitical: b.baseDateArithmitical} 3567 newSig.cloneFrom(&b.baseBuiltinFunc) 3568 return newSig 3569 } 3570 3571 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3572 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3573 func (b *builtinAddDateIntIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3574 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3575 if isNull || err != nil { 3576 return types.ZeroTime, true, err 3577 } 3578 3579 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 3580 if isNull || err != nil { 3581 return types.ZeroTime, true, err 3582 } 3583 3584 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 3585 if isNull || err != nil { 3586 return types.ZeroTime, true, err 3587 } 3588 3589 result, isNull, err := b.add(b.ctx, date, interval, unit) 3590 return result, isNull || err != nil, err 3591 } 3592 3593 type builtinAddDateIntRealSig struct { 3594 baseBuiltinFunc 3595 baseDateArithmitical 3596 } 3597 3598 func (b *builtinAddDateIntRealSig) Clone() builtinFunc { 3599 newSig := &builtinAddDateIntRealSig{baseDateArithmitical: b.baseDateArithmitical} 3600 newSig.cloneFrom(&b.baseBuiltinFunc) 3601 return newSig 3602 } 3603 3604 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3605 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3606 func (b *builtinAddDateIntRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3607 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3608 if isNull || err != nil { 3609 return types.ZeroTime, true, err 3610 } 3611 3612 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 3613 if isNull || err != nil { 3614 return types.ZeroTime, true, err 3615 } 3616 3617 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 3618 if isNull || err != nil { 3619 return types.ZeroTime, true, err 3620 } 3621 3622 result, isNull, err := b.add(b.ctx, date, interval, unit) 3623 return result, isNull || err != nil, err 3624 } 3625 3626 type builtinAddDateIntDecimalSig struct { 3627 baseBuiltinFunc 3628 baseDateArithmitical 3629 } 3630 3631 func (b *builtinAddDateIntDecimalSig) Clone() builtinFunc { 3632 newSig := &builtinAddDateIntDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 3633 newSig.cloneFrom(&b.baseBuiltinFunc) 3634 return newSig 3635 } 3636 3637 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3638 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3639 func (b *builtinAddDateIntDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3640 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3641 if isNull || err != nil { 3642 return types.ZeroTime, true, err 3643 } 3644 3645 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 3646 if isNull || err != nil { 3647 return types.ZeroTime, true, err 3648 } 3649 3650 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 3651 if isNull || err != nil { 3652 return types.ZeroTime, true, err 3653 } 3654 3655 result, isNull, err := b.add(b.ctx, date, interval, unit) 3656 return result, isNull || err != nil, err 3657 } 3658 3659 type builtinAddDateDatetimeStringSig struct { 3660 baseBuiltinFunc 3661 baseDateArithmitical 3662 } 3663 3664 func (b *builtinAddDateDatetimeStringSig) Clone() builtinFunc { 3665 newSig := &builtinAddDateDatetimeStringSig{baseDateArithmitical: b.baseDateArithmitical} 3666 newSig.cloneFrom(&b.baseBuiltinFunc) 3667 return newSig 3668 } 3669 3670 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3671 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3672 func (b *builtinAddDateDatetimeStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3673 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3674 if isNull || err != nil { 3675 return types.ZeroTime, true, err 3676 } 3677 3678 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 3679 if isNull || err != nil { 3680 return types.ZeroTime, true, err 3681 } 3682 3683 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 3684 if isNull || err != nil { 3685 return types.ZeroTime, true, err 3686 } 3687 3688 result, isNull, err := b.add(b.ctx, date, interval, unit) 3689 return result, isNull || err != nil, err 3690 } 3691 3692 type builtinAddDateDatetimeIntSig struct { 3693 baseBuiltinFunc 3694 baseDateArithmitical 3695 } 3696 3697 func (b *builtinAddDateDatetimeIntSig) Clone() builtinFunc { 3698 newSig := &builtinAddDateDatetimeIntSig{baseDateArithmitical: b.baseDateArithmitical} 3699 newSig.cloneFrom(&b.baseBuiltinFunc) 3700 return newSig 3701 } 3702 3703 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3704 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3705 func (b *builtinAddDateDatetimeIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3706 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3707 if isNull || err != nil { 3708 return types.ZeroTime, true, err 3709 } 3710 3711 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 3712 if isNull || err != nil { 3713 return types.ZeroTime, true, err 3714 } 3715 3716 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 3717 if isNull || err != nil { 3718 return types.ZeroTime, true, err 3719 } 3720 3721 result, isNull, err := b.add(b.ctx, date, interval, unit) 3722 return result, isNull || err != nil, err 3723 } 3724 3725 type builtinAddDateDatetimeRealSig struct { 3726 baseBuiltinFunc 3727 baseDateArithmitical 3728 } 3729 3730 func (b *builtinAddDateDatetimeRealSig) Clone() builtinFunc { 3731 newSig := &builtinAddDateDatetimeRealSig{baseDateArithmitical: b.baseDateArithmitical} 3732 newSig.cloneFrom(&b.baseBuiltinFunc) 3733 return newSig 3734 } 3735 3736 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3737 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3738 func (b *builtinAddDateDatetimeRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3739 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3740 if isNull || err != nil { 3741 return types.ZeroTime, true, err 3742 } 3743 3744 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 3745 if isNull || err != nil { 3746 return types.ZeroTime, true, err 3747 } 3748 3749 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 3750 if isNull || err != nil { 3751 return types.ZeroTime, true, err 3752 } 3753 3754 result, isNull, err := b.add(b.ctx, date, interval, unit) 3755 return result, isNull || err != nil, err 3756 } 3757 3758 type builtinAddDateDatetimeDecimalSig struct { 3759 baseBuiltinFunc 3760 baseDateArithmitical 3761 } 3762 3763 func (b *builtinAddDateDatetimeDecimalSig) Clone() builtinFunc { 3764 newSig := &builtinAddDateDatetimeDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 3765 newSig.cloneFrom(&b.baseBuiltinFunc) 3766 return newSig 3767 } 3768 3769 // evalTime evals ADDDATE(date,INTERVAL expr unit). 3770 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate 3771 func (b *builtinAddDateDatetimeDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 3772 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3773 if isNull || err != nil { 3774 return types.ZeroTime, true, err 3775 } 3776 3777 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 3778 if isNull || err != nil { 3779 return types.ZeroTime, true, err 3780 } 3781 3782 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 3783 if isNull || err != nil { 3784 return types.ZeroTime, true, err 3785 } 3786 3787 result, isNull, err := b.add(b.ctx, date, interval, unit) 3788 return result, isNull || err != nil, err 3789 } 3790 3791 type builtinAddDateDurationStringSig struct { 3792 baseBuiltinFunc 3793 baseDateArithmitical 3794 } 3795 3796 func (b *builtinAddDateDurationStringSig) Clone() builtinFunc { 3797 newSig := &builtinAddDateDurationStringSig{baseDateArithmitical: b.baseDateArithmitical} 3798 newSig.cloneFrom(&b.baseBuiltinFunc) 3799 return newSig 3800 } 3801 3802 func (b *builtinAddDateDurationStringSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 3803 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3804 if isNull || err != nil { 3805 return types.ZeroDuration, true, err 3806 } 3807 3808 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 3809 if isNull || err != nil { 3810 return types.ZeroDuration, true, err 3811 } 3812 3813 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 3814 if isNull || err != nil { 3815 return types.ZeroDuration, true, err 3816 } 3817 3818 result, isNull, err := b.addDuration(b.ctx, dur, interval, unit) 3819 return result, isNull || err != nil, err 3820 } 3821 3822 type builtinAddDateDurationIntSig struct { 3823 baseBuiltinFunc 3824 baseDateArithmitical 3825 } 3826 3827 func (b *builtinAddDateDurationIntSig) Clone() builtinFunc { 3828 newSig := &builtinAddDateDurationIntSig{baseDateArithmitical: b.baseDateArithmitical} 3829 newSig.cloneFrom(&b.baseBuiltinFunc) 3830 return newSig 3831 } 3832 3833 func (b *builtinAddDateDurationIntSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 3834 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3835 if isNull || err != nil { 3836 return types.ZeroDuration, true, err 3837 } 3838 3839 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 3840 if isNull || err != nil { 3841 return types.ZeroDuration, true, err 3842 } 3843 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 3844 if isNull || err != nil { 3845 return types.ZeroDuration, true, err 3846 } 3847 3848 result, isNull, err := b.addDuration(b.ctx, dur, interval, unit) 3849 return result, isNull || err != nil, err 3850 } 3851 3852 type builtinAddDateDurationDecimalSig struct { 3853 baseBuiltinFunc 3854 baseDateArithmitical 3855 } 3856 3857 func (b *builtinAddDateDurationDecimalSig) Clone() builtinFunc { 3858 newSig := &builtinAddDateDurationDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 3859 newSig.cloneFrom(&b.baseBuiltinFunc) 3860 return newSig 3861 } 3862 3863 func (b *builtinAddDateDurationDecimalSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 3864 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3865 if isNull || err != nil { 3866 return types.ZeroDuration, true, err 3867 } 3868 3869 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 3870 if isNull || err != nil { 3871 return types.ZeroDuration, true, err 3872 } 3873 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 3874 if isNull || err != nil { 3875 return types.ZeroDuration, true, err 3876 } 3877 3878 result, isNull, err := b.addDuration(b.ctx, dur, interval, unit) 3879 return result, isNull || err != nil, err 3880 } 3881 3882 type builtinAddDateDurationRealSig struct { 3883 baseBuiltinFunc 3884 baseDateArithmitical 3885 } 3886 3887 func (b *builtinAddDateDurationRealSig) Clone() builtinFunc { 3888 newSig := &builtinAddDateDurationRealSig{baseDateArithmitical: b.baseDateArithmitical} 3889 newSig.cloneFrom(&b.baseBuiltinFunc) 3890 return newSig 3891 } 3892 3893 func (b *builtinAddDateDurationRealSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 3894 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 3895 if isNull || err != nil { 3896 return types.ZeroDuration, true, err 3897 } 3898 3899 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 3900 if isNull || err != nil { 3901 return types.ZeroDuration, true, err 3902 } 3903 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 3904 if isNull || err != nil { 3905 return types.ZeroDuration, true, err 3906 } 3907 3908 result, isNull, err := b.addDuration(b.ctx, dur, interval, unit) 3909 return result, isNull || err != nil, err 3910 } 3911 3912 type subDateFunctionClass struct { 3913 baseFunctionClass 3914 } 3915 3916 func (c *subDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 3917 if err = c.verifyArgs(args); err != nil { 3918 return nil, err 3919 } 3920 3921 dateEvalTp := args[0].GetType().EvalType() 3922 if dateEvalTp != types.ETString && dateEvalTp != types.ETInt && dateEvalTp != types.ETDuration { 3923 dateEvalTp = types.ETDatetime 3924 } 3925 3926 intervalEvalTp := args[1].GetType().EvalType() 3927 if intervalEvalTp != types.ETString && intervalEvalTp != types.ETDecimal && intervalEvalTp != types.ETReal { 3928 intervalEvalTp = types.ETInt 3929 } 3930 3931 argTps := []types.EvalType{dateEvalTp, intervalEvalTp, types.ETString} 3932 var bf baseBuiltinFunc 3933 if dateEvalTp == types.ETDuration { 3934 unit, _, err := args[2].EvalString(ctx, chunk.Event{}) 3935 if err != nil { 3936 return nil, err 3937 } 3938 internalFsp := 0 3939 switch unit { 3940 // If the unit has micro second, then the fsp must be the MaxFsp. 3941 case "MICROSECOND", "SECOND_MICROSECOND", "MINUTE_MICROSECOND", "HOUR_MICROSECOND", "DAY_MICROSECOND": 3942 internalFsp = int(types.MaxFsp) 3943 // If the unit is second, the fsp is related with the arg[1]'s. 3944 case "SECOND": 3945 internalFsp = int(types.MaxFsp) 3946 if intervalEvalTp != types.ETString { 3947 internalFsp = mathutil.Min(args[1].GetType().Decimal, int(types.MaxFsp)) 3948 } 3949 // Otherwise, the fsp should be 0. 3950 } 3951 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, argTps...) 3952 if err != nil { 3953 return nil, err 3954 } 3955 arg0Dec, err := getExpressionFsp(ctx, args[0]) 3956 if err != nil { 3957 return nil, err 3958 } 3959 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDurationWidthWithFsp, mathutil.Max(arg0Dec, internalFsp) 3960 } else { 3961 bf, err = newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, argTps...) 3962 if err != nil { 3963 return nil, err 3964 } 3965 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDatetimeFullWidth, types.UnspecifiedLength 3966 } 3967 3968 switch { 3969 case dateEvalTp == types.ETString && intervalEvalTp == types.ETString: 3970 sig = &builtinSubDateStringStringSig{ 3971 baseBuiltinFunc: bf, 3972 baseDateArithmitical: newDateArighmeticalUtil(), 3973 } 3974 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateStringString) 3975 case dateEvalTp == types.ETString && intervalEvalTp == types.ETInt: 3976 sig = &builtinSubDateStringIntSig{ 3977 baseBuiltinFunc: bf, 3978 baseDateArithmitical: newDateArighmeticalUtil(), 3979 } 3980 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateStringInt) 3981 case dateEvalTp == types.ETString && intervalEvalTp == types.ETReal: 3982 sig = &builtinSubDateStringRealSig{ 3983 baseBuiltinFunc: bf, 3984 baseDateArithmitical: newDateArighmeticalUtil(), 3985 } 3986 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateStringReal) 3987 case dateEvalTp == types.ETString && intervalEvalTp == types.ETDecimal: 3988 sig = &builtinSubDateStringDecimalSig{ 3989 baseBuiltinFunc: bf, 3990 baseDateArithmitical: newDateArighmeticalUtil(), 3991 } 3992 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateStringDecimal) 3993 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETString: 3994 sig = &builtinSubDateIntStringSig{ 3995 baseBuiltinFunc: bf, 3996 baseDateArithmitical: newDateArighmeticalUtil(), 3997 } 3998 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateIntString) 3999 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETInt: 4000 sig = &builtinSubDateIntIntSig{ 4001 baseBuiltinFunc: bf, 4002 baseDateArithmitical: newDateArighmeticalUtil(), 4003 } 4004 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateIntInt) 4005 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETReal: 4006 sig = &builtinSubDateIntRealSig{ 4007 baseBuiltinFunc: bf, 4008 baseDateArithmitical: newDateArighmeticalUtil(), 4009 } 4010 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateIntReal) 4011 case dateEvalTp == types.ETInt && intervalEvalTp == types.ETDecimal: 4012 sig = &builtinSubDateIntDecimalSig{ 4013 baseBuiltinFunc: bf, 4014 baseDateArithmitical: newDateArighmeticalUtil(), 4015 } 4016 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateIntDecimal) 4017 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETString: 4018 sig = &builtinSubDateDatetimeStringSig{ 4019 baseBuiltinFunc: bf, 4020 baseDateArithmitical: newDateArighmeticalUtil(), 4021 } 4022 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDatetimeString) 4023 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETInt: 4024 sig = &builtinSubDateDatetimeIntSig{ 4025 baseBuiltinFunc: bf, 4026 baseDateArithmitical: newDateArighmeticalUtil(), 4027 } 4028 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDatetimeInt) 4029 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETReal: 4030 sig = &builtinSubDateDatetimeRealSig{ 4031 baseBuiltinFunc: bf, 4032 baseDateArithmitical: newDateArighmeticalUtil(), 4033 } 4034 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDatetimeReal) 4035 case dateEvalTp == types.ETDatetime && intervalEvalTp == types.ETDecimal: 4036 sig = &builtinSubDateDatetimeDecimalSig{ 4037 baseBuiltinFunc: bf, 4038 baseDateArithmitical: newDateArighmeticalUtil(), 4039 } 4040 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDatetimeDecimal) 4041 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETString: 4042 sig = &builtinSubDateDurationStringSig{ 4043 baseBuiltinFunc: bf, 4044 baseDateArithmitical: newDateArighmeticalUtil(), 4045 } 4046 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDurationString) 4047 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETInt: 4048 sig = &builtinSubDateDurationIntSig{ 4049 baseBuiltinFunc: bf, 4050 baseDateArithmitical: newDateArighmeticalUtil(), 4051 } 4052 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDurationInt) 4053 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETReal: 4054 sig = &builtinSubDateDurationRealSig{ 4055 baseBuiltinFunc: bf, 4056 baseDateArithmitical: newDateArighmeticalUtil(), 4057 } 4058 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDurationReal) 4059 case dateEvalTp == types.ETDuration && intervalEvalTp == types.ETDecimal: 4060 sig = &builtinSubDateDurationDecimalSig{ 4061 baseBuiltinFunc: bf, 4062 baseDateArithmitical: newDateArighmeticalUtil(), 4063 } 4064 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateDurationDecimal) 4065 } 4066 return sig, nil 4067 } 4068 4069 type builtinSubDateStringStringSig struct { 4070 baseBuiltinFunc 4071 baseDateArithmitical 4072 } 4073 4074 func (b *builtinSubDateStringStringSig) Clone() builtinFunc { 4075 newSig := &builtinSubDateStringStringSig{baseDateArithmitical: b.baseDateArithmitical} 4076 newSig.cloneFrom(&b.baseBuiltinFunc) 4077 return newSig 4078 } 4079 4080 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4081 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4082 func (b *builtinSubDateStringStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4083 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4084 if isNull || err != nil { 4085 return types.ZeroTime, true, err 4086 } 4087 4088 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 4089 if isNull || err != nil { 4090 return types.ZeroTime, true, err 4091 } 4092 4093 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 4094 if isNull || err != nil { 4095 return types.ZeroTime, true, err 4096 } 4097 4098 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4099 return result, isNull || err != nil, err 4100 } 4101 4102 type builtinSubDateStringIntSig struct { 4103 baseBuiltinFunc 4104 baseDateArithmitical 4105 } 4106 4107 func (b *builtinSubDateStringIntSig) Clone() builtinFunc { 4108 newSig := &builtinSubDateStringIntSig{baseDateArithmitical: b.baseDateArithmitical} 4109 newSig.cloneFrom(&b.baseBuiltinFunc) 4110 return newSig 4111 } 4112 4113 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4114 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4115 func (b *builtinSubDateStringIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4116 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4117 if isNull || err != nil { 4118 return types.ZeroTime, true, err 4119 } 4120 4121 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 4122 if isNull || err != nil { 4123 return types.ZeroTime, true, err 4124 } 4125 4126 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 4127 if isNull || err != nil { 4128 return types.ZeroTime, true, err 4129 } 4130 4131 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4132 return result, isNull || err != nil, err 4133 } 4134 4135 type builtinSubDateStringRealSig struct { 4136 baseBuiltinFunc 4137 baseDateArithmitical 4138 } 4139 4140 func (b *builtinSubDateStringRealSig) Clone() builtinFunc { 4141 newSig := &builtinSubDateStringRealSig{baseDateArithmitical: b.baseDateArithmitical} 4142 newSig.cloneFrom(&b.baseBuiltinFunc) 4143 return newSig 4144 } 4145 4146 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4147 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4148 func (b *builtinSubDateStringRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4149 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4150 if isNull || err != nil { 4151 return types.ZeroTime, true, err 4152 } 4153 4154 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 4155 if isNull || err != nil { 4156 return types.ZeroTime, true, err 4157 } 4158 4159 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 4160 if isNull || err != nil { 4161 return types.ZeroTime, true, err 4162 } 4163 4164 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4165 return result, isNull || err != nil, err 4166 } 4167 4168 type builtinSubDateStringDecimalSig struct { 4169 baseBuiltinFunc 4170 baseDateArithmitical 4171 } 4172 4173 func (b *builtinSubDateStringDecimalSig) Clone() builtinFunc { 4174 newSig := &builtinSubDateStringDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 4175 newSig.cloneFrom(&b.baseBuiltinFunc) 4176 return newSig 4177 } 4178 4179 func (b *builtinSubDateStringDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4180 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4181 if isNull || err != nil { 4182 return types.ZeroTime, true, err 4183 } 4184 4185 date, isNull, err := b.getDateFromString(b.ctx, b.args, event, unit) 4186 if isNull || err != nil { 4187 return types.ZeroTime, true, err 4188 } 4189 4190 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 4191 if isNull || err != nil { 4192 return types.ZeroTime, true, err 4193 } 4194 4195 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4196 return result, isNull || err != nil, err 4197 } 4198 4199 type builtinSubDateIntStringSig struct { 4200 baseBuiltinFunc 4201 baseDateArithmitical 4202 } 4203 4204 func (b *builtinSubDateIntStringSig) Clone() builtinFunc { 4205 newSig := &builtinSubDateIntStringSig{baseDateArithmitical: b.baseDateArithmitical} 4206 newSig.cloneFrom(&b.baseBuiltinFunc) 4207 return newSig 4208 } 4209 4210 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4211 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4212 func (b *builtinSubDateIntStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4213 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4214 if isNull || err != nil { 4215 return types.ZeroTime, true, err 4216 } 4217 4218 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 4219 if isNull || err != nil { 4220 return types.ZeroTime, true, err 4221 } 4222 4223 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 4224 if isNull || err != nil { 4225 return types.ZeroTime, true, err 4226 } 4227 4228 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4229 return result, isNull || err != nil, err 4230 } 4231 4232 type builtinSubDateIntIntSig struct { 4233 baseBuiltinFunc 4234 baseDateArithmitical 4235 } 4236 4237 func (b *builtinSubDateIntIntSig) Clone() builtinFunc { 4238 newSig := &builtinSubDateIntIntSig{baseDateArithmitical: b.baseDateArithmitical} 4239 newSig.cloneFrom(&b.baseBuiltinFunc) 4240 return newSig 4241 } 4242 4243 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4244 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4245 func (b *builtinSubDateIntIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4246 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4247 if isNull || err != nil { 4248 return types.ZeroTime, true, err 4249 } 4250 4251 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 4252 if isNull || err != nil { 4253 return types.ZeroTime, true, err 4254 } 4255 4256 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 4257 if isNull || err != nil { 4258 return types.ZeroTime, true, err 4259 } 4260 4261 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4262 return result, isNull || err != nil, err 4263 } 4264 4265 type builtinSubDateIntRealSig struct { 4266 baseBuiltinFunc 4267 baseDateArithmitical 4268 } 4269 4270 func (b *builtinSubDateIntRealSig) Clone() builtinFunc { 4271 newSig := &builtinSubDateIntRealSig{baseDateArithmitical: b.baseDateArithmitical} 4272 newSig.cloneFrom(&b.baseBuiltinFunc) 4273 return newSig 4274 } 4275 4276 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4277 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4278 func (b *builtinSubDateIntRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4279 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4280 if isNull || err != nil { 4281 return types.ZeroTime, true, err 4282 } 4283 4284 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 4285 if isNull || err != nil { 4286 return types.ZeroTime, true, err 4287 } 4288 4289 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 4290 if isNull || err != nil { 4291 return types.ZeroTime, true, err 4292 } 4293 4294 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4295 return result, isNull || err != nil, err 4296 } 4297 4298 type builtinSubDateDatetimeStringSig struct { 4299 baseBuiltinFunc 4300 baseDateArithmitical 4301 } 4302 4303 type builtinSubDateIntDecimalSig struct { 4304 baseBuiltinFunc 4305 baseDateArithmitical 4306 } 4307 4308 func (b *builtinSubDateIntDecimalSig) Clone() builtinFunc { 4309 newSig := &builtinSubDateIntDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 4310 newSig.cloneFrom(&b.baseBuiltinFunc) 4311 return newSig 4312 } 4313 4314 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4315 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4316 func (b *builtinSubDateIntDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4317 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4318 if isNull || err != nil { 4319 return types.ZeroTime, true, err 4320 } 4321 4322 date, isNull, err := b.getDateFromInt(b.ctx, b.args, event, unit) 4323 if isNull || err != nil { 4324 return types.ZeroTime, true, err 4325 } 4326 4327 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 4328 if isNull || err != nil { 4329 return types.ZeroTime, true, err 4330 } 4331 4332 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4333 return result, isNull || err != nil, err 4334 } 4335 4336 func (b *builtinSubDateDatetimeStringSig) Clone() builtinFunc { 4337 newSig := &builtinSubDateDatetimeStringSig{baseDateArithmitical: b.baseDateArithmitical} 4338 newSig.cloneFrom(&b.baseBuiltinFunc) 4339 return newSig 4340 } 4341 4342 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4343 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4344 func (b *builtinSubDateDatetimeStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4345 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4346 if isNull || err != nil { 4347 return types.ZeroTime, true, err 4348 } 4349 4350 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 4351 if isNull || err != nil { 4352 return types.ZeroTime, true, err 4353 } 4354 4355 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 4356 if isNull || err != nil { 4357 return types.ZeroTime, true, err 4358 } 4359 4360 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4361 return result, isNull || err != nil, err 4362 } 4363 4364 type builtinSubDateDatetimeIntSig struct { 4365 baseBuiltinFunc 4366 baseDateArithmitical 4367 } 4368 4369 func (b *builtinSubDateDatetimeIntSig) Clone() builtinFunc { 4370 newSig := &builtinSubDateDatetimeIntSig{baseDateArithmitical: b.baseDateArithmitical} 4371 newSig.cloneFrom(&b.baseBuiltinFunc) 4372 return newSig 4373 } 4374 4375 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4376 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4377 func (b *builtinSubDateDatetimeIntSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4378 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4379 if isNull || err != nil { 4380 return types.ZeroTime, true, err 4381 } 4382 4383 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 4384 if isNull || err != nil { 4385 return types.ZeroTime, true, err 4386 } 4387 4388 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 4389 if isNull || err != nil { 4390 return types.ZeroTime, true, err 4391 } 4392 4393 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4394 return result, isNull || err != nil, err 4395 } 4396 4397 type builtinSubDateDatetimeRealSig struct { 4398 baseBuiltinFunc 4399 baseDateArithmitical 4400 } 4401 4402 func (b *builtinSubDateDatetimeRealSig) Clone() builtinFunc { 4403 newSig := &builtinSubDateDatetimeRealSig{baseDateArithmitical: b.baseDateArithmitical} 4404 newSig.cloneFrom(&b.baseBuiltinFunc) 4405 return newSig 4406 } 4407 4408 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4409 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4410 func (b *builtinSubDateDatetimeRealSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4411 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4412 if isNull || err != nil { 4413 return types.ZeroTime, true, err 4414 } 4415 4416 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 4417 if isNull || err != nil { 4418 return types.ZeroTime, true, err 4419 } 4420 4421 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 4422 if isNull || err != nil { 4423 return types.ZeroTime, true, err 4424 } 4425 4426 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4427 return result, isNull || err != nil, err 4428 } 4429 4430 type builtinSubDateDatetimeDecimalSig struct { 4431 baseBuiltinFunc 4432 baseDateArithmitical 4433 } 4434 4435 func (b *builtinSubDateDatetimeDecimalSig) Clone() builtinFunc { 4436 newSig := &builtinSubDateDatetimeDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 4437 newSig.cloneFrom(&b.baseBuiltinFunc) 4438 return newSig 4439 } 4440 4441 // evalTime evals SUBDATE(date,INTERVAL expr unit). 4442 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate 4443 func (b *builtinSubDateDatetimeDecimalSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4444 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4445 if isNull || err != nil { 4446 return types.ZeroTime, true, err 4447 } 4448 4449 date, isNull, err := b.getDateFromDatetime(b.ctx, b.args, event, unit) 4450 if isNull || err != nil { 4451 return types.ZeroTime, true, err 4452 } 4453 4454 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 4455 if isNull || err != nil { 4456 return types.ZeroTime, true, err 4457 } 4458 4459 result, isNull, err := b.sub(b.ctx, date, interval, unit) 4460 return result, isNull || err != nil, err 4461 } 4462 4463 type builtinSubDateDurationStringSig struct { 4464 baseBuiltinFunc 4465 baseDateArithmitical 4466 } 4467 4468 func (b *builtinSubDateDurationStringSig) Clone() builtinFunc { 4469 newSig := &builtinSubDateDurationStringSig{baseDateArithmitical: b.baseDateArithmitical} 4470 newSig.cloneFrom(&b.baseBuiltinFunc) 4471 return newSig 4472 } 4473 4474 func (b *builtinSubDateDurationStringSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 4475 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4476 if isNull || err != nil { 4477 return types.ZeroDuration, true, err 4478 } 4479 4480 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 4481 if isNull || err != nil { 4482 return types.ZeroDuration, true, err 4483 } 4484 4485 interval, isNull, err := b.getIntervalFromString(b.ctx, b.args, event, unit) 4486 if isNull || err != nil { 4487 return types.ZeroDuration, true, err 4488 } 4489 4490 result, isNull, err := b.subDuration(b.ctx, dur, interval, unit) 4491 return result, isNull || err != nil, err 4492 } 4493 4494 type builtinSubDateDurationIntSig struct { 4495 baseBuiltinFunc 4496 baseDateArithmitical 4497 } 4498 4499 func (b *builtinSubDateDurationIntSig) Clone() builtinFunc { 4500 newSig := &builtinSubDateDurationIntSig{baseDateArithmitical: b.baseDateArithmitical} 4501 newSig.cloneFrom(&b.baseBuiltinFunc) 4502 return newSig 4503 } 4504 4505 func (b *builtinSubDateDurationIntSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 4506 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4507 if isNull || err != nil { 4508 return types.ZeroDuration, true, err 4509 } 4510 4511 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 4512 if isNull || err != nil { 4513 return types.ZeroDuration, true, err 4514 } 4515 4516 interval, isNull, err := b.getIntervalFromInt(b.ctx, b.args, event, unit) 4517 if isNull || err != nil { 4518 return types.ZeroDuration, true, err 4519 } 4520 4521 result, isNull, err := b.subDuration(b.ctx, dur, interval, unit) 4522 return result, isNull || err != nil, err 4523 } 4524 4525 type builtinSubDateDurationDecimalSig struct { 4526 baseBuiltinFunc 4527 baseDateArithmitical 4528 } 4529 4530 func (b *builtinSubDateDurationDecimalSig) Clone() builtinFunc { 4531 newSig := &builtinSubDateDurationDecimalSig{baseDateArithmitical: b.baseDateArithmitical} 4532 newSig.cloneFrom(&b.baseBuiltinFunc) 4533 return newSig 4534 } 4535 4536 func (b *builtinSubDateDurationDecimalSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 4537 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4538 if isNull || err != nil { 4539 return types.ZeroDuration, true, err 4540 } 4541 4542 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 4543 if isNull || err != nil { 4544 return types.ZeroDuration, true, err 4545 } 4546 4547 interval, isNull, err := b.getIntervalFromDecimal(b.ctx, b.args, event, unit) 4548 if isNull || err != nil { 4549 return types.ZeroDuration, true, err 4550 } 4551 4552 result, isNull, err := b.subDuration(b.ctx, dur, interval, unit) 4553 return result, isNull || err != nil, err 4554 } 4555 4556 type builtinSubDateDurationRealSig struct { 4557 baseBuiltinFunc 4558 baseDateArithmitical 4559 } 4560 4561 func (b *builtinSubDateDurationRealSig) Clone() builtinFunc { 4562 newSig := &builtinSubDateDurationRealSig{baseDateArithmitical: b.baseDateArithmitical} 4563 newSig.cloneFrom(&b.baseBuiltinFunc) 4564 return newSig 4565 } 4566 4567 func (b *builtinSubDateDurationRealSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 4568 unit, isNull, err := b.args[2].EvalString(b.ctx, event) 4569 if isNull || err != nil { 4570 return types.ZeroDuration, true, err 4571 } 4572 4573 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 4574 if isNull || err != nil { 4575 return types.ZeroDuration, true, err 4576 } 4577 interval, isNull, err := b.getIntervalFromReal(b.ctx, b.args, event, unit) 4578 if isNull || err != nil { 4579 return types.ZeroDuration, true, err 4580 } 4581 4582 result, isNull, err := b.subDuration(b.ctx, dur, interval, unit) 4583 return result, isNull || err != nil, err 4584 } 4585 4586 type timestamFIDeliffFunctionClass struct { 4587 baseFunctionClass 4588 } 4589 4590 func (c *timestamFIDeliffFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 4591 if err := c.verifyArgs(args); err != nil { 4592 return nil, err 4593 } 4594 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString, types.ETDatetime, types.ETDatetime) 4595 if err != nil { 4596 return nil, err 4597 } 4598 sig := &builtinTimestamFIDeliffSig{bf} 4599 sig.setPbCode(fidelpb.ScalarFuncSig_TimestamFIDeliff) 4600 return sig, nil 4601 } 4602 4603 type builtinTimestamFIDeliffSig struct { 4604 baseBuiltinFunc 4605 } 4606 4607 func (b *builtinTimestamFIDeliffSig) Clone() builtinFunc { 4608 newSig := &builtinTimestamFIDeliffSig{} 4609 newSig.cloneFrom(&b.baseBuiltinFunc) 4610 return newSig 4611 } 4612 4613 // evalInt evals a builtinTimestamFIDeliffSig. 4614 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestamFIDeliff 4615 func (b *builtinTimestamFIDeliffSig) evalInt(event chunk.Event) (int64, bool, error) { 4616 unit, isNull, err := b.args[0].EvalString(b.ctx, event) 4617 if isNull || err != nil { 4618 return 0, isNull, err 4619 } 4620 lhs, isNull, err := b.args[1].EvalTime(b.ctx, event) 4621 if isNull || err != nil { 4622 return 0, isNull, handleInvalidTimeError(b.ctx, err) 4623 } 4624 rhs, isNull, err := b.args[2].EvalTime(b.ctx, event) 4625 if isNull || err != nil { 4626 return 0, isNull, handleInvalidTimeError(b.ctx, err) 4627 } 4628 if invalidLHS, invalidRHS := lhs.InvalidZero(), rhs.InvalidZero(); invalidLHS || invalidRHS { 4629 if invalidLHS { 4630 err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, lhs.String())) 4631 } 4632 if invalidRHS { 4633 err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, rhs.String())) 4634 } 4635 return 0, true, err 4636 } 4637 return types.TimestamFIDeliff(unit, lhs, rhs), false, nil 4638 } 4639 4640 type unixTimestampFunctionClass struct { 4641 baseFunctionClass 4642 } 4643 4644 func (c *unixTimestampFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 4645 if err := c.verifyArgs(args); err != nil { 4646 return nil, err 4647 } 4648 var ( 4649 argTps []types.EvalType 4650 retTp types.EvalType 4651 retFLen, retDecimal int 4652 ) 4653 4654 if len(args) == 0 { 4655 retTp, retDecimal = types.ETInt, 0 4656 } else { 4657 argTps = []types.EvalType{types.ETDatetime} 4658 argType := args[0].GetType() 4659 argEvaltp := argType.EvalType() 4660 if argEvaltp == types.ETString { 4661 // Treat types.ETString as unspecified decimal. 4662 retDecimal = types.UnspecifiedLength 4663 if cnst, ok := args[0].(*Constant); ok { 4664 tmpStr, _, err := cnst.EvalString(ctx, chunk.Event{}) 4665 if err != nil { 4666 return nil, err 4667 } 4668 retDecimal = 0 4669 if dotIdx := strings.LastIndex(tmpStr, "."); dotIdx >= 0 { 4670 retDecimal = len(tmpStr) - dotIdx - 1 4671 } 4672 } 4673 } else { 4674 retDecimal = argType.Decimal 4675 } 4676 if retDecimal > 6 || retDecimal == types.UnspecifiedLength { 4677 retDecimal = 6 4678 } 4679 if retDecimal == 0 { 4680 retTp = types.ETInt 4681 } else { 4682 retTp = types.ETDecimal 4683 } 4684 } 4685 if retTp == types.ETInt { 4686 retFLen = 11 4687 } else if retTp == types.ETDecimal { 4688 retFLen = 12 + retDecimal 4689 } else { 4690 panic("Unexpected retTp") 4691 } 4692 4693 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, retTp, argTps...) 4694 if err != nil { 4695 return nil, err 4696 } 4697 bf.tp.Flen = retFLen 4698 bf.tp.Decimal = retDecimal 4699 4700 var sig builtinFunc 4701 if len(args) == 0 { 4702 sig = &builtinUnixTimestampCurrentSig{bf} 4703 sig.setPbCode(fidelpb.ScalarFuncSig_UnixTimestampCurrent) 4704 } else if retTp == types.ETInt { 4705 sig = &builtinUnixTimestampIntSig{bf} 4706 sig.setPbCode(fidelpb.ScalarFuncSig_UnixTimestampInt) 4707 } else if retTp == types.ETDecimal { 4708 sig = &builtinUnixTimestamFIDelecSig{bf} 4709 sig.setPbCode(fidelpb.ScalarFuncSig_UnixTimestamFIDelec) 4710 } 4711 return sig, nil 4712 } 4713 4714 // goTimeToMysqlUnixTimestamp converts go time into MyALLEGROSQL's Unix timestamp. 4715 // MyALLEGROSQL's Unix timestamp ranges in int32. Values out of range should be rewritten to 0. 4716 func goTimeToMysqlUnixTimestamp(t time.Time, decimal int) (*types.MyDecimal, error) { 4717 nanoSeconds := t.UnixNano() 4718 if nanoSeconds < 0 || (nanoSeconds/1e3) >= (math.MaxInt32+1)*1e6 { 4719 return new(types.MyDecimal), nil 4720 } 4721 dec := new(types.MyDecimal) 4722 // Here we don't use float to prevent precision lose. 4723 dec.FromInt(nanoSeconds) 4724 err := dec.Shift(-9) 4725 if err != nil { 4726 return nil, err 4727 } 4728 4729 // In MyALLEGROSQL's implementation, unix_timestamp() will truncate the result instead of rounding it. 4730 // Results below are from MyALLEGROSQL 5.7, which can prove it. 4731 // allegrosql> select unix_timestamp(), unix_timestamp(now(0)), now(0), unix_timestamp(now(3)), now(3), now(6); 4732 // +------------------+------------------------+---------------------+------------------------+-------------------------+----------------------------+ 4733 // | unix_timestamp() | unix_timestamp(now(0)) | now(0) | unix_timestamp(now(3)) | now(3) | now(6) | 4734 // +------------------+------------------------+---------------------+------------------------+-------------------------+----------------------------+ 4735 // | 1553503194 | 1553503194 | 2020-03-25 16:39:54 | 1553503194.992 | 2020-03-25 16:39:54.992 | 2020-03-25 16:39:54.992969 | 4736 // +------------------+------------------------+---------------------+------------------------+-------------------------+----------------------------+ 4737 err = dec.Round(dec, decimal, types.ModeTruncate) 4738 return dec, err 4739 } 4740 4741 type builtinUnixTimestampCurrentSig struct { 4742 baseBuiltinFunc 4743 } 4744 4745 func (b *builtinUnixTimestampCurrentSig) Clone() builtinFunc { 4746 newSig := &builtinUnixTimestampCurrentSig{} 4747 newSig.cloneFrom(&b.baseBuiltinFunc) 4748 return newSig 4749 } 4750 4751 // evalInt evals a UNIX_TIMESTAMP(). 4752 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp 4753 func (b *builtinUnixTimestampCurrentSig) evalInt(event chunk.Event) (int64, bool, error) { 4754 nowTs, err := getStmtTimestamp(b.ctx) 4755 if err != nil { 4756 return 0, true, err 4757 } 4758 dec, err := goTimeToMysqlUnixTimestamp(nowTs, 1) 4759 if err != nil { 4760 return 0, true, err 4761 } 4762 intVal, err := dec.ToInt() 4763 if !terror.ErrorEqual(err, types.ErrTruncated) { 4764 terror.Log(err) 4765 } 4766 return intVal, false, nil 4767 } 4768 4769 type builtinUnixTimestampIntSig struct { 4770 baseBuiltinFunc 4771 } 4772 4773 func (b *builtinUnixTimestampIntSig) Clone() builtinFunc { 4774 newSig := &builtinUnixTimestampIntSig{} 4775 newSig.cloneFrom(&b.baseBuiltinFunc) 4776 return newSig 4777 } 4778 4779 // evalInt evals a UNIX_TIMESTAMP(time). 4780 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp 4781 func (b *builtinUnixTimestampIntSig) evalInt(event chunk.Event) (int64, bool, error) { 4782 return b.evalIntWithCtx(b.ctx, event) 4783 } 4784 4785 func (b *builtinUnixTimestampIntSig) evalIntWithCtx(ctx stochastikctx.Context, event chunk.Event) (int64, bool, error) { 4786 val, isNull, err := b.args[0].EvalTime(ctx, event) 4787 if err != nil && terror.ErrorEqual(types.ErrWrongValue.GenWithStackByArgs(types.TimeStr, val), err) { 4788 // Return 0 for invalid date time. 4789 return 0, false, nil 4790 } 4791 if isNull { 4792 return 0, true, nil 4793 } 4794 4795 tz := ctx.GetStochastikVars().Location() 4796 t, err := val.GoTime(tz) 4797 if err != nil { 4798 return 0, false, nil 4799 } 4800 dec, err := goTimeToMysqlUnixTimestamp(t, 1) 4801 if err != nil { 4802 return 0, true, err 4803 } 4804 intVal, err := dec.ToInt() 4805 if !terror.ErrorEqual(err, types.ErrTruncated) { 4806 terror.Log(err) 4807 } 4808 return intVal, false, nil 4809 } 4810 4811 type builtinUnixTimestamFIDelecSig struct { 4812 baseBuiltinFunc 4813 } 4814 4815 func (b *builtinUnixTimestamFIDelecSig) Clone() builtinFunc { 4816 newSig := &builtinUnixTimestamFIDelecSig{} 4817 newSig.cloneFrom(&b.baseBuiltinFunc) 4818 return newSig 4819 } 4820 4821 // evalDecimal evals a UNIX_TIMESTAMP(time). 4822 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp 4823 func (b *builtinUnixTimestamFIDelecSig) evalDecimal(event chunk.Event) (*types.MyDecimal, bool, error) { 4824 val, isNull, err := b.args[0].EvalTime(b.ctx, event) 4825 if isNull || err != nil { 4826 // Return 0 for invalid date time. 4827 return new(types.MyDecimal), isNull, nil 4828 } 4829 t, err := val.GoTime(getTimeZone(b.ctx)) 4830 if err != nil { 4831 return new(types.MyDecimal), false, nil 4832 } 4833 result, err := goTimeToMysqlUnixTimestamp(t, b.tp.Decimal) 4834 return result, err != nil, err 4835 } 4836 4837 type timestampFunctionClass struct { 4838 baseFunctionClass 4839 } 4840 4841 func (c *timestampFunctionClass) getDefaultFsp(tp *types.FieldType) int8 { 4842 if tp.Tp == allegrosql.TypeDatetime || tp.Tp == allegrosql.TypeDate || tp.Tp == allegrosql.TypeDuration || 4843 tp.Tp == allegrosql.TypeTimestamp { 4844 return int8(tp.Decimal) 4845 } 4846 switch cls := tp.EvalType(); cls { 4847 case types.ETInt: 4848 return types.MinFsp 4849 case types.ETReal, types.ETDatetime, types.ETTimestamp, types.ETDuration, types.ETJson, types.ETString: 4850 return types.MaxFsp 4851 case types.ETDecimal: 4852 if tp.Decimal < int(types.MaxFsp) { 4853 return int8(tp.Decimal) 4854 } 4855 return types.MaxFsp 4856 } 4857 return types.MaxFsp 4858 } 4859 4860 func (c *timestampFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 4861 if err := c.verifyArgs(args); err != nil { 4862 return nil, err 4863 } 4864 evalTps, argLen := []types.EvalType{types.ETString}, len(args) 4865 if argLen == 2 { 4866 evalTps = append(evalTps, types.ETString) 4867 } 4868 fsp := c.getDefaultFsp(args[0].GetType()) 4869 if argLen == 2 { 4870 fsp = mathutil.MaxInt8(fsp, c.getDefaultFsp(args[1].GetType())) 4871 } 4872 isFloat := false 4873 switch args[0].GetType().Tp { 4874 case allegrosql.TypeFloat, allegrosql.TypeDouble, allegrosql.TypeNewDecimal: 4875 isFloat = true 4876 } 4877 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, evalTps...) 4878 if err != nil { 4879 return nil, err 4880 } 4881 bf.tp.Decimal, bf.tp.Flen = -1, 19 4882 if fsp != 0 { 4883 bf.tp.Flen += 1 + int(fsp) 4884 } 4885 var sig builtinFunc 4886 if argLen == 2 { 4887 sig = &builtinTimestamp2ArgsSig{bf, isFloat} 4888 sig.setPbCode(fidelpb.ScalarFuncSig_Timestamp2Args) 4889 } else { 4890 sig = &builtinTimestamp1ArgSig{bf, isFloat} 4891 sig.setPbCode(fidelpb.ScalarFuncSig_Timestamp1Arg) 4892 } 4893 return sig, nil 4894 } 4895 4896 type builtinTimestamp1ArgSig struct { 4897 baseBuiltinFunc 4898 4899 isFloat bool 4900 } 4901 4902 func (b *builtinTimestamp1ArgSig) Clone() builtinFunc { 4903 newSig := &builtinTimestamp1ArgSig{isFloat: b.isFloat} 4904 newSig.cloneFrom(&b.baseBuiltinFunc) 4905 return newSig 4906 } 4907 4908 // evalTime evals a builtinTimestamp1ArgSig. 4909 // See https://dev.allegrosql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestamp 4910 func (b *builtinTimestamp1ArgSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4911 s, isNull, err := b.args[0].EvalString(b.ctx, event) 4912 if isNull || err != nil { 4913 return types.ZeroTime, isNull, err 4914 } 4915 var tm types.Time 4916 sc := b.ctx.GetStochastikVars().StmtCtx 4917 if b.isFloat { 4918 tm, err = types.ParseTimeFromFloatString(sc, s, allegrosql.TypeDatetime, types.GetFsp(s)) 4919 } else { 4920 tm, err = types.ParseTime(sc, s, allegrosql.TypeDatetime, types.GetFsp(s)) 4921 } 4922 if err != nil { 4923 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 4924 } 4925 return tm, false, nil 4926 } 4927 4928 type builtinTimestamp2ArgsSig struct { 4929 baseBuiltinFunc 4930 4931 isFloat bool 4932 } 4933 4934 func (b *builtinTimestamp2ArgsSig) Clone() builtinFunc { 4935 newSig := &builtinTimestamp2ArgsSig{isFloat: b.isFloat} 4936 newSig.cloneFrom(&b.baseBuiltinFunc) 4937 return newSig 4938 } 4939 4940 // evalTime evals a builtinTimestamp2ArgsSig. 4941 // See https://dev.allegrosql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestamp 4942 func (b *builtinTimestamp2ArgsSig) evalTime(event chunk.Event) (types.Time, bool, error) { 4943 arg0, isNull, err := b.args[0].EvalString(b.ctx, event) 4944 if isNull || err != nil { 4945 return types.ZeroTime, isNull, err 4946 } 4947 var tm types.Time 4948 sc := b.ctx.GetStochastikVars().StmtCtx 4949 if b.isFloat { 4950 tm, err = types.ParseTimeFromFloatString(sc, arg0, allegrosql.TypeDatetime, types.GetFsp(arg0)) 4951 } else { 4952 tm, err = types.ParseTime(sc, arg0, allegrosql.TypeDatetime, types.GetFsp(arg0)) 4953 } 4954 if err != nil { 4955 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 4956 } 4957 arg1, isNull, err := b.args[1].EvalString(b.ctx, event) 4958 if isNull || err != nil { 4959 return types.ZeroTime, isNull, err 4960 } 4961 if !isDuration(arg1) { 4962 return types.ZeroTime, true, nil 4963 } 4964 duration, err := types.ParseDuration(sc, arg1, types.GetFsp(arg1)) 4965 if err != nil { 4966 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 4967 } 4968 tmp, err := tm.Add(sc, duration) 4969 if err != nil { 4970 return types.ZeroTime, true, err 4971 } 4972 return tmp, false, nil 4973 } 4974 4975 type timestampLiteralFunctionClass struct { 4976 baseFunctionClass 4977 } 4978 4979 func (c *timestampLiteralFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 4980 if err := c.verifyArgs(args); err != nil { 4981 return nil, err 4982 } 4983 con, ok := args[0].(*Constant) 4984 if !ok { 4985 panic("Unexpected parameter for timestamp literal") 4986 } 4987 dt, err := con.Eval(chunk.Event{}) 4988 if err != nil { 4989 return nil, err 4990 } 4991 str, err := dt.ToString() 4992 if err != nil { 4993 return nil, err 4994 } 4995 if !timestampPattern.MatchString(str) { 4996 return nil, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, str) 4997 } 4998 tm, err := types.ParseTime(ctx.GetStochastikVars().StmtCtx, str, allegrosql.TypeTimestamp, types.GetFsp(str)) 4999 if err != nil { 5000 return nil, err 5001 } 5002 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, []Expression{}, types.ETDatetime) 5003 if err != nil { 5004 return nil, err 5005 } 5006 bf.tp.Flen, bf.tp.Decimal = allegrosql.MaxDatetimeWidthNoFsp, int(tm.Fsp()) 5007 if tm.Fsp() > 0 { 5008 bf.tp.Flen += int(tm.Fsp()) + 1 5009 } 5010 sig := &builtinTimestampLiteralSig{bf, tm} 5011 return sig, nil 5012 } 5013 5014 type builtinTimestampLiteralSig struct { 5015 baseBuiltinFunc 5016 tm types.Time 5017 } 5018 5019 func (b *builtinTimestampLiteralSig) Clone() builtinFunc { 5020 newSig := &builtinTimestampLiteralSig{tm: b.tm} 5021 newSig.cloneFrom(&b.baseBuiltinFunc) 5022 return newSig 5023 } 5024 5025 // evalTime evals TIMESTAMP 'stringLit'. 5026 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-literals.html 5027 func (b *builtinTimestampLiteralSig) evalTime(event chunk.Event) (types.Time, bool, error) { 5028 return b.tm, false, nil 5029 } 5030 5031 // getFsp4TimeAddSub is used to in function 'ADDTIME' and 'SUBTIME' to evaluate `fsp` for the 5032 // second parameter. It's used only if the second parameter is of string type. It's different 5033 // from getFsp in that the result of getFsp4TimeAddSub is either 6 or 0. 5034 func getFsp4TimeAddSub(s string) int8 { 5035 if len(s)-strings.Index(s, ".")-1 == len(s) { 5036 return types.MinFsp 5037 } 5038 for _, c := range s[strings.Index(s, ".")+1:] { 5039 if c != '0' { 5040 return types.MaxFsp 5041 } 5042 } 5043 return types.MinFsp 5044 } 5045 5046 // getBf4TimeAddSub parses input types, generates baseBuiltinFunc and set related attributes for 5047 // builtin function 'ADDTIME' and 'SUBTIME' 5048 func getBf4TimeAddSub(ctx stochastikctx.Context, funcName string, args []Expression) (tp1, tp2 *types.FieldType, bf baseBuiltinFunc, err error) { 5049 tp1, tp2 = args[0].GetType(), args[1].GetType() 5050 var argTp1, argTp2, retTp types.EvalType 5051 switch tp1.Tp { 5052 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5053 argTp1, retTp = types.ETDatetime, types.ETDatetime 5054 case allegrosql.TypeDuration: 5055 argTp1, retTp = types.ETDuration, types.ETDuration 5056 case allegrosql.TypeDate: 5057 argTp1, retTp = types.ETDuration, types.ETString 5058 default: 5059 argTp1, retTp = types.ETString, types.ETString 5060 } 5061 switch tp2.Tp { 5062 case allegrosql.TypeDatetime, allegrosql.TypeDuration: 5063 argTp2 = types.ETDuration 5064 default: 5065 argTp2 = types.ETString 5066 } 5067 arg0Dec, err := getExpressionFsp(ctx, args[0]) 5068 if err != nil { 5069 return 5070 } 5071 arg1Dec, err := getExpressionFsp(ctx, args[1]) 5072 if err != nil { 5073 return 5074 } 5075 5076 bf, err = newBaseBuiltinFuncWithTp(ctx, funcName, args, retTp, argTp1, argTp2) 5077 if err != nil { 5078 return 5079 } 5080 bf.tp.Decimal = mathutil.Min(mathutil.Max(arg0Dec, arg1Dec), int(types.MaxFsp)) 5081 if retTp == types.ETString { 5082 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeString, allegrosql.MaxDatetimeWidthWithFsp, types.UnspecifiedLength 5083 } 5084 return 5085 } 5086 5087 func getTimeZone(ctx stochastikctx.Context) *time.Location { 5088 ret := ctx.GetStochastikVars().TimeZone 5089 if ret == nil { 5090 ret = time.Local 5091 } 5092 return ret 5093 } 5094 5095 // isDuration returns a boolean indicating whether the str matches the format of duration. 5096 // See https://dev.allegrosql.com/doc/refman/5.7/en/time.html 5097 func isDuration(str string) bool { 5098 return durationPattern.MatchString(str) 5099 } 5100 5101 // strDatetimeAddDuration adds duration to datetime string, returns a string value. 5102 func strDatetimeAddDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (string, error) { 5103 arg0, err := types.ParseTime(sc, d, allegrosql.TypeDatetime, types.MaxFsp) 5104 if err != nil { 5105 return "", err 5106 } 5107 ret, err := arg0.Add(sc, arg1) 5108 if err != nil { 5109 return "", err 5110 } 5111 fsp := types.MaxFsp 5112 if ret.Microsecond() == 0 { 5113 fsp = types.MinFsp 5114 } 5115 ret.SetFsp(fsp) 5116 return ret.String(), nil 5117 } 5118 5119 // strDurationAddDuration adds duration to duration string, returns a string value. 5120 func strDurationAddDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (string, error) { 5121 arg0, err := types.ParseDuration(sc, d, types.MaxFsp) 5122 if err != nil { 5123 return "", err 5124 } 5125 tmFIDeluration, err := arg0.Add(arg1) 5126 if err != nil { 5127 return "", err 5128 } 5129 tmFIDeluration.Fsp = types.MaxFsp 5130 if tmFIDeluration.MicroSecond() == 0 { 5131 tmFIDeluration.Fsp = types.MinFsp 5132 } 5133 return tmFIDeluration.String(), nil 5134 } 5135 5136 // strDatetimeSubDuration subtracts duration from datetime string, returns a string value. 5137 func strDatetimeSubDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (string, error) { 5138 arg0, err := types.ParseTime(sc, d, allegrosql.TypeDatetime, types.MaxFsp) 5139 if err != nil { 5140 return "", err 5141 } 5142 arg1time, err := arg1.ConvertToTime(sc, uint8(types.GetFsp(arg1.String()))) 5143 if err != nil { 5144 return "", err 5145 } 5146 tmFIDeluration := arg0.Sub(sc, &arg1time) 5147 fsp := types.MaxFsp 5148 if tmFIDeluration.MicroSecond() == 0 { 5149 fsp = types.MinFsp 5150 } 5151 resultDuration, err := tmFIDeluration.ConvertToTime(sc, allegrosql.TypeDatetime) 5152 if err != nil { 5153 return "", err 5154 } 5155 resultDuration.SetFsp(fsp) 5156 return resultDuration.String(), nil 5157 } 5158 5159 // strDurationSubDuration subtracts duration from duration string, returns a string value. 5160 func strDurationSubDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (string, error) { 5161 arg0, err := types.ParseDuration(sc, d, types.MaxFsp) 5162 if err != nil { 5163 return "", err 5164 } 5165 tmFIDeluration, err := arg0.Sub(arg1) 5166 if err != nil { 5167 return "", err 5168 } 5169 tmFIDeluration.Fsp = types.MaxFsp 5170 if tmFIDeluration.MicroSecond() == 0 { 5171 tmFIDeluration.Fsp = types.MinFsp 5172 } 5173 return tmFIDeluration.String(), nil 5174 } 5175 5176 type addTimeFunctionClass struct { 5177 baseFunctionClass 5178 } 5179 5180 func (c *addTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 5181 if err = c.verifyArgs(args); err != nil { 5182 return nil, err 5183 } 5184 tp1, tp2, bf, err := getBf4TimeAddSub(ctx, c.funcName, args) 5185 if err != nil { 5186 return nil, err 5187 } 5188 switch tp1.Tp { 5189 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5190 switch tp2.Tp { 5191 case allegrosql.TypeDuration: 5192 sig = &builtinAddDatetimeAndDurationSig{bf} 5193 sig.setPbCode(fidelpb.ScalarFuncSig_AddDatetimeAndDuration) 5194 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5195 sig = &builtinAddTimeDateTimeNullSig{bf} 5196 sig.setPbCode(fidelpb.ScalarFuncSig_AddTimeDateTimeNull) 5197 default: 5198 sig = &builtinAddDatetimeAndStringSig{bf} 5199 sig.setPbCode(fidelpb.ScalarFuncSig_AddDatetimeAndString) 5200 } 5201 case allegrosql.TypeDate: 5202 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 5203 switch tp2.Tp { 5204 case allegrosql.TypeDuration: 5205 sig = &builtinAddDateAndDurationSig{bf} 5206 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateAndDuration) 5207 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5208 sig = &builtinAddTimeStringNullSig{bf} 5209 sig.setPbCode(fidelpb.ScalarFuncSig_AddTimeStringNull) 5210 default: 5211 sig = &builtinAddDateAndStringSig{bf} 5212 sig.setPbCode(fidelpb.ScalarFuncSig_AddDateAndString) 5213 } 5214 case allegrosql.TypeDuration: 5215 switch tp2.Tp { 5216 case allegrosql.TypeDuration: 5217 sig = &builtinAddDurationAndDurationSig{bf} 5218 sig.setPbCode(fidelpb.ScalarFuncSig_AddDurationAndDuration) 5219 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5220 sig = &builtinAddTimeDurationNullSig{bf} 5221 sig.setPbCode(fidelpb.ScalarFuncSig_AddTimeDurationNull) 5222 default: 5223 sig = &builtinAddDurationAndStringSig{bf} 5224 sig.setPbCode(fidelpb.ScalarFuncSig_AddDurationAndString) 5225 } 5226 default: 5227 switch tp2.Tp { 5228 case allegrosql.TypeDuration: 5229 sig = &builtinAddStringAndDurationSig{bf} 5230 sig.setPbCode(fidelpb.ScalarFuncSig_AddStringAndDuration) 5231 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 5232 sig = &builtinAddTimeStringNullSig{bf} 5233 sig.setPbCode(fidelpb.ScalarFuncSig_AddTimeStringNull) 5234 default: 5235 sig = &builtinAddStringAndStringSig{bf} 5236 sig.setPbCode(fidelpb.ScalarFuncSig_AddStringAndString) 5237 } 5238 } 5239 return sig, nil 5240 } 5241 5242 type builtinAddTimeDateTimeNullSig struct { 5243 baseBuiltinFunc 5244 } 5245 5246 func (b *builtinAddTimeDateTimeNullSig) Clone() builtinFunc { 5247 newSig := &builtinAddTimeDateTimeNullSig{} 5248 newSig.cloneFrom(&b.baseBuiltinFunc) 5249 return newSig 5250 } 5251 5252 // evalTime evals a builtinAddTimeDateTimeNullSig. 5253 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5254 func (b *builtinAddTimeDateTimeNullSig) evalTime(event chunk.Event) (types.Time, bool, error) { 5255 return types.ZeroDatetime, true, nil 5256 } 5257 5258 type builtinAddDatetimeAndDurationSig struct { 5259 baseBuiltinFunc 5260 } 5261 5262 func (b *builtinAddDatetimeAndDurationSig) Clone() builtinFunc { 5263 newSig := &builtinAddDatetimeAndDurationSig{} 5264 newSig.cloneFrom(&b.baseBuiltinFunc) 5265 return newSig 5266 } 5267 5268 // evalTime evals a builtinAddDatetimeAndDurationSig. 5269 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5270 func (b *builtinAddDatetimeAndDurationSig) evalTime(event chunk.Event) (types.Time, bool, error) { 5271 arg0, isNull, err := b.args[0].EvalTime(b.ctx, event) 5272 if isNull || err != nil { 5273 return types.ZeroDatetime, isNull, err 5274 } 5275 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 5276 if isNull || err != nil { 5277 return types.ZeroDatetime, isNull, err 5278 } 5279 result, err := arg0.Add(b.ctx.GetStochastikVars().StmtCtx, arg1) 5280 return result, err != nil, err 5281 } 5282 5283 type builtinAddDatetimeAndStringSig struct { 5284 baseBuiltinFunc 5285 } 5286 5287 func (b *builtinAddDatetimeAndStringSig) Clone() builtinFunc { 5288 newSig := &builtinAddDatetimeAndStringSig{} 5289 newSig.cloneFrom(&b.baseBuiltinFunc) 5290 return newSig 5291 } 5292 5293 // evalTime evals a builtinAddDatetimeAndStringSig. 5294 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5295 func (b *builtinAddDatetimeAndStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 5296 arg0, isNull, err := b.args[0].EvalTime(b.ctx, event) 5297 if isNull || err != nil { 5298 return types.ZeroDatetime, isNull, err 5299 } 5300 s, isNull, err := b.args[1].EvalString(b.ctx, event) 5301 if isNull || err != nil { 5302 return types.ZeroDatetime, isNull, err 5303 } 5304 if !isDuration(s) { 5305 return types.ZeroDatetime, true, nil 5306 } 5307 sc := b.ctx.GetStochastikVars().StmtCtx 5308 arg1, err := types.ParseDuration(sc, s, types.GetFsp(s)) 5309 if err != nil { 5310 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5311 sc.AppendWarning(err) 5312 return types.ZeroDatetime, true, nil 5313 } 5314 return types.ZeroDatetime, true, err 5315 } 5316 result, err := arg0.Add(sc, arg1) 5317 return result, err != nil, err 5318 } 5319 5320 type builtinAddTimeDurationNullSig struct { 5321 baseBuiltinFunc 5322 } 5323 5324 func (b *builtinAddTimeDurationNullSig) Clone() builtinFunc { 5325 newSig := &builtinAddTimeDurationNullSig{} 5326 newSig.cloneFrom(&b.baseBuiltinFunc) 5327 return newSig 5328 } 5329 5330 // evalDuration evals a builtinAddTimeDurationNullSig. 5331 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5332 func (b *builtinAddTimeDurationNullSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 5333 return types.ZeroDuration, true, nil 5334 } 5335 5336 type builtinAddDurationAndDurationSig struct { 5337 baseBuiltinFunc 5338 } 5339 5340 func (b *builtinAddDurationAndDurationSig) Clone() builtinFunc { 5341 newSig := &builtinAddDurationAndDurationSig{} 5342 newSig.cloneFrom(&b.baseBuiltinFunc) 5343 return newSig 5344 } 5345 5346 // evalDuration evals a builtinAddDurationAndDurationSig. 5347 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5348 func (b *builtinAddDurationAndDurationSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 5349 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 5350 if isNull || err != nil { 5351 return types.ZeroDuration, isNull, err 5352 } 5353 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 5354 if isNull || err != nil { 5355 return types.ZeroDuration, isNull, err 5356 } 5357 result, err := arg0.Add(arg1) 5358 if err != nil { 5359 return types.ZeroDuration, true, err 5360 } 5361 return result, false, nil 5362 } 5363 5364 type builtinAddDurationAndStringSig struct { 5365 baseBuiltinFunc 5366 } 5367 5368 func (b *builtinAddDurationAndStringSig) Clone() builtinFunc { 5369 newSig := &builtinAddDurationAndStringSig{} 5370 newSig.cloneFrom(&b.baseBuiltinFunc) 5371 return newSig 5372 } 5373 5374 // evalDuration evals a builtinAddDurationAndStringSig. 5375 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5376 func (b *builtinAddDurationAndStringSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 5377 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 5378 if isNull || err != nil { 5379 return types.ZeroDuration, isNull, err 5380 } 5381 s, isNull, err := b.args[1].EvalString(b.ctx, event) 5382 if isNull || err != nil { 5383 return types.ZeroDuration, isNull, err 5384 } 5385 if !isDuration(s) { 5386 return types.ZeroDuration, true, nil 5387 } 5388 sc := b.ctx.GetStochastikVars().StmtCtx 5389 arg1, err := types.ParseDuration(sc, s, types.GetFsp(s)) 5390 if err != nil { 5391 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5392 sc.AppendWarning(err) 5393 return types.ZeroDuration, true, nil 5394 } 5395 return types.ZeroDuration, true, err 5396 } 5397 result, err := arg0.Add(arg1) 5398 if err != nil { 5399 return types.ZeroDuration, true, err 5400 } 5401 return result, false, nil 5402 } 5403 5404 type builtinAddTimeStringNullSig struct { 5405 baseBuiltinFunc 5406 } 5407 5408 func (b *builtinAddTimeStringNullSig) Clone() builtinFunc { 5409 newSig := &builtinAddTimeStringNullSig{} 5410 newSig.cloneFrom(&b.baseBuiltinFunc) 5411 return newSig 5412 } 5413 5414 // evalString evals a builtinAddDurationAndDurationSig. 5415 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5416 func (b *builtinAddTimeStringNullSig) evalString(event chunk.Event) (string, bool, error) { 5417 return "", true, nil 5418 } 5419 5420 type builtinAddStringAndDurationSig struct { 5421 baseBuiltinFunc 5422 } 5423 5424 func (b *builtinAddStringAndDurationSig) Clone() builtinFunc { 5425 newSig := &builtinAddStringAndDurationSig{} 5426 newSig.cloneFrom(&b.baseBuiltinFunc) 5427 return newSig 5428 } 5429 5430 // evalString evals a builtinAddStringAndDurationSig. 5431 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5432 func (b *builtinAddStringAndDurationSig) evalString(event chunk.Event) (result string, isNull bool, err error) { 5433 var ( 5434 arg0 string 5435 arg1 types.Duration 5436 ) 5437 arg0, isNull, err = b.args[0].EvalString(b.ctx, event) 5438 if isNull || err != nil { 5439 return "", isNull, err 5440 } 5441 arg1, isNull, err = b.args[1].EvalDuration(b.ctx, event) 5442 if isNull || err != nil { 5443 return "", isNull, err 5444 } 5445 sc := b.ctx.GetStochastikVars().StmtCtx 5446 if isDuration(arg0) { 5447 result, err = strDurationAddDuration(sc, arg0, arg1) 5448 if err != nil { 5449 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5450 sc.AppendWarning(err) 5451 return "", true, nil 5452 } 5453 return "", true, err 5454 } 5455 return result, false, nil 5456 } 5457 result, err = strDatetimeAddDuration(sc, arg0, arg1) 5458 return result, err != nil, err 5459 } 5460 5461 type builtinAddStringAndStringSig struct { 5462 baseBuiltinFunc 5463 } 5464 5465 func (b *builtinAddStringAndStringSig) Clone() builtinFunc { 5466 newSig := &builtinAddStringAndStringSig{} 5467 newSig.cloneFrom(&b.baseBuiltinFunc) 5468 return newSig 5469 } 5470 5471 // evalString evals a builtinAddStringAndStringSig. 5472 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5473 func (b *builtinAddStringAndStringSig) evalString(event chunk.Event) (result string, isNull bool, err error) { 5474 var ( 5475 arg0, arg1Str string 5476 arg1 types.Duration 5477 ) 5478 arg0, isNull, err = b.args[0].EvalString(b.ctx, event) 5479 if isNull || err != nil { 5480 return "", isNull, err 5481 } 5482 arg1Type := b.args[1].GetType() 5483 if allegrosql.HasBinaryFlag(arg1Type.Flag) { 5484 return "", true, nil 5485 } 5486 arg1Str, isNull, err = b.args[1].EvalString(b.ctx, event) 5487 if isNull || err != nil { 5488 return "", isNull, err 5489 } 5490 sc := b.ctx.GetStochastikVars().StmtCtx 5491 arg1, err = types.ParseDuration(sc, arg1Str, getFsp4TimeAddSub(arg1Str)) 5492 if err != nil { 5493 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5494 sc.AppendWarning(err) 5495 return "", true, nil 5496 } 5497 return "", true, err 5498 } 5499 if isDuration(arg0) { 5500 result, err = strDurationAddDuration(sc, arg0, arg1) 5501 if err != nil { 5502 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5503 sc.AppendWarning(err) 5504 return "", true, nil 5505 } 5506 return "", true, err 5507 } 5508 return result, false, nil 5509 } 5510 result, err = strDatetimeAddDuration(sc, arg0, arg1) 5511 return result, err != nil, err 5512 } 5513 5514 type builtinAddDateAndDurationSig struct { 5515 baseBuiltinFunc 5516 } 5517 5518 func (b *builtinAddDateAndDurationSig) Clone() builtinFunc { 5519 newSig := &builtinAddDateAndDurationSig{} 5520 newSig.cloneFrom(&b.baseBuiltinFunc) 5521 return newSig 5522 } 5523 5524 // evalString evals a builtinAddDurationAndDurationSig. 5525 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5526 func (b *builtinAddDateAndDurationSig) evalString(event chunk.Event) (string, bool, error) { 5527 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 5528 if isNull || err != nil { 5529 return "", isNull, err 5530 } 5531 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 5532 if isNull || err != nil { 5533 return "", isNull, err 5534 } 5535 result, err := arg0.Add(arg1) 5536 return result.String(), err != nil, err 5537 } 5538 5539 type builtinAddDateAndStringSig struct { 5540 baseBuiltinFunc 5541 } 5542 5543 func (b *builtinAddDateAndStringSig) Clone() builtinFunc { 5544 newSig := &builtinAddDateAndStringSig{} 5545 newSig.cloneFrom(&b.baseBuiltinFunc) 5546 return newSig 5547 } 5548 5549 // evalString evals a builtinAddDateAndStringSig. 5550 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_addtime 5551 func (b *builtinAddDateAndStringSig) evalString(event chunk.Event) (string, bool, error) { 5552 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 5553 if isNull || err != nil { 5554 return "", isNull, err 5555 } 5556 s, isNull, err := b.args[1].EvalString(b.ctx, event) 5557 if isNull || err != nil { 5558 return "", isNull, err 5559 } 5560 if !isDuration(s) { 5561 return "", true, nil 5562 } 5563 sc := b.ctx.GetStochastikVars().StmtCtx 5564 arg1, err := types.ParseDuration(sc, s, getFsp4TimeAddSub(s)) 5565 if err != nil { 5566 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 5567 sc.AppendWarning(err) 5568 return "", true, nil 5569 } 5570 return "", true, err 5571 } 5572 result, err := arg0.Add(arg1) 5573 return result.String(), err != nil, err 5574 } 5575 5576 type convertTzFunctionClass struct { 5577 baseFunctionClass 5578 } 5579 5580 func (c *convertTzFunctionClass) getDecimal(ctx stochastikctx.Context, arg Expression) int { 5581 decimal := int(types.MaxFsp) 5582 if dt, isConstant := arg.(*Constant); isConstant { 5583 switch arg.GetType().EvalType() { 5584 case types.ETInt: 5585 decimal = 0 5586 case types.ETReal, types.ETDecimal: 5587 decimal = arg.GetType().Decimal 5588 case types.ETString: 5589 str, isNull, err := dt.EvalString(ctx, chunk.Event{}) 5590 if err == nil && !isNull { 5591 decimal = types.DateFSP(str) 5592 } 5593 } 5594 } 5595 if decimal > int(types.MaxFsp) { 5596 return int(types.MaxFsp) 5597 } 5598 if decimal < int(types.MinFsp) { 5599 return int(types.MinFsp) 5600 } 5601 return decimal 5602 } 5603 5604 func (c *convertTzFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 5605 if err := c.verifyArgs(args); err != nil { 5606 return nil, err 5607 } 5608 // tzRegex holds the regex to check whether a string is a time zone. 5609 tzRegex, err := regexp.Compile(`(^(\+|-)(0?[0-9]|1[0-2]):[0-5]?\d$)|(^\+13:00$)`) 5610 if err != nil { 5611 return nil, err 5612 } 5613 5614 decimal := c.getDecimal(ctx, args[0]) 5615 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETDatetime, types.ETString, types.ETString) 5616 if err != nil { 5617 return nil, err 5618 } 5619 bf.tp.Decimal = decimal 5620 sig := &builtinConvertTzSig{ 5621 baseBuiltinFunc: bf, 5622 timezoneRegex: tzRegex, 5623 } 5624 sig.setPbCode(fidelpb.ScalarFuncSig_ConvertTz) 5625 return sig, nil 5626 } 5627 5628 type builtinConvertTzSig struct { 5629 baseBuiltinFunc 5630 timezoneRegex *regexp.Regexp 5631 } 5632 5633 func (b *builtinConvertTzSig) Clone() builtinFunc { 5634 newSig := &builtinConvertTzSig{timezoneRegex: b.timezoneRegex} 5635 newSig.cloneFrom(&b.baseBuiltinFunc) 5636 return newSig 5637 } 5638 5639 // evalTime evals CONVERT_TZ(dt,from_tz,to_tz). 5640 // `CONVERT_TZ` function returns NULL if the arguments are invalid. 5641 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_convert-tz 5642 func (b *builtinConvertTzSig) evalTime(event chunk.Event) (types.Time, bool, error) { 5643 dt, isNull, err := b.args[0].EvalTime(b.ctx, event) 5644 if isNull || err != nil { 5645 return types.ZeroTime, true, nil 5646 } 5647 5648 fromTzStr, isNull, err := b.args[1].EvalString(b.ctx, event) 5649 if isNull || err != nil { 5650 return types.ZeroTime, true, nil 5651 } 5652 5653 toTzStr, isNull, err := b.args[2].EvalString(b.ctx, event) 5654 if isNull || err != nil { 5655 return types.ZeroTime, true, nil 5656 } 5657 5658 return b.convertTz(dt, fromTzStr, toTzStr) 5659 } 5660 5661 func (b *builtinConvertTzSig) convertTz(dt types.Time, fromTzStr, toTzStr string) (types.Time, bool, error) { 5662 if fromTzStr == "" || toTzStr == "" { 5663 return types.ZeroTime, true, nil 5664 } 5665 fromTzMatched := b.timezoneRegex.MatchString(fromTzStr) 5666 toTzMatched := b.timezoneRegex.MatchString(toTzStr) 5667 5668 if !fromTzMatched && !toTzMatched { 5669 fromTz, err := time.LoadLocation(fromTzStr) 5670 if err != nil { 5671 return types.ZeroTime, true, nil 5672 } 5673 5674 toTz, err := time.LoadLocation(toTzStr) 5675 if err != nil { 5676 return types.ZeroTime, true, nil 5677 } 5678 5679 t, err := dt.GoTime(fromTz) 5680 if err != nil { 5681 return types.ZeroTime, true, nil 5682 } 5683 5684 return types.NewTime(types.FromGoTime(t.In(toTz)), allegrosql.TypeDatetime, int8(b.tp.Decimal)), false, nil 5685 } 5686 if fromTzMatched && toTzMatched { 5687 t, err := dt.GoTime(time.Local) 5688 if err != nil { 5689 return types.ZeroTime, true, nil 5690 } 5691 5692 return types.NewTime(types.FromGoTime(t.Add(timeZone2Duration(toTzStr)-timeZone2Duration(fromTzStr))), allegrosql.TypeDatetime, int8(b.tp.Decimal)), false, nil 5693 } 5694 return types.ZeroTime, true, nil 5695 } 5696 5697 type makeDateFunctionClass struct { 5698 baseFunctionClass 5699 } 5700 5701 func (c *makeDateFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 5702 if err := c.verifyArgs(args); err != nil { 5703 return nil, err 5704 } 5705 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETInt, types.ETInt) 5706 if err != nil { 5707 return nil, err 5708 } 5709 tp := bf.tp 5710 tp.Tp, tp.Flen, tp.Decimal = allegrosql.TypeDate, allegrosql.MaxDateWidth, 0 5711 sig := &builtinMakeDateSig{bf} 5712 sig.setPbCode(fidelpb.ScalarFuncSig_MakeDate) 5713 return sig, nil 5714 } 5715 5716 type builtinMakeDateSig struct { 5717 baseBuiltinFunc 5718 } 5719 5720 func (b *builtinMakeDateSig) Clone() builtinFunc { 5721 newSig := &builtinMakeDateSig{} 5722 newSig.cloneFrom(&b.baseBuiltinFunc) 5723 return newSig 5724 } 5725 5726 // evalTime evaluates a builtinMakeDateSig. 5727 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_makedate 5728 func (b *builtinMakeDateSig) evalTime(event chunk.Event) (d types.Time, isNull bool, err error) { 5729 args := b.getArgs() 5730 var year, dayOfYear int64 5731 year, isNull, err = args[0].EvalInt(b.ctx, event) 5732 if isNull || err != nil { 5733 return d, true, err 5734 } 5735 dayOfYear, isNull, err = args[1].EvalInt(b.ctx, event) 5736 if isNull || err != nil { 5737 return d, true, err 5738 } 5739 if dayOfYear <= 0 || year < 0 || year > 9999 { 5740 return d, true, nil 5741 } 5742 if year < 70 { 5743 year += 2000 5744 } else if year < 100 { 5745 year += 1900 5746 } 5747 startTime := types.NewTime(types.FromDate(int(year), 1, 1, 0, 0, 0, 0), allegrosql.TypeDate, 0) 5748 retTimestamp := types.TimestamFIDeliff("DAY", types.ZeroDate, startTime) 5749 if retTimestamp == 0 { 5750 return d, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, startTime.String())) 5751 } 5752 ret := types.TimeFromDays(retTimestamp + dayOfYear - 1) 5753 if ret.IsZero() || ret.Year() > 9999 { 5754 return d, true, nil 5755 } 5756 return ret, false, nil 5757 } 5758 5759 type makeTimeFunctionClass struct { 5760 baseFunctionClass 5761 } 5762 5763 func (c *makeTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 5764 if err := c.verifyArgs(args); err != nil { 5765 return nil, err 5766 } 5767 tp, flen, decimal := args[2].GetType().EvalType(), 10, 0 5768 switch tp { 5769 case types.ETInt: 5770 case types.ETReal, types.ETDecimal: 5771 decimal = args[2].GetType().Decimal 5772 if decimal > 6 || decimal == types.UnspecifiedLength { 5773 decimal = 6 5774 } 5775 if decimal > 0 { 5776 flen += 1 + decimal 5777 } 5778 default: 5779 flen, decimal = 17, 6 5780 } 5781 // MyALLEGROSQL will cast the first and second arguments to INT, and the third argument to DECIMAL. 5782 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETInt, types.ETInt, types.ETReal) 5783 if err != nil { 5784 return nil, err 5785 } 5786 bf.tp.Flen, bf.tp.Decimal = flen, decimal 5787 sig := &builtinMakeTimeSig{bf} 5788 sig.setPbCode(fidelpb.ScalarFuncSig_MakeTime) 5789 return sig, nil 5790 } 5791 5792 type builtinMakeTimeSig struct { 5793 baseBuiltinFunc 5794 } 5795 5796 func (b *builtinMakeTimeSig) Clone() builtinFunc { 5797 newSig := &builtinMakeTimeSig{} 5798 newSig.cloneFrom(&b.baseBuiltinFunc) 5799 return newSig 5800 } 5801 5802 func (b *builtinMakeTimeSig) makeTime(hour int64, minute int64, second float64, hourUnsignedFlag bool) (types.Duration, error) { 5803 var overflow bool 5804 // MyALLEGROSQL TIME datatype: https://dev.allegrosql.com/doc/refman/5.7/en/time.html 5805 // ranges from '-838:59:59.000000' to '838:59:59.000000' 5806 if hour < 0 && hourUnsignedFlag { 5807 hour = 838 5808 overflow = true 5809 } 5810 if hour < -838 { 5811 hour = -838 5812 overflow = true 5813 } else if hour > 838 { 5814 hour = 838 5815 overflow = true 5816 } 5817 if hour == -838 || hour == 838 { 5818 if second > 59 { 5819 second = 59 5820 } 5821 } 5822 if overflow { 5823 minute = 59 5824 second = 59 5825 } 5826 fsp := b.tp.Decimal 5827 return types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, fmt.Sprintf("%02d:%02d:%v", hour, minute, second), int8(fsp)) 5828 } 5829 5830 // evalDuration evals a builtinMakeTimeIntSig. 5831 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_maketime 5832 func (b *builtinMakeTimeSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 5833 dur := types.ZeroDuration 5834 dur.Fsp = types.MaxFsp 5835 hour, isNull, err := b.args[0].EvalInt(b.ctx, event) 5836 if isNull || err != nil { 5837 return dur, isNull, err 5838 } 5839 minute, isNull, err := b.args[1].EvalInt(b.ctx, event) 5840 if isNull || err != nil { 5841 return dur, isNull, err 5842 } 5843 if minute < 0 || minute >= 60 { 5844 return dur, true, nil 5845 } 5846 second, isNull, err := b.args[2].EvalReal(b.ctx, event) 5847 if isNull || err != nil { 5848 return dur, isNull, err 5849 } 5850 if second < 0 || second >= 60 { 5851 return dur, true, nil 5852 } 5853 dur, err = b.makeTime(hour, minute, second, allegrosql.HasUnsignedFlag(b.args[0].GetType().Flag)) 5854 if err != nil { 5855 return dur, true, err 5856 } 5857 return dur, false, nil 5858 } 5859 5860 type periodAddFunctionClass struct { 5861 baseFunctionClass 5862 } 5863 5864 func (c *periodAddFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 5865 if err := c.verifyArgs(args); err != nil { 5866 return nil, err 5867 } 5868 5869 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt, types.ETInt) 5870 if err != nil { 5871 return nil, err 5872 } 5873 bf.tp.Flen = 6 5874 sig := &builtinPeriodAddSig{bf} 5875 return sig, nil 5876 } 5877 5878 // validPeriod checks if this period is valid, it comes from MyALLEGROSQL 8.0+. 5879 func validPeriod(p int64) bool { 5880 return !(p < 0 || p%100 == 0 || p%100 > 12) 5881 } 5882 5883 // period2Month converts a period to months, in which period is represented in the format of YYMM or YYYYMM. 5884 // Note that the period argument is not a date value. 5885 func period2Month(period uint64) uint64 { 5886 if period == 0 { 5887 return 0 5888 } 5889 5890 year, month := period/100, period%100 5891 if year < 70 { 5892 year += 2000 5893 } else if year < 100 { 5894 year += 1900 5895 } 5896 5897 return year*12 + month - 1 5898 } 5899 5900 // month2Period converts a month to a period. 5901 func month2Period(month uint64) uint64 { 5902 if month == 0 { 5903 return 0 5904 } 5905 5906 year := month / 12 5907 if year < 70 { 5908 year += 2000 5909 } else if year < 100 { 5910 year += 1900 5911 } 5912 5913 return year*100 + month%12 + 1 5914 } 5915 5916 type builtinPeriodAddSig struct { 5917 baseBuiltinFunc 5918 } 5919 5920 func (b *builtinPeriodAddSig) Clone() builtinFunc { 5921 newSig := &builtinPeriodAddSig{} 5922 newSig.cloneFrom(&b.baseBuiltinFunc) 5923 return newSig 5924 } 5925 5926 // evalInt evals PERIOD_ADD(P,N). 5927 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_period-add 5928 func (b *builtinPeriodAddSig) evalInt(event chunk.Event) (int64, bool, error) { 5929 p, isNull, err := b.args[0].EvalInt(b.ctx, event) 5930 if isNull || err != nil { 5931 return 0, true, err 5932 } 5933 5934 n, isNull, err := b.args[1].EvalInt(b.ctx, event) 5935 if isNull || err != nil { 5936 return 0, true, err 5937 } 5938 5939 // in MyALLEGROSQL, if p is invalid but n is NULL, the result is NULL, so we have to check if n is NULL first. 5940 if !validPeriod(p) { 5941 return 0, false, errIncorrectArgs.GenWithStackByArgs("period_add") 5942 } 5943 5944 sumMonth := int64(period2Month(uint64(p))) + n 5945 return int64(month2Period(uint64(sumMonth))), false, nil 5946 } 5947 5948 type periodDiffFunctionClass struct { 5949 baseFunctionClass 5950 } 5951 5952 func (c *periodDiffFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 5953 if err := c.verifyArgs(args); err != nil { 5954 return nil, err 5955 } 5956 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETInt, types.ETInt) 5957 if err != nil { 5958 return nil, err 5959 } 5960 bf.tp.Flen = 6 5961 sig := &builtinPeriodDiffSig{bf} 5962 return sig, nil 5963 } 5964 5965 type builtinPeriodDiffSig struct { 5966 baseBuiltinFunc 5967 } 5968 5969 func (b *builtinPeriodDiffSig) Clone() builtinFunc { 5970 newSig := &builtinPeriodDiffSig{} 5971 newSig.cloneFrom(&b.baseBuiltinFunc) 5972 return newSig 5973 } 5974 5975 // evalInt evals PERIOD_DIFF(P1,P2). 5976 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_period-diff 5977 func (b *builtinPeriodDiffSig) evalInt(event chunk.Event) (int64, bool, error) { 5978 p1, isNull, err := b.args[0].EvalInt(b.ctx, event) 5979 if isNull || err != nil { 5980 return 0, isNull, err 5981 } 5982 5983 p2, isNull, err := b.args[1].EvalInt(b.ctx, event) 5984 if isNull || err != nil { 5985 return 0, isNull, err 5986 } 5987 5988 if !validPeriod(p1) { 5989 return 0, false, errIncorrectArgs.GenWithStackByArgs("period_diff") 5990 } 5991 5992 if !validPeriod(p2) { 5993 return 0, false, errIncorrectArgs.GenWithStackByArgs("period_diff") 5994 } 5995 5996 return int64(period2Month(uint64(p1)) - period2Month(uint64(p2))), false, nil 5997 } 5998 5999 type quarterFunctionClass struct { 6000 baseFunctionClass 6001 } 6002 6003 func (c *quarterFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6004 if err := c.verifyArgs(args); err != nil { 6005 return nil, err 6006 } 6007 6008 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 6009 if err != nil { 6010 return nil, err 6011 } 6012 bf.tp.Flen = 1 6013 6014 sig := &builtinQuarterSig{bf} 6015 sig.setPbCode(fidelpb.ScalarFuncSig_Quarter) 6016 return sig, nil 6017 } 6018 6019 type builtinQuarterSig struct { 6020 baseBuiltinFunc 6021 } 6022 6023 func (b *builtinQuarterSig) Clone() builtinFunc { 6024 newSig := &builtinQuarterSig{} 6025 newSig.cloneFrom(&b.baseBuiltinFunc) 6026 return newSig 6027 } 6028 6029 // evalInt evals QUARTER(date). 6030 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_quarter 6031 func (b *builtinQuarterSig) evalInt(event chunk.Event) (int64, bool, error) { 6032 date, isNull, err := b.args[0].EvalTime(b.ctx, event) 6033 if isNull || err != nil { 6034 return 0, true, handleInvalidTimeError(b.ctx, err) 6035 } 6036 6037 if date.IsZero() { 6038 // MyALLEGROSQL compatibility, #11203 6039 // 0 | 0.0 should be converted to 0 value (not null) 6040 n, err := date.ToNumber().ToInt() 6041 isOriginalIntOrDecimalZero := err == nil && n == 0 6042 // Args like "0000-00-00", "0000-00-00 00:00:00" set Fsp to 6 6043 isOriginalStringZero := date.Fsp() > 0 6044 if isOriginalIntOrDecimalZero && !isOriginalStringZero { 6045 return 0, false, nil 6046 } 6047 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())) 6048 } 6049 6050 return int64((date.Month() + 2) / 3), false, nil 6051 } 6052 6053 type secToTimeFunctionClass struct { 6054 baseFunctionClass 6055 } 6056 6057 func (c *secToTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6058 if err := c.verifyArgs(args); err != nil { 6059 return nil, err 6060 } 6061 var retFlen, retFsp int 6062 argType := args[0].GetType() 6063 argEvalTp := argType.EvalType() 6064 if argEvalTp == types.ETString { 6065 retFsp = types.UnspecifiedLength 6066 } else { 6067 retFsp = argType.Decimal 6068 } 6069 if retFsp > int(types.MaxFsp) || retFsp == int(types.UnspecifiedFsp) { 6070 retFsp = int(types.MaxFsp) 6071 } else if retFsp < int(types.MinFsp) { 6072 retFsp = int(types.MinFsp) 6073 } 6074 retFlen = 10 6075 if retFsp > 0 { 6076 retFlen += 1 + retFsp 6077 } 6078 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, types.ETReal) 6079 if err != nil { 6080 return nil, err 6081 } 6082 bf.tp.Flen, bf.tp.Decimal = retFlen, retFsp 6083 sig := &builtinSecToTimeSig{bf} 6084 sig.setPbCode(fidelpb.ScalarFuncSig_SecToTime) 6085 return sig, nil 6086 } 6087 6088 type builtinSecToTimeSig struct { 6089 baseBuiltinFunc 6090 } 6091 6092 func (b *builtinSecToTimeSig) Clone() builtinFunc { 6093 newSig := &builtinSecToTimeSig{} 6094 newSig.cloneFrom(&b.baseBuiltinFunc) 6095 return newSig 6096 } 6097 6098 // evalDuration evals SEC_TO_TIME(seconds). 6099 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_sec-to-time 6100 func (b *builtinSecToTimeSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6101 secondsFloat, isNull, err := b.args[0].EvalReal(b.ctx, event) 6102 if isNull || err != nil { 6103 return types.Duration{}, isNull, err 6104 } 6105 var ( 6106 hour int64 6107 minute int64 6108 second int64 6109 demical float64 6110 secondDemical float64 6111 negative string 6112 ) 6113 6114 if secondsFloat < 0 { 6115 negative = "-" 6116 secondsFloat = math.Abs(secondsFloat) 6117 } 6118 seconds := int64(secondsFloat) 6119 demical = secondsFloat - float64(seconds) 6120 6121 hour = seconds / 3600 6122 if hour > 838 { 6123 hour = 838 6124 minute = 59 6125 second = 59 6126 } else { 6127 minute = seconds % 3600 / 60 6128 second = seconds % 60 6129 } 6130 secondDemical = float64(second) + demical 6131 6132 var dur types.Duration 6133 dur, err = types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), int8(b.tp.Decimal)) 6134 if err != nil { 6135 return types.Duration{}, err != nil, err 6136 } 6137 return dur, false, nil 6138 } 6139 6140 type subTimeFunctionClass struct { 6141 baseFunctionClass 6142 } 6143 6144 func (c *subTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (sig builtinFunc, err error) { 6145 if err = c.verifyArgs(args); err != nil { 6146 return nil, err 6147 } 6148 tp1, tp2, bf, err := getBf4TimeAddSub(ctx, c.funcName, args) 6149 if err != nil { 6150 return nil, err 6151 } 6152 switch tp1.Tp { 6153 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 6154 switch tp2.Tp { 6155 case allegrosql.TypeDuration: 6156 sig = &builtinSubDatetimeAndDurationSig{bf} 6157 sig.setPbCode(fidelpb.ScalarFuncSig_SubDatetimeAndDuration) 6158 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 6159 sig = &builtinSubTimeDateTimeNullSig{bf} 6160 sig.setPbCode(fidelpb.ScalarFuncSig_SubTimeDateTimeNull) 6161 default: 6162 sig = &builtinSubDatetimeAndStringSig{bf} 6163 sig.setPbCode(fidelpb.ScalarFuncSig_SubDatetimeAndString) 6164 } 6165 case allegrosql.TypeDate: 6166 bf.tp.Charset, bf.tp.DefCauslate = ctx.GetStochastikVars().GetCharsetInfo() 6167 switch tp2.Tp { 6168 case allegrosql.TypeDuration: 6169 sig = &builtinSubDateAndDurationSig{bf} 6170 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateAndDuration) 6171 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 6172 sig = &builtinSubTimeStringNullSig{bf} 6173 sig.setPbCode(fidelpb.ScalarFuncSig_SubTimeStringNull) 6174 default: 6175 sig = &builtinSubDateAndStringSig{bf} 6176 sig.setPbCode(fidelpb.ScalarFuncSig_SubDateAndString) 6177 } 6178 case allegrosql.TypeDuration: 6179 switch tp2.Tp { 6180 case allegrosql.TypeDuration: 6181 sig = &builtinSubDurationAndDurationSig{bf} 6182 sig.setPbCode(fidelpb.ScalarFuncSig_SubDurationAndDuration) 6183 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 6184 sig = &builtinSubTimeDurationNullSig{bf} 6185 sig.setPbCode(fidelpb.ScalarFuncSig_SubTimeDurationNull) 6186 default: 6187 sig = &builtinSubDurationAndStringSig{bf} 6188 sig.setPbCode(fidelpb.ScalarFuncSig_SubDurationAndString) 6189 } 6190 default: 6191 switch tp2.Tp { 6192 case allegrosql.TypeDuration: 6193 sig = &builtinSubStringAndDurationSig{bf} 6194 sig.setPbCode(fidelpb.ScalarFuncSig_SubStringAndDuration) 6195 case allegrosql.TypeDatetime, allegrosql.TypeTimestamp: 6196 sig = &builtinSubTimeStringNullSig{bf} 6197 sig.setPbCode(fidelpb.ScalarFuncSig_SubTimeStringNull) 6198 default: 6199 sig = &builtinSubStringAndStringSig{bf} 6200 sig.setPbCode(fidelpb.ScalarFuncSig_SubStringAndString) 6201 } 6202 } 6203 return sig, nil 6204 } 6205 6206 type builtinSubDatetimeAndDurationSig struct { 6207 baseBuiltinFunc 6208 } 6209 6210 func (b *builtinSubDatetimeAndDurationSig) Clone() builtinFunc { 6211 newSig := &builtinSubDatetimeAndDurationSig{} 6212 newSig.cloneFrom(&b.baseBuiltinFunc) 6213 return newSig 6214 } 6215 6216 // evalTime evals a builtinSubDatetimeAndDurationSig. 6217 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6218 func (b *builtinSubDatetimeAndDurationSig) evalTime(event chunk.Event) (types.Time, bool, error) { 6219 arg0, isNull, err := b.args[0].EvalTime(b.ctx, event) 6220 if isNull || err != nil { 6221 return types.ZeroDatetime, isNull, err 6222 } 6223 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 6224 if isNull || err != nil { 6225 return types.ZeroDatetime, isNull, err 6226 } 6227 sc := b.ctx.GetStochastikVars().StmtCtx 6228 arg1time, err := arg1.ConvertToTime(sc, allegrosql.TypeDatetime) 6229 if err != nil { 6230 return arg1time, true, err 6231 } 6232 tmFIDeluration := arg0.Sub(sc, &arg1time) 6233 result, err := tmFIDeluration.ConvertToTime(sc, arg0.Type()) 6234 return result, err != nil, err 6235 } 6236 6237 type builtinSubDatetimeAndStringSig struct { 6238 baseBuiltinFunc 6239 } 6240 6241 func (b *builtinSubDatetimeAndStringSig) Clone() builtinFunc { 6242 newSig := &builtinSubDatetimeAndStringSig{} 6243 newSig.cloneFrom(&b.baseBuiltinFunc) 6244 return newSig 6245 } 6246 6247 // evalTime evals a builtinSubDatetimeAndStringSig. 6248 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6249 func (b *builtinSubDatetimeAndStringSig) evalTime(event chunk.Event) (types.Time, bool, error) { 6250 arg0, isNull, err := b.args[0].EvalTime(b.ctx, event) 6251 if isNull || err != nil { 6252 return types.ZeroDatetime, isNull, err 6253 } 6254 s, isNull, err := b.args[1].EvalString(b.ctx, event) 6255 if isNull || err != nil { 6256 return types.ZeroDatetime, isNull, err 6257 } 6258 if err != nil { 6259 return types.ZeroDatetime, true, err 6260 } 6261 if !isDuration(s) { 6262 return types.ZeroDatetime, true, nil 6263 } 6264 sc := b.ctx.GetStochastikVars().StmtCtx 6265 arg1, err := types.ParseDuration(sc, s, types.GetFsp(s)) 6266 if err != nil { 6267 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6268 sc.AppendWarning(err) 6269 return types.ZeroDatetime, true, nil 6270 } 6271 return types.ZeroDatetime, true, err 6272 } 6273 arg1time, err := arg1.ConvertToTime(sc, allegrosql.TypeDatetime) 6274 if err != nil { 6275 return types.ZeroDatetime, true, err 6276 } 6277 tmFIDeluration := arg0.Sub(sc, &arg1time) 6278 result, err := tmFIDeluration.ConvertToTime(sc, allegrosql.TypeDatetime) 6279 return result, err != nil, err 6280 } 6281 6282 type builtinSubTimeDateTimeNullSig struct { 6283 baseBuiltinFunc 6284 } 6285 6286 func (b *builtinSubTimeDateTimeNullSig) Clone() builtinFunc { 6287 newSig := &builtinSubTimeDateTimeNullSig{} 6288 newSig.cloneFrom(&b.baseBuiltinFunc) 6289 return newSig 6290 } 6291 6292 // evalTime evals a builtinSubTimeDateTimeNullSig. 6293 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6294 func (b *builtinSubTimeDateTimeNullSig) evalTime(event chunk.Event) (types.Time, bool, error) { 6295 return types.ZeroDatetime, true, nil 6296 } 6297 6298 type builtinSubStringAndDurationSig struct { 6299 baseBuiltinFunc 6300 } 6301 6302 func (b *builtinSubStringAndDurationSig) Clone() builtinFunc { 6303 newSig := &builtinSubStringAndDurationSig{} 6304 newSig.cloneFrom(&b.baseBuiltinFunc) 6305 return newSig 6306 } 6307 6308 // evalString evals a builtinSubStringAndDurationSig. 6309 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6310 func (b *builtinSubStringAndDurationSig) evalString(event chunk.Event) (result string, isNull bool, err error) { 6311 var ( 6312 arg0 string 6313 arg1 types.Duration 6314 ) 6315 arg0, isNull, err = b.args[0].EvalString(b.ctx, event) 6316 if isNull || err != nil { 6317 return "", isNull, err 6318 } 6319 arg1, isNull, err = b.args[1].EvalDuration(b.ctx, event) 6320 if isNull || err != nil { 6321 return "", isNull, err 6322 } 6323 sc := b.ctx.GetStochastikVars().StmtCtx 6324 if isDuration(arg0) { 6325 result, err = strDurationSubDuration(sc, arg0, arg1) 6326 if err != nil { 6327 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6328 sc.AppendWarning(err) 6329 return "", true, nil 6330 } 6331 return "", true, err 6332 } 6333 return result, false, nil 6334 } 6335 result, err = strDatetimeSubDuration(sc, arg0, arg1) 6336 return result, err != nil, err 6337 } 6338 6339 type builtinSubStringAndStringSig struct { 6340 baseBuiltinFunc 6341 } 6342 6343 func (b *builtinSubStringAndStringSig) Clone() builtinFunc { 6344 newSig := &builtinSubStringAndStringSig{} 6345 newSig.cloneFrom(&b.baseBuiltinFunc) 6346 return newSig 6347 } 6348 6349 // evalString evals a builtinSubStringAndStringSig. 6350 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6351 func (b *builtinSubStringAndStringSig) evalString(event chunk.Event) (result string, isNull bool, err error) { 6352 var ( 6353 s, arg0 string 6354 arg1 types.Duration 6355 ) 6356 arg0, isNull, err = b.args[0].EvalString(b.ctx, event) 6357 if isNull || err != nil { 6358 return "", isNull, err 6359 } 6360 arg1Type := b.args[1].GetType() 6361 if allegrosql.HasBinaryFlag(arg1Type.Flag) { 6362 return "", true, nil 6363 } 6364 s, isNull, err = b.args[1].EvalString(b.ctx, event) 6365 if isNull || err != nil { 6366 return "", isNull, err 6367 } 6368 sc := b.ctx.GetStochastikVars().StmtCtx 6369 arg1, err = types.ParseDuration(sc, s, getFsp4TimeAddSub(s)) 6370 if err != nil { 6371 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6372 sc.AppendWarning(err) 6373 return "", true, nil 6374 } 6375 return "", true, err 6376 } 6377 if isDuration(arg0) { 6378 result, err = strDurationSubDuration(sc, arg0, arg1) 6379 if err != nil { 6380 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6381 sc.AppendWarning(err) 6382 return "", true, nil 6383 } 6384 return "", true, err 6385 } 6386 return result, false, nil 6387 } 6388 result, err = strDatetimeSubDuration(sc, arg0, arg1) 6389 return result, err != nil, err 6390 } 6391 6392 type builtinSubTimeStringNullSig struct { 6393 baseBuiltinFunc 6394 } 6395 6396 func (b *builtinSubTimeStringNullSig) Clone() builtinFunc { 6397 newSig := &builtinSubTimeStringNullSig{} 6398 newSig.cloneFrom(&b.baseBuiltinFunc) 6399 return newSig 6400 } 6401 6402 // evalString evals a builtinSubTimeStringNullSig. 6403 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6404 func (b *builtinSubTimeStringNullSig) evalString(event chunk.Event) (string, bool, error) { 6405 return "", true, nil 6406 } 6407 6408 type builtinSubDurationAndDurationSig struct { 6409 baseBuiltinFunc 6410 } 6411 6412 func (b *builtinSubDurationAndDurationSig) Clone() builtinFunc { 6413 newSig := &builtinSubDurationAndDurationSig{} 6414 newSig.cloneFrom(&b.baseBuiltinFunc) 6415 return newSig 6416 } 6417 6418 // evalDuration evals a builtinSubDurationAndDurationSig. 6419 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6420 func (b *builtinSubDurationAndDurationSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6421 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6422 if isNull || err != nil { 6423 return types.ZeroDuration, isNull, err 6424 } 6425 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 6426 if isNull || err != nil { 6427 return types.ZeroDuration, isNull, err 6428 } 6429 result, err := arg0.Sub(arg1) 6430 if err != nil { 6431 return types.ZeroDuration, true, err 6432 } 6433 return result, false, nil 6434 } 6435 6436 type builtinSubDurationAndStringSig struct { 6437 baseBuiltinFunc 6438 } 6439 6440 func (b *builtinSubDurationAndStringSig) Clone() builtinFunc { 6441 newSig := &builtinSubDurationAndStringSig{} 6442 newSig.cloneFrom(&b.baseBuiltinFunc) 6443 return newSig 6444 } 6445 6446 // evalDuration evals a builtinSubDurationAndStringSig. 6447 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6448 func (b *builtinSubDurationAndStringSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6449 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6450 if isNull || err != nil { 6451 return types.ZeroDuration, isNull, err 6452 } 6453 s, isNull, err := b.args[1].EvalString(b.ctx, event) 6454 if isNull || err != nil { 6455 return types.ZeroDuration, isNull, err 6456 } 6457 if !isDuration(s) { 6458 return types.ZeroDuration, true, nil 6459 } 6460 sc := b.ctx.GetStochastikVars().StmtCtx 6461 arg1, err := types.ParseDuration(sc, s, types.GetFsp(s)) 6462 if err != nil { 6463 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6464 sc.AppendWarning(err) 6465 return types.ZeroDuration, true, nil 6466 } 6467 return types.ZeroDuration, true, err 6468 } 6469 result, err := arg0.Sub(arg1) 6470 return result, err != nil, err 6471 } 6472 6473 type builtinSubTimeDurationNullSig struct { 6474 baseBuiltinFunc 6475 } 6476 6477 func (b *builtinSubTimeDurationNullSig) Clone() builtinFunc { 6478 newSig := &builtinSubTimeDurationNullSig{} 6479 newSig.cloneFrom(&b.baseBuiltinFunc) 6480 return newSig 6481 } 6482 6483 // evalDuration evals a builtinSubTimeDurationNullSig. 6484 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6485 func (b *builtinSubTimeDurationNullSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6486 return types.ZeroDuration, true, nil 6487 } 6488 6489 type builtinSubDateAndDurationSig struct { 6490 baseBuiltinFunc 6491 } 6492 6493 func (b *builtinSubDateAndDurationSig) Clone() builtinFunc { 6494 newSig := &builtinSubDateAndDurationSig{} 6495 newSig.cloneFrom(&b.baseBuiltinFunc) 6496 return newSig 6497 } 6498 6499 // evalString evals a builtinSubDateAndDurationSig. 6500 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6501 func (b *builtinSubDateAndDurationSig) evalString(event chunk.Event) (string, bool, error) { 6502 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6503 if isNull || err != nil { 6504 return "", isNull, err 6505 } 6506 arg1, isNull, err := b.args[1].EvalDuration(b.ctx, event) 6507 if isNull || err != nil { 6508 return "", isNull, err 6509 } 6510 result, err := arg0.Sub(arg1) 6511 return result.String(), err != nil, err 6512 } 6513 6514 type builtinSubDateAndStringSig struct { 6515 baseBuiltinFunc 6516 } 6517 6518 func (b *builtinSubDateAndStringSig) Clone() builtinFunc { 6519 newSig := &builtinSubDateAndStringSig{} 6520 newSig.cloneFrom(&b.baseBuiltinFunc) 6521 return newSig 6522 } 6523 6524 // evalString evals a builtinSubDateAndStringSig. 6525 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subtime 6526 func (b *builtinSubDateAndStringSig) evalString(event chunk.Event) (string, bool, error) { 6527 arg0, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6528 if isNull || err != nil { 6529 return "", isNull, err 6530 } 6531 s, isNull, err := b.args[1].EvalString(b.ctx, event) 6532 if isNull || err != nil { 6533 return "", isNull, err 6534 } 6535 if !isDuration(s) { 6536 return "", true, nil 6537 } 6538 sc := b.ctx.GetStochastikVars().StmtCtx 6539 arg1, err := types.ParseDuration(sc, s, getFsp4TimeAddSub(s)) 6540 if err != nil { 6541 if terror.ErrorEqual(err, types.ErrTruncatedWrongVal) { 6542 sc.AppendWarning(err) 6543 return "", true, nil 6544 } 6545 return "", true, err 6546 } 6547 result, err := arg0.Sub(arg1) 6548 if err != nil { 6549 return "", true, err 6550 } 6551 return result.String(), false, nil 6552 } 6553 6554 type timeFormatFunctionClass struct { 6555 baseFunctionClass 6556 } 6557 6558 func (c *timeFormatFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6559 if err := c.verifyArgs(args); err != nil { 6560 return nil, err 6561 } 6562 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETDuration, types.ETString) 6563 if err != nil { 6564 return nil, err 6565 } 6566 // worst case: formatMask=%r%r%r...%r, each %r takes 11 characters 6567 bf.tp.Flen = (args[1].GetType().Flen + 1) / 2 * 11 6568 sig := &builtinTimeFormatSig{bf} 6569 sig.setPbCode(fidelpb.ScalarFuncSig_TimeFormat) 6570 return sig, nil 6571 } 6572 6573 type builtinTimeFormatSig struct { 6574 baseBuiltinFunc 6575 } 6576 6577 func (b *builtinTimeFormatSig) Clone() builtinFunc { 6578 newSig := &builtinTimeFormatSig{} 6579 newSig.cloneFrom(&b.baseBuiltinFunc) 6580 return newSig 6581 } 6582 6583 // evalString evals a builtinTimeFormatSig. 6584 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time-format 6585 func (b *builtinTimeFormatSig) evalString(event chunk.Event) (string, bool, error) { 6586 dur, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6587 // if err != nil, then dur is ZeroDuration, outputs 00:00:00 in this case which follows the behavior of allegrosql. 6588 if err != nil { 6589 logutil.BgLogger().Warn("time_format.args[0].EvalDuration failed", zap.Error(err)) 6590 } 6591 if isNull { 6592 return "", isNull, err 6593 } 6594 formatMask, isNull, err := b.args[1].EvalString(b.ctx, event) 6595 if err != nil || isNull { 6596 return "", isNull, err 6597 } 6598 res, err := b.formatTime(b.ctx, dur, formatMask) 6599 return res, isNull, err 6600 } 6601 6602 // formatTime see https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time-format 6603 func (b *builtinTimeFormatSig) formatTime(ctx stochastikctx.Context, t types.Duration, formatMask string) (res string, err error) { 6604 return t.DurationFormat(formatMask) 6605 } 6606 6607 type timeToSecFunctionClass struct { 6608 baseFunctionClass 6609 } 6610 6611 func (c *timeToSecFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6612 if err := c.verifyArgs(args); err != nil { 6613 return nil, err 6614 } 6615 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDuration) 6616 if err != nil { 6617 return nil, err 6618 } 6619 bf.tp.Flen = 10 6620 sig := &builtinTimeToSecSig{bf} 6621 sig.setPbCode(fidelpb.ScalarFuncSig_TimeToSec) 6622 return sig, nil 6623 } 6624 6625 type builtinTimeToSecSig struct { 6626 baseBuiltinFunc 6627 } 6628 6629 func (b *builtinTimeToSecSig) Clone() builtinFunc { 6630 newSig := &builtinTimeToSecSig{} 6631 newSig.cloneFrom(&b.baseBuiltinFunc) 6632 return newSig 6633 } 6634 6635 // evalInt evals TIME_TO_SEC(time). 6636 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time-to-sec 6637 func (b *builtinTimeToSecSig) evalInt(event chunk.Event) (int64, bool, error) { 6638 duration, isNull, err := b.args[0].EvalDuration(b.ctx, event) 6639 if isNull || err != nil { 6640 return 0, isNull, err 6641 } 6642 var sign int 6643 if duration.Duration >= 0 { 6644 sign = 1 6645 } else { 6646 sign = -1 6647 } 6648 return int64(sign * (duration.Hour()*3600 + duration.Minute()*60 + duration.Second())), false, nil 6649 } 6650 6651 type timestampAddFunctionClass struct { 6652 baseFunctionClass 6653 } 6654 6655 func (c *timestampAddFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6656 if err := c.verifyArgs(args); err != nil { 6657 return nil, err 6658 } 6659 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString, types.ETString, types.ETInt, types.ETDatetime) 6660 if err != nil { 6661 return nil, err 6662 } 6663 bf.tp = &types.FieldType{Tp: allegrosql.TypeString, Flen: allegrosql.MaxDatetimeWidthNoFsp, Decimal: types.UnspecifiedLength} 6664 sig := &builtinTimestampAddSig{bf} 6665 sig.setPbCode(fidelpb.ScalarFuncSig_TimestampAdd) 6666 return sig, nil 6667 6668 } 6669 6670 type builtinTimestampAddSig struct { 6671 baseBuiltinFunc 6672 } 6673 6674 func (b *builtinTimestampAddSig) Clone() builtinFunc { 6675 newSig := &builtinTimestampAddSig{} 6676 newSig.cloneFrom(&b.baseBuiltinFunc) 6677 return newSig 6678 } 6679 6680 // evalString evals a builtinTimestampAddSig. 6681 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestampadd 6682 func (b *builtinTimestampAddSig) evalString(event chunk.Event) (string, bool, error) { 6683 unit, isNull, err := b.args[0].EvalString(b.ctx, event) 6684 if isNull || err != nil { 6685 return "", isNull, err 6686 } 6687 v, isNull, err := b.args[1].EvalInt(b.ctx, event) 6688 if isNull || err != nil { 6689 return "", isNull, err 6690 } 6691 arg, isNull, err := b.args[2].EvalTime(b.ctx, event) 6692 if isNull || err != nil { 6693 return "", isNull, err 6694 } 6695 tm1, err := arg.GoTime(time.Local) 6696 if err != nil { 6697 return "", isNull, err 6698 } 6699 var tb time.Time 6700 fsp := types.DefaultFsp 6701 switch unit { 6702 case "MICROSECOND": 6703 tb = tm1.Add(time.Duration(v) * time.Microsecond) 6704 fsp = types.MaxFsp 6705 case "SECOND": 6706 tb = tm1.Add(time.Duration(v) * time.Second) 6707 case "MINUTE": 6708 tb = tm1.Add(time.Duration(v) * time.Minute) 6709 case "HOUR": 6710 tb = tm1.Add(time.Duration(v) * time.Hour) 6711 case "DAY": 6712 tb = tm1.AddDate(0, 0, int(v)) 6713 case "WEEK": 6714 tb = tm1.AddDate(0, 0, 7*int(v)) 6715 case "MONTH": 6716 tb = tm1.AddDate(0, int(v), 0) 6717 case "QUARTER": 6718 tb = tm1.AddDate(0, 3*int(v), 0) 6719 case "YEAR": 6720 tb = tm1.AddDate(int(v), 0, 0) 6721 default: 6722 return "", true, types.ErrWrongValue.GenWithStackByArgs(types.TimeStr, unit) 6723 } 6724 r := types.NewTime(types.FromGoTime(tb), b.resolveType(arg.Type(), unit), fsp) 6725 if err = r.Check(b.ctx.GetStochastikVars().StmtCtx); err != nil { 6726 return "", true, handleInvalidTimeError(b.ctx, err) 6727 } 6728 return r.String(), false, nil 6729 } 6730 6731 func (b *builtinTimestampAddSig) resolveType(typ uint8, unit string) uint8 { 6732 // The approach below is from MyALLEGROSQL. 6733 // The field type for the result of an Item_date function is defined as 6734 // follows: 6735 // 6736 //- If first arg is a MYALLEGROSQL_TYPE_DATETIME result is MYALLEGROSQL_TYPE_DATETIME 6737 //- If first arg is a MYALLEGROSQL_TYPE_DATE and the interval type uses hours, 6738 // minutes, seconds or microsecond then type is MYALLEGROSQL_TYPE_DATETIME. 6739 //- Otherwise the result is MYALLEGROSQL_TYPE_STRING 6740 // (This is because you can't know if the string contains a DATE, MYALLEGROSQL_TIME 6741 // or DATETIME argument) 6742 if typ == allegrosql.TypeDate && (unit == "HOUR" || unit == "MINUTE" || unit == "SECOND" || unit == "MICROSECOND") { 6743 return allegrosql.TypeDatetime 6744 } 6745 return typ 6746 } 6747 6748 type toDaysFunctionClass struct { 6749 baseFunctionClass 6750 } 6751 6752 func (c *toDaysFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6753 if err := c.verifyArgs(args); err != nil { 6754 return nil, err 6755 } 6756 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 6757 if err != nil { 6758 return nil, err 6759 } 6760 sig := &builtinToDaysSig{bf} 6761 sig.setPbCode(fidelpb.ScalarFuncSig_ToDays) 6762 return sig, nil 6763 } 6764 6765 type builtinToDaysSig struct { 6766 baseBuiltinFunc 6767 } 6768 6769 func (b *builtinToDaysSig) Clone() builtinFunc { 6770 newSig := &builtinToDaysSig{} 6771 newSig.cloneFrom(&b.baseBuiltinFunc) 6772 return newSig 6773 } 6774 6775 // evalInt evals a builtinToDaysSig. 6776 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_to-days 6777 func (b *builtinToDaysSig) evalInt(event chunk.Event) (int64, bool, error) { 6778 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 6779 6780 if isNull || err != nil { 6781 return 0, true, handleInvalidTimeError(b.ctx, err) 6782 } 6783 ret := types.TimestamFIDeliff("DAY", types.ZeroDate, arg) 6784 if ret == 0 { 6785 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 6786 } 6787 return ret, false, nil 6788 } 6789 6790 type toSecondsFunctionClass struct { 6791 baseFunctionClass 6792 } 6793 6794 func (c *toSecondsFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6795 if err := c.verifyArgs(args); err != nil { 6796 return nil, err 6797 } 6798 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETDatetime) 6799 if err != nil { 6800 return nil, err 6801 } 6802 sig := &builtinToSecondsSig{bf} 6803 sig.setPbCode(fidelpb.ScalarFuncSig_ToSeconds) 6804 return sig, nil 6805 } 6806 6807 type builtinToSecondsSig struct { 6808 baseBuiltinFunc 6809 } 6810 6811 func (b *builtinToSecondsSig) Clone() builtinFunc { 6812 newSig := &builtinToSecondsSig{} 6813 newSig.cloneFrom(&b.baseBuiltinFunc) 6814 return newSig 6815 } 6816 6817 // evalInt evals a builtinToSecondsSig. 6818 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_to-seconds 6819 func (b *builtinToSecondsSig) evalInt(event chunk.Event) (int64, bool, error) { 6820 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 6821 if isNull || err != nil { 6822 return 0, true, handleInvalidTimeError(b.ctx, err) 6823 } 6824 ret := types.TimestamFIDeliff("SECOND", types.ZeroDate, arg) 6825 if ret == 0 { 6826 return 0, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 6827 } 6828 return ret, false, nil 6829 } 6830 6831 type utcTimeFunctionClass struct { 6832 baseFunctionClass 6833 } 6834 6835 func (c *utcTimeFunctionClass) getFlenAndDecimal4UTCTime(ctx stochastikctx.Context, args []Expression) (flen, decimal int) { 6836 if len(args) == 0 { 6837 flen, decimal = 8, 0 6838 return 6839 } 6840 if constant, ok := args[0].(*Constant); ok { 6841 fsp, isNull, err := constant.EvalInt(ctx, chunk.Event{}) 6842 if isNull || err != nil || fsp > int64(types.MaxFsp) { 6843 decimal = int(types.MaxFsp) 6844 } else if fsp < int64(types.MinFsp) { 6845 decimal = int(types.MinFsp) 6846 } else { 6847 decimal = int(fsp) 6848 } 6849 } 6850 if decimal > 0 { 6851 flen = 8 + 1 + decimal 6852 } else { 6853 flen = 8 6854 } 6855 return flen, decimal 6856 } 6857 6858 func (c *utcTimeFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6859 if err := c.verifyArgs(args); err != nil { 6860 return nil, err 6861 } 6862 argTps := make([]types.EvalType, 0, 1) 6863 if len(args) == 1 { 6864 argTps = append(argTps, types.ETInt) 6865 } 6866 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDuration, argTps...) 6867 if err != nil { 6868 return nil, err 6869 } 6870 bf.tp.Flen, bf.tp.Decimal = c.getFlenAndDecimal4UTCTime(bf.ctx, args) 6871 6872 var sig builtinFunc 6873 if len(args) == 1 { 6874 sig = &builtinUTCTimeWithArgSig{bf} 6875 sig.setPbCode(fidelpb.ScalarFuncSig_UTCTimeWithArg) 6876 } else { 6877 sig = &builtinUTCTimeWithoutArgSig{bf} 6878 sig.setPbCode(fidelpb.ScalarFuncSig_UTCTimeWithoutArg) 6879 } 6880 return sig, nil 6881 } 6882 6883 type builtinUTCTimeWithoutArgSig struct { 6884 baseBuiltinFunc 6885 } 6886 6887 func (b *builtinUTCTimeWithoutArgSig) Clone() builtinFunc { 6888 newSig := &builtinUTCTimeWithoutArgSig{} 6889 newSig.cloneFrom(&b.baseBuiltinFunc) 6890 return newSig 6891 } 6892 6893 // evalDuration evals a builtinUTCTimeWithoutArgSig. 6894 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-time 6895 func (b *builtinUTCTimeWithoutArgSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6896 nowTs, err := getStmtTimestamp(b.ctx) 6897 if err != nil { 6898 return types.Duration{}, true, err 6899 } 6900 v, err := types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, nowTs.UTC().Format(types.TimeFormat), 0) 6901 return v, false, err 6902 } 6903 6904 type builtinUTCTimeWithArgSig struct { 6905 baseBuiltinFunc 6906 } 6907 6908 func (b *builtinUTCTimeWithArgSig) Clone() builtinFunc { 6909 newSig := &builtinUTCTimeWithArgSig{} 6910 newSig.cloneFrom(&b.baseBuiltinFunc) 6911 return newSig 6912 } 6913 6914 // evalDuration evals a builtinUTCTimeWithArgSig. 6915 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-time 6916 func (b *builtinUTCTimeWithArgSig) evalDuration(event chunk.Event) (types.Duration, bool, error) { 6917 fsp, isNull, err := b.args[0].EvalInt(b.ctx, event) 6918 if isNull || err != nil { 6919 return types.Duration{}, isNull, err 6920 } 6921 if fsp > int64(types.MaxFsp) { 6922 return types.Duration{}, true, errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v.", fsp, types.MaxFsp) 6923 } 6924 if fsp < int64(types.MinFsp) { 6925 return types.Duration{}, true, errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp) 6926 } 6927 nowTs, err := getStmtTimestamp(b.ctx) 6928 if err != nil { 6929 return types.Duration{}, true, err 6930 } 6931 v, err := types.ParseDuration(b.ctx.GetStochastikVars().StmtCtx, nowTs.UTC().Format(types.TimeFSPFormat), int8(fsp)) 6932 return v, false, err 6933 } 6934 6935 type lastDayFunctionClass struct { 6936 baseFunctionClass 6937 } 6938 6939 func (c *lastDayFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6940 if err := c.verifyArgs(args); err != nil { 6941 return nil, err 6942 } 6943 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDatetime, types.ETDatetime) 6944 if err != nil { 6945 return nil, err 6946 } 6947 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeDate, allegrosql.MaxDateWidth, int(types.DefaultFsp) 6948 sig := &builtinLastDaySig{bf} 6949 sig.setPbCode(fidelpb.ScalarFuncSig_LastDay) 6950 return sig, nil 6951 } 6952 6953 type builtinLastDaySig struct { 6954 baseBuiltinFunc 6955 } 6956 6957 func (b *builtinLastDaySig) Clone() builtinFunc { 6958 newSig := &builtinLastDaySig{} 6959 newSig.cloneFrom(&b.baseBuiltinFunc) 6960 return newSig 6961 } 6962 6963 // evalTime evals a builtinLastDaySig. 6964 // See https://dev.allegrosql.com/doc/refman/5.7/en/date-and-time-functions.html#function_last-day 6965 func (b *builtinLastDaySig) evalTime(event chunk.Event) (types.Time, bool, error) { 6966 arg, isNull, err := b.args[0].EvalTime(b.ctx, event) 6967 if isNull || err != nil { 6968 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 6969 } 6970 tm := arg 6971 year, month := tm.Year(), tm.Month() 6972 if arg.InvalidZero() { 6973 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())) 6974 } 6975 lastDay := types.GetLastDay(year, month) 6976 ret := types.NewTime(types.FromDate(year, month, lastDay, 0, 0, 0, 0), allegrosql.TypeDate, types.DefaultFsp) 6977 return ret, false, nil 6978 } 6979 6980 // getExpressionFsp calculates the fsp from given memex. 6981 func getExpressionFsp(ctx stochastikctx.Context, memex Expression) (int, error) { 6982 constExp, isConstant := memex.(*Constant) 6983 if isConstant && types.IsString(memex.GetType().Tp) && !isTemporalDeferredCauset(memex) { 6984 str, isNil, err := constExp.EvalString(ctx, chunk.Event{}) 6985 if isNil || err != nil { 6986 return 0, err 6987 } 6988 return int(types.GetFsp(str)), nil 6989 } 6990 return mathutil.Min(memex.GetType().Decimal, int(types.MaxFsp)), nil 6991 } 6992 6993 // milevadbParseTsoFunctionClass extracts physical time from a tso 6994 type milevadbParseTsoFunctionClass struct { 6995 baseFunctionClass 6996 } 6997 6998 func (c *milevadbParseTsoFunctionClass) getFunction(ctx stochastikctx.Context, args []Expression) (builtinFunc, error) { 6999 if err := c.verifyArgs(args); err != nil { 7000 return nil, err 7001 } 7002 argTp := args[0].GetType().EvalType() 7003 bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, argTp, types.ETInt) 7004 if err != nil { 7005 return nil, err 7006 } 7007 7008 bf.tp.Tp, bf.tp.Flen, bf.tp.Decimal = allegrosql.TypeDate, allegrosql.MaxDateWidth, int(types.DefaultFsp) 7009 sig := &builtinMilevaDBParseTsoSig{bf} 7010 return sig, nil 7011 } 7012 7013 type builtinMilevaDBParseTsoSig struct { 7014 baseBuiltinFunc 7015 } 7016 7017 func (b *builtinMilevaDBParseTsoSig) Clone() builtinFunc { 7018 newSig := &builtinMilevaDBParseTsoSig{} 7019 newSig.cloneFrom(&b.baseBuiltinFunc) 7020 return newSig 7021 } 7022 7023 // evalTime evals a builtinMilevaDBParseTsoSig. 7024 func (b *builtinMilevaDBParseTsoSig) evalTime(event chunk.Event) (types.Time, bool, error) { 7025 arg, isNull, err := b.args[0].EvalInt(b.ctx, event) 7026 if isNull || err != nil || arg <= 0 { 7027 return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) 7028 } 7029 7030 t := oracle.GetTimeFromTS(uint64(arg)) 7031 result := types.NewTime(types.FromGoTime(t), allegrosql.TypeDatetime, types.MaxFsp) 7032 err = result.ConvertTimeZone(time.Local, b.ctx.GetStochastikVars().Location()) 7033 if err != nil { 7034 return types.ZeroTime, true, err 7035 } 7036 return result, false, nil 7037 }