Commit d02aa878 authored by Marko Mäkelä's avatar Marko Mäkelä

On second ADD COLUMN, update the 'default row' record

btr_cur_optimistic_update(), btr_cur_pessimistic_update(): Do not trim
the 'default row' record.

innobase_instant_add_try(): Compute and apply the update vector for
the 'default row'.

FIXME: The rollback of the 'default row' operations (that is, the
ROLLBACK of the ALTER TABLE…ADD COLUMN operation) has not been tested
and is unlikely to work. We need a test that flushes the redo log
and kills the server at the end of innobase_instant_add_try(), before
the ALTER TABLE transaction is committed.
parent e0d348a5
......@@ -4040,7 +4040,9 @@ btr_cur_optimistic_update(
|| trx_is_recv(thr_get_trx(thr)));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
if (!row_upd_changes_field_size_or_external(index, *offsets, update)) {
if (UNIV_LIKELY(update->info_bits != REC_INFO_DEFAULT_ROW)
&& !row_upd_changes_field_size_or_external(index, *offsets,
update)) {
/* The simplest and the most common case: the update does not
change the size of any field and none of the updated fields is
......@@ -4094,7 +4096,10 @@ btr_cur_optimistic_update(
Thus the following call is safe. */
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
*heap);
if (index->is_instant()) new_entry->trim(*index);
if (index->is_instant()
&& UNIV_LIKELY(update->info_bits != REC_INFO_DEFAULT_ROW)) {
new_entry->trim(*index);
}
old_rec_size = rec_offs_size(*offsets);
new_rec_size = rec_get_converted_size(index, new_entry, 0);
......@@ -4420,7 +4425,10 @@ btr_cur_pessimistic_update(
itself. Thus the following call is safe. */
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
entry_heap);
if (index->is_instant()) new_entry->trim(*index);
if (index->is_instant()
&& UNIV_LIKELY(update->info_bits != REC_INFO_DEFAULT_ROW)) {
new_entry->trim(*index);
}
/* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */
......
......@@ -45,6 +45,7 @@ Smart ALTER TABLE
#include "row0merge.h"
#include "row0ins.h"
#include "row0row.h"
#include "row0upd.h"
#include "trx0trx.h"
#include "trx0roll.h"
#include "handler0alter.h"
......@@ -4398,26 +4399,68 @@ innobase_add_instant_try(
mtr_t mtr;
mtr.start();
mtr.set_named_space(index->space);
btr_cur_t cursor;
btr_cur_open_at_index_side(true, index, BTR_MODIFY_TREE, &cursor, 0,
&mtr);
buf_block_t* block = btr_cur_get_block(&cursor);
rec_t* rec = btr_cur_get_rec(&cursor);
ut_ad(page_rec_is_infimum(rec));
rec = page_rec_get_next(rec);
btr_pcur_t pcur;
btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true,
0, &mtr);
ut_ad(btr_pcur_is_before_first_on_page(&pcur));
btr_pcur_move_to_next_on_page(&pcur);
buf_block_t* block = btr_pcur_get_block(&pcur);
ut_ad(page_is_leaf(block->frame));
ut_ad(!buf_block_get_page_zip(block));
const rec_t* rec = btr_pcur_get_rec(&pcur);
if (rec_is_default_row(rec, index)) {
if (rec_is_default_row(rec, old_index)) {
ut_ad(page_rec_is_user_rec(rec));
ut_ad(user_table->is_instant());
ut_ad(old_index->is_instant());
if (page_rec_is_last(rec, block->frame)) {
goto empty_table;
}
/* FIXME: calculate and apply an update vector with
the instantly added columns (no changes to key columns!) */
/* Extend the record with the instantly added columns. */
const unsigned n = index->n_fields - old_index->n_fields;
/* Reserve room for DB_TRX_ID,DB_ROLL_PTR and any
non-updated off-page columns in case they are moved off
page as a result of the update. */
upd_t* update = upd_create(index->n_fields, ctx->heap);
update->n_fields = n + 2;
update->info_bits = REC_INFO_DEFAULT_ROW;
/* Add DB_TRX_ID, DB_ROLL_PTR */
for (unsigned i = 0; i < 2; i++) {
upd_field_t* uf = upd_get_nth_field(update, i);
uf->field_no = index->n_uniq + i;
uf->new_val = entry->fields[index->n_uniq + i];
}
/* Add the default values for instantly added columns */
for (unsigned i = 0; i < n; i++) {
upd_field_t* uf = upd_get_nth_field(update, i + 2);
unsigned f = i + old_index->n_fields;
uf->field_no = f;
uf->new_val = entry->fields[f];
}
ulint* offsets = NULL;
mem_heap_t* offsets_heap = NULL;
big_rec_t* big_rec;
dberr_t error = btr_cur_pessimistic_update(
BTR_NO_LOCKING_FLAG, btr_pcur_get_btr_cur(&pcur),
&offsets, &offsets_heap, ctx->heap,
&big_rec, update, UPD_NODE_NO_ORD_CHANGE,
pars_complete_graph_for_exec(NULL, trx, ctx->heap,
NULL), trx->id, &mtr);
if (big_rec) {
if (error == DB_SUCCESS) {
error = btr_store_big_rec_extern_fields(
&pcur, update, offsets, big_rec, &mtr,
BTR_STORE_UPDATE);
}
dtuple_big_rec_free(big_rec);
}
if (offsets_heap) {
mem_heap_free(offsets_heap);
}
btr_pcur_close(&pcur);
mtr.commit();
return false;
return error != DB_SUCCESS;
} else if (page_rec_is_supremum(rec)) {
ut_ad(!user_table->is_instant());
empty_table:
......
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