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