summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0upd.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0upd.cc')
-rw-r--r--storage/innobase/row/row0upd.cc431
1 files changed, 65 insertions, 366 deletions
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index b594f8a8020..09f49edfc71 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -460,36 +460,6 @@ upd_node_create(
return(node);
}
-/*********************************************************************//**
-Updates the trx id and roll ptr field in a clustered index record in database
-recovery. */
-void
-row_upd_rec_sys_fields_in_recovery(
-/*===============================*/
- rec_t* rec, /*!< in/out: record */
- page_zip_des_t* page_zip,/*!< in/out: compressed page, or NULL */
- const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */
- ulint pos, /*!< in: TRX_ID position in rec */
- trx_id_t trx_id, /*!< in: transaction id */
- roll_ptr_t roll_ptr)/*!< in: roll ptr of the undo log record */
-{
- ut_ad(rec_offs_validate(rec, NULL, offsets));
-
- if (page_zip) {
- page_zip_write_trx_id_and_roll_ptr(
- page_zip, rec, offsets, pos, trx_id, roll_ptr);
- } else {
- byte* field;
- ulint len;
-
- field = rec_get_nth_field(rec, offsets, pos, &len);
- ut_ad(len == DATA_TRX_ID_LEN);
- compile_time_assert(DATA_TRX_ID + 1 == DATA_ROLL_PTR);
- trx_write_trx_id(field, trx_id);
- trx_write_roll_ptr(field + DATA_TRX_ID_LEN, roll_ptr);
- }
-}
-
/***********************************************************//**
Returns TRUE if row update changes size of some field in index or if some
field to be updated is stored externally in rec or update.
@@ -531,11 +501,6 @@ row_upd_changes_field_size_or_external(
ut_ad(new_len != UNIV_SQL_DEFAULT);
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
- manually immediately after we commit this to 4.1. */
-
new_len = dict_col_get_sql_null_size(
dict_index_get_nth_col(index,
upd_field->field_no),
@@ -613,277 +578,6 @@ row_upd_changes_disowned_external(
return(false);
}
-/***********************************************************//**
-Replaces the new column values stored in the update vector to the
-record given. No field size changes are allowed. This function is
-usually invoked on a clustered index. The only use case for a
-secondary index is row_ins_sec_index_entry_by_modify() or its
-counterpart in ibuf_insert_to_index_page(). */
-void
-row_upd_rec_in_place(
-/*=================*/
- rec_t* rec, /*!< in/out: record where replaced */
- dict_index_t* index, /*!< in: the index the record belongs to */
- const rec_offs* offsets,/*!< in: array returned by rec_get_offsets() */
- const upd_t* update, /*!< in: update vector */
- page_zip_des_t* page_zip)/*!< in: compressed page with enough space
- available, or NULL */
-{
- const upd_field_t* upd_field;
- const dfield_t* new_val;
- ulint n_fields;
- ulint i;
-
- ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(!index->table->skip_alter_undo);
-
- if (rec_offs_comp(offsets)) {
-#ifdef UNIV_DEBUG
- switch (rec_get_status(rec)) {
- case REC_STATUS_ORDINARY:
- break;
- case REC_STATUS_INSTANT:
- ut_ad(index->is_instant());
- break;
- case REC_STATUS_NODE_PTR:
- if (index->is_dummy
- && fil_page_get_type(page_align(rec))
- == FIL_PAGE_RTREE) {
- /* The function rtr_update_mbr_field_in_place()
- is generating MLOG_COMP_REC_UPDATE_IN_PLACE
- and MLOG_REC_UPDATE_IN_PLACE records for
- node pointer pages. */
- break;
- }
- /* fall through */
- case REC_STATUS_INFIMUM:
- case REC_STATUS_SUPREMUM:
- ut_ad(!"wrong record status in update");
- }
-#endif /* UNIV_DEBUG */
-
- rec_set_info_bits_new(rec, update->info_bits);
- } else {
- rec_set_info_bits_old(rec, update->info_bits);
- }
-
- n_fields = upd_get_n_fields(update);
-
- for (i = 0; i < n_fields; i++) {
- upd_field = upd_get_nth_field(update, i);
-
- /* No need to update virtual columns for non-virtual index */
- if (upd_fld_is_virtual_col(upd_field)
- && !dict_index_has_virtual(index)) {
- continue;
- }
-
- new_val = &(upd_field->new_val);
- ut_ad(!dfield_is_ext(new_val) ==
- !rec_offs_nth_extern(offsets, upd_field->field_no));
-
- rec_set_nth_field(rec, offsets, upd_field->field_no,
- dfield_get_data(new_val),
- dfield_get_len(new_val));
- }
-
- if (page_zip) {
- page_zip_write_rec(page_zip, rec, index, offsets, 0);
- }
-}
-
-/*********************************************************************//**
-Parses the log data of system field values.
-@return log data end or NULL */
-byte*
-row_upd_parse_sys_vals(
-/*===================*/
- const byte* ptr, /*!< in: buffer */
- const byte* end_ptr,/*!< in: buffer end */
- ulint* pos, /*!< out: TRX_ID position in record */
- trx_id_t* trx_id, /*!< out: trx id */
- roll_ptr_t* roll_ptr)/*!< out: roll ptr */
-{
- *pos = mach_parse_compressed(&ptr, end_ptr);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- if (end_ptr < ptr + DATA_ROLL_PTR_LEN) {
-
- return(NULL);
- }
-
- *roll_ptr = trx_read_roll_ptr(ptr);
- ptr += DATA_ROLL_PTR_LEN;
-
- *trx_id = mach_u64_parse_compressed(&ptr, end_ptr);
-
- return(const_cast<byte*>(ptr));
-}
-
-/***********************************************************//**
-Writes to the redo log the new values of the fields occurring in the index. */
-void
-row_upd_index_write_log(
-/*====================*/
- const upd_t* update, /*!< in: update vector */
- byte* log_ptr,/*!< in: pointer to mlog buffer: must
- contain at least MLOG_BUF_MARGIN bytes
- of free space; the buffer is closed
- within this function */
- mtr_t* mtr) /*!< in: mtr into whose log to write */
-{
- const upd_field_t* upd_field;
- const dfield_t* new_val;
- ulint len;
- ulint n_fields;
- byte* buf_end;
- ulint i;
-
- n_fields = upd_get_n_fields(update);
-
- buf_end = log_ptr + MLOG_BUF_MARGIN;
-
- mach_write_to_1(log_ptr, update->info_bits);
- log_ptr++;
- log_ptr += mach_write_compressed(log_ptr, n_fields);
-
- for (i = 0; i < n_fields; i++) {
- compile_time_assert(MLOG_BUF_MARGIN > 30);
-
- if (log_ptr + 30 > buf_end) {
- mlog_close(mtr, log_ptr);
-
- log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
- buf_end = log_ptr + MLOG_BUF_MARGIN;
- }
-
- upd_field = upd_get_nth_field(update, i);
-
- new_val = &(upd_field->new_val);
-
- len = dfield_get_len(new_val);
-
- /* If this is a virtual column, mark it using special
- field_no */
- ulint field_no = upd_fld_is_virtual_col(upd_field)
- ? REC_MAX_N_FIELDS + unsigned(upd_field->field_no)
- : unsigned(upd_field->field_no);
-
- log_ptr += mach_write_compressed(log_ptr, field_no);
- log_ptr += mach_write_compressed(log_ptr, len);
-
- if (len != UNIV_SQL_NULL) {
- if (log_ptr + len < buf_end) {
- memcpy(log_ptr, dfield_get_data(new_val), len);
-
- log_ptr += len;
- } else {
- mlog_close(mtr, log_ptr);
-
- mlog_catenate_string(
- mtr,
- static_cast<const byte*>(
- dfield_get_data(new_val)),
- len);
-
- log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN);
- buf_end = log_ptr + MLOG_BUF_MARGIN;
- }
- }
- }
-
- mlog_close(mtr, log_ptr);
-}
-
-/*********************************************************************//**
-Parses the log data written by row_upd_index_write_log.
-@return log data end or NULL */
-byte*
-row_upd_index_parse(
-/*================*/
- const byte* ptr, /*!< in: buffer */
- const byte* end_ptr,/*!< in: buffer end */
- mem_heap_t* heap, /*!< in: memory heap where update vector is
- built */
- upd_t** update_out)/*!< out: update vector */
-{
- upd_t* update;
- upd_field_t* upd_field;
- dfield_t* new_val;
- ulint len;
- ulint n_fields;
- ulint info_bits;
- ulint i;
-
- if (end_ptr < ptr + 1) {
-
- return(NULL);
- }
-
- info_bits = mach_read_from_1(ptr);
- ptr++;
- n_fields = mach_parse_compressed(&ptr, end_ptr);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- update = upd_create(n_fields, heap);
- update->info_bits = info_bits;
-
- for (i = 0; i < n_fields; i++) {
- ulint field_no;
- upd_field = upd_get_nth_field(update, i);
- new_val = &(upd_field->new_val);
-
- field_no = mach_parse_compressed(&ptr, end_ptr);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- /* Check if this is a virtual column, mark the prtype
- if that is the case */
- if (field_no >= REC_MAX_N_FIELDS) {
- new_val->type.prtype |= DATA_VIRTUAL;
- field_no -= REC_MAX_N_FIELDS;
- }
-
- upd_field->field_no = field_no;
-
- len = mach_parse_compressed(&ptr, end_ptr);
-
- if (ptr == NULL) {
-
- return(NULL);
- }
-
- if (len != UNIV_SQL_NULL) {
-
- if (end_ptr < ptr + len) {
-
- return(NULL);
- }
-
- dfield_set_data(new_val,
- mem_heap_dup(heap, ptr, len), len);
- ptr += len;
- } else {
- dfield_set_null(new_val);
- }
- }
-
- *update_out = update;
-
- return(const_cast<byte*>(ptr));
-}
-
/***************************************************************//**
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
@@ -904,7 +598,6 @@ row_upd_build_sec_rec_difference_binary(
ulint len;
upd_t* update;
ulint n_diff;
- ulint i;
/* This function is used only for a secondary index */
ut_a(!dict_index_is_clust(index));
@@ -918,7 +611,7 @@ row_upd_build_sec_rec_difference_binary(
n_diff = 0;
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
+ for (uint16_t i = 0; i < dtuple_get_n_fields(entry); i++) {
data = rec_get_nth_field(rec, offsets, i, &len);
@@ -1007,7 +700,7 @@ row_upd_build_difference_binary(
ut_ad(rec_offs_validate(rec, index, offsets));
}
- for (ulint i = 0; i < entry->n_fields; i++) {
+ for (uint16_t i = 0; i < entry->n_fields; i++) {
const byte* data = rec_get_nth_cfield(rec, index, offsets, i,
&len);
const dfield_t* dfield = dtuple_get_nth_field(entry, i);
@@ -1028,7 +721,8 @@ row_upd_build_difference_binary(
}
}
- for (ulint i = entry->n_fields; i < index->n_fields; i++) {
+ for (uint16_t i = static_cast<uint16_t>(entry->n_fields);
+ i < index->n_fields; i++) {
upd_field_t* uf = upd_get_nth_field(update, n_diff++);
const dict_col_t* col = dict_index_get_nth_col(index, i);
/* upd_create() zero-initialized uf */
@@ -1057,7 +751,7 @@ row_upd_build_difference_binary(
ib_vcol_row vc(NULL);
uchar *record = vc.record(thd, index, &mysql_table);
- for (ulint i = 0; i < n_v_fld; i++) {
+ for (uint16_t i = 0; i < n_v_fld; i++) {
const dict_v_col_t* col
= dict_table_get_nth_v_col(index->table, i);
@@ -1318,7 +1012,7 @@ row_upd_index_replace_new_col_vals_index_pos(
dtuple_set_info_bits(entry, update->info_bits);
- for (unsigned i = index->n_fields; i--; ) {
+ for (uint16_t i = index->n_fields; i--; ) {
const dict_field_t* field;
const dict_col_t* col;
const upd_field_t* uf;
@@ -1376,7 +1070,8 @@ row_upd_index_replace_new_col_vals(dtuple_t *entry, const dict_index_t &index,
uf= upd_get_field_by_field_no(update, vcol->v_pos, true);
}
else
- uf= upd_get_field_by_field_no(update, dict_col_get_clust_pos(col, &index),
+ uf= upd_get_field_by_field_no(update, static_cast<uint16_t>
+ (dict_col_get_clust_pos(col, &index)),
false);
if (!uf)
@@ -1489,15 +1184,12 @@ row_upd_replace_vcol(
ptr += 2;
while (ptr != end_ptr) {
- const byte* field;
- ulint field_no;
- ulint len;
- ulint orig_len;
- bool is_v;
+ const byte* field;
+ uint32_t field_no, len, orig_len;
field_no = mach_read_next_compressed(&ptr);
- is_v = (field_no >= REC_MAX_N_FIELDS);
+ const bool is_v = (field_no >= REC_MAX_N_FIELDS);
if (is_v) {
ptr = trx_undo_read_v_idx(
@@ -1509,7 +1201,7 @@ row_upd_replace_vcol(
ptr = trx_undo_rec_get_col_val(
ptr, &field, &len, &orig_len);
- if (field_no == ULINT_UNDEFINED) {
+ if (field_no == FIL_NULL) {
ut_ad(is_v);
continue;
}
@@ -1681,8 +1373,9 @@ row_upd_changes_ord_field_binary_func(
update, vcol->v_pos, true);
} else {
upd_field = upd_get_field_by_field_no(
- update,
- dict_col_get_clust_pos(col, clust_index),
+ update, static_cast<uint16_t>(
+ dict_col_get_clust_pos(
+ col, clust_index)),
false);
}
@@ -1845,7 +1538,7 @@ row_upd_changes_ord_field_binary_func(
/* The externally stored field
was not written yet. This
record should only be seen by
- recv_recovery_rollback_active(),
+ trx_rollback_recovered()
when the server had crashed before
storing the field. */
ut_ad(thr->graph->trx->is_recovered);
@@ -2425,11 +2118,17 @@ row_upd_sec_index_entry(
row_ins_sec_index_entry() below */
if (!rec_get_deleted_flag(
rec, dict_table_is_comp(index->table))) {
- err = btr_cur_del_mark_set_sec_rec(
- flags, btr_cur, TRUE, thr, &mtr);
+ err = lock_sec_rec_modify_check_and_lock(
+ flags,
+ btr_cur_get_block(btr_cur),
+ btr_cur_get_rec(btr_cur), index, thr, &mtr);
if (err != DB_SUCCESS) {
break;
}
+
+ btr_rec_set_deleted<true>(btr_cur_get_block(btr_cur),
+ btr_cur_get_rec(btr_cur),
+ &mtr);
#ifdef WITH_WSREP
if (!referenced && foreign
&& wsrep_must_process_fk(node, trx)
@@ -2594,14 +2293,13 @@ row_upd_clust_rec_by_insert_inherit_func(
const upd_t* update) /*!< in: update vector */
{
bool inherit = false;
- ulint i;
ut_ad(!rec == !offsets);
ut_ad(!rec == !index);
ut_ad(!rec || rec_offs_validate(rec, index, offsets));
ut_ad(!rec || rec_offs_any_extern(offsets));
- for (i = 0; i < dtuple_get_n_fields(entry); i++) {
+ for (uint16_t i = 0; i < dtuple_get_n_fields(entry); i++) {
dfield_t* dfield = dtuple_get_nth_field(entry, i);
byte* data;
ulint len;
@@ -2652,7 +2350,7 @@ row_upd_clust_rec_by_insert_inherit_func(
a lock wait and we already had disowned the BLOB. */
ut_a(rec == NULL
|| !(data[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
- data[BTR_EXTERN_LEN] &= ~BTR_EXTERN_OWNER_FLAG;
+ data[BTR_EXTERN_LEN] &= byte(~BTR_EXTERN_OWNER_FLAG);
data[BTR_EXTERN_LEN] |= BTR_EXTERN_INHERITED_FLAG;
/* The BTR_EXTERN_INHERITED_FLAG only matters in
rollback of a fresh insert. Purge will always free
@@ -2772,7 +2470,7 @@ row_upd_clust_rec_by_insert(
insert fails, then this disown will be undone
when the operation is rolled back. */
btr_cur_disown_inherited_fields(
- btr_cur_get_page_zip(btr_cur),
+ btr_cur_get_block(btr_cur),
rec, index, offsets, node->update,
mtr);
}
@@ -2889,7 +2587,7 @@ row_upd_clust_rec(
goto success;
}
- if (buf_LRU_buf_pool_running_out()) {
+ if (buf_pool.running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
}
@@ -3058,6 +2756,7 @@ row_upd_clust_step(
{
dict_index_t* index;
btr_pcur_t* pcur;
+ ibool success;
dberr_t err;
mtr_t mtr;
rec_t* rec;
@@ -3117,7 +2816,9 @@ row_upd_clust_step(
mode = BTR_MODIFY_LEAF;
}
- if (!btr_pcur_restore_position(mode, pcur, &mtr)) {
+ success = btr_pcur_restore_position(mode, pcur, &mtr);
+
+ if (!success) {
err = DB_RECORD_NOT_FOUND;
goto exit_func;
}
@@ -3131,17 +2832,21 @@ row_upd_clust_step(
ut_ad(!dict_index_is_online_ddl(index));
- dict_drop_index_tree(
- btr_pcur_get_rec(pcur), pcur, trx, &mtr);
+ dict_drop_index_tree(pcur, trx, &mtr);
mtr.commit();
mtr.start();
index->set_modified(mtr);
- if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr)) {
+ success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur,
+ &mtr);
+ if (!success) {
err = DB_ERROR;
- goto exit_func;
+
+ mtr.commit();
+
+ return(err);
}
}
@@ -3263,7 +2968,7 @@ row_upd(
ut_ad(!thr_get_trx(thr)->in_rollback);
DBUG_PRINT("row_upd", ("table: %s", node->table->name.m_name));
- DBUG_PRINT("row_upd", ("info bits in update vector: 0x" ULINTPFx,
+ DBUG_PRINT("row_upd", ("info bits in update vector: 0x%x",
node->update ? node->update->info_bits: 0));
DBUG_PRINT("row_upd", ("foreign_id: %s",
node->foreign ? node->foreign->id: "NULL"));
@@ -3470,48 +3175,42 @@ make_versioned_delete().
@param[in] vers_sys_idx table->row_start or table->row_end */
void upd_node_t::vers_update_fields(const trx_t *trx, ulint idx)
{
- ut_ad(in_mysql_interface); // otherwise needs to recalculate
- // node->cmpl_info
- ut_ad(idx == table->vers_start || idx == table->vers_end);
-
- dict_index_t* clust_index = dict_table_get_first_index(table);
- const dict_col_t *col= dict_table_get_nth_col(table, idx);
- ulint field_no= dict_col_get_clust_pos(col, clust_index);
- upd_field_t *ufield;
-
- for (ulint i= 0; i < update->n_fields; ++i)
- {
- if (update->fields[i].field_no == field_no)
- {
- ufield= &update->fields[i];
- goto skip_append;
- }
- }
-
- /* row_create_update_node_for_mysql() pre-allocated this much.
- At least one PK column always remains unchanged. */
- ut_ad(update->n_fields < ulint(table->n_cols + table->n_v_cols));
-
- update->n_fields++;
- ufield= upd_get_nth_field(update, update->n_fields - 1);
- upd_field_set_field_no(ufield, field_no, clust_index);
+ ut_ad(in_mysql_interface); // otherwise needs to recalculate node->cmpl_info
+ ut_ad(idx == table->vers_start || idx == table->vers_end);
+
+ dict_index_t *clust_index= dict_table_get_first_index(table);
+ const dict_col_t *col= dict_table_get_nth_col(table, idx);
+ ulint field_no= dict_col_get_clust_pos(col, clust_index);
+ upd_field_t *ufield;
+
+ for (ulint i= 0; i < update->n_fields; ++i)
+ {
+ if (update->fields[i].field_no == field_no)
+ {
+ ufield= &update->fields[i];
+ goto skip_append;
+ }
+ }
+
+ /* row_create_update_node_for_mysql() pre-allocated this much.
+ At least one PK column always remains unchanged. */
+ ut_ad(update->n_fields < ulint(table->n_cols + table->n_v_cols));
+
+ update->n_fields++;
+ ufield= upd_get_nth_field(update, update->n_fields - 1);
+ upd_field_set_field_no(ufield, static_cast<uint16_t>(field_no), clust_index);
skip_append:
char *where= reinterpret_cast<char *>(update->vers_sys_value);
if (col->vers_native())
- {
mach_write_to_8(where, trx->id);
- }
else
- {
thd_get_query_start_data(trx->mysql_thd, where);
- }
dfield_set_data(&ufield->new_val, update->vers_sys_value, col->len);
for (ulint col_no= 0; col_no < dict_table_get_n_v_cols(table); col_no++)
{
-
const dict_v_col_t *v_col= dict_table_get_nth_v_col(table, col_no);
if (!v_col->m_col.ord_part)
continue;