mirror of
https://github.com/MariaDB/server.git
synced 2025-10-12 12:25:37 +03:00
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).
This commit is contained in:
@@ -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);
|
||||
min_size = dtype_get_min_size(type);
|
||||
|
||||
/* TODO: pad in UCS-2 with 0x0020.
|
||||
TODO: How does the special truncation of
|
||||
UTF-8 CHAR cols affect this? */
|
||||
|
||||
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;
|
||||
|
Reference in New Issue
Block a user