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