Commit 67d0502b authored by unknown's avatar unknown

InnoDB ON UPDATE CASCADE fixes:

Enforce maximum char_length of UTF-8 data (Bug #10409).
Pad UTF-8 variable-length CHAR columns with 0x20.
Pad UCS2 CHAR columns with 0x0020 (Bug #10511).


innobase/data/data0type.c:
  dtype_get_at_most_n_mbchars(): Avoid division by zero in assertion
  when this function is called with dtype->mbmaxlen==0
innobase/row/row0ins.c:
  row_ins_cascade_calc_update_vec(): Enforce maximum char_length of
  UTF-8 data (Bug #10409).
  Pad UTF-8 CHAR columns with 0x20.
  Pad UCS2 CHAR columns with 0x0020 (Bug #10511).
parent 807a543b
......@@ -63,9 +63,10 @@ dtype_get_at_most_n_mbchars(
{
#ifndef UNIV_HOTBACKUP
ut_a(data_len != UNIV_SQL_NULL);
ut_a(!(prefix_len % dtype->mbmaxlen));
ut_ad(!dtype->mbmaxlen || !(prefix_len % dtype->mbmaxlen));
if (dtype->mbminlen != dtype->mbmaxlen) {
ut_a(!(prefix_len % dtype->mbmaxlen));
return(innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(dtype->prtype),
prefix_len, data_len, str));
......
......@@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec(
if (parent_ufield->field_no == parent_field_no) {
ulint fixed_size;
ulint min_size;
/* A field in the parent index record is
updated. Let us make the update vector
......@@ -508,10 +508,13 @@ row_ins_cascade_calc_update_vec(
column, do not allow the update */
if (ufield->new_val.len != UNIV_SQL_NULL
&& ufield->new_val.len
> dtype_get_len(type)) {
&& dtype_get_at_most_n_mbchars(
type, dtype_get_len(type),
ufield->new_val.len,
ufield->new_val.data)
< ufield->new_val.len) {
return(ULINT_UNDEFINED);
return(ULINT_UNDEFINED);
}
/* If the parent column type has a different
......@@ -519,29 +522,46 @@ row_ins_cascade_calc_update_vec(
need to pad with spaces the new value of the
child column */
fixed_size = dtype_get_fixed_size(type);
/* TODO: pad in UCS-2 with 0x0020.
TODO: How does the special truncation of
UTF-8 CHAR cols affect this? */
min_size = dtype_get_min_size(type);
if (fixed_size
if (min_size
&& ufield->new_val.len != UNIV_SQL_NULL
&& ufield->new_val.len < fixed_size) {
&& ufield->new_val.len < min_size) {
char* pad_start;
const char* pad_end;
ufield->new_val.data =
mem_heap_alloc(heap,
fixed_size);
ufield->new_val.len = fixed_size;
ut_a(dtype_get_pad_char(type)
!= ULINT_UNDEFINED);
memset(ufield->new_val.data,
(byte)dtype_get_pad_char(type),
fixed_size);
min_size);
pad_start = ufield->new_val.data
+ ufield->new_val.len;
pad_end = ufield->new_val.data
+ min_size;
ufield->new_val.len = min_size;
ut_memcpy(ufield->new_val.data,
parent_ufield->new_val.data,
parent_ufield->new_val.len);
switch (UNIV_EXPECT(
dtype_get_mbminlen(type), 1)) {
default:
ut_error;
case 1:
/* space=0x20 */
memset(pad_start, 0x20,
pad_end - pad_start);
break;
case 2:
/* space=0x0020 */
ut_a(!(ufield->new_val.len
% 2));
ut_a(!(min_size % 2));
do {
*pad_start++ = 0x00;
*pad_start++ = 0x20;
} while (pad_start < pad_end);
break;
}
}
ufield->extern_storage = FALSE;
......
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