You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2722 lines
65 KiB
2722 lines
65 KiB
// Copyright 2019 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package expression
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pingcap/errors"
|
|
"github.com/pingcap/parser/mysql"
|
|
"github.com/pingcap/parser/terror"
|
|
"github.com/pingcap/tidb/sessionctx/variable"
|
|
"github.com/pingcap/tidb/store/tikv/oracle"
|
|
"github.com/pingcap/tidb/types"
|
|
"github.com/pingcap/tidb/util/chunk"
|
|
)
|
|
|
|
func (b *builtinMonthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < input.NumRows(); i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].IsZero() {
|
|
if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = 0
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].Month())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMonthSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinYearSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < input.NumRows(); i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].IsZero() {
|
|
if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = 0
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].Year())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinYearSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDateSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, result); err != nil {
|
|
return err
|
|
}
|
|
times := result.Times()
|
|
for i := 0; i < len(times); i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if times[i].IsZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, times[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
} else {
|
|
times[i].SetCoreTime(types.FromDate(times[i].Year(), times[i].Month(), times[i].Day(), 0, 0, 0, 0))
|
|
times[i].SetType(mysql.TypeDate)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDateSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinFromUnixTime2ArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinFromUnixTime2ArgSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf1, err := b.bufAllocator.get(types.ETDecimal, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err = b.args[0].VecEvalDecimal(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf2, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf2)
|
|
if err = b.args[1].VecEvalString(b.ctx, input, buf2); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
ds := buf1.Decimals()
|
|
fsp := int8(b.tp.Decimal)
|
|
for i := 0; i < n; i++ {
|
|
if buf1.IsNull(i) || buf2.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
t, isNull, err := evalFromUnixTime(b.ctx, fsp, &ds[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
res, err := t.DateFormat(buf2.GetString(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.AppendString(res)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinSysDateWithoutFspSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinSysDateWithoutFspSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
loc := b.ctx.GetSessionVars().Location()
|
|
now := time.Now().In(loc)
|
|
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
t, err := convertTimeToMysqlTime(now, 0, types.ModeHalfEven)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
times[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinExtractDatetimeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinExtractDatetimeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf1, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err := b.args[1].VecEvalTime(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
i64s := result.Int64s()
|
|
ds := buf1.Times()
|
|
result.MergeNulls(buf, buf1)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
res, err := types.ExtractDatetimeNum(&ds[i], buf.GetString(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
i64s[i] = res
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDayNameSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDayNameSig) vecEvalIndex(input *chunk.Chunk, apply func(i, res int), applyNull func(i int)) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if buf.IsNull(i) {
|
|
applyNull(i)
|
|
continue
|
|
}
|
|
if ds[i].InvalidZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
applyNull(i)
|
|
continue
|
|
}
|
|
// Monday is 0, ... Sunday = 6 in MySQL
|
|
// but in go, Sunday is 0, ... Saturday is 6
|
|
// we will do a conversion.
|
|
res := (int(ds[i].Weekday()) + 6) % 7
|
|
apply(i, res)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// vecEvalString evals a builtinDayNameSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_dayname
|
|
func (b *builtinDayNameSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ReserveString(n)
|
|
|
|
return b.vecEvalIndex(input,
|
|
func(i, res int) {
|
|
result.AppendString(types.WeekdayNames[res])
|
|
},
|
|
func(i int) {
|
|
result.AppendNull()
|
|
},
|
|
)
|
|
}
|
|
|
|
func (b *builtinDayNameSig) vecEvalReal(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeFloat64(n, false)
|
|
f64s := result.Float64s()
|
|
|
|
return b.vecEvalIndex(input,
|
|
func(i, res int) {
|
|
f64s[i] = float64(res)
|
|
},
|
|
func(i int) {
|
|
result.SetNull(i, true)
|
|
},
|
|
)
|
|
}
|
|
|
|
func (b *builtinDayNameSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeInt64(n, false)
|
|
i64s := result.Int64s()
|
|
|
|
return b.vecEvalIndex(input,
|
|
func(i, res int) {
|
|
i64s[i] = int64(res)
|
|
},
|
|
func(i int) {
|
|
result.SetNull(i, true)
|
|
},
|
|
)
|
|
}
|
|
|
|
func (b *builtinWeekDaySig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinWeekDaySig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < input.NumRows(); i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].IsZero() {
|
|
if err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = int64((ds[i].Weekday() + 6) % 7)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimeFormatSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTimeFormatSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
// If err != nil, then dur is ZeroDuration, outputs 00:00:00
|
|
// in this case which follows the behavior of mysql.
|
|
// Use the non-vectorized method to handle this kind of error.
|
|
return vecEvalStringByRows(b, input, result)
|
|
}
|
|
|
|
buf1, err1 := b.bufAllocator.get(types.ETString, n)
|
|
if err1 != nil {
|
|
return err1
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
for i := 0; i < n; i++ {
|
|
if buf.IsNull(i) || buf1.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
res, err := b.formatTime(b.ctx, buf.GetDuration(i, 0), buf1.GetString(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.AppendString(res)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUTCTimeWithArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalDuration evals a builtinUTCTimeWithArgSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-time
|
|
func (b *builtinUTCTimeWithArgSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
utc := nowTs.UTC().Format(types.TimeFSPFormat)
|
|
stmtCtx := b.ctx.GetSessionVars().StmtCtx
|
|
result.ResizeGoDuration(n, false)
|
|
d64s := result.GoDurations()
|
|
i64s := buf.Int64s()
|
|
result.MergeNulls(buf)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
fsp := i64s[i]
|
|
if fsp > int64(types.MaxFsp) {
|
|
return errors.Errorf("Too-big precision %v specified for 'utc_time'. Maximum is %v.", fsp, types.MaxFsp)
|
|
}
|
|
if fsp < int64(types.MinFsp) {
|
|
return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp)
|
|
}
|
|
res, err := types.ParseDuration(stmtCtx, utc, int8(fsp))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d64s[i] = res.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUnixTimestampCurrentSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinUnixTimestampCurrentSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
dec, err := goTimeToMysqlUnixTimestamp(nowTs, 1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
intVal, err := dec.ToInt()
|
|
if !terror.ErrorEqual(err, types.ErrTruncated) {
|
|
terror.Log(err)
|
|
}
|
|
n := input.NumRows()
|
|
result.ResizeInt64(n, false)
|
|
intRes := result.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
intRes[i] = intVal
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinYearWeekWithoutModeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals YEARWEEK(date).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_yearweek
|
|
func (b *builtinYearWeekWithoutModeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
date := ds[i]
|
|
if date.InvalidZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
year, week := date.YearWeek(0)
|
|
i64s[i] = int64(week + year*100)
|
|
if i64s[i] < 0 {
|
|
i64s[i] = int64(math.MaxUint32)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinPeriodDiffSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals PERIOD_DIFF(P1,P2).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_period-diff
|
|
func (b *builtinPeriodDiffSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, result); err != nil {
|
|
return err
|
|
}
|
|
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
i64s := result.Int64s()
|
|
periods := buf.Int64s()
|
|
result.MergeNulls(buf)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if !validPeriod(i64s[i]) || !validPeriod(periods[i]) {
|
|
return errIncorrectArgs.GenWithStackByArgs("period_diff")
|
|
}
|
|
i64s[i] = int64(period2Month(uint64(i64s[i])) - period2Month(uint64(periods[i])))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinNowWithArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinNowWithArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
bufFsp, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(bufFsp)
|
|
if err = b.args[0].VecEvalInt(b.ctx, input, bufFsp); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
fsps := bufFsp.Int64s()
|
|
|
|
for i := 0; i < n; i++ {
|
|
fsp := int8(0)
|
|
if !bufFsp.IsNull(i) {
|
|
if fsps[i] > int64(types.MaxFsp) {
|
|
return errors.Errorf("Too-big precision %v specified for 'now'. Maximum is %v.", fsps[i], types.MaxFsp)
|
|
}
|
|
if fsps[i] < int64(types.MinFsp) {
|
|
return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsps[i])
|
|
}
|
|
fsp = int8(fsps[i])
|
|
}
|
|
|
|
t, isNull, err := evalNowWithFsp(b.ctx, fsp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
|
|
times[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinGetFormatSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalString evals a builtinGetFormatSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_get-format
|
|
func (b *builtinGetFormatSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf0, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf0)
|
|
if err = b.args[0].VecEvalString(b.ctx, input, buf0); err != nil {
|
|
return err
|
|
}
|
|
buf1, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err = b.args[1].VecEvalString(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
for i := 0; i < n; i++ {
|
|
if buf0.IsNull(i) || buf1.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
format := buf0.GetString(i)
|
|
location := buf1.GetString(i)
|
|
res := b.getFormat(format, location)
|
|
result.AppendString(res)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinGetFormatSig) getFormat(format, location string) string {
|
|
res := ""
|
|
switch format {
|
|
case dateFormat:
|
|
switch location {
|
|
case usaLocation:
|
|
res = "%m.%d.%Y"
|
|
case jisLocation:
|
|
res = "%Y-%m-%d"
|
|
case isoLocation:
|
|
res = "%Y-%m-%d"
|
|
case eurLocation:
|
|
res = "%d.%m.%Y"
|
|
case internalLocation:
|
|
res = "%Y%m%d"
|
|
}
|
|
case datetimeFormat, timestampFormat:
|
|
switch location {
|
|
case usaLocation:
|
|
res = "%Y-%m-%d %H.%i.%s"
|
|
case jisLocation:
|
|
res = "%Y-%m-%d %H:%i:%s"
|
|
case isoLocation:
|
|
res = "%Y-%m-%d %H:%i:%s"
|
|
case eurLocation:
|
|
res = "%Y-%m-%d %H.%i.%s"
|
|
case internalLocation:
|
|
res = "%Y%m%d%H%i%s"
|
|
}
|
|
case timeFormat:
|
|
switch location {
|
|
case usaLocation:
|
|
res = "%h:%i:%s %p"
|
|
case jisLocation:
|
|
res = "%H:%i:%s"
|
|
case isoLocation:
|
|
res = "%H:%i:%s"
|
|
case eurLocation:
|
|
res = "%H.%i.%s"
|
|
case internalLocation:
|
|
res = "%H%i%s"
|
|
}
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (b *builtinLastDaySig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinLastDaySig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, result); err != nil {
|
|
return err
|
|
}
|
|
times := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if times[i].InvalidZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, times[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
tm := times[i]
|
|
year, month := tm.Year(), tm.Month()
|
|
lastDay := types.GetLastDay(year, month)
|
|
times[i] = types.NewTime(types.FromDate(year, month, lastDay, 0, 0, 0, 0), mysql.TypeDate, types.DefaultFsp)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinStrToDateDateSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinStrToDateDateSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
bufStrings, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(bufStrings)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, bufStrings); err != nil {
|
|
return err
|
|
}
|
|
|
|
bufFormats, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(bufFormats)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, bufFormats); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(bufStrings, bufFormats)
|
|
times := result.Times()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
var t types.Time
|
|
succ := t.StrToDate(sc, bufStrings.GetString(i), bufFormats.GetString(i))
|
|
if !succ {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
t.SetType(mysql.TypeDate)
|
|
t.SetFsp(types.MinFsp)
|
|
times[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinSysDateWithFspSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinSysDateWithFspSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
loc := b.ctx.GetSessionVars().Location()
|
|
now := time.Now().In(loc)
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf)
|
|
times := result.Times()
|
|
ds := buf.Int64s()
|
|
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
t, err := convertTimeToMysqlTime(now, int8(ds[i]), types.ModeHalfEven)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
times[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTidbParseTsoSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTidbParseTsoSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
args := buf.Int64s()
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf)
|
|
times := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if args[i] <= 0 {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
t := oracle.GetTimeFromTS(uint64(args[i]))
|
|
r := types.NewTime(types.FromGoTime(t), mysql.TypeDatetime, types.MaxFsp)
|
|
if err := r.ConvertTimeZone(time.Local, b.ctx.GetSessionVars().Location()); err != nil {
|
|
return err
|
|
}
|
|
times[i] = r
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinFromDaysSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinFromDaysSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf)
|
|
ts := result.Times()
|
|
i64s := buf.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
ts[i] = types.TimeFromDays(i64s[i])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMicroSecondSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinMicroSecondSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
return vecEvalIntByRows(b, input, result)
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
i64s[i] = int64((ds[i] % time.Second) / time.Microsecond)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinQuarterSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals QUARTER(date).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_quarter
|
|
func (b *builtinQuarterSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
date := ds[i]
|
|
if date.IsZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = int64((date.Month() + 2) / 3)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinWeekWithModeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinWeekWithModeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf1, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
|
|
buf2, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf2); err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf2)
|
|
|
|
result.ResizeInt64(n, false)
|
|
i64s := result.Int64s()
|
|
ds := buf1.Times()
|
|
ms := buf2.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if buf1.IsNull(i) {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
date := ds[i]
|
|
if date.IsZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
if buf2.IsNull(i) {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
mode := int(ms[i])
|
|
week := date.Week(int(mode))
|
|
i64s[i] = int64(week)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinExtractDurationSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinExtractDurationSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
unit, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(unit)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, unit); err != nil {
|
|
return err
|
|
}
|
|
dur, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(dur)
|
|
if err = b.args[1].VecEvalDuration(b.ctx, input, dur); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(unit, dur)
|
|
i64s := result.Int64s()
|
|
durIs := dur.GoDurations()
|
|
var duration types.Duration
|
|
duration.Fsp = int8(b.args[1].GetType().Decimal)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
unitI := unit.GetString(i)
|
|
duration.Duration = durIs[i]
|
|
i64s[i], err = types.ExtractDurationNum(&duration, unitI)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinStrToDateDurationSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinStrToDateDurationSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
bufStrings, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(bufStrings)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, bufStrings); err != nil {
|
|
return err
|
|
}
|
|
|
|
bufFormats, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(bufFormats)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, bufFormats); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeGoDuration(n, false)
|
|
result.MergeNulls(bufStrings, bufFormats)
|
|
d64s := result.GoDurations()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
hasNoZeroDateMode := b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
var t types.Time
|
|
succ := t.StrToDate(sc, bufStrings.GetString(i), bufFormats.GetString(i))
|
|
if !succ {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
if hasNoZeroDateMode && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
t.SetFsp(int8(b.tp.Decimal))
|
|
dur, err := t.ConvertToDuration()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d64s[i] = dur.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinToSecondsSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals a builtinToSecondsSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_to-seconds
|
|
func (b *builtinToSecondsSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
arg := ds[i]
|
|
ret := types.TimestampDiff("SECOND", types.ZeroDate, arg)
|
|
if ret == 0 {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = ret
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMinuteSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinMinuteSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
return vecEvalIntByRows(b, input, result)
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
i64s[i] = int64(buf.GetDuration(i, int(types.UnspecifiedFsp)).Minute())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinSecondSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinSecondSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
return vecEvalIntByRows(b, input, result)
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
i64s[i] = int64(buf.GetDuration(i, int(types.UnspecifiedFsp)).Second())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinNowWithoutArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinNowWithoutArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
nowTs, isNull, err := evalNowWithFsp(b.ctx, int8(0))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.ResizeTime(n, true)
|
|
return nil
|
|
}
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
times[i] = nowTs
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestampLiteralSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTimestampLiteralSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
for i := range times {
|
|
times[i] = b.tm
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMakeDateSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinMakeDateSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf1, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf2, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf2)
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf2); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf1, buf2)
|
|
|
|
times := result.Times()
|
|
years := buf1.Int64s()
|
|
days := buf2.Int64s()
|
|
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if days[i] <= 0 || years[i] < 0 || years[i] > 9999 {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
if years[i] < 70 {
|
|
years[i] += 2000
|
|
} else if years[i] < 100 {
|
|
years[i] += 1900
|
|
}
|
|
startTime := types.NewTime(types.FromDate(int(years[i]), 1, 1, 0, 0, 0, 0), mysql.TypeDate, 0)
|
|
retTimestamp := types.TimestampDiff("DAY", types.ZeroDate, startTime)
|
|
if retTimestamp == 0 {
|
|
if err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, startTime.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
ret := types.TimeFromDays(retTimestamp + days[i] - 1)
|
|
if ret.IsZero() || ret.Year() > 9999 {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
times[i] = ret
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinWeekOfYearSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinWeekOfYearSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].IsZero() {
|
|
if err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
week := ds[i].Week(3)
|
|
i64s[i] = int64(week)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUTCTimestampWithArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalTime evals UTC_TIMESTAMP(fsp).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-timestamp
|
|
func (b *builtinUTCTimestampWithArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeTime(n, false)
|
|
t64s := result.Times()
|
|
i64s := buf.Int64s()
|
|
result.MergeNulls(buf)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
fsp := i64s[i]
|
|
if fsp > int64(types.MaxFsp) {
|
|
return errors.Errorf("Too-big precision %v specified for 'utc_timestamp'. Maximum is %v.", fsp, types.MaxFsp)
|
|
}
|
|
if fsp < int64(types.MinFsp) {
|
|
return errors.Errorf("Invalid negative %d specified, must in [0, 6].", fsp)
|
|
}
|
|
res, isNull, err := evalUTCTimestampWithFsp(b.ctx, int8(fsp))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
t64s[i] = res
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimeToSecSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals TIME_TO_SEC(time).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time-to-sec
|
|
func (b *builtinTimeToSecSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
fsp := b.args[0].GetType().Decimal
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
var sign int
|
|
duration := buf.GetDuration(i, int(fsp))
|
|
if duration.Duration >= 0 {
|
|
sign = 1
|
|
} else {
|
|
sign = -1
|
|
}
|
|
i64s[i] = int64(sign * (duration.Hour()*3600 + duration.Minute()*60 + duration.Second()))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinStrToDateDatetimeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinStrToDateDatetimeSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
dateBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(dateBuf)
|
|
if err = b.args[0].VecEvalString(b.ctx, input, dateBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
formatBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(formatBuf)
|
|
if err = b.args[1].VecEvalString(b.ctx, input, formatBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(dateBuf, formatBuf)
|
|
times := result.Times()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
hasNoZeroDateMode := b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode()
|
|
fsp := int8(b.tp.Decimal)
|
|
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
var t types.Time
|
|
succ := t.StrToDate(sc, dateBuf.GetString(i), formatBuf.GetString(i))
|
|
if !succ {
|
|
if err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
if hasNoZeroDateMode && (t.Year() == 0 || t.Month() == 0 || t.Day() == 0) {
|
|
if err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
t.SetType(mysql.TypeDatetime)
|
|
t.SetFsp(fsp)
|
|
times[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUTCDateSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinUTCDateSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
year, month, day := nowTs.UTC().Date()
|
|
utcDate := types.NewTime(types.FromGoTime(time.Date(year, month, day, 0, 0, 0, 0, time.UTC)), mysql.TypeDate, types.UnspecifiedFsp)
|
|
|
|
n := input.NumRows()
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
times[i] = utcDate
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinWeekWithoutModeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinWeekWithoutModeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
|
|
mode := 0
|
|
modeStr, ok := b.ctx.GetSessionVars().GetSystemVar(variable.DefaultWeekFormat)
|
|
if ok && modeStr != "" {
|
|
mode, err = strconv.Atoi(modeStr)
|
|
if err != nil {
|
|
return handleInvalidTimeError(b.ctx, types.ErrInvalidWeekModeFormat.GenWithStackByArgs(modeStr))
|
|
}
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
date := ds[i]
|
|
if date.IsZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
|
|
week := date.Week(mode)
|
|
i64s[i] = int64(week)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUnixTimestampDecSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinUnixTimestampDecSig) vecEvalDecimal(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeDecimal(n, false)
|
|
ts := result.Decimals()
|
|
timeBuf, err := b.bufAllocator.get(types.ETTimestamp, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(timeBuf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, timeBuf); err != nil {
|
|
for i := 0; i < n; i++ {
|
|
temp, isNull, err := b.evalDecimal(input.GetRow(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ts[i] = *temp
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
}
|
|
}
|
|
} else {
|
|
result.MergeNulls(timeBuf)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
t, err := timeBuf.GetTime(i).GoTime(getTimeZone(b.ctx))
|
|
if err != nil {
|
|
ts[i] = *new(types.MyDecimal)
|
|
continue
|
|
}
|
|
tmp, err := goTimeToMysqlUnixTimestamp(t, b.tp.Decimal)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ts[i] = *tmp
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinPeriodAddSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals PERIOD_ADD(P,N).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_period-add
|
|
func (b *builtinPeriodAddSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, result); err != nil {
|
|
return err
|
|
}
|
|
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
i64s := result.Int64s()
|
|
result.MergeNulls(buf)
|
|
ns := buf.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
|
|
// in MySQL, if p is invalid but n is NULL, the result is NULL, so we have to check if n is NULL first.
|
|
if !validPeriod(i64s[i]) {
|
|
return errIncorrectArgs.GenWithStackByArgs("period_add")
|
|
}
|
|
sumMonth := int64(period2Month(uint64(i64s[i]))) + ns[i]
|
|
i64s[i] = int64(month2Period(uint64(sumMonth)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestampAddSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalString evals a builtinTimestampAddSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestampadd
|
|
func (b *builtinTimestampAddSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf1, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf2, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf2)
|
|
if err := b.args[2].VecEvalTime(b.ctx, input, buf2); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
nums := buf1.Int64s()
|
|
ds := buf2.Times()
|
|
for i := 0; i < n; i++ {
|
|
if buf.IsNull(i) || buf1.IsNull(i) || buf2.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
|
|
unit := buf.GetString(i)
|
|
v := nums[i]
|
|
arg := ds[i]
|
|
|
|
tm1, err := arg.GoTime(time.Local)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var tb time.Time
|
|
fsp := types.DefaultFsp
|
|
switch unit {
|
|
case "MICROSECOND":
|
|
tb = tm1.Add(time.Duration(v) * time.Microsecond)
|
|
fsp = types.MaxFsp
|
|
case "SECOND":
|
|
tb = tm1.Add(time.Duration(v) * time.Second)
|
|
case "MINUTE":
|
|
tb = tm1.Add(time.Duration(v) * time.Minute)
|
|
case "HOUR":
|
|
tb = tm1.Add(time.Duration(v) * time.Hour)
|
|
case "DAY":
|
|
tb = tm1.AddDate(0, 0, int(v))
|
|
case "WEEK":
|
|
tb = tm1.AddDate(0, 0, 7*int(v))
|
|
case "MONTH":
|
|
tb = tm1.AddDate(0, int(v), 0)
|
|
case "QUARTER":
|
|
tb = tm1.AddDate(0, 3*int(v), 0)
|
|
case "YEAR":
|
|
tb = tm1.AddDate(int(v), 0, 0)
|
|
default:
|
|
return types.ErrWrongValue.GenWithStackByArgs(types.TimeStr, unit)
|
|
}
|
|
r := types.NewTime(types.FromGoTime(tb), b.resolveType(arg.Type(), unit), fsp)
|
|
if err = r.Check(b.ctx.GetSessionVars().StmtCtx); err != nil {
|
|
if err = handleInvalidTimeError(b.ctx, err); err != nil {
|
|
return err
|
|
}
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
result.AppendString(r.String())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinToDaysSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals a builtinToDaysSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_to-days
|
|
func (b *builtinToDaysSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
arg := ds[i]
|
|
ret := types.TimestampDiff("DAY", types.ZeroDate, arg)
|
|
if ret == 0 {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, arg.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = ret
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDateFormatSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDateFormatSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
|
|
dateBuf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(dateBuf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, dateBuf); err != nil {
|
|
return err
|
|
}
|
|
times := dateBuf.Times()
|
|
|
|
formatBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(formatBuf)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, formatBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
|
|
for i := range times {
|
|
t := times[i]
|
|
if dateBuf.IsNull(i) || formatBuf.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
|
|
formatMask := formatBuf.GetString(i)
|
|
// MySQL compatibility, #11203
|
|
// If format mask is 0 then return 0 without warnings
|
|
if formatMask == "0" {
|
|
result.AppendString("0")
|
|
continue
|
|
}
|
|
|
|
if t.InvalidZero() {
|
|
// MySQL compatibility, #11203
|
|
// 0 | 0.0 should be converted to null without warnings
|
|
n, err := t.ToNumber().ToInt()
|
|
isOriginalIntOrDecimalZero := err == nil && n == 0
|
|
// Args like "0000-00-00", "0000-00-00 00:00:00" set Fsp to 6
|
|
isOriginalStringZero := t.Fsp() > 0
|
|
|
|
result.AppendNull()
|
|
if isOriginalIntOrDecimalZero && !isOriginalStringZero {
|
|
continue
|
|
}
|
|
if errHandled := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, t.String())); errHandled != nil {
|
|
return errHandled
|
|
}
|
|
continue
|
|
}
|
|
res, err := t.DateFormat(formatMask)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.AppendString(res)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinHourSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinHourSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDuration, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDuration(b.ctx, input, buf); err != nil {
|
|
return vecEvalIntByRows(b, input, result)
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].Hours())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinSecToTimeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinSecToTimeSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETReal, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalReal(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
args := buf.Float64s()
|
|
result.ResizeGoDuration(n, false)
|
|
result.MergeNulls(buf)
|
|
durations := result.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
secondsFloat := args[i]
|
|
negative := ""
|
|
if secondsFloat < 0 {
|
|
negative = "-"
|
|
secondsFloat = math.Abs(secondsFloat)
|
|
}
|
|
seconds := int64(secondsFloat)
|
|
demical := secondsFloat - float64(seconds)
|
|
var minute, second int64
|
|
hour := seconds / 3600
|
|
if hour > 838 {
|
|
hour = 838
|
|
minute = 59
|
|
second = 59
|
|
} else {
|
|
minute = seconds % 3600 / 60
|
|
second = seconds % 60
|
|
}
|
|
secondDemical := float64(second) + demical
|
|
duration, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, fmt.Sprintf("%s%02d:%02d:%s", negative, hour, minute, strconv.FormatFloat(secondDemical, 'f', -1, 64)), int8(b.tp.Decimal))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
durations[i] = duration.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUTCTimeWithoutArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalDuration evals a builtinUTCTimeWithoutArgSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-time
|
|
func (b *builtinUTCTimeWithoutArgSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
res, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, nowTs.UTC().Format(types.TimeFormat), types.DefaultFsp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.ResizeGoDuration(n, false)
|
|
d64s := result.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
d64s[i] = res.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDateDiffSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDateDiffSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf0, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf0)
|
|
if err = b.args[0].VecEvalTime(b.ctx, input, buf0); err != nil {
|
|
return err
|
|
}
|
|
buf1, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err = b.args[1].VecEvalTime(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf0, buf1)
|
|
args0 := buf0.Times()
|
|
args1 := buf1.Times()
|
|
i64s := result.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if invalidArg0, invalidArg1 := args0[i].InvalidZero(), args1[i].InvalidZero(); invalidArg0 || invalidArg1 {
|
|
if invalidArg0 {
|
|
err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, args0[i].String()))
|
|
}
|
|
if invalidArg1 {
|
|
err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, args1[i].String()))
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = int64(types.DateDiff(args0[i].CoreTime(), args1[i].CoreTime()))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinCurrentDateSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinCurrentDateSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tz := b.ctx.GetSessionVars().Location()
|
|
year, month, day := nowTs.In(tz).Date()
|
|
timeValue := types.NewTime(types.FromDate(year, int(month), day, 0, 0, 0, 0), mysql.TypeDate, 0)
|
|
|
|
n := input.NumRows()
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
times[i] = timeValue
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMakeTimeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinMakeTimeSig) getVecIntParam(arg Expression, input *chunk.Chunk, col *chunk.Column) (err error) {
|
|
if arg.GetType().EvalType() == types.ETReal {
|
|
err = arg.VecEvalReal(b.ctx, input, col)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
f64s := col.Float64s()
|
|
i64s := col.Int64s()
|
|
n := input.NumRows()
|
|
for i := 0; i < n; i++ {
|
|
i64s[i] = int64(f64s[i])
|
|
}
|
|
return nil
|
|
}
|
|
err = arg.VecEvalInt(b.ctx, input, col)
|
|
return err
|
|
}
|
|
|
|
func (b *builtinMakeTimeSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeInt64(n, false)
|
|
hoursBuf := result
|
|
var err error
|
|
if err = b.getVecIntParam(b.args[0], input, hoursBuf); err != nil {
|
|
return err
|
|
}
|
|
minutesBuf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(minutesBuf)
|
|
if err = b.getVecIntParam(b.args[1], input, minutesBuf); err != nil {
|
|
return err
|
|
}
|
|
secondsBuf, err := b.bufAllocator.get(types.ETReal, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(secondsBuf)
|
|
if err = b.args[2].VecEvalReal(b.ctx, input, secondsBuf); err != nil {
|
|
return err
|
|
}
|
|
hours := hoursBuf.Int64s()
|
|
minutes := minutesBuf.Int64s()
|
|
seconds := secondsBuf.Float64s()
|
|
durs := result.GoDurations()
|
|
result.MergeNulls(minutesBuf, secondsBuf)
|
|
hourUnsignedFlag := mysql.HasUnsignedFlag(b.args[0].GetType().Flag)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if minutes[i] < 0 || minutes[i] >= 60 || seconds[i] < 0 || seconds[i] >= 60 {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
dur, err := b.makeTime(hours[i], minutes[i], seconds[i], hourUnsignedFlag)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
durs[i] = dur.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDayOfYearSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDayOfYearSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].InvalidZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].YearDay())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinFromUnixTime1ArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinFromUnixTime1ArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDecimal, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err = b.args[0].VecEvalDecimal(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf)
|
|
ts := result.Times()
|
|
ds := buf.Decimals()
|
|
fsp := int8(b.tp.Decimal)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
t, isNull, err := evalFromUnixTime(b.ctx, fsp, &ds[i])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
ts[i] = t
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinYearWeekWithModeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals YEARWEEK(date,mode).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_yearweek
|
|
func (b *builtinYearWeekWithModeSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf1, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
buf2, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := b.args[1].VecEvalInt(b.ctx, input, buf2); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf1)
|
|
i64s := result.Int64s()
|
|
ds := buf1.Times()
|
|
ms := buf2.Int64s()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
date := ds[i]
|
|
if date.IsZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, date.String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
mode := int(ms[i])
|
|
if buf2.IsNull(i) {
|
|
mode = 0
|
|
}
|
|
year, week := date.YearWeek(mode)
|
|
i64s[i] = int64(week + year*100)
|
|
if i64s[i] < 0 {
|
|
i64s[i] = int64(math.MaxUint32)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestampDiffSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals a builtinTimestampDiffSig.
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timestampdiff
|
|
func (b *builtinTimestampDiffSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
unitBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(unitBuf)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, unitBuf); err != nil {
|
|
return err
|
|
}
|
|
lhsBuf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(lhsBuf)
|
|
if err := b.args[1].VecEvalTime(b.ctx, input, lhsBuf); err != nil {
|
|
return err
|
|
}
|
|
rhsBuf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(rhsBuf)
|
|
if err := b.args[2].VecEvalTime(b.ctx, input, rhsBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(unitBuf, lhsBuf, rhsBuf)
|
|
i64s := result.Int64s()
|
|
lhs := lhsBuf.Times()
|
|
rhs := rhsBuf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if invalidLHS, invalidRHS := lhs[i].InvalidZero(), rhs[i].InvalidZero(); invalidLHS || invalidRHS {
|
|
if invalidLHS {
|
|
err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, lhs[i].String()))
|
|
}
|
|
if invalidRHS {
|
|
err = handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, rhs[i].String()))
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = types.TimestampDiff(unitBuf.GetString(i), lhs[i], rhs[i])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUnixTimestampIntSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalInt evals a UNIX_TIMESTAMP(time).
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_unix-timestamp
|
|
func (b *builtinUnixTimestampIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
|
|
result.ResizeInt64(n, false)
|
|
i64s := result.Int64s()
|
|
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
var isNull bool
|
|
for i := 0; i < n; i++ {
|
|
i64s[i], isNull, err = b.evalInt(input.GetRow(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
}
|
|
}
|
|
} else {
|
|
result.MergeNulls(buf)
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
|
|
t, err := buf.GetTime(i).GoTime(getTimeZone(b.ctx))
|
|
if err != nil {
|
|
i64s[i] = 0
|
|
continue
|
|
}
|
|
dec, err := goTimeToMysqlUnixTimestamp(t, 1)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
intVal, err := dec.ToInt()
|
|
if !terror.ErrorEqual(err, types.ErrTruncated) {
|
|
terror.Log(err)
|
|
}
|
|
i64s[i] = intVal
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinCurrentTime0ArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinCurrentTime0ArgSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tz := b.ctx.GetSessionVars().Location()
|
|
dur := nowTs.In(tz).Format(types.TimeFormat)
|
|
res, err := types.ParseDuration(b.ctx.GetSessionVars().StmtCtx, dur, types.MinFsp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
result.ResizeGoDuration(n, false)
|
|
durations := result.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
durations[i] = res.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimeSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTimeSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeGoDuration(n, false)
|
|
result.MergeNulls(buf)
|
|
ds := result.GoDurations()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
|
|
fsp := 0
|
|
expr := buf.GetString(i)
|
|
if idx := strings.Index(expr, "."); idx != -1 {
|
|
fsp = len(expr) - idx - 1
|
|
}
|
|
|
|
var tmpFsp int8
|
|
if tmpFsp, err = types.CheckFsp(fsp); err != nil {
|
|
return err
|
|
}
|
|
fsp = int(tmpFsp)
|
|
|
|
res, err := types.ParseDuration(sc, expr, int8(fsp))
|
|
if types.ErrTruncatedWrongVal.Equal(err) {
|
|
err = sc.HandleTruncate(err)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ds[i] = res.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDateLiteralSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDateLiteralSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
mode := b.ctx.GetSessionVars().SQLMode
|
|
if mode.HasNoZeroDateMode() && b.literal.IsZero() {
|
|
return types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, b.literal.String())
|
|
}
|
|
if mode.HasNoZeroInDateMode() && (b.literal.InvalidZero() && !b.literal.IsZero()) {
|
|
return types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, b.literal.String())
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
times := result.Times()
|
|
for i := range times {
|
|
times[i] = b.literal
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimeLiteralSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTimeLiteralSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
result.ResizeGoDuration(n, false)
|
|
d64s := result.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
d64s[i] = b.duration.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMonthNameSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ReserveString(n)
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if buf.IsNull(i) {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
mon := ds[i].Month()
|
|
if (ds[i].IsZero() && b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode()) || mon < 0 || mon > len(types.MonthNames) {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.AppendNull()
|
|
continue
|
|
} else if mon == 0 || ds[i].IsZero() {
|
|
result.AppendNull()
|
|
continue
|
|
}
|
|
result.AppendString(types.MonthNames[mon-1])
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinMonthNameSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDayOfWeekSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDayOfWeekSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].InvalidZero() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].Weekday() + 1)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinCurrentTime1ArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinCurrentTime1ArgSig) vecEvalDuration(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETInt, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalInt(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
nowTs, err := getStmtTimestamp(b.ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tz := b.ctx.GetSessionVars().Location()
|
|
dur := nowTs.In(tz).Format(types.TimeFSPFormat)
|
|
stmtCtx := b.ctx.GetSessionVars().StmtCtx
|
|
i64s := buf.Int64s()
|
|
result.ResizeGoDuration(n, false)
|
|
durations := result.GoDurations()
|
|
for i := 0; i < n; i++ {
|
|
res, err := types.ParseDuration(stmtCtx, dur, int8(i64s[i]))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
durations[i] = res.Duration
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinUTCTimestampWithoutArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
// vecEvalTime evals UTC_TIMESTAMP().
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_utc-timestamp
|
|
func (b *builtinUTCTimestampWithoutArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
res, isNull, err := evalUTCTimestampWithFsp(b.ctx, types.DefaultFsp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.ResizeTime(n, true)
|
|
return nil
|
|
}
|
|
result.ResizeTime(n, false)
|
|
t64s := result.Times()
|
|
for i := 0; i < n; i++ {
|
|
t64s[i] = res
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinConvertTzSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinConvertTzSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, result); err != nil {
|
|
return err
|
|
}
|
|
|
|
fromTzBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(fromTzBuf)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, fromTzBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
toTzBuf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(toTzBuf)
|
|
if err := b.args[2].VecEvalString(b.ctx, input, toTzBuf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.MergeNulls(fromTzBuf, toTzBuf)
|
|
ts := result.Times()
|
|
var isNull bool
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
|
|
ts[i], isNull, err = b.convertTz(ts[i], fromTzBuf.GetString(i), toTzBuf.GetString(i))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if isNull {
|
|
result.SetNull(i, true)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestamp1ArgSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf)
|
|
times := result.Times()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
var tm types.Time
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
s := buf.GetString(i)
|
|
|
|
if b.isFloat {
|
|
tm, err = types.ParseTimeFromFloatString(sc, s, mysql.TypeDatetime, types.GetFsp(s))
|
|
} else {
|
|
tm, err = types.ParseTime(sc, s, mysql.TypeDatetime, types.GetFsp(s))
|
|
}
|
|
if err != nil {
|
|
if err = handleInvalidTimeError(b.ctx, err); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
times[i] = tm
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestamp1ArgSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinTimestamp2ArgsSig) vecEvalTime(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf0, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf0)
|
|
if err := b.args[0].VecEvalString(b.ctx, input, buf0); err != nil {
|
|
return err
|
|
}
|
|
|
|
buf1, err := b.bufAllocator.get(types.ETString, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf1)
|
|
if err := b.args[1].VecEvalString(b.ctx, input, buf1); err != nil {
|
|
return err
|
|
}
|
|
|
|
result.ResizeTime(n, false)
|
|
result.MergeNulls(buf0, buf1)
|
|
times := result.Times()
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
var tm types.Time
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
arg0 := buf0.GetString(i)
|
|
arg1 := buf1.GetString(i)
|
|
|
|
if b.isFloat {
|
|
tm, err = types.ParseTimeFromFloatString(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0))
|
|
} else {
|
|
tm, err = types.ParseTime(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0))
|
|
}
|
|
if err != nil {
|
|
if err = handleInvalidTimeError(b.ctx, err); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
|
|
if !isDuration(arg1) {
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
|
|
duration, err := types.ParseDuration(sc, arg1, types.GetFsp(arg1))
|
|
if err != nil {
|
|
if err = handleInvalidTimeError(b.ctx, err); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
tmp, err := tm.Add(sc, duration)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
times[i] = tmp
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinTimestamp2ArgsSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|
|
func (b *builtinDayOfMonthSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
|
|
n := input.NumRows()
|
|
buf, err := b.bufAllocator.get(types.ETDatetime, n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer b.bufAllocator.put(buf)
|
|
if err := b.args[0].VecEvalTime(b.ctx, input, buf); err != nil {
|
|
return err
|
|
}
|
|
result.ResizeInt64(n, false)
|
|
result.MergeNulls(buf)
|
|
i64s := result.Int64s()
|
|
ds := buf.Times()
|
|
for i := 0; i < n; i++ {
|
|
if result.IsNull(i) {
|
|
continue
|
|
}
|
|
if ds[i].IsZero() {
|
|
if b.ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() {
|
|
if err := handleInvalidTimeError(b.ctx, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, ds[i].String())); err != nil {
|
|
return err
|
|
}
|
|
result.SetNull(i, true)
|
|
continue
|
|
}
|
|
i64s[i] = 0
|
|
continue
|
|
}
|
|
i64s[i] = int64(ds[i].Day())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *builtinDayOfMonthSig) vectorized() bool {
|
|
return true
|
|
}
|
|
|