diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index a847f2d7025..6859d9db728 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -314,4 +314,24 @@ key1 key2 key3 key4 key5 key6 key7 key8 key9 keyA keyB keyC 11 11 11 11 11 11 11 1013 11 11 11 11 12 12 12 12 12 12 12 1012 12 12 12 12 1016 1016 1016 1016 1016 1016 1016 8 1016 1016 1016 1016 +explain select * from t0 where key1 < 3 or key2 < 4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 index_merge i1,i2 i1,i2 4,4 NULL 7 Using where +select * from t0 where key1 < 3 or key2 < 4; +key1 key2 key3 key4 key5 key6 key7 key8 +1 1 1 1 1 1 1 1023 +2 2 2 2 2 2 2 1022 +3 3 3 3 3 3 3 1021 +update t0 set key8=123 where key1 < 3 or key2 < 4; +select * from t0 where key1 < 3 or key2 < 4; +key1 key2 key3 key4 key5 key6 key7 key8 +1 1 1 1 1 1 1 123 +2 2 2 2 2 2 2 123 +3 3 3 3 3 3 3 123 +delete from t0 where key1 < 3 or key2 < 4; +select * from t0 where key1 < 3 or key2 < 4; +key1 key2 key3 key4 key5 key6 key7 key8 +select count(*) from t0; +count(*) +1021 drop table t0, t1, t2, t3, t4; diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 029c2e4a013..9745723ca59 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -267,5 +267,15 @@ select * from t3 where key5=5 or key6=6 or key7=7 or key8=8 or key9=9 or keyA=10 or keyB=11 or keyC=12; +# Test for Bug#3183 +explain select * from t0 where key1 < 3 or key2 < 4; +select * from t0 where key1 < 3 or key2 < 4; + +update t0 set key8=123 where key1 < 3 or key2 < 4; +select * from t0 where key1 < 3 or key2 < 4; + +delete from t0 where key1 < 3 or key2 < 4; +select * from t0 where key1 < 3 or key2 < 4; +select count(*) from t0; drop table t0, t1, t2, t3, t4; diff --git a/sql/opt_range.h b/sql/opt_range.h index 1e5f58bc1f5..3c528719b29 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -87,7 +87,16 @@ public: QUICK_SELECT_I(); virtual ~QUICK_SELECT_I(){}; + /* + Call init() immediately after creation of quick select. if init() call + fails, reset() or get_next() must not be called. + */ virtual int init() = 0; + + /* + Call reset() before first get_next call. get_next must not be called if + reset() call fails. + */ virtual int reset(void) = 0; virtual int get_next() = 0; /* get next record to retrieve */ virtual bool reverse_sorted() = 0; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 1fa216fdb58..7ebe9cb6002 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -150,6 +150,13 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order, select= 0; } + /* If quick select is used, initialize it before retrieving rows. */ + if (select && select->quick && select->quick->reset()) + { + delete select; + free_underlaid_joins(thd, &thd->lex->select_lex); + DBUG_RETURN(-1); // This will force out message + } init_read_record(&info,thd,table,select,1,1); deleted=0L; init_ftfuncs(thd, &thd->lex->select_lex, 1); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 03ab3d01c1a..24199df9b84 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -246,7 +246,11 @@ int mysql_update(THD *thd, DISK_BUFFER_SIZE, MYF(MY_WME))) goto err; + /* If quick select is used, initialize it before retrieving rows. */ + if (select && select->quick && select->quick->reset()) + goto err; init_read_record(&info,thd,table,select,0,1); + thd->proc_info="Searching rows for update"; uint tmp_limit= limit;