Commit deaba603 authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#52199 utf32: mbminlen=4, mbmaxlen=4, type->mbminlen=0, type->mbmaxlen=4

Merge and adjust a forgotten change to fix this bug.
rb://393 approved by Jimmy Yang
  ------------------------------------------------------------------------
  r3794 | marko | 2009-01-07 14:14:53 +0000 (Wed, 07 Jan 2009) | 18 lines

  branches/6.0: Allow the minimum length of a multi-byte character to be
  up to 4 bytes. (Bug #35391)

  dtype_t, dict_col_t: Replace mbminlen:2, mbmaxlen:3 with mbminmaxlen:5.
  In this way, the 5 bits can hold two values of 0..4, and the storage size
  of the fields will not cross the 64-bit boundary.  Encode the values as
  DATA_MBMAX * mbmaxlen + mbminlen.  Define the auxiliary macros
  DB_MBMINLEN(mbminmaxlen), DB_MBMAXLEN(mbminmaxlen), and
  DB_MINMAXLEN(mbminlen, mbmaxlen).

  Try to trim and pad UTF-16 and UTF-32 with spaces as appropriate.

  Alexander Barkov suggested the use of cs->cset->fill(cs, buff, len, 0x20).
  ha_innobase::store_key_val_for_row() now does that, but the added function
  row_mysql_pad_col() does not, because it doesn't have the MySQL TABLE object.

  rb://49 approved by Heikki Tuuri
  ------------------------------------------------------------------------
parent 3d2c88ad
CREATE TABLE bug52199 (a INT NOT NULL,
b CHAR(125) CHARACTER SET utf32 COLLATE utf32_bin NOT NULL
)ENGINE=InnoDB;
CREATE UNIQUE INDEX idx ON bug52199(a);
DROP TABLE bug52199;
-- source include/have_innodb.inc
CREATE TABLE bug52199 (a INT NOT NULL,
b CHAR(125) CHARACTER SET utf32 COLLATE utf32_bin NOT NULL
)ENGINE=InnoDB;
CREATE UNIQUE INDEX idx ON bug52199(a);
DROP TABLE bug52199;
...@@ -49,10 +49,8 @@ ulint ...@@ -49,10 +49,8 @@ ulint
dtype_get_at_most_n_mbchars( dtype_get_at_most_n_mbchars(
/*========================*/ /*========================*/
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint mbminlen, /*!< in: minimum length of a ulint mbminmaxlen, /*!< in: minimum and maximum length of
multi-byte character */ a multi-byte character */
ulint mbmaxlen, /*!< in: maximum length of a
multi-byte character */
ulint prefix_len, /*!< in: length of the requested ulint prefix_len, /*!< in: length of the requested
prefix, in characters, multiplied by prefix, in characters, multiplied by
dtype_get_mbmaxlen(dtype) */ dtype_get_mbmaxlen(dtype) */
...@@ -60,6 +58,9 @@ dtype_get_at_most_n_mbchars( ...@@ -60,6 +58,9 @@ dtype_get_at_most_n_mbchars(
const char* str) /*!< in: the string whose prefix const char* str) /*!< in: the string whose prefix
length is being determined */ length is being determined */
{ {
ulint mbminlen = DATA_MBMINLEN(mbminmaxlen);
ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen);
ut_a(data_len != UNIV_SQL_NULL); ut_a(data_len != UNIV_SQL_NULL);
ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen));
...@@ -180,7 +181,7 @@ dtype_validate( ...@@ -180,7 +181,7 @@ dtype_validate(
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
ut_a(type->mbminlen <= type->mbmaxlen); ut_a(dtype_get_mbminlen(type) <= dtype_get_mbmaxlen(type));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
return(TRUE); return(TRUE);
......
...@@ -206,6 +206,37 @@ dict_mem_table_add_col( ...@@ -206,6 +206,37 @@ dict_mem_table_add_col(
dict_mem_fill_column_struct(col, i, mtype, prtype, len); dict_mem_fill_column_struct(col, i, mtype, prtype, len);
} }
/**********************************************************************//**
This function populates a dict_col_t memory structure with
supplied information. */
UNIV_INTERN
void
dict_mem_fill_column_struct(
/*========================*/
dict_col_t* column, /*!< out: column struct to be
filled */
ulint col_pos, /*!< in: column position */
ulint mtype, /*!< in: main data type */
ulint prtype, /*!< in: precise type */
ulint col_len) /*!< in: column length */
{
#ifndef UNIV_HOTBACKUP
ulint mbminlen;
ulint mbmaxlen;
#endif /* !UNIV_HOTBACKUP */
column->ind = (unsigned int) col_pos;
column->ord_part = 0;
column->mtype = (unsigned int) mtype;
column->prtype = (unsigned int) prtype;
column->len = (unsigned int) col_len;
#ifndef UNIV_HOTBACKUP
dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen);
#endif /* !UNIV_HOTBACKUP */
}
/**********************************************************************//** /**********************************************************************//**
Creates an index memory object. Creates an index memory object.
@return own: index object */ @return own: index object */
......
...@@ -1036,6 +1036,8 @@ innobase_get_cset_width( ...@@ -1036,6 +1036,8 @@ innobase_get_cset_width(
if (cs) { if (cs) {
*mbminlen = cs->mbminlen; *mbminlen = cs->mbminlen;
*mbmaxlen = cs->mbmaxlen; *mbmaxlen = cs->mbmaxlen;
ut_ad(*mbminlen < DATA_MBMAX);
ut_ad(*mbmaxlen < DATA_MBMAX);
} else { } else {
THD* thd = current_thd; THD* thd = current_thd;
...@@ -4433,15 +4435,14 @@ ha_innobase::store_key_val_for_row( ...@@ -4433,15 +4435,14 @@ ha_innobase::store_key_val_for_row(
memcpy(buff, src_start, true_len); memcpy(buff, src_start, true_len);
buff += true_len; buff += true_len;
/* Pad the unused space with spaces. Note that no /* Pad the unused space with spaces. */
padding is ever needed for UCS-2 because in MySQL,
all UCS2 characters are 2 bytes, as MySQL does not
support surrogate pairs, which are needed to represent
characters in the range U+10000 to U+10FFFF. */
if (true_len < key_len) { if (true_len < key_len) {
ulint pad_len = key_len - true_len; ulint pad_len = key_len - true_len;
memset(buff, ' ', pad_len); ut_a(!(pad_len % cs->mbminlen));
cs->cset->fill(cs, buff, pad_len,
0x20 /* space */);
buff += pad_len; buff += pad_len;
} }
} }
...@@ -4550,6 +4551,7 @@ build_template( ...@@ -4550,6 +4551,7 @@ build_template(
/* Note that in InnoDB, i is the column number. MySQL calls columns /* Note that in InnoDB, i is the column number. MySQL calls columns
'fields'. */ 'fields'. */
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
const dict_col_t* col = &index->table->cols[i];
templ = prebuilt->mysql_template + n_requested_fields; templ = prebuilt->mysql_template + n_requested_fields;
field = table->field[i]; field = table->field[i];
...@@ -4598,7 +4600,7 @@ include_field: ...@@ -4598,7 +4600,7 @@ include_field:
if (index == clust_index) { if (index == clust_index) {
templ->rec_field_no = dict_col_get_clust_pos( templ->rec_field_no = dict_col_get_clust_pos(
&index->table->cols[i], index); col, index);
} else { } else {
templ->rec_field_no = dict_index_get_nth_col_pos( templ->rec_field_no = dict_index_get_nth_col_pos(
index, i); index, i);
...@@ -4627,7 +4629,7 @@ include_field: ...@@ -4627,7 +4629,7 @@ include_field:
mysql_prefix_len = templ->mysql_col_offset mysql_prefix_len = templ->mysql_col_offset
+ templ->mysql_col_len; + templ->mysql_col_len;
} }
templ->type = index->table->cols[i].mtype; templ->type = col->mtype;
templ->mysql_type = (ulint)field->type(); templ->mysql_type = (ulint)field->type();
if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
...@@ -4635,12 +4637,10 @@ include_field: ...@@ -4635,12 +4637,10 @@ include_field:
(((Field_varstring*)field)->length_bytes); (((Field_varstring*)field)->length_bytes);
} }
templ->charset = dtype_get_charset_coll( templ->charset = dtype_get_charset_coll(col->prtype);
index->table->cols[i].prtype); templ->mbminlen = dict_col_get_mbminlen(col);
templ->mbminlen = index->table->cols[i].mbminlen; templ->mbmaxlen = dict_col_get_mbmaxlen(col);
templ->mbmaxlen = index->table->cols[i].mbmaxlen; templ->is_unsigned = col->prtype & DATA_UNSIGNED;
templ->is_unsigned = index->table->cols[i].prtype
& DATA_UNSIGNED;
if (templ->type == DATA_BLOB) { if (templ->type == DATA_BLOB) {
prebuilt->templ_contains_blob = TRUE; prebuilt->templ_contains_blob = TRUE;
} }
......
...@@ -99,8 +99,10 @@ innobase_col_to_mysql( ...@@ -99,8 +99,10 @@ innobase_col_to_mysql(
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
case DATA_MYSQL: case DATA_MYSQL:
ut_ad(flen >= len); ut_ad(flen >= len);
ut_ad(col->mbmaxlen >= col->mbminlen); ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
ut_ad(col->mbmaxlen > col->mbminlen || flen == len); >= DATA_MBMINLEN(col->mbminmaxlen));
ut_ad(DATA_MBMAXLEN(col->mbminmaxlen)
> DATA_MBMINLEN(col->mbminmaxlen) || flen == len);
memcpy(dest, data, len); memcpy(dest, data, len);
break; break;
......
...@@ -168,6 +168,17 @@ SQL null*/ ...@@ -168,6 +168,17 @@ 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
/* Maximum multi-byte character length in bytes, plus 1 */
#define DATA_MBMAX 5
/* Pack mbminlen, mbmaxlen to mbminmaxlen. */
#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \
((mbmaxlen) * DATA_MBMAX + (mbminlen))
/* Get mbminlen from mbminmaxlen. */
#define DATA_MBMINLEN(mbminmaxlen) UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), 1)
/* Get mbmaxlen from mbminmaxlen. */
#define DATA_MBMAXLEN(mbminmaxlen) ((mbminmaxlen) / DATA_MBMAX)
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/*********************************************************************//** /*********************************************************************//**
Gets the MySQL type code from a dtype. Gets the MySQL type code from a dtype.
...@@ -187,10 +198,8 @@ ulint ...@@ -187,10 +198,8 @@ ulint
dtype_get_at_most_n_mbchars( dtype_get_at_most_n_mbchars(
/*========================*/ /*========================*/
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint mbminlen, /*!< in: minimum length of a ulint mbminmaxlen, /*!< in: minimum and maximum length of
multi-byte character */ a multi-byte character */
ulint mbmaxlen, /*!< in: maximum length of a
multi-byte character */
ulint prefix_len, /*!< in: length of the requested ulint prefix_len, /*!< in: length of the requested
prefix, in characters, multiplied by prefix, in characters, multiplied by
dtype_get_mbmaxlen(dtype) */ dtype_get_mbmaxlen(dtype) */
...@@ -335,6 +344,19 @@ dtype_get_mbmaxlen( ...@@ -335,6 +344,19 @@ dtype_get_mbmaxlen(
/*===============*/ /*===============*/
const dtype_t* type); /*!< in: type */ const dtype_t* type); /*!< in: type */
/*********************************************************************//** /*********************************************************************//**
Sets the minimum and maximum length of a character, in bytes. */
UNIV_INLINE
void
dtype_set_mbminmaxlen(
/*==================*/
dtype_t* type, /*!< in/out: type */
ulint mbminlen, /*!< in: minimum length of a char,
in bytes, or 0 if this is not
a character type */
ulint mbmaxlen); /*!< in: maximum length of a char,
in bytes, or 0 if this is not
a character type */
/*********************************************************************//**
Gets the padding character code for the type. Gets the padding character code for the type.
@return padding character code, or ULINT_UNDEFINED if no padding specified */ @return padding character code, or ULINT_UNDEFINED if no padding specified */
UNIV_INLINE UNIV_INLINE
...@@ -354,8 +376,8 @@ dtype_get_fixed_size_low( ...@@ -354,8 +376,8 @@ dtype_get_fixed_size_low(
ulint mtype, /*!< in: main type */ ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */ ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */ ulint mbminmaxlen, /*!< in: minimum and maximum length of a
ulint mbmaxlen, /*!< in: maximum length of a multibyte char */ multibyte character, in bytes */
ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */ ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
/***********************************************************************//** /***********************************************************************//**
...@@ -368,8 +390,8 @@ dtype_get_min_size_low( ...@@ -368,8 +390,8 @@ dtype_get_min_size_low(
ulint mtype, /*!< in: main type */ ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */ ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */ ulint mbminmaxlen); /*!< in: minimum and maximum length of a
ulint mbmaxlen); /*!< in: maximum length of a multibyte char */ multibyte character */
/***********************************************************************//** /***********************************************************************//**
Returns the maximum size of a data type. Note: types in system tables may be Returns the maximum size of a data type. Note: types in system tables may be
incomplete and return incorrect information. incomplete and return incorrect information.
...@@ -472,10 +494,11 @@ struct dtype_struct{ ...@@ -472,10 +494,11 @@ struct dtype_struct{
the string, MySQL uses 1 or 2 the string, MySQL uses 1 or 2
bytes to store the string length) */ bytes to store the string length) */
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
unsigned mbminlen:2; /*!< minimum length of a unsigned mbminmaxlen:5; /*!< minimum and maximum length of a
character, in bytes */ character, in bytes;
unsigned mbmaxlen:3; /*!< maximum length of a DATA_MBMINMAXLEN(mbminlen,mbmaxlen);
character, in bytes */ mbminlen=DATA_MBMINLEN(mbminmaxlen);
mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
}; };
......
...@@ -93,13 +93,34 @@ dtype_get_mblen( ...@@ -93,13 +93,34 @@ dtype_get_mblen(
innobase_get_cset_width(dtype_get_charset_coll(prtype), innobase_get_cset_width(dtype_get_charset_coll(prtype),
mbminlen, mbmaxlen); mbminlen, mbmaxlen);
ut_ad(*mbminlen <= *mbmaxlen); ut_ad(*mbminlen <= *mbmaxlen);
ut_ad(*mbminlen <= 2); /* mbminlen in dtype_t is 0..3 */ ut_ad(*mbminlen < DATA_MBMAX);
ut_ad(*mbmaxlen < 1 << 3); /* mbmaxlen in dtype_t is 0..7 */ ut_ad(*mbmaxlen < DATA_MBMAX);
} else { } else {
*mbminlen = *mbmaxlen = 0; *mbminlen = *mbmaxlen = 0;
} }
} }
/*********************************************************************//**
Sets the minimum and maximum length of a character, in bytes. */
UNIV_INLINE
void
dtype_set_mbminmaxlen(
/*==================*/
dtype_t* type, /*!< in/out: type */
ulint mbminlen, /*!< in: minimum length of a char,
in bytes, or 0 if this is not
a character type */
ulint mbmaxlen) /*!< in: maximum length of a char,
in bytes, or 0 if this is not
a character type */
{
ut_ad(mbminlen < DATA_MBMAX);
ut_ad(mbmaxlen < DATA_MBMAX);
ut_ad(mbminlen <= mbmaxlen);
type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
}
/*********************************************************************//** /*********************************************************************//**
Compute the mbminlen and mbmaxlen members of a data type structure. */ Compute the mbminlen and mbmaxlen members of a data type structure. */
UNIV_INLINE UNIV_INLINE
...@@ -112,8 +133,7 @@ dtype_set_mblen( ...@@ -112,8 +133,7 @@ dtype_set_mblen(
ulint mbmaxlen; ulint mbmaxlen;
dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen);
type->mbminlen = mbminlen; dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen);
type->mbmaxlen = mbmaxlen;
ut_ad(dtype_validate(type)); ut_ad(dtype_validate(type));
} }
...@@ -210,7 +230,7 @@ dtype_get_mbminlen( ...@@ -210,7 +230,7 @@ dtype_get_mbminlen(
const dtype_t* type) /*!< in: type */ const dtype_t* type) /*!< in: type */
{ {
ut_ad(type); ut_ad(type);
return(type->mbminlen); return(DATA_MBMINLEN(type->mbminmaxlen));
} }
/*********************************************************************//** /*********************************************************************//**
Gets the maximum length of a character, in bytes. Gets the maximum length of a character, in bytes.
...@@ -223,7 +243,7 @@ dtype_get_mbmaxlen( ...@@ -223,7 +243,7 @@ dtype_get_mbmaxlen(
const dtype_t* type) /*!< in: type */ const dtype_t* type) /*!< in: type */
{ {
ut_ad(type); ut_ad(type);
return(type->mbmaxlen); return(DATA_MBMAXLEN(type->mbminmaxlen));
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -404,8 +424,8 @@ dtype_get_fixed_size_low( ...@@ -404,8 +424,8 @@ dtype_get_fixed_size_low(
ulint mtype, /*!< in: main type */ ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */ ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */ ulint mbminmaxlen, /*!< in: minimum and maximum length of
ulint mbmaxlen, /*!< in: maximum length of a multibyte char */ a multibyte character, in bytes */
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
{ {
switch (mtype) { switch (mtype) {
...@@ -453,8 +473,9 @@ dtype_get_fixed_size_low( ...@@ -453,8 +473,9 @@ dtype_get_fixed_size_low(
dtype_get_charset_coll(prtype), dtype_get_charset_coll(prtype),
&i_mbminlen, &i_mbmaxlen); &i_mbminlen, &i_mbmaxlen);
if (UNIV_UNLIKELY(mbminlen != i_mbminlen) if (UNIV_UNLIKELY
|| UNIV_UNLIKELY(mbmaxlen != i_mbmaxlen)) { (DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen)
!= mbminmaxlen)) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: " fprintf(stderr, " InnoDB: "
...@@ -464,10 +485,10 @@ dtype_get_fixed_size_low( ...@@ -464,10 +485,10 @@ dtype_get_fixed_size_low(
"type->mbmaxlen=%lu\n", "type->mbmaxlen=%lu\n",
(ulong) i_mbminlen, (ulong) i_mbminlen,
(ulong) i_mbmaxlen, (ulong) i_mbmaxlen,
(ulong) mbminlen, (ulong) DATA_MBMINLEN(mbminmaxlen),
(ulong) mbmaxlen); (ulong) DATA_MBMAXLEN(mbminmaxlen));
} }
if (mbminlen == mbmaxlen) { if (i_mbminlen == i_mbmaxlen) {
return(len); return(len);
} }
} }
...@@ -499,8 +520,8 @@ dtype_get_min_size_low( ...@@ -499,8 +520,8 @@ dtype_get_min_size_low(
ulint mtype, /*!< in: main type */ ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint len, /*!< in: length */ ulint len, /*!< in: length */
ulint mbminlen, /*!< in: minimum length of a multibyte char */ ulint mbminmaxlen) /*!< in: minimum and maximum length of a
ulint mbmaxlen) /*!< in: maximum length of a multibyte char */ multi-byte character */
{ {
switch (mtype) { switch (mtype) {
case DATA_SYS: case DATA_SYS:
...@@ -527,14 +548,22 @@ dtype_get_min_size_low( ...@@ -527,14 +548,22 @@ dtype_get_min_size_low(
case DATA_DOUBLE: case DATA_DOUBLE:
return(len); return(len);
case DATA_MYSQL: case DATA_MYSQL:
if ((prtype & DATA_BINARY_TYPE) || mbminlen == mbmaxlen) { if (prtype & DATA_BINARY_TYPE) {
return(len);
} else {
ulint mbminlen = DATA_MBMINLEN(mbminmaxlen);
ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen);
if (mbminlen == mbmaxlen) {
return(len); return(len);
} }
/* this is a variable-length character set */ /* this is a variable-length character set */
ut_a(mbminlen > 0); ut_a(mbminlen > 0);
ut_a(mbmaxlen > mbminlen); ut_a(mbmaxlen > mbminlen);
ut_a(len % mbmaxlen == 0); ut_a(len % mbmaxlen == 0);
return(len * mbminlen / mbmaxlen); return(len * mbminlen / mbmaxlen);
}
case DATA_VARCHAR: case DATA_VARCHAR:
case DATA_BINARY: case DATA_BINARY:
case DATA_DECIMAL: case DATA_DECIMAL:
...@@ -595,9 +624,9 @@ dtype_get_sql_null_size( ...@@ -595,9 +624,9 @@ dtype_get_sql_null_size(
{ {
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
type->mbminlen, type->mbmaxlen, comp)); type->mbminmaxlen, comp));
#else /* !UNIV_HOTBACKUP */ #else /* !UNIV_HOTBACKUP */
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
0, 0, 0)); 0, 0));
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
} }
...@@ -102,6 +102,33 @@ void ...@@ -102,6 +102,33 @@ void
dict_load_space_id_list(void); dict_load_space_id_list(void);
/*=========================*/ /*=========================*/
/*********************************************************************//** /*********************************************************************//**
Gets the minimum number of bytes per character.
@return minimum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbminlen(
/*==================*/
const dict_col_t* col); /*!< in: column */
/*********************************************************************//**
Gets the maximum number of bytes per character.
@return maximum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbmaxlen(
/*==================*/
const dict_col_t* col); /*!< in: column */
/*********************************************************************//**
Sets the minimum and maximum number of bytes per character. */
UNIV_INLINE
void
dict_col_set_mbminmaxlen(
/*=====================*/
dict_col_t* col, /*!< in/out: column */
ulint mbminlen, /*!< in: minimum multi-byte
character size, in bytes */
ulint mbmaxlen); /*!< in: minimum multi-byte
character size, in bytes */
/*********************************************************************//**
Gets the column data type. */ Gets the column data type. */
UNIV_INLINE UNIV_INLINE
void void
......
...@@ -28,6 +28,46 @@ Created 1/8/1996 Heikki Tuuri ...@@ -28,6 +28,46 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0load.h" #include "dict0load.h"
#include "rem0types.h" #include "rem0types.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@return minimum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbminlen(
/*==================*/
const dict_col_t* col) /*!< in: column */
{
return(DATA_MBMINLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Gets the maximum number of bytes per character.
@return maximum multi-byte char size, in bytes */
UNIV_INLINE
ulint
dict_col_get_mbmaxlen(
/*==================*/
const dict_col_t* col) /*!< in: column */
{
return(DATA_MBMAXLEN(col->mbminmaxlen));
}
/*********************************************************************//**
Sets the minimum and maximum number of bytes per character. */
UNIV_INLINE
void
dict_col_set_mbminmaxlen(
/*=====================*/
dict_col_t* col, /*!< in/out: column */
ulint mbminlen, /*!< in: minimum multi-byte
character size, in bytes */
ulint mbmaxlen) /*!< in: minimum multi-byte
character size, in bytes */
{
ut_ad(mbminlen < DATA_MBMAX);
ut_ad(mbmaxlen < DATA_MBMAX);
ut_ad(mbminlen <= mbmaxlen);
col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
}
/*********************************************************************//** /*********************************************************************//**
Gets the column data type. */ Gets the column data type. */
UNIV_INLINE UNIV_INLINE
...@@ -42,8 +82,7 @@ dict_col_copy_type( ...@@ -42,8 +82,7 @@ dict_col_copy_type(
type->mtype = col->mtype; type->mtype = col->mtype;
type->prtype = col->prtype; type->prtype = col->prtype;
type->len = col->len; type->len = col->len;
type->mbminlen = col->mbminlen; type->mbminmaxlen = col->mbminmaxlen;
type->mbmaxlen = col->mbmaxlen;
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -65,8 +104,7 @@ dict_col_type_assert_equal( ...@@ -65,8 +104,7 @@ dict_col_type_assert_equal(
ut_ad(col->prtype == type->prtype); ut_ad(col->prtype == type->prtype);
ut_ad(col->len == type->len); ut_ad(col->len == type->len);
# ifndef UNIV_HOTBACKUP # ifndef UNIV_HOTBACKUP
ut_ad(col->mbminlen == type->mbminlen); ut_ad(col->mbminmaxlen == type->mbminmaxlen);
ut_ad(col->mbmaxlen == type->mbmaxlen);
# endif /* !UNIV_HOTBACKUP */ # endif /* !UNIV_HOTBACKUP */
return(TRUE); return(TRUE);
...@@ -84,7 +122,7 @@ dict_col_get_min_size( ...@@ -84,7 +122,7 @@ dict_col_get_min_size(
const dict_col_t* col) /*!< in: column */ const dict_col_t* col) /*!< in: column */
{ {
return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, return(dtype_get_min_size_low(col->mtype, col->prtype, col->len,
col->mbminlen, col->mbmaxlen)); col->mbminmaxlen));
} }
/***********************************************************************//** /***********************************************************************//**
Returns the maximum size of the column. Returns the maximum size of the column.
...@@ -109,7 +147,7 @@ dict_col_get_fixed_size( ...@@ -109,7 +147,7 @@ dict_col_get_fixed_size(
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
{ {
return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
col->mbminlen, col->mbmaxlen, comp)); col->mbminmaxlen, comp));
} }
/***********************************************************************//** /***********************************************************************//**
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
......
...@@ -151,9 +151,9 @@ dict_mem_table_add_col( ...@@ -151,9 +151,9 @@ dict_mem_table_add_col(
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint len); /*!< in: precision */ ulint len); /*!< in: precision */
/**********************************************************************//** /**********************************************************************//**
This function poplulates a dict_col_t memory structure with This function populates a dict_col_t memory structure with
supplied information. */ supplied information. */
UNIV_INLINE UNIV_INTERN
void void
dict_mem_fill_column_struct( dict_mem_fill_column_struct(
/*========================*/ /*========================*/
...@@ -162,7 +162,7 @@ dict_mem_fill_column_struct( ...@@ -162,7 +162,7 @@ dict_mem_fill_column_struct(
ulint col_pos, /*!< in: column position */ ulint col_pos, /*!< in: column position */
ulint mtype, /*!< in: main data type */ ulint mtype, /*!< in: main data type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint col_len); /*!< in: column lenght */ ulint col_len); /*!< in: column length */
/**********************************************************************//** /**********************************************************************//**
This function poplulates a dict_index_t index memory structure with This function poplulates a dict_index_t index memory structure with
supplied information. */ supplied information. */
...@@ -249,10 +249,11 @@ struct dict_col_struct{ ...@@ -249,10 +249,11 @@ struct dict_col_struct{
the string, MySQL uses 1 or 2 the string, MySQL uses 1 or 2
bytes to store the string length) */ bytes to store the string length) */
unsigned mbminlen:2; /*!< minimum length of a unsigned mbminmaxlen:5; /*!< minimum and maximum length of a
character, in bytes */ character, in bytes;
unsigned mbmaxlen:3; /*!< maximum length of a DATA_MBMINMAXLEN(mbminlen,mbmaxlen);
character, in bytes */ mbminlen=DATA_MBMINLEN(mbminmaxlen);
mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */
/*----------------------*/ /*----------------------*/
/* End of definitions copied from dtype_t */ /* End of definitions copied from dtype_t */
/* @} */ /* @} */
......
...@@ -70,35 +70,3 @@ dict_mem_fill_index_struct( ...@@ -70,35 +70,3 @@ dict_mem_fill_index_struct(
index->magic_n = DICT_INDEX_MAGIC_N; index->magic_n = DICT_INDEX_MAGIC_N;
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
} }
/**********************************************************************//**
This function poplulates a dict_col_t memory structure with
supplied information. */
UNIV_INLINE
void
dict_mem_fill_column_struct(
/*========================*/
dict_col_t* column, /*!< out: column struct to be
filled */
ulint col_pos, /*!< in: column position */
ulint mtype, /*!< in: main data type */
ulint prtype, /*!< in: precise type */
ulint col_len) /*!< in: column lenght */
{
#ifndef UNIV_HOTBACKUP
ulint mbminlen;
ulint mbmaxlen;
#endif /* !UNIV_HOTBACKUP */
column->ind = (unsigned int) col_pos;
column->ord_part = 0;
column->mtype = (unsigned int) mtype;
column->prtype = (unsigned int) prtype;
column->len = (unsigned int) col_len;
#ifndef UNIV_HOTBACKUP
dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
column->mbminlen = (unsigned int) mbminlen;
column->mbmaxlen = (unsigned int) mbmaxlen;
#endif /* !UNIV_HOTBACKUP */
}
...@@ -103,6 +103,17 @@ row_mysql_read_blob_ref( ...@@ -103,6 +103,17 @@ row_mysql_read_blob_ref(
ulint col_len); /*!< in: BLOB reference length ulint col_len); /*!< in: BLOB reference length
(not BLOB length) */ (not BLOB length) */
/**************************************************************//** /**************************************************************//**
Pad a column with spaces. */
UNIV_INTERN
void
row_mysql_pad_col(
/*==============*/
ulint mbminlen, /*!< in: minimum size of a character,
in bytes */
byte* pad, /*!< out: padded buffer */
ulint len); /*!< in: number of bytes to pad */
/**************************************************************//**
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format. Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
The counterpart of this function is row_sel_field_store_in_mysql_format() in The counterpart of this function is row_sel_field_store_in_mysql_format() in
row0sel.c. row0sel.c.
......
...@@ -515,8 +515,7 @@ row_ins_cascade_calc_update_vec( ...@@ -515,8 +515,7 @@ row_ins_cascade_calc_update_vec(
if (!dfield_is_null(&ufield->new_val) if (!dfield_is_null(&ufield->new_val)
&& dtype_get_at_most_n_mbchars( && dtype_get_at_most_n_mbchars(
col->prtype, col->prtype, col->mbminmaxlen,
col->mbminlen, col->mbmaxlen,
col->len, col->len,
ufield_len, ufield_len,
dfield_get_data(&ufield->new_val)) dfield_get_data(&ufield->new_val))
...@@ -539,49 +538,37 @@ row_ins_cascade_calc_update_vec( ...@@ -539,49 +538,37 @@ row_ins_cascade_calc_update_vec(
if (min_size > ufield_len) { if (min_size > ufield_len) {
char* pad_start; byte* pad;
const char* pad_end; ulint pad_len;
char* padded_data byte* padded_data;
= mem_heap_alloc( ulint mbminlen;
padded_data = mem_heap_alloc(
heap, min_size); heap, min_size);
pad_start = padded_data + ufield_len;
pad_end = padded_data + min_size; pad = padded_data + ufield_len;
pad_len = min_size - ufield_len;
memcpy(padded_data, memcpy(padded_data,
dfield_get_data(&ufield dfield_get_data(&ufield
->new_val), ->new_val),
dfield_get_len(&ufield ufield_len);
->new_val));
switch (UNIV_EXPECT(col->mbminlen,1)) { mbminlen = dict_col_get_mbminlen(col);
default:
ut_error; ut_ad(!(ufield_len % mbminlen));
return(ULINT_UNDEFINED); ut_ad(!(min_size % mbminlen));
case 1:
if (UNIV_UNLIKELY if (mbminlen == 1
(dtype_get_charset_coll( && dtype_get_charset_coll(
col->prtype) col->prtype)
== DATA_MYSQL_BINARY_CHARSET_COLL)) { == DATA_MYSQL_BINARY_CHARSET_COLL) {
/* Do not pad BINARY /* Do not pad BINARY columns */
columns. */
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
} }
/* space=0x20 */ row_mysql_pad_col(mbminlen,
memset(pad_start, 0x20, pad, pad_len);
pad_end - pad_start);
break;
case 2:
/* space=0x0020 */
ut_a(!(ufield_len % 2));
ut_a(!(min_size % 2));
do {
*pad_start++ = 0x00;
*pad_start++ = 0x20;
} while (pad_start < pad_end);
break;
}
dfield_set_data(&ufield->new_val, dfield_set_data(&ufield->new_val,
padded_data, min_size); padded_data, min_size);
} }
...@@ -2232,7 +2219,7 @@ row_ins_index_entry_set_vals( ...@@ -2232,7 +2219,7 @@ row_ins_index_entry_set_vals(
= dict_field_get_col(ind_field); = dict_field_get_col(ind_field);
len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminmaxlen,
ind_field->prefix_len, ind_field->prefix_len,
len, dfield_get_data(row_field)); len, dfield_get_data(row_field));
......
...@@ -338,7 +338,7 @@ row_merge_buf_add( ...@@ -338,7 +338,7 @@ row_merge_buf_add(
if (ifield->prefix_len) { if (ifield->prefix_len) {
len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->prtype,
col->mbminlen, col->mbmaxlen, col->mbminmaxlen,
ifield->prefix_len, ifield->prefix_len,
len, dfield_get_data(field)); len, dfield_get_data(field));
dfield_set_len(field, len); dfield_set_len(field, len);
......
...@@ -265,6 +265,49 @@ row_mysql_read_blob_ref( ...@@ -265,6 +265,49 @@ row_mysql_read_blob_ref(
return(data); return(data);
} }
/**************************************************************//**
Pad a column with spaces. */
UNIV_INTERN
void
row_mysql_pad_col(
/*==============*/
ulint mbminlen, /*!< in: minimum size of a character,
in bytes */
byte* pad, /*!< out: padded buffer */
ulint len) /*!< in: number of bytes to pad */
{
const byte* pad_end;
switch (UNIV_EXPECT(mbminlen, 1)) {
default:
ut_error;
case 1:
/* space=0x20 */
memset(pad, 0x20, len);
break;
case 2:
/* space=0x0020 */
pad_end = pad + len;
ut_a(!(len % 2));
do {
*pad++ = 0x00;
*pad++ = 0x20;
} while (pad < pad_end);
break;
case 4:
/* space=0x00000020 */
pad_end = pad + len;
ut_a(!(len % 4));
do {
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x00;
*pad++ = 0x20;
} while (pad < pad_end);
break;
}
}
/**************************************************************//** /**************************************************************//**
Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format. Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.
The counterpart of this function is row_sel_field_store_in_mysql_format() in The counterpart of this function is row_sel_field_store_in_mysql_format() in
...@@ -357,12 +400,28 @@ row_mysql_store_col_in_innobase_format( ...@@ -357,12 +400,28 @@ row_mysql_store_col_in_innobase_format(
/* Remove trailing spaces from old style VARCHAR /* Remove trailing spaces from old style VARCHAR
columns. */ columns. */
/* Handle UCS2 strings differently. */ /* Handle Unicode strings differently. */
ulint mbminlen = dtype_get_mbminlen(dtype); ulint mbminlen = dtype_get_mbminlen(dtype);
ptr = mysql_data; ptr = mysql_data;
if (mbminlen == 2) { switch (mbminlen) {
default:
ut_error;
case 4:
/* space=0x00000020 */
/* Trim "half-chars", just in case. */
col_len &= ~3;
while (col_len >= 4
&& ptr[col_len - 4] == 0x00
&& ptr[col_len - 3] == 0x00
&& ptr[col_len - 2] == 0x00
&& ptr[col_len - 1] == 0x20) {
col_len -= 4;
}
break;
case 2:
/* space=0x0020 */ /* space=0x0020 */
/* Trim "half-chars", just in case. */ /* Trim "half-chars", just in case. */
col_len &= ~1; col_len &= ~1;
...@@ -371,8 +430,8 @@ row_mysql_store_col_in_innobase_format( ...@@ -371,8 +430,8 @@ row_mysql_store_col_in_innobase_format(
&& ptr[col_len - 1] == 0x20) { && ptr[col_len - 1] == 0x20) {
col_len -= 2; col_len -= 2;
} }
} else { break;
ut_a(mbminlen == 1); case 1:
/* space=0x20 */ /* space=0x20 */
while (col_len > 0 while (col_len > 0
&& ptr[col_len - 1] == 0x20) { && ptr[col_len - 1] == 0x20) {
......
...@@ -156,7 +156,7 @@ row_build_index_entry( ...@@ -156,7 +156,7 @@ row_build_index_entry(
} }
len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminmaxlen,
ind_field->prefix_len, len, dfield_get_data(dfield)); ind_field->prefix_len, len, dfield_get_data(dfield));
dfield_set_len(dfield, len); dfield_set_len(dfield, len);
} }
...@@ -514,8 +514,7 @@ row_build_row_ref( ...@@ -514,8 +514,7 @@ row_build_row_ref(
dfield_set_len(dfield, dfield_set_len(dfield,
dtype_get_at_most_n_mbchars( dtype_get_at_most_n_mbchars(
dtype->prtype, dtype->prtype,
dtype->mbminlen, dtype->mbminmaxlen,
dtype->mbmaxlen,
clust_col_prefix_len, clust_col_prefix_len,
len, (char*) field)); len, (char*) field));
} }
...@@ -629,8 +628,7 @@ notfound: ...@@ -629,8 +628,7 @@ notfound:
dfield_set_len(dfield, dfield_set_len(dfield,
dtype_get_at_most_n_mbchars( dtype_get_at_most_n_mbchars(
dtype->prtype, dtype->prtype,
dtype->mbminlen, dtype->mbminmaxlen,
dtype->mbmaxlen,
clust_col_prefix_len, clust_col_prefix_len,
len, (char*) field)); len, (char*) field));
} }
......
...@@ -88,10 +88,8 @@ row_sel_sec_rec_is_for_blob( ...@@ -88,10 +88,8 @@ row_sel_sec_rec_is_for_blob(
/*========================*/ /*========================*/
ulint mtype, /*!< in: main type */ ulint mtype, /*!< in: main type */
ulint prtype, /*!< in: precise type */ ulint prtype, /*!< in: precise type */
ulint mbminlen, /*!< in: minimum length of a ulint mbminmaxlen, /*!< in: minimum and maximum length of
multi-byte character */ a multi-byte character */
ulint mbmaxlen, /*!< in: maximum length of a
multi-byte character */
const byte* clust_field, /*!< in: the locally stored part of const byte* clust_field, /*!< in: the locally stored part of
the clustered index column, including the clustered index column, including
the BLOB pointer; the clustered the BLOB pointer; the clustered
...@@ -119,7 +117,7 @@ row_sel_sec_rec_is_for_blob( ...@@ -119,7 +117,7 @@ row_sel_sec_rec_is_for_blob(
return(FALSE); return(FALSE);
} }
len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen,
sec_len, len, (const char*) buf); sec_len, len, (const char*) buf);
return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len));
...@@ -202,14 +200,14 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -202,14 +200,14 @@ row_sel_sec_rec_is_for_clust_rec(
} }
len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminmaxlen,
ifield->prefix_len, len, (char*) clust_field); ifield->prefix_len, len, (char*) clust_field);
if (rec_offs_nth_extern(clust_offs, clust_pos) if (rec_offs_nth_extern(clust_offs, clust_pos)
&& len < sec_len) { && len < sec_len) {
if (!row_sel_sec_rec_is_for_blob( if (!row_sel_sec_rec_is_for_blob(
col->mtype, col->prtype, col->mtype, col->prtype,
col->mbminlen, col->mbmaxlen, col->mbminmaxlen,
clust_field, clust_len, clust_field, clust_len,
sec_field, sec_len, sec_field, sec_len,
dict_table_zip_size( dict_table_zip_size(
...@@ -2508,13 +2506,13 @@ row_sel_field_store_in_mysql_format( ...@@ -2508,13 +2506,13 @@ row_sel_field_store_in_mysql_format(
ulint len) /*!< in: length of the data */ ulint len) /*!< in: length of the data */
{ {
byte* ptr; byte* ptr;
byte* field_end;
byte* pad_ptr;
ut_ad(len != UNIV_SQL_NULL); ut_ad(len != UNIV_SQL_NULL);
UNIV_MEM_ASSERT_RW(data, len); UNIV_MEM_ASSERT_RW(data, len);
switch (templ->type) { switch (templ->type) {
const byte* field_end;
byte* pad;
case DATA_INT: case DATA_INT:
/* Convert integer data from Innobase to a little-endian /* Convert integer data from Innobase to a little-endian
format, sign bit restored to normal */ format, sign bit restored to normal */
...@@ -2558,38 +2556,32 @@ row_sel_field_store_in_mysql_format( ...@@ -2558,38 +2556,32 @@ row_sel_field_store_in_mysql_format(
unused end of a >= 5.0.3 true VARCHAR column, just in case unused end of a >= 5.0.3 true VARCHAR column, just in case
MySQL expects its contents to be deterministic. */ MySQL expects its contents to be deterministic. */
pad_ptr = dest + len; pad = dest + len;
ut_ad(templ->mbminlen <= templ->mbmaxlen); ut_ad(templ->mbminlen <= templ->mbmaxlen);
/* We handle UCS2 charset strings differently. */ /* We treat some Unicode charset strings specially. */
if (templ->mbminlen == 2) { switch (templ->mbminlen) {
/* A space char is two bytes, 0x0020 in UCS2 */ case 4:
/* InnoDB should never have stripped partial
UTF-32 characters. */
ut_a(!(len & 3));
break;
case 2:
/* A space char is two bytes,
0x0020 in UCS2 and UTF-16 */
if (len & 1) { if (UNIV_UNLIKELY(len & 1)) {
/* A 0x20 has been stripped from the column. /* A 0x20 has been stripped from the column.
Pad it back. */ Pad it back. */
if (pad_ptr < field_end) { if (pad < field_end) {
*pad_ptr = 0x20; *pad++ = 0x20;
pad_ptr++;
} }
} }
/* Pad the rest of the string with 0x0020 */
while (pad_ptr < field_end) {
*pad_ptr = 0x00;
pad_ptr++;
*pad_ptr = 0x20;
pad_ptr++;
} }
} else {
ut_ad(templ->mbminlen == 1);
/* space=0x20 */
memset(pad_ptr, 0x20, field_end - pad_ptr); row_mysql_pad_col(templ->mbminlen, pad, field_end - pad);
}
break; break;
case DATA_BLOB: case DATA_BLOB:
...@@ -2614,9 +2606,9 @@ row_sel_field_store_in_mysql_format( ...@@ -2614,9 +2606,9 @@ row_sel_field_store_in_mysql_format(
|| !(templ->mysql_col_len % templ->mbmaxlen)); || !(templ->mysql_col_len % templ->mbmaxlen));
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len); ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);
if (templ->mbminlen != templ->mbmaxlen) { if (templ->mbminlen == 1 && templ->mbmaxlen != 1) {
/* Pad with spaces. This undoes the stripping /* Pad with spaces. This undoes the stripping
done in row0mysql.ic, function done in row0mysql.c, function
row_mysql_store_col_in_innobase_format(). */ row_mysql_store_col_in_innobase_format(). */
memset(dest + len, 0x20, templ->mysql_col_len - len); memset(dest + len, 0x20, templ->mysql_col_len - len);
......
...@@ -949,7 +949,7 @@ row_upd_index_replace_new_col_val( ...@@ -949,7 +949,7 @@ row_upd_index_replace_new_col_val(
} }
len = dtype_get_at_most_n_mbchars(col->prtype, len = dtype_get_at_most_n_mbchars(col->prtype,
col->mbminlen, col->mbmaxlen, col->mbminmaxlen,
field->prefix_len, len, field->prefix_len, len,
(const char*) data); (const char*) data);
......
...@@ -2024,7 +2024,7 @@ trx_get_trx_by_xid( ...@@ -2024,7 +2024,7 @@ trx_get_trx_by_xid(
while (trx) { while (trx) {
/* Compare two X/Open XA transaction id's: their /* Compare two X/Open XA transaction id's: their
length should be the same and binary comparison length should be the same and binary comparison
of gtrid_lenght+bqual_length bytes should be of gtrid_length+bqual_length bytes should be
the same */ the same */
if (xid->gtrid_length == trx->xid.gtrid_length if (xid->gtrid_length == trx->xid.gtrid_length
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment