mirror of
https://github.com/MariaDB/server.git
synced 2025-11-09 11:41:36 +03:00
MDEV-37312 ASAN errors or assertion failure upon attempt to UPDATE FOR PORTION violating long unique under READ COMMITTED
in case of a long unique conflict ha_write_row() used delete_row() to remove the newly inserted row, and it used rnd_pos() to position the cursor before deletion. This rnd_pos() was freeing and reallocating blobs in record[0]. So when the code for FOR PORTION OF did store_record(record[2]); ha_write_row() restore_record(record[2]); it ended up with blob pointers to a freed memory. Let's use lookup_handler for deletion.
This commit is contained in:
@@ -15,3 +15,20 @@ INSERT INTO t1 VALUES (1,'foo','2022-01-01', '2025-01-01');
|
||||
DELETE FROM t1 FOR PORTION OF app FROM '2023-01-01' TO '2024-01-01';
|
||||
ERROR 23000: Duplicate entry 'foo' for key 'b'
|
||||
DROP TABLE t1;
|
||||
# End of 10.5 tests
|
||||
#
|
||||
# MDEV-37312 ASAN errors or assertion failure upon attempt to UPDATE FOR PORTION violating long unique under READ COMMITTED
|
||||
#
|
||||
create table t1 (a int, f text unique, s datetime, e datetime, period for p(s,e)) engine=innodb;
|
||||
insert into t1 values (1,'foo','1900-01-01','2000-01-01'),(2,'bar','1900-01-01','2000-01-01');
|
||||
set transaction isolation level read committed;
|
||||
update t1 for portion of p from '1980-01-01' to '1980-01-02' set a = 1;
|
||||
ERROR 23000: Duplicate entry 'foo' for key 'f'
|
||||
drop table t1;
|
||||
create table t1 (a int, f text unique, s datetime, e datetime, period for p(s,e)) engine=innodb partition by hash (a);
|
||||
insert into t1 values (1,'foo','1900-01-01','2000-01-01'),(2,'bar','1900-01-01','2000-01-01');
|
||||
set transaction isolation level read committed;
|
||||
update t1 for portion of p from '1980-01-01' to '1980-01-02' set a = 1;
|
||||
ERROR 23000: Duplicate entry 'foo' for key 'f'
|
||||
drop table t1;
|
||||
# End of 10.6 tests
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_partition.inc
|
||||
|
||||
--echo #
|
||||
@@ -21,3 +22,23 @@ INSERT INTO t1 VALUES (1,'foo','2022-01-01', '2025-01-01');
|
||||
DELETE FROM t1 FOR PORTION OF app FROM '2023-01-01' TO '2024-01-01';
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 10.5 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-37312 ASAN errors or assertion failure upon attempt to UPDATE FOR PORTION violating long unique under READ COMMITTED
|
||||
--echo #
|
||||
create table t1 (a int, f text unique, s datetime, e datetime, period for p(s,e)) engine=innodb;
|
||||
insert into t1 values (1,'foo','1900-01-01','2000-01-01'),(2,'bar','1900-01-01','2000-01-01');
|
||||
set transaction isolation level read committed;
|
||||
--error ER_DUP_ENTRY
|
||||
update t1 for portion of p from '1980-01-01' to '1980-01-02' set a = 1;
|
||||
drop table t1;
|
||||
|
||||
create table t1 (a int, f text unique, s datetime, e datetime, period for p(s,e)) engine=innodb partition by hash (a);
|
||||
insert into t1 values (1,'foo','1900-01-01','2000-01-01'),(2,'bar','1900-01-01','2000-01-01');
|
||||
set transaction isolation level read committed;
|
||||
--error ER_DUP_ENTRY
|
||||
update t1 for portion of p from '1980-01-01' to '1980-01-02' set a = 1;
|
||||
drop table t1;
|
||||
|
||||
--echo # End of 10.6 tests
|
||||
|
||||
@@ -3367,7 +3367,7 @@ int handler::create_lookup_handler()
|
||||
if (!(tmp= clone(table->s->normalized_path.str, table->in_use->mem_root)))
|
||||
return 1;
|
||||
lookup_handler= tmp;
|
||||
return lookup_handler->ha_external_lock(table->in_use, F_RDLCK);
|
||||
return lookup_handler->ha_external_lock(table->in_use, F_WRLCK);
|
||||
}
|
||||
|
||||
LEX_CSTRING *handler::engine_name()
|
||||
@@ -7774,16 +7774,16 @@ int handler::ha_write_row(const uchar *buf)
|
||||
if (lookup_handler != this) // INSERT IGNORE or REPLACE or ODKU
|
||||
{
|
||||
int olderror= error;
|
||||
if ((error= rnd_init(0)))
|
||||
if ((error= lookup_handler->rnd_init(0)))
|
||||
goto err;
|
||||
position(buf);
|
||||
if ((error= rnd_pos(lookup_buffer, ref)))
|
||||
if ((error= lookup_handler->rnd_pos(lookup_buffer, ref)))
|
||||
goto err;
|
||||
|
||||
increment_statistics(&SSV::ha_delete_count);
|
||||
TABLE_IO_WAIT(tracker, PSI_TABLE_DELETE_ROW, MAX_KEY, error,
|
||||
{ error= delete_row(buf);})
|
||||
rnd_end();
|
||||
{ error= lookup_handler->delete_row(buf);})
|
||||
lookup_handler->rnd_end();
|
||||
if (!error)
|
||||
error= olderror;
|
||||
}
|
||||
@@ -7916,8 +7916,7 @@ int handler::ha_delete_row(const uchar *buf)
|
||||
/*
|
||||
Normally table->record[0] is used, but sometimes table->record[1] is used.
|
||||
*/
|
||||
DBUG_ASSERT(buf == table->record[0] ||
|
||||
buf == table->record[1]);
|
||||
DBUG_ASSERT(buf == table->record[0] || buf == table->record[1]);
|
||||
|
||||
MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
mark_trx_read_write();
|
||||
|
||||
Reference in New Issue
Block a user