mirror of
https://github.com/MariaDB/server.git
synced 2025-01-26 00:34:18 +01:00
8f18616ef0
and lexer files). From now on, the following Emacs cc-mode settings apply when indenting C function bodies in InnoDB: (setq c-basic-offset 8) (setq c-label-minimum-indentation 0) (add-to-list 'c-offsets-alist '(c . 0)) (add-to-list 'c-offsets-alist '(label . [0])) The indentation rules for function declarations still have not been formalized, and they must be formatted manually. Try to limit all lines to at most 79 characters (assuming TAB stops every 8 characters) by splitting lines before opening parenthesis, or at string constants. Fix some grammar mistakes in diagnostic output: match to, match with -> match found from -> found in trying rename -> trying to rename Fix an error in page_check_dir(): it said "supremum not pointed to" when the infimum was not pointed to. Enclose commented-out code snippets in #if 0 ... #endif instead of /* ... */. Add (void*) casts to some %p parameters in fprintf() calls. Try to split lines before a binary operator, not after one. (These three fixes were not made everywhere.)
540 lines
13 KiB
Text
540 lines
13 KiB
Text
/******************************************************
|
|
Data types
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
Created 1/16/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "mach0data.h"
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**********************************************************************
|
|
Get the variable length bounds of the given character set.
|
|
|
|
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
|
this function, you MUST change also the prototype here! */
|
|
extern
|
|
void
|
|
innobase_get_cset_width(
|
|
/*====================*/
|
|
ulint cset, /* in: MySQL charset-collation code */
|
|
ulint* mbminlen, /* out: minimum length of a char (in bytes) */
|
|
ulint* mbmaxlen); /* out: maximum length of a char (in bytes) */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/*************************************************************************
|
|
Gets the MySQL charset-collation code for MySQL string types. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_charset_coll(
|
|
/*===================*/
|
|
ulint prtype) /* in: precise data type */
|
|
{
|
|
return((prtype >> 16) & 0xFFUL);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the MySQL type code from a dtype. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_mysql_type(
|
|
/*=================*/
|
|
/* out: MySQL type code; this is NOT an InnoDB
|
|
type code! */
|
|
dtype_t* type) /* in: type struct */
|
|
{
|
|
return(type->prtype & 0xFFUL);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Sets the mbminlen and mbmaxlen members of a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_set_mblen(
|
|
/*============*/
|
|
dtype_t* type) /* in/out: type struct */
|
|
{
|
|
ut_ad(type);
|
|
if (dtype_is_string_type(type->mtype)) {
|
|
#ifndef UNIV_HOTBACKUP
|
|
innobase_get_cset_width(dtype_get_charset_coll(type->prtype),
|
|
&type->mbminlen, &type->mbmaxlen);
|
|
ut_ad(type->mbminlen <= type->mbmaxlen);
|
|
#else /* !UNIV_HOTBACKUP */
|
|
#ifdef notdefined
|
|
printf("ibbackup: DEBUG: type->mtype=%lu, type->prtype=%lu\n",
|
|
type->mtype, type->prtype);
|
|
#endif
|
|
ut_a(type->mtype <= DATA_BINARY);
|
|
#ifdef notdefined
|
|
ut_a(type->prtype == (DATA_BINARY | DATA_NOT_NULL));
|
|
#endif
|
|
type->mbminlen = type->mbmaxlen = 1;
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
} else {
|
|
type->mbminlen = type->mbmaxlen = 0;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
Sets a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_set(
|
|
/*======*/
|
|
dtype_t* type, /* in: type struct to init */
|
|
ulint mtype, /* in: main data type */
|
|
ulint prtype, /* in: precise type */
|
|
ulint len, /* in: length of type */
|
|
ulint prec) /* in: precision of type */
|
|
{
|
|
ut_ad(type);
|
|
ut_ad(mtype <= DATA_MTYPE_MAX);
|
|
|
|
type->mtype = mtype;
|
|
type->prtype = prtype;
|
|
type->len = len;
|
|
type->prec = prec;
|
|
|
|
dtype_set_mblen(type);
|
|
ut_ad(dtype_validate(type));
|
|
}
|
|
|
|
/*************************************************************************
|
|
Copies a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_copy(
|
|
/*=======*/
|
|
dtype_t* type1, /* in: type struct to copy to */
|
|
dtype_t* type2) /* in: type struct to copy from */
|
|
{
|
|
*type1 = *type2;
|
|
|
|
ut_ad(dtype_validate(type1));
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the SQL main data type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_mtype(
|
|
/*============*/
|
|
dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->mtype);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the precise data type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_prtype(
|
|
/*=============*/
|
|
dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->prtype);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the type length. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_len(
|
|
/*==========*/
|
|
dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->len);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the type precision. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_prec(
|
|
/*===========*/
|
|
dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->prec);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the minimum length of a character, in bytes. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_mbminlen(
|
|
/*===============*/
|
|
/* out: minimum length of a char, in bytes,
|
|
or 0 if this is not a character type */
|
|
const dtype_t* type) /* in: type */
|
|
{
|
|
ut_ad(type);
|
|
return(type->mbminlen);
|
|
}
|
|
/*************************************************************************
|
|
Gets the maximum length of a character, in bytes. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_mbmaxlen(
|
|
/*===============*/
|
|
/* out: maximum length of a char, in bytes,
|
|
or 0 if this is not a character type */
|
|
const dtype_t* type) /* in: type */
|
|
{
|
|
ut_ad(type);
|
|
return(type->mbmaxlen);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the padding character code for the type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_pad_char(
|
|
/*===============*/
|
|
/* out: padding character code, or
|
|
ULINT_UNDEFINED if no padding specified */
|
|
const dtype_t* type) /* in: type */
|
|
{
|
|
switch (type->mtype) {
|
|
case DATA_FIXBINARY:
|
|
case DATA_BINARY:
|
|
if (UNIV_UNLIKELY(dtype_get_charset_coll(type->prtype)
|
|
== DATA_MYSQL_BINARY_CHARSET_COLL)) {
|
|
/* Starting from 5.0.18, do not pad
|
|
VARBINARY or BINARY columns. */
|
|
return(ULINT_UNDEFINED);
|
|
}
|
|
/* Fall through */
|
|
case DATA_CHAR:
|
|
case DATA_VARCHAR:
|
|
case DATA_MYSQL:
|
|
case DATA_VARMYSQL:
|
|
/* Space is the padding character for all char and binary
|
|
strings, and starting from 5.0.3, also for TEXT strings. */
|
|
|
|
return(0x20);
|
|
case DATA_BLOB:
|
|
if ((type->prtype & DATA_BINARY_TYPE) == 0) {
|
|
return(0x20);
|
|
}
|
|
/* Fall through */
|
|
default:
|
|
/* No padding specified */
|
|
return(ULINT_UNDEFINED);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
Stores for a type the information which determines its alphabetical ordering
|
|
and the storage size of an SQL NULL value. This is the >= 4.1.x storage
|
|
format. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_new_store_for_order_and_null_size(
|
|
/*====================================*/
|
|
byte* buf, /* in: buffer for
|
|
DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
|
bytes where we store the info */
|
|
dtype_t* type) /* in: type struct */
|
|
{
|
|
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
|
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
|
|
#endif
|
|
|
|
buf[0] = (byte)(type->mtype & 0xFFUL);
|
|
|
|
if (type->prtype & DATA_BINARY_TYPE) {
|
|
buf[0] = buf[0] | 128;
|
|
}
|
|
|
|
/* In versions < 4.1.2 we had: if (type->prtype & DATA_NONLATIN1) {
|
|
buf[0] = buf[0] | 64;
|
|
}
|
|
*/
|
|
|
|
buf[1] = (byte)(type->prtype & 0xFFUL);
|
|
|
|
mach_write_to_2(buf + 2, type->len & 0xFFFFUL);
|
|
|
|
ut_ad(dtype_get_charset_coll(type->prtype) < 256);
|
|
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
|
|
|
|
if (type->prtype & DATA_NOT_NULL) {
|
|
buf[4] |= 128;
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads to a type the stored information which determines its alphabetical
|
|
ordering and the storage size of an SQL NULL value. This is the < 4.1.x
|
|
storage format. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_read_for_order_and_null_size(
|
|
/*===============================*/
|
|
dtype_t* type, /* in: type struct */
|
|
byte* buf) /* in: buffer for stored type order info */
|
|
{
|
|
ut_ad(4 == DATA_ORDER_NULL_TYPE_BUF_SIZE);
|
|
|
|
type->mtype = buf[0] & 63;
|
|
type->prtype = buf[1];
|
|
|
|
if (buf[0] & 128) {
|
|
type->prtype = type->prtype | DATA_BINARY_TYPE;
|
|
}
|
|
|
|
type->len = mach_read_from_2(buf + 2);
|
|
|
|
type->prtype = dtype_form_prtype(type->prtype,
|
|
data_mysql_default_charset_coll);
|
|
dtype_set_mblen(type);
|
|
}
|
|
|
|
/**************************************************************************
|
|
Reads to a type the stored information which determines its alphabetical
|
|
ordering and the storage size of an SQL NULL value. This is the >= 4.1.x
|
|
storage format. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_new_read_for_order_and_null_size(
|
|
/*===================================*/
|
|
dtype_t* type, /* in: type struct */
|
|
byte* buf) /* in: buffer for stored type order info */
|
|
{
|
|
ulint charset_coll;
|
|
|
|
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
|
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
|
|
#endif
|
|
|
|
type->mtype = buf[0] & 63;
|
|
type->prtype = buf[1];
|
|
|
|
if (buf[0] & 128) {
|
|
type->prtype |= DATA_BINARY_TYPE;
|
|
}
|
|
|
|
if (buf[4] & 128) {
|
|
type->prtype |= DATA_NOT_NULL;
|
|
}
|
|
|
|
type->len = mach_read_from_2(buf + 2);
|
|
|
|
mach_read_from_2(buf + 4);
|
|
|
|
charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
|
|
|
|
if (dtype_is_string_type(type->mtype)) {
|
|
ut_a(charset_coll < 256);
|
|
|
|
if (charset_coll == 0) {
|
|
/* This insert buffer record was inserted with MySQL
|
|
version < 4.1.2, and the charset-collation code was not
|
|
explicitly stored to dtype->prtype at that time. It
|
|
must be the default charset-collation of this MySQL
|
|
installation. */
|
|
|
|
charset_coll = data_mysql_default_charset_coll;
|
|
}
|
|
|
|
type->prtype = dtype_form_prtype(type->prtype, charset_coll);
|
|
}
|
|
dtype_set_mblen(type);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns the size of a fixed size data type, 0 if not a fixed size type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_fixed_size(
|
|
/*=================*/
|
|
/* out: fixed size, or 0 */
|
|
dtype_t* type) /* in: type */
|
|
{
|
|
ulint mtype;
|
|
|
|
mtype = dtype_get_mtype(type);
|
|
|
|
switch (mtype) {
|
|
case DATA_SYS:
|
|
#ifdef UNIV_DEBUG
|
|
switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
|
|
default:
|
|
ut_ad(0);
|
|
return(0);
|
|
case DATA_ROW_ID:
|
|
ut_ad(type->len == DATA_ROW_ID_LEN);
|
|
break;
|
|
case DATA_TRX_ID:
|
|
ut_ad(type->len == DATA_TRX_ID_LEN);
|
|
break;
|
|
case DATA_ROLL_PTR:
|
|
ut_ad(type->len == DATA_ROLL_PTR_LEN);
|
|
break;
|
|
case DATA_MIX_ID:
|
|
ut_ad(type->len == DATA_MIX_ID_LEN);
|
|
break;
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
case DATA_CHAR:
|
|
case DATA_FIXBINARY:
|
|
case DATA_INT:
|
|
case DATA_FLOAT:
|
|
case DATA_DOUBLE:
|
|
return(dtype_get_len(type));
|
|
case DATA_MYSQL:
|
|
if (type->prtype & DATA_BINARY_TYPE) {
|
|
return(dtype_get_len(type));
|
|
} else {
|
|
#ifdef UNIV_HOTBACKUP
|
|
if (type->mbminlen == type->mbmaxlen) {
|
|
return(dtype_get_len(type));
|
|
}
|
|
#else /* UNIV_HOTBACKUP */
|
|
/* We play it safe here and ask MySQL for
|
|
mbminlen and mbmaxlen. Although
|
|
type->mbminlen and type->mbmaxlen are
|
|
initialized if and only if type->prtype
|
|
is (in one of the 3 functions in this file),
|
|
it could be that none of these functions
|
|
has been called. */
|
|
|
|
ulint mbminlen, mbmaxlen;
|
|
|
|
innobase_get_cset_width
|
|
(dtype_get_charset_coll(type->prtype),
|
|
&mbminlen, &mbmaxlen);
|
|
|
|
if (UNIV_UNLIKELY(type->mbminlen != mbminlen)
|
|
|| UNIV_UNLIKELY(type->mbmaxlen != mbmaxlen)) {
|
|
|
|
ut_print_timestamp(stderr);
|
|
fprintf(stderr, " InnoDB: "
|
|
"mbminlen=%lu, "
|
|
"mbmaxlen=%lu, "
|
|
"type->mbminlen=%lu, "
|
|
"type->mbmaxlen=%lu\n",
|
|
(ulong) mbminlen,
|
|
(ulong) mbmaxlen,
|
|
(ulong) type->mbminlen,
|
|
(ulong) type->mbmaxlen);
|
|
}
|
|
if (mbminlen == mbmaxlen) {
|
|
return(dtype_get_len(type));
|
|
}
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
}
|
|
/* fall through for variable-length charsets */
|
|
case DATA_VARCHAR:
|
|
case DATA_BINARY:
|
|
case DATA_DECIMAL:
|
|
case DATA_VARMYSQL:
|
|
case DATA_BLOB:
|
|
return(0);
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns the minimum size of a data type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_min_size(
|
|
/*===============*/
|
|
/* out: minimum size */
|
|
const dtype_t* type) /* in: type */
|
|
{
|
|
switch (type->mtype) {
|
|
case DATA_SYS:
|
|
#ifdef UNIV_DEBUG
|
|
switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
|
|
default:
|
|
ut_ad(0);
|
|
return(0);
|
|
case DATA_ROW_ID:
|
|
ut_ad(type->len == DATA_ROW_ID_LEN);
|
|
break;
|
|
case DATA_TRX_ID:
|
|
ut_ad(type->len == DATA_TRX_ID_LEN);
|
|
break;
|
|
case DATA_ROLL_PTR:
|
|
ut_ad(type->len == DATA_ROLL_PTR_LEN);
|
|
break;
|
|
case DATA_MIX_ID:
|
|
ut_ad(type->len == DATA_MIX_ID_LEN);
|
|
break;
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
case DATA_CHAR:
|
|
case DATA_FIXBINARY:
|
|
case DATA_INT:
|
|
case DATA_FLOAT:
|
|
case DATA_DOUBLE:
|
|
return(type->len);
|
|
case DATA_MYSQL:
|
|
if ((type->prtype & DATA_BINARY_TYPE)
|
|
|| type->mbminlen == type->mbmaxlen) {
|
|
return(type->len);
|
|
}
|
|
/* this is a variable-length character set */
|
|
ut_a(type->mbminlen > 0);
|
|
ut_a(type->mbmaxlen > type->mbminlen);
|
|
ut_a(type->len % type->mbmaxlen == 0);
|
|
return(type->len * type->mbminlen / type->mbmaxlen);
|
|
case DATA_VARCHAR:
|
|
case DATA_BINARY:
|
|
case DATA_DECIMAL:
|
|
case DATA_VARMYSQL:
|
|
case DATA_BLOB:
|
|
return(0);
|
|
default: ut_error;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns a stored SQL NULL size for a type. For fixed length types it is
|
|
the fixed length of the type, otherwise 0. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_sql_null_size(
|
|
/*====================*/
|
|
/* out: SQL null storage size */
|
|
dtype_t* type) /* in: type */
|
|
{
|
|
return(dtype_get_fixed_size(type));
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns TRUE if a type is of a fixed size. */
|
|
UNIV_INLINE
|
|
ibool
|
|
dtype_is_fixed_size(
|
|
/*================*/
|
|
/* out: TRUE if fixed size */
|
|
dtype_t* type) /* in: type */
|
|
{
|
|
ulint size;
|
|
|
|
size = dtype_get_fixed_size(type);
|
|
|
|
if (size) {
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|