mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
committed by
Marko Mäkelä
parent
7056812ed1
commit
48a662dae5
@ -32,5 +32,19 @@ insert into t1 values (1,1);
|
|||||||
create or replace table t2 (c int);
|
create or replace table t2 (c int);
|
||||||
create or replace view v as select t1.* from t1 join t2;
|
create or replace view v as select t1.* from t1 join t2;
|
||||||
replace into v (a, b) select a, b from t1;
|
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;
|
drop database test;
|
||||||
create 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 table t2 (c int);
|
||||||
create or replace view v as select t1.* from t1 join t2;
|
create or replace view v as select t1.* from t1 join t2;
|
||||||
replace into v (a, b) select a, b from t1;
|
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;
|
drop database test;
|
||||||
create database test;
|
create database test;
|
||||||
|
@ -1417,26 +1417,24 @@ row_insert_for_mysql(
|
|||||||
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec,
|
row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec,
|
||||||
&blob_heap);
|
&blob_heap);
|
||||||
|
|
||||||
if (ins_mode != ROW_INS_NORMAL)
|
if (ins_mode != ROW_INS_NORMAL) {
|
||||||
{
|
|
||||||
ut_ad(table->vers_start != table->vers_end);
|
ut_ad(table->vers_start != table->vers_end);
|
||||||
/* Return back modified fields into mysql_rec, so that
|
const mysql_row_templ_t* t
|
||||||
upper logic may benefit from it (f.ex. 'on duplicate key'). */
|
= 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);
|
||||||
ut_ad(t->mysql_col_len == 8);
|
ut_ad(t->mysql_col_len == 8);
|
||||||
|
|
||||||
if (ins_mode == ROW_INS_HISTORICAL) {
|
if (ins_mode == ROW_INS_HISTORICAL) {
|
||||||
set_tuple_col_8(node->row, table->vers_end, trx->id, node->vers_end_buf);
|
set_tuple_col_8(node->row, table->vers_end, trx->id,
|
||||||
}
|
node->vers_end_buf);
|
||||||
else /* ROW_INS_VERSIONED */ {
|
} else /* ROW_INS_VERSIONED */ {
|
||||||
set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf);
|
set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX,
|
||||||
int8store(&mysql_rec[t->mysql_col_offset], TRX_ID_MAX);
|
node->vers_end_buf);
|
||||||
t = prebuilt->get_template_by_col(table->vers_start);
|
t = prebuilt->get_template_by_col(table->vers_start);
|
||||||
ut_ad(t);
|
ut_ad(t);
|
||||||
ut_ad(t->mysql_col_len == 8);
|
ut_ad(t->mysql_col_len == 8);
|
||||||
set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf);
|
set_tuple_col_8(node->row, table->vers_start, trx->id,
|
||||||
int8store(&mysql_rec[t->mysql_col_offset], 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);
|
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++;
|
update->n_fields++;
|
||||||
upd_field_t* ufield =
|
upd_field_t* ufield = upd_get_nth_field(update, update->n_fields - 1);
|
||||||
upd_get_nth_field(update, upd_get_n_fields(update) - 1);
|
|
||||||
const dict_col_t* col = dict_table_get_nth_col(table, idx);
|
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),
|
upd_field_set_field_no(ufield, dict_col_get_clust_pos(col, clust_index),
|
||||||
|
Reference in New Issue
Block a user