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