mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 14:54:20 +01:00
6bf52fdaca
and modify some functions to return const pointers. Add const qualifiers to local variable declarations or casts to remove the const qualifier in those places where write access is needed.
562 lines
14 KiB
Text
562 lines
14 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! */
|
|
const dtype_t* type) /* in: type struct */
|
|
{
|
|
return(type->prtype & 0xFFUL);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Compute the mbminlen and mbmaxlen members of a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_get_mblen(
|
|
/*============*/
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype, /* in: precise type (and collation) */
|
|
ulint* mbminlen, /* out: minimum length of a
|
|
multi-byte character */
|
|
ulint* mbmaxlen) /* out: maximum length of a
|
|
multi-byte character */
|
|
{
|
|
if (dtype_is_string_type(mtype)) {
|
|
#ifndef UNIV_HOTBACKUP
|
|
innobase_get_cset_width(dtype_get_charset_coll(prtype),
|
|
mbminlen, mbmaxlen);
|
|
ut_ad(*mbminlen <= *mbmaxlen);
|
|
ut_ad(*mbminlen <= 2); /* cf. the bit-field in dtype_t */
|
|
ut_ad(*mbmaxlen < 1 << 3); /* cf. the bit-field in dtype_t */
|
|
#else /* !UNIV_HOTBACKUP */
|
|
ut_a(mtype <= DATA_BINARY);
|
|
*mbminlen = *mbmaxlen = 1;
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
} else {
|
|
*mbminlen = *mbmaxlen = 0;
|
|
}
|
|
}
|
|
|
|
/*************************************************************************
|
|
Compute the mbminlen and mbmaxlen members of a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_set_mblen(
|
|
/*============*/
|
|
dtype_t* type) /* in/out: type */
|
|
{
|
|
ulint mbminlen;
|
|
ulint mbmaxlen;
|
|
|
|
dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
|
|
type->mbminlen = mbminlen;
|
|
type->mbmaxlen = mbmaxlen;
|
|
|
|
ut_ad(dtype_validate(type));
|
|
}
|
|
|
|
/*************************************************************************
|
|
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: precision of type */
|
|
{
|
|
ut_ad(type);
|
|
ut_ad(mtype <= DATA_MTYPE_MAX);
|
|
|
|
type->mtype = mtype;
|
|
type->prtype = prtype;
|
|
type->len = len;
|
|
|
|
dtype_set_mblen(type);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Copies a data type structure. */
|
|
UNIV_INLINE
|
|
void
|
|
dtype_copy(
|
|
/*=======*/
|
|
dtype_t* type1, /* in: type struct to copy to */
|
|
const 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(
|
|
/*============*/
|
|
const dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->mtype);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the precise data type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_prtype(
|
|
/*=============*/
|
|
const dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->prtype);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Gets the type length. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_len(
|
|
/*==========*/
|
|
const dtype_t* type)
|
|
{
|
|
ut_ad(type);
|
|
|
|
return(type->len);
|
|
}
|
|
|
|
/*************************************************************************
|
|
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 a type. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_pad_char(
|
|
/*===============*/
|
|
/* out: padding character code, or
|
|
ULINT_UNDEFINED if no padding specified */
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype) /* in: precise type */
|
|
{
|
|
switch (mtype) {
|
|
case DATA_FIXBINARY:
|
|
case DATA_BINARY:
|
|
if (UNIV_UNLIKELY(dtype_get_charset_coll(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 (!(prtype & DATA_BINARY_TYPE)) {
|
|
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 */
|
|
const dtype_t* type, /* in: type struct */
|
|
ulint prefix_len)/* in: prefix length to
|
|
replace type->len, or 0 */
|
|
{
|
|
#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
|
|
#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
|
|
#endif
|
|
ulint len;
|
|
|
|
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);
|
|
|
|
len = prefix_len ? prefix_len : type->len;
|
|
|
|
mach_write_to_2(buf + 2, 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 */
|
|
const byte* buf) /* in: buffer for stored type order info */
|
|
{
|
|
#if 4 != DATA_ORDER_NULL_TYPE_BUF_SIZE
|
|
# error "4 != DATA_ORDER_NULL_TYPE_BUF_SIZE"
|
|
#endif
|
|
|
|
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 */
|
|
const 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_low(
|
|
/*=====================*/
|
|
/* out: fixed size, or 0 */
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype, /* in: precise type */
|
|
ulint len, /* in: length */
|
|
ulint mbminlen, /* in: minimum length of a multibyte char */
|
|
ulint mbmaxlen) /* in: maximum length of a multibyte char */
|
|
{
|
|
switch (mtype) {
|
|
case DATA_SYS:
|
|
#ifdef UNIV_DEBUG
|
|
switch (prtype & DATA_MYSQL_TYPE_MASK) {
|
|
case DATA_ROW_ID:
|
|
ut_ad(len == DATA_ROW_ID_LEN);
|
|
break;
|
|
case DATA_TRX_ID:
|
|
ut_ad(len == DATA_TRX_ID_LEN);
|
|
break;
|
|
case DATA_ROLL_PTR:
|
|
ut_ad(len == DATA_ROLL_PTR_LEN);
|
|
break;
|
|
default:
|
|
ut_ad(0);
|
|
return(0);
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
case DATA_CHAR:
|
|
case DATA_FIXBINARY:
|
|
case DATA_INT:
|
|
case DATA_FLOAT:
|
|
case DATA_DOUBLE:
|
|
return(len);
|
|
case DATA_MYSQL:
|
|
if (prtype & DATA_BINARY_TYPE) {
|
|
return(len);
|
|
} else {
|
|
#ifdef UNIV_HOTBACKUP
|
|
if (mbminlen == mbmaxlen) {
|
|
return(len);
|
|
}
|
|
#else /* UNIV_HOTBACKUP */
|
|
/* We play it safe here and ask MySQL for
|
|
mbminlen and mbmaxlen. Although
|
|
mbminlen and mbmaxlen are
|
|
initialized if and only if prtype
|
|
is (in one of the 3 functions in this file),
|
|
it could be that none of these functions
|
|
has been called. */
|
|
|
|
ulint i_mbminlen, i_mbmaxlen;
|
|
|
|
innobase_get_cset_width(
|
|
dtype_get_charset_coll(prtype),
|
|
&i_mbminlen, &i_mbmaxlen);
|
|
|
|
if (UNIV_UNLIKELY(mbminlen != i_mbminlen)
|
|
|| UNIV_UNLIKELY(mbmaxlen != i_mbmaxlen)) {
|
|
|
|
ut_print_timestamp(stderr);
|
|
fprintf(stderr, " InnoDB: "
|
|
"mbminlen=%lu, "
|
|
"mbmaxlen=%lu, "
|
|
"type->mbminlen=%lu, "
|
|
"type->mbmaxlen=%lu\n",
|
|
(ulong) i_mbminlen,
|
|
(ulong) i_mbmaxlen,
|
|
(ulong) mbminlen,
|
|
(ulong) mbmaxlen);
|
|
}
|
|
if (mbminlen == mbmaxlen) {
|
|
return(len);
|
|
}
|
|
#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_low(
|
|
/*===================*/
|
|
/* out: minimum size */
|
|
ulint mtype, /* in: main type */
|
|
ulint prtype, /* in: precise type */
|
|
ulint len, /* in: length */
|
|
ulint mbminlen, /* in: minimum length of a multibyte char */
|
|
ulint mbmaxlen) /* in: maximum length of a multibyte char */
|
|
{
|
|
switch (mtype) {
|
|
case DATA_SYS:
|
|
#ifdef UNIV_DEBUG
|
|
switch (prtype & DATA_MYSQL_TYPE_MASK) {
|
|
case DATA_ROW_ID:
|
|
ut_ad(len == DATA_ROW_ID_LEN);
|
|
break;
|
|
case DATA_TRX_ID:
|
|
ut_ad(len == DATA_TRX_ID_LEN);
|
|
break;
|
|
case DATA_ROLL_PTR:
|
|
ut_ad(len == DATA_ROLL_PTR_LEN);
|
|
break;
|
|
default:
|
|
ut_ad(0);
|
|
return(0);
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
case DATA_CHAR:
|
|
case DATA_FIXBINARY:
|
|
case DATA_INT:
|
|
case DATA_FLOAT:
|
|
case DATA_DOUBLE:
|
|
return(len);
|
|
case DATA_MYSQL:
|
|
if ((prtype & DATA_BINARY_TYPE) || mbminlen == mbmaxlen) {
|
|
return(len);
|
|
}
|
|
/* this is a variable-length character set */
|
|
ut_a(mbminlen > 0);
|
|
ut_a(mbmaxlen > mbminlen);
|
|
ut_a(len % mbmaxlen == 0);
|
|
return(len * mbminlen / mbmaxlen);
|
|
case DATA_VARCHAR:
|
|
case DATA_BINARY:
|
|
case DATA_DECIMAL:
|
|
case DATA_VARMYSQL:
|
|
case DATA_BLOB:
|
|
return(0);
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns the maximum size of a data type. Note: types in system tables may be
|
|
incomplete and return incorrect information. */
|
|
UNIV_INLINE
|
|
ulint
|
|
dtype_get_max_size_low(
|
|
/*===================*/
|
|
/* out: maximum size */
|
|
ulint mtype, /* in: main type */
|
|
ulint len) /* in: length */
|
|
{
|
|
switch (mtype) {
|
|
case DATA_SYS:
|
|
case DATA_CHAR:
|
|
case DATA_FIXBINARY:
|
|
case DATA_INT:
|
|
case DATA_FLOAT:
|
|
case DATA_DOUBLE:
|
|
case DATA_MYSQL:
|
|
case DATA_VARCHAR:
|
|
case DATA_BINARY:
|
|
case DATA_DECIMAL:
|
|
case DATA_VARMYSQL:
|
|
return(len);
|
|
case DATA_BLOB:
|
|
break;
|
|
default:
|
|
ut_error;
|
|
}
|
|
|
|
return(ULINT_MAX);
|
|
}
|
|
|
|
/***************************************************************************
|
|
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of 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
|
|
in ROW_FORMAT=REDUNDANT */
|
|
const dtype_t* type) /* in: type */
|
|
{
|
|
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
|
|
type->mbminlen, type->mbmaxlen) > 0);
|
|
}
|