mirror of
https://github.com/MariaDB/server.git
synced 2026-05-14 19:07:15 +02:00
InnoDB: Fix Bug #7350 without hard-coding charset-collation numbers.
innobase/data/data0type.c: Add mbminlen and mbmaxlen to dtype_t innobase/include/data0type.h: Add mbminlen and mbmaxlen to dtype_t Add dtype_get_mbminlen() and dtype_get_mbmaxlen() innobase/include/data0type.ic: Add dtype_set_mblen() Add dtype_get_mbminlen() and dtype_get_mbmaxlen() Replace innobase_is_mb_cset() with innobase_get_mb_cset() innobase/include/row0mysql.h: Add mbminlen and mbmaxlen innobase/include/row0mysql.ic: Detect UCS2 collations based on mbminlen innobase/row/row0sel.c: Detect UCS2 collations based on mbminlen sql/ha_innodb.cc: Replace innobase_is_mb_cset() with innobase_get_mb_cset() build_template(): Initialize templ->mbminlen and templ->mbmaxlen
This commit is contained in:
parent
63bcbfc433
commit
f9a394dbdd
7 changed files with 126 additions and 54 deletions
|
|
@ -271,6 +271,24 @@ dtype_get_prec(
|
|||
/*===========*/
|
||||
dtype_t* type);
|
||||
/*************************************************************************
|
||||
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 */
|
||||
/*************************************************************************
|
||||
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 */
|
||||
/*************************************************************************
|
||||
Gets the padding character code for the type. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
|
|
@ -358,10 +376,13 @@ struct dtype_struct{
|
|||
ulint mtype; /* main data type */
|
||||
ulint prtype; /* precise type; MySQL data type */
|
||||
|
||||
/* the remaining two fields do not affect alphabetical ordering: */
|
||||
/* the remaining fields do not affect alphabetical ordering: */
|
||||
|
||||
ulint len; /* length */
|
||||
ulint prec; /* precision */
|
||||
|
||||
ulint mbminlen; /* minimum length of a character, in bytes */
|
||||
ulint mbmaxlen; /* maximum length of a character, in bytes */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
|
|
|
|||
|
|
@ -9,15 +9,46 @@ Created 1/16/1996 Heikki Tuuri
|
|||
#include "mach0data.h"
|
||||
|
||||
/**********************************************************************
|
||||
Determines whether the given character set is of variable length.
|
||||
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
|
||||
ibool
|
||||
innobase_is_mb_cset(
|
||||
/*================*/
|
||||
ulint cset); /* in: MySQL charset-collation code */
|
||||
void
|
||||
innobase_get_mb_cset(
|
||||
/*=================*/
|
||||
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) */
|
||||
|
||||
/*************************************************************************
|
||||
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);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
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)) {
|
||||
innobase_get_mb_cset(dtype_get_charset_coll(type->prtype),
|
||||
&type->mbminlen, &type->mbmaxlen);
|
||||
ut_ad(type->mbminlen <= type->mbmaxlen);
|
||||
} else {
|
||||
type->mbminlen = type->mbmaxlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Sets a data type structure. */
|
||||
|
|
@ -39,6 +70,7 @@ dtype_set(
|
|||
type->len = len;
|
||||
type->prec = prec;
|
||||
|
||||
dtype_set_mblen(type);
|
||||
ut_ad(dtype_validate(type));
|
||||
}
|
||||
|
||||
|
|
@ -82,17 +114,6 @@ dtype_get_prtype(
|
|||
return(type->prtype);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
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 type length. */
|
||||
UNIV_INLINE
|
||||
|
|
@ -119,6 +140,33 @@ dtype_get_prec(
|
|||
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
|
||||
|
|
@ -211,6 +259,7 @@ dtype_read_for_order_and_null_size(
|
|||
|
||||
type->prtype = dtype_form_prtype(type->prtype,
|
||||
data_mysql_default_charset_coll);
|
||||
dtype_set_mblen(type);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
@ -262,6 +311,7 @@ dtype_new_read_for_order_and_null_size(
|
|||
|
||||
type->prtype = dtype_form_prtype(type->prtype, charset_coll);
|
||||
}
|
||||
dtype_set_mblen(type);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
|
@ -306,9 +356,7 @@ dtype_get_fixed_size(
|
|||
case DATA_DOUBLE:
|
||||
case DATA_MYSQL:
|
||||
if ((type->prtype & DATA_BINARY_TYPE)
|
||||
|| !innobase_is_mb_cset(
|
||||
dtype_get_charset_coll(
|
||||
type->prtype))) {
|
||||
|| type->mbminlen == type->mbmaxlen) {
|
||||
return(dtype_get_len(type));
|
||||
}
|
||||
/* fall through for variable-length charsets */
|
||||
|
|
|
|||
|
|
@ -458,6 +458,10 @@ struct mysql_row_templ_struct {
|
|||
numbers DATA_CHAR... */
|
||||
ulint charset; /* MySQL charset-collation code
|
||||
of the column, or zero */
|
||||
ulint mbminlen; /* minimum length of a char, in bytes,
|
||||
or zero if not a char type */
|
||||
ulint mbmaxlen; /* maximum length of a char, in bytes,
|
||||
or zero if not a char type */
|
||||
ulint is_unsigned; /* if a column type is an integer
|
||||
type and this field is != 0, then
|
||||
it is an unsigned integer type */
|
||||
|
|
|
|||
|
|
@ -93,17 +93,11 @@ row_mysql_store_col_in_innobase_format(
|
|||
|| type == DATA_BINARY) {
|
||||
/* Remove trailing spaces. */
|
||||
|
||||
/* Handle UCS2 strings differently. As no new
|
||||
collations will be introduced in 4.1, we hardcode the
|
||||
charset-collation codes here. In 5.0, the logic will
|
||||
be based on mbminlen. */
|
||||
ulint cset = dtype_get_charset_coll(
|
||||
dtype_get_prtype(dfield_get_type(dfield)));
|
||||
/* Handle UCS2 strings differently. */
|
||||
ulint mbminlen = dtype_get_mbminlen(
|
||||
dfield_get_type(dfield));
|
||||
ptr = row_mysql_read_var_ref(&col_len, mysql_data);
|
||||
if (cset == 35/*ucs2_general_ci*/
|
||||
|| cset == 90/*ucs2_bin*/
|
||||
|| (cset >= 128/*ucs2_unicode_ci*/
|
||||
&& cset <= 144/*ucs2_persian_ci*/)) {
|
||||
if (mbminlen == 2) {
|
||||
/* space=0x0020 */
|
||||
/* Trim "half-chars", just in case. */
|
||||
col_len &= ~1;
|
||||
|
|
@ -113,6 +107,7 @@ row_mysql_store_col_in_innobase_format(
|
|||
col_len -= 2;
|
||||
}
|
||||
} else {
|
||||
ut_a(mbminlen == 1);
|
||||
/* space=0x20 */
|
||||
while (col_len > 0 && ptr[col_len - 1] == 0x20) {
|
||||
col_len--;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue