github.com/XiaoMi/Gaea@v1.2.5/parser/tidb-types/field_type_test.go (about) 1 // Copyright 2015 PingCAP, 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 types 15 16 import ( 17 . "github.com/pingcap/check" 18 19 "github.com/XiaoMi/Gaea/mysql" 20 "github.com/XiaoMi/Gaea/util/testleak" 21 ) 22 23 var _ = Suite(&testFieldTypeSuite{}) 24 25 type testFieldTypeSuite struct { 26 } 27 28 func (s *testFieldTypeSuite) TestFieldType(c *C) { 29 defer testleak.AfterTest(c)() 30 ft := NewFieldType(mysql.TypeDuration) 31 c.Assert(ft.Flen, Equals, UnspecifiedLength) 32 c.Assert(ft.Decimal, Equals, UnspecifiedLength) 33 ft.Decimal = 5 34 c.Assert(ft.String(), Equals, "time(5)") 35 36 ft = NewFieldType(mysql.TypeLong) 37 ft.Flen = 5 38 ft.Flag = mysql.UnsignedFlag | mysql.ZerofillFlag 39 c.Assert(ft.String(), Equals, "int(5) UNSIGNED ZEROFILL") 40 c.Assert(ft.InfoSchemaStr(), Equals, "int(5) unsigned") 41 42 ft = NewFieldType(mysql.TypeFloat) 43 ft.Flen = 12 // Default 44 ft.Decimal = 3 // Not Default 45 c.Assert(ft.String(), Equals, "float(12,3)") 46 ft = NewFieldType(mysql.TypeFloat) 47 ft.Flen = 12 // Default 48 ft.Decimal = -1 // Default 49 c.Assert(ft.String(), Equals, "float") 50 ft = NewFieldType(mysql.TypeFloat) 51 ft.Flen = 5 // Not Default 52 ft.Decimal = -1 // Default 53 c.Assert(ft.String(), Equals, "float") 54 ft = NewFieldType(mysql.TypeFloat) 55 ft.Flen = 7 // Not Default 56 ft.Decimal = 3 // Not Default 57 c.Assert(ft.String(), Equals, "float(7,3)") 58 59 ft = NewFieldType(mysql.TypeDouble) 60 ft.Flen = 22 // Default 61 ft.Decimal = 3 // Not Default 62 c.Assert(ft.String(), Equals, "double(22,3)") 63 ft = NewFieldType(mysql.TypeDouble) 64 ft.Flen = 22 // Default 65 ft.Decimal = -1 // Default 66 c.Assert(ft.String(), Equals, "double") 67 ft = NewFieldType(mysql.TypeDouble) 68 ft.Flen = 5 // Not Default 69 ft.Decimal = -1 // Default 70 c.Assert(ft.String(), Equals, "double") 71 ft = NewFieldType(mysql.TypeDouble) 72 ft.Flen = 7 // Not Default 73 ft.Decimal = 3 // Not Default 74 c.Assert(ft.String(), Equals, "double(7,3)") 75 76 ft = NewFieldType(mysql.TypeBlob) 77 ft.Flen = 10 78 ft.Charset = "UTF8" 79 ft.Collate = "UTF8_UNICODE_GI" 80 c.Assert(ft.String(), Equals, "text CHARACTER SET UTF8 COLLATE UTF8_UNICODE_GI") 81 82 ft = NewFieldType(mysql.TypeVarchar) 83 ft.Flen = 10 84 ft.Flag |= mysql.BinaryFlag 85 c.Assert(ft.String(), Equals, "varchar(10) BINARY") 86 87 ft = NewFieldType(mysql.TypeString) 88 ft.Charset = mysql.CollationBin 89 ft.Flag |= mysql.BinaryFlag 90 c.Assert(ft.String(), Equals, "binary(1)") 91 92 ft = NewFieldType(mysql.TypeEnum) 93 ft.Elems = []string{"a", "b"} 94 c.Assert(ft.String(), Equals, "enum('a','b')") 95 96 ft = NewFieldType(mysql.TypeEnum) 97 ft.Elems = []string{"'a'", "'b'"} 98 c.Assert(ft.String(), Equals, "enum('''a''','''b''')") 99 100 ft = NewFieldType(mysql.TypeEnum) 101 ft.Elems = []string{"a\nb", "a\tb", "a\rb"} 102 c.Assert(ft.String(), Equals, "enum('a\\nb','a\tb','a\\rb')") 103 104 ft = NewFieldType(mysql.TypeEnum) 105 ft.Elems = []string{"a\nb", "a'\t\r\nb", "a\rb"} 106 c.Assert(ft.String(), Equals, "enum('a\\nb','a'' \\r\\nb','a\\rb')") 107 108 ft = NewFieldType(mysql.TypeSet) 109 ft.Elems = []string{"a", "b"} 110 c.Assert(ft.String(), Equals, "set('a','b')") 111 112 ft = NewFieldType(mysql.TypeSet) 113 ft.Elems = []string{"'a'", "'b'"} 114 c.Assert(ft.String(), Equals, "set('''a''','''b''')") 115 116 ft = NewFieldType(mysql.TypeSet) 117 ft.Elems = []string{"a\nb", "a'\t\r\nb", "a\rb"} 118 c.Assert(ft.String(), Equals, "set('a\\nb','a'' \\r\\nb','a\\rb')") 119 120 ft = NewFieldType(mysql.TypeSet) 121 ft.Elems = []string{"a'\nb", "a'b\tc"} 122 c.Assert(ft.String(), Equals, "set('a''\\nb','a''b c')") 123 124 ft = NewFieldType(mysql.TypeTimestamp) 125 ft.Flen = 8 126 ft.Decimal = 2 127 c.Assert(ft.String(), Equals, "timestamp(2)") 128 ft = NewFieldType(mysql.TypeTimestamp) 129 ft.Flen = 8 130 ft.Decimal = 0 131 c.Assert(ft.String(), Equals, "timestamp") 132 133 ft = NewFieldType(mysql.TypeDatetime) 134 ft.Flen = 8 135 ft.Decimal = 2 136 c.Assert(ft.String(), Equals, "datetime(2)") 137 ft = NewFieldType(mysql.TypeDatetime) 138 ft.Flen = 8 139 ft.Decimal = 0 140 c.Assert(ft.String(), Equals, "datetime") 141 142 ft = NewFieldType(mysql.TypeDate) 143 ft.Flen = 8 144 ft.Decimal = 2 145 c.Assert(ft.String(), Equals, "date") 146 ft = NewFieldType(mysql.TypeDate) 147 ft.Flen = 8 148 ft.Decimal = 0 149 c.Assert(ft.String(), Equals, "date") 150 151 ft = NewFieldType(mysql.TypeYear) 152 ft.Flen = 4 153 ft.Decimal = 0 154 c.Assert(ft.String(), Equals, "year") 155 ft = NewFieldType(mysql.TypeYear) 156 ft.Flen = 2 157 ft.Decimal = 2 158 c.Assert(ft.String(), Equals, "year") // Note: Invalid year. 159 } 160 161 func (s *testFieldTypeSuite) TestDefaultTypeForValue(c *C) { 162 defer testleak.AfterTest(c)() 163 tests := []struct { 164 value interface{} 165 tp byte 166 flen int 167 decimal int 168 charset string 169 collation string 170 flag uint 171 }{ 172 {nil, mysql.TypeNull, 0, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 173 {1, mysql.TypeLonglong, 1, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 174 {uint64(1), mysql.TypeLonglong, 1, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag}, 175 {"abc", mysql.TypeVarString, 3, UnspecifiedLength, mysql.CharsetUTF8MB4, mysql.CollationUTF8MB4, 0}, 176 {1.1, mysql.TypeDouble, 3, -1, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 177 {[]byte("abc"), mysql.TypeBlob, 3, UnspecifiedLength, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 178 {HexLiteral{}, mysql.TypeVarString, 0, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag | mysql.UnsignedFlag}, 179 {BitLiteral{}, mysql.TypeVarString, 0, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 180 {Time{Type: mysql.TypeDatetime}, mysql.TypeDatetime, 19, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 181 {Time{ 182 Time: FromDate(2017, 12, 12, 12, 59, 59, 0), 183 Type: mysql.TypeDatetime, 184 Fsp: 3}, mysql.TypeDatetime, 23, 3, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 185 {Duration{}, mysql.TypeDuration, 8, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 186 {&MyDecimal{}, mysql.TypeNewDecimal, 1, 0, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 187 {Enum{Name: "a", Value: 1}, mysql.TypeEnum, 1, UnspecifiedLength, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 188 {Set{Name: "a", Value: 1}, mysql.TypeSet, 1, UnspecifiedLength, mysql.CharsetBin, mysql.CharsetBin, mysql.BinaryFlag}, 189 } 190 for _, tt := range tests { 191 var ft FieldType 192 DefaultTypeForValue(tt.value, &ft) 193 c.Assert(ft.Tp, Equals, tt.tp, Commentf("%v %v", ft.Tp, tt.tp)) 194 c.Assert(ft.Flen, Equals, tt.flen, Commentf("%v %v", ft.Flen, tt.flen)) 195 c.Assert(ft.Charset, Equals, tt.charset, Commentf("%v %v", ft.Charset, tt.charset)) 196 c.Assert(ft.Decimal, Equals, tt.decimal, Commentf("%v %v", ft.Decimal, tt.decimal)) 197 c.Assert(ft.Collate, Equals, tt.collation, Commentf("%v %v", ft.Collate, tt.collation)) 198 c.Assert(ft.Flag, Equals, tt.flag, Commentf("%v %v", ft.Flag, tt.flag)) 199 } 200 } 201 202 func (s *testFieldTypeSuite) TestAggFieldType(c *C) { 203 defer testleak.AfterTest(c)() 204 fts := []*FieldType{ 205 NewFieldType(mysql.TypeDecimal), 206 NewFieldType(mysql.TypeTiny), 207 NewFieldType(mysql.TypeShort), 208 NewFieldType(mysql.TypeLong), 209 NewFieldType(mysql.TypeFloat), 210 NewFieldType(mysql.TypeDouble), 211 NewFieldType(mysql.TypeNull), 212 NewFieldType(mysql.TypeTimestamp), 213 NewFieldType(mysql.TypeLonglong), 214 NewFieldType(mysql.TypeInt24), 215 NewFieldType(mysql.TypeDate), 216 NewFieldType(mysql.TypeDuration), 217 NewFieldType(mysql.TypeDatetime), 218 NewFieldType(mysql.TypeYear), 219 NewFieldType(mysql.TypeNewDate), 220 NewFieldType(mysql.TypeVarchar), 221 NewFieldType(mysql.TypeBit), 222 NewFieldType(mysql.TypeJSON), 223 NewFieldType(mysql.TypeNewDecimal), 224 NewFieldType(mysql.TypeEnum), 225 NewFieldType(mysql.TypeSet), 226 NewFieldType(mysql.TypeTinyBlob), 227 NewFieldType(mysql.TypeMediumBlob), 228 NewFieldType(mysql.TypeLongBlob), 229 NewFieldType(mysql.TypeBlob), 230 NewFieldType(mysql.TypeVarString), 231 NewFieldType(mysql.TypeString), 232 NewFieldType(mysql.TypeGeometry), 233 } 234 235 for i := range fts { 236 aggTp := AggFieldType(fts[i : i+1]) 237 c.Assert(aggTp.Tp, Equals, fts[i].Tp) 238 239 aggTp = AggFieldType([]*FieldType{fts[i], fts[i]}) 240 switch fts[i].Tp { 241 case mysql.TypeDate: 242 c.Assert(aggTp.Tp, Equals, mysql.TypeDate) 243 case mysql.TypeJSON: 244 c.Assert(aggTp.Tp, Equals, mysql.TypeJSON) 245 case mysql.TypeEnum, mysql.TypeSet, mysql.TypeVarString: 246 c.Assert(aggTp.Tp, Equals, mysql.TypeVarchar) 247 case mysql.TypeDecimal: 248 c.Assert(aggTp.Tp, Equals, mysql.TypeNewDecimal) 249 default: 250 c.Assert(aggTp.Tp, Equals, fts[i].Tp) 251 } 252 253 aggTp = AggFieldType([]*FieldType{fts[i], NewFieldType(mysql.TypeLong)}) 254 switch fts[i].Tp { 255 case mysql.TypeTiny, mysql.TypeShort, mysql.TypeLong, 256 mysql.TypeYear, mysql.TypeInt24, mysql.TypeNull: 257 c.Assert(aggTp.Tp, Equals, mysql.TypeLong) 258 case mysql.TypeLonglong: 259 c.Assert(aggTp.Tp, Equals, mysql.TypeLonglong) 260 case mysql.TypeFloat, mysql.TypeDouble: 261 c.Assert(aggTp.Tp, Equals, mysql.TypeDouble) 262 case mysql.TypeTimestamp, mysql.TypeDate, mysql.TypeDuration, 263 mysql.TypeDatetime, mysql.TypeNewDate, mysql.TypeVarchar, 264 mysql.TypeBit, mysql.TypeJSON, mysql.TypeEnum, mysql.TypeSet, 265 mysql.TypeVarString, mysql.TypeGeometry: 266 c.Assert(aggTp.Tp, Equals, mysql.TypeVarchar) 267 case mysql.TypeString: 268 c.Assert(aggTp.Tp, Equals, mysql.TypeString) 269 case mysql.TypeDecimal, mysql.TypeNewDecimal: 270 c.Assert(aggTp.Tp, Equals, mysql.TypeNewDecimal) 271 case mysql.TypeTinyBlob: 272 c.Assert(aggTp.Tp, Equals, mysql.TypeTinyBlob) 273 case mysql.TypeBlob: 274 c.Assert(aggTp.Tp, Equals, mysql.TypeBlob) 275 case mysql.TypeMediumBlob: 276 c.Assert(aggTp.Tp, Equals, mysql.TypeMediumBlob) 277 case mysql.TypeLongBlob: 278 c.Assert(aggTp.Tp, Equals, mysql.TypeLongBlob) 279 } 280 281 aggTp = AggFieldType([]*FieldType{fts[i], NewFieldType(mysql.TypeJSON)}) 282 switch fts[i].Tp { 283 case mysql.TypeJSON, mysql.TypeNull: 284 c.Assert(aggTp.Tp, Equals, mysql.TypeJSON) 285 case mysql.TypeLongBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeBlob: 286 c.Assert(aggTp.Tp, Equals, mysql.TypeLongBlob) 287 case mysql.TypeString: 288 c.Assert(aggTp.Tp, Equals, mysql.TypeString) 289 default: 290 c.Assert(aggTp.Tp, Equals, mysql.TypeVarchar) 291 } 292 } 293 } 294 295 func (s *testFieldTypeSuite) TestAggregateEvalType(c *C) { 296 defer testleak.AfterTest(c)() 297 fts := []*FieldType{ 298 NewFieldType(mysql.TypeDecimal), 299 NewFieldType(mysql.TypeTiny), 300 NewFieldType(mysql.TypeShort), 301 NewFieldType(mysql.TypeLong), 302 NewFieldType(mysql.TypeFloat), 303 NewFieldType(mysql.TypeDouble), 304 NewFieldType(mysql.TypeNull), 305 NewFieldType(mysql.TypeTimestamp), 306 NewFieldType(mysql.TypeLonglong), 307 NewFieldType(mysql.TypeInt24), 308 NewFieldType(mysql.TypeDate), 309 NewFieldType(mysql.TypeDuration), 310 NewFieldType(mysql.TypeDatetime), 311 NewFieldType(mysql.TypeYear), 312 NewFieldType(mysql.TypeNewDate), 313 NewFieldType(mysql.TypeVarchar), 314 NewFieldType(mysql.TypeBit), 315 NewFieldType(mysql.TypeJSON), 316 NewFieldType(mysql.TypeNewDecimal), 317 NewFieldType(mysql.TypeEnum), 318 NewFieldType(mysql.TypeSet), 319 NewFieldType(mysql.TypeTinyBlob), 320 NewFieldType(mysql.TypeMediumBlob), 321 NewFieldType(mysql.TypeLongBlob), 322 NewFieldType(mysql.TypeBlob), 323 NewFieldType(mysql.TypeVarString), 324 NewFieldType(mysql.TypeString), 325 NewFieldType(mysql.TypeGeometry), 326 } 327 328 for i := range fts { 329 var flag uint 330 aggregatedEvalType := AggregateEvalType(fts[i:i+1], &flag) 331 switch fts[i].Tp { 332 case mysql.TypeDecimal, mysql.TypeNull, mysql.TypeTimestamp, mysql.TypeDate, 333 mysql.TypeDuration, mysql.TypeDatetime, mysql.TypeNewDate, mysql.TypeVarchar, 334 mysql.TypeJSON, mysql.TypeEnum, mysql.TypeSet, mysql.TypeTinyBlob, 335 mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeBlob, 336 mysql.TypeVarString, mysql.TypeString, mysql.TypeGeometry: 337 c.Assert(aggregatedEvalType.IsStringKind(), IsTrue) 338 c.Assert(flag, Equals, uint(0)) 339 case mysql.TypeTiny, mysql.TypeShort, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeBit, 340 mysql.TypeInt24, mysql.TypeYear: 341 c.Assert(aggregatedEvalType, Equals, ETInt) 342 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 343 case mysql.TypeFloat, mysql.TypeDouble: 344 c.Assert(aggregatedEvalType, Equals, ETReal) 345 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 346 case mysql.TypeNewDecimal: 347 c.Assert(aggregatedEvalType, Equals, ETDecimal) 348 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 349 } 350 351 flag = 0 352 aggregatedEvalType = AggregateEvalType([]*FieldType{fts[i], fts[i]}, &flag) 353 switch fts[i].Tp { 354 case mysql.TypeDecimal, mysql.TypeNull, mysql.TypeTimestamp, mysql.TypeDate, 355 mysql.TypeDuration, mysql.TypeDatetime, mysql.TypeNewDate, mysql.TypeVarchar, 356 mysql.TypeJSON, mysql.TypeEnum, mysql.TypeSet, mysql.TypeTinyBlob, 357 mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeBlob, 358 mysql.TypeVarString, mysql.TypeString, mysql.TypeGeometry: 359 c.Assert(aggregatedEvalType.IsStringKind(), IsTrue) 360 c.Assert(flag, Equals, uint(0)) 361 case mysql.TypeTiny, mysql.TypeShort, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeBit, 362 mysql.TypeInt24, mysql.TypeYear: 363 c.Assert(aggregatedEvalType, Equals, ETInt) 364 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 365 case mysql.TypeFloat, mysql.TypeDouble: 366 c.Assert(aggregatedEvalType, Equals, ETReal) 367 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 368 case mysql.TypeNewDecimal: 369 c.Assert(aggregatedEvalType, Equals, ETDecimal) 370 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 371 } 372 flag = 0 373 aggregatedEvalType = AggregateEvalType([]*FieldType{fts[i], NewFieldType(mysql.TypeLong)}, &flag) 374 switch fts[i].Tp { 375 case mysql.TypeTimestamp, mysql.TypeDate, mysql.TypeDuration, 376 mysql.TypeDatetime, mysql.TypeNewDate, mysql.TypeVarchar, mysql.TypeJSON, 377 mysql.TypeEnum, mysql.TypeSet, mysql.TypeTinyBlob, mysql.TypeMediumBlob, 378 mysql.TypeLongBlob, mysql.TypeBlob, mysql.TypeVarString, 379 mysql.TypeString, mysql.TypeGeometry: 380 c.Assert(aggregatedEvalType.IsStringKind(), IsTrue) 381 c.Assert(flag, Equals, uint(0)) 382 case mysql.TypeDecimal, mysql.TypeTiny, mysql.TypeShort, mysql.TypeLong, mysql.TypeNull, mysql.TypeBit, 383 mysql.TypeLonglong, mysql.TypeYear, mysql.TypeInt24: 384 c.Assert(aggregatedEvalType, Equals, ETInt) 385 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 386 case mysql.TypeFloat, mysql.TypeDouble: 387 c.Assert(aggregatedEvalType, Equals, ETReal) 388 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 389 case mysql.TypeNewDecimal: 390 c.Assert(aggregatedEvalType, Equals, ETDecimal) 391 c.Assert(flag, Equals, uint(mysql.BinaryFlag)) 392 } 393 } 394 }