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