599 lines
25 KiB
Go
599 lines
25 KiB
Go
// 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,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package expression
|
|
|
|
import (
|
|
"math"
|
|
"math/rand"
|
|
"testing"
|
|
|
|
"github.com/pingcap/tidb/pkg/parser/ast"
|
|
"github.com/pingcap/tidb/pkg/parser/mysql"
|
|
"github.com/pingcap/tidb/pkg/types"
|
|
"github.com/pingcap/tidb/pkg/util/chunk"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type periodGener struct {
|
|
randGen *defaultRandGen
|
|
}
|
|
|
|
func newPeriodGener() *periodGener {
|
|
return &periodGener{newDefaultRandGen()}
|
|
}
|
|
|
|
func (g *periodGener) gen() any {
|
|
return int64((g.randGen.Intn(2500)+1)*100 + g.randGen.Intn(12) + 1)
|
|
}
|
|
|
|
// unitStrGener is used to generate strings which are unit format
|
|
type unitStrGener struct {
|
|
randGen *defaultRandGen
|
|
}
|
|
|
|
func newUnitStrGener() *unitStrGener {
|
|
return &unitStrGener{newDefaultRandGen()}
|
|
}
|
|
|
|
func (g *unitStrGener) gen() any {
|
|
units := []string{
|
|
"MICROSECOND",
|
|
"SECOND",
|
|
"MINUTE",
|
|
"HOUR",
|
|
"DAY",
|
|
"WEEK",
|
|
"MONTH",
|
|
"QUARTER",
|
|
"YEAR",
|
|
}
|
|
|
|
n := g.randGen.Intn(len(units))
|
|
return units[n]
|
|
}
|
|
|
|
// tzStrGener is used to generate strings which are timezones
|
|
type tzStrGener struct{}
|
|
|
|
func (g *tzStrGener) gen() any {
|
|
tzs := []string{
|
|
"",
|
|
"GMT",
|
|
"MET",
|
|
"+00:00",
|
|
"+10:00",
|
|
}
|
|
|
|
n := rand.Int() % len(tzs)
|
|
return tzs[n]
|
|
}
|
|
|
|
var vecBuiltinTimeCases = map[string][]vecExprBenchCase{
|
|
ast.DateLiteral: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDatetime},
|
|
constants: []*Constant{{Value: types.NewStringDatum("2019-11-11"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
},
|
|
ast.TimeLiteral: {
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString},
|
|
constants: []*Constant{
|
|
{Value: types.NewStringDatum("838:59:59"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
},
|
|
ast.DateDiff: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime, types.ETDatetime}},
|
|
},
|
|
ast.DateFormat: {
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateTimeStrGener{randGen: newDefaultRandGen()}, newTimeFormatGener(0.5)},
|
|
},
|
|
},
|
|
ast.Hour: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}, geners: []dataGenerator{newRangeDurationGener(0.2)}},
|
|
},
|
|
ast.Minute: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}, geners: []dataGenerator{newRangeDurationGener(0.2)}},
|
|
},
|
|
ast.Second: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}, geners: []dataGenerator{newRangeDurationGener(0.2)}},
|
|
},
|
|
ast.ToSeconds: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.MicroSecond: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}, geners: []dataGenerator{newRangeDurationGener(0.2)}},
|
|
},
|
|
ast.Now: {
|
|
{retEvalType: types.ETDatetime},
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETInt},
|
|
geners: []dataGenerator{newRangeInt64Gener(0, 7)},
|
|
},
|
|
},
|
|
ast.DayOfWeek: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.DayOfYear: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.Day: {},
|
|
ast.ToDays: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.CurrentTime: {
|
|
{retEvalType: types.ETDuration},
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt}, geners: []dataGenerator{newRangeInt64Gener(0, 7)}}, // fsp must be in the range 0 to 6.
|
|
},
|
|
ast.Time: {
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&dateTimeStrGener{randGen: newDefaultRandGen()}}},
|
|
},
|
|
ast.CurrentDate: {
|
|
{retEvalType: types.ETDatetime},
|
|
},
|
|
ast.MakeDate: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETInt, types.ETInt},
|
|
geners: []dataGenerator{newRangeInt64Gener(0, 2200), newRangeInt64Gener(0, 365)},
|
|
},
|
|
},
|
|
ast.MakeTime: {
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt, types.ETInt, types.ETReal}, geners: []dataGenerator{newRangeInt64Gener(-1000, 1000)}},
|
|
{
|
|
retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt, types.ETInt, types.ETReal},
|
|
childrenFieldTypes: []*types.FieldType{
|
|
types.NewFieldTypeBuilder().SetType(mysql.TypeLonglong).SetFlag(mysql.UnsignedFlag).BuildP(),
|
|
},
|
|
geners: []dataGenerator{newRangeInt64Gener(-1000, 1000)},
|
|
},
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETReal, types.ETReal, types.ETReal}, geners: []dataGenerator{newRangeRealGener(-1000.0, 1000.0, 0.1)}},
|
|
},
|
|
ast.PeriodAdd: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, geners: []dataGenerator{newPeriodGener(), newPeriodGener()}},
|
|
},
|
|
ast.PeriodDiff: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt, types.ETInt}, geners: []dataGenerator{newPeriodGener(), newPeriodGener()}},
|
|
},
|
|
ast.Quarter: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.TimeFormat: {
|
|
{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDuration, types.ETString}, geners: []dataGenerator{newRangeDurationGener(0.5), newTimeFormatGener(0.5)}},
|
|
},
|
|
ast.TimeToSec: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}},
|
|
},
|
|
ast.SecToTime: {
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETReal}},
|
|
},
|
|
// This test case may fail due to the issue: https://github.com/pingcap/tidb/issues/13638.
|
|
// We remove this case to stabilize CI, and will reopen this when we fix the issue above.
|
|
// ast.TimestampAdd: {
|
|
// {
|
|
// retEvalType: types.ETString,
|
|
// childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETDatetime},
|
|
// geners: []dataGenerator{&unitStrGener{newDefaultRandGen()}, nil, nil},
|
|
// },
|
|
// },
|
|
ast.UnixTimestamp: {
|
|
{
|
|
retEvalType: types.ETInt,
|
|
childrenTypes: []types.EvalType{types.ETDatetime},
|
|
childrenFieldTypes: []*types.FieldType{
|
|
types.NewFieldTypeBuilder().SetType(mysql.TypeDatetime).SetFlag(mysql.BinaryFlag).SetFlen(types.UnspecifiedLength).BuildP(),
|
|
},
|
|
geners: []dataGenerator{&dateTimeGener{Fsp: 0, randGen: newDefaultRandGen()}},
|
|
},
|
|
{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETTimestamp}},
|
|
{retEvalType: types.ETInt},
|
|
},
|
|
ast.TimestampDiff: {
|
|
{
|
|
retEvalType: types.ETInt,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETDatetime, types.ETDatetime},
|
|
geners: []dataGenerator{newUnitStrGener(), nil, nil}},
|
|
},
|
|
ast.TimestampLiteral: {
|
|
{retEvalType: types.ETTimestamp, childrenTypes: []types.EvalType{types.ETString},
|
|
constants: []*Constant{{Value: types.NewStringDatum("2019-12-04 00:00:00"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
},
|
|
ast.SubDate: {
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
&numStrGener{rangeInt64Gener{math.MinInt32 + 1, math.MaxInt32, newDefaultRandGen()}},
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
newDefaultGener(0.2, types.ETInt),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
newDefaultGener(0.2, types.ETReal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETString, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
&numStrGener{rangeInt64Gener{math.MinInt32 + 1, math.MaxInt32, newDefaultRandGen()}},
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETInt, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
newDefaultGener(0.2, types.ETInt),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETReal, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
newDefaultGener(0.2, types.ETReal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETDecimal, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
newDefaultGener(0.2, types.ETDecimal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
},
|
|
ast.AddDate: {
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
&numStrGener{rangeInt64Gener{math.MinInt32 + 1, math.MaxInt32, newDefaultRandGen()}},
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
newDefaultGener(0.2, types.ETInt),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETReal, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
newDefaultGener(0.2, types.ETReal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETDecimal, types.ETString},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{NullRation: 0.2, randGen: newDefaultRandGen()},
|
|
newDefaultGener(0.2, types.ETDecimal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETString, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
&numStrGener{rangeInt64Gener{math.MinInt32 + 1, math.MaxInt32, newDefaultRandGen()}},
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETInt, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
newDefaultGener(0.2, types.ETInt),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETInt, types.ETReal, types.ETString},
|
|
geners: []dataGenerator{
|
|
newNullWrappedGener(0.2, dateTimeIntGener{dateTimeGener: dateTimeGener{randGen: newDefaultRandGen()}}),
|
|
newDefaultGener(0.2, types.ETReal),
|
|
},
|
|
constants: []*Constant{nil, nil, {Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
chunkSize: 128,
|
|
},
|
|
},
|
|
ast.SubTime: {
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
childrenFieldTypes: []*types.FieldType{nil,
|
|
types.NewFieldTypeBuilder().SetType(mysql.TypeString).SetFlag(mysql.BinaryFlag).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP()},
|
|
geners: []dataGenerator{
|
|
&dateStrGener{randGen: newDefaultRandGen()},
|
|
&dateStrGener{randGen: newDefaultRandGen()},
|
|
},
|
|
},
|
|
// builtinSubTimeStringNullSig
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETDatetime, types.ETDatetime},
|
|
childrenFieldTypes: []*types.FieldType{types.NewFieldType(mysql.TypeDate), types.NewFieldType(mysql.TypeDatetime)},
|
|
},
|
|
},
|
|
ast.AddTime: {
|
|
// builtinAddStringAndStringSig, a special case written by hand.
|
|
// arg1 has BinaryFlag here.
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
childrenFieldTypes: []*types.FieldType{nil,
|
|
types.NewFieldTypeBuilder().SetType(mysql.TypeString).SetFlag(mysql.BinaryFlag).SetFlen(types.UnspecifiedLength).SetDecimal(types.UnspecifiedLength).BuildP(),
|
|
},
|
|
geners: []dataGenerator{
|
|
gener{*newDefaultGener(0.2, types.ETString)},
|
|
gener{*newDefaultGener(0.2, types.ETString)},
|
|
},
|
|
},
|
|
},
|
|
ast.Week: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime, types.ETInt}},
|
|
},
|
|
ast.Month: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.Year: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.Date: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.Timestamp: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&dateTimeStrGener{randGen: newDefaultRandGen()}}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&dateStrGener{randGen: newDefaultRandGen()}}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&timeStrGener{randGen: newDefaultRandGen()}}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateTimeStrGener{randGen: newDefaultRandGen()}, &timeStrGener{randGen: newDefaultRandGen()}}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateTimeStrGener{randGen: newDefaultRandGen()}, nil}},
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{nil, &timeStrGener{randGen: newDefaultRandGen()}}},
|
|
},
|
|
ast.MonthName: {
|
|
{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.DayOfMonth: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.DayName: {
|
|
{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.UTCDate: {
|
|
{retEvalType: types.ETDatetime},
|
|
},
|
|
ast.UTCTimestamp: {
|
|
{retEvalType: types.ETTimestamp},
|
|
{retEvalType: types.ETTimestamp, childrenTypes: []types.EvalType{types.ETInt}, geners: []dataGenerator{newRangeInt64Gener(0, 7)}},
|
|
},
|
|
ast.UTCTime: {
|
|
{retEvalType: types.ETDuration},
|
|
{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt}, geners: []dataGenerator{newRangeInt64Gener(0, 7)}},
|
|
},
|
|
ast.Weekday: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}, geners: []dataGenerator{gener{*newDefaultGener(0.2, types.ETDatetime)}}},
|
|
},
|
|
ast.YearWeek: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime, types.ETInt}},
|
|
},
|
|
ast.WeekOfYear: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
ast.FromDays: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETInt}},
|
|
},
|
|
ast.FromUnixTime: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDecimal},
|
|
geners: []dataGenerator{gener{*newDefaultGener(0.9, types.ETDecimal)}},
|
|
},
|
|
},
|
|
ast.StrToDate: {
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateStrGener{randGen: newDefaultRandGen()}, &constStrGener{"%y-%m-%d"}},
|
|
},
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateStrGener{NullRation: 0.3, randGen: newDefaultRandGen()}, nil},
|
|
constants: []*Constant{nil, {Value: types.NewDatum("%Y-%m-%d"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&dateStrGener{randGen: newDefaultRandGen()}, nil},
|
|
// "%y%m%d" is wrong format, STR_TO_DATE should be failed for all rows
|
|
constants: []*Constant{nil, {Value: types.NewDatum("%y%m%d"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{
|
|
retEvalType: types.ETDuration,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&timeStrGener{nullRation: 0.3, randGen: newDefaultRandGen()}, nil},
|
|
constants: []*Constant{nil, {Value: types.NewDatum("%H:%i:%s"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{
|
|
retEvalType: types.ETDuration,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{&timeStrGener{nullRation: 0.3, randGen: newDefaultRandGen()}, nil},
|
|
// "%H%i%s" is wrong format, STR_TO_DATE should be failed for all rows
|
|
constants: []*Constant{nil, {Value: types.NewDatum("%H%i%s"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
},
|
|
ast.GetFormat: {
|
|
{
|
|
retEvalType: types.ETString,
|
|
childrenTypes: []types.EvalType{types.ETString, types.ETString},
|
|
geners: []dataGenerator{newFormatGener(0.2), newLocationGener(0.2)},
|
|
},
|
|
},
|
|
ast.Sysdate: {
|
|
// Because there is a chance that a time error will cause the test to fail,
|
|
// we cannot use the vectorized test framework to test builtinSysDateWithoutFspSig.
|
|
// We test the builtinSysDateWithoutFspSig in TestSysDate function.
|
|
// {retEvalType: types.ETDatetime},
|
|
// {retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETInt},
|
|
// geners: []dataGenerator{newRangeInt64Gener(0, 7)}},
|
|
},
|
|
ast.TiDBParseTso: {
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETInt},
|
|
// TiDB has DST time problem. Change the random ranges to [2000-01-01 00:00:01, +inf]
|
|
geners: []dataGenerator{newRangeInt64Gener(248160190726144000, math.MaxInt64)},
|
|
},
|
|
},
|
|
// Todo: how to inject the safeTS for better testing.
|
|
ast.TiDBBoundedStaleness: {
|
|
{
|
|
retEvalType: types.ETDatetime,
|
|
childrenTypes: []types.EvalType{types.ETDatetime, types.ETDatetime},
|
|
},
|
|
},
|
|
ast.LastDay: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDatetime}},
|
|
},
|
|
/* TODO: to fix https://github.com/pingcap/tidb/issues/9716 in vectorized evaluation.
|
|
ast.Extract: {
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDatetime}, geners: []dataGenerator{newDateTimeUnitStrGener(), nil}},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("SECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("MINUTE"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("HOUR"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("SECOND_MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("MINUTE_MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("MINUTE_SECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("HOUR_MICROSECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("HOUR_SECOND"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString, types.ETDuration},
|
|
constants: []*Constant{{Value: types.NewStringDatum("HOUR_MINUTE"), RetType: types.NewFieldType(mysql.TypeString)}},
|
|
},
|
|
},
|
|
*/
|
|
ast.ConvertTz: {
|
|
{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDatetime, types.ETString, types.ETString},
|
|
geners: []dataGenerator{nil, newNullWrappedGener(0.2, &tzStrGener{}), newNullWrappedGener(0.2, &tzStrGener{})}},
|
|
},
|
|
}
|
|
|
|
func TestVectorizedBuiltinTimeEvalOneVec(t *testing.T) {
|
|
testVectorizedEvalOneVec(t, vecBuiltinTimeCases)
|
|
}
|
|
|
|
func TestVectorizedBuiltinTimeFunc(t *testing.T) {
|
|
testVectorizedBuiltinFunc(t, vecBuiltinTimeCases)
|
|
}
|
|
|
|
func BenchmarkVectorizedBuiltinTimeEvalOneVec(b *testing.B) {
|
|
benchmarkVectorizedEvalOneVec(b, vecBuiltinTimeCases)
|
|
}
|
|
|
|
func BenchmarkVectorizedBuiltinTimeFunc(b *testing.B) {
|
|
benchmarkVectorizedBuiltinFunc(b, vecBuiltinTimeCases)
|
|
}
|
|
|
|
func TestVecMonth(t *testing.T) {
|
|
ctx := createContext(t)
|
|
typeFlags := ctx.GetSessionVars().StmtCtx.TypeFlags()
|
|
ctx.GetSessionVars().StmtCtx.SetTypeFlags(typeFlags.WithTruncateAsWarning(true))
|
|
input := chunk.New([]*types.FieldType{types.NewFieldType(mysql.TypeDatetime)}, 3, 3)
|
|
input.Reset()
|
|
input.AppendTime(0, types.ZeroDate)
|
|
input.AppendNull(0)
|
|
input.AppendTime(0, types.ZeroDate)
|
|
|
|
f, _, _, result := genVecBuiltinFuncBenchCase(ctx, ast.Month, vecExprBenchCase{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}})
|
|
require.True(t, ctx.GetSessionVars().SQLMode.HasStrictMode())
|
|
require.NoError(t, vecEvalType(ctx, f, types.ETInt, input, result))
|
|
require.Equal(t, 0, len(ctx.GetSessionVars().StmtCtx.GetWarnings()))
|
|
|
|
ctx.GetSessionVars().StmtCtx.InInsertStmt = true
|
|
ctx.GetSessionVars().StmtCtx.SetTypeFlags(typeFlags.WithTruncateAsWarning(false))
|
|
require.NoError(t, vecEvalType(ctx, f, types.ETInt, input, result))
|
|
}
|