1/***************************************************************************** 2 3Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. 4Copyright (c) 2017, 2019, 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 ulint* mbminlen, /*!< out: minimum length of a 76 multi-byte character */ 77 ulint* 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 ulint mbminlen; 100 ulint mbmaxlen; 101 102 dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); 103 type->mbminlen = mbminlen; 104 type->mbmaxlen = mbmaxlen; 105 106 ut_ad(dtype_validate(type)); 107} 108 109/*********************************************************************//** 110Sets a data type structure. */ 111UNIV_INLINE 112void 113dtype_set( 114/*======*/ 115 dtype_t* type, /*!< in: type struct to init */ 116 ulint mtype, /*!< in: main data type */ 117 ulint prtype, /*!< in: precise type */ 118 ulint len) /*!< in: precision of type */ 119{ 120 ut_ad(type); 121 ut_ad(mtype <= DATA_MTYPE_MAX); 122 123 type->mtype = unsigned(mtype); 124 type->prtype = unsigned(prtype); 125 type->len = unsigned(len); 126 127 dtype_set_mblen(type); 128} 129 130/*********************************************************************//** 131Copies a data type structure. */ 132UNIV_INLINE 133void 134dtype_copy( 135/*=======*/ 136 dtype_t* type1, /*!< in: type struct to copy to */ 137 const dtype_t* type2) /*!< in: type struct to copy from */ 138{ 139 *type1 = *type2; 140 141 ut_ad(dtype_validate(type1)); 142} 143 144/*********************************************************************//** 145Gets the SQL main data type. 146@return SQL main data type */ 147UNIV_INLINE 148ulint 149dtype_get_mtype( 150/*============*/ 151 const dtype_t* type) /*!< in: data type */ 152{ 153 ut_ad(type); 154 155 return(type->mtype); 156} 157 158/*********************************************************************//** 159Gets the precise data type. 160@return precise data type */ 161UNIV_INLINE 162ulint 163dtype_get_prtype( 164/*=============*/ 165 const dtype_t* type) /*!< in: data type */ 166{ 167 ut_ad(type); 168 169 return(type->prtype); 170} 171 172/*********************************************************************//** 173Gets the type length. 174@return fixed length of the type, in bytes, or 0 if variable-length */ 175UNIV_INLINE 176ulint 177dtype_get_len( 178/*==========*/ 179 const dtype_t* type) /*!< in: data type */ 180{ 181 ut_ad(type); 182 183 return(type->len); 184} 185 186/*********************************************************************//** 187Gets the minimum length of a character, in bytes. 188@return minimum length of a char, in bytes, or 0 if this is not a 189character type */ 190UNIV_INLINE 191ulint 192dtype_get_mbminlen( 193/*===============*/ 194 const dtype_t* type) /*!< in: type */ 195{ 196 return type->mbminlen; 197} 198/*********************************************************************//** 199Gets the maximum length of a character, in bytes. 200@return maximum length of a char, in bytes, or 0 if this is not a 201character type */ 202UNIV_INLINE 203ulint 204dtype_get_mbmaxlen( 205/*===============*/ 206 const dtype_t* type) /*!< in: type */ 207{ 208 return type->mbmaxlen; 209} 210 211/**********************************************************************//** 212Stores for a type the information which determines its alphabetical ordering 213and the storage size of an SQL NULL value. This is the >= 4.1.x storage 214format. */ 215UNIV_INLINE 216void 217dtype_new_store_for_order_and_null_size( 218/*====================================*/ 219 byte* buf, /*!< in: buffer for 220 DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 221 bytes where we store the info */ 222 const dtype_t* type, /*!< in: type struct */ 223 ulint prefix_len)/*!< in: prefix length to 224 replace type->len, or 0 */ 225{ 226 compile_time_assert(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 227 228 ulint len; 229 230 ut_ad(type); 231 ut_ad(type->mtype >= DATA_VARCHAR); 232 ut_ad(type->mtype <= DATA_MTYPE_MAX); 233 234 buf[0] = (byte)(type->mtype & 0xFFUL); 235 236 if (type->prtype & DATA_BINARY_TYPE) { 237 buf[0] |= 128; 238 } 239 240 /* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) { 241 buf[0] |= 64; 242 } 243 */ 244 245 buf[1] = (byte)(type->prtype & 0xFFUL); 246 247 len = prefix_len ? prefix_len : type->len; 248 249 mach_write_to_2(buf + 2, len & 0xFFFFUL); 250 251 ut_ad(dtype_get_charset_coll(type->prtype) <= MAX_CHAR_COLL_NUM); 252 mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); 253 254 if (type->prtype & DATA_NOT_NULL) { 255 buf[4] |= 128; 256 } 257} 258 259/**********************************************************************//** 260Reads to a type the stored information which determines its alphabetical 261ordering and the storage size of an SQL NULL value. This is the < 4.1.x 262storage format. */ 263UNIV_INLINE 264void 265dtype_read_for_order_and_null_size( 266/*===============================*/ 267 dtype_t* type, /*!< in: type struct */ 268 const byte* buf) /*!< in: buffer for stored type order info */ 269{ 270 compile_time_assert(4 == DATA_ORDER_NULL_TYPE_BUF_SIZE); 271 type->mtype = buf[0] & 63; 272 type->prtype = buf[1]; 273 274 if (buf[0] & 128) { 275 type->prtype |= DATA_BINARY_TYPE; 276 } 277 278 type->len = mach_read_from_2(buf + 2); 279 280 type->prtype = dtype_form_prtype(type->prtype, 281 data_mysql_default_charset_coll); 282 dtype_set_mblen(type); 283} 284 285/**********************************************************************//** 286Reads to a type the stored information which determines its alphabetical 287ordering and the storage size of an SQL NULL value. This is the >= 4.1.x 288storage format. */ 289UNIV_INLINE 290void 291dtype_new_read_for_order_and_null_size( 292/*===================================*/ 293 dtype_t* type, /*!< in: type struct */ 294 const byte* buf) /*!< in: buffer for stored type order info */ 295{ 296 compile_time_assert(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE); 297 298 type->mtype = buf[0] & 63; 299 type->prtype = buf[1]; 300 301 if (buf[0] & 128) { 302 type->prtype |= DATA_BINARY_TYPE; 303 } 304 305 if (buf[4] & 128) { 306 type->prtype |= DATA_NOT_NULL; 307 } 308 309 type->len = mach_read_from_2(buf + 2); 310 311 ulint charset_coll = mach_read_from_2(buf + 4) & CHAR_COLL_MASK; 312 313 if (dtype_is_string_type(type->mtype)) { 314 ut_a(charset_coll <= MAX_CHAR_COLL_NUM); 315 316 if (charset_coll == 0) { 317 /* This insert buffer record was inserted with MySQL 318 version < 4.1.2, and the charset-collation code was not 319 explicitly stored to dtype->prtype at that time. It 320 must be the default charset-collation of this MySQL 321 installation. */ 322 323 charset_coll = data_mysql_default_charset_coll; 324 } 325 326 type->prtype = dtype_form_prtype(type->prtype, charset_coll); 327 } 328 dtype_set_mblen(type); 329} 330 331/*********************************************************************//** 332Returns the type's SQL name (e.g. BIGINT UNSIGNED) from mtype,prtype,len 333@return the SQL type name */ 334UNIV_INLINE 335char* 336dtype_sql_name( 337/*===========*/ 338 unsigned mtype, /*!< in: mtype */ 339 unsigned prtype, /*!< in: prtype */ 340 unsigned len, /*!< in: len */ 341 char* name, /*!< out: SQL name */ 342 unsigned name_sz)/*!< in: size of the name buffer */ 343{ 344 345#define APPEND_UNSIGNED() \ 346 do { \ 347 if (prtype & DATA_UNSIGNED) { \ 348 snprintf(name + strlen(name), \ 349 name_sz - strlen(name), \ 350 " UNSIGNED"); \ 351 } \ 352 } while (0) 353 354 snprintf(name, name_sz, "UNKNOWN"); 355 356 switch (mtype) { 357 case DATA_INT: 358 switch (len) { 359 case 1: 360 snprintf(name, name_sz, "TINYINT"); 361 break; 362 case 2: 363 snprintf(name, name_sz, "SMALLINT"); 364 break; 365 case 3: 366 snprintf(name, name_sz, "MEDIUMINT"); 367 break; 368 case 4: 369 snprintf(name, name_sz, "INT"); 370 break; 371 case 8: 372 snprintf(name, name_sz, "BIGINT"); 373 break; 374 } 375 APPEND_UNSIGNED(); 376 break; 377 case DATA_FLOAT: 378 snprintf(name, name_sz, "FLOAT"); 379 APPEND_UNSIGNED(); 380 break; 381 case DATA_DOUBLE: 382 snprintf(name, name_sz, "DOUBLE"); 383 APPEND_UNSIGNED(); 384 break; 385 case DATA_FIXBINARY: 386 snprintf(name, name_sz, "BINARY(%u)", len); 387 break; 388 case DATA_CHAR: 389 case DATA_MYSQL: 390 snprintf(name, name_sz, "CHAR(%u)", len); 391 break; 392 case DATA_VARCHAR: 393 case DATA_VARMYSQL: 394 snprintf(name, name_sz, "VARCHAR(%u)", len); 395 break; 396 case DATA_BINARY: 397 snprintf(name, name_sz, "VARBINARY(%u)", len); 398 break; 399 case DATA_GEOMETRY: 400 snprintf(name, name_sz, "GEOMETRY"); 401 break; 402 case DATA_BLOB: 403 switch (len) { 404 case 9: 405 snprintf(name, name_sz, "TINYBLOB"); 406 break; 407 case 10: 408 snprintf(name, name_sz, "BLOB"); 409 break; 410 case 11: 411 snprintf(name, name_sz, "MEDIUMBLOB"); 412 break; 413 case 12: 414 snprintf(name, name_sz, "LONGBLOB"); 415 break; 416 } 417 } 418 419 if (prtype & DATA_NOT_NULL) { 420 snprintf(name + strlen(name), 421 name_sz - strlen(name), 422 " NOT NULL"); 423 } 424 425 return(name); 426} 427 428/***********************************************************************//** 429Returns the size of a fixed size data type, 0 if not a fixed size type. 430@return fixed size, or 0 */ 431UNIV_INLINE 432ulint 433dtype_get_fixed_size_low( 434/*=====================*/ 435 ulint mtype, /*!< in: main type */ 436 ulint prtype, /*!< in: precise type */ 437 ulint len, /*!< in: length */ 438 ulint mbminlen, /*!< in: minimum length of a 439 multibyte character, in bytes */ 440 ulint mbmaxlen, /*!< in: maximum length of a 441 multibyte character, in bytes */ 442 ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ 443{ 444 switch (mtype) { 445 case DATA_SYS: 446#ifdef UNIV_DEBUG 447 switch (prtype & DATA_MYSQL_TYPE_MASK) { 448 case DATA_ROW_ID: 449 ut_ad(len == DATA_ROW_ID_LEN); 450 break; 451 case DATA_TRX_ID: 452 ut_ad(len == DATA_TRX_ID_LEN); 453 break; 454 case DATA_ROLL_PTR: 455 ut_ad(len == DATA_ROLL_PTR_LEN); 456 break; 457 default: 458 ut_ad(0); 459 return(0); 460 } 461#endif /* UNIV_DEBUG */ 462 /* fall through */ 463 case DATA_CHAR: 464 case DATA_FIXBINARY: 465 case DATA_INT: 466 case DATA_FLOAT: 467 case DATA_DOUBLE: 468 return(len); 469 case DATA_MYSQL: 470 if (prtype & DATA_BINARY_TYPE) { 471 return(len); 472 } else if (!comp) { 473 return(len); 474 } else { 475#ifdef UNIV_DEBUG 476 ulint i_mbminlen, i_mbmaxlen; 477 478 innobase_get_cset_width( 479 dtype_get_charset_coll(prtype), 480 &i_mbminlen, &i_mbmaxlen); 481 482 ut_ad(i_mbminlen == mbminlen); 483 ut_ad(i_mbmaxlen == mbmaxlen); 484#endif /* UNIV_DEBUG */ 485 if (mbminlen == mbmaxlen) { 486 return(len); 487 } 488 } 489 /* Treat as variable-length. */ 490 /* fall through */ 491 case DATA_VARCHAR: 492 case DATA_BINARY: 493 case DATA_DECIMAL: 494 case DATA_VARMYSQL: 495 case DATA_GEOMETRY: 496 case DATA_BLOB: 497 return(0); 498 default: 499 ut_error; 500 } 501 502 return(0); 503} 504 505/***********************************************************************//** 506Returns the minimum size of a data type. 507@return minimum size */ 508UNIV_INLINE 509ulint 510dtype_get_min_size_low( 511/*===================*/ 512 ulint mtype, /*!< in: main type */ 513 ulint prtype, /*!< in: precise type */ 514 ulint len, /*!< in: length */ 515 ulint mbminlen, /*!< in: minimum length of a character */ 516 ulint mbmaxlen) /*!< in: maximum length of a character */ 517{ 518 switch (mtype) { 519 case DATA_SYS: 520#ifdef UNIV_DEBUG 521 switch (prtype & DATA_MYSQL_TYPE_MASK) { 522 case DATA_ROW_ID: 523 ut_ad(len == DATA_ROW_ID_LEN); 524 break; 525 case DATA_TRX_ID: 526 ut_ad(len == DATA_TRX_ID_LEN); 527 break; 528 case DATA_ROLL_PTR: 529 ut_ad(len == DATA_ROLL_PTR_LEN); 530 break; 531 default: 532 ut_ad(0); 533 return(0); 534 } 535#endif /* UNIV_DEBUG */ 536 /* fall through */ 537 case DATA_CHAR: 538 case DATA_FIXBINARY: 539 case DATA_INT: 540 case DATA_FLOAT: 541 case DATA_DOUBLE: 542 return(len); 543 case DATA_MYSQL: 544 if (prtype & DATA_BINARY_TYPE) { 545 return(len); 546 } else { 547 if (mbminlen == mbmaxlen) { 548 return(len); 549 } 550 551 /* this is a variable-length character set */ 552 ut_a(mbminlen > 0); 553 ut_a(mbmaxlen > mbminlen); 554 ut_a(len % mbmaxlen == 0); 555 return(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