mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03: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:
@ -12,6 +12,27 @@ Created 1/16/1996 Heikki Tuuri
|
|||||||
#include "data0type.ic"
|
#include "data0type.ic"
|
||||||
#endif
|
#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
|
/* 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
|
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
|
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_val = {DATA_BINARY, 0, 0, 0};
|
||||||
dtype_t* dtype_binary = &dtype_binary_val;
|
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
|
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||||
string type. */
|
string type. */
|
||||||
|
@ -144,6 +144,29 @@ SQL null*/
|
|||||||
store the charset-collation number; one byte is left unused, though */
|
store the charset-collation number; one byte is left unused, though */
|
||||||
#define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6
|
#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
|
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||||
string type. */
|
string type. */
|
||||||
|
@ -16,6 +16,40 @@ Created 12/18/1995 Heikki Tuuri
|
|||||||
#include "ut0byte.h"
|
#include "ut0byte.h"
|
||||||
#include "page0types.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
|
/* If records are inserted in order, there are the following
|
||||||
flags to tell this (their type is made byte for the compiler
|
flags to tell this (their type is made byte for the compiler
|
||||||
to warn if direction and hint parameters are switched in
|
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
|
if (ind_field->prefix_len > 0
|
||||||
&& dfield_get_len(row_field) != UNIV_SQL_NULL) {
|
&& 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(
|
cur_type = dict_col_get_type(
|
||||||
dict_field_get_col(ind_field));
|
dict_field_get_col(ind_field));
|
||||||
|
|
||||||
field->len = innobase_get_at_most_n_mbchars(
|
field->len = dtype_get_at_most_n_mbchars(cur_type,
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
ind_field->prefix_len,
|
||||||
ind_field->prefix_len,
|
dfield_get_len(row_field), row_field->data);
|
||||||
dfield_get_len(row_field),row_field->data);
|
|
||||||
} else {
|
} else {
|
||||||
field->len = row_field->len;
|
field->len = row_field->len;
|
||||||
}
|
}
|
||||||
|
@ -143,18 +143,15 @@ row_build_index_entry(
|
|||||||
if (ind_field->prefix_len > 0
|
if (ind_field->prefix_len > 0
|
||||||
&& dfield_get_len(dfield2) != UNIV_SQL_NULL) {
|
&& 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(
|
cur_type = dict_col_get_type(
|
||||||
dict_field_get_col(ind_field));
|
dict_field_get_col(ind_field));
|
||||||
|
|
||||||
storage_len = innobase_get_at_most_n_mbchars(
|
storage_len = dtype_get_at_most_n_mbchars(
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
cur_type,
|
||||||
ind_field->prefix_len,
|
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
|
if (field->prefix_len > 0
|
||||||
&& dfield->len != UNIV_SQL_NULL) {
|
&& dfield->len != UNIV_SQL_NULL) {
|
||||||
|
|
||||||
/* For prefix keys get the storage length
|
|
||||||
for the prefix_len characters. */
|
|
||||||
|
|
||||||
cur_type = dict_col_get_type(
|
cur_type = dict_col_get_type(
|
||||||
dict_field_get_col(field));
|
dict_field_get_col(field));
|
||||||
|
|
||||||
dfield->len = innobase_get_at_most_n_mbchars(
|
dfield->len = dtype_get_at_most_n_mbchars(
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
cur_type,
|
||||||
field->prefix_len,
|
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
|
if (ifield->prefix_len > 0
|
||||||
&& clust_len != UNIV_SQL_NULL) {
|
&& clust_len != UNIV_SQL_NULL) {
|
||||||
|
|
||||||
/* For prefix keys get the storage length
|
|
||||||
for the prefix_len characters. */
|
|
||||||
|
|
||||||
cur_type = dict_col_get_type(
|
cur_type = dict_col_get_type(
|
||||||
dict_field_get_col(ifield));
|
dict_field_get_col(ifield));
|
||||||
|
|
||||||
clust_len = innobase_get_at_most_n_mbchars(
|
clust_len = dtype_get_at_most_n_mbchars(
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
cur_type,
|
||||||
ifield->prefix_len,
|
ifield->prefix_len,
|
||||||
clust_len,clust_field);
|
clust_len, clust_field);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 != cmp_data_data(dict_col_get_type(col),
|
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
|
if (field->prefix_len > 0
|
||||||
&& new_val->len != UNIV_SQL_NULL) {
|
&& new_val->len != UNIV_SQL_NULL) {
|
||||||
|
|
||||||
/* For prefix keys get the storage length
|
cur_type = dict_col_get_type(
|
||||||
for the prefix_len characters. */
|
dict_field_get_col(field));
|
||||||
|
|
||||||
cur_type = dict_col_get_type(
|
dfield->len =
|
||||||
dict_field_get_col(field));
|
dtype_get_at_most_n_mbchars(
|
||||||
|
cur_type,
|
||||||
dfield->len =
|
field->prefix_len,
|
||||||
innobase_get_at_most_n_mbchars(
|
new_val->len,
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
new_val->data);
|
||||||
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
|
if (field->prefix_len > 0
|
||||||
&& new_val->len != UNIV_SQL_NULL) {
|
&& new_val->len != UNIV_SQL_NULL) {
|
||||||
|
|
||||||
/* For prefix keys get the storage length
|
cur_type = dict_col_get_type(
|
||||||
for the prefix_len characters. */
|
dict_field_get_col(field));
|
||||||
|
|
||||||
cur_type = dict_col_get_type(
|
dfield->len =
|
||||||
dict_field_get_col(field));
|
dtype_get_at_most_n_mbchars(
|
||||||
|
cur_type,
|
||||||
dfield->len =
|
field->prefix_len,
|
||||||
innobase_get_at_most_n_mbchars(
|
new_val->len,
|
||||||
dtype_get_charset_coll(cur_type->prtype),
|
new_val->data);
|
||||||
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 */
|
char *binlog_name, /* in: binlog name */
|
||||||
longlong offset /* in: binlog offset */
|
longlong offset /* in: binlog offset */
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
mtr_t mtr;
|
mtr_t mtr;
|
||||||
|
|
||||||
assert(binlog_name != NULL);
|
assert(binlog_name != NULL);
|
||||||
@ -5298,50 +5297,58 @@ ulonglong ha_innobase::get_mysql_bin_log_pos()
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
This function is used to find storage length of prefix_len characters
|
This function is used to find the storage length in bytes of the first n
|
||||||
in bytes for prefix indexes using multibyte character set.
|
characters for prefix indexes using a multibyte character set. The function
|
||||||
Function finds charset information and returns length of
|
finds charset information and returns length of prefix_len characters in the
|
||||||
prefix_len characters in the index field in bytes. */
|
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 charset_id, /* in: character set id */
|
||||||
ulint prefix_len, /* in: prefix length of the index */
|
ulint prefix_len, /* in: prefix length in bytes of the index
|
||||||
ulint data_len, /* in: length of the sting in bytes */
|
(this has to be divided by mbmaxlen to get the
|
||||||
const char *pos) /* in: character string */
|
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 char_length; /* character length in bytes */
|
||||||
|
ulint n_chars; /* number of characters in prefix */
|
||||||
CHARSET_INFO* charset; /* charset used in the field */
|
CHARSET_INFO* charset; /* charset used in the field */
|
||||||
|
|
||||||
ut_ad(pos);
|
|
||||||
byte_length = data_len;
|
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);
|
||||||
ut_ad(charset->mbmaxlen);
|
ut_ad(charset->mbmaxlen);
|
||||||
|
|
||||||
/* Calculate the storage length of the one character in bytes and
|
/* Calculate how many characters at most the prefix index contains */
|
||||||
how many characters the prefix index contains */
|
|
||||||
|
|
||||||
char_length = byte_length / charset->mbmaxlen;
|
n_chars = prefix_len / charset->mbmaxlen;
|
||||||
prefix_len = prefix_len / charset->mbmaxlen;
|
|
||||||
|
|
||||||
/* If length of the string is greater than storage length of the
|
/* If the charset is multi-byte, then we must find the length of the
|
||||||
one character, we have to find the storage position of the
|
first at most n chars in the string. If the string contains less
|
||||||
prefix_len character in the string */
|
characters than n, then we return the length to the end of the last
|
||||||
|
full character. */
|
||||||
|
|
||||||
if (byte_length > char_length) {
|
if (charset->mbmaxlen > 1) {
|
||||||
char_length = my_charpos(charset, pos,
|
/* my_charpos() returns the byte length of the first n_chars
|
||||||
pos + byte_length, prefix_len);
|
characters, or the end of the last full character */
|
||||||
set_if_smaller(char_length, byte_length);
|
|
||||||
}
|
char_length = my_charpos(charset, str,
|
||||||
else {
|
str + byte_length, n_chars);
|
||||||
|
} else {
|
||||||
char_length = prefix_len;
|
char_length = prefix_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return char_length;
|
return(char_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user