upd_t* row_upd_build_sec_rec_difference_binary( /*====================================*/ /* out, own: update vector of differing fields */ dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: entry to insert */ rec_t* rec, /* in: secondary index record */ mem_heap_t* heap) /* in: memory heap from which allocated */ { upd_field_t* upd_field; dfield_t* dfield; byte* data; ulint len; upd_t* update; ulint n_diff; ulint i; /* This function is used only for a secondary index */ ut_ad(0 == (index->type & DICT_CLUSTERED)); update = upd_create(dtuple_get_n_fields(entry), heap); n_diff = 0; for (i = 0; i < dtuple_get_n_fields(entry); i++) { data = rec_get_nth_field(rec, i, &len); dfield = dtuple_get_nth_field(entry, i); ut_a(len == dfield_get_len(dfield)); /* NOTE: we compare the fields as binary strings! (No collation) */ if (!dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); dfield_copy(&(upd_field->new_val), dfield); upd_field_set_field_no(upd_field, i, index); upd_field->extern_storage = FALSE; n_diff++; } } update->n_fields = n_diff; return(update); }
/*******************************************************************//** Builds an update vector based on a remaining part of an undo log record. @return remaining part of the record, NULL if an error detected, which means that the record is corrupted */ UNIV_INTERN byte* trx_undo_update_rec_get_update( /*===========================*/ byte* ptr, /*!< in: remaining part in update undo log record, after reading the row reference NOTE that this copy of the undo log record must be preserved as long as the update vector is used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ ulint type, /*!< in: TRX_UNDO_UPD_EXIST_REC, TRX_UNDO_UPD_DEL_REC, or TRX_UNDO_DEL_MARK_REC; in the last case, only trx id and roll ptr fields are added to the update vector */ trx_id_t trx_id, /*!< in: transaction id from this undo record */ roll_ptr_t roll_ptr,/*!< in: roll pointer from this undo record */ ulint info_bits,/*!< in: info bits from this undo record */ trx_t* trx, /*!< in: transaction */ mem_heap_t* heap, /*!< in: memory heap from which the memory needed is allocated */ upd_t** upd) /*!< out, own: update vector */ { upd_field_t* upd_field; upd_t* update; ulint n_fields; byte* buf; ulint i; ut_a(dict_index_is_clust(index)); if (type != TRX_UNDO_DEL_MARK_REC) { ptr = trx_undo_update_rec_get_n_upd_fields(ptr, &n_fields); } else { n_fields = 0; } update = upd_create(n_fields + 2, heap); update->info_bits = info_bits; /* Store first trx id and roll ptr to update vector */ upd_field = upd_get_nth_field(update, n_fields); buf = mem_heap_alloc(heap, DATA_TRX_ID_LEN); trx_write_trx_id(buf, trx_id); upd_field_set_field_no(upd_field, dict_index_get_sys_col_pos(index, DATA_TRX_ID), index, trx); dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN); upd_field = upd_get_nth_field(update, n_fields + 1); buf = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN); trx_write_roll_ptr(buf, roll_ptr); upd_field_set_field_no( upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR), index, trx); dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN); /* Store then the updated ordinary columns to the update vector */ for (i = 0; i < n_fields; i++) { byte* field; ulint len; ulint field_no; ulint orig_len; ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); if (field_no >= dict_index_get_n_fields(index)) { fprintf(stderr, "InnoDB: Error: trying to access" " update undo rec field %lu in ", (ulong) field_no); dict_index_name_print(stderr, trx, index); fprintf(stderr, "\n" "InnoDB: but index has only %lu fields\n" "InnoDB: Submit a detailed bug report" " to http://bugs.mysql.com\n" "InnoDB: Run also CHECK TABLE ", (ulong) dict_index_get_n_fields(index)); ut_print_name(stderr, trx, TRUE, index->table_name); fprintf(stderr, "\n" "InnoDB: n_fields = %lu, i = %lu, ptr %p\n", (ulong) n_fields, (ulong) i, ptr); *upd = NULL; return(NULL); } upd_field = upd_get_nth_field(update, i); upd_field_set_field_no(upd_field, field_no, index, trx); ptr = trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len); upd_field->orig_len = orig_len; if (len == UNIV_SQL_NULL) { dfield_set_null(&upd_field->new_val); } else if (len < UNIV_EXTERN_STORAGE_FIELD) { dfield_set_data(&upd_field->new_val, field, len); } else { len -= UNIV_EXTERN_STORAGE_FIELD; dfield_set_data(&upd_field->new_val, field, len); dfield_set_ext(&upd_field->new_val); } } *upd = update; return(ptr); }
upd_t* row_upd_build_difference_binary( /*============================*/ /* out, own: update vector of differing fields, excluding roll ptr and trx id */ dict_index_t* index, /* in: clustered index */ dtuple_t* entry, /* in: 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 */ rec_t* rec, /* in: clustered index record */ mem_heap_t* heap) /* in: memory heap from which allocated */ { upd_field_t* upd_field; dfield_t* dfield; byte* data; ulint len; upd_t* update; ulint n_diff; ulint roll_ptr_pos; ulint trx_id_pos; ulint i; /* This function is used only for a clustered index */ ut_a(index->type & DICT_CLUSTERED); update = upd_create(dtuple_get_n_fields(entry), heap); n_diff = 0; roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR); trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID); for (i = 0; i < dtuple_get_n_fields(entry); i++) { data = rec_get_nth_field(rec, i, &len); dfield = dtuple_get_nth_field(entry, i); /* NOTE: we compare the fields as binary strings! (No collation) */ if (i == trx_id_pos || i == roll_ptr_pos) { goto skip_compare; } if (rec_get_nth_field_extern_bit(rec, i) != upd_ext_vec_contains(ext_vec, n_ext_vec, i) || !dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); dfield_copy(&(upd_field->new_val), dfield); upd_field_set_field_no(upd_field, i, index); if (upd_ext_vec_contains(ext_vec, n_ext_vec, i)) { upd_field->extern_storage = TRUE; } else { upd_field->extern_storage = FALSE; } n_diff++; } skip_compare: ; } update->n_fields = n_diff; return(update); }