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