summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0row.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0row.cc')
-rw-r--r--storage/innobase/row/row0row.cc199
1 files changed, 113 insertions, 86 deletions
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index 8c703b1e06c..be786f954fb 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -50,28 +50,26 @@ Created 4/20/1996 Heikki Tuuri
/*****************************************************************//**
When an insert or purge to a table is performed, this function builds
the entry to be inserted into or purged from an index on the table.
-@return index entry which should be inserted or purged, or NULL if the
-externally stored columns in the clustered index record are
-unavailable and ext != NULL */
+@return index entry which should be inserted or purged
+@retval NULL if the externally stored columns in the clustered index record
+are unavailable and ext != NULL, or row is missing some needed columns. */
UNIV_INTERN
dtuple_t*
-row_build_index_entry(
-/*==================*/
- const dtuple_t* row, /*!< in: row which should be
- inserted or purged */
- row_ext_t* ext, /*!< in: externally stored column prefixes,
- or NULL */
- dict_index_t* index, /*!< in: index on the table */
- mem_heap_t* heap) /*!< in: memory heap from which the memory for
- the index entry is allocated */
+row_build_index_entry_low(
+/*======================*/
+ const dtuple_t* row, /*!< in: row which should be
+ inserted or purged */
+ const row_ext_t* ext, /*!< in: externally stored column
+ prefixes, or NULL */
+ dict_index_t* index, /*!< in: index on the table */
+ mem_heap_t* heap) /*!< in: memory heap from which
+ the memory for the index entry
+ is allocated */
{
dtuple_t* entry;
ulint entry_len;
ulint i;
- ut_ad(row && index && heap);
- ut_ad(dtuple_check_typed(row));
-
entry_len = dict_index_get_n_fields(index);
entry = dtuple_create(heap, entry_len);
@@ -96,8 +94,19 @@ row_build_index_entry(
= dtuple_get_nth_field(entry, i);
const dfield_t* dfield2
= dtuple_get_nth_field(row, col_no);
- ulint len
- = dfield_get_len(dfield2);
+ ulint len;
+
+#if DATA_MISSING != 0
+# error "DATA_MISSING != 0"
+#endif
+ if (UNIV_UNLIKELY(dfield_get_type(dfield2)->mtype
+ == DATA_MISSING)) {
+ /* The field has not been initialized in the row.
+ This should be from trx_undo_rec_get_partial_row(). */
+ return(NULL);
+ }
+
+ len = dfield_get_len(dfield2);
dfield_copy(dfield, dfield2);
@@ -171,8 +180,6 @@ row_build_index_entry(
}
}
- ut_ad(dtuple_check_typed(entry));
-
return(entry);
}
@@ -211,21 +218,23 @@ row_build(
of an index, or NULL if
index->table should be
consulted instead */
+ const dtuple_t* add_cols,
+ /*!< in: default values of
+ added columns, or NULL */
+ const ulint* col_map,/*!< in: mapping of old column
+ numbers to new ones, or NULL */
row_ext_t** ext, /*!< out, own: cache of
externally stored column
prefixes, or NULL */
mem_heap_t* heap) /*!< in: memory heap from which
the memory needed is allocated */
{
+ const byte* copy;
dtuple_t* row;
- const dict_table_t* table;
- ulint n_fields;
ulint n_ext_cols;
ulint* ext_cols = NULL; /* remove warning */
ulint len;
- ulint row_len;
byte* buf;
- ulint i;
ulint j;
mem_heap_t* tmp_heap = NULL;
ulint offsets_[REC_OFFS_NORMAL_SIZE];
@@ -234,6 +243,7 @@ row_build(
ut_ad(index && rec && heap);
ut_ad(dict_index_is_clust(index));
ut_ad(!mutex_own(&trx_sys->mutex));
+ ut_ad(!col_map || col_table);
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_,
@@ -260,55 +270,84 @@ row_build(
buf = static_cast<byte*>(
mem_heap_alloc(heap, rec_offs_size(offsets)));
- rec = rec_copy(buf, rec, offsets);
- /* Avoid a debug assertion in rec_offs_validate(). */
- rec_offs_make_valid(rec, index, (ulint*) offsets);
+ copy = rec_copy(buf, rec, offsets);
+ } else {
+ copy = rec;
}
- table = index->table;
- row_len = dict_table_get_n_cols(table);
-
- row = dtuple_create(heap, row_len);
-
- dict_table_copy_types(row, table);
-
- dtuple_set_info_bits(row, rec_get_info_bits(
- rec, dict_table_is_comp(table)));
-
- n_fields = rec_offs_n_fields(offsets);
n_ext_cols = rec_offs_n_extern(offsets);
if (n_ext_cols) {
ext_cols = static_cast<ulint*>(
mem_heap_alloc(heap, n_ext_cols * sizeof *ext_cols));
}
- for (i = j = 0; i < n_fields; i++) {
- dict_field_t* ind_field
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(copy, index, const_cast<ulint*>(offsets));
+
+ if (!col_table) {
+ ut_ad(!col_map);
+ ut_ad(!add_cols);
+ col_table = index->table;
+ }
+
+ if (add_cols) {
+ ut_ad(col_map);
+ row = dtuple_copy(add_cols, heap);
+ /* dict_table_copy_types() would set the fields to NULL */
+ for (ulint i = 0; i < dict_table_get_n_cols(col_table); i++) {
+ dict_col_copy_type(
+ dict_table_get_nth_col(col_table, i),
+ dfield_get_type(dtuple_get_nth_field(row, i)));
+ }
+ } else {
+ row = dtuple_create(heap, dict_table_get_n_cols(col_table));
+ dict_table_copy_types(row, col_table);
+ }
+
+ dtuple_set_info_bits(row, rec_get_info_bits(
+ copy, rec_offs_comp(offsets)));
+
+ j = 0;
+
+ for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
+ const dict_field_t* ind_field
= dict_index_get_nth_field(index, i);
+
+ if (ind_field->prefix_len) {
+ /* Column prefixes can only occur in key
+ fields, which cannot be stored externally. For
+ a column prefix, there should also be the full
+ field in the clustered index tuple. The row
+ tuple comprises full fields, not prefixes. */
+ ut_ad(!rec_offs_nth_extern(offsets, i));
+ continue;
+ }
+
const dict_col_t* col
= dict_field_get_col(ind_field);
ulint col_no
= dict_col_get_no(col);
- dfield_t* dfield
- = dtuple_get_nth_field(row, col_no);
-
- if (ind_field->prefix_len == 0) {
- const byte* field = rec_get_nth_field(
- rec, offsets, i, &len);
+ if (col_map) {
+ col_no = col_map[col_no];
- dfield_set_data(dfield, field, len);
+ if (col_no == ULINT_UNDEFINED) {
+ /* dropped column */
+ continue;
+ }
}
+ dfield_t* dfield = dtuple_get_nth_field(row, col_no);
+
+ const byte* field = rec_get_nth_field(
+ copy, offsets, i, &len);
+
+ dfield_set_data(dfield, field, len);
+
if (rec_offs_nth_extern(offsets, i)) {
dfield_set_ext(dfield);
- if (UNIV_LIKELY_NULL(col_table)) {
- ut_a(col_no
- < dict_table_get_n_cols(col_table));
- col = dict_table_get_nth_col(
- col_table, col_no);
- }
+ col = dict_table_get_nth_col(col_table, col_no);
if (col->ord_part) {
/* We will have to fetch prefixes of
@@ -319,14 +358,20 @@ row_build(
}
}
+ rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
+
ut_ad(dtuple_check_typed(row));
if (!ext) {
/* REDUNDANT and COMPACT formats store a local
768-byte prefix of each externally stored
- column. No cache is needed. */
- ut_ad(dict_table_get_format(index->table)
- < UNIV_FORMAT_B);
+ column. No cache is needed.
+
+ During online table rebuild,
+ row_log_table_apply_delete_low()
+ may use a cache that was set up by
+ row_log_table_delete(). */
+
} else if (j) {
*ext = row_ext_create(j, ext_cols, index->table->flags, row,
heap);
@@ -402,28 +447,14 @@ row_rec_to_index_entry_low(
/*******************************************************************//**
Converts an index record to a typed data tuple. NOTE that externally
stored (often big) fields are NOT copied to heap.
-@return own: index entry built; see the NOTE below! */
+@return own: index entry built */
UNIV_INTERN
dtuple_t*
row_rec_to_index_entry(
/*===================*/
- ulint type, /*!< in: ROW_COPY_DATA, or
- ROW_COPY_POINTERS: the former
- copies also the data fields to
- heap as the latter only places
- pointers to data fields on the
- index page */
- const rec_t* rec, /*!< in: record in the index;
- NOTE: in the case
- ROW_COPY_POINTERS the data
- fields in the row will point
- directly into this record,
- therefore, the buffer page of
- this record must be at least
- s-latched and the latch held
- as long as the dtuple is used! */
+ const rec_t* rec, /*!< in: record in the index */
const dict_index_t* index, /*!< in: index */
- ulint* offsets,/*!< in/out: rec_get_offsets(rec) */
+ const ulint* offsets,/*!< in: rec_get_offsets(rec) */
ulint* n_ext, /*!< out: number of externally
stored columns */
mem_heap_t* heap) /*!< in: memory heap from which
@@ -431,25 +462,21 @@ row_rec_to_index_entry(
{
dtuple_t* entry;
byte* buf;
+ const rec_t* copy_rec;
ut_ad(rec && heap && index);
ut_ad(rec_offs_validate(rec, index, offsets));
- if (type == ROW_COPY_DATA) {
- /* Take a copy of rec to heap */
- buf = static_cast<byte*>(
- mem_heap_alloc(heap, rec_offs_size(offsets)));
+ /* Take a copy of rec to heap */
+ buf = static_cast<byte*>(
+ mem_heap_alloc(heap, rec_offs_size(offsets)));
- rec = rec_copy(buf, rec, offsets);
- /* Avoid a debug assertion in rec_offs_validate(). */
- rec_offs_make_valid(rec, index, offsets);
-#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
- } else {
- ut_a(!rec_offs_any_null_extern(rec, offsets));
-#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- }
+ copy_rec = rec_copy(buf, rec, offsets);
- entry = row_rec_to_index_entry_low(rec, index, offsets, n_ext, heap);
+ rec_offs_make_valid(copy_rec, index, const_cast<ulint*>(offsets));
+ entry = row_rec_to_index_entry_low(
+ copy_rec, index, offsets, n_ext, heap);
+ rec_offs_make_valid(rec, index, const_cast<ulint*>(offsets));
dtuple_set_info_bits(entry,
rec_get_info_bits(rec, rec_offs_comp(offsets)));