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( ...@@ -4040,7 +4040,9 @@ btr_cur_optimistic_update(
|| trx_is_recv(thr_get_trx(thr))); || trx_is_recv(thr_get_trx(thr)));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ #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 /* The simplest and the most common case: the update does not
change the size of any field and none of the updated fields is change the size of any field and none of the updated fields is
...@@ -4094,7 +4096,10 @@ btr_cur_optimistic_update( ...@@ -4094,7 +4096,10 @@ btr_cur_optimistic_update(
Thus the following call is safe. */ Thus the following call is safe. */
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
*heap); *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); old_rec_size = rec_offs_size(*offsets);
new_rec_size = rec_get_converted_size(index, new_entry, 0); new_rec_size = rec_get_converted_size(index, new_entry, 0);
...@@ -4420,7 +4425,10 @@ btr_cur_pessimistic_update( ...@@ -4420,7 +4425,10 @@ btr_cur_pessimistic_update(
itself. Thus the following call is safe. */ itself. Thus the following call is safe. */
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
entry_heap); 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 /* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */ record to be inserted: we have to remember which fields were such */
......
...@@ -45,6 +45,7 @@ Smart ALTER TABLE ...@@ -45,6 +45,7 @@ Smart ALTER TABLE
#include "row0merge.h" #include "row0merge.h"
#include "row0ins.h" #include "row0ins.h"
#include "row0row.h" #include "row0row.h"
#include "row0upd.h"
#include "trx0trx.h" #include "trx0trx.h"
#include "trx0roll.h" #include "trx0roll.h"
#include "handler0alter.h" #include "handler0alter.h"
...@@ -4398,26 +4399,68 @@ innobase_add_instant_try( ...@@ -4398,26 +4399,68 @@ innobase_add_instant_try(
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
mtr.set_named_space(index->space); mtr.set_named_space(index->space);
btr_cur_t cursor; btr_pcur_t pcur;
btr_cur_open_at_index_side(true, index, BTR_MODIFY_TREE, &cursor, 0, btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true,
&mtr); 0, &mtr);
buf_block_t* block = btr_cur_get_block(&cursor); ut_ad(btr_pcur_is_before_first_on_page(&pcur));
rec_t* rec = btr_cur_get_rec(&cursor); btr_pcur_move_to_next_on_page(&pcur);
ut_ad(page_rec_is_infimum(rec));
rec = page_rec_get_next(rec); buf_block_t* block = btr_pcur_get_block(&pcur);
ut_ad(page_is_leaf(block->frame)); ut_ad(page_is_leaf(block->frame));
ut_ad(!buf_block_get_page_zip(block)); 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(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)) { if (page_rec_is_last(rec, block->frame)) {
goto empty_table; goto empty_table;
} }
/* FIXME: calculate and apply an update vector with /* Extend the record with the instantly added columns. */
the instantly added columns (no changes to key 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(); mtr.commit();
return false; return error != DB_SUCCESS;
} else if (page_rec_is_supremum(rec)) { } else if (page_rec_is_supremum(rec)) {
ut_ad(!user_table->is_instant()); ut_ad(!user_table->is_instant());
empty_table: 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