diff options
-rw-r--r-- | mysql-test/suite/federated/federated_maybe_16324629.result | 1 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/update.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/vcol/t/update.test | 10 | ||||
-rw-r--r-- | sql/sql_class.h | 20 | ||||
-rw-r--r-- | sql/sql_delete.cc | 11 | ||||
-rw-r--r-- | sql/sql_lex.cc | 9 | ||||
-rw-r--r-- | sql/sql_select.cc | 1 | ||||
-rw-r--r-- | sql/sql_update.cc | 17 |
8 files changed, 63 insertions, 17 deletions
diff --git a/mysql-test/suite/federated/federated_maybe_16324629.result b/mysql-test/suite/federated/federated_maybe_16324629.result index 0417b5c0659..e16e4dd101d 100644 --- a/mysql-test/suite/federated/federated_maybe_16324629.result +++ b/mysql-test/suite/federated/federated_maybe_16324629.result @@ -13,7 +13,6 @@ insert into t1 values (3, 3), (7, 7); delete t1 from t1 where a = 3; select * from t1; a b -3 3 7 7 drop table t1; connection slave; diff --git a/mysql-test/suite/vcol/r/update.result b/mysql-test/suite/vcol/r/update.result index dd864e4a7e2..e88502492cb 100644 --- a/mysql-test/suite/vcol/r/update.result +++ b/mysql-test/suite/vcol/r/update.result @@ -43,3 +43,14 @@ select * from t1; a b c b 2 b drop table t1; +create table t (a int primary key, b int, c int as (b), index (c)); +insert t (a,b) values (9,0); +create table t2 select * from t; +update t, t2 set t.b=10 where t.a=t2.a; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +select * from t; +a b c +9 10 10 +drop table t, t2; diff --git a/mysql-test/suite/vcol/t/update.test b/mysql-test/suite/vcol/t/update.test index f840c277cd1..8be5872a26b 100644 --- a/mysql-test/suite/vcol/t/update.test +++ b/mysql-test/suite/vcol/t/update.test @@ -55,3 +55,13 @@ replace t1 set a = 'a',b =1; insert t1 (a,b) values ('a', 1) on duplicate key update a='b', b=2; select * from t1; drop table t1; + +# +# multi-UPDATE and const tables +# +create table t (a int primary key, b int, c int as (b), index (c)); +insert t (a,b) values (9,0); +create table t2 select * from t; +update t, t2 set t.b=10 where t.a=t2.a; +check table t; select * from t; +drop table t, t2; diff --git a/sql/sql_class.h b/sql/sql_class.h index 0434f5485cf..507fadedac1 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4455,6 +4455,9 @@ public: #endif virtual void update_used_tables() {} + /* this method is called just before the first row of the table can be read */ + virtual void prepare_to_read_rows() {} + void reset_offset_limit() { unit->offset_limit_cnt= 0; @@ -5301,11 +5304,9 @@ public: int do_deletes(); int do_table_deletes(TABLE *table, SORT_INFO *sort_info, bool ignore); bool send_eof(); - inline ha_rows num_deleted() - { - return deleted; - } + inline ha_rows num_deleted() const { return deleted; } virtual void abort_result_set(); + void prepare_to_read_rows(); }; @@ -5349,16 +5350,11 @@ public: bool initialize_tables (JOIN *join); int do_updates(); bool send_eof(); - inline ha_rows num_found() - { - return found; - } - inline ha_rows num_updated() - { - return updated; - } + inline ha_rows num_found() const { return found; } + inline ha_rows num_updated() const { return updated; } virtual void abort_result_set(); void update_used_tables(); + void prepare_to_read_rows(); }; class my_var : public Sql_alloc { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 46491a832b3..e9a3be30060 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -924,6 +924,15 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_RETURN(0); } +void multi_delete::prepare_to_read_rows() +{ + /* see multi_update::prepare_to_read_rows() */ + for (TABLE_LIST *walk= delete_tables; walk; walk= walk->next_local) + { + TABLE_LIST *tbl= walk->correspondent_table->find_table_for_update(); + tbl->table->mark_columns_needed_for_delete(); + } +} bool multi_delete::initialize_tables(JOIN *join) @@ -953,7 +962,6 @@ multi_delete::initialize_tables(JOIN *join) } } - walk= delete_tables; for (JOIN_TAB *tab= first_linear_tab(join, WITHOUT_BUSH_ROOTS, @@ -977,7 +985,6 @@ multi_delete::initialize_tables(JOIN *join) normal_tables= 1; tbl->prepare_triggers_for_delete_stmt_or_event(); tbl->prepare_for_position(); - tbl->mark_columns_needed_for_delete(); } else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) && walk == delete_tables) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index bea3b14e607..634b6d1a3b8 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -4122,6 +4122,15 @@ void SELECT_LEX::update_used_tables() TABLE *tab= tl->table; tab->covering_keys= tab->s->keys_for_keyread; tab->covering_keys.intersect(tab->keys_in_use_for_query); + /* + View/derived was merged. Need to recalculate read_set/vcol_set + bitmaps here. For example: + CREATE VIEW v1 AS SELECT f1,f2,f3 FROM t1; + SELECT f1 FROM v1; + Initially, the view definition will put all f1,f2,f3 in the + read_set for t1. But after the view is merged, only f1 should + be in the read_set. + */ bitmap_clear_all(tab->read_set); if (tab->vcol_set) bitmap_clear_all(tab->vcol_set); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index efeee4085ff..89a9eeb1e32 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1466,6 +1466,7 @@ JOIN::optimize_inner() /* Calculate how to do the join */ THD_STAGE_INFO(thd, stage_statistics); + result->prepare_to_read_rows(); if (make_join_statistics(this, select_lex->leaf_tables, &keyuse) || thd->is_fatal_error) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index da0e6cd2116..05f7080609a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1800,6 +1800,21 @@ void multi_update::update_used_tables() } } +void multi_update::prepare_to_read_rows() +{ + /* + update column maps now. it cannot be done in ::prepare() before the + optimizer, because the optimize might reset them (in + SELECT_LEX::update_used_tables()), it cannot be done in + ::initialize_tables() after the optimizer, because the optimizer + might read rows from const tables + */ + + for (TABLE_LIST *tl= update_tables; tl; tl= tl->next_local) + tl->table->mark_columns_needed_for_update(); +} + + /* Check if table is safe to update on fly @@ -1916,12 +1931,10 @@ multi_update::initialize_tables(JOIN *join) { if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables)) { - table->mark_columns_needed_for_update(); table_to_update= table; // Update table on the fly continue; } } - table->mark_columns_needed_for_update(); table->prepare_for_position(); /* |