mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-20515 multi-update tries to position updated table by null reference
Cause
Join tmp table inserts null row because of OUTER JOIN, that's
expected. Since `multi_update::prepare2()` converted
`Item_temptable_rowid` into `Item_field` (28dbdf3
)
`multi_update::send_data()` accesses join tmp record directly and
treats it as a normal row ignoring null status of ref field. NULL ref
field is then treated as normal in `multi_update::do_updates()` which
tries to position updated table by reference 0.
Note that reference 0 may be valid reference and the first row of
table can be wrongly updated (see multi_update.test).
Fix
Do not add row into multi-update tmp table in case of null ref
field. Join tmp table does not have null_row status at this time (as
well as `STATUS_NULL_ROW`) and cannot be skipped by these properties
(see first comment in multi_update::send_data()). But it has all null
fields (including the ref field).
This commit is contained in:
@ -1081,3 +1081,20 @@ b c
|
||||
2 0
|
||||
drop view v1;
|
||||
drop table t0, t1,t2;
|
||||
#
|
||||
# MDEV-20515 multi-update tries to position updated table by null reference
|
||||
#
|
||||
create or replace table t1 (a int);
|
||||
insert into t1 values (0), (2);
|
||||
create or replace table t2 (b int);
|
||||
insert into t2 values (1), (2);
|
||||
select * from t1 left join t2 on a = b order by b;
|
||||
a b
|
||||
0 NULL
|
||||
2 2
|
||||
update t1 left join t2 on a = b set b= 3 order by b;
|
||||
select * from t2;
|
||||
b
|
||||
1
|
||||
3
|
||||
drop tables t1, t2;
|
||||
|
@ -1019,3 +1019,18 @@ update v1,t0 set c=1 where b<3 and x=c order by x,b limit 1;
|
||||
select * from v1;
|
||||
drop view v1;
|
||||
drop table t0, t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-20515 multi-update tries to position updated table by null reference
|
||||
--echo #
|
||||
create or replace table t1 (a int);
|
||||
insert into t1 values (0), (2);
|
||||
|
||||
create or replace table t2 (b int);
|
||||
insert into t2 values (1), (2);
|
||||
|
||||
select * from t1 left join t2 on a = b order by b;
|
||||
update t1 left join t2 on a = b set b= 3 order by b;
|
||||
select * from t2;
|
||||
|
||||
drop tables t1, t2;
|
||||
|
@ -615,6 +615,17 @@ insert into t2 values (1),(2);
|
||||
update t1, t2 set a = 1;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# MDEV-20515 multi-update tries to position updated table by null reference
|
||||
#
|
||||
create or replace table t1 (a int);
|
||||
insert into t1 values (0), (1);
|
||||
create or replace table t2 (b int) with system versioning
|
||||
partition by system_time
|
||||
(partition p1 history, partition pn current);
|
||||
insert into t2 values (0), (2);
|
||||
update t1 left join t2 on a > b set b= 2 order by b;
|
||||
drop table t1, t2;
|
||||
#
|
||||
# MDEV-17091 Assertion `old_part_id == m_last_part' failed in
|
||||
# ha_partition::update_row or `part_id == m_last_part' in
|
||||
# ha_partition::delete_row upon UPDATE/DELETE after dropping versioning
|
||||
|
@ -567,6 +567,22 @@ update t1, t2 set a = 1;
|
||||
# cleanup
|
||||
drop table t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-20515 multi-update tries to position updated table by null reference
|
||||
--echo #
|
||||
create or replace table t1 (a int);
|
||||
insert into t1 values (0), (1);
|
||||
|
||||
create or replace table t2 (b int) with system versioning
|
||||
partition by system_time
|
||||
(partition p1 history, partition pn current);
|
||||
|
||||
insert into t2 values (0), (2);
|
||||
update t1 left join t2 on a > b set b= 2 order by b;
|
||||
|
||||
# cleanup
|
||||
drop table t1, t2;
|
||||
|
||||
--source suite/versioning/common_finish.inc
|
||||
--echo #
|
||||
--echo # MDEV-17091 Assertion `old_part_id == m_last_part' failed in
|
||||
|
@ -2467,6 +2467,9 @@ int multi_update::send_data(List<Item> ¬_used_values)
|
||||
TABLE *tmp_table= tmp_tables[offset];
|
||||
if (copy_funcs(tmp_table_param[offset].items_to_copy, thd))
|
||||
DBUG_RETURN(1);
|
||||
/* rowid field is NULL if join tmp table has null row from outer join */
|
||||
if (tmp_table->field[0]->is_null())
|
||||
continue;
|
||||
/* Store regular updated fields in the row. */
|
||||
DBUG_ASSERT(1 + unupdated_check_opt_tables.elements ==
|
||||
tmp_table_param[offset].func_count);
|
||||
@ -2671,6 +2674,7 @@ int multi_update::do_updates()
|
||||
uint field_num= 0;
|
||||
do
|
||||
{
|
||||
DBUG_ASSERT(!tmp_table->field[field_num]->is_null());
|
||||
if (unlikely((local_error=
|
||||
tbl->file->ha_rnd_pos(tbl->record[0],
|
||||
(uchar *) tmp_table->
|
||||
|
Reference in New Issue
Block a user