github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/func_max_min_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 aggfuncs_test
    15  
    16  import (
    17  	"fmt"
    18  	"time"
    19  
    20  	. "github.com/whtcorpsinc/check"
    21  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    22  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    23  	"github.com/whtcorpsinc/milevadb/interlock/aggfuncs"
    24  	"github.com/whtcorpsinc/milevadb/types"
    25  	"github.com/whtcorpsinc/milevadb/types/json"
    26  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    27  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    28  )
    29  
    30  func maxMinUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType, isMax bool) (memDeltas []int64, err error) {
    31  	memDeltas = make([]int64, srcChk.NumEvents())
    32  	var (
    33  		preStringVal string
    34  		preJSONVal   string
    35  		preEnumVal   types.Enum
    36  		preSetVal    types.Set
    37  	)
    38  
    39  	for i := 0; i < srcChk.NumEvents(); i++ {
    40  		event := srcChk.GetEvent(i)
    41  		if event.IsNull(0) {
    42  			continue
    43  		}
    44  		switch dataType.Tp {
    45  		case allegrosql.TypeString:
    46  			curVal := event.GetString(0)
    47  			if i == 0 {
    48  				memDeltas[i] = int64(len(curVal))
    49  				preStringVal = curVal
    50  			} else if isMax && curVal > preStringVal || !isMax && curVal < preStringVal {
    51  				memDeltas[i] = int64(len(curVal)) - int64(len(preStringVal))
    52  				preStringVal = curVal
    53  			}
    54  		case allegrosql.TypeJSON:
    55  			curVal := event.GetJSON(0)
    56  			curStringVal := string(curVal.Value)
    57  			if i == 0 {
    58  				memDeltas[i] = int64(len(curStringVal))
    59  				preJSONVal = curStringVal
    60  			} else if isMax && curStringVal > preJSONVal || !isMax && curStringVal < preJSONVal {
    61  				memDeltas[i] = int64(len(curStringVal)) - int64(len(preJSONVal))
    62  				preJSONVal = curStringVal
    63  			}
    64  		case allegrosql.TypeEnum:
    65  			curVal := event.GetEnum(0)
    66  			if i == 0 {
    67  				memDeltas[i] = int64(len(curVal.Name))
    68  				preEnumVal = curVal
    69  			} else if isMax && curVal.Value > preEnumVal.Value || !isMax && curVal.Value < preEnumVal.Value {
    70  				memDeltas[i] = int64(len(curVal.Name)) - int64(len(preEnumVal.Name))
    71  				preEnumVal = curVal
    72  			}
    73  		case allegrosql.TypeSet:
    74  			curVal := event.GetSet(0)
    75  			if i == 0 {
    76  				memDeltas[i] = int64(len(curVal.Name))
    77  				preSetVal = curVal
    78  			} else if isMax && curVal.Value > preSetVal.Value || !isMax && curVal.Value < preSetVal.Value {
    79  				memDeltas[i] = int64(len(curVal.Name)) - int64(len(preSetVal.Name))
    80  				preSetVal = curVal
    81  			}
    82  		}
    83  	}
    84  	return memDeltas, nil
    85  }
    86  
    87  func maxUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (memDeltas []int64, err error) {
    88  	return maxMinUFIDelateMemDeltaGens(srcChk, dataType, true)
    89  }
    90  
    91  func minUFIDelateMemDeltaGens(srcChk *chunk.Chunk, dataType *types.FieldType) (memDeltas []int64, err error) {
    92  	return maxMinUFIDelateMemDeltaGens(srcChk, dataType, false)
    93  }
    94  
    95  func (s *testSuite) TestMergePartialResult4MaxMin(c *C) {
    96  	elems := []string{"a", "b", "c", "d", "e"}
    97  	enumA, _ := types.ParseEnumName(elems, "a", allegrosql.DefaultDefCauslationName)
    98  	enumC, _ := types.ParseEnumName(elems, "c", allegrosql.DefaultDefCauslationName)
    99  	enumE, _ := types.ParseEnumName(elems, "e", allegrosql.DefaultDefCauslationName)
   100  
   101  	setA, _ := types.ParseSetName(elems, "a", allegrosql.DefaultDefCauslationName)    // setA.Value == 1
   102  	setAB, _ := types.ParseSetName(elems, "a,b", allegrosql.DefaultDefCauslationName) // setAB.Value == 3
   103  	setAC, _ := types.ParseSetName(elems, "a,c", allegrosql.DefaultDefCauslationName) // setAC.Value == 5
   104  
   105  	unsignedType := types.NewFieldType(allegrosql.TypeLonglong)
   106  	unsignedType.Flag |= allegrosql.UnsignedFlag
   107  	tests := []aggTest{
   108  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, 4, 4, 4),
   109  		builPosetDaggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, 4, 4, 4),
   110  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeFloat, 5, 4.0, 4.0, 4.0),
   111  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDouble, 5, 4.0, 4.0, 4.0),
   112  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5, types.NewDecFromInt(4), types.NewDecFromInt(4), types.NewDecFromInt(4)),
   113  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeString, 5, "4", "4", "4"),
   114  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDate, 5, types.TimeFromDays(369), types.TimeFromDays(369), types.TimeFromDays(369)),
   115  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDuration, 5, types.Duration{Duration: time.Duration(4)}, types.Duration{Duration: time.Duration(4)}, types.Duration{Duration: time.Duration(4)}),
   116  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeJSON, 5, json.CreateBinary(int64(4)), json.CreateBinary(int64(4)), json.CreateBinary(int64(4))),
   117  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeEnum, 5, enumE, enumE, enumE),
   118  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeSet, 5, setAC, setAC, setAC),
   119  
   120  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, 0, 2, 0),
   121  		builPosetDaggTesterWithFieldType(ast.AggFuncMin, unsignedType, 5, 0, 2, 0),
   122  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeFloat, 5, 0.0, 2.0, 0.0),
   123  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDouble, 5, 0.0, 2.0, 0.0),
   124  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5, types.NewDecFromInt(0), types.NewDecFromInt(2), types.NewDecFromInt(0)),
   125  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeString, 5, "0", "2", "0"),
   126  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDate, 5, types.TimeFromDays(365), types.TimeFromDays(367), types.TimeFromDays(365)),
   127  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDuration, 5, types.Duration{Duration: time.Duration(0)}, types.Duration{Duration: time.Duration(2)}, types.Duration{Duration: time.Duration(0)}),
   128  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeJSON, 5, json.CreateBinary(int64(0)), json.CreateBinary(int64(2)), json.CreateBinary(int64(0))),
   129  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeEnum, 5, enumA, enumC, enumA),
   130  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeSet, 5, setA, setAB, setA),
   131  	}
   132  	for _, test := range tests {
   133  		s.testMergePartialResult(c, test)
   134  	}
   135  }
   136  
   137  func (s *testSuite) TestMaxMin(c *C) {
   138  	unsignedType := types.NewFieldType(allegrosql.TypeLonglong)
   139  	unsignedType.Flag |= allegrosql.UnsignedFlag
   140  	tests := []aggTest{
   141  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5, nil, 4),
   142  		builPosetDaggTesterWithFieldType(ast.AggFuncMax, unsignedType, 5, nil, 4),
   143  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeFloat, 5, nil, 4.0),
   144  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDouble, 5, nil, 4.0),
   145  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5, nil, types.NewDecFromInt(4)),
   146  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeString, 5, nil, "4", "4"),
   147  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDate, 5, nil, types.TimeFromDays(369)),
   148  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeDuration, 5, nil, types.Duration{Duration: time.Duration(4)}),
   149  		builPosetDaggTester(ast.AggFuncMax, allegrosql.TypeJSON, 5, nil, json.CreateBinary(int64(4))),
   150  
   151  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5, nil, 0),
   152  		builPosetDaggTesterWithFieldType(ast.AggFuncMin, unsignedType, 5, nil, 0),
   153  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeFloat, 5, nil, 0.0),
   154  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDouble, 5, nil, 0.0),
   155  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5, nil, types.NewDecFromInt(0)),
   156  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeString, 5, nil, "0"),
   157  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDate, 5, nil, types.TimeFromDays(365)),
   158  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeDuration, 5, nil, types.Duration{Duration: time.Duration(0)}),
   159  		builPosetDaggTester(ast.AggFuncMin, allegrosql.TypeJSON, 5, nil, json.CreateBinary(int64(0))),
   160  	}
   161  	for _, test := range tests {
   162  		s.testAggFunc(c, test)
   163  	}
   164  }
   165  
   166  func (s *testSuite) TestMemMaxMin(c *C) {
   167  	tests := []aggMemTest{
   168  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5,
   169  			aggfuncs.DefPartialResult4MaxMinIntSize, defaultUFIDelateMemDeltaGens, false),
   170  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeLonglong, 5,
   171  			aggfuncs.DefPartialResult4MaxMinUintSize, defaultUFIDelateMemDeltaGens, false),
   172  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeNewDecimal, 5,
   173  			aggfuncs.DefPartialResult4MaxMinDecimalSize, defaultUFIDelateMemDeltaGens, false),
   174  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeFloat, 5,
   175  			aggfuncs.DefPartialResult4MaxMinFloat32Size, defaultUFIDelateMemDeltaGens, false),
   176  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDouble, 5,
   177  			aggfuncs.DefPartialResult4MaxMinFloat64Size, defaultUFIDelateMemDeltaGens, false),
   178  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDate, 5,
   179  			aggfuncs.DefPartialResult4TimeSize, defaultUFIDelateMemDeltaGens, false),
   180  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeDuration, 5,
   181  			aggfuncs.DefPartialResult4MaxMinDurationSize, defaultUFIDelateMemDeltaGens, false),
   182  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeString, 99,
   183  			aggfuncs.DefPartialResult4MaxMinStringSize, maxUFIDelateMemDeltaGens, false),
   184  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeJSON, 99,
   185  			aggfuncs.DefPartialResult4MaxMinJSONSize, maxUFIDelateMemDeltaGens, false),
   186  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeEnum, 99,
   187  			aggfuncs.DefPartialResult4MaxMinEnumSize, maxUFIDelateMemDeltaGens, false),
   188  		builPosetDaggMemTester(ast.AggFuncMax, allegrosql.TypeSet, 99,
   189  			aggfuncs.DefPartialResult4MaxMinSetSize, maxUFIDelateMemDeltaGens, false),
   190  
   191  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5,
   192  			aggfuncs.DefPartialResult4MaxMinIntSize, defaultUFIDelateMemDeltaGens, false),
   193  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeLonglong, 5,
   194  			aggfuncs.DefPartialResult4MaxMinUintSize, defaultUFIDelateMemDeltaGens, false),
   195  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeNewDecimal, 5,
   196  			aggfuncs.DefPartialResult4MaxMinDecimalSize, defaultUFIDelateMemDeltaGens, false),
   197  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeFloat, 5,
   198  			aggfuncs.DefPartialResult4MaxMinFloat32Size, defaultUFIDelateMemDeltaGens, false),
   199  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDouble, 5,
   200  			aggfuncs.DefPartialResult4MaxMinFloat64Size, defaultUFIDelateMemDeltaGens, false),
   201  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDate, 5,
   202  			aggfuncs.DefPartialResult4TimeSize, defaultUFIDelateMemDeltaGens, false),
   203  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeDuration, 5,
   204  			aggfuncs.DefPartialResult4MaxMinDurationSize, defaultUFIDelateMemDeltaGens, false),
   205  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeString, 99,
   206  			aggfuncs.DefPartialResult4MaxMinStringSize, minUFIDelateMemDeltaGens, false),
   207  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeJSON, 99,
   208  			aggfuncs.DefPartialResult4MaxMinJSONSize, minUFIDelateMemDeltaGens, false),
   209  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeEnum, 99,
   210  			aggfuncs.DefPartialResult4MaxMinEnumSize, minUFIDelateMemDeltaGens, false),
   211  		builPosetDaggMemTester(ast.AggFuncMin, allegrosql.TypeSet, 99,
   212  			aggfuncs.DefPartialResult4MaxMinSetSize, minUFIDelateMemDeltaGens, false),
   213  	}
   214  	for _, test := range tests {
   215  		s.testAggMemFunc(c, test)
   216  	}
   217  }
   218  
   219  type maxSlidingWindowTestCase struct {
   220  	rowType       string
   221  	insertValue   string
   222  	expect        []string
   223  	orderByExpect []string
   224  	orderBy       bool
   225  	frameType     ast.FrameType
   226  }
   227  
   228  func testMaxSlidingWindow(tk *testkit.TestKit, tc maxSlidingWindowTestCase) {
   229  	tk.MustInterDirc(fmt.Sprintf("CREATE TABLE t (a %s);", tc.rowType))
   230  	tk.MustInterDirc(fmt.Sprintf("insert into t values %s;", tc.insertValue))
   231  	var orderBy string
   232  	if tc.orderBy {
   233  		orderBy = "ORDER BY a"
   234  	}
   235  	var result *testkit.Result
   236  	switch tc.frameType {
   237  	case ast.Events:
   238  		result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM t;", orderBy))
   239  	case ast.Ranges:
   240  		result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) FROM t;", orderBy))
   241  	default:
   242  		result = tk.MustQuery(fmt.Sprintf("SELECT max(a) OVER (%s) FROM t;", orderBy))
   243  		if tc.orderBy {
   244  			result.Check(testkit.Events(tc.orderByExpect...))
   245  			return
   246  		}
   247  	}
   248  	result.Check(testkit.Events(tc.expect...))
   249  }
   250  
   251  func (s *testSuite) TestMaxSlidingWindow(c *C) {
   252  	tk := testkit.NewTestKitWithInit(c, s.causetstore)
   253  	testCases := []maxSlidingWindowTestCase{
   254  		{
   255  			rowType:       "bigint",
   256  			insertValue:   "(1), (3), (2)",
   257  			expect:        []string{"3", "3", "3"},
   258  			orderByExpect: []string{"1", "2", "3"},
   259  		},
   260  		{
   261  			rowType:       "float",
   262  			insertValue:   "(1.1), (3.3), (2.2)",
   263  			expect:        []string{"3.3", "3.3", "3.3"},
   264  			orderByExpect: []string{"1.1", "2.2", "3.3"},
   265  		},
   266  		{
   267  			rowType:       "double",
   268  			insertValue:   "(1.1), (3.3), (2.2)",
   269  			expect:        []string{"3.3", "3.3", "3.3"},
   270  			orderByExpect: []string{"1.1", "2.2", "3.3"},
   271  		},
   272  		{
   273  			rowType:       "decimal(5, 2)",
   274  			insertValue:   "(1.1), (3.3), (2.2)",
   275  			expect:        []string{"3.30", "3.30", "3.30"},
   276  			orderByExpect: []string{"1.10", "2.20", "3.30"},
   277  		},
   278  		{
   279  			rowType:       "text",
   280  			insertValue:   "('1.1'), ('3.3'), ('2.2')",
   281  			expect:        []string{"3.3", "3.3", "3.3"},
   282  			orderByExpect: []string{"1.1", "2.2", "3.3"},
   283  		},
   284  		{
   285  			rowType:       "time",
   286  			insertValue:   "('00:00:00'), ('03:00:00'), ('02:00:00')",
   287  			expect:        []string{"03:00:00", "03:00:00", "03:00:00"},
   288  			orderByExpect: []string{"00:00:00", "02:00:00", "03:00:00"},
   289  		},
   290  		{
   291  			rowType:       "date",
   292  			insertValue:   "('2020-09-08'), ('2022-09-10'), ('2020-09-10')",
   293  			expect:        []string{"2022-09-10", "2022-09-10", "2022-09-10"},
   294  			orderByExpect: []string{"2020-09-08", "2020-09-10", "2022-09-10"},
   295  		},
   296  		{
   297  			rowType:       "datetime",
   298  			insertValue:   "('2020-09-08 02:00:00'), ('2022-09-10 00:00:00'), ('2020-09-10 00:00:00')",
   299  			expect:        []string{"2022-09-10 00:00:00", "2022-09-10 00:00:00", "2022-09-10 00:00:00"},
   300  			orderByExpect: []string{"2020-09-08 02:00:00", "2020-09-10 00:00:00", "2022-09-10 00:00:00"},
   301  		},
   302  	}
   303  
   304  	orderBy := []bool{false, true}
   305  	frameType := []ast.FrameType{ast.Events, ast.Ranges, -1}
   306  	for _, o := range orderBy {
   307  		for _, f := range frameType {
   308  			for _, tc := range testCases {
   309  				tc.frameType = f
   310  				tc.orderBy = o
   311  				tk.MustInterDirc("drop causet if exists t;")
   312  				testMaxSlidingWindow(tk, tc)
   313  			}
   314  		}
   315  	}
   316  }