github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_compare_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package memex
    15  
    16  import (
    17  	"time"
    18  
    19  	. "github.com/whtcorpsinc/check"
    20  	"github.com/whtcorpsinc/errors"
    21  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    22  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    23  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    24  	"github.com/whtcorpsinc/milevadb/types"
    25  	"github.com/whtcorpsinc/milevadb/types/json"
    26  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    27  )
    28  
    29  func (s *testEvaluatorSuite) TestCompareFunctionWithRefine(c *C) {
    30  	tblInfo := newTestBlockBuilder("").add("a", allegrosql.TypeLong).build()
    31  	tests := []struct {
    32  		exprStr string
    33  		result  string
    34  	}{
    35  		{"a < '1.0'", "lt(a, 1)"},
    36  		{"a <= '1.0'", "le(a, 1)"},
    37  		{"a > '1'", "gt(a, 1)"},
    38  		{"a >= '1'", "ge(a, 1)"},
    39  		{"a = '1'", "eq(a, 1)"},
    40  		{"a <=> '1'", "nulleq(a, 1)"},
    41  		{"a != '1'", "ne(a, 1)"},
    42  		{"a < '1.1'", "lt(a, 2)"},
    43  		{"a <= '1.1'", "le(a, 1)"},
    44  		{"a > 1.1", "gt(a, 1)"},
    45  		{"a >= '1.1'", "ge(a, 2)"},
    46  		{"a = '1.1'", "0"},
    47  		{"a <=> '1.1'", "0"},
    48  		{"a != '1.1'", "ne(cast(a, double BINARY), 1.1)"},
    49  		{"'1' < a", "lt(1, a)"},
    50  		{"'1' <= a", "le(1, a)"},
    51  		{"'1' > a", "gt(1, a)"},
    52  		{"'1' >= a", "ge(1, a)"},
    53  		{"'1' = a", "eq(1, a)"},
    54  		{"'1' <=> a", "nulleq(1, a)"},
    55  		{"'1' != a", "ne(1, a)"},
    56  		{"'1.1' < a", "lt(1, a)"},
    57  		{"'1.1' <= a", "le(2, a)"},
    58  		{"'1.1' > a", "gt(2, a)"},
    59  		{"'1.1' >= a", "ge(1, a)"},
    60  		{"'1.1' = a", "0"},
    61  		{"'1.1' <=> a", "0"},
    62  		{"'1.1' != a", "ne(1.1, cast(a, double BINARY))"},
    63  		{"'123456789123456711111189' = a", "0"},
    64  		{"123456789123456789.12345 = a", "0"},
    65  		{"123456789123456789123456789.12345 > a", "1"},
    66  		{"-123456789123456789123456789.12345 > a", "0"},
    67  		{"123456789123456789123456789.12345 < a", "0"},
    68  		{"-123456789123456789123456789.12345 < a", "1"},
    69  		{"'aaaa'=a", "eq(0, a)"},
    70  	}
    71  	defcaus, names, err := DeferredCausetInfos2DeferredCausetsAndNames(s.ctx, perceptron.NewCIStr(""), tblInfo.Name, tblInfo.DefCauss(), tblInfo)
    72  	c.Assert(err, IsNil)
    73  	schemaReplicant := NewSchema(defcaus...)
    74  	for _, t := range tests {
    75  		f, err := ParseSimpleExprsWithNames(s.ctx, t.exprStr, schemaReplicant, names)
    76  		c.Assert(err, IsNil)
    77  		c.Assert(f[0].String(), Equals, t.result)
    78  	}
    79  }
    80  
    81  func (s *testEvaluatorSuite) TestCompare(c *C) {
    82  	intVal, uintVal, realVal, stringVal, decimalVal := 1, uint64(1), 1.1, "123", types.NewDecFromFloatForTest(123.123)
    83  	timeVal := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 6)
    84  	durationVal := types.Duration{Duration: 12*time.Hour + 1*time.Minute + 1*time.Second}
    85  	jsonVal := json.CreateBinary("123")
    86  	// test cases for generating function signatures.
    87  	tests := []struct {
    88  		arg0     interface{}
    89  		arg1     interface{}
    90  		funcName string
    91  		tp       byte
    92  		expected int64
    93  	}{
    94  		{intVal, intVal, ast.LT, allegrosql.TypeLonglong, 0},
    95  		{stringVal, stringVal, ast.LT, allegrosql.TypeVarString, 0},
    96  		{intVal, decimalVal, ast.LT, allegrosql.TypeNewDecimal, 1},
    97  		{realVal, decimalVal, ast.LT, allegrosql.TypeDouble, 1},
    98  		{durationVal, durationVal, ast.LT, allegrosql.TypeDuration, 0},
    99  		{realVal, realVal, ast.LT, allegrosql.TypeDouble, 0},
   100  		{intVal, intVal, ast.NullEQ, allegrosql.TypeLonglong, 1},
   101  		{decimalVal, decimalVal, ast.LE, allegrosql.TypeNewDecimal, 1},
   102  		{decimalVal, decimalVal, ast.GT, allegrosql.TypeNewDecimal, 0},
   103  		{decimalVal, decimalVal, ast.GE, allegrosql.TypeNewDecimal, 1},
   104  		{decimalVal, decimalVal, ast.NE, allegrosql.TypeNewDecimal, 0},
   105  		{decimalVal, decimalVal, ast.EQ, allegrosql.TypeNewDecimal, 1},
   106  		{decimalVal, decimalVal, ast.NullEQ, allegrosql.TypeNewDecimal, 1},
   107  		{durationVal, durationVal, ast.LE, allegrosql.TypeDuration, 1},
   108  		{durationVal, durationVal, ast.GT, allegrosql.TypeDuration, 0},
   109  		{durationVal, durationVal, ast.GE, allegrosql.TypeDuration, 1},
   110  		{durationVal, durationVal, ast.EQ, allegrosql.TypeDuration, 1},
   111  		{durationVal, durationVal, ast.NE, allegrosql.TypeDuration, 0},
   112  		{durationVal, durationVal, ast.NullEQ, allegrosql.TypeDuration, 1},
   113  		{nil, nil, ast.NullEQ, allegrosql.TypeNull, 1},
   114  		{nil, intVal, ast.NullEQ, allegrosql.TypeDouble, 0},
   115  		{uintVal, intVal, ast.NullEQ, allegrosql.TypeLonglong, 1},
   116  		{uintVal, intVal, ast.EQ, allegrosql.TypeLonglong, 1},
   117  		{intVal, uintVal, ast.NullEQ, allegrosql.TypeLonglong, 1},
   118  		{intVal, uintVal, ast.EQ, allegrosql.TypeLonglong, 1},
   119  		{timeVal, timeVal, ast.LT, allegrosql.TypeDatetime, 0},
   120  		{timeVal, timeVal, ast.LE, allegrosql.TypeDatetime, 1},
   121  		{timeVal, timeVal, ast.GT, allegrosql.TypeDatetime, 0},
   122  		{timeVal, timeVal, ast.GE, allegrosql.TypeDatetime, 1},
   123  		{timeVal, timeVal, ast.EQ, allegrosql.TypeDatetime, 1},
   124  		{timeVal, timeVal, ast.NE, allegrosql.TypeDatetime, 0},
   125  		{timeVal, timeVal, ast.NullEQ, allegrosql.TypeDatetime, 1},
   126  		{jsonVal, jsonVal, ast.LT, allegrosql.TypeJSON, 0},
   127  		{jsonVal, jsonVal, ast.LE, allegrosql.TypeJSON, 1},
   128  		{jsonVal, jsonVal, ast.GT, allegrosql.TypeJSON, 0},
   129  		{jsonVal, jsonVal, ast.GE, allegrosql.TypeJSON, 1},
   130  		{jsonVal, jsonVal, ast.NE, allegrosql.TypeJSON, 0},
   131  		{jsonVal, jsonVal, ast.EQ, allegrosql.TypeJSON, 1},
   132  		{jsonVal, jsonVal, ast.NullEQ, allegrosql.TypeJSON, 1},
   133  	}
   134  
   135  	for _, t := range tests {
   136  		bf, err := funcs[t.funcName].getFunction(s.ctx, s.primitiveValsToConstants([]interface{}{t.arg0, t.arg1}))
   137  		c.Assert(err, IsNil)
   138  		args := bf.getArgs()
   139  		c.Assert(args[0].GetType().Tp, Equals, t.tp)
   140  		c.Assert(args[1].GetType().Tp, Equals, t.tp)
   141  		res, isNil, err := bf.evalInt(chunk.Event{})
   142  		c.Assert(err, IsNil)
   143  		c.Assert(isNil, IsFalse)
   144  		c.Assert(res, Equals, t.expected)
   145  	}
   146  
   147  	// test <non-const decimal memex> <cmp> <const string memex>
   148  	decimalDefCaus, stringCon := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal)}, &Constant{RetType: types.NewFieldType(allegrosql.TypeVarchar)}
   149  	bf, err := funcs[ast.LT].getFunction(s.ctx, []Expression{decimalDefCaus, stringCon})
   150  	c.Assert(err, IsNil)
   151  	args := bf.getArgs()
   152  	c.Assert(args[0].GetType().Tp, Equals, allegrosql.TypeNewDecimal)
   153  	c.Assert(args[1].GetType().Tp, Equals, allegrosql.TypeNewDecimal)
   154  
   155  	// test <time defCausumn> <cmp> <non-time const>
   156  	timeDefCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime)}
   157  	bf, err = funcs[ast.LT].getFunction(s.ctx, []Expression{timeDefCaus, stringCon})
   158  	c.Assert(err, IsNil)
   159  	args = bf.getArgs()
   160  	c.Assert(args[0].GetType().Tp, Equals, allegrosql.TypeDatetime)
   161  	c.Assert(args[1].GetType().Tp, Equals, allegrosql.TypeDatetime)
   162  }
   163  
   164  func (s *testEvaluatorSuite) TestCoalesce(c *C) {
   165  	cases := []struct {
   166  		args     []interface{}
   167  		expected interface{}
   168  		isNil    bool
   169  		getErr   bool
   170  	}{
   171  		{[]interface{}{nil}, nil, true, false},
   172  		{[]interface{}{nil, nil}, nil, true, false},
   173  		{[]interface{}{nil, nil, nil}, nil, true, false},
   174  		{[]interface{}{nil, 1}, int64(1), false, false},
   175  		{[]interface{}{nil, 1.1}, float64(1.1), false, false},
   176  		{[]interface{}{1, 1.1}, float64(1), false, false},
   177  		{[]interface{}{nil, types.NewDecFromFloatForTest(123.456)}, types.NewDecFromFloatForTest(123.456), false, false},
   178  		{[]interface{}{1, types.NewDecFromFloatForTest(123.456)}, types.NewDecFromInt(1), false, false},
   179  		{[]interface{}{nil, duration}, duration, false, false},
   180  		{[]interface{}{nil, tm, nil}, tm, false, false},
   181  		{[]interface{}{nil, dt, nil}, dt, false, false},
   182  		{[]interface{}{tm, dt}, tm, false, false},
   183  	}
   184  
   185  	for _, t := range cases {
   186  		f, err := newFunctionForTest(s.ctx, ast.Coalesce, s.primitiveValsToConstants(t.args)...)
   187  		c.Assert(err, IsNil)
   188  
   189  		d, err := f.Eval(chunk.Event{})
   190  
   191  		if t.getErr {
   192  			c.Assert(err, NotNil)
   193  		} else {
   194  			c.Assert(err, IsNil)
   195  			if t.isNil {
   196  				c.Assert(d.HoTT(), Equals, types.HoTTNull)
   197  			} else {
   198  				c.Assert(d.GetValue(), DeepEquals, t.expected)
   199  			}
   200  		}
   201  	}
   202  
   203  	_, err := funcs[ast.Length].getFunction(s.ctx, []Expression{NewZero()})
   204  	c.Assert(err, IsNil)
   205  }
   206  
   207  func (s *testEvaluatorSuite) TestIntervalFunc(c *C) {
   208  	sc := s.ctx.GetStochastikVars().StmtCtx
   209  	origin := sc.IgnoreTruncate
   210  	sc.IgnoreTruncate = true
   211  	defer func() {
   212  		sc.IgnoreTruncate = origin
   213  	}()
   214  
   215  	for _, t := range []struct {
   216  		args   []types.Causet
   217  		ret    int64
   218  		getErr bool
   219  	}{
   220  		{types.MakeCausets(nil, 1, 2), -1, false},
   221  		{types.MakeCausets(1, 2, 3), 0, false},
   222  		{types.MakeCausets(2, 1, 3), 1, false},
   223  		{types.MakeCausets(3, 1, 2), 2, false},
   224  		{types.MakeCausets(0, "b", "1", "2"), 1, false},
   225  		{types.MakeCausets("a", "b", "1", "2"), 1, false},
   226  		{types.MakeCausets(23, 1, 23, 23, 23, 30, 44, 200), 4, false},
   227  		{types.MakeCausets(23, 1.7, 15.3, 23.1, 30, 44, 200), 2, false},
   228  		{types.MakeCausets(9007199254740992, 9007199254740993), 0, false},
   229  		{types.MakeCausets(uint64(9223372036854775808), uint64(9223372036854775809)), 0, false},
   230  		{types.MakeCausets(9223372036854775807, uint64(9223372036854775808)), 0, false},
   231  		{types.MakeCausets(-9223372036854775807, uint64(9223372036854775808)), 0, false},
   232  		{types.MakeCausets(uint64(9223372036854775806), 9223372036854775807), 0, false},
   233  		{types.MakeCausets(uint64(9223372036854775806), -9223372036854775807), 1, false},
   234  		{types.MakeCausets("9007199254740991", "9007199254740992"), 0, false},
   235  		{types.MakeCausets(1, uint32(1), uint32(1)), 0, true},
   236  		{types.MakeCausets(-1, 2333, nil), 0, false},
   237  		{types.MakeCausets(1, nil, nil, nil), 3, false},
   238  		{types.MakeCausets(1, nil, nil, nil, 2), 3, false},
   239  		{types.MakeCausets(uint64(9223372036854775808), nil, nil, nil, 4), 4, false},
   240  
   241  		// tests for appropriate precision loss
   242  		{types.MakeCausets(9007199254740992, "9007199254740993"), 1, false},
   243  		{types.MakeCausets("9007199254740992", 9007199254740993), 1, false},
   244  		{types.MakeCausets("9007199254740992", "9007199254740993"), 1, false},
   245  	} {
   246  		fc := funcs[ast.Interval]
   247  		f, err := fc.getFunction(s.ctx, s.datumsToConstants(t.args))
   248  		c.Assert(err, IsNil)
   249  		if t.getErr {
   250  			v, err := evalBuiltinFunc(f, chunk.Event{})
   251  			c.Assert(err, NotNil)
   252  			c.Assert(v.GetInt64(), Equals, t.ret)
   253  			continue
   254  		}
   255  		v, err := evalBuiltinFunc(f, chunk.Event{})
   256  		c.Assert(err, IsNil)
   257  		c.Assert(v.GetInt64(), Equals, t.ret)
   258  	}
   259  }
   260  
   261  func (s *testEvaluatorSuite) TestGreatestLeastFuncs(c *C) {
   262  	sc := s.ctx.GetStochastikVars().StmtCtx
   263  	originIgnoreTruncate := sc.IgnoreTruncate
   264  	sc.IgnoreTruncate = true
   265  	defer func() {
   266  		sc.IgnoreTruncate = originIgnoreTruncate
   267  	}()
   268  
   269  	for _, t := range []struct {
   270  		args             []interface{}
   271  		expectedGreatest interface{}
   272  		expectedLeast    interface{}
   273  		isNil            bool
   274  		getErr           bool
   275  	}{
   276  		{
   277  			[]interface{}{1, 2, 3, 4},
   278  			int64(4), int64(1), false, false,
   279  		},
   280  		{
   281  			[]interface{}{"a", "b", "c"},
   282  			"c", "a", false, false,
   283  		},
   284  		{
   285  			[]interface{}{"123a", "b", "c", 12},
   286  			float64(123), float64(0), false, false,
   287  		},
   288  		{
   289  			[]interface{}{tm, "123"},
   290  			curTimeString, "123", false, false,
   291  		},
   292  		{
   293  			[]interface{}{tm, 123},
   294  			curTimeInt, int64(123), false, false,
   295  		},
   296  		{
   297  			[]interface{}{tm, "invalid_time_1", "invalid_time_2", tmWithFsp},
   298  			curTimeWithFspString, "invalid_time_1", false, false,
   299  		},
   300  		{
   301  			[]interface{}{tm, "invalid_time_2", "invalid_time_1", tmWithFsp},
   302  			curTimeWithFspString, "invalid_time_2", false, false,
   303  		},
   304  		{
   305  			[]interface{}{tm, "invalid_time", nil, tmWithFsp},
   306  			nil, nil, true, false,
   307  		},
   308  		{
   309  			[]interface{}{duration, "123"},
   310  			"12:59:59", "123", false, false,
   311  		},
   312  		{
   313  			[]interface{}{"123", nil, "123"},
   314  			nil, nil, true, false,
   315  		},
   316  		{
   317  			[]interface{}{errors.New("must error"), 123},
   318  			nil, nil, false, true,
   319  		},
   320  	} {
   321  		f0, err := newFunctionForTest(s.ctx, ast.Greatest, s.primitiveValsToConstants(t.args)...)
   322  		c.Assert(err, IsNil)
   323  		d, err := f0.Eval(chunk.Event{})
   324  		if t.getErr {
   325  			c.Assert(err, NotNil)
   326  		} else {
   327  			c.Assert(err, IsNil)
   328  			if t.isNil {
   329  				c.Assert(d.HoTT(), Equals, types.HoTTNull)
   330  			} else {
   331  				c.Assert(d.GetValue(), DeepEquals, t.expectedGreatest)
   332  			}
   333  		}
   334  
   335  		f1, err := newFunctionForTest(s.ctx, ast.Least, s.primitiveValsToConstants(t.args)...)
   336  		c.Assert(err, IsNil)
   337  		d, err = f1.Eval(chunk.Event{})
   338  		if t.getErr {
   339  			c.Assert(err, NotNil)
   340  		} else {
   341  			c.Assert(err, IsNil)
   342  			if t.isNil {
   343  				c.Assert(d.HoTT(), Equals, types.HoTTNull)
   344  			} else {
   345  				c.Assert(d.GetValue(), DeepEquals, t.expectedLeast)
   346  			}
   347  		}
   348  	}
   349  	_, err := funcs[ast.Greatest].getFunction(s.ctx, []Expression{NewZero(), NewOne()})
   350  	c.Assert(err, IsNil)
   351  	_, err = funcs[ast.Least].getFunction(s.ctx, []Expression{NewZero(), NewOne()})
   352  	c.Assert(err, IsNil)
   353  }