diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index f5ae87c69ce..410ce34ee65 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -675,4 +675,55 @@ Warning 1292 Incorrect datetime value: '1' DROP VIEW v1; DROP FUNCTION f1; DROP TABLE t1; +# +# MDEV-4123: Incorrect results after multi-table update or +# assertion `!table || (!table->read_set || +# bitmap_is_set(table->read_set, field_index))' failure +# +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 ( +id int(10) unsigned NOT NULL, +level tinyint(3) unsigned NOT NULL, +PRIMARY KEY (id) +); +INSERT INTO t1 VALUES (2519583,1); +DROP TABLE IF EXISTS t2; +Warnings: +Note 1051 Unknown table 't2' +CREATE TABLE t2 ( +club_id int(11) NOT NULL DEFAULT '0', +profile_id int(11) NOT NULL DEFAULT '0', +member_level_id int(11) NOT NULL DEFAULT '0', +PRIMARY KEY (profile_id,club_id) +); +INSERT INTO t2 VALUES (2,2519583,12); +DROP TABLE IF EXISTS t3; +Warnings: +Note 1051 Unknown table 't3' +CREATE TABLE t3 ( +member_level_id int(11) unsigned NOT NULL DEFAULT '0', +map_level int(11) unsigned NOT NULL DEFAULT '0', +map_status int(11) unsigned NOT NULL DEFAULT '0', +PRIMARY KEY (member_level_id) +); +INSERT INTO t3 VALUES (12,12,1); +CREATE +VIEW v1 AS +select club_id,profile_id, +map_level AS member_level_id,map_status AS member_status +from (t2 tc join t3 map +on(((tc.member_level_id = map.member_level_id) and +(club_id = 2)))); +select level, count(*) as cnt from t1 group by level; +level cnt +1 1 +UPDATE t1 c LEFT JOIN v1 t ON (c.id = t.profile_id AND t.club_id = 2) +SET c.level = IF (t.member_status IS NULL, 1, IF (t.member_status = 1, 2,3)); +select level, count(*) as cnt from t1 group by level; +level cnt +2 1 +drop view v1; +drop table t1,t2,t3; end of tests diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 58a614e3a11..7743aa5efca 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -691,4 +691,51 @@ DROP VIEW v1; DROP FUNCTION f1; DROP TABLE t1; +--echo # +--echo # MDEV-4123: Incorrect results after multi-table update or +--echo # assertion `!table || (!table->read_set || +--echo # bitmap_is_set(table->read_set, field_index))' failure +--echo # + +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( + id int(10) unsigned NOT NULL, + level tinyint(3) unsigned NOT NULL, + PRIMARY KEY (id) +); +INSERT INTO t1 VALUES (2519583,1); + +DROP TABLE IF EXISTS t2; +CREATE TABLE t2 ( + club_id int(11) NOT NULL DEFAULT '0', + profile_id int(11) NOT NULL DEFAULT '0', + member_level_id int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (profile_id,club_id) +); +INSERT INTO t2 VALUES (2,2519583,12); + +DROP TABLE IF EXISTS t3; +CREATE TABLE t3 ( + member_level_id int(11) unsigned NOT NULL DEFAULT '0', + map_level int(11) unsigned NOT NULL DEFAULT '0', + map_status int(11) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (member_level_id) +); +INSERT INTO t3 VALUES (12,12,1); + +CREATE + VIEW v1 AS + select club_id,profile_id, + map_level AS member_level_id,map_status AS member_status + from (t2 tc join t3 map + on(((tc.member_level_id = map.member_level_id) and + (club_id = 2)))); + +select level, count(*) as cnt from t1 group by level; +UPDATE t1 c LEFT JOIN v1 t ON (c.id = t.profile_id AND t.club_id = 2) + SET c.level = IF (t.member_status IS NULL, 1, IF (t.member_status = 1, 2,3)); +select level, count(*) as cnt from t1 group by level; +drop view v1; +drop table t1,t2,t3; + --echo end of tests diff --git a/sql/sql_class.h b/sql/sql_class.h index 4c8fe9cd164..48d8560dcfc 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2833,6 +2833,7 @@ public: #else void begin_dataset() {} #endif + virtual void update_used_tables() {} }; @@ -3578,6 +3579,7 @@ public: int do_updates(); bool send_eof(); virtual void abort(); + void update_used_tables(); }; class my_var : public Sql_alloc { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8222088c8f3..5bacb675644 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3540,7 +3540,8 @@ void SELECT_LEX::update_used_tables() { for (ORDER *order= order_list.first; order; order= order->next) (*order->item)->update_used_tables(); - } + } + join->result->update_used_tables(); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9d00118f450..21e5828699f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1473,6 +1473,15 @@ int multi_update::prepare(List ¬_used_values, DBUG_RETURN(thd->is_fatal_error != 0); } +void multi_update::update_used_tables() +{ + Item *item; + List_iterator_fast it(*values); + while ((item= it++)) + { + item->update_used_tables(); + } +} /* Check if table is safe to update on fly