summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0log.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2018-11-10 14:52:57 -0800
committerIgor Babaev <igor@askmonty.org>2018-11-10 14:52:57 -0800
commit5f46670bd09babbee75a24ac82eb4ade0706da66 (patch)
tree85e2759b75650b8165c3e01638e9458eb4d1274c /storage/innobase/row/row0log.cc
parent8d5a11122c32f4d9eb87536886c6e893377bdd07 (diff)
parent3ea7de9a78a1410a9b79362774247e9e44b201b3 (diff)
downloadmariadb-git-5f46670bd09babbee75a24ac82eb4ade0706da66.tar.gz
Merge branch '10.4' into 10.4-mdev16188
Diffstat (limited to 'storage/innobase/row/row0log.cc')
-rw-r--r--storage/innobase/row/row0log.cc120
1 files changed, 86 insertions, 34 deletions
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index db33910c6f2..07772fc5468 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -227,6 +227,8 @@ struct row_log_t {
table could be emptied, so that table->is_instant() no longer holds,
but all log records must be in the "instant" format. */
unsigned n_core_fields;
+ /** the default values of non-core fields when the operation started */
+ dict_col_t::def_t* non_core_fields;
bool allow_not_null; /*!< Whether the alter ignore is being
used or if the sql mode is non-strict mode;
if not, NULL values will not be converted to
@@ -243,6 +245,14 @@ struct row_log_t {
ut_ad(n_core_fields <= index->n_fields);
return n_core_fields != index->n_fields;
}
+
+ const byte* instant_field_value(ulint n, ulint* len) const
+ {
+ ut_ad(n >= n_core_fields);
+ const dict_col_t::def_t& d= non_core_fields[n - n_core_fields];
+ *len = d.len;
+ return static_cast<const byte*>(d.data);
+ }
};
/** Create the file or online log if it does not exist.
@@ -674,9 +684,9 @@ row_log_table_delete(
fields of the record. */
heap = mem_heap_create(
DATA_TRX_ID_LEN
- + DTUPLE_EST_ALLOC(unsigned(new_index->n_uniq) + 2));
- old_pk = tuple = dtuple_create(
- heap, unsigned(new_index->n_uniq) + 2);
+ + DTUPLE_EST_ALLOC(new_index->first_user_field()));
+ old_pk = tuple = dtuple_create(heap,
+ new_index->first_user_field());
dict_index_copy_types(tuple, new_index, tuple->n_fields);
dtuple_set_n_fields_cmp(tuple, new_index->n_uniq);
@@ -841,7 +851,7 @@ row_log_table_low_redundant(
const bool is_instant = index->online_log->is_instant(index);
rec_comp_status_t status = is_instant
- ? REC_STATUS_COLUMNS_ADDED : REC_STATUS_ORDINARY;
+ ? REC_STATUS_INSTANT : REC_STATUS_ORDINARY;
size = rec_get_converted_size_temp(
index, tuple->fields, tuple->n_fields, &extra_size, status);
@@ -895,7 +905,7 @@ row_log_table_low_redundant(
*b++ = static_cast<byte>(extra_size);
}
- if (status == REC_STATUS_COLUMNS_ADDED) {
+ if (status == REC_STATUS_INSTANT) {
ut_ad(is_instant);
if (n_fields <= index->online_log->n_core_fields) {
status = REC_STATUS_ORDINARY;
@@ -935,15 +945,16 @@ row_log_table_low(
ulint mrec_size;
ulint avail_size;
const dict_index_t* new_index;
+ row_log_t* log = index->online_log;
- new_index = dict_table_get_first_index(index->online_log->table);
+ new_index = dict_table_get_first_index(log->table);
ut_ad(dict_index_is_clust(index));
ut_ad(dict_index_is_clust(new_index));
ut_ad(!dict_index_is_online_ddl(new_index));
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_n_fields(offsets) == dict_index_get_n_fields(index));
- ut_ad(rec_offs_size(offsets) <= sizeof index->online_log->tail.buf);
+ ut_ad(rec_offs_size(offsets) <= sizeof log->tail.buf);
ut_ad(rw_lock_own_flagged(
&index->lock,
RW_LOCK_FLAG_S | RW_LOCK_FLAG_X | RW_LOCK_FLAG_SX));
@@ -959,7 +970,7 @@ row_log_table_low(
ut_ad(!"wrong page type");
}
#endif /* UNIV_DEBUG */
- ut_ad(!rec_is_default_row(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
ut_ad(page_rec_is_leaf(rec));
ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets));
/* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix
@@ -970,7 +981,7 @@ row_log_table_low(
if (index->online_status != ONLINE_INDEX_CREATION
|| (index->type & DICT_CORRUPT) || index->table->corrupted
- || index->online_log->error != DB_SUCCESS) {
+ || log->error != DB_SUCCESS) {
return;
}
@@ -982,19 +993,37 @@ row_log_table_low(
ut_ad(page_is_comp(page_align(rec)));
ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY
- || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED);
+ || rec_get_status(rec) == REC_STATUS_INSTANT);
const ulint omit_size = REC_N_NEW_EXTRA_BYTES;
const ulint rec_extra_size = rec_offs_extra_size(offsets) - omit_size;
- const bool is_instant = index->online_log->is_instant(index);
+ const bool is_instant = log->is_instant(index);
extra_size = rec_extra_size + is_instant;
+ unsigned fake_extra_size = 0;
+ byte fake_extra_buf[2];
+ if (is_instant && UNIV_UNLIKELY(!index->is_instant())) {
+ /* The source table was emptied after ALTER TABLE
+ started, and it was converted to non-instant format.
+ Because row_log_table_apply_op() expects to find
+ all records to be logged in the same way, we will
+ be unable to copy the rec_extra_size bytes from the
+ record header, but must convert them here. */
+ unsigned n_add = index->n_fields - 1 - log->n_core_fields;
+ fake_extra_size = rec_get_n_add_field_len(n_add);
+ ut_ad(fake_extra_size == 1 || fake_extra_size == 2);
+ extra_size += fake_extra_size;
+ byte* fake_extra = fake_extra_buf + fake_extra_size - 1;
+ rec_set_n_add_field(fake_extra, n_add);
+ ut_ad(fake_extra + 1 == fake_extra_buf);
+ }
+
mrec_size = ROW_LOG_HEADER_SIZE
+ (extra_size >= 0x80) + rec_offs_size(offsets) - omit_size
- + is_instant;
+ + is_instant + fake_extra_size;
- if (insert || index->online_log->same_pk) {
+ if (insert || log->same_pk) {
ut_ad(!old_pk);
old_pk_extra_size = old_pk_size = 0;
} else {
@@ -1012,8 +1041,7 @@ row_log_table_low(
mrec_size += 1/*old_pk_extra_size*/ + old_pk_size;
}
- if (byte* b = row_log_table_open(index->online_log,
- mrec_size, &avail_size)) {
+ if (byte* b = row_log_table_open(log, mrec_size, &avail_size)) {
if (insert) {
*b++ = ROW_T_INSERT;
} else {
@@ -1038,20 +1066,23 @@ row_log_table_low(
}
if (is_instant) {
- *b++ = rec_get_status(rec);
+ *b++ = fake_extra_size
+ ? REC_STATUS_INSTANT
+ : rec_get_status(rec);
} else {
ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
}
memcpy(b, rec - rec_extra_size - omit_size, rec_extra_size);
b += rec_extra_size;
+ memcpy(b, fake_extra_buf, fake_extra_size);
+ b += fake_extra_size;
ulint len;
ulint trx_id_offs = rec_get_nth_field_offs(
offsets, index->n_uniq, &len);
ut_ad(len == DATA_TRX_ID_LEN);
memcpy(b, rec, rec_offs_data_size(offsets));
- if (trx_read_trx_id(b + trx_id_offs)
- < index->online_log->min_trx) {
+ if (trx_read_trx_id(b + trx_id_offs) < log->min_trx) {
memcpy(b + trx_id_offs,
reset_trx_id, sizeof reset_trx_id);
}
@@ -1133,7 +1164,6 @@ row_log_table_get_pk_col(
field = rec_get_nth_field(rec, offsets, i, &len);
if (len == UNIV_SQL_NULL) {
-
if (!log->allow_not_null) {
return(DB_INVALID_NULL);
}
@@ -1142,6 +1172,9 @@ row_log_table_get_pk_col(
field = static_cast<const byte*>(
log->defaults->fields[n_default_cols].data);
+ if (!field) {
+ return(DB_INVALID_NULL);
+ }
len = log->defaults->fields[i - DATA_N_SYS_COLS].len;
}
@@ -1526,11 +1559,17 @@ row_log_table_apply_convert_mrec(
const dict_col_t* col
= dict_field_get_col(ind_field);
+ if (col->is_dropped()) {
+ /* the column was instantly dropped earlier */
+ ut_ad(index->table->instant);
+ continue;
+ }
+
ulint col_no
= log->col_map[dict_col_get_no(col)];
if (col_no == ULINT_UNDEFINED) {
- /* dropped column */
+ /* the column is being dropped now */
continue;
}
@@ -1576,7 +1615,7 @@ blob_done:
} else {
data = rec_get_nth_field(mrec, offsets, i, &len);
if (len == UNIV_SQL_DEFAULT) {
- data = index->instant_field_value(i, &len);
+ data = log->instant_field_value(i, &len);
}
dfield_set_data(dfield, data, len);
}
@@ -1886,8 +1925,7 @@ row_log_table_apply_delete(
btr_pcur_t pcur;
ulint* offsets;
- ut_ad(rec_offs_n_fields(moffsets)
- == dict_index_get_n_unique(index) + 2);
+ ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field());
ut_ad(!rec_offs_any_extern(moffsets));
/* Convert the row to a search tuple. */
@@ -2416,7 +2454,7 @@ row_log_table_apply_op(
rec_offs_set_n_fields(offsets, dup->index->n_fields);
rec_init_offsets_temp(mrec, dup->index, offsets,
- log->n_core_fields,
+ log->n_core_fields, log->non_core_fields,
is_instant
? static_cast<rec_comp_status_t>(
*(mrec - extra_size))
@@ -2450,8 +2488,7 @@ row_log_table_apply_op(
/* The ROW_T_DELETE record was converted by
rec_convert_dtuple_to_temp() using new_index. */
ut_ad(!new_index->is_instant());
- rec_offs_set_n_fields(offsets,
- unsigned(new_index->n_uniq) + 2);
+ rec_offs_set_n_fields(offsets, new_index->first_user_field());
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets);
if (next_mrec > mrec_end) {
@@ -2497,6 +2534,7 @@ row_log_table_apply_op(
rec_offs_set_n_fields(offsets, dup->index->n_fields);
rec_init_offsets_temp(mrec, dup->index, offsets,
log->n_core_fields,
+ log->non_core_fields,
is_instant
? static_cast<rec_comp_status_t>(
*(mrec - extra_size))
@@ -2542,7 +2580,7 @@ row_log_table_apply_op(
rec_convert_dtuple_to_temp() using new_index. */
ut_ad(!new_index->is_instant());
rec_offs_set_n_fields(offsets,
- unsigned(new_index->n_uniq) + 2);
+ new_index->first_user_field());
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets);
@@ -2552,13 +2590,12 @@ row_log_table_apply_op(
/* Copy the PRIMARY KEY fields and
DB_TRX_ID, DB_ROLL_PTR from mrec to old_pk. */
- old_pk = dtuple_create(
- heap, unsigned(new_index->n_uniq) + 2);
+ old_pk = dtuple_create(heap,
+ new_index->first_user_field());
dict_index_copy_types(old_pk, new_index,
old_pk->n_fields);
- for (ulint i = 0;
- i < dict_index_get_n_unique(new_index) + 2;
+ for (ulint i = 0; i < new_index->first_user_field();
i++) {
const void* field;
ulint len;
@@ -2598,6 +2635,7 @@ row_log_table_apply_op(
rec_offs_set_n_fields(offsets, dup->index->n_fields);
rec_init_offsets_temp(mrec, dup->index, offsets,
log->n_core_fields,
+ log->non_core_fields,
is_instant
? static_cast<rec_comp_status_t>(
*(mrec - extra_size))
@@ -2708,8 +2746,8 @@ row_log_table_apply_ops(
dict_index_t* new_index = dict_table_get_first_index(
new_table);
const ulint i = 1 + REC_OFFS_HEADER_SIZE
- + ut_max(dict_index_get_n_fields(index),
- dict_index_get_n_unique(new_index) + 2);
+ + std::max<ulint>(index->n_fields,
+ new_index->first_user_field());
const ulint new_trx_id_col = dict_col_get_clust_pos(
dict_table_get_sys_col(new_table, DATA_TRX_ID), new_index);
trx_t* trx = thr_get_trx(thr);
@@ -3169,11 +3207,24 @@ row_log_allocate(
log->head.total = 0;
log->path = path;
log->n_core_fields = index->n_core_fields;
- ut_ad(!table || log->is_instant(index) == index->is_instant());
+ ut_ad(!table || log->is_instant(index)
+ == (index->n_core_fields < index->n_fields));
log->allow_not_null = allow_not_null;
log->old_table = old_table;
log->n_rows = 0;
+ if (table && index->is_instant()) {
+ const unsigned n = log->n_core_fields;
+ log->non_core_fields = UT_NEW_ARRAY_NOKEY(
+ dict_col_t::def_t, index->n_fields - n);
+ for (unsigned i = n; i < index->n_fields; i++) {
+ log->non_core_fields[i - n]
+ = index->fields[i].col->def_val;
+ }
+ } else {
+ log->non_core_fields = NULL;
+ }
+
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
index->online_log = log;
@@ -3206,6 +3257,7 @@ row_log_free(
MONITOR_ATOMIC_DEC(MONITOR_ONLINE_CREATE_INDEX);
UT_DELETE(log->blobs);
+ UT_DELETE_ARRAY(log->non_core_fields);
row_log_block_free(log->tail);
row_log_block_free(log->head);
row_merge_file_destroy_low(log->fd);