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