vitess.io/vitess@v0.16.2/go/sqltypes/type_test.go (about) 1 /* 2 Copyright 2019 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package sqltypes 18 19 import ( 20 "strings" 21 "testing" 22 23 querypb "vitess.io/vitess/go/vt/proto/query" 24 ) 25 26 func TestTypeValues(t *testing.T) { 27 testcases := []struct { 28 defined querypb.Type 29 expected int 30 }{{ 31 defined: Null, 32 expected: 0, 33 }, { 34 defined: Int8, 35 expected: 1 | flagIsIntegral, 36 }, { 37 defined: Uint8, 38 expected: 2 | flagIsIntegral | flagIsUnsigned, 39 }, { 40 defined: Int16, 41 expected: 3 | flagIsIntegral, 42 }, { 43 defined: Uint16, 44 expected: 4 | flagIsIntegral | flagIsUnsigned, 45 }, { 46 defined: Int24, 47 expected: 5 | flagIsIntegral, 48 }, { 49 defined: Uint24, 50 expected: 6 | flagIsIntegral | flagIsUnsigned, 51 }, { 52 defined: Int32, 53 expected: 7 | flagIsIntegral, 54 }, { 55 defined: Uint32, 56 expected: 8 | flagIsIntegral | flagIsUnsigned, 57 }, { 58 defined: Int64, 59 expected: 9 | flagIsIntegral, 60 }, { 61 defined: Uint64, 62 expected: 10 | flagIsIntegral | flagIsUnsigned, 63 }, { 64 defined: Float32, 65 expected: 11 | flagIsFloat, 66 }, { 67 defined: Float64, 68 expected: 12 | flagIsFloat, 69 }, { 70 defined: Timestamp, 71 expected: 13 | flagIsQuoted, 72 }, { 73 defined: Date, 74 expected: 14 | flagIsQuoted, 75 }, { 76 defined: Time, 77 expected: 15 | flagIsQuoted, 78 }, { 79 defined: Datetime, 80 expected: 16 | flagIsQuoted, 81 }, { 82 defined: Year, 83 expected: 17 | flagIsIntegral | flagIsUnsigned, 84 }, { 85 defined: Decimal, 86 expected: 18, 87 }, { 88 defined: Text, 89 expected: 19 | flagIsQuoted | flagIsText, 90 }, { 91 defined: Blob, 92 expected: 20 | flagIsQuoted | flagIsBinary, 93 }, { 94 defined: VarChar, 95 expected: 21 | flagIsQuoted | flagIsText, 96 }, { 97 defined: VarBinary, 98 expected: 22 | flagIsQuoted | flagIsBinary, 99 }, { 100 defined: Char, 101 expected: 23 | flagIsQuoted | flagIsText, 102 }, { 103 defined: Binary, 104 expected: 24 | flagIsQuoted | flagIsBinary, 105 }, { 106 defined: Bit, 107 expected: 25 | flagIsQuoted, 108 }, { 109 defined: Enum, 110 expected: 26 | flagIsQuoted, 111 }, { 112 defined: Set, 113 expected: 27 | flagIsQuoted, 114 }, { 115 defined: Geometry, 116 expected: 29 | flagIsQuoted, 117 }, { 118 defined: TypeJSON, 119 expected: 30 | flagIsQuoted, 120 }, { 121 defined: Expression, 122 expected: 31, 123 }, { 124 defined: HexNum, 125 expected: 32 | flagIsText, 126 }, { 127 defined: HexVal, 128 expected: 33 | flagIsText, 129 }, { 130 defined: BitNum, 131 expected: 34 | flagIsText, 132 }} 133 for _, tcase := range testcases { 134 if int(tcase.defined) != tcase.expected { 135 t.Errorf("Type %s: %d, want: %d", tcase.defined, int(tcase.defined), tcase.expected) 136 } 137 } 138 } 139 140 // TestCategory verifies that the type categorizations 141 // are non-overlapping and complete. 142 func TestCategory(t *testing.T) { 143 alltypes := []querypb.Type{ 144 Null, 145 Int8, 146 Uint8, 147 Int16, 148 Uint16, 149 Int24, 150 Uint24, 151 Int32, 152 Uint32, 153 Int64, 154 Uint64, 155 Float32, 156 Float64, 157 Timestamp, 158 Date, 159 Time, 160 Datetime, 161 Year, 162 Decimal, 163 Text, 164 Blob, 165 VarChar, 166 VarBinary, 167 Char, 168 Binary, 169 Bit, 170 Enum, 171 Set, 172 Geometry, 173 TypeJSON, 174 Expression, 175 HexNum, 176 HexVal, 177 BitNum, 178 } 179 for _, typ := range alltypes { 180 matched := false 181 if IsSigned(typ) { 182 if !IsIntegral(typ) { 183 t.Errorf("Signed type %v is not an integral", typ) 184 } 185 matched = true 186 } 187 if IsUnsigned(typ) { 188 if !IsIntegral(typ) { 189 t.Errorf("Unsigned type %v is not an integral", typ) 190 } 191 if matched { 192 t.Errorf("%v matched more than one category", typ) 193 } 194 matched = true 195 } 196 if IsFloat(typ) { 197 if matched { 198 t.Errorf("%v matched more than one category", typ) 199 } 200 matched = true 201 } 202 if IsQuoted(typ) { 203 if matched { 204 t.Errorf("%v matched more than one category", typ) 205 } 206 matched = true 207 } 208 if typ == Null || typ == Decimal || typ == Expression || typ == Bit || 209 typ == HexNum || typ == HexVal || typ == BitNum { 210 if matched { 211 t.Errorf("%v matched more than one category", typ) 212 } 213 matched = true 214 } 215 if !matched { 216 t.Errorf("%v matched no category", typ) 217 } 218 } 219 } 220 221 func TestIsFunctions(t *testing.T) { 222 if IsIntegral(Null) { 223 t.Error("Null: IsIntegral, must be false") 224 } 225 if !IsIntegral(Int64) { 226 t.Error("Int64: !IsIntegral, must be true") 227 } 228 if IsSigned(Uint64) { 229 t.Error("Uint64: IsSigned, must be false") 230 } 231 if !IsSigned(Int64) { 232 t.Error("Int64: !IsSigned, must be true") 233 } 234 if IsUnsigned(Int64) { 235 t.Error("Int64: IsUnsigned, must be false") 236 } 237 if !IsUnsigned(Uint64) { 238 t.Error("Uint64: !IsUnsigned, must be true") 239 } 240 if IsFloat(Int64) { 241 t.Error("Int64: IsFloat, must be false") 242 } 243 if !IsFloat(Float64) { 244 t.Error("Uint64: !IsFloat, must be true") 245 } 246 if IsQuoted(Int64) { 247 t.Error("Int64: IsQuoted, must be false") 248 } 249 if !IsQuoted(Binary) { 250 t.Error("Binary: !IsQuoted, must be true") 251 } 252 if IsText(Int64) { 253 t.Error("Int64: IsText, must be false") 254 } 255 if !IsText(Char) { 256 t.Error("Char: !IsText, must be true") 257 } 258 if IsBinary(Int64) { 259 t.Error("Int64: IsBinary, must be false") 260 } 261 if !IsBinary(Binary) { 262 t.Error("Char: !IsBinary, must be true") 263 } 264 if !IsNumber(Int64) { 265 t.Error("Int64: !isNumber, must be true") 266 } 267 } 268 269 func TestTypeToMySQL(t *testing.T) { 270 v, f := TypeToMySQL(Bit) 271 if v != 16 { 272 t.Errorf("Bit: %d, want 16", v) 273 } 274 if f != mysqlUnsigned { 275 t.Errorf("Bit flag: %x, want %x", f, mysqlUnsigned) 276 } 277 v, f = TypeToMySQL(Date) 278 if v != 10 { 279 t.Errorf("Bit: %d, want 10", v) 280 } 281 if f != mysqlBinary { 282 t.Errorf("Bit flag: %x, want %x", f, mysqlBinary) 283 } 284 } 285 286 func TestMySQLToType(t *testing.T) { 287 testcases := []struct { 288 intype int64 289 inflags int64 290 outtype querypb.Type 291 }{{ 292 intype: 1, 293 outtype: Int8, 294 }, { 295 intype: 1, 296 inflags: mysqlUnsigned, 297 outtype: Uint8, 298 }, { 299 intype: 2, 300 outtype: Int16, 301 }, { 302 intype: 2, 303 inflags: mysqlUnsigned, 304 outtype: Uint16, 305 }, { 306 intype: 3, 307 outtype: Int32, 308 }, { 309 intype: 3, 310 inflags: mysqlUnsigned, 311 outtype: Uint32, 312 }, { 313 intype: 4, 314 outtype: Float32, 315 }, { 316 intype: 5, 317 outtype: Float64, 318 }, { 319 intype: 6, 320 outtype: Null, 321 }, { 322 intype: 7, 323 outtype: Timestamp, 324 }, { 325 intype: 8, 326 outtype: Int64, 327 }, { 328 intype: 8, 329 inflags: mysqlUnsigned, 330 outtype: Uint64, 331 }, { 332 intype: 9, 333 outtype: Int24, 334 }, { 335 intype: 9, 336 inflags: mysqlUnsigned, 337 outtype: Uint24, 338 }, { 339 intype: 10, 340 outtype: Date, 341 }, { 342 intype: 11, 343 outtype: Time, 344 }, { 345 intype: 12, 346 outtype: Datetime, 347 }, { 348 intype: 13, 349 outtype: Year, 350 }, { 351 intype: 16, 352 outtype: Bit, 353 }, { 354 intype: 245, 355 outtype: TypeJSON, 356 }, { 357 intype: 246, 358 outtype: Decimal, 359 }, { 360 intype: 249, 361 outtype: Text, 362 }, { 363 intype: 250, 364 outtype: Text, 365 }, { 366 intype: 251, 367 outtype: Text, 368 }, { 369 intype: 252, 370 outtype: Text, 371 }, { 372 intype: 252, 373 inflags: mysqlBinary, 374 outtype: Blob, 375 }, { 376 intype: 253, 377 outtype: VarChar, 378 }, { 379 intype: 253, 380 inflags: mysqlBinary, 381 outtype: VarBinary, 382 }, { 383 intype: 254, 384 outtype: Char, 385 }, { 386 intype: 254, 387 inflags: mysqlBinary, 388 outtype: Binary, 389 }, { 390 intype: 254, 391 inflags: mysqlEnum, 392 outtype: Enum, 393 }, { 394 intype: 254, 395 inflags: mysqlSet, 396 outtype: Set, 397 }, { 398 intype: 255, 399 outtype: Geometry, 400 }, { 401 // Binary flag must be ignored. 402 intype: 8, 403 inflags: mysqlUnsigned | mysqlBinary, 404 outtype: Uint64, 405 }, { 406 // Unsigned flag must be ignored 407 intype: 252, 408 inflags: mysqlUnsigned | mysqlBinary, 409 outtype: Blob, 410 }} 411 for _, tcase := range testcases { 412 got, err := MySQLToType(tcase.intype, tcase.inflags) 413 if err != nil { 414 t.Error(err) 415 } 416 if got != tcase.outtype { 417 t.Errorf("MySQLToType(%d, %x): %v, want %v", tcase.intype, tcase.inflags, got, tcase.outtype) 418 } 419 } 420 } 421 422 func TestTypeError(t *testing.T) { 423 _, err := MySQLToType(50, 0) 424 want := "unsupported type: 50" 425 if err == nil || err.Error() != want { 426 t.Errorf("MySQLToType: %v, want %s", err, want) 427 } 428 } 429 430 func TestTypeEquivalenceCheck(t *testing.T) { 431 if !AreTypesEquivalent(Int16, Int16) { 432 t.Errorf("Int16 and Int16 are same types.") 433 } 434 if AreTypesEquivalent(Int16, Int24) { 435 t.Errorf("Int16 and Int24 are not same types.") 436 } 437 if !AreTypesEquivalent(VarChar, VarBinary) { 438 t.Errorf("VarChar in binlog and VarBinary in schema are equivalent types.") 439 } 440 if AreTypesEquivalent(VarBinary, VarChar) { 441 t.Errorf("VarBinary in binlog and VarChar in schema are not equivalent types.") 442 } 443 if !AreTypesEquivalent(Int16, Uint16) { 444 t.Errorf("Int16 in binlog and Uint16 in schema are equivalent types.") 445 } 446 if AreTypesEquivalent(Uint16, Int16) { 447 t.Errorf("Uint16 in binlog and Int16 in schema are not equivalent types.") 448 } 449 } 450 451 func TestPrintTypeChecks(t *testing.T) { 452 var funcs = []struct { 453 name string 454 f func(p Type) bool 455 }{ 456 {"IsSigned", IsSigned}, 457 {"IsFloat", IsFloat}, 458 {"IsUnsigned", IsUnsigned}, 459 {"IsIntegral", IsIntegral}, 460 {"IsText", IsText}, 461 {"IsNumber", IsNumber}, 462 {"IsQuoted", IsQuoted}, 463 {"IsBinary", IsBinary}, 464 {"IsDate", IsDate}, 465 {"IsNull", IsNull}, 466 } 467 var types = []Type{ 468 Null, 469 Int8, 470 Uint8, 471 Int16, 472 Uint16, 473 Int24, 474 Uint24, 475 Int32, 476 Uint32, 477 Int64, 478 Uint64, 479 Float32, 480 Float64, 481 Timestamp, 482 Date, 483 Time, 484 Datetime, 485 Year, 486 Decimal, 487 Text, 488 Blob, 489 VarChar, 490 VarBinary, 491 Char, 492 Binary, 493 Bit, 494 Enum, 495 Set, 496 Geometry, 497 TypeJSON, 498 Expression, 499 HexNum, 500 HexVal, 501 Tuple, 502 BitNum, 503 } 504 505 for _, f := range funcs { 506 var match []string 507 for _, tt := range types { 508 if f.f(tt) { 509 match = append(match, tt.String()) 510 } 511 } 512 t.Logf("%s(): %s", f.name, strings.Join(match, ", ")) 513 } 514 }