github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/statistics/scalar_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 statistics
    15  
    16  import (
    17  	"math"
    18  
    19  	. "github.com/whtcorpsinc/check"
    20  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    21  	"github.com/whtcorpsinc/milevadb/types"
    22  )
    23  
    24  const eps = 1e-9
    25  
    26  func getDecimal(value float64) *types.MyDecimal {
    27  	dec := &types.MyDecimal{}
    28  	dec.FromFloat64(value)
    29  	return dec
    30  }
    31  
    32  func getDuration(value string) types.Duration {
    33  	dur, _ := types.ParseDuration(nil, value, 0)
    34  	return dur
    35  }
    36  
    37  func getTime(year, month, day int, timeType byte) types.Time {
    38  	ret := types.NewTime(types.FromDate(year, month, day, 0, 0, 0, 0), timeType, types.DefaultFsp)
    39  	return ret
    40  }
    41  
    42  func getTimeStamp(hour, min, sec int, timeType byte) types.Time {
    43  	ret := types.NewTime(types.FromDate(2020, 1, 1, hour, min, sec, 0), timeType, 0)
    44  	return ret
    45  }
    46  
    47  func getBinaryLiteral(value string) types.BinaryLiteral {
    48  	b, _ := types.ParseBitStr(value)
    49  	return b
    50  }
    51  
    52  func getUnsignedFieldType() *types.FieldType {
    53  	tp := types.NewFieldType(allegrosql.TypeLonglong)
    54  	tp.Flag |= allegrosql.UnsignedFlag
    55  	return tp
    56  }
    57  
    58  func (s *testStatisticsSuite) TestCalcFraction(c *C) {
    59  	tests := []struct {
    60  		lower    types.Causet
    61  		upper    types.Causet
    62  		value    types.Causet
    63  		fraction float64
    64  		tp       *types.FieldType
    65  	}{
    66  		{
    67  			lower:    types.NewIntCauset(0),
    68  			upper:    types.NewIntCauset(4),
    69  			value:    types.NewIntCauset(1),
    70  			fraction: 0.25,
    71  			tp:       types.NewFieldType(allegrosql.TypeLonglong),
    72  		},
    73  		{
    74  			lower:    types.NewIntCauset(0),
    75  			upper:    types.NewIntCauset(4),
    76  			value:    types.NewIntCauset(4),
    77  			fraction: 1,
    78  			tp:       types.NewFieldType(allegrosql.TypeLonglong),
    79  		},
    80  		{
    81  			lower:    types.NewIntCauset(0),
    82  			upper:    types.NewIntCauset(4),
    83  			value:    types.NewIntCauset(-1),
    84  			fraction: 0,
    85  			tp:       types.NewFieldType(allegrosql.TypeLonglong),
    86  		},
    87  		{
    88  			lower:    types.NewUintCauset(0),
    89  			upper:    types.NewUintCauset(4),
    90  			value:    types.NewUintCauset(1),
    91  			fraction: 0.25,
    92  			tp:       getUnsignedFieldType(),
    93  		},
    94  		{
    95  			lower:    types.NewFloat64Causet(0),
    96  			upper:    types.NewFloat64Causet(4),
    97  			value:    types.NewFloat64Causet(1),
    98  			fraction: 0.25,
    99  			tp:       types.NewFieldType(allegrosql.TypeDouble),
   100  		},
   101  		{
   102  			lower:    types.NewFloat32Causet(0),
   103  			upper:    types.NewFloat32Causet(4),
   104  			value:    types.NewFloat32Causet(1),
   105  			fraction: 0.25,
   106  			tp:       types.NewFieldType(allegrosql.TypeFloat),
   107  		},
   108  		{
   109  			lower:    types.NewDecimalCauset(getDecimal(0)),
   110  			upper:    types.NewDecimalCauset(getDecimal(4)),
   111  			value:    types.NewDecimalCauset(getDecimal(1)),
   112  			fraction: 0.25,
   113  			tp:       types.NewFieldType(allegrosql.TypeNewDecimal),
   114  		},
   115  		{
   116  			lower:    types.NewMysqlBitCauset(getBinaryLiteral("0b0")),
   117  			upper:    types.NewMysqlBitCauset(getBinaryLiteral("0b100")),
   118  			value:    types.NewMysqlBitCauset(getBinaryLiteral("0b1")),
   119  			fraction: 0.5,
   120  			tp:       types.NewFieldType(allegrosql.TypeBit),
   121  		},
   122  		{
   123  			lower:    types.NewDurationCauset(getDuration("0:00:00")),
   124  			upper:    types.NewDurationCauset(getDuration("4:00:00")),
   125  			value:    types.NewDurationCauset(getDuration("1:00:00")),
   126  			fraction: 0.25,
   127  			tp:       types.NewFieldType(allegrosql.TypeDuration),
   128  		},
   129  		{
   130  			lower:    types.NewTimeCauset(getTime(2020, 1, 1, allegrosql.TypeTimestamp)),
   131  			upper:    types.NewTimeCauset(getTime(2020, 4, 1, allegrosql.TypeTimestamp)),
   132  			value:    types.NewTimeCauset(getTime(2020, 2, 1, allegrosql.TypeTimestamp)),
   133  			fraction: 0.34444444444444444,
   134  			tp:       types.NewFieldType(allegrosql.TypeTimestamp),
   135  		},
   136  		{
   137  			lower:    types.NewTimeCauset(getTime(2020, 1, 1, allegrosql.TypeDatetime)),
   138  			upper:    types.NewTimeCauset(getTime(2020, 4, 1, allegrosql.TypeDatetime)),
   139  			value:    types.NewTimeCauset(getTime(2020, 2, 1, allegrosql.TypeDatetime)),
   140  			fraction: 0.34444444444444444,
   141  			tp:       types.NewFieldType(allegrosql.TypeDatetime),
   142  		},
   143  		{
   144  			lower:    types.NewTimeCauset(getTime(2020, 1, 1, allegrosql.TypeDate)),
   145  			upper:    types.NewTimeCauset(getTime(2020, 4, 1, allegrosql.TypeDate)),
   146  			value:    types.NewTimeCauset(getTime(2020, 2, 1, allegrosql.TypeDate)),
   147  			fraction: 0.34444444444444444,
   148  			tp:       types.NewFieldType(allegrosql.TypeDate),
   149  		},
   150  		{
   151  			lower:    types.NewStringCauset("aasad"),
   152  			upper:    types.NewStringCauset("addad"),
   153  			value:    types.NewStringCauset("abfsd"),
   154  			fraction: 0.32280253984063745,
   155  			tp:       types.NewFieldType(allegrosql.TypeString),
   156  		},
   157  		{
   158  			lower:    types.NewBytesCauset([]byte("aasad")),
   159  			upper:    types.NewBytesCauset([]byte("asdff")),
   160  			value:    types.NewBytesCauset([]byte("abfsd")),
   161  			fraction: 0.0529216802217269,
   162  			tp:       types.NewFieldType(allegrosql.TypeBlob),
   163  		},
   164  	}
   165  	for _, test := range tests {
   166  		hg := NewHistogram(0, 0, 0, 0, test.tp, 1, 0)
   167  		hg.AppendBucket(&test.lower, &test.upper, 0, 0)
   168  		hg.PreCalculateScalar()
   169  		fraction := hg.calcFraction(0, &test.value)
   170  		c.Check(math.Abs(fraction-test.fraction) < eps, IsTrue)
   171  	}
   172  }
   173  
   174  func (s *testStatisticsSuite) TestEnumRangeValues(c *C) {
   175  	tests := []struct {
   176  		low         types.Causet
   177  		high        types.Causet
   178  		lowExclude  bool
   179  		highExclude bool
   180  		res         string
   181  	}{
   182  		{
   183  			low:         types.NewIntCauset(0),
   184  			high:        types.NewIntCauset(5),
   185  			lowExclude:  false,
   186  			highExclude: true,
   187  			res:         "(0, 1, 2, 3, 4)",
   188  		},
   189  		{
   190  			low:         types.NewIntCauset(math.MinInt64),
   191  			high:        types.NewIntCauset(math.MaxInt64),
   192  			lowExclude:  false,
   193  			highExclude: false,
   194  			res:         "",
   195  		},
   196  		{
   197  			low:         types.NewUintCauset(0),
   198  			high:        types.NewUintCauset(5),
   199  			lowExclude:  false,
   200  			highExclude: true,
   201  			res:         "(0, 1, 2, 3, 4)",
   202  		},
   203  		{
   204  			low:         types.NewDurationCauset(getDuration("0:00:00")),
   205  			high:        types.NewDurationCauset(getDuration("0:00:05")),
   206  			lowExclude:  false,
   207  			highExclude: true,
   208  			res:         "(00:00:00, 00:00:01, 00:00:02, 00:00:03, 00:00:04)",
   209  		},
   210  		{
   211  			low:         types.NewDurationCauset(getDuration("0:00:00")),
   212  			high:        types.NewDurationCauset(getDuration("0:00:05")),
   213  			lowExclude:  false,
   214  			highExclude: true,
   215  			res:         "(00:00:00, 00:00:01, 00:00:02, 00:00:03, 00:00:04)",
   216  		},
   217  		{
   218  			low:         types.NewTimeCauset(getTime(2020, 1, 1, allegrosql.TypeDate)),
   219  			high:        types.NewTimeCauset(getTime(2020, 1, 5, allegrosql.TypeDate)),
   220  			lowExclude:  false,
   221  			highExclude: true,
   222  			res:         "(2020-01-01, 2020-01-02, 2020-01-03, 2020-01-04)",
   223  		},
   224  		{
   225  			low:         types.NewTimeCauset(getTimeStamp(0, 0, 0, allegrosql.TypeTimestamp)),
   226  			high:        types.NewTimeCauset(getTimeStamp(0, 0, 5, allegrosql.TypeTimestamp)),
   227  			lowExclude:  false,
   228  			highExclude: true,
   229  			res:         "(2020-01-01 00:00:00, 2020-01-01 00:00:01, 2020-01-01 00:00:02, 2020-01-01 00:00:03, 2020-01-01 00:00:04)",
   230  		},
   231  		{
   232  			low:         types.NewTimeCauset(getTimeStamp(0, 0, 0, allegrosql.TypeDatetime)),
   233  			high:        types.NewTimeCauset(getTimeStamp(0, 0, 5, allegrosql.TypeDatetime)),
   234  			lowExclude:  false,
   235  			highExclude: true,
   236  			res:         "(2020-01-01 00:00:00, 2020-01-01 00:00:01, 2020-01-01 00:00:02, 2020-01-01 00:00:03, 2020-01-01 00:00:04)",
   237  		},
   238  		// fix issue 11610
   239  		{
   240  			low:         types.NewIntCauset(math.MinInt64),
   241  			high:        types.NewIntCauset(0),
   242  			lowExclude:  false,
   243  			highExclude: false,
   244  			res:         "",
   245  		},
   246  	}
   247  	for _, t := range tests {
   248  		vals := enumRangeValues(t.low, t.high, t.lowExclude, t.highExclude)
   249  		str, err := types.CausetsToString(vals, true)
   250  		c.Assert(err, IsNil)
   251  		c.Assert(str, Equals, t.res)
   252  	}
   253  }