mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 23:04:20 +01:00
b707b2e3b1
within UNIV_DEBUG. The two remaining callers in non-debug builds, btr_search_guess_on_hash() and btr_search_validate(), were rewritten to call buf_page_hash_get(). To implement support for a resizeable buffer pool, the function buf_block_align() had been rewritten to perform a page hash lookup in the buffer pool. The caller was also made responsible for holding the buffer pool mutex. Because the page hash lookup is expensive and it has to be done while holding the buffer pool mutex, implement buf_block_align() by pointer arithmetics again, and make btr_search_guess_on_hash() call it. Note that this will have to be adjusted if the interface to the resizeable buffer pool is actually implemented. rb://83 approved by Heikki Tuuri, to address Issue #161. As a deviation from the approved patch, this patch also makes btr_search_validate() (invoked by CHECK TABLE) check that buf_pool->page_hash is consistent with buf_block_align().
163 lines
4.3 KiB
Text
163 lines
4.3 KiB
Text
/******************************************************
|
|
Update of a row
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
Created 12/27/1996 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#include "mtr0log.h"
|
|
#include "trx0trx.h"
|
|
#include "trx0undo.h"
|
|
#include "row0row.h"
|
|
#include "btr0sea.h"
|
|
#include "page0zip.h"
|
|
|
|
/*************************************************************************
|
|
Creates an update vector object. */
|
|
UNIV_INLINE
|
|
upd_t*
|
|
upd_create(
|
|
/*=======*/
|
|
/* out, own: update vector object */
|
|
ulint n, /* in: number of fields */
|
|
mem_heap_t* heap) /* in: heap from which memory allocated */
|
|
{
|
|
upd_t* update;
|
|
|
|
update = (upd_t*) mem_heap_alloc(heap, sizeof(upd_t));
|
|
|
|
update->info_bits = 0;
|
|
update->n_fields = n;
|
|
update->fields = (upd_field_t*)
|
|
mem_heap_alloc(heap, sizeof(upd_field_t) * n);
|
|
|
|
return(update);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Returns the number of fields in the update vector == number of columns
|
|
to be updated by an update vector. */
|
|
UNIV_INLINE
|
|
ulint
|
|
upd_get_n_fields(
|
|
/*=============*/
|
|
/* out: number of fields */
|
|
const upd_t* update) /* in: update vector */
|
|
{
|
|
ut_ad(update);
|
|
|
|
return(update->n_fields);
|
|
}
|
|
|
|
#ifdef UNIV_DEBUG
|
|
/*************************************************************************
|
|
Returns the nth field of an update vector. */
|
|
UNIV_INLINE
|
|
upd_field_t*
|
|
upd_get_nth_field(
|
|
/*==============*/
|
|
/* out: update vector field */
|
|
const upd_t* update, /* in: update vector */
|
|
ulint n) /* in: field position in update vector */
|
|
{
|
|
ut_ad(update);
|
|
ut_ad(n < update->n_fields);
|
|
|
|
return((upd_field_t*) update->fields + n);
|
|
}
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
/*************************************************************************
|
|
Sets an index field number to be updated by an update vector field. */
|
|
UNIV_INLINE
|
|
void
|
|
upd_field_set_field_no(
|
|
/*===================*/
|
|
upd_field_t* upd_field, /* in: update vector field */
|
|
ulint field_no, /* in: field number in a clustered
|
|
index */
|
|
dict_index_t* index, /* in: index */
|
|
trx_t* trx) /* in: transaction */
|
|
{
|
|
upd_field->field_no = field_no;
|
|
upd_field->orig_len = 0;
|
|
|
|
if (UNIV_UNLIKELY(field_no >= dict_index_get_n_fields(index))) {
|
|
fprintf(stderr,
|
|
"InnoDB: Error: trying to access field %lu in ",
|
|
(ulong) field_no);
|
|
dict_index_name_print(stderr, trx, index);
|
|
fprintf(stderr, "\n"
|
|
"InnoDB: but index only has %lu fields\n",
|
|
(ulong) dict_index_get_n_fields(index));
|
|
}
|
|
|
|
dict_col_copy_type(dict_index_get_nth_col(index, field_no),
|
|
dfield_get_type(&upd_field->new_val));
|
|
}
|
|
|
|
/*************************************************************************
|
|
Returns a field of an update vector by field_no. */
|
|
UNIV_INLINE
|
|
const upd_field_t*
|
|
upd_get_field_by_field_no(
|
|
/*======================*/
|
|
/* out: update vector field, or NULL */
|
|
const upd_t* update, /* in: update vector */
|
|
ulint no) /* in: field_no */
|
|
{
|
|
ulint i;
|
|
for (i = 0; i < upd_get_n_fields(update); i++) {
|
|
const upd_field_t* uf = upd_get_nth_field(update, i);
|
|
|
|
if (uf->field_no == no) {
|
|
|
|
return(uf);
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Updates the trx id and roll ptr field in a clustered index record when
|
|
a row is updated or marked deleted. */
|
|
UNIV_INLINE
|
|
void
|
|
row_upd_rec_sys_fields(
|
|
/*===================*/
|
|
rec_t* rec, /* in/out: record */
|
|
page_zip_des_t* page_zip,/* in/out: compressed page whose
|
|
uncompressed part will be updated, or NULL */
|
|
dict_index_t* index, /* in: clustered index */
|
|
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
|
|
trx_t* trx, /* in: transaction */
|
|
dulint roll_ptr)/* in: roll ptr of the undo log record */
|
|
{
|
|
ut_ad(dict_index_is_clust(index));
|
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
|
#ifdef UNIV_SYNC_DEBUG
|
|
if (!rw_lock_own(&btr_search_latch, RW_LOCK_EX)) {
|
|
ut_ad(!buf_block_align(rec)->is_hashed);
|
|
}
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
|
|
if (UNIV_LIKELY_NULL(page_zip)) {
|
|
ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
|
|
page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets,
|
|
pos, trx->id, roll_ptr);
|
|
} else {
|
|
ulint offset = index->trx_id_offset;
|
|
|
|
if (!offset) {
|
|
offset = row_get_trx_id_offset(rec, index, offsets);
|
|
}
|
|
|
|
#if DATA_TRX_ID + 1 != DATA_ROLL_PTR
|
|
# error "DATA_TRX_ID + 1 != DATA_ROLL_PTR"
|
|
#endif
|
|
trx_write_trx_id(rec + offset, trx->id);
|
|
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
|
|
}
|
|
}
|