github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/interlock/aggfuncs/window_func_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  	"time"
    18  
    19  	. "github.com/whtcorpsinc/check"
    20  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    21  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    22  
    23  	"github.com/whtcorpsinc/milevadb/interlock/aggfuncs"
    24  	"github.com/whtcorpsinc/milevadb/memex"
    25  	"github.com/whtcorpsinc/milevadb/memex/aggregation"
    26  	"github.com/whtcorpsinc/milevadb/types"
    27  	"github.com/whtcorpsinc/milevadb/types/json"
    28  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    29  )
    30  
    31  type windowTest struct {
    32  	dataType    *types.FieldType
    33  	numEvents     int
    34  	funcName    string
    35  	args        []memex.Expression
    36  	orderByDefCauss []*memex.DeferredCauset
    37  	results     []types.Causet
    38  }
    39  
    40  func (p *windowTest) genSrcChk() *chunk.Chunk {
    41  	srcChk := chunk.NewChunkWithCapacity([]*types.FieldType{p.dataType}, p.numEvents)
    42  	dataGen := getDataGenFunc(p.dataType)
    43  	for i := 0; i < p.numEvents; i++ {
    44  		dt := dataGen(i)
    45  		srcChk.AppendCauset(0, &dt)
    46  	}
    47  	return srcChk
    48  }
    49  
    50  type windowMemTest struct {
    51  	windowTest         windowTest
    52  	allocMemDelta      int64
    53  	uFIDelateMemDeltaGens uFIDelateMemDeltaGens
    54  }
    55  
    56  func (s *testSuite) testWindowFunc(c *C, p windowTest) {
    57  	srcChk := p.genSrcChk()
    58  
    59  	desc, err := aggregation.NewAggFuncDesc(s.ctx, p.funcName, p.args, false)
    60  	c.Assert(err, IsNil)
    61  	finalFunc := aggfuncs.BuildWindowFunctions(s.ctx, desc, 0, p.orderByDefCauss)
    62  	finalPr, _ := finalFunc.AllocPartialResult()
    63  	resultChk := chunk.NewChunkWithCapacity([]*types.FieldType{desc.RetTp}, 1)
    64  
    65  	iter := chunk.NewIterator4Chunk(srcChk)
    66  	for event := iter.Begin(); event != iter.End(); event = iter.Next() {
    67  		_, err = finalFunc.UFIDelatePartialResult(s.ctx, []chunk.Event{event}, finalPr)
    68  		c.Assert(err, IsNil)
    69  	}
    70  
    71  	c.Assert(p.numEvents, Equals, len(p.results))
    72  	for i := 0; i < p.numEvents; i++ {
    73  		err = finalFunc.AppendFinalResult2Chunk(s.ctx, finalPr, resultChk)
    74  		c.Assert(err, IsNil)
    75  		dt := resultChk.GetEvent(0).GetCauset(0, desc.RetTp)
    76  		result, err := dt.CompareCauset(s.ctx.GetStochastikVars().StmtCtx, &p.results[i])
    77  		c.Assert(err, IsNil)
    78  		c.Assert(result, Equals, 0)
    79  		resultChk.Reset()
    80  	}
    81  	finalFunc.ResetPartialResult(finalPr)
    82  }
    83  
    84  func (s *testSuite) testWindowAggMemFunc(c *C, p windowMemTest) {
    85  	srcChk := p.windowTest.genSrcChk()
    86  
    87  	desc, err := aggregation.NewAggFuncDesc(s.ctx, p.windowTest.funcName, p.windowTest.args, false)
    88  	c.Assert(err, IsNil)
    89  	finalFunc := aggfuncs.BuildWindowFunctions(s.ctx, desc, 0, p.windowTest.orderByDefCauss)
    90  	finalPr, memDelta := finalFunc.AllocPartialResult()
    91  	c.Assert(memDelta, Equals, p.allocMemDelta)
    92  
    93  	uFIDelateMemDeltas, err := p.uFIDelateMemDeltaGens(srcChk, p.windowTest.dataType)
    94  	c.Assert(err, IsNil)
    95  
    96  	i := 0
    97  	iter := chunk.NewIterator4Chunk(srcChk)
    98  	for event := iter.Begin(); event != iter.End(); event = iter.Next() {
    99  		memDelta, err = finalFunc.UFIDelatePartialResult(s.ctx, []chunk.Event{event}, finalPr)
   100  		c.Assert(err, IsNil)
   101  		c.Assert(memDelta, Equals, uFIDelateMemDeltas[i])
   102  		i++
   103  	}
   104  }
   105  
   106  func buildWindowTesterWithArgs(funcName string, tp byte, args []memex.Expression, orderByDefCauss int, numEvents int, results ...interface{}) windowTest {
   107  	pt := windowTest{
   108  		dataType: types.NewFieldType(tp),
   109  		numEvents:  numEvents,
   110  		funcName: funcName,
   111  	}
   112  	if funcName != ast.WindowFuncNtile {
   113  		pt.args = append(pt.args, &memex.DeferredCauset{RetType: pt.dataType, Index: 0})
   114  	}
   115  	pt.args = append(pt.args, args...)
   116  	if orderByDefCauss > 0 {
   117  		pt.orderByDefCauss = append(pt.orderByDefCauss, &memex.DeferredCauset{RetType: pt.dataType, Index: 0})
   118  	}
   119  
   120  	for _, result := range results {
   121  		pt.results = append(pt.results, types.NewCauset(result))
   122  	}
   123  	return pt
   124  }
   125  
   126  func buildWindowTester(funcName string, tp byte, constantArg uint64, orderByDefCauss int, numEvents int, results ...interface{}) windowTest {
   127  	pt := windowTest{
   128  		dataType: types.NewFieldType(tp),
   129  		numEvents:  numEvents,
   130  		funcName: funcName,
   131  	}
   132  	if funcName != ast.WindowFuncNtile {
   133  		pt.args = append(pt.args, &memex.DeferredCauset{RetType: pt.dataType, Index: 0})
   134  	}
   135  	if constantArg > 0 {
   136  		pt.args = append(pt.args, &memex.Constant{Value: types.NewUintCauset(constantArg)})
   137  	}
   138  	if orderByDefCauss > 0 {
   139  		pt.orderByDefCauss = append(pt.orderByDefCauss, &memex.DeferredCauset{RetType: pt.dataType, Index: 0})
   140  	}
   141  
   142  	for _, result := range results {
   143  		pt.results = append(pt.results, types.NewCauset(result))
   144  	}
   145  	return pt
   146  }
   147  
   148  func buildWindowMemTester(funcName string, tp byte, constantArg uint64, numEvents int, orderByDefCauss int, allocMemDelta int64, uFIDelateMemDeltaGens uFIDelateMemDeltaGens) windowMemTest {
   149  	windowTest := buildWindowTester(funcName, tp, constantArg, orderByDefCauss, numEvents)
   150  	pt := windowMemTest{
   151  		windowTest:         windowTest,
   152  		allocMemDelta:      allocMemDelta,
   153  		uFIDelateMemDeltaGens: uFIDelateMemDeltaGens,
   154  	}
   155  	return pt
   156  }
   157  
   158  func buildWindowMemTesterWithArgs(funcName string, tp byte, args []memex.Expression, orderByDefCauss int, numEvents int, allocMemDelta int64, uFIDelateMemDeltaGens uFIDelateMemDeltaGens) windowMemTest {
   159  	windowTest := buildWindowTesterWithArgs(funcName, tp, args, orderByDefCauss, numEvents)
   160  	pt := windowMemTest{
   161  		windowTest:         windowTest,
   162  		allocMemDelta:      allocMemDelta,
   163  		uFIDelateMemDeltaGens: uFIDelateMemDeltaGens,
   164  	}
   165  	return pt
   166  }
   167  
   168  func (s *testSuite) TestWindowFunctions(c *C) {
   169  	tests := []windowTest{
   170  		buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 1, 1, 1),
   171  		buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 0, 2, 1, 1),
   172  		buildWindowTester(ast.WindowFuncCumeDist, allegrosql.TypeLonglong, 0, 1, 4, 0.25, 0.5, 0.75, 1),
   173  
   174  		buildWindowTester(ast.WindowFuncDenseRank, allegrosql.TypeLonglong, 0, 0, 2, 1, 1),
   175  		buildWindowTester(ast.WindowFuncDenseRank, allegrosql.TypeLonglong, 0, 1, 4, 1, 2, 3, 4),
   176  
   177  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeLonglong, 0, 1, 2, 0, 0),
   178  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeFloat, 0, 1, 2, 0, 0),
   179  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDouble, 0, 1, 2, 0, 0),
   180  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeNewDecimal, 0, 1, 2, types.NewDecFromInt(0), types.NewDecFromInt(0)),
   181  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeString, 0, 1, 2, "0", "0"),
   182  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDate, 0, 1, 2, types.TimeFromDays(365), types.TimeFromDays(365)),
   183  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeDuration, 0, 1, 2, types.Duration{Duration: time.Duration(0)}, types.Duration{Duration: time.Duration(0)}),
   184  		buildWindowTester(ast.WindowFuncFirstValue, allegrosql.TypeJSON, 0, 1, 2, json.CreateBinary(int64(0)), json.CreateBinary(int64(0))),
   185  
   186  		buildWindowTester(ast.WindowFuncLastValue, allegrosql.TypeLonglong, 1, 0, 2, 1, 1),
   187  
   188  		buildWindowTester(ast.WindowFuncNthValue, allegrosql.TypeLonglong, 2, 0, 3, 1, 1, 1),
   189  		buildWindowTester(ast.WindowFuncNthValue, allegrosql.TypeLonglong, 5, 0, 3, nil, nil, nil),
   190  
   191  		buildWindowTester(ast.WindowFuncNtile, allegrosql.TypeLonglong, 3, 0, 4, 1, 1, 2, 3),
   192  		buildWindowTester(ast.WindowFuncNtile, allegrosql.TypeLonglong, 5, 0, 3, 1, 2, 3),
   193  
   194  		buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 1, 1, 0),
   195  		buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 0, 3, 0, 0, 0),
   196  		buildWindowTester(ast.WindowFuncPercentRank, allegrosql.TypeLonglong, 0, 1, 4, 0, 0.3333333333333333, 0.6666666666666666, 1),
   197  
   198  		buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 1, 1, 1),
   199  		buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 0, 3, 1, 1, 1),
   200  		buildWindowTester(ast.WindowFuncRank, allegrosql.TypeLonglong, 0, 1, 4, 1, 2, 3, 4),
   201  
   202  		buildWindowTester(ast.WindowFuncEventNumber, allegrosql.TypeLonglong, 0, 0, 4, 1, 2, 3, 4),
   203  	}
   204  	for _, test := range tests {
   205  		s.testWindowFunc(c, test)
   206  	}
   207  }