Commit 48a662da authored by Eugene Kosov's avatar Eugene Kosov Committed by Marko Mäkelä

MDEV-19486 Server crashes in row_upd or row_upd_del_mark_clust_rec on REPLACE...

MDEV-19486 Server crashes in row_upd or row_upd_del_mark_clust_rec on REPLACE into a versioned table

row_insert_for_mysql(): InnoDB sets values for row_start and row_end.
And this function used to return those values to server in
ha_innobase::write_row().  This buggy behavior was removed. Also,
a piece of code in this function was reformatted.

upd_node_t::make_versioned_helper(): Assert that the preallocated size
of the update vector is not exceeded.
parent 7056812e
......@@ -32,5 +32,19 @@ insert into t1 values (1,1);
create or replace table t2 (c int);
create or replace view v as select t1.* from t1 join t2;
replace into v (a, b) select a, b from t1;
drop table t1;
CREATE TABLE t1 (
pk INT AUTO_INCREMENT,
f INT,
row_start SYS_DATATYPE AS ROW START INVISIBLE,
row_end SYS_DATATYPE AS ROW END INVISIBLE,
PRIMARY KEY(pk),
UNIQUE(f),
PERIOD FOR SYSTEM_TIME(row_start, row_end)
) WITH SYSTEM VERSIONING;
INSERT INTO t1 () VALUES (),(),(),(),(),();
UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
drop database test;
create database test;
......@@ -35,6 +35,23 @@ insert into t1 values (1,1);
create or replace table t2 (c int);
create or replace view v as select t1.* from t1 join t2;
replace into v (a, b) select a, b from t1;
drop table t1;
--replace_result $sys_datatype_expl SYS_DATATYPE
eval CREATE TABLE t1 (
pk INT AUTO_INCREMENT,
f INT,
row_start $sys_datatype_expl AS ROW START INVISIBLE,
row_end $sys_datatype_expl AS ROW END INVISIBLE,
PRIMARY KEY(pk),
UNIQUE(f),
PERIOD FOR SYSTEM_TIME(row_start, row_end)
) WITH SYSTEM VERSIONING;
INSERT INTO t1 () VALUES (),(),(),(),(),();
UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
drop database test;
create database test;
......@@ -1417,26 +1417,24 @@ row_insert_for_mysql(
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec,
&blob_heap);
if (ins_mode != ROW_INS_NORMAL)
{
if (ins_mode != ROW_INS_NORMAL) {
ut_ad(table->vers_start != table->vers_end);
/* Return back modified fields into mysql_rec, so that
upper logic may benefit from it (f.ex. 'on duplicate key'). */
const mysql_row_templ_t* t = prebuilt->get_template_by_col(table->vers_end);
const mysql_row_templ_t* t
= prebuilt->get_template_by_col(table->vers_end);
ut_ad(t);
ut_ad(t->mysql_col_len == 8);
if (ins_mode == ROW_INS_HISTORICAL) {
set_tuple_col_8(node->row, table->vers_end, trx->id, node->vers_end_buf);
}
else /* ROW_INS_VERSIONED */ {
set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf);
int8store(&mysql_rec[t->mysql_col_offset], TRX_ID_MAX);
set_tuple_col_8(node->row, table->vers_end, trx->id,
node->vers_end_buf);
} else /* ROW_INS_VERSIONED */ {
set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX,
node->vers_end_buf);
t = prebuilt->get_template_by_col(table->vers_start);
ut_ad(t);
ut_ad(t->mysql_col_len == 8);
set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf);
int8store(&mysql_rec[t->mysql_col_offset], trx->id);
set_tuple_col_8(node->row, table->vers_start, trx->id,
node->vers_start_buf);
}
}
......
......@@ -3485,9 +3485,11 @@ void upd_node_t::make_versioned_helper(const trx_t* trx, ulint idx)
dict_index_t* clust_index = dict_table_get_first_index(table);
/* row_create_update_node_for_mysql() pre-allocated this much */
ut_ad(update->n_fields < table->n_cols + table->n_v_cols);
update->n_fields++;
upd_field_t* ufield =
upd_get_nth_field(update, upd_get_n_fields(update) - 1);
upd_field_t* ufield = upd_get_nth_field(update, update->n_fields - 1);
const dict_col_t* col = dict_table_get_nth_col(table, idx);
upd_field_set_field_no(ufield, dict_col_get_clust_pos(col, clust_index),
......
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