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