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