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 }