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