Commit 1a0a9e6a authored by marko's avatar marko

branches/zip: Allow in-place updates of UTF-8 CHAR columns

from or to NULL in ROW_FORMAT=REDUNDANT. (Bug #44032)

rb://107 approved by Heikki Tuuri.
parent 50f3f5c8
2009-04-07 The InnoDB Team
* btr/btr0btr.c, dict/dict0dict.c, ibuf/ibuf0ibuf.c,
include/data0data.h, include/data0data.ic, include/data0type.h,
include/data0type.ic, include/dict0dict.h,
include/dict0dict.ic, include/rem0rec.ic,
mysql-test/innodb.result, mysql-test/innodb.test,
pars/pars0pars.c, rem/rem0rec.c, row/row0upd.c:
Fix Bug#44032 In ROW_FORMAT=REDUNDANT, update UTF-8 CHAR
to/from NULL is not in-place
2009-04-07 The InnoDB Team
* page/page0cur.c:
......
......@@ -3178,7 +3178,7 @@ btr_index_rec_validate(
for (i = 0; i < n; i++) {
ulint fixed_size = dict_col_get_fixed_size(
dict_index_get_nth_col(index, i));
dict_index_get_nth_col(index, i), page_is_comp(page));
rec_get_nth_field_offs(offsets, i, &len);
......
......@@ -1252,7 +1252,8 @@ dict_index_too_big_for_undo(
ulint max_size
= dict_col_get_max_size(col);
ulint fixed_size
= dict_col_get_fixed_size(col);
= dict_col_get_fixed_size(col,
dict_table_is_comp(table));
if (fixed_size) {
/* Fixed-size columns are stored locally. */
......@@ -1382,7 +1383,7 @@ dict_index_too_big_for_tree(
case in rec_get_converted_size_comp() for
REC_STATUS_ORDINARY records. */
field_max_size = dict_col_get_fixed_size(col);
field_max_size = dict_col_get_fixed_size(col, comp);
if (field_max_size) {
/* dict_index_add_col() should guarantee this */
ut_ad(!field->prefix_len
......@@ -1542,7 +1543,7 @@ too_big:
if (field->prefix_len /* prefix index */
&& !col->ord_part /* not yet ordering column */
&& !dict_col_get_fixed_size(col) /* variable-length */
&& !dict_col_get_fixed_size(col, TRUE) /* variable-length */
&& dict_col_get_max_size(col)
> BTR_EXTERN_FIELD_REF_SIZE * 2 /* long enough */) {
......@@ -1737,7 +1738,8 @@ dict_index_add_col(
field = dict_index_get_nth_field(index, index->n_def - 1);
field->col = col;
field->fixed_len = (unsigned int) dict_col_get_fixed_size(col);
field->fixed_len = (unsigned int) dict_col_get_fixed_size(
col, dict_table_is_comp(table));
if (prefix_len && field->fixed_len > prefix_len) {
field->fixed_len = (unsigned int) prefix_len;
......@@ -1934,7 +1936,8 @@ dict_index_build_internal_clust(
for (i = 0; i < trx_id_pos; i++) {
fixed_size = dict_col_get_fixed_size(
dict_index_get_nth_col(new_index, i));
dict_index_get_nth_col(new_index, i),
dict_table_is_comp(table));
if (fixed_size == 0) {
new_index->trx_id_offset = 0;
......@@ -4070,14 +4073,15 @@ dict_index_calc_min_rec_len(
{
ulint sum = 0;
ulint i;
ulint comp = dict_table_is_comp(index->table);
if (dict_table_is_comp(index->table)) {
if (comp) {
ulint nullable = 0;
sum = REC_N_NEW_EXTRA_BYTES;
for (i = 0; i < dict_index_get_n_fields(index); i++) {
const dict_col_t* col
= dict_index_get_nth_col(index, i);
ulint size = dict_col_get_fixed_size(col);
ulint size = dict_col_get_fixed_size(col, comp);
sum += size;
if (!size) {
size = col->len;
......@@ -4096,7 +4100,7 @@ dict_index_calc_min_rec_len(
for (i = 0; i < dict_index_get_n_fields(index); i++) {
sum += dict_col_get_fixed_size(
dict_index_get_nth_col(index, i));
dict_index_get_nth_col(index, i), comp);
}
if (sum > 127) {
......
......@@ -1320,6 +1320,7 @@ ibuf_rec_get_volume(
const byte* data;
ulint len;
ulint i;
ulint comp;
ut_ad(ibuf_inside());
ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
......@@ -1337,6 +1338,7 @@ ibuf_rec_get_volume(
types = rec_get_nth_field_old(ibuf_rec, 1, &len);
ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
comp = FALSE;
} else {
/* >= 4.1.x format record */
......@@ -1345,8 +1347,10 @@ ibuf_rec_get_volume(
types = rec_get_nth_field_old(ibuf_rec, 3, &len);
ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
comp = len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE;
ut_a(comp <= 1);
if (comp) {
/* compact record format */
ulint volume;
dict_index_t* dummy_index;
......@@ -1380,7 +1384,7 @@ ibuf_rec_get_volume(
}
if (len == UNIV_SQL_NULL) {
data_size += dtype_get_sql_null_size(&dtype);
data_size += dtype_get_sql_null_size(&dtype, comp);
} else {
data_size += len;
}
......
......@@ -277,7 +277,8 @@ ulint
dtuple_get_data_size(
/*=================*/
/* out: sum of data lens */
const dtuple_t* tuple); /* in: typed data tuple */
const dtuple_t* tuple, /* in: typed data tuple */
ulint comp); /* in: nonzero=ROW_FORMAT=COMPACT */
/*************************************************************************
Computes the number of externally stored fields in a data tuple. */
UNIV_INLINE
......
......@@ -433,7 +433,8 @@ ulint
dtuple_get_data_size(
/*=================*/
/* out: sum of data lengths */
const dtuple_t* tuple) /* in: typed data tuple */
const dtuple_t* tuple, /* in: typed data tuple */
ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
{
const dfield_t* field;
ulint n_fields;
......@@ -452,7 +453,8 @@ dtuple_get_data_size(
len = dfield_get_len(field);
if (len == UNIV_SQL_NULL) {
len = dtype_get_sql_null_size(dfield_get_type(field));
len = dtype_get_sql_null_size(dfield_get_type(field),
comp);
}
sum += len;
......
......@@ -352,7 +352,8 @@ dtype_get_fixed_size_low(
ulint prtype, /* in: precise type */
ulint len, /* in: length */
ulint mbminlen, /* in: minimum length of a multibyte char */
ulint mbmaxlen); /* in: maximum length of a multibyte char */
ulint mbmaxlen, /* in: maximum length of a multibyte char */
ulint comp); /* in: nonzero=ROW_FORMAT=COMPACT */
#ifndef UNIV_HOTBACKUP
/***************************************************************************
Returns the minimum size of a data type. */
......@@ -386,7 +387,8 @@ dtype_get_sql_null_size(
/*====================*/
/* out: SQL null storage size
in ROW_FORMAT=REDUNDANT */
const dtype_t* type); /* in: type */
const dtype_t* type, /* in: type */
ulint comp); /* in: nonzero=ROW_FORMAT=COMPACT */
#ifndef UNIV_HOTBACKUP
/**************************************************************************
Reads to a type the stored information which determines its alphabetical
......
......@@ -398,7 +398,8 @@ dtype_get_fixed_size_low(
ulint prtype, /* in: precise type */
ulint len, /* in: length */
ulint mbminlen, /* in: minimum length of a multibyte char */
ulint mbmaxlen) /* in: maximum length of a multibyte char */
ulint mbmaxlen, /* in: maximum length of a multibyte char */
ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
{
switch (mtype) {
case DATA_SYS:
......@@ -428,6 +429,8 @@ dtype_get_fixed_size_low(
#ifndef UNIV_HOTBACKUP
if (prtype & DATA_BINARY_TYPE) {
return(len);
} else if (!comp) {
return(len);
} else {
/* We play it safe here and ask MySQL for
mbminlen and mbmaxlen. Although
......@@ -581,13 +584,14 @@ dtype_get_sql_null_size(
/*====================*/
/* out: SQL null storage size
in ROW_FORMAT=REDUNDANT */
const dtype_t* type) /* in: type */
const dtype_t* type, /* in: type */
ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
{
#ifndef UNIV_HOTBACKUP
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
type->mbminlen, type->mbmaxlen));
type->mbminlen, type->mbmaxlen, comp));
#else /* !UNIV_HOTBACKUP */
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
0, 0));
0, 0, 0));
#endif /* !UNIV_HOTBACKUP */
}
......@@ -144,7 +144,8 @@ ulint
dict_col_get_fixed_size(
/*====================*/
/* out: fixed size, or 0 */
const dict_col_t* col); /* in: column */
const dict_col_t* col, /* in: column */
ulint comp); /* in: nonzero=ROW_FORMAT=COMPACT */
/***************************************************************************
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
For fixed length types it is the fixed length of the type, otherwise 0. */
......@@ -154,7 +155,8 @@ dict_col_get_sql_null_size(
/*=======================*/
/* out: SQL null storage size
in ROW_FORMAT=REDUNDANT */
const dict_col_t* col); /* in: column */
const dict_col_t* col, /* in: column */
ulint comp); /* in: nonzero=ROW_FORMAT=COMPACT */
/*************************************************************************
Gets the column number. */
......
......@@ -104,10 +104,11 @@ ulint
dict_col_get_fixed_size(
/*====================*/
/* out: fixed size, or 0 */
const dict_col_t* col) /* in: column */
const dict_col_t* col, /* in: column */
ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
{
return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len,
col->mbminlen, col->mbmaxlen));
col->mbminlen, col->mbmaxlen, comp));
}
/***************************************************************************
Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column.
......@@ -118,9 +119,10 @@ dict_col_get_sql_null_size(
/*=======================*/
/* out: SQL null storage size
in ROW_FORMAT=REDUNDANT */
const dict_col_t* col) /* in: column */
const dict_col_t* col, /* in: column */
ulint comp) /* in: nonzero=ROW_FORMAT=COMPACT */
{
return(dict_col_get_fixed_size(col));
return(dict_col_get_fixed_size(col, comp));
}
/*************************************************************************
......
......@@ -1577,7 +1577,7 @@ rec_get_converted_size(
dtuple->n_fields, NULL));
}
data_size = dtuple_get_data_size(dtuple);
data_size = dtuple_get_data_size(dtuple, 0);
extra_size = rec_get_converted_extra_size(
data_size, dtuple_get_n_fields(dtuple), n_ext);
......
......@@ -3306,3 +3306,10 @@ Variable_name Value
Handler_update 1
Variable_name Value
Handler_delete 1
CREATE TABLE t1(c CHAR(3) CHARACTER SET UTF8) ROW_FORMAT=REDUNDANT
ENGINE=InnoDB;
INSERT INTO t1 VALUES('abc'),(0xEFBCA4EFBCA4EFBCA4);
UPDATE t1 SET c='DDD' WHERE c=0xEFBCA4EFBCA4EFBCA4;
UPDATE t1 SET c=NULL WHERE c='DDD';
UPDATE t1 SET c='DDD' WHERE c IS NULL;
DROP TABLE t1;
......@@ -2524,6 +2524,19 @@ DROP TABLE bug35537;
DISCONNECT c1;
CONNECTION default;
-- enable_query_log
# Bug : no update-in-place of UTF-8 columns in ROW_FORMAT=REDUNDANT
# (btr_cur_update_in_place not invoked when updating from/to NULL;
# the update is performed by delete and insert instead)
CREATE TABLE t1(c CHAR(3) CHARACTER SET UTF8) ROW_FORMAT=REDUNDANT
ENGINE=InnoDB;
INSERT INTO t1 VALUES('abc'),(0xEFBCA4EFBCA4EFBCA4);
UPDATE t1 SET c='DDD' WHERE c=0xEFBCA4EFBCA4EFBCA4;
UPDATE t1 SET c=NULL WHERE c='DDD';
UPDATE t1 SET c='DDD' WHERE c IS NULL;
DROP TABLE t1;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
......
......@@ -945,7 +945,8 @@ pars_process_assign_list(
if (!dict_col_get_fixed_size(
dict_index_get_nth_col(clust_index,
upd_field->field_no))) {
upd_field->field_no),
dict_table_is_comp(node->table))) {
changes_field_size = 0;
}
......
......@@ -949,7 +949,7 @@ rec_convert_dtuple_to_rec_old(
ut_ad(dtuple_check_typed(dtuple));
n_fields = dtuple_get_n_fields(dtuple);
data_size = dtuple_get_data_size(dtuple);
data_size = dtuple_get_data_size(dtuple, FALSE);
ut_ad(n_fields > 0);
......@@ -982,7 +982,7 @@ rec_convert_dtuple_to_rec_old(
if (dfield_is_null(field)) {
len = dtype_get_sql_null_size(
dfield_get_type(field));
dfield_get_type(field), FALSE);
data_write_sql_null(rec + end_offset, len);
end_offset += len;
......@@ -1010,7 +1010,7 @@ rec_convert_dtuple_to_rec_old(
if (dfield_is_null(field)) {
len = dtype_get_sql_null_size(
dfield_get_type(field));
dfield_get_type(field), FALSE);
data_write_sql_null(rec + end_offset, len);
end_offset += len;
......
......@@ -422,7 +422,8 @@ row_upd_changes_field_size_or_external(
new_len = dict_col_get_sql_null_size(
dict_index_get_nth_col(index,
upd_field->field_no));
upd_field->field_no),
FALSE);
}
old_len = rec_offs_nth_size(offsets, upd_field->field_no);
......
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