Skip to content

Commit

Permalink
MDEV-20515 multi-update tries to position updated table by null refer…
Browse files Browse the repository at this point in the history
…ence

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).
  • Loading branch information
midenok committed Apr 2, 2020
1 parent ba34f40 commit 0932c58
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 0 deletions.
17 changes: 17 additions & 0 deletions mysql-test/main/multi_update.result
Original file line number Diff line number Diff line change
Expand Up @@ -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;
15 changes: 15 additions & 0 deletions mysql-test/main/multi_update.test
Original file line number Diff line number Diff line change
Expand Up @@ -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;
11 changes: 11 additions & 0 deletions mysql-test/suite/versioning/r/partition.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions mysql-test/suite/versioning/t/partition.test
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions sql/sql_update.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,9 @@ int multi_update::send_data(List<Item> &not_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);
Expand Down Expand Up @@ -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->
Expand Down

0 comments on commit 0932c58

Please sign in to comment.