mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Many files:
Fix bug introduced by the prefix key + multibyte charsets patch today sql/ha_innodb.cc: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/include/data0type.h: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/include/fsp0fsp.h: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/data/data0type.c: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/row/row0ins.c: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/row/row0row.c: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/row/row0sel.c: Fix bug introduced by the prefix key + multibyte charsets patch today innobase/row/row0upd.c: Fix bug introduced by the prefix key + multibyte charsets patch today
This commit is contained in:
parent
0db72d6e33
commit
d822c6f7ef
8 changed files with 199 additions and 74 deletions
|
@ -12,6 +12,27 @@ Created 1/16/1996 Heikki Tuuri
|
|||
#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
|
||||
|
@ -23,6 +44,63 @@ 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. */
|
||||
|
|
|
@ -144,6 +144,29 @@ SQL null*/
|
|||
store the charset-collation number; one byte is left unused, though */
|
||||
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
|
||||
|
||||
/*************************************************************************
|
||||
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 */
|
||||
/*************************************************************************
|
||||
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);
|
||||
/*************************************************************************
|
||||
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||
string type. */
|
||||
|
|
|
@ -16,6 +16,40 @@ Created 12/18/1995 Heikki Tuuri
|
|||
#include "ut0byte.h"
|
||||
#include "page0types.h"
|
||||
|
||||
typedef byte xdes_t;
|
||||
|
||||
/************************************************************************
|
||||
Gets pointer to a the extent descriptor of a page. The page where the
|
||||
extent descriptor resides is x-locked. If the page offset is equal to
|
||||
the free limit of the space, adds new extents from above the free limit
|
||||
to the space free list, if not free limit == space size. This adding
|
||||
is necessary to make the descriptor defined, as they are uninitialized
|
||||
above the free limit. */
|
||||
|
||||
xdes_t*
|
||||
xdes_get_descriptor(
|
||||
/*================*/
|
||||
/* out: pointer to the extent descriptor, NULL if the
|
||||
page does not exist in the space or if offset > free
|
||||
limit */
|
||||
ulint space, /* in: space id */
|
||||
ulint offset, /* in: page offset; if equal to the free limit,
|
||||
we try to add new extents to the space free list */
|
||||
mtr_t* mtr); /* in: mtr handle */
|
||||
|
||||
/**************************************************************************
|
||||
Gets a descriptor bit of a page. */
|
||||
|
||||
ibool
|
||||
xdes_get_bit(
|
||||
/*=========*/
|
||||
/* out: TRUE if free */
|
||||
xdes_t* descr, /* in: descriptor */
|
||||
ulint bit, /* in: XDES_FREE_BIT or XDES_CLEAN_BIT */
|
||||
ulint offset, /* in: page offset within extent:
|
||||
0 ... FSP_EXTENT_SIZE - 1 */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
|
||||
/* If records are inserted in order, there are the following
|
||||
flags to tell this (their type is made byte for the compiler
|
||||
to warn if direction and hint parameters are switched in
|
||||
|
|
|
@ -2019,16 +2019,12 @@ row_ins_index_entry_set_vals(
|
|||
if (ind_field->prefix_len > 0
|
||||
&& dfield_get_len(row_field) != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(ind_field));
|
||||
|
||||
field->len = innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
ind_field->prefix_len,
|
||||
dfield_get_len(row_field),row_field->data);
|
||||
field->len = dtype_get_at_most_n_mbchars(cur_type,
|
||||
ind_field->prefix_len,
|
||||
dfield_get_len(row_field), row_field->data);
|
||||
} else {
|
||||
field->len = row_field->len;
|
||||
}
|
||||
|
|
|
@ -143,18 +143,15 @@ row_build_index_entry(
|
|||
if (ind_field->prefix_len > 0
|
||||
&& dfield_get_len(dfield2) != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(ind_field));
|
||||
|
||||
storage_len = innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
storage_len = dtype_get_at_most_n_mbchars(
|
||||
cur_type,
|
||||
ind_field->prefix_len,
|
||||
dfield_get_len(dfield2),dfield2->data);
|
||||
dfield_get_len(dfield2), dfield2->data);
|
||||
|
||||
dfield_set_len(dfield,storage_len);
|
||||
dfield_set_len(dfield, storage_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,16 +494,13 @@ row_build_row_ref_from_row(
|
|||
if (field->prefix_len > 0
|
||||
&& dfield->len != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
|
||||
dfield->len = innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
dfield->len = dtype_get_at_most_n_mbchars(
|
||||
cur_type,
|
||||
field->prefix_len,
|
||||
dfield->len,dfield->data);
|
||||
dfield->len, dfield->data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,16 +94,13 @@ row_sel_sec_rec_is_for_clust_rec(
|
|||
if (ifield->prefix_len > 0
|
||||
&& clust_len != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(ifield));
|
||||
|
||||
clust_len = innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
clust_len = dtype_get_at_most_n_mbchars(
|
||||
cur_type,
|
||||
ifield->prefix_len,
|
||||
clust_len,clust_field);
|
||||
clust_len, clust_field);
|
||||
}
|
||||
|
||||
if (0 != cmp_data_data(dict_col_get_type(col),
|
||||
|
|
|
@ -876,17 +876,15 @@ row_upd_index_replace_new_col_vals_index_pos(
|
|||
if (field->prefix_len > 0
|
||||
&& new_val->len != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
|
||||
dfield->len =
|
||||
innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
field->prefix_len,
|
||||
new_val->len,new_val->data);
|
||||
dfield->len =
|
||||
dtype_get_at_most_n_mbchars(
|
||||
cur_type,
|
||||
field->prefix_len,
|
||||
new_val->len,
|
||||
new_val->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -948,17 +946,15 @@ row_upd_index_replace_new_col_vals(
|
|||
if (field->prefix_len > 0
|
||||
&& new_val->len != UNIV_SQL_NULL) {
|
||||
|
||||
/* For prefix keys get the storage length
|
||||
for the prefix_len characters. */
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
|
||||
cur_type = dict_col_get_type(
|
||||
dict_field_get_col(field));
|
||||
|
||||
dfield->len =
|
||||
innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(cur_type->prtype),
|
||||
field->prefix_len,
|
||||
new_val->len,new_val->data);
|
||||
dfield->len =
|
||||
dtype_get_at_most_n_mbchars(
|
||||
cur_type,
|
||||
field->prefix_len,
|
||||
new_val->len,
|
||||
new_val->data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5258,8 +5258,7 @@ innobase_store_binlog_offset_and_flush_log(
|
|||
/*=============================*/
|
||||
char *binlog_name, /* in: binlog name */
|
||||
longlong offset /* in: binlog offset */
|
||||
)
|
||||
{
|
||||
) {
|
||||
mtr_t mtr;
|
||||
|
||||
assert(binlog_name != NULL);
|
||||
|
@ -5298,50 +5297,58 @@ ulonglong ha_innobase::get_mysql_bin_log_pos()
|
|||
|
||||
extern "C" {
|
||||
/**********************************************************************
|
||||
This function is used to find storage length of prefix_len characters
|
||||
in bytes for prefix indexes using multibyte character set.
|
||||
Function finds charset information and returns length of
|
||||
prefix_len characters in the index field in bytes. */
|
||||
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.
|
||||
|
||||
ulint innobase_get_at_most_n_mbchars(
|
||||
/*=================================*/
|
||||
NOTE: the prototype of this function is copied to data0type.c! If you change
|
||||
this function, you MUST change also data0type.c! */
|
||||
|
||||
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 of the index */
|
||||
ulint data_len, /* in: length of the sting in bytes */
|
||||
const char *pos) /* in: character string */
|
||||
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 */
|
||||
{
|
||||
ulint byte_length; /* storage length, in bytes. */
|
||||
ulint byte_length; /* string length in bytes. */
|
||||
ulint char_length; /* character length in bytes */
|
||||
ulint n_chars; /* number of characters in prefix */
|
||||
CHARSET_INFO* charset; /* charset used in the field */
|
||||
|
||||
ut_ad(pos);
|
||||
byte_length = data_len;
|
||||
|
||||
charset = get_charset(charset_id,MYF(MY_WME));
|
||||
charset = get_charset(charset_id, MYF(MY_WME));
|
||||
|
||||
ut_ad(charset);
|
||||
ut_ad(charset->mbmaxlen);
|
||||
|
||||
/* Calculate the storage length of the one character in bytes and
|
||||
how many characters the prefix index contains */
|
||||
/* Calculate how many characters at most the prefix index contains */
|
||||
|
||||
char_length = byte_length / charset->mbmaxlen;
|
||||
prefix_len = prefix_len / charset->mbmaxlen;
|
||||
n_chars = prefix_len / charset->mbmaxlen;
|
||||
|
||||
/* If length of the string is greater than storage length of the
|
||||
one character, we have to find the storage position of the
|
||||
prefix_len character in the string */
|
||||
/* If the charset is multi-byte, then we must find the length of the
|
||||
first at most n chars in the string. If the string contains less
|
||||
characters than n, then we return the length to the end of the last
|
||||
full character. */
|
||||
|
||||
if (byte_length > char_length) {
|
||||
char_length = my_charpos(charset, pos,
|
||||
pos + byte_length, prefix_len);
|
||||
set_if_smaller(char_length, byte_length);
|
||||
}
|
||||
else {
|
||||
if (charset->mbmaxlen > 1) {
|
||||
/* my_charpos() returns the byte length of the first n_chars
|
||||
characters, or the end of the last full character */
|
||||
|
||||
char_length = my_charpos(charset, str,
|
||||
str + byte_length, n_chars);
|
||||
} else {
|
||||
char_length = prefix_len;
|
||||
}
|
||||
|
||||
return char_length;
|
||||
return(char_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue