Commit 5288876e authored by marko's avatar marko

branches/zip: Make merge sort handle externally stored columns.

Some things still fail in innodb-index.test, and there seems to be
a race condition (data dictionary lock wait) when running with --valgrind.

dfield_t: Add an "external storage" flag, dfield->ext.

dfield_is_null(), dfield_is_ext(), dfield_set_ext(), dfield_set_null():
New functions.

dfield_copy(), dfield_copy_data(): Add const qualifiers, fix in/out comments.

data_write_sql_null(): Use memset().

big_rec_field_t: Replace byte* data with const void* data.

ut_ulint_sort(): Remove.

upd_field_t: Remove extern_storage.

upd_node_t: Replace ext_vec, n_ext_vec with n_ext.

row_merge_copy_blobs(): New function.

row_ins_index_entry(): Add the parameter "ibool foreign" for suppressing
foreign key checks during fast index creation or when inserting into
secondary indexes.

btr_page_insert_fits(): Add const qualifiers.

btr_cur_add_ext(), upd_ext_vec_contains(): Remove.

dfield_print_also_hex(), dfield_print(): Replace if...else if with switch.
Observe dfield_is_ext().
parent d7dbb460
...@@ -1078,9 +1078,8 @@ btr_root_raise_and_insert( ...@@ -1078,9 +1078,8 @@ btr_root_raise_and_insert(
on the root page; when the function returns, on the root page; when the function returns,
the cursor is positioned on the predecessor the cursor is positioned on the predecessor
of the inserted record */ of the inserted record */
dtuple_t* tuple, /* in: tuple to insert */ const dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
mtr_t* mtr) /* in: mtr */ mtr_t* mtr) /* in: mtr */
{ {
dict_index_t* index; dict_index_t* index;
...@@ -1195,7 +1194,7 @@ btr_root_raise_and_insert( ...@@ -1195,7 +1194,7 @@ btr_root_raise_and_insert(
page_cur_set_before_first(root_block, page_cursor); page_cur_set_before_first(root_block, page_cursor);
node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr, node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr,
index, NULL, 0, mtr); index, 0, mtr);
/* The root page should only contain the node pointer /* The root page should only contain the node pointer
to new_page at this point. Thus, the data should fit. */ to new_page at this point. Thus, the data should fit. */
...@@ -1219,7 +1218,7 @@ btr_root_raise_and_insert( ...@@ -1219,7 +1218,7 @@ btr_root_raise_and_insert(
PAGE_CUR_LE, page_cursor); PAGE_CUR_LE, page_cursor);
/* Split the child and insert tuple */ /* Split the child and insert tuple */
return(btr_page_split_and_insert(cursor, tuple, ext, n_ext, mtr)); return(btr_page_split_and_insert(cursor, tuple, n_ext, mtr));
} }
/***************************************************************** /*****************************************************************
...@@ -1333,14 +1332,11 @@ static ...@@ -1333,14 +1332,11 @@ static
rec_t* rec_t*
btr_page_get_sure_split_rec( btr_page_get_sure_split_rec(
/*========================*/ /*========================*/
/* out: split record, or NULL if /* out: split record, or NULL if tuple
tuple will be the first record on will be the first record on upper half-page */
upper half-page */ btr_cur_t* cursor, /* in: cursor at which insert should be made */
btr_cur_t* cursor, /* in: cursor at which insert const dtuple_t* tuple, /* in: tuple to insert */
should be made */ ulint n_ext) /* in: number of externally stored columns */
dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */
ulint n_ext) /* in: number of elements in ext */
{ {
page_t* page; page_t* page;
page_zip_des_t* page_zip; page_zip_des_t* page_zip;
...@@ -1359,7 +1355,7 @@ btr_page_get_sure_split_rec( ...@@ -1359,7 +1355,7 @@ btr_page_get_sure_split_rec(
page = btr_cur_get_page(cursor); page = btr_cur_get_page(cursor);
insert_size = rec_get_converted_size(cursor->index, tuple, ext, n_ext); insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
free_space = page_get_free_space_of_empty(page_is_comp(page)); free_space = page_get_free_space_of_empty(page_is_comp(page));
page_zip = btr_cur_get_page_zip(cursor); page_zip = btr_cur_get_page_zip(cursor);
...@@ -1456,27 +1452,26 @@ static ...@@ -1456,27 +1452,26 @@ static
ibool ibool
btr_page_insert_fits( btr_page_insert_fits(
/*=================*/ /*=================*/
/* out: TRUE if fits */ /* out: TRUE if fits */
btr_cur_t* cursor, /* in: cursor at which insert btr_cur_t* cursor, /* in: cursor at which insert
should be made */ should be made */
rec_t* split_rec, /* in: suggestion for first record const rec_t* split_rec,/* in: suggestion for first record
on upper half-page, or NULL if on upper half-page, or NULL if
tuple to be inserted should be first */ tuple to be inserted should be first */
const ulint* offsets, /* in: rec_get_offsets( const ulint* offsets,/* in: rec_get_offsets(
split_rec, cursor->index) */ split_rec, cursor->index) */
dtuple_t* tuple, /* in: tuple to insert */ const dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in ext */ mem_heap_t* heap) /* in: temporary memory heap */
mem_heap_t* heap) /* in: temporary memory heap */
{ {
page_t* page; page_t* page;
ulint insert_size; ulint insert_size;
ulint free_space; ulint free_space;
ulint total_data; ulint total_data;
ulint total_n_recs; ulint total_n_recs;
rec_t* rec; const rec_t* rec;
rec_t* end_rec; const rec_t* end_rec;
ulint* offs; ulint* offs;
page = btr_cur_get_page(cursor); page = btr_cur_get_page(cursor);
...@@ -1486,7 +1481,7 @@ btr_page_insert_fits( ...@@ -1486,7 +1481,7 @@ btr_page_insert_fits(
ut_ad(!offsets ut_ad(!offsets
|| rec_offs_validate(split_rec, cursor->index, offsets)); || rec_offs_validate(split_rec, cursor->index, offsets));
insert_size = rec_get_converted_size(cursor->index, tuple, ext, n_ext); insert_size = rec_get_converted_size(cursor->index, tuple, n_ext);
free_space = page_get_free_space_of_empty(page_is_comp(page)); free_space = page_get_free_space_of_empty(page_is_comp(page));
/* free_space is now the free space of a created new page */ /* free_space is now the free space of a created new page */
...@@ -1541,7 +1536,7 @@ btr_page_insert_fits( ...@@ -1541,7 +1536,7 @@ btr_page_insert_fits(
return(TRUE); return(TRUE);
} }
rec = page_rec_get_next(rec); rec = page_rec_get_next((rec_t*) rec);
} }
return(FALSE); return(FALSE);
...@@ -1574,7 +1569,7 @@ btr_insert_on_non_leaf_level( ...@@ -1574,7 +1569,7 @@ btr_insert_on_non_leaf_level(
| BTR_KEEP_SYS_FLAG | BTR_KEEP_SYS_FLAG
| BTR_NO_UNDO_LOG_FLAG, | BTR_NO_UNDO_LOG_FLAG,
&cursor, tuple, &rec, &cursor, tuple, &rec,
&dummy_big_rec, NULL, 0, NULL, mtr); &dummy_big_rec, 0, NULL, mtr);
ut_a(err == DB_SUCCESS); ut_a(err == DB_SUCCESS);
} }
...@@ -1730,9 +1725,8 @@ btr_page_split_and_insert( ...@@ -1730,9 +1725,8 @@ btr_page_split_and_insert(
btr_cur_t* cursor, /* in: cursor at which to insert; when the btr_cur_t* cursor, /* in: cursor at which to insert; when the
function returns, the cursor is positioned function returns, the cursor is positioned
on the predecessor of the inserted record */ on the predecessor of the inserted record */
dtuple_t* tuple, /* in: tuple to insert */ const dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
mtr_t* mtr) /* in: mtr */ mtr_t* mtr) /* in: mtr */
{ {
buf_block_t* block; buf_block_t* block;
...@@ -1789,8 +1783,7 @@ btr_page_split_and_insert( ...@@ -1789,8 +1783,7 @@ btr_page_split_and_insert(
if (n_iterations > 0) { if (n_iterations > 0) {
direction = FSP_UP; direction = FSP_UP;
hint_page_no = page_no + 1; hint_page_no = page_no + 1;
split_rec = btr_page_get_sure_split_rec(cursor, tuple, split_rec = btr_page_get_sure_split_rec(cursor, tuple, n_ext);
ext, n_ext);
} else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) { } else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) {
direction = FSP_UP; direction = FSP_UP;
...@@ -1821,10 +1814,10 @@ btr_page_split_and_insert( ...@@ -1821,10 +1814,10 @@ btr_page_split_and_insert(
first_rec = move_limit = split_rec; first_rec = move_limit = split_rec;
} else { } else {
buf = mem_alloc(rec_get_converted_size(cursor->index, buf = mem_alloc(rec_get_converted_size(cursor->index,
tuple, ext, n_ext)); tuple, n_ext));
first_rec = rec_convert_dtuple_to_rec(buf, cursor->index, first_rec = rec_convert_dtuple_to_rec(buf, cursor->index,
tuple, ext, n_ext); tuple, n_ext);
move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
} }
...@@ -1845,13 +1838,13 @@ btr_page_split_and_insert( ...@@ -1845,13 +1838,13 @@ btr_page_split_and_insert(
insert_left = cmp_dtuple_rec(tuple, split_rec, offsets) < 0; insert_left = cmp_dtuple_rec(tuple, split_rec, offsets) < 0;
insert_will_fit = btr_page_insert_fits(cursor, split_rec, insert_will_fit = btr_page_insert_fits(cursor, split_rec,
offsets, tuple, offsets, tuple,
ext, n_ext, heap); n_ext, heap);
} else { } else {
mem_free(buf); mem_free(buf);
insert_left = FALSE; insert_left = FALSE;
insert_will_fit = btr_page_insert_fits(cursor, NULL, insert_will_fit = btr_page_insert_fits(cursor, NULL,
NULL, tuple, NULL, tuple,
ext, n_ext, heap); n_ext, heap);
} }
if (insert_will_fit && page_is_leaf(page) && !page_zip) { if (insert_will_fit && page_is_leaf(page) && !page_zip) {
...@@ -1946,7 +1939,7 @@ btr_page_split_and_insert( ...@@ -1946,7 +1939,7 @@ btr_page_split_and_insert(
PAGE_CUR_LE, page_cursor); PAGE_CUR_LE, page_cursor);
rec = page_cur_tuple_insert(page_cursor, tuple, rec = page_cur_tuple_insert(page_cursor, tuple,
cursor->index, ext, n_ext, mtr); cursor->index, n_ext, mtr);
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
{ {
...@@ -1973,7 +1966,7 @@ btr_page_split_and_insert( ...@@ -1973,7 +1966,7 @@ btr_page_split_and_insert(
page_cur_search(insert_block, cursor->index, tuple, page_cur_search(insert_block, cursor->index, tuple,
PAGE_CUR_LE, page_cursor); PAGE_CUR_LE, page_cursor);
rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index,
ext, n_ext, mtr); n_ext, mtr);
if (UNIV_UNLIKELY(rec == NULL)) { if (UNIV_UNLIKELY(rec == NULL)) {
/* The insert did not fit on the page: loop back to the /* The insert did not fit on the page: loop back to the
......
This diff is collapsed.
...@@ -275,7 +275,7 @@ dtuple_validate( ...@@ -275,7 +275,7 @@ dtuple_validate(
field = dtuple_get_nth_field(tuple, i); field = dtuple_get_nth_field(tuple, i);
len = dfield_get_len(field); len = dfield_get_len(field);
if (len != UNIV_SQL_NULL) { if (!dfield_is_null(field)) {
data = field->data; data = field->data;
...@@ -305,30 +305,34 @@ dfield_print( ...@@ -305,30 +305,34 @@ dfield_print(
{ {
const byte* data; const byte* data;
ulint len; ulint len;
ulint mtype;
ulint i; ulint i;
len = dfield_get_len(dfield); len = dfield_get_len(dfield);
data = dfield_get_data(dfield); data = dfield_get_data(dfield);
if (len == UNIV_SQL_NULL) { if (dfield_is_null(dfield)) {
fputs("NULL", stderr); fputs("NULL", stderr);
return; return;
} }
mtype = dtype_get_mtype(dfield_get_type(dfield)); switch (dtype_get_mtype(dfield_get_type(dfield))) {
case DATA_CHAR:
if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { case DATA_VARCHAR:
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int c = *data++; int c = *data++;
putc(isprint(c) ? c : ' ', stderr); putc(isprint(c) ? c : ' ', stderr);
} }
} else if (mtype == DATA_INT) {
if (dfield_is_ext(dfield)) {
fputs("(external)", stderr);
}
break;
case DATA_INT:
ut_a(len == 4); /* only works for 32-bit integers */ ut_a(len == 4); /* only works for 32-bit integers */
fprintf(stderr, "%d", (int)mach_read_from_4(data)); fprintf(stderr, "%d", (int)mach_read_from_4(data));
} else { break;
default:
ut_error; ut_error;
} }
} }
...@@ -344,7 +348,6 @@ dfield_print_also_hex( ...@@ -344,7 +348,6 @@ dfield_print_also_hex(
{ {
const byte* data; const byte* data;
ulint len; ulint len;
ulint mtype;
ulint prtype; ulint prtype;
ulint i; ulint i;
ibool print_also_hex; ibool print_also_hex;
...@@ -352,60 +355,21 @@ dfield_print_also_hex( ...@@ -352,60 +355,21 @@ dfield_print_also_hex(
len = dfield_get_len(dfield); len = dfield_get_len(dfield);
data = dfield_get_data(dfield); data = dfield_get_data(dfield);
if (len == UNIV_SQL_NULL) { if (dfield_is_null(dfield)) {
fputs("NULL", stderr); fputs("NULL", stderr);
return; return;
} }
mtype = dtype_get_mtype(dfield_get_type(dfield));
prtype = dtype_get_prtype(dfield_get_type(dfield)); prtype = dtype_get_prtype(dfield_get_type(dfield));
if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { switch (dtype_get_mtype(dfield_get_type(dfield))) {
dulint id;
print_also_hex = FALSE; case DATA_INT:
switch (len) {
for (i = 0; i < len; i++) {
int c = *data++;
if (!isprint(c)) {
print_also_hex = TRUE;
fprintf(stderr, "\\x%02x", (unsigned char) c);
} else {
putc(c, stderr);
}
}
if (!print_also_hex) {
return;
}
fputs(" Hex: ", stderr);
data = dfield_get_data(dfield);
for (i = 0; i < len; i++) {
fprintf(stderr, "%02lx", (ulint)*data);
data++;
}
} else if (mtype == DATA_BINARY) {
data = dfield_get_data(dfield);
fputs(" Hex: ",stderr);
for (i = 0; i < len; i++) {
fprintf(stderr, "%02lx", (ulint)*data);
data++;
}
} else if (mtype == DATA_INT) {
dulint big_val;
if (len == 1) {
ulint val; ulint val;
case 1:
val = (ulint)mach_read_from_1(data); val = mach_read_from_1(data);
if (!(prtype & DATA_UNSIGNED)) { if (!(prtype & DATA_UNSIGNED)) {
val &= ~0x80; val &= ~0x80;
...@@ -413,11 +377,10 @@ dfield_print_also_hex( ...@@ -413,11 +377,10 @@ dfield_print_also_hex(
} else { } else {
fprintf(stderr, "%lu", (ulong) val); fprintf(stderr, "%lu", (ulong) val);
} }
break;
} else if (len == 2) { case 2:
ulint val; val = mach_read_from_2(data);
val = (ulint)mach_read_from_2(data);
if (!(prtype & DATA_UNSIGNED)) { if (!(prtype & DATA_UNSIGNED)) {
val &= ~0x8000; val &= ~0x8000;
...@@ -425,11 +388,10 @@ dfield_print_also_hex( ...@@ -425,11 +388,10 @@ dfield_print_also_hex(
} else { } else {
fprintf(stderr, "%lu", (ulong) val); fprintf(stderr, "%lu", (ulong) val);
} }
break;
} else if (len == 3) { case 3:
ulint val; val = mach_read_from_3(data);
val = (ulint)mach_read_from_3(data);
if (!(prtype & DATA_UNSIGNED)) { if (!(prtype & DATA_UNSIGNED)) {
val &= ~0x800000; val &= ~0x800000;
...@@ -437,11 +399,10 @@ dfield_print_also_hex( ...@@ -437,11 +399,10 @@ dfield_print_also_hex(
} else { } else {
fprintf(stderr, "%lu", (ulong) val); fprintf(stderr, "%lu", (ulong) val);
} }
break;
} else if (len == 4) { case 4:
ulint val; val = mach_read_from_4(data);
val = (ulint)mach_read_from_4(data);
if (!(prtype & DATA_UNSIGNED)) { if (!(prtype & DATA_UNSIGNED)) {
val &= ~0x80000000; val &= ~0x80000000;
...@@ -449,33 +410,33 @@ dfield_print_also_hex( ...@@ -449,33 +410,33 @@ dfield_print_also_hex(
} else { } else {
fprintf(stderr, "%lu", (ulong) val); fprintf(stderr, "%lu", (ulong) val);
} }
break;
} else if (len == 6) { case 6:
big_val = (dulint)mach_read_from_6(data); id = mach_read_from_6(data);
fprintf(stderr, "{%lu %lu}", fprintf(stderr, "{%lu %lu}",
ut_dulint_get_high(big_val), ut_dulint_get_high(id),
ut_dulint_get_low(big_val)); ut_dulint_get_low(id));
} else if (len == 7) { break;
big_val = (dulint)mach_read_from_7(data);
case 7:
id = mach_read_from_7(data);
fprintf(stderr, "{%lu %lu}", fprintf(stderr, "{%lu %lu}",
ut_dulint_get_high(big_val), ut_dulint_get_high(id),
ut_dulint_get_low(big_val)); ut_dulint_get_low(id));
} else if (len == 8) { break;
big_val = (dulint)mach_read_from_8(data); case 8:
id = mach_read_from_8(data);
fprintf(stderr, "{%lu %lu}", fprintf(stderr, "{%lu %lu}",
ut_dulint_get_high(big_val), ut_dulint_get_high(id),
ut_dulint_get_low(big_val)); ut_dulint_get_low(id));
} else { break;
fputs(" Hex: ",stderr); default:
goto print_hex;
for (i = 0; i < len; i++) {
fprintf(stderr, "%02lx", (ulint)*data);
data++;
}
} }
} else if (mtype == DATA_SYS) { break;
dulint id;
case DATA_SYS:
if (prtype & DATA_TRX_ID) { if (prtype & DATA_TRX_ID) {
id = mach_read_from_6(data); id = mach_read_from_6(data);
...@@ -497,13 +458,46 @@ dfield_print_also_hex( ...@@ -497,13 +458,46 @@ dfield_print_also_hex(
fprintf(stderr, "mix_id {%lu %lu}", fprintf(stderr, "mix_id {%lu %lu}",
ut_dulint_get_high(id), ut_dulint_get_low(id)); ut_dulint_get_high(id), ut_dulint_get_low(id));
} }
break;
} else { case DATA_CHAR:
case DATA_VARCHAR:
print_also_hex = FALSE;
for (i = 0; i < len; i++) {
int c = *data++;
if (!isprint(c)) {
print_also_hex = TRUE;
fprintf(stderr, "\\x%02x", (unsigned char) c);
} else {
putc(c, stderr);
}
}
if (dfield_is_ext(dfield)) {
fputs("(external)", stderr);
}
if (!print_also_hex) {
break;
}
data = dfield_get_data(dfield);
/* fall through */
case DATA_BINARY:
default:
print_hex:
fputs(" Hex: ",stderr); fputs(" Hex: ",stderr);
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
fprintf(stderr, "%02lx", (ulint)*data); fprintf(stderr, "%02lx", (ulint) *data++);
data++; }
if (dfield_is_ext(dfield)) {
fputs("(external)", stderr);
} }
} }
} }
...@@ -518,11 +512,13 @@ dfield_print_raw( ...@@ -518,11 +512,13 @@ dfield_print_raw(
const dfield_t* dfield) /* in: dfield */ const dfield_t* dfield) /* in: dfield */
{ {
ulint len = dfield->len; ulint len = dfield->len;
if (len != UNIV_SQL_NULL) { if (!dfield_is_null(dfield)) {
ulint print_len = ut_min(len, 1000); ulint print_len = ut_min(len, 1000);
ut_print_buf(f, dfield->data, print_len); ut_print_buf(f, dfield->data, print_len);
if (len != print_len) { if (len != print_len) {
fprintf(f, "(total %lu bytes)", (ulong) len); fprintf(f, "(total %lu bytes%s)",
(ulong) len,
dfield_is_ext(dfield) ? ", external" : "");
} }
} else { } else {
fputs(" SQL NULL", f); fputs(" SQL NULL", f);
...@@ -572,12 +568,9 @@ dtuple_convert_big_rec( ...@@ -572,12 +568,9 @@ dtuple_convert_big_rec(
too many fixed-length or short fields too many fixed-length or short fields
in entry or the index is clustered */ in entry or the index is clustered */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
const dtuple_t* entry, /* in: index entry */ dtuple_t* entry, /* in/out: index entry */
const ulint* ext_vec,/* in: array of externally stored fields, ulint* n_ext) /* in/out: number of
or NULL: if a field already is externally externally stored columns */
stored, then we cannot move it to the vector
this function returns */
ulint n_ext_vec)/* in: number of elements is ext_vec */
{ {
mem_heap_t* heap; mem_heap_t* heap;
big_rec_t* vector; big_rec_t* vector;
...@@ -592,7 +585,7 @@ dtuple_convert_big_rec( ...@@ -592,7 +585,7 @@ dtuple_convert_big_rec(
ut_a(dtuple_check_typed_no_assert(entry)); ut_a(dtuple_check_typed_no_assert(entry));
size = rec_get_converted_size(index, entry, ext_vec, n_ext_vec); size = rec_get_converted_size(index, entry, *n_ext);
if (UNIV_UNLIKELY(size > 1000000000)) { if (UNIV_UNLIKELY(size > 1000000000)) {
fprintf(stderr, fprintf(stderr,
...@@ -619,8 +612,7 @@ dtuple_convert_big_rec( ...@@ -619,8 +612,7 @@ dtuple_convert_big_rec(
n_fields = 0; n_fields = 0;
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
ext_vec, *n_ext),
n_ext_vec),
dict_table_is_comp(index->table), dict_table_is_comp(index->table),
dict_table_zip_size(index->table))) { dict_table_zip_size(index->table))) {
ulint i; ulint i;
...@@ -634,10 +626,12 @@ dtuple_convert_big_rec( ...@@ -634,10 +626,12 @@ dtuple_convert_big_rec(
dfield = dtuple_get_nth_field(entry, i); dfield = dtuple_get_nth_field(entry, i);
ifield = dict_index_get_nth_field(index, i); ifield = dict_index_get_nth_field(index, i);
/* Skip fixed-length or NULL or short columns */ /* Skip fixed-length, NULL, externally stored,
or short columns */
if (ifield->fixed_len if (ifield->fixed_len
|| dfield->len == UNIV_SQL_NULL || dfield_is_null(dfield)
|| dfield_is_ext(dfield)
|| dfield->len <= BTR_EXTERN_FIELD_REF_SIZE * 2) { || dfield->len <= BTR_EXTERN_FIELD_REF_SIZE * 2) {
goto skip_field; goto skip_field;
} }
...@@ -649,18 +643,6 @@ dtuple_convert_big_rec( ...@@ -649,18 +643,6 @@ dtuple_convert_big_rec(
goto skip_field; goto skip_field;
} }
/* Skip externally stored columns */
if (ext_vec) {
ulint j;
for (j = 0; j < n_ext_vec; j++) {
if (ext_vec[j] == i) {
goto skip_field;
}
}
}
longest_i = i; longest_i = i;
longest = savings; longest = savings;
...@@ -691,11 +673,14 @@ dtuple_convert_big_rec( ...@@ -691,11 +673,14 @@ dtuple_convert_big_rec(
vector->fields[n_fields].data = dfield->data; vector->fields[n_fields].data = dfield->data;
/* Set the extern field reference in dfield to zero */ /* Set the extern field reference in dfield to zero */
dfield->len = BTR_EXTERN_FIELD_REF_SIZE; dfield_set_data(dfield,
dfield->data = mem_heap_calloc(heap, mem_heap_calloc(heap,
BTR_EXTERN_FIELD_REF_SIZE); BTR_EXTERN_FIELD_REF_SIZE),
BTR_EXTERN_FIELD_REF_SIZE);
dfield_set_ext(dfield);
UNIV_MEM_ALLOC(dfield->data, BTR_EXTERN_FIELD_REF_SIZE); UNIV_MEM_ALLOC(dfield->data, BTR_EXTERN_FIELD_REF_SIZE);
n_fields++; n_fields++;
(*n_ext)++;
ut_ad(n_fields < dtuple_get_n_fields(entry)); ut_ad(n_fields < dtuple_get_n_fields(entry));
} }
...@@ -723,8 +708,9 @@ dtuple_convert_back_big_rec( ...@@ -723,8 +708,9 @@ dtuple_convert_back_big_rec(
dfield = dtuple_get_nth_field(entry, dfield = dtuple_get_nth_field(entry,
vector->fields[i].field_no); vector->fields[i].field_no);
dfield->data = vector->fields[i].data; ut_ad(dfield_is_ext(dfield));
dfield->len = vector->fields[i].len; dfield_set_data(dfield,
vector->fields[i].data, vector->fields[i].len);
} }
mem_heap_free(vector->heap); mem_heap_free(vector->heap);
......
...@@ -100,7 +100,7 @@ dict_create_sys_tables_tuple( ...@@ -100,7 +100,7 @@ dict_create_sys_tables_tuple(
dfield_set_data(dfield, ptr, 4); dfield_set_data(dfield, ptr, 4);
/* 8: CLUSTER_NAME ---------------------*/ /* 8: CLUSTER_NAME ---------------------*/
dfield = dtuple_get_nth_field(entry, 6); dfield = dtuple_get_nth_field(entry, 6);
dfield_set_data(dfield, NULL, UNIV_SQL_NULL); /* not supported */ dfield_set_null(dfield); /* not supported */
/* 9: SPACE ----------------------------*/ /* 9: SPACE ----------------------------*/
dfield = dtuple_get_nth_field(entry, 7); dfield = dtuple_get_nth_field(entry, 7);
......
...@@ -792,7 +792,7 @@ eval_func( ...@@ -792,7 +792,7 @@ eval_func(
/* The functions are not defined for SQL null argument /* The functions are not defined for SQL null argument
values, except for eval_cmp and notfound */ values, except for eval_cmp and notfound */
if ((dfield_get_len(que_node_get_val(arg)) == UNIV_SQL_NULL) if (dfield_is_null(que_node_get_val(arg))
&& (class != PARS_FUNC_CMP) && (class != PARS_FUNC_CMP)
&& (func != PARS_NOTFOUND_TOKEN) && (func != PARS_NOTFOUND_TOKEN)
&& (func != PARS_PRINTF_TOKEN)) { && (func != PARS_PRINTF_TOKEN)) {
......
...@@ -3685,11 +3685,9 @@ calc_row_difference( ...@@ -3685,11 +3685,9 @@ calc_row_difference(
new_mysql_row_col, new_mysql_row_col,
col_pack_len, col_pack_len,
dict_table_is_comp(prebuilt->table)); dict_table_is_comp(prebuilt->table));
ufield->new_val.data = dfield.data; dfield_copy_data(&ufield->new_val, &dfield);
ufield->new_val.len = dfield.len;
} else { } else {
ufield->new_val.data = NULL; dfield_set_null(&ufield->new_val);
ufield->new_val.len = UNIV_SQL_NULL;
} }
ufield->exp = NULL; ufield->exp = NULL;
......
...@@ -1350,8 +1350,7 @@ ibuf_rec_get_volume( ...@@ -1350,8 +1350,7 @@ ibuf_rec_get_volume(
mem_heap_t* heap = mem_heap_create(500); mem_heap_t* heap = mem_heap_create(500);
dtuple_t* entry = ibuf_build_entry_from_ibuf_rec( dtuple_t* entry = ibuf_build_entry_from_ibuf_rec(
ibuf_rec, heap, &dummy_index); ibuf_rec, heap, &dummy_index);
volume = rec_get_converted_size(dummy_index, entry, volume = rec_get_converted_size(dummy_index, entry, 0);
NULL, 0);
ibuf_dummy_index_free(dummy_index); ibuf_dummy_index_free(dummy_index);
mem_heap_free(heap); mem_heap_free(heap);
return(volume + page_dir_calc_reserved_space(1)); return(volume + page_dir_calc_reserved_space(1));
...@@ -2654,7 +2653,7 @@ ibuf_insert_low( ...@@ -2654,7 +2653,7 @@ ibuf_insert_low(
ibuf_enter(); ibuf_enter();
} }
entry_size = rec_get_converted_size(index, entry, NULL, 0); entry_size = rec_get_converted_size(index, entry, 0);
heap = mem_heap_create(512); heap = mem_heap_create(512);
...@@ -2732,8 +2731,7 @@ ibuf_insert_low( ...@@ -2732,8 +2731,7 @@ ibuf_insert_low(
if (mode == BTR_MODIFY_PREV) { if (mode == BTR_MODIFY_PREV) {
err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor, err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor,
ibuf_entry, &ins_rec, ibuf_entry, &ins_rec,
&dummy_big_rec, NULL, 0, &dummy_big_rec, 0, thr, &mtr);
thr, &mtr);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
/* Update the page max trx id field */ /* Update the page max trx id field */
page_update_max_trx_id(btr_cur_get_block(cursor), NULL, page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
...@@ -2753,8 +2751,7 @@ ibuf_insert_low( ...@@ -2753,8 +2751,7 @@ ibuf_insert_low(
| BTR_NO_UNDO_LOG_FLAG, | BTR_NO_UNDO_LOG_FLAG,
cursor, cursor,
ibuf_entry, &ins_rec, ibuf_entry, &ins_rec,
&dummy_big_rec, NULL, 0, &dummy_big_rec, 0, thr, &mtr);
thr, &mtr);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
/* Update the page max trx id field */ /* Update the page max trx id field */
page_update_max_trx_id(btr_cur_get_block(cursor), NULL, page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
...@@ -2836,7 +2833,7 @@ ibuf_insert( ...@@ -2836,7 +2833,7 @@ ibuf_insert(
ut_a(!dict_index_is_clust(index)); ut_a(!dict_index_is_clust(index));
if (rec_get_converted_size(index, entry, NULL, 0) if (rec_get_converted_size(index, entry, 0)
>= (page_get_free_space_of_empty(dict_table_is_comp(index->table)) >= (page_get_free_space_of_empty(dict_table_is_comp(index->table))
/ 2)) { / 2)) {
return(FALSE); return(FALSE);
...@@ -2927,8 +2924,7 @@ ibuf_insert_to_index_page( ...@@ -2927,8 +2924,7 @@ ibuf_insert_to_index_page(
btr_cur_del_unmark_for_ibuf(rec, mtr); btr_cur_del_unmark_for_ibuf(rec, mtr);
} else { } else {
rec = page_cur_tuple_insert(&page_cur, entry, index, rec = page_cur_tuple_insert(&page_cur, entry, index, 0, mtr);
NULL, 0, mtr);
if (UNIV_LIKELY(rec != NULL)) { if (UNIV_LIKELY(rec != NULL)) {
return; return;
...@@ -2942,7 +2938,7 @@ ibuf_insert_to_index_page( ...@@ -2942,7 +2938,7 @@ ibuf_insert_to_index_page(
/* This time the record must fit */ /* This time the record must fit */
if (UNIV_UNLIKELY if (UNIV_UNLIKELY
(!page_cur_tuple_insert(&page_cur, entry, index, (!page_cur_tuple_insert(&page_cur, entry, index,
NULL, 0, mtr))) { 0, mtr))) {
ulint space; ulint space;
ulint page_no; ulint page_no;
ulint zip_size; ulint zip_size;
...@@ -2956,7 +2952,7 @@ ibuf_insert_to_index_page( ...@@ -2956,7 +2952,7 @@ ibuf_insert_to_index_page(
(ulong) page_get_max_insert_size( (ulong) page_get_max_insert_size(
page, 1), page, 1),
(ulong) rec_get_converted_size( (ulong) rec_get_converted_size(
index, entry, NULL, 0)); index, entry, 0));
fputs("InnoDB: Cannot insert index record ", fputs("InnoDB: Cannot insert index record ",
stderr); stderr);
dtuple_print(stderr, entry); dtuple_print(stderr, entry);
...@@ -3337,8 +3333,7 @@ ibuf_merge_or_delete_for_page( ...@@ -3337,8 +3333,7 @@ ibuf_merge_or_delete_for_page(
entry = ibuf_build_entry_from_ibuf_rec( entry = ibuf_build_entry_from_ibuf_rec(
ibuf_rec, heap, &dummy_index); ibuf_rec, heap, &dummy_index);
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
volume += rec_get_converted_size(dummy_index, entry, volume += rec_get_converted_size(dummy_index, entry, 0)
NULL, 0)
+ page_dir_calc_reserved_space(1); + page_dir_calc_reserved_space(1);
ut_a(volume <= 4 * UNIV_PAGE_SIZE ut_a(volume <= 4 * UNIV_PAGE_SIZE
/ IBUF_PAGE_SIZE_PER_FREE_SPACE); / IBUF_PAGE_SIZE_PER_FREE_SPACE);
......
...@@ -225,9 +225,8 @@ btr_root_raise_and_insert( ...@@ -225,9 +225,8 @@ btr_root_raise_and_insert(
on the root page; when the function returns, on the root page; when the function returns,
the cursor is positioned on the predecessor the cursor is positioned on the predecessor
of the inserted record */ of the inserted record */
dtuple_t* tuple, /* in: tuple to insert */ const dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
/***************************************************************** /*****************************************************************
Reorganizes an index page. Reorganizes an index page.
...@@ -284,9 +283,8 @@ btr_page_split_and_insert( ...@@ -284,9 +283,8 @@ btr_page_split_and_insert(
btr_cur_t* cursor, /* in: cursor at which to insert; when the btr_cur_t* cursor, /* in: cursor at which to insert; when the
function returns, the cursor is positioned function returns, the cursor is positioned
on the predecessor of the inserted record */ on the predecessor of the inserted record */
dtuple_t* tuple, /* in: tuple to insert */ const dtuple_t* tuple, /* in: tuple to insert */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
/*********************************************************** /***********************************************************
Inserts a data tuple to a tree on a non-leaf level. It is assumed Inserts a data tuple to a tree on a non-leaf level. It is assumed
......
...@@ -177,8 +177,7 @@ btr_cur_optimistic_insert( ...@@ -177,8 +177,7 @@ btr_cur_optimistic_insert(
big_rec_t** big_rec,/* out: big rec vector whose fields have to big_rec_t** big_rec,/* out: big rec vector whose fields have to
be stored externally by the caller, or be stored externally by the caller, or
NULL */ NULL */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
que_thr_t* thr, /* in: query thread or NULL */ que_thr_t* thr, /* in: query thread or NULL */
mtr_t* mtr); /* in: mtr; if this function returns mtr_t* mtr); /* in: mtr; if this function returns
DB_SUCCESS on a leaf page of a secondary DB_SUCCESS on a leaf page of a secondary
...@@ -209,8 +208,7 @@ btr_cur_pessimistic_insert( ...@@ -209,8 +208,7 @@ btr_cur_pessimistic_insert(
big_rec_t** big_rec,/* out: big rec vector whose fields have to big_rec_t** big_rec,/* out: big rec vector whose fields have to
be stored externally by the caller, or be stored externally by the caller, or
NULL */ NULL */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in vec */
que_thr_t* thr, /* in: query thread or NULL */ que_thr_t* thr, /* in: query thread or NULL */
mtr_t* mtr); /* in: mtr */ mtr_t* mtr); /* in: mtr */
/***************************************************************** /*****************************************************************
...@@ -458,9 +456,6 @@ btr_cur_mark_dtuple_inherited_extern( ...@@ -458,9 +456,6 @@ btr_cur_mark_dtuple_inherited_extern(
/*=================================*/ /*=================================*/
dtuple_t* entry, /* in/out: updated entry to be dtuple_t* entry, /* in/out: updated entry to be
inserted to clustered index */ inserted to clustered index */
const ulint* ext_vec, /* in: array of extern fields in the
original record */
ulint n_ext_vec, /* in: number of elements in ext_vec */
const upd_t* update); /* in: update vector */ const upd_t* update); /* in: update vector */
/*********************************************************************** /***********************************************************************
Marks all extern fields in a dtuple as owned by the record. */ Marks all extern fields in a dtuple as owned by the record. */
...@@ -468,10 +463,7 @@ Marks all extern fields in a dtuple as owned by the record. */ ...@@ -468,10 +463,7 @@ Marks all extern fields in a dtuple as owned by the record. */
void void
btr_cur_unmark_dtuple_extern_fields( btr_cur_unmark_dtuple_extern_fields(
/*================================*/ /*================================*/
dtuple_t* entry, /* in/out: clustered index entry */ dtuple_t* entry); /* in/out: clustered index entry */
const ulint* ext_vec, /* in: array of numbers of fields
which have been stored externally */
ulint n_ext_vec); /* in: number of elements in ext_vec */
/*********************************************************************** /***********************************************************************
Stores the fields in big_rec_vec to the tablespace and puts pointers to Stores the fields in big_rec_vec to the tablespace and puts pointers to
them in rec. The extern flags in rec will have to be set beforehand. them in rec. The extern flags in rec will have to be set beforehand.
...@@ -568,10 +560,8 @@ update. */ ...@@ -568,10 +560,8 @@ update. */
ulint ulint
btr_push_update_extern_fields( btr_push_update_extern_fields(
/*==========================*/ /*==========================*/
/* out: number of values stored in ext_vect */ /* out: number of externally stored columns */
ulint* ext_vect,/* out: array of ulints, must be preallocated dtuple_t* tuple, /* in/out: data tuple */
to have twice the space for all fields
in rec */
const ulint* offsets,/* in: array returned by rec_get_offsets() */ const ulint* offsets,/* in: array returned by rec_get_offsets() */
const upd_t* update);/* in: update vector or NULL */ const upd_t* update);/* in: update vector or NULL */
......
...@@ -65,6 +65,29 @@ dfield_set_len( ...@@ -65,6 +65,29 @@ dfield_set_len(
dfield_t* field, /* in: field */ dfield_t* field, /* in: field */
ulint len); /* in: length or UNIV_SQL_NULL */ ulint len); /* in: length or UNIV_SQL_NULL */
/************************************************************************* /*************************************************************************
Determines if a field is SQL NULL */
UNIV_INLINE
ulint
dfield_is_null(
/*===========*/
/* out: nonzero if SQL null data */
const dfield_t* field); /* in: field */
/*************************************************************************
Determines if a field is externally stored */
UNIV_INLINE
ulint
dfield_is_ext(
/*==========*/
/* out: nonzero if externally stored */
const dfield_t* field); /* in: field */
/*************************************************************************
Sets the "external storage" flag */
UNIV_INLINE
void
dfield_set_ext(
/*===========*/
dfield_t* field); /* in/out: field */
/*************************************************************************
Sets pointer to the data and length in a field. */ Sets pointer to the data and length in a field. */
UNIV_INLINE UNIV_INLINE
void void
...@@ -73,6 +96,13 @@ dfield_set_data( ...@@ -73,6 +96,13 @@ dfield_set_data(
dfield_t* field, /* in: field */ dfield_t* field, /* in: field */
const void* data, /* in: data */ const void* data, /* in: data */
ulint len); /* in: length or UNIV_SQL_NULL */ ulint len); /* in: length or UNIV_SQL_NULL */
/*************************************************************************
Sets a data field to SQL NULL. */
UNIV_INLINE
void
dfield_set_null(
/*============*/
dfield_t* field); /* in/out: field */
/************************************************************************** /**************************************************************************
Writes an SQL null field full of zeros. */ Writes an SQL null field full of zeros. */
UNIV_INLINE UNIV_INLINE
...@@ -87,15 +117,15 @@ UNIV_INLINE ...@@ -87,15 +117,15 @@ UNIV_INLINE
void void
dfield_copy_data( dfield_copy_data(
/*=============*/ /*=============*/
dfield_t* field1, /* in: field to copy to */ dfield_t* field1, /* out: field to copy to */
dfield_t* field2);/* in: field to copy from */ const dfield_t* field2);/* in: field to copy from */
/************************************************************************* /*************************************************************************
Copies a data field to another. */ Copies a data field to another. */
UNIV_INLINE UNIV_INLINE
void void
dfield_copy( dfield_copy(
/*========*/ /*========*/
dfield_t* field1, /* in: field to copy to */ dfield_t* field1, /* out: field to copy to */
const dfield_t* field2);/* in: field to copy from */ const dfield_t* field2);/* in: field to copy from */
/************************************************************************* /*************************************************************************
Tests if data length and content is equal for two dfields. */ Tests if data length and content is equal for two dfields. */
...@@ -329,12 +359,9 @@ dtuple_convert_big_rec( ...@@ -329,12 +359,9 @@ dtuple_convert_big_rec(
too many fixed-length or short fields too many fixed-length or short fields
in entry or the index is clustered */ in entry or the index is clustered */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
const dtuple_t* entry, /* in: index entry */ dtuple_t* entry, /* in/out: index entry */
const ulint* ext_vec,/* in: array of externally stored fields, ulint* n_ext); /* in/out: number of
or NULL: if a field already is externally externally stored columns */
stored, then we cannot move it to the vector
this function returns */
ulint n_ext_vec);/* in: number of elements is ext_vec */
/****************************************************************** /******************************************************************
Puts back to entry the data stored in vector. Note that to ensure the Puts back to entry the data stored in vector. Note that to ensure the
fields in entry can accommodate the data, vector must have been created fields in entry can accommodate the data, vector must have been created
...@@ -361,7 +388,8 @@ dtuple_big_rec_free( ...@@ -361,7 +388,8 @@ dtuple_big_rec_free(
/* Structure for an SQL data field */ /* Structure for an SQL data field */
struct dfield_struct{ struct dfield_struct{
void* data; /* pointer to data */ void* data; /* pointer to data */
ulint len; /* data length; UNIV_SQL_NULL if SQL null; */ unsigned ext:1; /* TRUE=externally stored, FALSE=local */
unsigned len:32; /* data length; UNIV_SQL_NULL if SQL null */
dtype_t type; /* type of data */ dtype_t type; /* type of data */
}; };
...@@ -392,7 +420,7 @@ typedef struct big_rec_field_struct big_rec_field_t; ...@@ -392,7 +420,7 @@ typedef struct big_rec_field_struct big_rec_field_t;
struct big_rec_field_struct { struct big_rec_field_struct {
ulint field_no; /* field number in record */ ulint field_no; /* field number in record */
ulint len; /* stored data len */ ulint len; /* stored data len */
byte* data; /* stored data */ const void* data; /* stored data */
}; };
/* Storage format for overflow data in a big record, that is, a record /* Storage format for overflow data in a big record, that is, a record
......
...@@ -87,9 +87,51 @@ dfield_set_len( ...@@ -87,9 +87,51 @@ dfield_set_len(
{ {
ut_ad(field); ut_ad(field);
field->ext = 0;
field->len = len; field->len = len;
} }
/*************************************************************************
Determines if a field is SQL NULL */
UNIV_INLINE
ulint
dfield_is_null(
/*===========*/
/* out: nonzero if SQL null data */
const dfield_t* field) /* in: field */
{
ut_ad(field);
return(field->len == UNIV_SQL_NULL);
}
/*************************************************************************
Determines if a field is externally stored */
UNIV_INLINE
ulint
dfield_is_ext(
/*==========*/
/* out: nonzero if externally stored */
const dfield_t* field) /* in: field */
{
ut_ad(field);
return(UNIV_UNLIKELY(field->ext));
}
/*************************************************************************
Sets the "external storage" flag */
UNIV_INLINE
void
dfield_set_ext(
/*===========*/
dfield_t* field) /* in/out: field */
{
ut_ad(field);
field->ext = 1;
}
/************************************************************************* /*************************************************************************
Sets pointer to the data and length in a field. */ Sets pointer to the data and length in a field. */
UNIV_INLINE UNIV_INLINE
...@@ -103,22 +145,35 @@ dfield_set_data( ...@@ -103,22 +145,35 @@ dfield_set_data(
ut_ad(field); ut_ad(field);
field->data = (void*) data; field->data = (void*) data;
field->ext = 0;
field->len = len; field->len = len;
} }
/*************************************************************************
Sets a data field to SQL NULL. */
UNIV_INLINE
void
dfield_set_null(
/*============*/
dfield_t* field) /* in/out: field */
{
dfield_set_data(field, NULL, UNIV_SQL_NULL);
}
/************************************************************************* /*************************************************************************
Copies the data and len fields. */ Copies the data and len fields. */
UNIV_INLINE UNIV_INLINE
void void
dfield_copy_data( dfield_copy_data(
/*=============*/ /*=============*/
dfield_t* field1, /* in: field to copy to */ dfield_t* field1, /* out: field to copy to */
dfield_t* field2) /* in: field to copy from */ const dfield_t* field2) /* in: field to copy from */
{ {
ut_ad(field1 && field2); ut_ad(field1 && field2);
field1->data = field2->data; field1->data = field2->data;
field1->len = field2->len; field1->len = field2->len;
field1->ext = field2->ext;
} }
/************************************************************************* /*************************************************************************
...@@ -127,7 +182,7 @@ UNIV_INLINE ...@@ -127,7 +182,7 @@ UNIV_INLINE
void void
dfield_copy( dfield_copy(
/*========*/ /*========*/
dfield_t* field1, /* in: field to copy to */ dfield_t* field1, /* out: field to copy to */
const dfield_t* field2) /* in: field to copy from */ const dfield_t* field2) /* in: field to copy from */
{ {
*field1 = *field2; *field1 = *field2;
...@@ -412,11 +467,7 @@ data_write_sql_null( ...@@ -412,11 +467,7 @@ data_write_sql_null(
byte* data, /* in: pointer to a buffer of size len */ byte* data, /* in: pointer to a buffer of size len */
ulint len) /* in: SQL null size in bytes */ ulint len) /* in: SQL null size in bytes */
{ {
ulint j; memset(data, 0, len);
for (j = 0; j < len; j++) {
data[j] = '\0';
}
} }
/************************************************************************** /**************************************************************************
...@@ -434,8 +485,7 @@ dtuple_contains_null( ...@@ -434,8 +485,7 @@ dtuple_contains_null(
n = dtuple_get_n_fields(tuple); n = dtuple_get_n_fields(tuple);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (dfield_get_len(dtuple_get_nth_field(tuple, i)) if (dfield_is_null(dtuple_get_nth_field(tuple, i))) {
== UNIV_SQL_NULL) {
return(TRUE); return(TRUE);
} }
......
...@@ -150,8 +150,7 @@ page_cur_tuple_insert( ...@@ -150,8 +150,7 @@ page_cur_tuple_insert(
page_cur_t* cursor, /* in/out: a page cursor */ page_cur_t* cursor, /* in/out: a page cursor */
const dtuple_t* tuple, /* in: pointer to a data tuple */ const dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in ext */
mtr_t* mtr); /* in: mini-transaction handle, or NULL */ mtr_t* mtr); /* in: mini-transaction handle, or NULL */
/*************************************************************** /***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if Inserts a record next to page cursor. Returns pointer to inserted record if
......
...@@ -218,14 +218,13 @@ page_cur_tuple_insert( ...@@ -218,14 +218,13 @@ page_cur_tuple_insert(
page_cur_t* cursor, /* in/out: a page cursor */ page_cur_t* cursor, /* in/out: a page cursor */
const dtuple_t* tuple, /* in: pointer to a data tuple */ const dtuple_t* tuple, /* in: pointer to a data tuple */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext, /* in: number of externally stored columns */
ulint n_ext, /* in: number of elements in ext */
mtr_t* mtr) /* in: mini-transaction handle, or NULL */ mtr_t* mtr) /* in: mini-transaction handle, or NULL */
{ {
mem_heap_t* heap; mem_heap_t* heap;
ulint* offsets; ulint* offsets;
ulint size ulint size
= rec_get_converted_size(index, tuple, ext, n_ext); = rec_get_converted_size(index, tuple, n_ext);
rec_t* rec; rec_t* rec;
heap = mem_heap_create(size heap = mem_heap_create(size
...@@ -233,7 +232,7 @@ page_cur_tuple_insert( ...@@ -233,7 +232,7 @@ page_cur_tuple_insert(
+ dtuple_get_n_fields(tuple)) + dtuple_get_n_fields(tuple))
* sizeof *offsets); * sizeof *offsets);
rec = rec_convert_dtuple_to_rec(mem_heap_alloc(heap, size), rec = rec_convert_dtuple_to_rec(mem_heap_alloc(heap, size),
index, tuple, ext, n_ext); index, tuple, n_ext);
offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap); offsets = rec_get_offsets(rec, index, NULL, ULINT_UNDEFINED, &heap);
if (buf_block_get_page_zip(cursor->block)) { if (buf_block_get_page_zip(cursor->block)) {
......
...@@ -617,10 +617,7 @@ rec_convert_dtuple_to_rec_comp( ...@@ -617,10 +617,7 @@ rec_convert_dtuple_to_rec_comp(
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
ulint status, /* in: status bits of the record */ ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */ const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */ ulint n_fields);/* in: number of data fields */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext); /* in: number of elements in ext */
/************************************************************* /*************************************************************
Builds a physical record out of a data tuple and Builds a physical record out of a data tuple and
stores it into the given buffer. */ stores it into the given buffer. */
...@@ -634,9 +631,7 @@ rec_convert_dtuple_to_rec( ...@@ -634,9 +631,7 @@ rec_convert_dtuple_to_rec(
physical record */ physical record */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers, ulint n_ext); /* in: number of externally stored columns */
in ascending order */
ulint n_ext); /* in: number of elements in ext */
/************************************************************** /**************************************************************
Returns the extra size of an old-style physical record if we know its Returns the extra size of an old-style physical record if we know its
data size and number of fields. */ data size and number of fields. */
...@@ -661,8 +656,6 @@ rec_get_converted_size_comp( ...@@ -661,8 +656,6 @@ rec_get_converted_size_comp(
ulint status, /* in: status bits of the record */ ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */ const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */ ulint n_fields,/* in: number of data fields */
const ulint* ext, /* in: array of extern field numbers */
ulint n_ext, /* in: number of elements in ext */
ulint* extra); /* out: extra size */ ulint* extra); /* out: extra size */
/************************************************************** /**************************************************************
The following function returns the size of a data tuple when converted to The following function returns the size of a data tuple when converted to
...@@ -674,8 +667,7 @@ rec_get_converted_size( ...@@ -674,8 +667,7 @@ rec_get_converted_size(
/* out: size */ /* out: size */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext); /* in: number of externally stored columns */
ulint n_ext); /* in: number of elements in ext */
/****************************************************************** /******************************************************************
Copies the first n fields of a physical record to a data tuple. Copies the first n fields of a physical record to a data tuple.
The fields are copied to the memory heap. */ The fields are copied to the memory heap. */
......
...@@ -1522,8 +1522,7 @@ rec_get_converted_size( ...@@ -1522,8 +1522,7 @@ rec_get_converted_size(
/* out: size */ /* out: size */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers */ ulint n_ext) /* in: number of externally stored columns */
ulint n_ext) /* in: number of elements in ext */
{ {
ulint data_size; ulint data_size;
ulint extra_size; ulint extra_size;
...@@ -1544,8 +1543,7 @@ rec_get_converted_size( ...@@ -1544,8 +1543,7 @@ rec_get_converted_size(
dtuple_get_info_bits(dtuple) dtuple_get_info_bits(dtuple)
& REC_NEW_STATUS_MASK, & REC_NEW_STATUS_MASK,
dtuple->fields, dtuple->fields,
dtuple->n_fields, dtuple->n_fields, NULL));
ext, n_ext, NULL));
} }
data_size = dtuple_get_data_size(dtuple); data_size = dtuple_get_data_size(dtuple);
......
...@@ -70,9 +70,8 @@ row_ins_index_entry( ...@@ -70,9 +70,8 @@ row_ins_index_entry(
DB_DUPLICATE_KEY, or some other error code */ DB_DUPLICATE_KEY, or some other error code */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry to insert */ dtuple_t* entry, /* in: index entry to insert */
ulint* ext_vec,/* in: array containing field numbers of ulint n_ext, /* in: number of externally stored columns */
externally stored fields in entry, or NULL */ ibool foreign,/* in: TRUE=check foreign key constraints */
ulint n_ext_vec,/* in: number of fields in ext_vec */
que_thr_t* thr); /* in: query thread */ que_thr_t* thr); /* in: query thread */
/*************************************************************** /***************************************************************
Inserts a row to a table. */ Inserts a row to a table. */
......
...@@ -101,12 +101,15 @@ Converts an index record to a typed data tuple. */ ...@@ -101,12 +101,15 @@ Converts an index record to a typed data tuple. */
dtuple_t* dtuple_t*
row_rec_to_index_entry_low( row_rec_to_index_entry_low(
/*=======================*/ /*=======================*/
/* out, index entry built; does not /* out: index entry built; does not
set info_bits, and the data fields in set info_bits, and the data fields in
the entry will point directly to rec */ the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */ const rec_t* rec, /* in: record in the index */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally stored columns;
if this is passed as NULL, such columns are
not flagged nor counted */
mem_heap_t* heap); /* in: memory heap from which the memory mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */ needed is allocated */
/*********************************************************************** /***********************************************************************
......
...@@ -175,9 +175,6 @@ row_upd_build_difference_binary( ...@@ -175,9 +175,6 @@ row_upd_build_difference_binary(
fields, excluding roll ptr and trx id */ fields, excluding roll ptr and trx id */
dict_index_t* index, /* in: clustered index */ dict_index_t* index, /* in: clustered index */
const dtuple_t* entry, /* in: entry to insert */ const dtuple_t* entry, /* in: entry to insert */
const ulint* ext_vec,/* in: array containing field numbers of
externally stored fields in entry, or NULL */
ulint n_ext_vec,/* in: number of fields in ext_vec */
const rec_t* rec, /* in: clustered index record */ const rec_t* rec, /* in: clustered index record */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
mem_heap_t* heap); /* in: memory heap from which allocated */ mem_heap_t* heap); /* in: memory heap from which allocated */
...@@ -321,9 +318,6 @@ struct upd_field_struct{ ...@@ -321,9 +318,6 @@ struct upd_field_struct{
constants in the symbol table of the constants in the symbol table of the
query graph */ query graph */
dfield_t new_val; /* new value for the column */ dfield_t new_val; /* new value for the column */
ibool extern_storage; /* this is set to TRUE if dfield
actually contains a reference to
an externally stored field */
}; };
/* Update vector structure */ /* Update vector structure */
...@@ -395,10 +389,7 @@ struct upd_node_struct{ ...@@ -395,10 +389,7 @@ struct upd_node_struct{
to NULL after a successful update */ to NULL after a successful update */
row_ext_t* ext; /* NULL, or prefixes of the externally row_ext_t* ext; /* NULL, or prefixes of the externally
stored columns of the row */ stored columns of the row */
ulint* ext_vec;/* array describing which fields are stored ulint n_ext; /* number of fields in ext_vec */
externally in the clustered index record of
row */
ulint n_ext_vec;/* number of fields in ext_vec */
mem_heap_t* heap; /* memory heap used as auxiliary storage; mem_heap_t* heap; /* memory heap used as auxiliary storage;
this must be emptied after a successful this must be emptied after a successful
update */ update */
......
...@@ -24,7 +24,6 @@ upd_create( ...@@ -24,7 +24,6 @@ upd_create(
mem_heap_t* heap) /* in: heap from which memory allocated */ mem_heap_t* heap) /* in: heap from which memory allocated */
{ {
upd_t* update; upd_t* update;
ulint i;
update = mem_heap_alloc(heap, sizeof(upd_t)); update = mem_heap_alloc(heap, sizeof(upd_t));
...@@ -32,10 +31,6 @@ upd_create( ...@@ -32,10 +31,6 @@ upd_create(
update->n_fields = n; update->n_fields = n;
update->fields = mem_heap_alloc(heap, sizeof(upd_field_t) * n); update->fields = mem_heap_alloc(heap, sizeof(upd_field_t) * n);
for (i = 0; i < n; i++) {
update->fields[i].extern_storage = 0;
}
return(update); return(update);
} }
......
...@@ -138,12 +138,6 @@ ut_2_power_up( ...@@ -138,12 +138,6 @@ ut_2_power_up(
store the given number of bits. */ store the given number of bits. */
#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8) #define UT_BITS_IN_BYTES(b) (((b) + 7) / 8)
/****************************************************************
Sort function for ulint arrays. */
void
ut_ulint_sort(ulint* arr, ulint* aux_arr, ulint low, ulint high);
/*============================================================*/
/************************************************************** /**************************************************************
Returns system time. We do not specify the format of the time returned: Returns system time. We do not specify the format of the time returned:
the only way to manipulate it is to use the function ut_difftime. */ the only way to manipulate it is to use the function ut_difftime. */
......
...@@ -356,8 +356,7 @@ page_create_low( ...@@ -356,8 +356,7 @@ page_create_low(
heap_top = page + PAGE_DATA; heap_top = page + PAGE_DATA;
infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple, 0);
tuple, NULL, 0);
if (UNIV_LIKELY(comp)) { if (UNIV_LIKELY(comp)) {
ut_a(infimum_rec == page + PAGE_NEW_INFIMUM); ut_a(infimum_rec == page + PAGE_NEW_INFIMUM);
...@@ -386,8 +385,7 @@ page_create_low( ...@@ -386,8 +385,7 @@ page_create_low(
dtype_set(dfield_get_type(field), dtype_set(dfield_get_type(field),
DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9); DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, comp ? 8 : 9);
supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple, 0);
tuple, NULL, 0);
if (UNIV_LIKELY(comp)) { if (UNIV_LIKELY(comp)) {
ut_a(supremum_rec == page + PAGE_NEW_SUPREMUM); ut_a(supremum_rec == page + PAGE_NEW_SUPREMUM);
......
...@@ -263,7 +263,7 @@ sym_tab_add_null_lit( ...@@ -263,7 +263,7 @@ sym_tab_add_null_lit(
node->common.val.type.mtype = DATA_ERROR; node->common.val.type.mtype = DATA_ERROR;
dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL); dfield_set_null(&node->common.val);
node->common.val_buf_size = 0; node->common.val_buf_size = 0;
node->prefetch_buf = NULL; node->prefetch_buf = NULL;
...@@ -301,7 +301,7 @@ sym_tab_add_id( ...@@ -301,7 +301,7 @@ sym_tab_add_id(
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL); dfield_set_null(&node->common.val);
node->common.val_buf_size = 0; node->common.val_buf_size = 0;
node->prefetch_buf = NULL; node->prefetch_buf = NULL;
...@@ -340,7 +340,7 @@ sym_tab_add_bound_id( ...@@ -340,7 +340,7 @@ sym_tab_add_bound_id(
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL); dfield_set_null(&node->common.val);
node->common.val_buf_size = 0; node->common.val_buf_size = 0;
node->prefetch_buf = NULL; node->prefetch_buf = NULL;
......
...@@ -727,14 +727,11 @@ rec_get_converted_size_comp( ...@@ -727,14 +727,11 @@ rec_get_converted_size_comp(
ulint status, /* in: status bits of the record */ ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */ const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */ ulint n_fields,/* in: number of data fields */
const ulint* ext, /* in: array of extern field numbers */
ulint n_ext, /* in: number of elements in ext */
ulint* extra) /* out: extra size */ ulint* extra) /* out: extra size */
{ {
ulint extra_size; ulint extra_size;
ulint data_size; ulint data_size;
ulint i; ulint i;
ulint j;
ut_ad(index); ut_ad(index);
ut_ad(fields); ut_ad(fields);
ut_ad(n_fields > 0); ut_ad(n_fields > 0);
...@@ -748,7 +745,6 @@ rec_get_converted_size_comp( ...@@ -748,7 +745,6 @@ rec_get_converted_size_comp(
n_fields--; n_fields--;
ut_ad(n_fields == dict_index_get_n_unique_in_tree(index)); ut_ad(n_fields == dict_index_get_n_unique_in_tree(index));
ut_ad(fields[n_fields].len == 4); ut_ad(fields[n_fields].len == 4);
ut_ad(!n_ext);
data_size = 4; /* child page number */ data_size = 4; /* child page number */
break; break;
case REC_STATUS_INFIMUM: case REC_STATUS_INFIMUM:
...@@ -766,19 +762,19 @@ rec_get_converted_size_comp( ...@@ -766,19 +762,19 @@ rec_get_converted_size_comp(
+ UT_BITS_IN_BYTES(index->n_nullable); + UT_BITS_IN_BYTES(index->n_nullable);
/* read the lengths of fields 0..n */ /* read the lengths of fields 0..n */
for (i = j = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
dict_field_t* field; const dict_field_t* field;
ulint len; ulint len;
const dict_col_t* col; const dict_col_t* col;
field = dict_index_get_nth_field(index, i); field = dict_index_get_nth_field(index, i);
len = fields[i].len; len = dfield_get_len(&fields[i]);
col = dict_field_get_col(field); col = dict_field_get_col(field);
ut_ad(dict_col_type_assert_equal(col, ut_ad(dict_col_type_assert_equal(col,
dfield_get_type(&fields[i]))); dfield_get_type(&fields[i])));
if (len == UNIV_SQL_NULL) { if (dfield_is_null(&fields[i])) {
/* No length is stored for NULL fields. */ /* No length is stored for NULL fields. */
ut_ad(!(col->prtype & DATA_NOT_NULL)); ut_ad(!(col->prtype & DATA_NOT_NULL));
continue; continue;
...@@ -791,8 +787,7 @@ rec_get_converted_size_comp( ...@@ -791,8 +787,7 @@ rec_get_converted_size_comp(
/* dict_index_add_col() should guarantee this */ /* dict_index_add_col() should guarantee this */
ut_ad(!field->prefix_len ut_ad(!field->prefix_len
|| field->fixed_len == field->prefix_len); || field->fixed_len == field->prefix_len);
} else if (UNIV_UNLIKELY(j < n_ext) && i == ext[j]) { } else if (dfield_is_ext(&fields[i])) {
j++;
extra_size += 2; extra_size += 2;
} else if (len < 128 } else if (len < 128
|| (col->len < 256 && col->mtype != DATA_BLOB)) { || (col->len < 256 && col->mtype != DATA_BLOB)) {
...@@ -807,8 +802,6 @@ rec_get_converted_size_comp( ...@@ -807,8 +802,6 @@ rec_get_converted_size_comp(
data_size += len; data_size += len;
} }
ut_ad(j == n_ext);
func_exit: func_exit:
if (UNIV_LIKELY_NULL(extra)) { if (UNIV_LIKELY_NULL(extra)) {
*extra = extra_size; *extra = extra_size;
...@@ -885,8 +878,6 @@ rec_convert_dtuple_to_rec_old( ...@@ -885,8 +878,6 @@ rec_convert_dtuple_to_rec_old(
physical record */ physical record */
byte* buf, /* in: start address of the physical record */ byte* buf, /* in: start address of the physical record */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext) /* in: number of externally stored columns */ ulint n_ext) /* in: number of externally stored columns */
{ {
const dfield_t* field; const dfield_t* field;
...@@ -895,7 +886,6 @@ rec_convert_dtuple_to_rec_old( ...@@ -895,7 +886,6 @@ rec_convert_dtuple_to_rec_old(
rec_t* rec; rec_t* rec;
ulint end_offset; ulint end_offset;
ulint ored_offset; ulint ored_offset;
const byte* data;
ulint len; ulint len;
ulint i; ulint i;
...@@ -935,10 +925,7 @@ rec_convert_dtuple_to_rec_old( ...@@ -935,10 +925,7 @@ rec_convert_dtuple_to_rec_old(
field = dtuple_get_nth_field(dtuple, i); field = dtuple_get_nth_field(dtuple, i);
data = dfield_get_data(field); if (dfield_is_null(field)) {
len = dfield_get_len(field);
if (len == UNIV_SQL_NULL) {
len = dtype_get_sql_null_size( len = dtype_get_sql_null_size(
dfield_get_type(field)); dfield_get_type(field));
data_write_sql_null(rec + end_offset, len); data_write_sql_null(rec + end_offset, len);
...@@ -948,7 +935,10 @@ rec_convert_dtuple_to_rec_old( ...@@ -948,7 +935,10 @@ rec_convert_dtuple_to_rec_old(
| REC_1BYTE_SQL_NULL_MASK; | REC_1BYTE_SQL_NULL_MASK;
} else { } else {
/* If the data is not SQL null, store it */ /* If the data is not SQL null, store it */
ut_memcpy(rec + end_offset, data, len); len = dfield_get_len(field);
memcpy(rec + end_offset,
dfield_get_data(field), len);
end_offset += len; end_offset += len;
ored_offset = end_offset; ored_offset = end_offset;
...@@ -957,18 +947,13 @@ rec_convert_dtuple_to_rec_old( ...@@ -957,18 +947,13 @@ rec_convert_dtuple_to_rec_old(
rec_1_set_field_end_info(rec, i, ored_offset); rec_1_set_field_end_info(rec, i, ored_offset);
} }
} else { } else {
ulint j;
rec_set_1byte_offs_flag(rec, FALSE); rec_set_1byte_offs_flag(rec, FALSE);
for (i = j = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(dtuple, i); field = dtuple_get_nth_field(dtuple, i);
data = dfield_get_data(field); if (dfield_is_null(field)) {
len = dfield_get_len(field);
if (len == UNIV_SQL_NULL) {
len = dtype_get_sql_null_size( len = dtype_get_sql_null_size(
dfield_get_type(field)); dfield_get_type(field));
data_write_sql_null(rec + end_offset, len); data_write_sql_null(rec + end_offset, len);
...@@ -978,21 +963,21 @@ rec_convert_dtuple_to_rec_old( ...@@ -978,21 +963,21 @@ rec_convert_dtuple_to_rec_old(
| REC_2BYTE_SQL_NULL_MASK; | REC_2BYTE_SQL_NULL_MASK;
} else { } else {
/* If the data is not SQL null, store it */ /* If the data is not SQL null, store it */
ut_memcpy(rec + end_offset, data, len); len = dfield_get_len(field);
memcpy(rec + end_offset,
dfield_get_data(field), len);
end_offset += len; end_offset += len;
ored_offset = end_offset; ored_offset = end_offset;
if (UNIV_UNLIKELY(j < n_ext) && i == ext[j]) { if (dfield_is_ext(field)) {
j++;
ored_offset |= REC_2BYTE_EXTERN_MASK; ored_offset |= REC_2BYTE_EXTERN_MASK;
} }
} }
rec_2_set_field_end_info(rec, i, ored_offset); rec_2_set_field_end_info(rec, i, ored_offset);
} }
ut_ad(j == n_ext);
} }
return(rec); return(rec);
...@@ -1011,10 +996,7 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1011,10 +996,7 @@ rec_convert_dtuple_to_rec_comp(
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
ulint status, /* in: status bits of the record */ ulint status, /* in: status bits of the record */
const dfield_t* fields, /* in: array of data fields */ const dfield_t* fields, /* in: array of data fields */
ulint n_fields,/* in: number of data fields */ ulint n_fields)/* in: number of data fields */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext) /* in: number of elements in ext */
{ {
const dfield_t* field; const dfield_t* field;
const dtype_t* type; const dtype_t* type;
...@@ -1023,7 +1005,6 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1023,7 +1005,6 @@ rec_convert_dtuple_to_rec_comp(
byte* lens; byte* lens;
ulint len; ulint len;
ulint i; ulint i;
ulint j;
ulint n_node_ptr_field; ulint n_node_ptr_field;
ulint fixed_len; ulint fixed_len;
ulint null_mask = 1; ulint null_mask = 1;
...@@ -1057,7 +1038,7 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1057,7 +1038,7 @@ rec_convert_dtuple_to_rec_comp(
/* Store the data and the offsets */ /* Store the data and the offsets */
for (i = j = 0, field = fields; i < n_fields; i++, field++) { for (i = 0, field = fields; i < n_fields; i++, field++) {
type = dfield_get_type(field); type = dfield_get_type(field);
len = dfield_get_len(field); len = dfield_get_len(field);
...@@ -1081,7 +1062,7 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1081,7 +1062,7 @@ rec_convert_dtuple_to_rec_comp(
ut_ad(*nulls < null_mask); ut_ad(*nulls < null_mask);
/* set the null flag if necessary */ /* set the null flag if necessary */
if (len == UNIV_SQL_NULL) { if (dfield_is_null(field)) {
*nulls |= null_mask; *nulls |= null_mask;
null_mask <<= 1; null_mask <<= 1;
continue; continue;
...@@ -1090,24 +1071,24 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1090,24 +1071,24 @@ rec_convert_dtuple_to_rec_comp(
null_mask <<= 1; null_mask <<= 1;
} }
/* only nullable fields can be null */ /* only nullable fields can be null */
ut_ad(len != UNIV_SQL_NULL); ut_ad(!dfield_is_null(field));
fixed_len = dict_index_get_nth_field(index, i)->fixed_len; fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
if (fixed_len) { if (fixed_len) {
ut_ad(len == fixed_len); ut_ad(len == fixed_len);
ut_ad(!dfield_is_ext(field));
} else if (dfield_is_ext(field)) {
ut_ad(len < REC_MAX_INDEX_COL_LEN);
*lens-- = (byte) (len >> 8) | 0xc0;
*lens-- = (byte) len;
} else { } else {
ut_ad(len <= dtype_get_len(type) ut_ad(len <= dtype_get_len(type)
|| dtype_get_mtype(type) == DATA_BLOB); || dtype_get_mtype(type) == DATA_BLOB);
if (UNIV_UNLIKELY(j < n_ext) && i == ext[j]) { if (len < 128
j++; || (dtype_get_len(type) < 256
ut_ad(len < REC_MAX_INDEX_COL_LEN); && dtype_get_mtype(type) != DATA_BLOB)) {
*lens-- = (byte) (len >> 8) | 0xc0;
*lens-- = (byte) len;
} else if (len < 128
|| (dtype_get_len(type) < 256
&& dtype_get_mtype(type)
!= DATA_BLOB)) {
*lens-- = (byte) len; *lens-- = (byte) len;
} else { } else {
ut_ad(len < 16384); ut_ad(len < 16384);
...@@ -1119,8 +1100,6 @@ rec_convert_dtuple_to_rec_comp( ...@@ -1119,8 +1100,6 @@ rec_convert_dtuple_to_rec_comp(
memcpy(end, dfield_get_data(field), len); memcpy(end, dfield_get_data(field), len);
end += len; end += len;
} }
ut_ad(j == n_ext);
} }
/************************************************************* /*************************************************************
...@@ -1134,10 +1113,7 @@ rec_convert_dtuple_to_rec_new( ...@@ -1134,10 +1113,7 @@ rec_convert_dtuple_to_rec_new(
of physical record */ of physical record */
byte* buf, /* in: start address of the physical record */ byte* buf, /* in: start address of the physical record */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple) /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers,
in ascending order */
ulint n_ext) /* in: number of elements in ext */
{ {
ulint extra_size; ulint extra_size;
ulint status; ulint status;
...@@ -1146,12 +1122,12 @@ rec_convert_dtuple_to_rec_new( ...@@ -1146,12 +1122,12 @@ rec_convert_dtuple_to_rec_new(
status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK; status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK;
rec_get_converted_size_comp(index, status, rec_get_converted_size_comp(index, status,
dtuple->fields, dtuple->n_fields, dtuple->fields, dtuple->n_fields,
ext, n_ext, &extra_size); &extra_size);
rec = buf + extra_size; rec = buf + extra_size;
rec_convert_dtuple_to_rec_comp( rec_convert_dtuple_to_rec_comp(
rec, REC_N_NEW_EXTRA_BYTES, index, status, rec, REC_N_NEW_EXTRA_BYTES, index, status,
dtuple->fields, dtuple->n_fields, ext, n_ext); dtuple->fields, dtuple->n_fields);
/* Set the info bits of the record */ /* Set the info bits of the record */
rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple)); rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple));
...@@ -1172,9 +1148,7 @@ rec_convert_dtuple_to_rec( ...@@ -1172,9 +1148,7 @@ rec_convert_dtuple_to_rec(
physical record */ physical record */
dict_index_t* index, /* in: record descriptor */ dict_index_t* index, /* in: record descriptor */
const dtuple_t* dtuple, /* in: data tuple */ const dtuple_t* dtuple, /* in: data tuple */
const ulint* ext, /* in: array of extern field numbers, ulint n_ext) /* in: number of externally stored columns */
in ascending order */
ulint n_ext) /* in: number of elements in ext */
{ {
rec_t* rec; rec_t* rec;
...@@ -1183,10 +1157,9 @@ rec_convert_dtuple_to_rec( ...@@ -1183,10 +1157,9 @@ rec_convert_dtuple_to_rec(
ut_ad(dtuple_check_typed(dtuple)); ut_ad(dtuple_check_typed(dtuple));
if (dict_table_is_comp(index->table)) { if (dict_table_is_comp(index->table)) {
rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple, rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
ext, n_ext);
} else { } else {
rec = rec_convert_dtuple_to_rec_old(buf, dtuple, ext, n_ext); rec = rec_convert_dtuple_to_rec_old(buf, dtuple, n_ext);
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -1220,13 +1193,9 @@ rec_copy_prefix_to_dtuple( ...@@ -1220,13 +1193,9 @@ rec_copy_prefix_to_dtuple(
ulint n_fields, /* in: number of fields to copy */ ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap) /* in: memory heap */ mem_heap_t* heap) /* in: memory heap */
{ {
dfield_t* field; ulint i;
const byte* data; ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint len; ulint* offsets = offsets_;
byte* buf = NULL;
ulint i;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
*offsets_ = (sizeof offsets_) / sizeof *offsets_; *offsets_ = (sizeof offsets_) / sizeof *offsets_;
offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap); offsets = rec_get_offsets(rec, index, offsets, n_fields, &heap);
...@@ -1238,17 +1207,19 @@ rec_copy_prefix_to_dtuple( ...@@ -1238,17 +1207,19 @@ rec_copy_prefix_to_dtuple(
rec, dict_table_is_comp(index->table))); rec, dict_table_is_comp(index->table)));
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
dfield_t* field;
const byte* data;
ulint len;
field = dtuple_get_nth_field(tuple, i); field = dtuple_get_nth_field(tuple, i);
data = rec_get_nth_field(rec, offsets, i, &len); data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) { if (len != UNIV_SQL_NULL) {
buf = mem_heap_alloc(heap, len); dfield_set_data(field,
mem_heap_dup(heap, data, len), len);
ut_memcpy(buf, data, len); } else {
dfield_set_null(field);
} }
dfield_set_data(field, buf, len);
} }
} }
......
...@@ -290,9 +290,6 @@ row_ins_clust_index_entry_by_modify( ...@@ -290,9 +290,6 @@ row_ins_clust_index_entry_by_modify(
which have to be stored externally by the which have to be stored externally by the
caller */ caller */
const dtuple_t* entry, /* in: index entry to insert */ const dtuple_t* entry, /* in: index entry to insert */
const ulint* ext_vec,/* in: array containing field numbers of
externally stored fields in entry, or NULL */
ulint n_ext_vec,/* in: number of fields in ext_vec */
que_thr_t* thr, /* in: query thread */ que_thr_t* thr, /* in: query thread */
mtr_t* mtr) /* in: mtr; must be committed before mtr_t* mtr) /* in: mtr; must be committed before
latching any further pages */ latching any further pages */
...@@ -318,8 +315,7 @@ row_ins_clust_index_entry_by_modify( ...@@ -318,8 +315,7 @@ row_ins_clust_index_entry_by_modify(
NOTE that this vector may NOT contain system columns trx_id or NOTE that this vector may NOT contain system columns trx_id or
roll_ptr */ roll_ptr */
update = row_upd_build_difference_binary(cursor->index, entry, ext_vec, update = row_upd_build_difference_binary(cursor->index, entry, rec,
n_ext_vec, rec,
thr_get_trx(thr), *heap); thr_get_trx(thr), *heap);
if (mode == BTR_MODIFY_LEAF) { if (mode == BTR_MODIFY_LEAF) {
/* Try optimistic updating of the record, keeping changes /* Try optimistic updating of the record, keeping changes
...@@ -494,11 +490,12 @@ row_ins_cascade_calc_update_vec( ...@@ -494,11 +490,12 @@ row_ins_cascade_calc_update_vec(
ufield->exp = NULL; ufield->exp = NULL;
ufield->new_val = parent_ufield->new_val; ufield->new_val = parent_ufield->new_val;
ufield->new_val.ext = 0;
/* Do not allow a NOT NULL column to be /* Do not allow a NOT NULL column to be
updated as NULL */ updated as NULL */
if (ufield->new_val.len == UNIV_SQL_NULL if (dfield_is_null(&ufield->new_val)
&& (col->prtype & DATA_NOT_NULL)) { && (col->prtype & DATA_NOT_NULL)) {
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
...@@ -507,7 +504,7 @@ row_ins_cascade_calc_update_vec( ...@@ -507,7 +504,7 @@ row_ins_cascade_calc_update_vec(
/* If the new value would not fit in the /* If the new value would not fit in the
column, do not allow the update */ column, do not allow the update */
if (ufield->new_val.len != UNIV_SQL_NULL if (!dfield_is_null(&ufield->new_val)
&& dtype_get_at_most_n_mbchars( && dtype_get_at_most_n_mbchars(
col->prtype, col->prtype,
col->mbminlen, col->mbmaxlen, col->mbminlen, col->mbmaxlen,
...@@ -527,7 +524,7 @@ row_ins_cascade_calc_update_vec( ...@@ -527,7 +524,7 @@ row_ins_cascade_calc_update_vec(
min_size = dict_col_get_min_size(col); min_size = dict_col_get_min_size(col);
if (min_size if (min_size
&& ufield->new_val.len != UNIV_SQL_NULL && !dfield_is_null(&ufield->new_val)
&& ufield->new_val.len < min_size) { && ufield->new_val.len < min_size) {
char* pad_start; char* pad_start;
...@@ -575,8 +572,6 @@ row_ins_cascade_calc_update_vec( ...@@ -575,8 +572,6 @@ row_ins_cascade_calc_update_vec(
} }
} }
ufield->extern_storage = FALSE;
n_fields_updated++; n_fields_updated++;
} }
} }
...@@ -1005,9 +1000,7 @@ row_ins_foreign_check_on_constraint( ...@@ -1005,9 +1000,7 @@ row_ins_foreign_check_on_constraint(
table, table,
dict_index_get_nth_col_no(index, i)); dict_index_get_nth_col_no(index, i));
(update->fields + i)->exp = NULL; (update->fields + i)->exp = NULL;
(update->fields + i)->new_val.len = UNIV_SQL_NULL; dfield_set_null(&update->fields[i].new_val);
(update->fields + i)->new_val.data = NULL;
(update->fields + i)->extern_storage = FALSE;
} }
} }
...@@ -1994,9 +1987,7 @@ row_ins_index_entry_low( ...@@ -1994,9 +1987,7 @@ row_ins_index_entry_low(
pessimistic descent down the index tree */ pessimistic descent down the index tree */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry to insert */ dtuple_t* entry, /* in: index entry to insert */
ulint* ext_vec,/* in: array containing field numbers of ulint n_ext, /* in: number of externally stored columns */
externally stored fields in entry, or NULL */
ulint n_ext_vec,/* in: number of fields in ext_vec */
que_thr_t* thr) /* in: query thread */ que_thr_t* thr) /* in: query thread */
{ {
btr_cur_t cursor; btr_cur_t cursor;
...@@ -2105,9 +2096,9 @@ row_ins_index_entry_low( ...@@ -2105,9 +2096,9 @@ row_ins_index_entry_low(
if (dict_index_is_clust(index)) { if (dict_index_is_clust(index)) {
err = row_ins_clust_index_entry_by_modify( err = row_ins_clust_index_entry_by_modify(
mode, &cursor, &heap, &big_rec, entry, mode, &cursor, &heap, &big_rec, entry,
ext_vec, n_ext_vec, thr, &mtr); thr, &mtr);
} else { } else {
ut_ad(!n_ext_vec); ut_ad(!n_ext);
err = row_ins_sec_index_entry_by_modify( err = row_ins_sec_index_entry_by_modify(
mode, &cursor, entry, thr, &mtr); mode, &cursor, entry, thr, &mtr);
} }
...@@ -2115,7 +2106,7 @@ row_ins_index_entry_low( ...@@ -2115,7 +2106,7 @@ row_ins_index_entry_low(
if (mode == BTR_MODIFY_LEAF) { if (mode == BTR_MODIFY_LEAF) {
err = btr_cur_optimistic_insert( err = btr_cur_optimistic_insert(
0, &cursor, entry, &insert_rec, &big_rec, 0, &cursor, entry, &insert_rec, &big_rec,
ext_vec, n_ext_vec, thr, &mtr); n_ext, thr, &mtr);
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) { if (buf_LRU_buf_pool_running_out()) {
...@@ -2126,7 +2117,7 @@ row_ins_index_entry_low( ...@@ -2126,7 +2117,7 @@ row_ins_index_entry_low(
} }
err = btr_cur_pessimistic_insert( err = btr_cur_pessimistic_insert(
0, &cursor, entry, &insert_rec, &big_rec, 0, &cursor, entry, &insert_rec, &big_rec,
ext_vec, n_ext_vec, thr, &mtr); n_ext, thr, &mtr);
} }
} }
...@@ -2176,14 +2167,13 @@ row_ins_index_entry( ...@@ -2176,14 +2167,13 @@ row_ins_index_entry(
DB_DUPLICATE_KEY, or some other error code */ DB_DUPLICATE_KEY, or some other error code */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
dtuple_t* entry, /* in: index entry to insert */ dtuple_t* entry, /* in: index entry to insert */
ulint* ext_vec,/* in: array containing field numbers of ulint n_ext, /* in: number of externally stored columns */
externally stored fields in entry, or NULL */ ibool foreign,/* in: TRUE=check foreign key constraints */
ulint n_ext_vec,/* in: number of fields in ext_vec */
que_thr_t* thr) /* in: query thread */ que_thr_t* thr) /* in: query thread */
{ {
ulint err; ulint err;
if (UT_LIST_GET_FIRST(index->table->foreign_list)) { if (foreign && UT_LIST_GET_FIRST(index->table->foreign_list)) {
err = row_ins_check_foreign_constraints(index->table, index, err = row_ins_check_foreign_constraints(index->table, index,
entry, thr); entry, thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -2195,7 +2185,7 @@ row_ins_index_entry( ...@@ -2195,7 +2185,7 @@ row_ins_index_entry(
/* Try first optimistic descent to the B-tree */ /* Try first optimistic descent to the B-tree */
err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry, err = row_ins_index_entry_low(BTR_MODIFY_LEAF, index, entry,
ext_vec, n_ext_vec, thr); n_ext, thr);
if (err != DB_FAIL) { if (err != DB_FAIL) {
return(err); return(err);
...@@ -2204,7 +2194,7 @@ row_ins_index_entry( ...@@ -2204,7 +2194,7 @@ row_ins_index_entry(
/* Try then pessimistic descent to the B-tree */ /* Try then pessimistic descent to the B-tree */
err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry, err = row_ins_index_entry_low(BTR_MODIFY_TREE, index, entry,
ext_vec, n_ext_vec, thr); n_ext, thr);
return(err); return(err);
} }
...@@ -2219,21 +2209,23 @@ row_ins_index_entry_set_vals( ...@@ -2219,21 +2209,23 @@ row_ins_index_entry_set_vals(
dtuple_t* entry, /* in: index entry to make */ dtuple_t* entry, /* in: index entry to make */
const dtuple_t* row) /* in: row */ const dtuple_t* row) /* in: row */
{ {
dict_field_t* ind_field; ulint n_fields;
dfield_t* field; ulint i;
const dfield_t* row_field;
ulint n_fields;
ulint i;
ut_ad(entry && row); ut_ad(entry && row);
n_fields = dtuple_get_n_fields(entry); n_fields = dtuple_get_n_fields(entry);
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
dict_field_t* ind_field;
dfield_t* field;
const dfield_t* row_field;
ulint len;
field = dtuple_get_nth_field(entry, i); field = dtuple_get_nth_field(entry, i);
ind_field = dict_index_get_nth_field(index, i); ind_field = dict_index_get_nth_field(index, i);
row_field = dtuple_get_nth_field(row, ind_field->col->ind); row_field = dtuple_get_nth_field(row, ind_field->col->ind);
len = dfield_get_len(row_field);
/* Check column prefix indexes */ /* Check column prefix indexes */
if (ind_field->prefix_len > 0 if (ind_field->prefix_len > 0
...@@ -2242,15 +2234,13 @@ row_ins_index_entry_set_vals( ...@@ -2242,15 +2234,13 @@ row_ins_index_entry_set_vals(
const dict_col_t* col const dict_col_t* col
= dict_field_get_col(ind_field); = dict_field_get_col(ind_field);
field->len = dtype_get_at_most_n_mbchars( len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminlen, col->mbmaxlen,
ind_field->prefix_len, ind_field->prefix_len,
row_field->len, row_field->data); len, row_field->data);
} else {
field->len = row_field->len;
} }
field->data = row_field->data; dfield_set_data(field, row_field->data, len);
} }
} }
...@@ -2273,7 +2263,7 @@ row_ins_index_entry_step( ...@@ -2273,7 +2263,7 @@ row_ins_index_entry_step(
ut_ad(dtuple_check_typed(node->entry)); ut_ad(dtuple_check_typed(node->entry));
err = row_ins_index_entry(node->index, node->entry, NULL, 0, thr); err = row_ins_index_entry(node->index, node->entry, 0, TRUE, thr);
return(err); return(err);
} }
......
...@@ -7,17 +7,6 @@ Created 12/4/2005 Jan Lindstrom ...@@ -7,17 +7,6 @@ Created 12/4/2005 Jan Lindstrom
Completed by Sunny Bains and Marko Makela Completed by Sunny Bains and Marko Makela
*******************************************************/ *******************************************************/
/******************************************************
TODO:
1. Run test with purify and valgrind and fix possible
errors found.
2. Add more test cases and fix bugs founds.
3. Run benchmarks.
*******************************************************/
#include "row0merge.h" #include "row0merge.h"
#include "row0ext.h" #include "row0ext.h"
#include "row0row.h" #include "row0row.h"
...@@ -185,9 +174,11 @@ row_merge_buf_add( ...@@ -185,9 +174,11 @@ row_merge_buf_add(
column prefixes, or NULL */ column prefixes, or NULL */
{ {
ulint i; ulint i;
ulint j;
ulint n_fields; ulint n_fields;
ulint data_size; ulint data_size;
ulint extra_size; ulint extra_size;
dict_index_t* index;
dfield_t* entry; dfield_t* entry;
dfield_t* field; dfield_t* field;
...@@ -195,45 +186,53 @@ row_merge_buf_add( ...@@ -195,45 +186,53 @@ row_merge_buf_add(
return(FALSE); return(FALSE);
} }
n_fields = dict_index_get_n_fields(buf->index); index = buf->index;
n_fields = dict_index_get_n_fields(index);
entry = mem_heap_alloc(buf->heap, n_fields * sizeof *entry); entry = mem_heap_alloc(buf->heap, n_fields * sizeof *entry);
buf->tuples[buf->n_tuples] = entry; buf->tuples[buf->n_tuples] = entry;
field = entry; field = entry;
data_size = 0; data_size = 0;
extra_size = UT_BITS_IN_BYTES(buf->index->n_nullable); extra_size = UT_BITS_IN_BYTES(index->n_nullable);
for (i = 0; i < n_fields; i++, field++) { for (i = j = 0; i < n_fields; i++, field++) {
dict_field_t* ifield; dict_field_t* ifield;
const dict_col_t* col; const dict_col_t* col;
ulint col_no; ulint col_no;
const dfield_t* row_field; const dfield_t* row_field;
ifield = dict_index_get_nth_field(buf->index, i); ifield = dict_index_get_nth_field(index, i);
col = ifield->col; col = ifield->col;
col_no = dict_col_get_no(col); col_no = dict_col_get_no(col);
row_field = dtuple_get_nth_field(row, col_no); row_field = dtuple_get_nth_field(row, col_no);
dfield_copy(field, row_field); dfield_copy(field, row_field);
if (UNIV_LIKELY_NULL(ext) if (dfield_is_null(field)) {
&& dfield_get_len(row_field) != UNIV_SQL_NULL) { ut_ad(!(col->prtype & DATA_NOT_NULL));
/* See if the column is stored externally. */ field->data = NULL;
continue;
} else if (UNIV_LIKELY(!ext)) {
} else if (dict_index_is_clust(index)) {
/* Flag externally stored fields. */
if (j < ext->n_ext && col_no == ext->ext[j]) {
j++;
ut_a(field->len >= BTR_EXTERN_FIELD_REF_SIZE);
dfield_set_ext(field);
}
} else {
ulint len = field->len;
byte* buf = row_ext_lookup(ext, col_no, byte* buf = row_ext_lookup(ext, col_no,
row_field->data, row_field->data,
row_field->len, row_field->len,
&field->len); &len);
if (UNIV_LIKELY_NULL(buf)) { if (UNIV_LIKELY_NULL(buf)) {
field->data = buf; dfield_set_data(field, buf, len);
} }
} }
if (field->len == UNIV_SQL_NULL) {
ut_ad(!(col->prtype & DATA_NOT_NULL));
field->data = NULL;
continue;
}
/* If a column prefix index, take only the prefix */ /* If a column prefix index, take only the prefix */
if (ifield->prefix_len) { if (ifield->prefix_len) {
...@@ -248,6 +247,9 @@ row_merge_buf_add( ...@@ -248,6 +247,9 @@ row_merge_buf_add(
if (ifield->fixed_len) { if (ifield->fixed_len) {
ut_ad(field->len == ifield->fixed_len); ut_ad(field->len == ifield->fixed_len);
ut_ad(!dfield_is_ext(field));
} else if (dfield_is_ext(field)) {
extra_size += 2;
} else if (field->len < 128 } else if (field->len < 128
|| (col->len < 256 && col->mtype != DATA_BLOB)) { || (col->len < 256 && col->mtype != DATA_BLOB)) {
extra_size++; extra_size++;
...@@ -257,15 +259,16 @@ row_merge_buf_add( ...@@ -257,15 +259,16 @@ row_merge_buf_add(
data_size += field->len; data_size += field->len;
} }
ut_ad(!ext || !dict_index_is_clust(index) || j == ext->n_ext);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
{ {
ulint size; ulint size;
ulint extra; ulint extra;
size = rec_get_converted_size_comp(buf->index, size = rec_get_converted_size_comp(index,
REC_STATUS_ORDINARY, REC_STATUS_ORDINARY,
entry, n_fields, NULL, 0, entry, n_fields, &extra);
&extra);
ut_ad(data_size + extra_size + REC_N_NEW_EXTRA_BYTES == size); ut_ad(data_size + extra_size + REC_N_NEW_EXTRA_BYTES == size);
ut_ad(extra_size + REC_N_NEW_EXTRA_BYTES == extra); ut_ad(extra_size + REC_N_NEW_EXTRA_BYTES == extra);
...@@ -290,7 +293,7 @@ row_merge_buf_add( ...@@ -290,7 +293,7 @@ row_merge_buf_add(
/* Copy the data fields. */ /* Copy the data fields. */
for (i = 0; i < n_fields; i++, field++) { for (i = 0; i < n_fields; i++, field++) {
if (field->len != UNIV_SQL_NULL) { if (!dfield_is_null(field)) {
field->data = mem_heap_dup(buf->heap, field->data = mem_heap_dup(buf->heap,
field->data, field->len); field->data, field->len);
} }
...@@ -360,7 +363,7 @@ row_merge_buf_sort( ...@@ -360,7 +363,7 @@ row_merge_buf_sort(
{ {
ulint n_dup = 0; ulint n_dup = 0;
row_merge_tuple_sort(dict_index_get_n_fields(buf->index), &n_dup, row_merge_tuple_sort(dict_index_get_n_unique(buf->index), &n_dup,
buf->tuples, buf->tmp_tuples, 0, buf->n_tuples); buf->tuples, buf->tmp_tuples, 0, buf->n_tuples);
return(n_dup); return(n_dup);
...@@ -379,16 +382,16 @@ row_merge_buf_write( ...@@ -379,16 +382,16 @@ row_merge_buf_write(
ulint n_fields= dict_index_get_n_fields(index); ulint n_fields= dict_index_get_n_fields(index);
byte* b = &(*block)[0]; byte* b = &(*block)[0];
ulint i; ulint i;
for (i = 0; i < buf->n_tuples; i++) { for (i = 0; i < buf->n_tuples; i++) {
ulint size; ulint size;
ulint extra_size; ulint extra_size;
const dfield_t* entry = buf->tuples[i]; const dfield_t* entry = buf->tuples[i];
size = rec_get_converted_size_comp(buf->index, size = rec_get_converted_size_comp(buf->index,
REC_STATUS_ORDINARY, REC_STATUS_ORDINARY,
entry, n_fields, NULL, 0, entry, n_fields,
&extra_size); &extra_size);
ut_ad(size > extra_size); ut_ad(size > extra_size);
ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES); ut_ad(extra_size >= REC_N_NEW_EXTRA_BYTES);
...@@ -408,7 +411,7 @@ row_merge_buf_write( ...@@ -408,7 +411,7 @@ row_merge_buf_write(
rec_convert_dtuple_to_rec_comp(b + extra_size, 0, index, rec_convert_dtuple_to_rec_comp(b + extra_size, 0, index,
REC_STATUS_ORDINARY, REC_STATUS_ORDINARY,
entry, n_fields, NULL, 0); entry, n_fields);
b += size; b += size;
} }
...@@ -1157,6 +1160,39 @@ row_merge_sort( ...@@ -1157,6 +1160,39 @@ row_merge_sort(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
/*****************************************************************
Copy externally stored columns to the data tuple. */
static
void
row_merge_copy_blobs(
/*=================*/
const mrec_t* mrec, /* in: merge record */
const ulint* offsets,/* in: offsets of mrec */
ulint zip_size,/* in: compressed page size in bytes, or 0 */
dtuple_t* tuple, /* in/out: data tuple */
mem_heap_t* heap) /* in/out: memory heap */
{
ulint i;
ulint n_fields = dtuple_get_n_fields(tuple);
for (i = 0; i < n_fields; i++) {
ulint len;
const void* data;
dfield_t* field = dtuple_get_nth_field(tuple, i);
if (!dfield_is_ext(field)) {
continue;
}
ut_ad(!dfield_is_null(field));
data = btr_rec_copy_externally_stored_field(
mrec, offsets, zip_size, i, &len, heap);
dfield_set_data(field, data, len);
}
}
/************************************************************************ /************************************************************************
Read sorted file containing index data tuples and insert these data Read sorted file containing index data tuples and insert these data
tuples to the index */ tuples to the index */
...@@ -1167,7 +1203,9 @@ row_merge_insert_index_tuples( ...@@ -1167,7 +1203,9 @@ row_merge_insert_index_tuples(
/* out: DB_SUCCESS or error number */ /* out: DB_SUCCESS or error number */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
dict_table_t* table, /* in: table */ dict_table_t* table, /* in: new table */
ulint zip_size,/* in: compressed page size of
the old table, or 0 if uncompressed */
int fd, /* in: file descriptor */ int fd, /* in: file descriptor */
row_merge_block_t* block) /* in/out: file buffer */ row_merge_block_t* block) /* in/out: file buffer */
{ {
...@@ -1215,6 +1253,7 @@ row_merge_insert_index_tuples( ...@@ -1215,6 +1253,7 @@ row_merge_insert_index_tuples(
for (;;) { for (;;) {
const mrec_t* mrec; const mrec_t* mrec;
dtuple_t* dtuple; dtuple_t* dtuple;
ulint n_ext;
b = row_merge_read_rec(block, &buf, b, index, b = row_merge_read_rec(block, &buf, b, index,
fd, &foffs, &mrec, offsets); fd, &foffs, &mrec, offsets);
...@@ -1226,8 +1265,14 @@ row_merge_insert_index_tuples( ...@@ -1226,8 +1265,14 @@ row_merge_insert_index_tuples(
break; break;
} }
n_ext = 0;
dtuple = row_rec_to_index_entry_low( dtuple = row_rec_to_index_entry_low(
mrec, index, offsets, tuple_heap); mrec, index, offsets, &n_ext, tuple_heap);
if (UNIV_UNLIKELY(n_ext)) {
row_merge_copy_blobs(mrec, offsets, zip_size,
dtuple, tuple_heap);
}
node->row = dtuple; node->row = dtuple;
node->table = table; node->table = table;
...@@ -1239,10 +1284,11 @@ row_merge_insert_index_tuples( ...@@ -1239,10 +1284,11 @@ row_merge_insert_index_tuples(
thr->run_node = thr; thr->run_node = thr;
thr->prev_node = thr->common.parent; thr->prev_node = thr->common.parent;
error = row_ins_index_entry( error = row_ins_index_entry(index, dtuple,
index, dtuple, NULL, 0, thr); 0, FALSE, thr);
if (UNIV_LIKELY(error == DB_SUCCESS)) { if (UNIV_LIKELY(error == DB_SUCCESS)) {
goto next_rec; goto next_rec;
} }
...@@ -1707,6 +1753,7 @@ row_merge_build_indexes( ...@@ -1707,6 +1753,7 @@ row_merge_build_indexes(
if (error == DB_SUCCESS) { if (error == DB_SUCCESS) {
error = row_merge_insert_index_tuples( error = row_merge_insert_index_tuples(
trx, indexes[i], new_table, trx, indexes[i], new_table,
dict_table_zip_size(old_table),
merge_files[i].fd, block); merge_files[i].fd, block);
} }
......
...@@ -421,7 +421,7 @@ row_mysql_convert_row_to_innobase( ...@@ -421,7 +421,7 @@ row_mysql_convert_row_to_innobase(
/* It is SQL NULL */ /* It is SQL NULL */
dfield_set_data(dfield, NULL, UNIV_SQL_NULL); dfield_set_null(dfield);
goto next_column; goto next_column;
} }
...@@ -890,7 +890,7 @@ row_get_prebuilt_insert_row( ...@@ -890,7 +890,7 @@ row_get_prebuilt_insert_row(
for (i = 0; i < dtuple_get_n_fields(row); i++) { for (i = 0; i < dtuple_get_n_fields(row); i++) {
dtuple_get_nth_field(row, i)->len = UNIV_SQL_NULL; dfield_set_null(dtuple_get_nth_field(row, i));
} }
ins_node_set_new_row(node, row); ins_node_set_new_row(node, row);
......
...@@ -363,7 +363,6 @@ row_purge_upd_exist_or_extern( ...@@ -363,7 +363,6 @@ row_purge_upd_exist_or_extern(
mem_heap_t* heap; mem_heap_t* heap;
dtuple_t* entry; dtuple_t* entry;
dict_index_t* index; dict_index_t* index;
upd_field_t* ufield;
ibool is_insert; ibool is_insert;
ulint rseg_id; ulint rseg_id;
ulint page_no; ulint page_no;
...@@ -401,9 +400,10 @@ row_purge_upd_exist_or_extern( ...@@ -401,9 +400,10 @@ row_purge_upd_exist_or_extern(
/* Free possible externally stored fields */ /* Free possible externally stored fields */
for (i = 0; i < upd_get_n_fields(node->update); i++) { for (i = 0; i < upd_get_n_fields(node->update); i++) {
ufield = upd_get_nth_field(node->update, i); const upd_field_t* ufield
= upd_get_nth_field(node->update, i);
if (UNIV_UNLIKELY(ufield->extern_storage)) { if (dfield_is_ext(&ufield->new_val)) {
buf_block_t* block; buf_block_t* block;
ulint internal_offset; ulint internal_offset;
byte* data_field; byte* data_field;
...@@ -414,7 +414,7 @@ row_purge_upd_exist_or_extern( ...@@ -414,7 +414,7 @@ row_purge_upd_exist_or_extern(
can calculate from node->roll_ptr the file can calculate from node->roll_ptr the file
address of the new_val data */ address of the new_val data */
internal_offset = ((byte*)ufield->new_val.data) internal_offset = ((const byte*)ufield->new_val.data)
- node->undo_rec; - node->undo_rec;
ut_a(internal_offset < UNIV_PAGE_SIZE); ut_a(internal_offset < UNIV_PAGE_SIZE);
......
...@@ -113,21 +113,19 @@ row_build_index_entry( ...@@ -113,21 +113,19 @@ row_build_index_entry(
dfield_copy(dfield, dfield2); dfield_copy(dfield, dfield2);
if (UNIV_LIKELY_NULL(ext) if (UNIV_LIKELY_NULL(ext) && !dfield_is_null(dfield)) {
&& dfield_get_len(dfield2) != UNIV_SQL_NULL) {
/* See if the column is stored externally. */ /* See if the column is stored externally. */
ulint len = dfield_get_len(dfield);
byte* buf = row_ext_lookup(ext, col_no, byte* buf = row_ext_lookup(ext, col_no,
dfield2->data, dfield->data,
dfield2->len, dfield->len, &len);
&dfield->len);
if (UNIV_LIKELY_NULL(buf)) { if (UNIV_LIKELY_NULL(buf)) {
dfield->data = buf; dfield_set_data(dfield, buf, len);
} }
} }
/* If a column prefix index, take only the prefix */ /* If a column prefix index, take only the prefix */
if (ind_field->prefix_len > 0 if (ind_field->prefix_len > 0 && !dfield_is_null(dfield)) {
&& dfield->len != UNIV_SQL_NULL) {
dfield->len = dtype_get_at_most_n_mbchars( dfield->len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminlen, col->mbmaxlen,
ind_field->prefix_len, ind_field->prefix_len,
...@@ -262,12 +260,15 @@ Converts an index record to a typed data tuple. */ ...@@ -262,12 +260,15 @@ Converts an index record to a typed data tuple. */
dtuple_t* dtuple_t*
row_rec_to_index_entry_low( row_rec_to_index_entry_low(
/*=======================*/ /*=======================*/
/* out, index entry built; does not /* out: index entry built; does not
set info_bits, and the data fields in set info_bits, and the data fields in
the entry will point directly to rec */ the entry will point directly to rec */
const rec_t* rec, /* in: record in the index */ const rec_t* rec, /* in: record in the index */
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
const ulint* offsets,/* in: rec_get_offsets(rec, index) */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint* n_ext, /* out: number of externally stored columns;
if this is passed as NULL, such columns are
not flagged nor counted */
mem_heap_t* heap) /* in: memory heap from which the memory mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */ needed is allocated */
{ {
...@@ -296,6 +297,11 @@ row_rec_to_index_entry_low( ...@@ -296,6 +297,11 @@ row_rec_to_index_entry_low(
field = rec_get_nth_field(rec, offsets, i, &len); field = rec_get_nth_field(rec, offsets, i, &len);
dfield_set_data(dfield, field, len); dfield_set_data(dfield, field, len);
if (n_ext && rec_offs_nth_extern(offsets, i)) {
dfield_set_ext(dfield);
(*n_ext)++;
}
} }
ut_ad(dtuple_check_typed(entry)); ut_ad(dtuple_check_typed(entry));
...@@ -347,7 +353,7 @@ row_rec_to_index_entry( ...@@ -347,7 +353,7 @@ row_rec_to_index_entry(
rec_offs_make_valid(rec, index, offsets); rec_offs_make_valid(rec, index, offsets);
} }
entry = row_rec_to_index_entry_low(rec, index, offsets, heap); entry = row_rec_to_index_entry_low(rec, index, offsets, NULL, heap);
dtuple_set_info_bits(entry, dtuple_set_info_bits(entry,
rec_get_info_bits(rec, rec_offs_comp(offsets))); rec_get_info_bits(rec, rec_offs_comp(offsets)));
...@@ -613,8 +619,7 @@ row_build_row_ref_from_row( ...@@ -613,8 +619,7 @@ row_build_row_ref_from_row(
dfield_copy(dfield, dfield2); dfield_copy(dfield, dfield2);
if (field->prefix_len > 0 if (field->prefix_len > 0 && !dfield_is_null(dfield)) {
&& dfield->len != UNIV_SQL_NULL) {
dfield->len = dtype_get_at_most_n_mbchars( dfield->len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen, col->prtype, col->mbminlen, col->mbmaxlen,
......
...@@ -386,6 +386,10 @@ row_sel_fetch_columns( ...@@ -386,6 +386,10 @@ row_sel_fetch_columns(
data = rec_get_nth_field(rec, offsets, data = rec_get_nth_field(rec, offsets,
field_no, &len); field_no, &len);
if (len == UNIV_SQL_NULL) {
len = UNIV_SQL_NULL;
}
needs_copy = column->copy_val; needs_copy = column->copy_val;
} }
...@@ -2317,7 +2321,7 @@ row_sel_convert_mysql_key_to_innobase( ...@@ -2317,7 +2321,7 @@ row_sel_convert_mysql_key_to_innobase(
data_offset = 1; data_offset = 1;
if (*key_ptr != 0) { if (*key_ptr != 0) {
dfield_set_data(dfield, NULL, UNIV_SQL_NULL); dfield_set_null(dfield);
is_null = TRUE; is_null = TRUE;
} }
......
...@@ -280,7 +280,7 @@ upd_node_create( ...@@ -280,7 +280,7 @@ upd_node_create(
node->row = NULL; node->row = NULL;
node->ext = NULL; node->ext = NULL;
node->ext_vec = NULL; node->n_ext = 0;
node->index = NULL; node->index = NULL;
node->update = NULL; node->update = NULL;
...@@ -392,9 +392,9 @@ row_upd_changes_field_size_or_external( ...@@ -392,9 +392,9 @@ row_upd_changes_field_size_or_external(
upd_field = upd_get_nth_field(update, i); upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val); new_val = &(upd_field->new_val);
new_len = new_val->len; new_len = dfield_get_len(new_val);
if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) { if (dfield_is_null(new_val) && !rec_offs_comp(offsets)) {
/* A bug fixed on Dec 31st, 2004: we looked at the /* A bug fixed on Dec 31st, 2004: we looked at the
SQL NULL size from the wrong field! We may backport SQL NULL size from the wrong field! We may backport
this fix also to 4.0. The merge to 5.0 will be made this fix also to 4.0. The merge to 5.0 will be made
...@@ -420,17 +420,8 @@ row_upd_changes_field_size_or_external( ...@@ -420,17 +420,8 @@ row_upd_changes_field_size_or_external(
old_len = UNIV_SQL_NULL; old_len = UNIV_SQL_NULL;
} }
if (old_len != new_len) { if (dfield_is_ext(new_val) || old_len != new_len
|| rec_offs_nth_extern(offsets, upd_field->field_no)) {
return(TRUE);
}
if (rec_offs_nth_extern(offsets, upd_field->field_no)) {
return(TRUE);
}
if (upd_field->extern_storage) {
return(TRUE); return(TRUE);
} }
...@@ -471,6 +462,8 @@ row_upd_rec_in_place( ...@@ -471,6 +462,8 @@ row_upd_rec_in_place(
for (i = 0; i < n_fields; i++) { for (i = 0; i < n_fields; i++) {
upd_field = upd_get_nth_field(update, i); upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val); new_val = &(upd_field->new_val);
ut_ad(!dfield_is_ext(new_val) ==
!rec_offs_nth_extern(offsets, i));
rec_set_nth_field(rec, offsets, upd_field->field_no, rec_set_nth_field(rec, offsets, upd_field->field_no,
dfield_get_data(new_val), dfield_get_data(new_val),
...@@ -694,34 +687,6 @@ row_upd_index_parse( ...@@ -694,34 +687,6 @@ row_upd_index_parse(
return(ptr); return(ptr);
} }
/*******************************************************************
Returns TRUE if ext_vec contains i. */
static
ibool
upd_ext_vec_contains(
/*=================*/
/* out: TRUE if i is in ext_vec */
const ulint* ext_vec, /* in: array of indexes or NULL */
ulint n_ext_vec, /* in: number of numbers in ext_vec */
ulint i) /* in: a number */
{
ulint j;
if (ext_vec == NULL) {
return(FALSE);
}
for (j = 0; j < n_ext_vec; j++) {
if (ext_vec[j] == i) {
return(TRUE);
}
}
return(FALSE);
}
/******************************************************************* /*******************************************************************
Builds an update vector from those fields which in a secondary index entry Builds an update vector from those fields which in a secondary index entry
differ from a record that has the equal ordering fields. NOTE: we compare differ from a record that has the equal ordering fields. NOTE: we compare
...@@ -783,8 +748,6 @@ row_upd_build_sec_rec_difference_binary( ...@@ -783,8 +748,6 @@ row_upd_build_sec_rec_difference_binary(
upd_field_set_field_no(upd_field, i, index, trx); upd_field_set_field_no(upd_field, i, index, trx);
upd_field->extern_storage = FALSE;
n_diff++; n_diff++;
} }
} }
...@@ -806,9 +769,6 @@ row_upd_build_difference_binary( ...@@ -806,9 +769,6 @@ row_upd_build_difference_binary(
fields, excluding roll ptr and trx id */ fields, excluding roll ptr and trx id */
dict_index_t* index, /* in: clustered index */ dict_index_t* index, /* in: clustered index */
const dtuple_t* entry, /* in: entry to insert */ const dtuple_t* entry, /* in: entry to insert */
const ulint* ext_vec,/* in: array containing field numbers of
externally stored fields in entry, or NULL */
ulint n_ext_vec,/* in: number of fields in ext_vec */
const rec_t* rec, /* in: clustered index record */ const rec_t* rec, /* in: clustered index record */
trx_t* trx, /* in: transaction */ trx_t* trx, /* in: transaction */
mem_heap_t* heap) /* in: memory heap from which allocated */ mem_heap_t* heap) /* in: memory heap from which allocated */
...@@ -821,7 +781,6 @@ row_upd_build_difference_binary( ...@@ -821,7 +781,6 @@ row_upd_build_difference_binary(
ulint n_diff; ulint n_diff;
ulint roll_ptr_pos; ulint roll_ptr_pos;
ulint trx_id_pos; ulint trx_id_pos;
ibool extern_bit;
ulint i; ulint i;
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint offsets_[REC_OFFS_NORMAL_SIZE];
const ulint* offsets; const ulint* offsets;
...@@ -854,10 +813,8 @@ row_upd_build_difference_binary( ...@@ -854,10 +813,8 @@ row_upd_build_difference_binary(
goto skip_compare; goto skip_compare;
} }
extern_bit = upd_ext_vec_contains(ext_vec, n_ext_vec, i); if (UNIV_UNLIKELY(!dfield_is_ext(dfield)
!= !rec_offs_nth_extern(offsets, i))
if (UNIV_UNLIKELY(extern_bit
== (ibool)!rec_offs_nth_extern(offsets, i))
|| !dfield_data_is_binary_equal(dfield, len, data)) { || !dfield_data_is_binary_equal(dfield, len, data)) {
upd_field = upd_get_nth_field(update, n_diff); upd_field = upd_get_nth_field(update, n_diff);
...@@ -866,8 +823,6 @@ row_upd_build_difference_binary( ...@@ -866,8 +823,6 @@ row_upd_build_difference_binary(
upd_field_set_field_no(upd_field, i, index, trx); upd_field_set_field_no(upd_field, i, index, trx);
upd_field->extern_storage = extern_bit;
n_diff++; n_diff++;
} }
skip_compare: skip_compare:
...@@ -903,7 +858,6 @@ row_upd_index_replace_new_col_vals_index_pos( ...@@ -903,7 +858,6 @@ row_upd_index_replace_new_col_vals_index_pos(
dict_field_t* field; dict_field_t* field;
upd_field_t* upd_field; upd_field_t* upd_field;
dfield_t* dfield; dfield_t* dfield;
dfield_t* new_val;
ulint j; ulint j;
ulint i; ulint i;
ulint n_fields; ulint n_fields;
...@@ -930,19 +884,19 @@ row_upd_index_replace_new_col_vals_index_pos( ...@@ -930,19 +884,19 @@ row_upd_index_replace_new_col_vals_index_pos(
dfield = dtuple_get_nth_field(entry, j); dfield = dtuple_get_nth_field(entry, j);
new_val = &(upd_field->new_val); dfield_copy_data(dfield, &upd_field->new_val);
if (dfield_is_null(dfield)) {
continue;
}
dfield_set_data(dfield, new_val->data, if (heap) {
new_val->len); dfield->data = mem_heap_dup(
if (heap && new_val->len != UNIV_SQL_NULL) { heap,
dfield->data = mem_heap_alloc( dfield->data, dfield->len);
heap, new_val->len);
ut_memcpy(dfield->data, new_val->data,
new_val->len);
} }
if (field->prefix_len > 0 if (field->prefix_len > 0) {
&& new_val->len != UNIV_SQL_NULL) {
const dict_col_t* col const dict_col_t* col
= dict_field_get_col(field); = dict_field_get_col(field);
...@@ -953,8 +907,8 @@ row_upd_index_replace_new_col_vals_index_pos( ...@@ -953,8 +907,8 @@ row_upd_index_replace_new_col_vals_index_pos(
col->mbminlen, col->mbminlen,
col->mbmaxlen, col->mbmaxlen,
field->prefix_len, field->prefix_len,
new_val->len, dfield->len,
new_val->data); dfield->data);
} }
} }
} }
...@@ -980,7 +934,6 @@ row_upd_index_replace_new_col_vals( ...@@ -980,7 +934,6 @@ row_upd_index_replace_new_col_vals(
{ {
upd_field_t* upd_field; upd_field_t* upd_field;
dfield_t* dfield; dfield_t* dfield;
dfield_t* new_val;
ulint j; ulint j;
ulint i; ulint i;
dict_index_t* clust_index; dict_index_t* clust_index;
...@@ -1006,19 +959,19 @@ row_upd_index_replace_new_col_vals( ...@@ -1006,19 +959,19 @@ row_upd_index_replace_new_col_vals(
dfield = dtuple_get_nth_field(entry, j); dfield = dtuple_get_nth_field(entry, j);
new_val = &(upd_field->new_val); dfield_copy_data(dfield, &upd_field->new_val);
dfield_set_data(dfield, new_val->data, if (dfield_is_null(dfield)) {
new_val->len); continue;
if (heap && new_val->len != UNIV_SQL_NULL) {
dfield->data = mem_heap_alloc(
heap, new_val->len);
ut_memcpy(dfield->data, new_val->data,
new_val->len);
} }
if (field->prefix_len > 0 if (heap) {
&& new_val->len != UNIV_SQL_NULL) { dfield->data = mem_heap_dup(
heap,
dfield->data, dfield->len);
}
if (field->prefix_len > 0) {
const dict_col_t* col const dict_col_t* col
= dict_field_get_col(field); = dict_field_get_col(field);
...@@ -1029,8 +982,8 @@ row_upd_index_replace_new_col_vals( ...@@ -1029,8 +982,8 @@ row_upd_index_replace_new_col_vals(
col->mbminlen, col->mbminlen,
col->mbmaxlen, col->mbmaxlen,
field->prefix_len, field->prefix_len,
new_val->len, dfield->len,
new_val->data); dfield->data);
} }
} }
} }
...@@ -1213,6 +1166,9 @@ row_upd_copy_columns( ...@@ -1213,6 +1166,9 @@ row_upd_copy_columns(
data = rec_get_nth_field(rec, offsets, data = rec_get_nth_field(rec, offsets,
column->field_nos[SYM_CLUST_FIELD_NO], column->field_nos[SYM_CLUST_FIELD_NO],
&len); &len);
if (len == UNIV_SQL_NULL) {
len = UNIV_SQL_NULL;
}
eval_node_copy_and_alloc_val(column, data, len); eval_node_copy_and_alloc_val(column, data, len);
column = UT_LIST_GET_NEXT(col_var_list, column); column = UT_LIST_GET_NEXT(col_var_list, column);
...@@ -1276,14 +1232,11 @@ row_upd_store_row( ...@@ -1276,14 +1232,11 @@ row_upd_store_row(
node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets, node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
&node->ext, node->heap); &node->ext, node->heap);
if (UNIV_LIKELY_NULL(node->ext)) { if (UNIV_LIKELY_NULL(node->ext)) {
node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint) node->n_ext = btr_push_update_extern_fields(
* 2 * node->ext->n_ext); node->row, offsets,
node->n_ext_vec = btr_push_update_extern_fields(
node->ext_vec, offsets,
node->is_delete ? NULL : node->update); node->is_delete ? NULL : node->update);
} else { } else {
node->ext_vec = NULL; node->n_ext = 0;
node->n_ext_vec = 0;
} }
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
...@@ -1381,7 +1334,7 @@ row_upd_sec_index_entry( ...@@ -1381,7 +1334,7 @@ row_upd_sec_index_entry(
row_upd_index_replace_new_col_vals(entry, index, node->update, NULL); row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
/* Insert new index entry */ /* Insert new index entry */
err = row_ins_index_entry(index, entry, NULL, 0, thr); err = row_ins_index_entry(index, entry, 0, FALSE, thr);
func_exit: func_exit:
mem_heap_free(heap); mem_heap_free(heap);
...@@ -1504,21 +1457,20 @@ row_upd_clust_rec_by_insert( ...@@ -1504,21 +1457,20 @@ row_upd_clust_rec_by_insert(
row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id); row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
/* If we return from a lock wait, for example, we may have if (node->n_ext) {
extern fields marked as not-owned in entry (marked in the /* If we return from a lock wait, for example, we may have
if-branch above). We must unmark them. */ extern fields marked as not-owned in entry (marked in the
if-branch above). We must unmark them. */
btr_cur_unmark_dtuple_extern_fields(entry, node->ext_vec, btr_cur_unmark_dtuple_extern_fields(entry);
node->n_ext_vec);
/* We must mark non-updated extern fields in entry as inherited,
so that a possible rollback will not free them */
btr_cur_mark_dtuple_inherited_extern(entry, node->ext_vec, /* We must mark non-updated extern fields in entry as
node->n_ext_vec, inherited, so that a possible rollback will not free them. */
node->update);
btr_cur_mark_dtuple_inherited_extern(entry, node->update);
}
err = row_ins_index_entry(index, entry, node->ext_vec, err = row_ins_index_entry(index, entry, node->n_ext, TRUE, thr);
node->n_ext_vec, thr);
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
...@@ -1916,8 +1868,7 @@ row_upd( ...@@ -1916,8 +1868,7 @@ row_upd(
if (node->row != NULL) { if (node->row != NULL) {
node->row = NULL; node->row = NULL;
node->ext = NULL; node->ext = NULL;
node->ext_vec = NULL; node->n_ext = 0;
node->n_ext_vec = 0;
mem_heap_empty(node->heap); mem_heap_empty(node->heap);
} }
......
...@@ -1074,12 +1074,12 @@ trx_undo_update_rec_get_update( ...@@ -1074,12 +1074,12 @@ trx_undo_update_rec_get_update(
if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) { if (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD) {
upd_field->extern_storage = TRUE;
len -= UNIV_EXTERN_STORAGE_FIELD; len -= UNIV_EXTERN_STORAGE_FIELD;
dfield_set_data(&upd_field->new_val, field, len);
dfield_set_ext(&upd_field->new_val);
} else {
dfield_set_data(&upd_field->new_val, field, len);
} }
dfield_set_data(&(upd_field->new_val), field, len);
} }
*upd = update; *upd = update;
...@@ -1800,29 +1800,24 @@ trx_undo_prev_version_build( ...@@ -1800,29 +1800,24 @@ trx_undo_prev_version_build(
} }
if (row_upd_changes_field_size_or_external(index, offsets, update)) { if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext;
ulint n_ext; ulint n_ext;
/* We have to set the appropriate extern storage bits in the /* We have to set the appropriate extern storage bits in the
old version of the record: the extern bits in rec for those old version of the record: the extern bits in rec for those
fields that update does NOT update, as well as the the bits for fields that update does NOT update, as well as the the bits for
those fields that update updates to become externally stored those fields that update updates to become externally stored
fields. Store the info to ext: */ fields. Store the info: */
ext = mem_alloc(sizeof(ulint) * 2
* rec_offs_n_fields(offsets));
n_ext = btr_push_update_extern_fields(ext, offsets, update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap); heap);
n_ext = btr_push_update_extern_fields(entry, offsets, update);
row_upd_index_replace_new_col_vals(entry, index, update, heap); row_upd_index_replace_new_col_vals(entry, index, update, heap);
buf = mem_heap_alloc(heap, rec_get_converted_size( buf = mem_heap_alloc(heap, rec_get_converted_size(index, entry,
index, entry, ext, n_ext)); n_ext));
*old_vers = rec_convert_dtuple_to_rec(buf, index, entry,
ext, n_ext);
mem_free(ext); *old_vers = rec_convert_dtuple_to_rec(buf, index,
entry, n_ext);
} else { } else {
buf = mem_heap_alloc(heap, rec_offs_size(offsets)); buf = mem_heap_alloc(heap, rec_offs_size(offsets));
*old_vers = rec_copy(buf, rec, offsets); *old_vers = rec_copy(buf, rec, offsets);
......
...@@ -16,7 +16,6 @@ Created 5/11/1994 Heikki Tuuri ...@@ -16,7 +16,6 @@ Created 5/11/1994 Heikki Tuuri
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "ut0sort.h"
#include "trx0trx.h" #include "trx0trx.h"
ibool ut_always_false = FALSE; ibool ut_always_false = FALSE;
...@@ -369,17 +368,6 @@ ut_print_buf( ...@@ -369,17 +368,6 @@ ut_print_buf(
putc(';', file); putc(';', file);
} }
/****************************************************************
Sort function for ulint arrays. */
void
ut_ulint_sort(ulint* arr, ulint* aux_arr, ulint low, ulint high)
/*============================================================*/
{
UT_SORT_FUNCTION_BODY(ut_ulint_sort, arr, aux_arr, low, high,
ut_ulint_cmp);
}
/***************************************************************** /*****************************************************************
Calculates fast the number rounded up to the nearest power of 2. */ Calculates fast the number rounded up to the nearest power of 2. */
......
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