1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-17 12:02:09 +03:00
Files
mariadb/innobase/data/data0type.c
unknown 7b06313785 InnoDB: Fixed bugs in the padding and trimming of trailing spaces
that affected the UCS2 character set. (Bug #7350)


innobase/data/data0type.c:
  Added dtype_get_charset_coll_noninline()
innobase/include/data0type.h:
  Added dtype_get_charset_coll_noninline()
innobase/include/row0mysql.h:
  Added charset field to mysql_row_templ_struct.
innobase/include/row0mysql.ic:
  row_mysql_store_col_in_innobase_format():
  When removing trailing spaces, treat the UCS2 character set properly.
innobase/rem/rem0cmp.c:
  cmp_whole_field(): Do not remove trailing 0x20 bytes, as
  innobase_mysql_cmp() implicitly pads the strings with trailing
  spaces as necessary.
innobase/row/row0sel.c:
  row_sel_field_store_in_mysql_format(): Do not pad with 0x20 bytes.
  row_sel_store_mysql_rec(): Pad VARCHARs with trailing spaces
  (0x20, or 0x0020 in UCS2).
sql/ha_innodb.cc:
  build_template(): Initialize templ->charset
2004-12-17 18:35:11 +02:00

273 lines
7.4 KiB
C

/******************************************************
Data types
(c) 1996 Innobase Oy
Created 1/16/1996 Heikki Tuuri
*******************************************************/
#include "data0type.h"
#ifdef UNIV_NONINL
#include "data0type.ic"
#endif
/**********************************************************************
This function is used to find the storage length in bytes of the first n
characters for prefix indexes using a multibyte character set. The function
finds charset information and returns length of prefix_len characters in the
index field in bytes.
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
this function, you MUST change also the prototype here! */
ulint
innobase_get_at_most_n_mbchars(
/*===========================*/
/* out: number of bytes occupied by the first
n characters */
ulint charset_id, /* in: character set id */
ulint prefix_len, /* in: prefix length in bytes of the index
(this has to be divided by mbmaxlen to get the
number of CHARACTERS n in the prefix) */
ulint data_len, /* in: length of the string in bytes */
const char* str); /* in: character string */
/* At the database startup we store the default-charset collation number of
this MySQL installation to this global variable. If we have < 4.1.2 format
column definitions, or records in the insert buffer, we use this
charset-collation code for them. */
ulint data_mysql_default_charset_coll = 99999999;
ulint data_mysql_latin1_swedish_charset_coll = 99999999;
dtype_t dtype_binary_val = {DATA_BINARY, 0, 0, 0};
dtype_t* dtype_binary = &dtype_binary_val;
/*************************************************************************
Checks if a string type has to be compared by the MySQL comparison functions.
InnoDB internally only handles binary byte string comparisons, as well as
latin1_swedish_ci strings. For example, UTF-8 strings have to be compared
by MySQL. */
ibool
dtype_str_needs_mysql_cmp(
/*======================*/
/* out: TRUE if a string type that requires
comparison with MySQL functions */
dtype_t* dtype) /* in: type struct */
{
if (dtype->mtype == DATA_MYSQL
|| dtype->mtype == DATA_VARMYSQL
|| (dtype->mtype == DATA_BLOB
&& 0 == (dtype->prtype & DATA_BINARY_TYPE)
&& dtype_get_charset_coll(dtype->prtype) !=
data_mysql_latin1_swedish_charset_coll)) {
return(TRUE);
}
return(FALSE);
}
/*************************************************************************
For the documentation of this function, see innobase_get_at_most_n_mbchars()
in ha_innodb.cc. */
ulint
dtype_get_at_most_n_mbchars(
/*========================*/
dtype_t* dtype,
ulint prefix_len,
ulint data_len,
const char* str)
{
ut_a(data_len != UNIV_SQL_NULL);
if (dtype_str_needs_mysql_cmp(dtype)) {
return(innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(dtype->prtype),
prefix_len, data_len, str));
}
/* We assume here that the string types that InnoDB itself can compare
are single-byte charsets! */
if (prefix_len < data_len) {
return(prefix_len);
}
return(data_len);
}
/*************************************************************************
Checks if a data main type is a string type. Also a BLOB is considered a
string type. */
ibool
dtype_is_string_type(
/*=================*/
/* out: TRUE if string type */
ulint mtype) /* in: InnoDB main data type code: DATA_CHAR, ... */
{
if (mtype <= DATA_BLOB
|| mtype == DATA_MYSQL
|| mtype == DATA_VARMYSQL) {
return(TRUE);
}
return(FALSE);
}
/*************************************************************************
Checks if a type is a binary string type. Note that for tables created with
< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
those DATA_BLOB columns this function currently returns FALSE. */
ibool
dtype_is_binary_string_type(
/*========================*/
/* out: TRUE if binary string type */
ulint mtype, /* in: main data type */
ulint prtype) /* in: precise type */
{
if ((mtype == DATA_FIXBINARY)
|| (mtype == DATA_BINARY)
|| (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE))) {
return(TRUE);
}
return(FALSE);
}
/*************************************************************************
Checks if a type is a non-binary string type. That is, dtype_is_string_type is
TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created
with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
For those DATA_BLOB columns this function currently returns TRUE. */
ibool
dtype_is_non_binary_string_type(
/*============================*/
/* out: TRUE if non-binary string type */
ulint mtype, /* in: main data type */
ulint prtype) /* in: precise type */
{
if (dtype_is_string_type(mtype) == TRUE
&& dtype_is_binary_string_type(mtype, prtype) == FALSE) {
return(TRUE);
}
return(FALSE);
}
/*************************************************************************
Gets the MySQL charset-collation code for MySQL string types. */
ulint
dtype_get_charset_coll_noninline(
/*=============================*/
ulint prtype) /* in: precise data type */
{
return(dtype_get_charset_coll(prtype));
}
/*************************************************************************
Forms a precise type from the < 4.1.2 format precise type plus the
charset-collation code. */
ulint
dtype_form_prtype(
/*==============*/
ulint old_prtype, /* in: the MySQL type code and the flags
DATA_BINARY_TYPE etc. */
ulint charset_coll) /* in: MySQL charset-collation code */
{
ut_a(old_prtype < 256 * 256);
ut_a(charset_coll < 256);
return(old_prtype + (charset_coll << 16));
}
/*************************************************************************
Validates a data type structure. */
ibool
dtype_validate(
/*===========*/
/* out: TRUE if ok */
dtype_t* type) /* in: type struct to validate */
{
ut_a(type);
ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL));
if (type->mtype == DATA_SYS) {
ut_a(type->prtype <= DATA_MIX_ID);
}
return(TRUE);
}
/*************************************************************************
Prints a data type structure. */
void
dtype_print(
/*========*/
dtype_t* type) /* in: type */
{
ulint mtype;
ulint prtype;
ulint len;
ut_a(type);
mtype = type->mtype;
prtype = type->prtype;
if (mtype == DATA_VARCHAR) {
fputs("DATA_VARCHAR", stderr);
} else if (mtype == DATA_CHAR) {
fputs("DATA_CHAR", stderr);
} else if (mtype == DATA_BINARY) {
fputs("DATA_BINARY", stderr);
} else if (mtype == DATA_INT) {
fputs("DATA_INT", stderr);
} else if (mtype == DATA_MYSQL) {
fputs("DATA_MYSQL", stderr);
} else if (mtype == DATA_SYS) {
fputs("DATA_SYS", stderr);
} else {
fprintf(stderr, "type %lu", (ulong) mtype);
}
len = type->len;
if ((type->mtype == DATA_SYS)
|| (type->mtype == DATA_VARCHAR)
|| (type->mtype == DATA_CHAR)) {
putc(' ', stderr);
if (prtype == DATA_ROW_ID) {
fputs("DATA_ROW_ID", stderr);
len = DATA_ROW_ID_LEN;
} else if (prtype == DATA_ROLL_PTR) {
fputs("DATA_ROLL_PTR", stderr);
len = DATA_ROLL_PTR_LEN;
} else if (prtype == DATA_TRX_ID) {
fputs("DATA_TRX_ID", stderr);
len = DATA_TRX_ID_LEN;
} else if (prtype == DATA_MIX_ID) {
fputs("DATA_MIX_ID", stderr);
} else if (prtype == DATA_ENGLISH) {
fputs("DATA_ENGLISH", stderr);
} else {
fprintf(stderr, "prtype %lu", (ulong) mtype);
}
}
fprintf(stderr, " len %lu prec %lu", (ulong) len, (ulong) type->prec);
}