1/***************************************************************************** 2 3Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License, version 2.0, as published by the 7Free Software Foundation. 8 9This program is also distributed with certain software (including but not 10limited to OpenSSL) that is licensed under separate terms, as designated in a 11particular file or component or in included license documentation. The authors 12of MySQL hereby grant you an additional permission to link the program and 13your derivative works with the separately licensed software that they have 14included with MySQL. 15 16This program is distributed in the hope that it will be useful, but WITHOUT 17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, 19for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25*****************************************************************************/ 26 27/** @file include/data0type.ic 28 Data types 29 30 Created 1/16/1996 Heikki Tuuri 31 *******************************************************/ 32 33#include "ha_prototypes.h" 34#include "mach0data.h" 35 36/** Gets the MySQL charset-collation code for MySQL string types. 37 @return MySQL charset-collation code */ 38UNIV_INLINE 39ulint dtype_get_charset_coll(ulint prtype) /*!< in: precise data type */ 40{ 41 return ((prtype >> 16) & CHAR_COLL_MASK); 42} 43 44#ifndef UNIV_HOTBACKUP 45/** Determines if a MySQL string type is a subset of UTF-8. This function 46 may return false negatives, in case further character-set collation 47 codes are introduced in MySQL later. 48 @return true if a subset of UTF-8 */ 49UNIV_INLINE 50ibool dtype_is_utf8(ulint prtype) /*!< in: precise data type */ 51{ 52 /* These codes have been copied from strings/ctype-extra.c 53 and strings/ctype-utf8.c. */ 54 switch (dtype_get_charset_coll(prtype)) { 55 case 11: /* ascii_general_ci */ 56 case 65: /* ascii_bin */ 57 case 33: /* utf8_general_ci */ 58 case 83: /* utf8_bin */ 59 case 254: /* utf8_general_cs */ 60 return (TRUE); 61 } 62 63 return (FALSE); 64} 65 66/** Gets the MySQL type code from a dtype. 67 @return MySQL type code; this is NOT an InnoDB type code! */ 68UNIV_INLINE 69ulint dtype_get_mysql_type(const dtype_t *type) /*!< in: type struct */ 70{ 71 return (type->prtype & 0xFFUL); 72} 73 74/** Compute the mbminlen and mbmaxlen members of a data type structure. */ 75UNIV_INLINE 76void dtype_get_mblen(ulint mtype, /*!< in: main type */ 77 ulint prtype, /*!< in: precise type (and collation) */ 78 ulint *mbminlen, /*!< out: minimum length of a 79 multi-byte character */ 80 ulint *mbmaxlen) /*!< out: maximum length of a 81 multi-byte character */ 82{ 83 if (dtype_is_string_type(mtype)) { 84 innobase_get_cset_width(dtype_get_charset_coll(prtype), mbminlen, mbmaxlen); 85 ut_ad(*mbminlen <= *mbmaxlen); 86 ut_ad(*mbminlen < DATA_MBMAX); 87 ut_ad(*mbmaxlen < DATA_MBMAX); 88 } else { 89 *mbminlen = *mbmaxlen = 0; 90 } 91} 92 93/** Sets the minimum and maximum length of a character, in bytes. */ 94UNIV_INLINE 95void dtype_set_mbminmaxlen(dtype_t *type, /*!< in/out: type */ 96 ulint mbminlen, /*!< in: minimum length of a char, 97 in bytes, or 0 if this is not 98 a character type */ 99 ulint mbmaxlen) /*!< in: maximum length of a char, 100 in bytes, or 0 if this is not 101 a character type */ 102{ 103 ut_ad(mbminlen < DATA_MBMAX); 104 ut_ad(mbmaxlen < DATA_MBMAX); 105 ut_ad(mbminlen <= mbmaxlen); 106 107 type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); 108} 109 110/** Compute the mbminlen and mbmaxlen members of a data type structure. */ 111UNIV_INLINE 112void dtype_set_mblen(dtype_t *type) /*!< in/out: type */ 113{ 114 ulint mbminlen; 115 ulint mbmaxlen; 116 117 dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); 118 dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); 119 120 ut_ad(dtype_validate(type)); 121} 122#else /* !UNIV_HOTBACKUP */ 123#define dtype_set_mblen(type) (void)0 124#endif /* !UNIV_HOTBACKUP */ 125 126/** Sets a data type structure. */ 127UNIV_INLINE 128void dtype_set(dtype_t *type, /*!< in: type struct to init */ 129 ulint mtype, /*!< in: main data type */ 130 ulint prtype, /*!< in: precise type */ 131 ulint len) /*!< in: precision of type */ 132{ 133 ut_ad(type); 134 ut_ad(mtype <= DATA_MTYPE_MAX); 135 136 type->mtype = mtype; 137 type->prtype = prtype; 138 type->len = len; 139 140 dtype_set_mblen(type); 141} 142 143/** Copies a data type structure. */ 144UNIV_INLINE 145void dtype_copy(dtype_t *type1, /*!< in: type struct to copy to */ 146 const dtype_t *type2) /*!< in: type struct to copy from */ 147{ 148 *type1 = *type2; 149 150 ut_ad(dtype_validate(type1)); 151} 152 153/** Gets the SQL main data type. 154 @return SQL main data type */ 155UNIV_INLINE 156ulint dtype_get_mtype(const dtype_t *type) /*!< in: data type */ 157{ 158 ut_ad(type); 159 160 return (type->mtype); 161} 162 163/** Gets the precise data type. 164 @return precise data type */ 165UNIV_INLINE 166ulint dtype_get_prtype(const dtype_t *type) /*!< in: data type */ 167{ 168 ut_ad(type); 169 170 return (type->prtype); 171} 172 173/** Gets the type length. 174 @return fixed length of the type, in bytes, or 0 if variable-length */ 175UNIV_INLINE 176ulint dtype_get_len(const dtype_t *type) /*!< in: data type */ 177{ 178 ut_ad(type); 179 180 return (type->len); 181} 182 183#ifndef UNIV_HOTBACKUP 184/** Gets the minimum length of a character, in bytes. 185 @return minimum length of a char, in bytes, or 0 if this is not a 186 character type */ 187UNIV_INLINE 188ulint dtype_get_mbminlen(const dtype_t *type) /*!< in: type */ 189{ 190 ut_ad(type); 191 return (DATA_MBMINLEN(type->mbminmaxlen)); 192} 193/** Gets the maximum length of a character, in bytes. 194 @return maximum length of a char, in bytes, or 0 if this is not a 195 character type */ 196UNIV_INLINE 197ulint dtype_get_mbmaxlen(const dtype_t *type) /*!< in: type */ 198{ 199 ut_ad(type); 200 return (DATA_MBMAXLEN(type->mbminmaxlen)); 201} 202 203/** Stores for a type the information which determines its alphabetical ordering 204 and the storage size of an SQL NULL value. This is the >= 4.1.x storage 205 format. */ 206UNIV_INLINE 207void dtype_new_store_for_order_and_null_size( 208 byte *buf, /*!< in: buffer for 209 DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 210 bytes where we store the info */ 211 const dtype_t *type, /*!< in: type struct */ 212 ulint prefix_len) /*!< in: prefix length to 213 replace type->len, or 0 */ 214{ 215#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 216#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" 217#endif 218 ulint len; 219 220 ut_ad(type); 221 ut_ad(type->mtype >= DATA_VARCHAR); 222 ut_ad(type->mtype <= DATA_MTYPE_MAX); 223 224 buf[0] = (byte)(type->mtype & 0xFFUL); 225 226 if (type->prtype & DATA_BINARY_TYPE) { 227 buf[0] |= 128; 228 } 229 230 /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { 231 buf[0] |= 64; 232 } 233 */ 234 if (type->prtype & DATA_MULTI_VALUE) { 235 buf[0] |= 64; 236 } 237 238 buf[1] = (byte)(type->prtype & 0xFFUL); 239 240 len = prefix_len ? prefix_len : type->len; 241 242 mach_write_to_2(buf + 2, len & 0xFFFFUL); 243 244 ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM); 245 mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); 246 247 if (type->prtype & DATA_NOT_NULL) { 248 buf[4] |= 128; 249 } 250} 251 252/** Reads to a type the stored information which determines its alphabetical 253 ordering and the storage size of an SQL NULL value. This is the < 4.1.x 254 storage format. */ 255UNIV_INLINE 256void dtype_read_for_order_and_null_size( 257 dtype_t *type, /*!< in: type struct */ 258 const byte *buf) /*!< in: buffer for stored type order info */ 259{ 260#if 4 != DATA_ORDER_NULL_TYPE_BUF_SIZE 261#error "4 != DATA_ORDER_NULL_TYPE_BUF_SIZE" 262#endif 263 264 type->mtype = buf[0] & 63; 265 type->prtype = buf[1]; 266 267 if (buf[0] & 128) { 268 type->prtype |= DATA_BINARY_TYPE; 269 } 270 271 type->len = mach_read_from_2(buf + 2); 272 273 type->prtype = 274 dtype_form_prtype(type->prtype, data_mysql_default_charset_coll); 275 dtype_set_mblen(type); 276} 277 278/** Reads to a type the stored information which determines its alphabetical 279 ordering and the storage size of an SQL NULL value. This is the >= 4.1.x 280 storage format. */ 281UNIV_INLINE 282void dtype_new_read_for_order_and_null_size( 283 dtype_t *type, /*!< in: type struct */ 284 const byte *buf) /*!< in: buffer for stored type order info */ 285{ 286 ulint charset_coll; 287 288#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 289#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" 290#endif 291 292 type->mtype = buf[0] & 63; 293 type->prtype = buf[1]; 294 295 if (buf[0] & 128) { 296 type->prtype |= DATA_BINARY_TYPE; 297 } 298 299 if (buf[0] & 64) { 300 type->prtype |= DATA_MULTI_VALUE; 301 } 302 303 if (buf[4] & 128) { 304 type->prtype |= DATA_NOT_NULL; 305 } 306 307 type->len = mach_read_from_2(buf + 2); 308 309 charset_coll = mach_read_from_2(buf + 4) & CHAR_COLL_MASK; 310 311 if (dtype_is_string_type(type->mtype)) { 312 ut_a(charset_coll <= MAX_CHAR_COLL_NUM); 313 314 if (charset_coll == 0) { 315 /* This insert buffer record was inserted with MySQL 316 version < 4.1.2, and the charset-collation code was not 317 explicitly stored to dtype->prtype at that time. It 318 must be the default charset-collation of this MySQL 319 installation. */ 320 321 charset_coll = data_mysql_default_charset_coll; 322 } 323 324 type->prtype = dtype_form_prtype(type->prtype, charset_coll); 325 } 326 dtype_set_mblen(type); 327} 328 329/** Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len 330 @return the SQL type name */ 331UNIV_INLINE 332char *dtype_sql_name(unsigned mtype, /*!< in: mtype */ 333 unsigned prtype, /*!< in: prtype */ 334 unsigned len, /*!< in: len */ 335 char *name, /*!< out: SQL name */ 336 unsigned name_sz) /*!< in: size of the name buffer */ 337{ 338#define APPEND_UNSIGNED() \ 339 do { \ 340 if (prtype & DATA_UNSIGNED) { \ 341 snprintf(name + strlen(name), name_sz - strlen(name), " UNSIGNED"); \ 342 } \ 343 } while (0) 344 345 snprintf(name, name_sz, "UNKNOWN"); 346 347 switch (mtype) { 348 case DATA_INT: 349 switch (len) { 350 case 1: 351 snprintf(name, name_sz, "TINYINT"); 352 break; 353 case 2: 354 snprintf(name, name_sz, "SMALLINT"); 355 break; 356 case 3: 357 snprintf(name, name_sz, "MEDIUMINT"); 358 break; 359 case 4: 360 snprintf(name, name_sz, "INT"); 361 break; 362 case 8: 363 snprintf(name, name_sz, "BIGINT"); 364 break; 365 } 366 APPEND_UNSIGNED(); 367 break; 368 case DATA_FLOAT: 369 snprintf(name, name_sz, "FLOAT"); 370 APPEND_UNSIGNED(); 371 break; 372 case DATA_DOUBLE: 373 snprintf(name, name_sz, "DOUBLE"); 374 APPEND_UNSIGNED(); 375 break; 376 case DATA_FIXBINARY: 377 snprintf(name, name_sz, "BINARY(%u)", len); 378 break; 379 case DATA_CHAR: 380 case DATA_MYSQL: 381 snprintf(name, name_sz, "CHAR(%u)", len); 382 break; 383 case DATA_VARCHAR: 384 case DATA_VARMYSQL: 385 snprintf(name, name_sz, "VARCHAR(%u)", len); 386 break; 387 case DATA_BINARY: 388 snprintf(name, name_sz, "VARBINARY(%u)", len); 389 break; 390 case DATA_GEOMETRY: 391 snprintf(name, name_sz, "GEOMETRY"); 392 break; 393 case DATA_BLOB: 394 switch (len) { 395 case 9: 396 snprintf(name, name_sz, "TINYBLOB"); 397 break; 398 case 10: 399 snprintf(name, name_sz, "BLOB"); 400 break; 401 case 11: 402 snprintf(name, name_sz, "MEDIUMBLOB"); 403 break; 404 case 12: 405 snprintf(name, name_sz, "LONGBLOB"); 406 break; 407 } 408 } 409 410 if (prtype & DATA_NOT_NULL) { 411 snprintf(name + strlen(name), name_sz - strlen(name), " NOT NULL"); 412 } 413 414 return (name); 415} 416 417#endif /* !UNIV_HOTBACKUP */ 418 419/** Returns the size of a fixed size data type, 0 if not a fixed size type. 420 @return fixed size, or 0 */ 421UNIV_INLINE 422ulint dtype_get_fixed_size_low( 423 ulint mtype, /*!< in: main type */ 424 ulint prtype, /*!< in: precise type */ 425 ulint len, /*!< in: length */ 426 ulint mbminmaxlen, /*!< in: minimum and maximum length of 427 a multibyte character, in bytes */ 428 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ 429{ 430 switch (mtype) { 431 case DATA_SYS: 432#ifdef UNIV_DEBUG 433 switch (prtype & DATA_MYSQL_TYPE_MASK) { 434 case DATA_ROW_ID: 435 ut_ad(len == DATA_ROW_ID_LEN); 436 break; 437 case DATA_TRX_ID: 438 ut_ad(len == DATA_TRX_ID_LEN); 439 break; 440 case DATA_ROLL_PTR: 441 ut_ad(len == DATA_ROLL_PTR_LEN); 442 break; 443 default: 444 ut_ad(0); 445 return (0); 446 } 447#endif /* UNIV_DEBUG */ 448 // Fall through. 449 case DATA_CHAR: 450 case DATA_FIXBINARY: 451 case DATA_INT: 452 case DATA_FLOAT: 453 case DATA_DOUBLE: 454 case DATA_POINT: 455 return (len); 456 case DATA_MYSQL: 457#ifndef UNIV_LIBRARY 458 if (prtype & DATA_BINARY_TYPE) { 459 return (len); 460 } else if (!comp) { 461 return (len); 462 } else { 463#ifndef UNIV_HOTBACKUP 464#ifdef UNIV_DEBUG 465 ulint i_mbminlen, i_mbmaxlen; 466 467 innobase_get_cset_width(dtype_get_charset_coll(prtype), &i_mbminlen, 468 &i_mbmaxlen); 469 470 ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen) == mbminmaxlen); 471#endif /* UNIV_DEBUG */ 472#endif /* !UNIV_HOTBACKUP */ 473 if (DATA_MBMINLEN(mbminmaxlen) == DATA_MBMAXLEN(mbminmaxlen)) { 474 return (len); 475 } 476 } 477#else /* !UNIV_LIBRARY */ 478 return (len); 479#endif /* !UNIV_LIBRARY */ 480 /* fall through for variable-length charsets */ 481 case DATA_VARCHAR: 482 case DATA_BINARY: 483 case DATA_DECIMAL: 484 case DATA_VARMYSQL: 485 case DATA_VAR_POINT: 486 case DATA_GEOMETRY: 487 case DATA_BLOB: 488 return (0); 489 default: 490 ut_error; 491 } 492} 493 494/** Returns the minimum size of a data type. 495 @return minimum size */ 496UNIV_INLINE 497ulint dtype_get_min_size_low( 498 ulint mtype, /*!< in: main type */ 499 ulint prtype, /*!< in: precise type */ 500 ulint len, /*!< in: length */ 501 ulint mbminmaxlen) /*!< in: minimum and maximum length of a 502 multi-byte character */ 503{ 504 switch (mtype) { 505 case DATA_SYS: 506#ifdef UNIV_DEBUG 507 switch (prtype & DATA_MYSQL_TYPE_MASK) { 508 case DATA_ROW_ID: 509 ut_ad(len == DATA_ROW_ID_LEN); 510 break; 511 case DATA_TRX_ID: 512 ut_ad(len == DATA_TRX_ID_LEN); 513 break; 514 case DATA_ROLL_PTR: 515 ut_ad(len == DATA_ROLL_PTR_LEN); 516 break; 517 default: 518 ut_ad(0); 519 return (0); 520 } 521#endif /* UNIV_DEBUG */ 522 // Fall through. 523 case DATA_CHAR: 524 case DATA_FIXBINARY: 525 case DATA_INT: 526 case DATA_FLOAT: 527 case DATA_DOUBLE: 528 case DATA_POINT: 529 return (len); 530 case DATA_MYSQL: 531 if (prtype & DATA_BINARY_TYPE) { 532 return (len); 533 } else { 534 ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); 535 ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); 536 537 if (mbminlen == mbmaxlen) { 538 return (len); 539 } 540 541 /* this is a variable-length character set */ 542 ut_a(mbminlen > 0); 543 ut_a(mbmaxlen > mbminlen); 544 ut_a(len % mbmaxlen == 0); 545 return (len * mbminlen / mbmaxlen); 546 } 547 case DATA_VARCHAR: 548 case DATA_BINARY: 549 case DATA_DECIMAL: 550 case DATA_VARMYSQL: 551 case DATA_VAR_POINT: 552 case DATA_GEOMETRY: 553 case DATA_BLOB: 554 return (0); 555 default: 556 ut_error; 557 } 558} 559 560/** Returns the maximum size of a data type. Note: types in system tables may 561be incomplete and return incorrect information. 562@param[in] mtype main type 563@param[in] len length 564@return maximum size */ 565UNIV_INLINE 566ulint dtype_get_max_size_low(ulint mtype, /*!< in: main type */ 567 ulint len) /*!< in: length */ 568{ 569 switch (mtype) { 570 case DATA_SYS: 571 case DATA_CHAR: 572 case DATA_FIXBINARY: 573 case DATA_INT: 574 case DATA_FLOAT: 575 case DATA_DOUBLE: 576 case DATA_MYSQL: 577 case DATA_VARCHAR: 578 case DATA_BINARY: 579 case DATA_DECIMAL: 580 case DATA_VARMYSQL: 581 case DATA_POINT: 582 return (len); 583 case DATA_VAR_POINT: 584 case DATA_GEOMETRY: 585 case DATA_BLOB: 586 break; 587 default: 588 ut_error; 589 } 590 return (ULINT_MAX); 591} 592 593/** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a type. 594 For fixed length types it is the fixed length of the type, otherwise 0. 595 @return SQL null storage size in ROW_FORMAT=REDUNDANT */ 596UNIV_INLINE 597ulint dtype_get_sql_null_size(const dtype_t *type, /*!< in: type */ 598 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ 599{ 600#ifndef UNIV_HOTBACKUP 601 return (dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, 602 type->mbminmaxlen, comp)); 603#else /* !UNIV_HOTBACKUP */ 604 return (dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, 0, 0)); 605#endif /* !UNIV_HOTBACKUP */ 606} 607