diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index f0975b6fa10..2b312a86289 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -324,6 +324,7 @@ a b 7 7 8 8 9 9 +update t1,t2 set t1.b=t2.b, t1.a=t2.a where t1.a=t2.a and not exists (select * from t2 where t2.a > 10); drop table t1,t2; CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) ENGINE=MyISAM; INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL); diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index fbd4624a57c..54bba1fd958 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -924,3 +924,15 @@ a 1 2 2 +set sql_select_limit=1; +select 1 union select 2; +1 +1 +(select 1) union (select 2); +1 +1 +(select 1) union (select 2) union (select 3) limit 2; +1 +1 +2 +set sql_select_limit=default; diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 8b6941c4a94..36854551a7f 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -260,6 +260,10 @@ update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t2.a=t1 select * from t1; select * from t2; +# test for non-updating table which is also used in sub-select + +update t1,t2 set t1.b=t2.b, t1.a=t2.a where t1.a=t2.a and not exists (select * from t2 where t2.a > 10); + drop table t1,t2; CREATE TABLE t3 ( KEY1 varchar(50) NOT NULL default '', PARAM_CORR_DISTANCE_RUSH double default NULL, PARAM_CORR_DISTANCE_GEM double default NULL, PARAM_AVG_TARE double default NULL, PARAM_AVG_NB_DAYS double default NULL, PARAM_DEFAULT_PROP_GEM_SRVC varchar(50) default NULL, PARAM_DEFAULT_PROP_GEM_NO_ETIK varchar(50) default NULL, PARAM_SCENARIO_COSTS varchar(50) default NULL, PARAM_DEFAULT_WAGON_COST double default NULL, tmp int(11) default NULL, PRIMARY KEY (KEY1)) ENGINE=MyISAM; INSERT INTO t3 VALUES ('A',1,1,22,3.2,'R','R','BASE2',0.24,NULL); diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 9866b867427..effb0139111 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -498,4 +498,9 @@ select * from t1 UNION ALL select * from t1; select * from t1 UNION select * from t1 UNION ALL select * from t1; drop table t1; select 1 as a union all select 1 union all select 2 union select 1 union all select 2; +set sql_select_limit=1; +select 1 union select 2; +(select 1) union (select 2); +(select 1) union (select 2) union (select 3) limit 2; +set sql_select_limit=default; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 42b67a79683..1b3995f30be 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -377,12 +377,21 @@ int st_select_lex_unit::exec() if (!thd->is_fatal_error) // Check if EOM { ulong options_tmp= thd->options; + /* + We have to take into the account a case when: + SET SQL_SELECT_LIMIT was set. + In mysql_new_select() function this value was copied to + the fake_select_lex node of the top-level unit. + Here below, we just take this value if global LIMIT was not applied + to the entire UNION. + */ + ha_rows select_limit= ((global_parameters->select_limit != HA_POS_ERROR) ? + global_parameters->select_limit : fake_select_lex->select_limit); thd->lex->current_select= fake_select_lex; offset_limit_cnt= global_parameters->offset_limit; - select_limit_cnt= global_parameters->select_limit + - global_parameters->offset_limit; + select_limit_cnt= select_limit + global_parameters->offset_limit; - if (select_limit_cnt < global_parameters->select_limit) + if (select_limit_cnt < select_limit) select_limit_cnt= HA_POS_ERROR; // no limit if (select_limit_cnt == HA_POS_ERROR) options_tmp&= ~OPTION_FOUND_ROWS; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 55ea15f1af4..d985d2c2e78 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -578,7 +578,7 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, int multi_update::prepare(List ¬_used_values, SELECT_LEX_UNIT *lex_unit) { - TABLE_LIST *table_ref; + TABLE_LIST *table_ref, *tables; SQL_LIST update; table_map tables_to_update= 0; Item_field *item; @@ -604,8 +604,9 @@ int multi_update::prepare(List ¬_used_values, We have to check values after setup_tables to get used_keys right in reference tables */ + tables= thd->lex->select_lex.get_table_list(); - if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0)) + if (setup_fields(thd, 0, tables, *values, 1, 0, 0)) DBUG_RETURN(1); /* @@ -615,7 +616,7 @@ int multi_update::prepare(List ¬_used_values, */ update.empty(); - for (table_ref= all_tables; table_ref; table_ref=table_ref->next) + for (table_ref= tables; table_ref; table_ref=table_ref->next) { TABLE *table=table_ref->table; if (tables_to_update & table->map) @@ -684,10 +685,10 @@ int multi_update::prepare(List ¬_used_values, which will cause an error when reading a row. (This issue is mostly relevent for MyISAM tables) */ - for (table_ref= all_tables; table_ref; table_ref=table_ref->next) + for (table_ref= tables; table_ref; table_ref=table_ref->next) { TABLE *table=table_ref->table; - if (!(tables_to_update & table->map) && + if (!(tables_to_update & table->map) || !table->no_keyread && find_real_table_in_list(update_tables, table_ref->db, table_ref->real_name)) table->no_cache= 1; // Disable row cache