569 lines
17 KiB
Go
569 lines
17 KiB
Go
// Copyright 2016 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 types
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pingcap/tidb/parser/mysql"
|
|
"github.com/pingcap/tidb/sessionctx/stmtctx"
|
|
"github.com/pingcap/tidb/types/json"
|
|
"github.com/pingcap/tidb/util/collate"
|
|
"github.com/pingcap/tidb/util/hack"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestDatum(t *testing.T) {
|
|
values := []interface{}{
|
|
int64(1),
|
|
uint64(1),
|
|
1.1,
|
|
"abc",
|
|
[]byte("abc"),
|
|
[]int{1},
|
|
}
|
|
for _, val := range values {
|
|
var d Datum
|
|
d.SetMinNotNull()
|
|
d.SetValueWithDefaultCollation(val)
|
|
x := d.GetValue()
|
|
require.Equal(t, val, x)
|
|
require.Equal(t, int(d.length), d.Length())
|
|
require.Equal(t, d.String(), fmt.Sprint(d))
|
|
}
|
|
}
|
|
|
|
func testDatumToBool(t *testing.T, in interface{}, res int) {
|
|
datum := NewDatum(in)
|
|
res64 := int64(res)
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
b, err := datum.ToBool(sc)
|
|
require.NoError(t, err)
|
|
require.Equal(t, res64, b)
|
|
}
|
|
|
|
func TestToBool(t *testing.T) {
|
|
testDatumToBool(t, 0, 0)
|
|
testDatumToBool(t, int64(0), 0)
|
|
testDatumToBool(t, uint64(0), 0)
|
|
testDatumToBool(t, float32(0.1), 1)
|
|
testDatumToBool(t, float64(0.1), 1)
|
|
testDatumToBool(t, float64(0.5), 1)
|
|
testDatumToBool(t, float64(0.499), 1)
|
|
testDatumToBool(t, "", 0)
|
|
testDatumToBool(t, "0.1", 1)
|
|
testDatumToBool(t, []byte{}, 0)
|
|
testDatumToBool(t, []byte("0.1"), 1)
|
|
testDatumToBool(t, NewBinaryLiteralFromUint(0, -1), 0)
|
|
testDatumToBool(t, Enum{Name: "a", Value: 1}, 1)
|
|
testDatumToBool(t, Set{Name: "a", Value: 1}, 1)
|
|
testDatumToBool(t, json.CreateBinary(int64(1)), 1)
|
|
testDatumToBool(t, json.CreateBinary(int64(0)), 0)
|
|
testDatumToBool(t, json.CreateBinary("0"), 1)
|
|
testDatumToBool(t, json.CreateBinary("aaabbb"), 1)
|
|
testDatumToBool(t, json.CreateBinary(float64(0.0)), 0)
|
|
testDatumToBool(t, json.CreateBinary(float64(3.1415)), 1)
|
|
testDatumToBool(t, json.CreateBinary([]interface{}{int64(1), int64(2)}), 1)
|
|
testDatumToBool(t, json.CreateBinary(map[string]interface{}{"ke": "val"}), 1)
|
|
testDatumToBool(t, json.CreateBinary("0000-00-00 00:00:00"), 1)
|
|
testDatumToBool(t, json.CreateBinary("0778"), 1)
|
|
testDatumToBool(t, json.CreateBinary("0000"), 1)
|
|
testDatumToBool(t, json.CreateBinary(nil), 1)
|
|
testDatumToBool(t, json.CreateBinary([]interface{}{nil}), 1)
|
|
testDatumToBool(t, json.CreateBinary(true), 1)
|
|
testDatumToBool(t, json.CreateBinary(false), 1)
|
|
testDatumToBool(t, json.CreateBinary(""), 1)
|
|
t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6)
|
|
require.NoError(t, err)
|
|
testDatumToBool(t, t1, 1)
|
|
|
|
td, err := ParseDuration(nil, "11:11:11.999999", 6)
|
|
require.NoError(t, err)
|
|
testDatumToBool(t, td, 1)
|
|
|
|
ft := NewFieldType(mysql.TypeNewDecimal)
|
|
ft.Decimal = 5
|
|
v, err := Convert(0.1415926, ft)
|
|
require.NoError(t, err)
|
|
testDatumToBool(t, v, 1)
|
|
d := NewDatum(&invalidMockType{})
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
_, err = d.ToBool(sc)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func testDatumToInt64(t *testing.T, val interface{}, expect int64) {
|
|
d := NewDatum(val)
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
b, err := d.ToInt64(sc)
|
|
require.NoError(t, err)
|
|
require.Equal(t, expect, b)
|
|
}
|
|
|
|
func TestToInt64(t *testing.T) {
|
|
testDatumToInt64(t, "0", int64(0))
|
|
testDatumToInt64(t, 0, int64(0))
|
|
testDatumToInt64(t, int64(0), int64(0))
|
|
testDatumToInt64(t, uint64(0), int64(0))
|
|
testDatumToInt64(t, float32(3.1), int64(3))
|
|
testDatumToInt64(t, float64(3.1), int64(3))
|
|
testDatumToInt64(t, NewBinaryLiteralFromUint(100, -1), int64(100))
|
|
testDatumToInt64(t, Enum{Name: "a", Value: 1}, int64(1))
|
|
testDatumToInt64(t, Set{Name: "a", Value: 1}, int64(1))
|
|
testDatumToInt64(t, json.CreateBinary(int64(3)), int64(3))
|
|
|
|
t1, err := ParseTime(&stmtctx.StatementContext{
|
|
TimeZone: time.UTC,
|
|
}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 0)
|
|
require.NoError(t, err)
|
|
testDatumToInt64(t, t1, int64(20111110111112))
|
|
|
|
td, err := ParseDuration(nil, "11:11:11.999999", 6)
|
|
require.NoError(t, err)
|
|
testDatumToInt64(t, td, int64(111112))
|
|
|
|
ft := NewFieldType(mysql.TypeNewDecimal)
|
|
ft.Decimal = 5
|
|
v, err := Convert(3.1415926, ft)
|
|
require.NoError(t, err)
|
|
testDatumToInt64(t, v, int64(3))
|
|
}
|
|
|
|
func testDatumToUInt32(t *testing.T, val interface{}, expect uint32, hasError bool) {
|
|
d := NewDatum(val)
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
|
|
ft := NewFieldType(mysql.TypeLong)
|
|
ft.Flag |= mysql.UnsignedFlag
|
|
converted, err := d.ConvertTo(sc, ft)
|
|
|
|
if hasError {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
require.Equal(t, KindUint64, converted.Kind())
|
|
require.Equal(t, uint64(expect), converted.GetUint64())
|
|
}
|
|
|
|
func TestToUint32(t *testing.T) {
|
|
// test overflow
|
|
testDatumToUInt32(t, 5000000000, 4294967295, true)
|
|
testDatumToUInt32(t, int64(-1), 4294967295, true)
|
|
testDatumToUInt32(t, "5000000000", 4294967295, true)
|
|
|
|
testDatumToUInt32(t, 12345, 12345, false)
|
|
testDatumToUInt32(t, int64(0), 0, false)
|
|
testDatumToUInt32(t, 2147483648, 2147483648, false)
|
|
testDatumToUInt32(t, Enum{Name: "a", Value: 1}, 1, false)
|
|
testDatumToUInt32(t, Set{Name: "a", Value: 1}, 1, false)
|
|
}
|
|
|
|
func TestConvertToFloat(t *testing.T) {
|
|
testCases := []struct {
|
|
d Datum
|
|
tp byte
|
|
errMsg string
|
|
r64 float64
|
|
r32 float32
|
|
}{
|
|
{NewDatum(float32(3.00)), mysql.TypeDouble, "", 3.00, 3.00},
|
|
{NewDatum(float64(12345.678)), mysql.TypeDouble, "", 12345.678, 12345.678},
|
|
{NewDatum("12345.678"), mysql.TypeDouble, "", 12345.678, 12345.678},
|
|
{NewDatum([]byte("12345.678")), mysql.TypeDouble, "", 12345.678, 12345.678},
|
|
{NewDatum(int64(12345)), mysql.TypeDouble, "", 12345, 12345},
|
|
{NewDatum(uint64(123456)), mysql.TypeDouble, "", 123456, 123456},
|
|
{NewDatum(byte(123)), mysql.TypeDouble, "cannot convert ", 0, 0},
|
|
{NewDatum(math.NaN()), mysql.TypeDouble, "constant .* overflows double", 0, 0},
|
|
{NewDatum(math.Inf(-1)), mysql.TypeDouble, "constant .* overflows double", math.Inf(-1), float32(math.Inf(-1))},
|
|
{NewDatum(math.Inf(1)), mysql.TypeDouble, "constant .* overflows double", math.Inf(1), float32(math.Inf(1))},
|
|
{NewDatum(float32(281.37)), mysql.TypeFloat, "", 281.37, 281.37},
|
|
{NewDatum("281.37"), mysql.TypeFloat, "", 281.37, 281.37},
|
|
}
|
|
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
for _, testCase := range testCases {
|
|
converted, err := testCase.d.ConvertTo(sc, NewFieldType(testCase.tp))
|
|
if testCase.errMsg == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.Error(t, err)
|
|
require.Regexp(t, testCase.errMsg, err.Error())
|
|
}
|
|
require.Equal(t, testCase.r32, converted.GetFloat32())
|
|
if testCase.tp == mysql.TypeDouble {
|
|
require.Equal(t, testCase.r64, converted.GetFloat64())
|
|
} else {
|
|
// Convert to float32 and convert back to float64, we will get a different value.
|
|
require.NotEqual(t, testCase.r64, converted.GetFloat64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// mustParseTimeIntoDatum is similar to ParseTime but panic if any error occurs.
|
|
func mustParseTimeIntoDatum(s string, tp byte, fsp int) (d Datum) {
|
|
t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp)
|
|
if err != nil {
|
|
panic("ParseTime fail")
|
|
}
|
|
d.SetMysqlTime(t)
|
|
return
|
|
}
|
|
|
|
func TestToJSON(t *testing.T) {
|
|
ft := NewFieldType(mysql.TypeJSON)
|
|
sc := new(stmtctx.StatementContext)
|
|
tests := []struct {
|
|
datum Datum
|
|
expected string
|
|
success bool
|
|
}{
|
|
{NewIntDatum(1), `1.0`, true},
|
|
{NewFloat64Datum(2), `2`, true},
|
|
{NewStringDatum("\"hello, 世界\""), `"hello, 世界"`, true},
|
|
{NewStringDatum("[1, 2, 3]"), `[1, 2, 3]`, true},
|
|
{NewStringDatum("{}"), `{}`, true},
|
|
{mustParseTimeIntoDatum("2011-11-10 11:11:11.111111", mysql.TypeTimestamp, 6), `"2011-11-10 11:11:11.111111"`, true},
|
|
{NewStringDatum(`{"a": "9223372036854775809"}`), `{"a": "9223372036854775809"}`, true},
|
|
{NewBinaryLiteralDatum([]byte{0x81}), ``, false},
|
|
|
|
// can not parse JSON from this string, so error occurs.
|
|
{NewStringDatum("hello, 世界"), "", false},
|
|
}
|
|
for _, tt := range tests {
|
|
obtain, err := tt.datum.ConvertTo(sc, ft)
|
|
if tt.success {
|
|
require.NoError(t, err)
|
|
|
|
sd := NewStringDatum(tt.expected)
|
|
var expected Datum
|
|
expected, err = sd.ConvertTo(sc, ft)
|
|
require.NoError(t, err)
|
|
|
|
var cmp int
|
|
cmp, err = obtain.Compare(sc, &expected, collate.GetBinaryCollator())
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, cmp)
|
|
} else {
|
|
require.Error(t, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIsNull(t *testing.T) {
|
|
tests := []struct {
|
|
data interface{}
|
|
isnull bool
|
|
}{
|
|
{nil, true},
|
|
{0, false},
|
|
{1, false},
|
|
{1.1, false},
|
|
{"string", false},
|
|
{"", false},
|
|
}
|
|
for _, tt := range tests {
|
|
testIsNull(t, tt.data, tt.isnull)
|
|
}
|
|
}
|
|
|
|
func testIsNull(t *testing.T, data interface{}, isnull bool) {
|
|
d := NewDatum(data)
|
|
require.Equalf(t, isnull, d.IsNull(), "data: %v, isnull: %v", data, isnull)
|
|
}
|
|
|
|
func TestToBytes(t *testing.T) {
|
|
tests := []struct {
|
|
a Datum
|
|
out []byte
|
|
}{
|
|
{NewIntDatum(1), []byte("1")},
|
|
{NewDecimalDatum(NewDecFromInt(1)), []byte("1")},
|
|
{NewFloat64Datum(1.23), []byte("1.23")},
|
|
{NewStringDatum("abc"), []byte("abc")},
|
|
{Datum{}, []byte{}},
|
|
}
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
for _, tt := range tests {
|
|
bin, err := tt.a.ToBytes()
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.out, bin)
|
|
}
|
|
}
|
|
|
|
func TestComputePlusAndMinus(t *testing.T) {
|
|
sc := &stmtctx.StatementContext{TimeZone: time.UTC}
|
|
tests := []struct {
|
|
a Datum
|
|
b Datum
|
|
plus Datum
|
|
minus Datum
|
|
hasErr bool
|
|
}{
|
|
{NewIntDatum(72), NewIntDatum(28), NewIntDatum(100), NewIntDatum(44), false},
|
|
{NewIntDatum(72), NewUintDatum(28), NewIntDatum(100), NewIntDatum(44), false},
|
|
{NewUintDatum(72), NewUintDatum(28), NewUintDatum(100), NewUintDatum(44), false},
|
|
{NewUintDatum(72), NewIntDatum(28), NewUintDatum(100), NewUintDatum(44), false},
|
|
{NewFloat64Datum(72.0), NewFloat64Datum(28.0), NewFloat64Datum(100.0), NewFloat64Datum(44.0), false},
|
|
{NewDecimalDatum(NewDecFromStringForTest("72.5")), NewDecimalDatum(NewDecFromInt(3)), NewDecimalDatum(NewDecFromStringForTest("75.5")), NewDecimalDatum(NewDecFromStringForTest("69.5")), false},
|
|
{NewIntDatum(72), NewFloat64Datum(42), Datum{}, Datum{}, true},
|
|
{NewStringDatum("abcd"), NewIntDatum(42), Datum{}, Datum{}, true},
|
|
}
|
|
|
|
for ith, tt := range tests {
|
|
got, err := ComputePlus(tt.a, tt.b)
|
|
require.Equal(t, tt.hasErr, err != nil)
|
|
v, err := got.Compare(sc, &tt.plus, collate.GetBinaryCollator())
|
|
require.NoError(t, err)
|
|
require.Equalf(t, 0, v, "%dth got:%#v, %#v, expect:%#v, %#v", ith, got, got.x, tt.plus, tt.plus.x)
|
|
}
|
|
}
|
|
|
|
func TestCloneDatum(t *testing.T) {
|
|
var raw Datum
|
|
raw.b = []byte("raw")
|
|
raw.k = KindRaw
|
|
tests := []Datum{
|
|
NewIntDatum(72),
|
|
NewUintDatum(72),
|
|
NewStringDatum("abcd"),
|
|
NewBytesDatum([]byte("abcd")),
|
|
raw,
|
|
}
|
|
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
for _, tt := range tests {
|
|
tt1 := *tt.Clone()
|
|
res, err := tt.Compare(sc, &tt1, collate.GetBinaryCollator())
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, res)
|
|
if tt.b != nil {
|
|
require.NotSame(t, &tt1.b[0], &tt.b[0])
|
|
}
|
|
}
|
|
}
|
|
|
|
func newTypeWithFlag(tp byte, flag uint) *FieldType {
|
|
t := NewFieldType(tp)
|
|
t.Flag |= flag
|
|
return t
|
|
}
|
|
|
|
func newMyDecimal(val string, t *testing.T) *MyDecimal {
|
|
d := MyDecimal{}
|
|
err := d.FromString([]byte(val))
|
|
require.NoError(t, err)
|
|
return &d
|
|
}
|
|
|
|
func newRetTypeWithFlenDecimal(tp byte, flen int, decimal int) *FieldType {
|
|
return &FieldType{
|
|
Tp: tp,
|
|
Flen: flen,
|
|
Decimal: decimal,
|
|
}
|
|
}
|
|
|
|
func TestEstimatedMemUsage(t *testing.T) {
|
|
b := []byte{'a', 'b', 'c', 'd'}
|
|
enum := Enum{Name: "a", Value: 1}
|
|
datumArray := []Datum{
|
|
NewIntDatum(1),
|
|
NewFloat64Datum(1.0),
|
|
NewFloat32Datum(1.0),
|
|
NewStringDatum(string(b)),
|
|
NewBytesDatum(b),
|
|
NewDecimalDatum(newMyDecimal("1234.1234", t)),
|
|
NewMysqlEnumDatum(enum),
|
|
}
|
|
bytesConsumed := 10 * (len(datumArray)*sizeOfEmptyDatum +
|
|
sizeOfMyDecimal +
|
|
len(b)*2 +
|
|
len(hack.Slice(enum.Name)))
|
|
require.Equal(t, bytesConsumed, int(EstimatedMemUsage(datumArray, 10)))
|
|
}
|
|
|
|
func TestChangeReverseResultByUpperLowerBound(t *testing.T) {
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
sc.OverflowAsWarning = true
|
|
// TODO: add more reserve convert tests for each pair of convert type.
|
|
testData := []struct {
|
|
a Datum
|
|
res Datum
|
|
retType *FieldType
|
|
roundType RoundingType
|
|
}{
|
|
// int64 reserve to uint64
|
|
{
|
|
NewIntDatum(1),
|
|
NewUintDatum(2),
|
|
newTypeWithFlag(mysql.TypeLonglong, mysql.UnsignedFlag),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(1),
|
|
NewUintDatum(1),
|
|
newTypeWithFlag(mysql.TypeLonglong, mysql.UnsignedFlag),
|
|
Floor,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
NewUintDatum(math.MaxUint64),
|
|
newTypeWithFlag(mysql.TypeLonglong, mysql.UnsignedFlag),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
NewUintDatum(math.MaxInt64),
|
|
newTypeWithFlag(mysql.TypeLonglong, mysql.UnsignedFlag),
|
|
Floor,
|
|
},
|
|
// int64 reserve to float64
|
|
{
|
|
NewIntDatum(1),
|
|
NewFloat64Datum(2),
|
|
newRetTypeWithFlenDecimal(mysql.TypeDouble, mysql.MaxRealWidth, UnspecifiedLength),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(1),
|
|
NewFloat64Datum(1),
|
|
newRetTypeWithFlenDecimal(mysql.TypeDouble, mysql.MaxRealWidth, UnspecifiedLength),
|
|
Floor,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
GetMaxValue(newRetTypeWithFlenDecimal(mysql.TypeDouble, mysql.MaxRealWidth, UnspecifiedLength)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeDouble, mysql.MaxRealWidth, UnspecifiedLength),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
NewFloat64Datum(float64(math.MaxInt64)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeDouble, mysql.MaxRealWidth, UnspecifiedLength),
|
|
Floor,
|
|
},
|
|
// int64 reserve to Decimal
|
|
{
|
|
NewIntDatum(1),
|
|
NewDecimalDatum(newMyDecimal("2", t)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeNewDecimal, 30, 3),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(1),
|
|
NewDecimalDatum(newMyDecimal("1", t)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeNewDecimal, 30, 3),
|
|
Floor,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
GetMaxValue(newRetTypeWithFlenDecimal(mysql.TypeNewDecimal, 30, 3)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeNewDecimal, 30, 3),
|
|
Ceiling,
|
|
},
|
|
{
|
|
NewIntDatum(math.MaxInt64),
|
|
NewDecimalDatum(newMyDecimal(strconv.FormatInt(math.MaxInt64, 10), t)),
|
|
newRetTypeWithFlenDecimal(mysql.TypeNewDecimal, 30, 3),
|
|
Floor,
|
|
},
|
|
}
|
|
for ith, test := range testData {
|
|
reverseRes, err := ChangeReverseResultByUpperLowerBound(sc, test.retType, test.a, test.roundType)
|
|
require.NoError(t, err)
|
|
var cmp int
|
|
cmp, err = reverseRes.Compare(sc, &test.res, collate.GetBinaryCollator())
|
|
require.NoError(t, err)
|
|
require.Equalf(t, 0, cmp, "%dth got:%#v, expect:%#v", ith, reverseRes, test.res)
|
|
}
|
|
}
|
|
|
|
func prepareCompareDatums() ([]Datum, []Datum) {
|
|
vals := make([]Datum, 0, 5)
|
|
vals = append(vals, NewIntDatum(1))
|
|
vals = append(vals, NewFloat64Datum(1.23))
|
|
vals = append(vals, NewStringDatum("abcde"))
|
|
vals = append(vals, NewDecimalDatum(NewDecFromStringForTest("1.2345")))
|
|
vals = append(vals, NewTimeDatum(NewTime(FromGoTime(time.Date(2018, 3, 8, 16, 1, 0, 315313000, time.UTC)), mysql.TypeTimestamp, 6)))
|
|
|
|
vals1 := make([]Datum, 0, 5)
|
|
vals1 = append(vals1, NewIntDatum(1))
|
|
vals1 = append(vals1, NewFloat64Datum(1.23))
|
|
vals1 = append(vals1, NewStringDatum("abcde"))
|
|
vals1 = append(vals1, NewDecimalDatum(NewDecFromStringForTest("1.2345")))
|
|
vals1 = append(vals1, NewTimeDatum(NewTime(FromGoTime(time.Date(2018, 3, 8, 16, 1, 0, 315313000, time.UTC)), mysql.TypeTimestamp, 6)))
|
|
return vals, vals1
|
|
}
|
|
|
|
func TestStringToMysqlBit(t *testing.T) {
|
|
tests := []struct {
|
|
a Datum
|
|
out []byte
|
|
}{
|
|
{NewStringDatum("true"), []byte{1}},
|
|
{NewStringDatum("false"), []byte{0}},
|
|
{NewStringDatum("1"), []byte{1}},
|
|
{NewStringDatum("0"), []byte{0}},
|
|
{NewStringDatum("b'1'"), []byte{1}},
|
|
{NewStringDatum("b'0'"), []byte{0}},
|
|
}
|
|
sc := new(stmtctx.StatementContext)
|
|
sc.IgnoreTruncate = true
|
|
tp := NewFieldType(mysql.TypeBit)
|
|
tp.Flen = 1
|
|
for _, tt := range tests {
|
|
bin, err := tt.a.convertToMysqlBit(nil, tp)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.out, bin.b)
|
|
}
|
|
}
|
|
|
|
func BenchmarkCompareDatum(b *testing.B) {
|
|
vals, vals1 := prepareCompareDatums()
|
|
sc := new(stmtctx.StatementContext)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j, v := range vals {
|
|
_, err := v.Compare(sc, &vals1[j], collate.GetBinaryCollator())
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkCompareDatumByReflect(b *testing.B) {
|
|
vals, vals1 := prepareCompareDatums()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
reflect.DeepEqual(vals, vals1)
|
|
}
|
|
}
|