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( ...@@ -63,9 +63,10 @@ dtype_get_at_most_n_mbchars(
{ {
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
ut_a(data_len != UNIV_SQL_NULL); 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) { if (dtype->mbminlen != dtype->mbmaxlen) {
ut_a(!(prefix_len % dtype->mbmaxlen));
return(innobase_get_at_most_n_mbchars( return(innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(dtype->prtype), dtype_get_charset_coll(dtype->prtype),
prefix_len, data_len, str)); prefix_len, data_len, str));
......
...@@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec( ...@@ -478,7 +478,7 @@ row_ins_cascade_calc_update_vec(
if (parent_ufield->field_no == parent_field_no) { if (parent_ufield->field_no == parent_field_no) {
ulint fixed_size; ulint min_size;
/* A field in the parent index record is /* A field in the parent index record is
updated. Let us make the update vector updated. Let us make the update vector
...@@ -508,8 +508,11 @@ row_ins_cascade_calc_update_vec( ...@@ -508,8 +508,11 @@ row_ins_cascade_calc_update_vec(
column, do not allow the update */ column, do not allow the update */
if (ufield->new_val.len != UNIV_SQL_NULL if (ufield->new_val.len != UNIV_SQL_NULL
&& ufield->new_val.len && dtype_get_at_most_n_mbchars(
> dtype_get_len(type)) { type, dtype_get_len(type),
ufield->new_val.len,
ufield->new_val.data)
< ufield->new_val.len) {
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
} }
...@@ -519,29 +522,46 @@ row_ins_cascade_calc_update_vec( ...@@ -519,29 +522,46 @@ row_ins_cascade_calc_update_vec(
need to pad with spaces the new value of the need to pad with spaces the new value of the
child column */ child column */
fixed_size = dtype_get_fixed_size(type); min_size = dtype_get_min_size(type);
/* TODO: pad in UCS-2 with 0x0020. if (min_size
TODO: How does the special truncation of
UTF-8 CHAR cols affect this? */
if (fixed_size
&& ufield->new_val.len != UNIV_SQL_NULL && 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 = ufield->new_val.data =
mem_heap_alloc(heap, mem_heap_alloc(heap,
fixed_size); min_size);
ufield->new_val.len = fixed_size; pad_start = ufield->new_val.data
ut_a(dtype_get_pad_char(type) + ufield->new_val.len;
!= ULINT_UNDEFINED); pad_end = ufield->new_val.data
+ min_size;
memset(ufield->new_val.data, ufield->new_val.len = min_size;
(byte)dtype_get_pad_char(type),
fixed_size);
ut_memcpy(ufield->new_val.data, ut_memcpy(ufield->new_val.data,
parent_ufield->new_val.data, parent_ufield->new_val.data,
parent_ufield->new_val.len); 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; 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