List:Commits« Previous MessageNext Message »
From:Sergey Petrunia Date:January 10 2008 10:05pm
Subject:bk commit into 6.0 tree (sergefp:1.2774) BUG#30622
View as plain text  
Below is the list of changes that have just been committed into a local
6.0 repository of psergey. When psergey does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-01-11 01:04:59+03:00, sergefp@stripped +17 -0
  BUG#30622: ORDER BY on a SELECT causes results to be missed
  - Restore the original table condition if we've done index condition pushdown
    for some index but later decided not to use it 
  - Remove outdated comments

  mysql-test/r/grant2.result@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +0 -6
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Fix the wrong test results

  mysql-test/r/index_merge_myisam.result@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +3 -3
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Fix the wrong test results

  mysql-test/r/myisam_mrr.result@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +28 -0
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Testcases

  mysql-test/r/order_by.result@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +2 -2
    BUG#30622: ORDER BY on a SELECT causes results to be missed 
    - Update test results

  mysql-test/t/disabled.def@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +1 -1
    BUG#30622: ORDER BY on a SELECT causes results to be missed 
    - Update test results

  mysql-test/t/myisam_mrr.test@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +29 -0
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Testcases

  sql/handler.cc@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +73 -81
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Change the DsMRR_impl: let it use the secondary object to do index scans 
      and primary object to do rnd_pos() calls. This allows the SQL layer to call
      position() on the primary object. 
    - Remove outdated deadcode

  sql/handler.h@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +44 -33
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Change the DsMRR_impl: let it use the secondary object to do index scans 
      and primary object to do rnd_pos() calls. This allows the SQL layer to call
      position() on the primary object. 
    - Remove outdated deadcode

  sql/opt_range.cc@stripped, 2008-01-11 01:04:52+03:00, sergefp@stripped +1 -1
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Fix: pass multi_range_read_const() HA_MRR_USE_DEFAULT_IMPL flag if we're told 
      to use the default MRR implementation.

  sql/set_var.cc@stripped, 2008-01-11 01:04:53+03:00, sergefp@stripped +0 -2
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Remove garbage comments

  sql/sql_select.cc@stripped, 2008-01-11 01:04:53+03:00, sergefp@stripped +7 -18
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Restore the original table condition if we've done index condition pushdown
      for some index but later decided not to use it 
    - Remove outdated comments

  storage/innobase/handler/ha_innodb.cc@stripped, 2008-01-11 01:04:53+03:00, sergefp@stripped +37 -36
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - MRR variables moved to class handler
    - Remove garbage comments

  storage/innobase/handler/ha_innodb.h@stripped, 2008-01-11 01:04:53+03:00, sergefp@stripped +0 -18
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - MRR variables moved to class handler
    - Remove garbage comments

  storage/myisam/ha_myisam.cc@stripped, 2008-01-11 01:04:53+03:00, sergefp@stripped +29 -27
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - MRR variables moved to class handler
    - Remove garbage comments

  storage/myisam/ha_myisam.h@stripped, 2008-01-11 01:04:54+03:00, sergefp@stripped +0 -9
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - MRR variables moved to class handler
    - Use the new DsMRR_impl use convention

  storage/myisam/mi_key.c@stripped, 2008-01-11 01:04:54+03:00, sergefp@stripped +0 -30
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Remove redundant deadcode

  storage/myisam/mi_rkey.c@stripped, 2008-01-11 01:04:54+03:00, sergefp@stripped +0 -13
    BUG#30622: ORDER BY on a SELECT causes results to be missed
    - Remove redundant deadcode

diff -Nrup a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
--- a/mysql-test/r/grant2.result	2007-10-04 14:37:03 +04:00
+++ b/mysql-test/r/grant2.result	2008-01-11 01:04:52 +03:00
@@ -148,9 +148,7 @@ host	user	password
 %	mysqltest_3	fffffffffffffffffffffffffffffffffffffffff
 select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
 host	db	user
-%	test	
 %	test	mysqltest_2
-%	test\_%	
 select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
 host	db	user	table_name
 %	test	mysqltest_2	t1
@@ -174,9 +172,7 @@ host	user	password
 %	mysqltest_3	fffffffffffffffffffffffffffffffffffffffff
 select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
 host	db	user
-%	test	
 %	test	mysqltest_2
-%	test\_%	
 select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
 host	db	user	table_name
 %	test	mysqltest_2	t1
@@ -193,9 +189,7 @@ host	user	password
 %	mysqltest_3	fffffffffffffffffffffffffffffffffffffffff
 select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
 host	db	user
-%	test	
 %	test	mysqltest_1
-%	test\_%	
 select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
 host	db	user	table_name
 %	test	mysqltest_1	t1
diff -Nrup a/mysql-test/r/index_merge_myisam.result b/mysql-test/r/index_merge_myisam.result
--- a/mysql-test/r/index_merge_myisam.result	2007-12-02 07:19:17 +03:00
+++ b/mysql-test/r/index_merge_myisam.result	2008-01-11 01:04:52 +03:00
@@ -398,13 +398,13 @@ Table	Op	Msg_type	Msg_text
 test.t1	optimize	status	OK
 select count(*) from t1;
 count(*)
-41984
+8704
 explain select * from t1 WHERE cola = 'foo' AND colb = 'bar';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	7	Using intersect(cola,colb); Using where
+1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	32	Using intersect(cola,colb); Using where
 explain select * from t1 force index(cola,colb) WHERE cola = 'foo' AND colb = 'bar';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	7	Using intersect(cola,colb); Using where
+1	SIMPLE	t1	index_merge	cola,colb	cola,colb	3,3	NULL	32	Using intersect(cola,colb); Using where
 drop table t1;
 create table t0 (a int);
 insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
diff -Nrup a/mysql-test/r/myisam_mrr.result b/mysql-test/r/myisam_mrr.result
--- a/mysql-test/r/myisam_mrr.result	2007-03-10 00:08:20 +03:00
+++ b/mysql-test/r/myisam_mrr.result	2008-01-11 01:04:52 +03:00
@@ -275,3 +275,31 @@ bb-1	NULL	cc-2	NULL-2
 bb-1	NULL	cc-2	NULL-1
 set @@read_rnd_buffer_size= @read_rnd_buffer_size_save;
 drop table t1, t2, t3, t4;
+CREATE TABLE t1 (
+ID int(10) unsigned NOT NULL AUTO_INCREMENT,
+col1 int(10) unsigned DEFAULT NULL,
+key1 int(10) unsigned NOT NULL DEFAULT '0',
+key2 int(10) unsigned DEFAULT NULL,
+text1 text,
+text2 text,
+col2 smallint(6) DEFAULT '100',
+col3 enum('headers','bodyandsubject') NOT NULL DEFAULT 'bodyandsubject',
+col4 tinyint(3) unsigned NOT NULL DEFAULT '0',
+PRIMARY KEY (ID),
+KEY (key1),
+KEY (key2)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES
+(1,NULL,1130,NULL,'Hello',NULL,100,'bodyandsubject',0),
+(2,NULL,1130,NULL,'bye',NULL,100,'bodyandsubject',0),
+(3,NULL,1130,NULL,'red',NULL,100,'bodyandsubject',0),
+(4,NULL,1130,NULL,'yellow',NULL,100,'bodyandsubject',0),
+(5,NULL,1130,NULL,'blue',NULL,100,'bodyandsubject',0);
+select * FROM t1 WHERE key1=1130 AND col1 IS NULL ORDER BY text1;
+ID	col1	key1	key2	text1	text2	col2	col3	col4
+5	NULL	1130	NULL	blue	NULL	100	bodyandsubject	0
+2	NULL	1130	NULL	bye	NULL	100	bodyandsubject	0
+1	NULL	1130	NULL	Hello	NULL	100	bodyandsubject	0
+3	NULL	1130	NULL	red	NULL	100	bodyandsubject	0
+4	NULL	1130	NULL	yellow	NULL	100	bodyandsubject	0
+drop table t1;
diff -Nrup a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
--- a/mysql-test/r/order_by.result	2007-10-24 03:58:33 +04:00
+++ b/mysql-test/r/order_by.result	2008-01-11 01:04:52 +03:00
@@ -609,7 +609,7 @@ FieldKey	LongVal	StringVal
 1	2	1
 EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1	range	FieldKey,LongField,StringField	FieldKey	38	NULL	4	Using index condition; Using MRR; Using filesort
+1	SIMPLE	t1	range	FieldKey,LongField,StringField	FieldKey	38	NULL	4	Using index condition; Using where; Using MRR; Using filesort
 SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
 FieldKey	LongVal	StringVal
 3	1	2
@@ -1107,7 +1107,7 @@ id	select_type	table	type	possible_keys	
 1	SIMPLE	t2	index	k2	k3	5	NULL	73	Using where
 EXPLAIN SELECT id,c3 FROM t2 WHERE c2 BETWEEN 20 AND 30 ORDER BY c3 LIMIT 4000;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using where; Using filesort
+1	SIMPLE	t2	range	k2	k2	5	NULL	386	Using index condition; Using where; Using MRR; Using filesort
 SELECT id,c3 FROM t2 WHERE c2=11 ORDER BY c3 LIMIT 20;
 id	c3
 6	14
diff -Nrup a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
--- a/mysql-test/t/disabled.def	2007-12-12 11:14:04 +03:00
+++ b/mysql-test/t/disabled.def	2008-01-11 01:04:52 +03:00
@@ -15,7 +15,7 @@ user_limits     : Bug#23921 random failu
 concurrent_innodb        : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences
 ctype_big5               : BUG#26711 2007-06-21 Lars Test has never worked on Double Whopper
 
-order_by             : WL#2475: spetrunia producing ordered streams is not handled correctly
+##order_by             : WL#2475: spetrunia producing ordered streams is not handled correctly
 federated_transactions   : Bug#29523 Transactions do not work
 locktrans_innodb     : Bug#29929 2007-07-20 ingo LOCK TABLES does not pre-lock tables used in triggers
 rpl_locktrans_innodb : Bug#29929 2007-07-20 ingo LOCK TABLES does not pre-lock tables used in triggers
diff -Nrup a/mysql-test/t/myisam_mrr.test b/mysql-test/t/myisam_mrr.test
--- a/mysql-test/t/myisam_mrr.test	2007-03-10 00:08:20 +03:00
+++ b/mysql-test/t/myisam_mrr.test	2008-01-11 01:04:52 +03:00
@@ -16,3 +16,32 @@ set @@read_rnd_buffer_size= @read_rnd_bu
 
 drop table t1, t2, t3, t4;
 
+#
+# BUG#30622: Incorrect query results for MRR + filesort
+# 
+CREATE TABLE t1 (
+  ID int(10) unsigned NOT NULL AUTO_INCREMENT,
+  col1 int(10) unsigned DEFAULT NULL,
+  key1 int(10) unsigned NOT NULL DEFAULT '0',
+  key2 int(10) unsigned DEFAULT NULL,
+  text1 text,
+  text2 text,
+  col2 smallint(6) DEFAULT '100',
+  col3 enum('headers','bodyandsubject') NOT NULL DEFAULT 'bodyandsubject',
+  col4 tinyint(3) unsigned NOT NULL DEFAULT '0',
+  PRIMARY KEY (ID),
+  KEY (key1),
+  KEY (key2)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES
+(1,NULL,1130,NULL,'Hello',NULL,100,'bodyandsubject',0),
+(2,NULL,1130,NULL,'bye',NULL,100,'bodyandsubject',0),
+(3,NULL,1130,NULL,'red',NULL,100,'bodyandsubject',0),
+(4,NULL,1130,NULL,'yellow',NULL,100,'bodyandsubject',0),
+(5,NULL,1130,NULL,'blue',NULL,100,'bodyandsubject',0);
+
+select * FROM t1 WHERE key1=1130 AND col1 IS NULL ORDER BY text1;
+
+drop table t1;
+
diff -Nrup a/sql/handler.cc b/sql/handler.cc
--- a/sql/handler.cc	2007-12-13 15:56:18 +03:00
+++ b/sql/handler.cc	2008-01-11 01:04:52 +03:00
@@ -3443,39 +3443,7 @@ int handler::multi_range_read_next(char 
     /* Save a call if there can be only one row in range. */
     if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
     {
-#if 0      
-      if (mrr_restore_scan)
-      {
-        result= mrr_restore_scan_res;
-        if (!result)
-          result= (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
-        else
-        {
-          if (result == HA_ERR_KEY_NOT_FOUND)
-            result= HA_ERR_END_OF_FILE;
-        }
-        mrr_restore_scan= FALSE;
-        if (!result)
-        {
-          /*
-            Continue as if we're scanning a generic (i.e. not necessarily
-            equality) range. The point is that if we're in the middle of
-            equality range, we can't continue scanning it as equality range.
-            The call sequence is:
-              file->index_read( ... , HA_READ_KEY_EXACT);
-              file->index_next_same(...)
-              ...
-              file->index_read(..., HA_READ_AFTER_KEY) // restore the scan
-            That is, the "restore the scan" call has interrupted the
-            equality range and we can't use index_next_same() anymore.
-          */
-          eq_range= FALSE; 
-        }
-      }
-      else
-#endif      
-        result= read_range_next();
-
+      result= read_range_next();
       /* On success or non-EOF errors jump to the end. */
       if (result != HA_ERR_END_OF_FILE)
         break;
@@ -3544,19 +3512,20 @@ int DsMrr_impl::dsmrr_init(handler *h, K
                            RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
                            uint n_ranges, uint mode, HANDLER_BUFFER *buf)
 {
-  int res;
   uint elem_size;
+  uint keyno;
+  Item *pushed_cond= NULL;
   DBUG_ENTER("DsMrr_impl::dsmrr_init");
+  keyno= h->active_index;
   if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
   {
     use_default_impl= TRUE;
     DBUG_RETURN(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
                                                   n_ranges, mode, buf));
   }
-  use_default_impl= FALSE;
   
   rowids_buf= buf->buffer;
-  last_idx_tuple= rowids_buf;
+  //psergey-todo: don't add key_length as it is not needed anymore
   rowids_buf += key->key_length + h->ref_length;
 
   is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
@@ -3567,15 +3536,7 @@ int DsMrr_impl::dsmrr_init(handler *h, K
                       ((rowids_buf_end - rowids_buf)/ elem_size)*
                       elem_size;
   rowids_buf_end= rowids_buf_last;
-  res= h->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
-                                         mode, buf);
-  DBUG_ASSERT(!res);
 
-  mrr_key= key;
-  mrr_keyno= h->active_index;
-  //h->mrr_restore_scan= FALSE;
-  /* h->mrr_restore_scan_res needs no initialization */
-  
   /* Create a separate handler object to do rndpos() calls. */
   THD *thd= current_thd;
   if (!(h2= h->clone(thd->mem_root)) || h2->ha_external_lock(thd, F_RDLCK))
@@ -3583,23 +3544,32 @@ int DsMrr_impl::dsmrr_init(handler *h, K
     delete h2;
     DBUG_RETURN(1);
   }
-
   my_bitmap_map *bmp_buf;
-  if (!(bmp_buf= (my_bitmap_map*)thd->alloc(h->table->s->column_bitmap_size)))
+  if (!(bmp_buf= (my_bitmap_map*)thd->alloc(table->s->column_bitmap_size)))
     goto error;
 
-  bitmap_init(&row_access_bitmap, bmp_buf, h->table->s->fields, FALSE);
-  bitmap_copy(&row_access_bitmap, h->table->read_set);
-  save_read_set= h->table->read_set;
-  save_write_set= h->table->write_set;
-  
-  if (h->index_end() || h->extra(HA_EXTRA_KEYREAD))
+  bitmap_init(&row_access_bitmap, bmp_buf, table->s->fields, FALSE);
+  bitmap_copy(&row_access_bitmap, table->read_set);
+  save_read_set= table->read_set;
+  save_write_set= table->write_set;
+  
+  if (keyno == h->pushed_idx_cond_keyno)
+    pushed_cond= h->pushed_idx_cond;
+  if (h->ha_index_end())
     goto error;
- 
-  h->table->key_read= TRUE;
-  h->table->prepare_for_position();
-  h->table->mark_columns_used_by_index_no_reset(mrr_keyno, h->table->read_set);
-  if (h->index_init(mrr_keyno, FALSE) || dsmrr_fill_buffer(h))
+   
+  table->prepare_for_position();
+  h2->extra(HA_EXTRA_KEYREAD);
+
+  if (h2->ha_index_init(keyno, FALSE) || 
+      h2->handler::multi_range_read_init(seq_funcs, seq_init_param, n_ranges,
+                                         mode, buf))
+    goto error;
+  use_default_impl= FALSE;
+  
+  if (pushed_cond)
+    h2->idx_cond_push(keyno, pushed_cond);
+  if (dsmrr_fill_buffer(h2))
     goto error;
 
   /*
@@ -3609,17 +3579,18 @@ int DsMrr_impl::dsmrr_init(handler *h, K
   if (dsmrr_eof) 
     buf->end_of_used_area= rowids_buf_last;
 
-  h->table->column_bitmaps_set_no_signal(&row_access_bitmap, 
+  table->column_bitmaps_set_no_signal(&row_access_bitmap, 
                                          &row_access_bitmap);
-  if (h2->rnd_init(FALSE))
+  if (h->ha_rnd_init(FALSE))
     goto error;
-
+  
   DBUG_RETURN(0);
 error:
+  h2->ha_index_or_rnd_end();
   h2->ha_external_lock(thd, F_UNLCK);
   h2->close();
   delete h2;
-  h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
+  table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
   DBUG_RETURN(1);
 }
 
@@ -3627,14 +3598,18 @@ error:
 void DsMrr_impl::dsmrr_close()
 {
   DBUG_ENTER("DsMrr_impl::dsmrr_close");
-  if (h2)
+  if (!use_default_impl)
   {
-    h2->ha_external_lock(current_thd, F_UNLCK);
-    h2->close();
-    delete h2;
-    h2= NULL;
+    if (h2)
+    {
+      h2->ha_external_lock(current_thd, F_UNLCK);
+      h2->close();
+      delete h2;
+      h2= NULL;
+    }
+    table->column_bitmaps_set(save_read_set, save_write_set);
+    use_default_impl= TRUE;
   }
-  h->table->column_bitmaps_set(save_read_set, save_write_set);
   DBUG_VOID_RETURN;
 }
 
@@ -3665,7 +3640,7 @@ static int rowid_cmp(void *h, uchar *a, 
     other - Error
 */
 
-int DsMrr_impl::dsmrr_fill_buffer(handler *h)
+int DsMrr_impl::dsmrr_fill_buffer(handler *unused)
 {
   char *range_info;
   int res;
@@ -3673,11 +3648,11 @@ int DsMrr_impl::dsmrr_fill_buffer(handle
 
   rowids_buf_cur= rowids_buf;
   while ((rowids_buf_cur < rowids_buf_end) && 
-         !(res= h->handler::multi_range_read_next(&range_info)))
+         !(res= h2->handler::multi_range_read_next(&range_info)))
   {
     /* Put rowid, or {rowid, range_id} pair into the buffer */
-    h->position(h->table->record[0]);
-    memcpy(rowids_buf_cur, h->ref, h->ref_length);
+    h2->position(table->record[0]);
+    memcpy(rowids_buf_cur, h2->ref, h2->ref_length);
     rowids_buf_cur += h->ref_length;
 
     if (is_mrr_assoc)
@@ -3716,7 +3691,7 @@ int DsMrr_impl::dsmrr_next(handler *h, c
     
   if (rowids_buf_cur == rowids_buf_last)
   {
-    h->table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
+    table->column_bitmaps_set_no_signal(save_read_set, save_write_set);
     if (dsmrr_eof)
     {
       res= HA_ERR_END_OF_FILE;
@@ -3724,7 +3699,8 @@ int DsMrr_impl::dsmrr_next(handler *h, c
     }
 
     res= dsmrr_fill_buffer(h);
-    h->table->column_bitmaps_set_no_signal(&row_access_bitmap,
+    
+    table->column_bitmaps_set_no_signal(&row_access_bitmap,
                                            &row_access_bitmap);
     if (res)
       goto end;
@@ -3737,7 +3713,7 @@ int DsMrr_impl::dsmrr_next(handler *h, c
     goto end;
   }
 
-  res= h2->rnd_pos(h->table->record[0], rowids_buf_cur);
+  res= h->rnd_pos(table->record[0], rowids_buf_cur);
   rowids_buf_cur += h->ref_length;
   if (is_mrr_assoc)
   {
@@ -3848,8 +3824,8 @@ ha_rows DsMrr_impl::dsmrr_info_const(uin
 
 bool DsMrr_impl::key_uses_partial_cols(uint keyno)
 {
-  KEY_PART_INFO *kp= h->table->key_info[keyno].key_part;
-  KEY_PART_INFO *kp_end= kp + h->table->key_info[keyno].key_parts;
+  KEY_PART_INFO *kp= table->key_info[keyno].key_part;
+  KEY_PART_INFO *kp_end= kp + table->key_info[keyno].key_parts;
   for (; kp != kp_end; kp++)
   {
     if (!kp->field->part_of_key.is_set(keyno))
@@ -3894,7 +3870,7 @@ bool DsMrr_impl::choose_mrr_impl(uint ke
   THD *thd= current_thd;
   if ((thd->variables.optimizer_use_mrr == 2) || 
       (*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
-      (keyno == h->table_share->primary_key && 
+      (keyno == table->s->primary_key && 
        h->primary_key_is_clustered()) || 
        key_uses_partial_cols(keyno))
   {
@@ -3903,7 +3879,7 @@ bool DsMrr_impl::choose_mrr_impl(uint ke
     return TRUE;
   }
   
-  uint add_len= h->table->key_info[keyno].key_length + h->ref_length; 
+  uint add_len= table->key_info[keyno].key_length + h->ref_length; 
   *bufsz -= add_len;
   if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
     return TRUE;
@@ -3984,7 +3960,7 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost
   /* Adjust buffer size if we expect to use only part of the buffer */
   if (n_full_steps)
   {
-    get_sort_and_sweep_cost(h->table, rows, cost);
+    get_sort_and_sweep_cost(table, rows, cost);
     cost->multiply(n_full_steps);
   }
   else
@@ -3992,11 +3968,11 @@ bool DsMrr_impl::get_disk_sweep_mrr_cost
     cost->zero();
     *buffer_size= max(*buffer_size, 
                       (size_t)(1.2*rows_in_last_step) * elem_size + 
-                      h->ref_length + h->table->key_info[keynr].key_length);
+                      h->ref_length + table->key_info[keynr].key_length);
   }
   
   COST_VECT last_step_cost;
-  get_sort_and_sweep_cost(h->table, rows_in_last_step, &last_step_cost);
+  get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
   cost->add(&last_step_cost);
  
   if (n_full_steps != 0)
@@ -4246,6 +4222,22 @@ int handler::compare_key(key_range *rang
   return cmp;
 }
 
+
+/*
+  Same as compare_key() but doesn't check have in_range_check_pushed_down.
+  This is used by index condition pushdown implementation.
+*/
+
+int handler::compare_key2(key_range *range)
+{
+  int cmp;
+  if (!range)
+    return 0;					// no max range
+  cmp= key_cmp(range_key_part, range->key, range->length);
+  if (!cmp)
+    cmp= key_compare_result_on_equal;
+  return cmp;
+}
 
 int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
                                 key_part_map keypart_map,
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h	2007-12-12 11:14:04 +03:00
+++ b/sql/handler.h	2008-01-11 01:04:52 +03:00
@@ -1205,7 +1205,6 @@ uint calculate_key_len(TABLE *, uint, co
 class handler :public Sql_alloc
 {
   friend class ha_partition;
-  friend class DsMrr_impl;
   friend int ha_delete_table(THD*,handlerton*,const char*,const char*,
                              const char*,bool);
 
@@ -1244,10 +1243,10 @@ public:
 
   ha_statistics stats;
   
-  /* Multi range read implementation-used members: */
-  range_seq_t mrr_iter;    /* MRR range sequence iterator being traversed */
-  RANGE_SEQ_IF mrr_funcs;  /* Saved MRR range sequence traversal functions */
-  HANDLER_BUFFER *multi_range_buffer; /* Saved MRR buffer info */
+  /* MultiRangeRead-related members: */
+  range_seq_t mrr_iter;    /* Interator to traverse the range sequence */
+  RANGE_SEQ_IF mrr_funcs;  /* Range sequence traversal functions */
+  HANDLER_BUFFER *multi_range_buffer; /* MRR buffer info */
   uint ranges_in_seq; /* Total number of ranges in the traversed sequence */
   /* TRUE <=> source MRR ranges and the output are ordered */
   bool mrr_is_output_sorted;
@@ -1257,17 +1256,13 @@ public:
   /* Current range (the one we're now returning rows from) */
   KEY_MULTI_RANGE mrr_cur_range;
   
-  /* Default MRR implementation: */
-  //bool mrr_restore_scan; /* TRUE <=> we're restoring the scan */
-  //int mrr_restore_scan_res; /* iff mrr_restore_scan: return value of next call */
-
   /* The following are for read_range() */
   key_range save_end_range, *end_range;
   KEY_PART_INFO *range_key_part;
   int key_compare_result_on_equal;
   bool eq_range;
   /* 
-    TRUE <=> the engine checks that returned records are within the range
+    TRUE <=> the engine guarantees that returned records are within the range
     being scanned.
   */
   bool in_range_check_pushed_down;
@@ -1281,7 +1276,11 @@ public:
   enum {NONE=0, INDEX, RND} inited;
   bool locked;
   bool implicit_emptied;                /* Can be !=0 only if HEAP */
-  const COND *pushed_cond;
+  const Item *pushed_cond;
+
+  Item *pushed_idx_cond;
+  uint pushed_idx_cond_keyno;  /* The index which the above condition is for */
+
   /*
     next_insert_id is the next value which should be inserted into the
     auto_increment column: in a inserting-multi-row statement (like INSERT
@@ -1308,12 +1307,13 @@ public:
   handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
     :table_share(share_arg), table(0),
     estimation_rows_to_insert(0), ht(ht_arg),
-    ref(0), /*mrr_restore_scan(FALSE), */ in_range_check_pushed_down(FALSE),
+    ref(0), in_range_check_pushed_down(FALSE),
     key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
     ref_length(sizeof(my_off_t)),
     ft_handler(0), inited(NONE),
     locked(FALSE), implicit_emptied(0),
-    pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0)
+    pushed_cond(0), pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY),
+    next_insert_id(0), insert_id_for_cur_row(0)
     {}
   virtual ~handler(void)
   {
@@ -1412,6 +1412,7 @@ public:
     DBUG_ASSERT(inited==NONE);
     if (!(result= index_init(idx, sorted)))
       inited=INDEX;
+    end_range= NULL;
     DBUG_RETURN(result);
   }
   int ha_index_end()
@@ -1419,6 +1420,7 @@ public:
     DBUG_ENTER("ha_index_end");
     DBUG_ASSERT(inited==INDEX);
     inited=NONE;
+    end_range= NULL;
     DBUG_RETURN(index_end());
   }
   int ha_rnd_init(bool scan)
@@ -1603,6 +1605,7 @@ public:
                                bool eq_range, bool sorted);
   virtual int read_range_next();
   int compare_key(key_range *range);
+  int compare_key2(key_range *range);
   virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
   void ft_end() { ft_handler=NULL; }
   virtual FT_INFO *ft_init_ext(uint flags, uint inx,String *key)
@@ -2171,7 +2174,6 @@ public:
     return HA_ERR_WRONG_COMMAND;
   }
 
-  virtual void add_explain_extra_info(uint keyno, String *extra) {}
 private:
   /*
     Row-level primitives for storage engines.  These should be
@@ -2224,34 +2226,43 @@ class DsMrr_impl
 public:
   typedef void (handler::*range_check_toggle_func_t)(bool on);
 
-  DsMrr_impl(range_check_toggle_func_t func)
-    : last_idx_tuple(NULL), range_check_toggle_func(func) {};
+  DsMrr_impl()
+    : use_default_impl(TRUE) {};
+
+  handler *h; /* The "owner" handler object. It is used for scanning the index */
+  TABLE *table; /* Always equal to h->table */
+private:
+  /*
+    Secondary handler object. It is used to retrieve full table rows by
+    calling rnd_pos().
+  */
+  handler *h2;
 
-  uchar *rowids_buf;       /* ROWIDs buffer */
+  /* Buffer to store rowids, or (rowid, range_id) pairs */
+  uchar *rowids_buf;
   uchar *rowids_buf_cur;   /* Current position when reading/writing */
-  uchar *rowids_buf_last;  /* Wen reading: end of used buffer space */
+  uchar *rowids_buf_last;  /* When reading: end of used buffer space */
   uchar *rowids_buf_end;   /* End of the buffer */
-  
-  KEY  *mrr_key;           /* Index to use */
-  uint mrr_keyno;          /* Number of the index */
 
-  uchar *last_idx_tuple; //TODO: remove 
-  bool dsmrr_eof;        //TODO: remove 
+  bool dsmrr_eof; /* TRUE <=> We have reached EOF when reading index tuples */
 
   /* TRUE <=> need range association, buffer holds {rowid, range_id} pairs */
-  bool is_mrr_assoc; 
+  bool is_mrr_assoc;
 
-  handler *h; /* Owner table handler */
-  handler *h2; /* Slave handler for doing rnd_pos(). */
-   
-  /* Bitmaps for the rnd_pos()-calling handler object */
+  /*
+    Column bitmaps to be used with slave handler object. Those are necessary
+    as we set primary handler object's bitmap to contain index columns only.
+  */
   MY_BITMAP row_access_bitmap;
   MY_BITMAP *save_read_set, *save_write_set;
-
-  bool use_default_impl; /* TRUE <=> shortcut the calls to default MRR impl */
-  range_check_toggle_func_t range_check_toggle_func;
-
-
+  
+  bool use_default_impl; /* TRUE <=> shortcut all calls to default MRR impl */
+public:
+  void init(handler *h_arg, TABLE *table_arg)
+  {
+    h= h_arg; 
+    table= table_arg;
+  }
   int dsmrr_init(handler *h, KEY *key, RANGE_SEQ_IF *seq_funcs, 
                  void *seq_init_param, uint n_ranges, uint mode, 
                  HANDLER_BUFFER *buf);
diff -Nrup a/sql/opt_range.cc b/sql/opt_range.cc
--- a/sql/opt_range.cc	2007-12-13 15:56:19 +03:00
+++ b/sql/opt_range.cc	2008-01-11 01:04:52 +03:00
@@ -7443,7 +7443,7 @@ ha_rows check_quick_select(PARAM *param,
     param->is_ror_scan= FALSE;
   
   *mrr_flags= param->force_default_mrr? HA_MRR_USE_DEFAULT_IMPL: 0;
-  *mrr_flags= HA_MRR_NO_ASSOCIATION;
+  *mrr_flags|= HA_MRR_NO_ASSOCIATION;
 
   bool pk_is_clustered= file->primary_key_is_clustered();
   if (index_only && 
diff -Nrup a/sql/set_var.cc b/sql/set_var.cc
--- a/sql/set_var.cc	2007-12-18 12:30:43 +03:00
+++ b/sql/set_var.cc	2008-01-11 01:04:53 +03:00
@@ -3583,8 +3583,6 @@ ulong fix_sql_mode(ulong sql_mode)
 }
 
 
-//psergey-todo: think if we can join this with thd_sql_mode one
-
 bool
 sys_var_thd_optimizer_switch::
 symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
diff -Nrup a/sql/sql_select.cc b/sql/sql_select.cc
--- a/sql/sql_select.cc	2007-12-20 18:00:13 +03:00
+++ b/sql/sql_select.cc	2008-01-11 01:04:53 +03:00
@@ -3213,19 +3213,6 @@ bool convert_subq_to_sj(JOIN *parent_joi
 
   if (subq_pred->left_expr->cols() == 1)
   {
-    /*
-      psergey-insideout-todo: 
-      Figure out if we can just collect a list of items or will need 
-      to wrap them into item-refs instead, like this:
-
-      (and if we do wrap, we will have to use a permanent place to store
-      pointers. (is that one of ref-pointer-array's functions?))
-
-      new Item_direct_view_ref(&subq_lex->context,
-                               subq_lex->ref_pointer_array[0],
-                               (char *)"<no matter>",
-                               (char *)"<list ref>");
-    */
     nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr);
 
     Item *item_eq= new Item_func_eq(subq_pred->left_expr, 
@@ -12254,8 +12241,7 @@ TABLE *create_duplicate_weedout_tmp_tabl
   table->copy_blobs= 1;
   table->in_use= thd;
   table->quick_keys.init();
-  table->covering_keys.init(); //psergey-todo: check if we need to set a bit there 
-  //table->used_keys.init();
+  table->covering_keys.init();
   table->keys_in_use_for_query.init();
 
   table->s= share;
@@ -15423,12 +15409,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,OR
       */
       if (table->covering_keys.is_set(ref_key))
 	usable_keys.intersect(table->covering_keys);
+      if (tab->pre_idx_push_select_cond)
+        tab->select_cond= tab->select->cond= tab->pre_idx_push_select_cond;
       if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
 				       &usable_keys)) < MAX_KEY)
       {
 	/* Found key that can be used to retrieve data in sorted order */
-        if (tab->pre_idx_push_select_cond)
-          tab->select_cond= tab->select->cond= tab->pre_idx_push_select_cond;
 	if (tab->ref.key >= 0)
 	{
           /*
@@ -18654,7 +18640,10 @@ void select_describe(JOIN *join, bool ne
         else if (tab->select && tab->select->quick)
           keyno = tab->select->quick->index;
 
-        tab->table->file->add_explain_extra_info(keyno, &extra);
+        if (keyno != MAX_KEY && keyno == table->file->pushed_idx_cond_keyno &&
+            table->file->pushed_idx_cond)
+          extra.append(STRING_WITH_LEN("; Using index condition"));
+
         if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || 
             quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
             quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
diff -Nrup a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
--- a/storage/innobase/handler/ha_innodb.cc	2007-12-13 15:47:18 +03:00
+++ b/storage/innobase/handler/ha_innodb.cc	2008-01-11 01:04:53 +03:00
@@ -976,12 +976,10 @@ ha_innobase::ha_innobase(handlerton *hto
                      value here because it doesn't matter if we return the
                      HA_DO_INDEX_COND_PUSHDOWN bit from those "early" calls */
   start_of_scan(0),
-  num_write_row(0),
-  ds_mrr((DsMrr_impl::range_check_toggle_func_t)
-         &ha_innobase::toggle_range_check),
-  cond_keyno(MAX_KEY)
+  num_write_row(0)
 {
-  ds_mrr.h= this;
+//  ds_mrr.init(this, table, (DsMrr_impl::range_check_toggle_func_t)
+//                            &ha_innobase::toggle_range_check);
 }
 
 /*************************************************************************
@@ -3127,9 +3125,12 @@ build_template(
 	prebuilt->templ_contains_blob = FALSE;
 
 
-        if (file->active_index == file->cond_keyno && 
-            file->active_index != MAX_KEY && 
-            file->active_index != 0 /* file->primary_key psergey-todo:!*/)
+        /*
+          Setup index condition pushdown (note: we don't need to check if
+          this is a scan on primary key as that is checked in idx_cond_push)
+        */
+        if (file->active_index == file->pushed_idx_cond_keyno && 
+            file->active_index != MAX_KEY)
           do_idx_cond_push= need_second_pass= TRUE;
 
         /* 
@@ -3263,7 +3264,7 @@ skip_field:
           prebuilt->idx_cond_func= NULL;
           prebuilt->n_index_fields= n_requested_fields;
         }
-        file->in_range_read= FALSE;
+       // file->in_range_read= FALSE;
 
 	if (index != clust_index && prebuilt->need_to_access_clustered) {
 		/* Change rec_field_no's to correspond to the clustered index
@@ -3991,7 +3992,8 @@ ha_innobase::index_end(void)
 	int	error	= 0;
 	DBUG_ENTER("index_end");
 	active_index=MAX_KEY;
-        in_range_check_pushed_down= FALSE;
+	in_range_check_pushed_down= FALSE;
+	ds_mrr.dsmrr_close();
 	DBUG_RETURN(error);
 }
 
@@ -4606,6 +4608,10 @@ ha_innobase::position(
 
 	ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
 
+        /*if (ds_mrr.call_position_for != this) {
+                ((ha_innobase*)ds_mrr.call_position_for)->position(record);
+                return;
+        }*/
 	if (prebuilt->clust_index_was_generated) {
 		/* No primary key was defined for the table and we
 		generated the clustered index from row id: the
@@ -6289,10 +6295,10 @@ ha_innobase::extra(
 			reset_template(prebuilt);
 
                         /* Reset index condition pushdown state */
-                        cond_keyno= MAX_KEY;
-                        in_range_read= FALSE;
+                        pushed_idx_cond= FALSE;
+                        pushed_idx_cond_keyno= MAX_KEY;
+                        //in_range_read= FALSE;
                         prebuilt->idx_cond_func= NULL;
-                        cond_keyno= MAX_KEY;
 			break;
 		case HA_EXTRA_NO_KEYREAD:
 			prebuilt->read_just_key = 0;
@@ -6337,11 +6343,10 @@ int ha_innobase::reset()
   }
   reset_template(prebuilt);
   /* Reset index condition pushdown state */
-  cond_keyno= MAX_KEY;
-  in_range_read= FALSE;
+  pushed_idx_cond_keyno= MAX_KEY;
+  pushed_idx_cond= NULL;
+  //in_range_read= FALSE;
   prebuilt->idx_cond_func= NULL;
-
-  cond_keyno= MAX_KEY;
   return 0;
 }
 
@@ -8206,6 +8211,8 @@ ha_rows ha_innobase::multi_range_read_in
                                                  uint *flags, 
                                                  COST_VECT *cost)
 {
+  /* See comments in ha_myisam::multi_range_read_info_const */
+  ds_mrr.init(this, table);
   return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
                                  flags, cost);
 }
@@ -8213,6 +8220,7 @@ ha_rows ha_innobase::multi_range_read_in
 int ha_innobase::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
                           uint *bufsz, uint *flags, COST_VECT *cost)
 {
+  ds_mrr.init(this, table);
   return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 }
 
@@ -8229,12 +8237,12 @@ C_MODE_START
 static my_bool index_cond_func_innodb(void *arg)
 {
   ha_innobase *h= (ha_innobase*)arg;
-  if (h->in_range_read)
+  if (h->end_range) //was: h->in_range_read
   {
-    if (h->compare_key(h->end_range) > 0)
+    if (h->compare_key2(h->end_range) > 0)
       return 2; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->idx_cond->val_int();
+  return (my_bool)h->pushed_idx_cond->val_int();
 }
 
 C_MODE_END
@@ -8244,33 +8252,26 @@ Item *ha_innobase::idx_cond_push(uint ke
 {
   if (keyno_arg != primary_key)
   {
-    cond_keyno= keyno_arg;
-    idx_cond= idx_cond_arg;
-    return NULL; /* Table handler will check the entire condition */
+    pushed_idx_cond_keyno= keyno_arg;
+    pushed_idx_cond= idx_cond_arg;
     in_range_check_pushed_down= TRUE;
+    return NULL; /* Table handler will check the entire condition */
   }
   return idx_cond_arg; /* Table handler will not make any checks */
 }
 
 
-void ha_innobase::add_explain_extra_info(uint keyno, String *extra)
-{
-  if (cond_keyno != MAX_KEY && idx_cond && keyno==cond_keyno)
-    extra->append(STRING_WITH_LEN("; Using index condition"));
-}
-
-
 int ha_innobase::read_range_first(const key_range *start_key,
 		 	        const key_range *end_key,
 			        bool eq_range_arg,
                                 bool sorted /* ignored */)
 {
   int res;
-  if (!eq_range_arg)
-    in_range_read= TRUE;
+  //if (!eq_range_arg)
+    //in_range_read= TRUE;
   res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
-  if (res)
-    in_range_read= FALSE;
+  //if (res)
+  //  in_range_read= FALSE;
   return res;
 }
 
@@ -8278,8 +8279,8 @@ int ha_innobase::read_range_first(const 
 int ha_innobase::read_range_next()
 {
   int res= handler::read_range_next();
-  if (res)
-    in_range_read= FALSE;
+  //if (res)
+  //  in_range_read= FALSE;
   return res;
 }
 
diff -Nrup a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
--- a/storage/innobase/handler/ha_innodb.h	2007-12-13 15:47:18 +03:00
+++ b/storage/innobase/handler/ha_innodb.h	2008-01-11 01:04:53 +03:00
@@ -228,24 +228,6 @@ public:
                             uint *bufsz, uint *flags, COST_VECT *cost);
   DsMrr_impl ds_mrr;
 
-  void add_explain_extra_info(uint keyno, String *extra);
-
-  /* Index Condition Pushdown implementation */
-  Item *idx_cond;   /* The pushed condition. Valid iff cond_keyno != MAX_KEY */
-  uint cond_keyno;  /* The index which the above condition is for */
-
-  /* 
-    TRUE <=> We're reading a range that is not equivalent to
-       "keypart1=const1 AND ... keypartK=constK"
-    if we're reading such range we should check if we've ran out of range
-    before checking the index condition
-  */ 
-  bool in_range_read;
-  void toggle_range_check(bool on)
-  {
-    in_range_read= on;
-  }
-
   int read_range_first(const key_range *start_key, const key_range *end_key,
                        bool eq_range_arg, bool sorted);
   int read_range_next();
diff -Nrup a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
--- a/storage/myisam/ha_myisam.cc	2007-12-13 15:56:22 +03:00
+++ b/storage/myisam/ha_myisam.cc	2008-01-11 01:04:53 +03:00
@@ -532,12 +532,8 @@ ha_myisam::ha_myisam(handlerton *hton, T
                   HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
                   HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT |
                   HA_NEED_READ_RANGE_BUFFER | HA_MRR_CANT_SORT),
-   can_enable_indexes(1),
-   cond_keyno(MAX_KEY),
-   ds_mrr((DsMrr_impl::range_check_toggle_func_t)&ha_myisam::toggle_range_check)
-{
-  ds_mrr.h= this;
-}
+   can_enable_indexes(1)
+{}
 
 handler *ha_myisam::clone(MEM_ROOT *mem_root)
 {
@@ -1450,12 +1446,13 @@ C_MODE_START
 my_bool index_cond_func_myisam(void *arg)
 {
   ha_myisam *h= (ha_myisam*)arg;
-  if (h->in_range_read)
+  /*if (h->in_range_read)*/
+  if (h->end_range)
   {
-    if (h->compare_key(h->end_range) > 0)
+    if (h->compare_key2(h->end_range) > 0)
       return 2; /* caller should return HA_ERR_END_OF_FILE already */
   }
-  return (my_bool)h->idx_cond->val_int();
+  return (my_bool)h->pushed_idx_cond->val_int();
 }
 
 C_MODE_END
@@ -1464,8 +1461,8 @@ C_MODE_END
 int ha_myisam::index_init(uint idx, bool sorted)
 { 
   active_index=idx;
-  in_range_read= FALSE;
-  if (cond_keyno == idx)
+  //in_range_read= FALSE;
+  if (pushed_idx_cond_keyno == idx)
     mi_set_index_cond_func(file, index_cond_func_myisam, this);
   return 0; 
 }
@@ -1474,8 +1471,10 @@ int ha_myisam::index_init(uint idx, bool
 int ha_myisam::index_end()
 {
   active_index=MAX_KEY;
+  //pushed_idx_cond_keyno= MAX_KEY;
   mi_set_index_cond_func(file, NULL, 0);
   in_range_check_pushed_down= FALSE;
+  ds_mrr.dsmrr_close();
   return 0; 
 }
 
@@ -1570,13 +1569,13 @@ int ha_myisam::read_range_first(const ke
                                 bool sorted /* ignored */)
 {
   int res;
-  if (!eq_range_arg)
-    in_range_read= TRUE;
+  //if (!eq_range_arg)
+  //  in_range_read= TRUE;
 
   res= handler::read_range_first(start_key, end_key, eq_range_arg, sorted);
 
-  if (res)
-    in_range_read= FALSE;
+  //if (res)
+  //  in_range_read= FALSE;
   return res;
 }
 
@@ -1584,8 +1583,8 @@ int ha_myisam::read_range_first(const ke
 int ha_myisam::read_range_next()
 {
   int res= handler::read_range_next();
-  if (res)
-    in_range_read= FALSE;
+  //if (res)
+  //  in_range_read= FALSE;
   return res;
 }
 
@@ -1618,6 +1617,7 @@ int ha_myisam::rnd_pos(uchar *buf, uchar
   return error;
 }
 
+
 void ha_myisam::position(const uchar *record)
 {
   my_off_t row_position= mi_position(file);
@@ -1701,7 +1701,8 @@ int ha_myisam::extra(enum ha_extra_funct
 
 int ha_myisam::reset(void)
 {
-  cond_keyno= MAX_KEY;
+  pushed_idx_cond= NULL;
+  pushed_idx_cond_keyno= MAX_KEY;
   mi_set_index_cond_func(file, NULL, 0);
   return mi_reset(file);
 }
@@ -1984,6 +1985,12 @@ ha_rows ha_myisam::multi_range_read_info
                                                uint n_ranges, uint *bufsz,
                                                uint *flags, COST_VECT *cost)
 {
+  /*
+    This call is here because there is no location where this->table would
+    already be known.
+    TODO: consider moving it into some per-query initialization call.
+  */
+  ds_mrr.init(this, table);
   return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
                                  flags, cost);
 }
@@ -1991,6 +1998,7 @@ ha_rows ha_myisam::multi_range_read_info
 int ha_myisam::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
                                      uint *bufsz, uint *flags, COST_VECT *cost)
 {
+  ds_mrr.init(this, table);
   return ds_mrr.dsmrr_info(keyno, n_ranges, keys, bufsz, flags, cost);
 }
 
@@ -2002,18 +2010,12 @@ int ha_myisam::multi_range_read_info(uin
 
 Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
 {
-  cond_keyno= keyno_arg;
-  idx_cond= idx_cond_arg;
+  pushed_idx_cond_keyno= keyno_arg;
+  pushed_idx_cond= idx_cond_arg;
   in_range_check_pushed_down= TRUE;
-  if (active_index == cond_keyno)
+  if (active_index == pushed_idx_cond_keyno)
     mi_set_index_cond_func(file, index_cond_func_myisam, this);
   return NULL;
-}
-
-void ha_myisam::add_explain_extra_info(uint keyno, String *extra)
-{
-  if (cond_keyno != MAX_KEY && idx_cond && keyno==cond_keyno)
-    extra->append(STRING_WITH_LEN("; Using index condition"));
 }
 
 
diff -Nrup a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
--- a/storage/myisam/ha_myisam.h	2007-11-15 23:03:43 +03:00
+++ b/storage/myisam/ha_myisam.h	2008-01-11 01:04:54 +03:00
@@ -164,18 +164,9 @@ public:
   
   /* Index condition pushdown implementation */
   Item *idx_cond_push(uint keyno, Item* idx_cond);
-
-  void add_explain_extra_info(uint keyno, String *extra);
 private:
-  uint cond_keyno;
-  Item *idx_cond;
   DsMrr_impl ds_mrr;
   key_map keys_with_parts;
-  bool in_range_read;
-  void toggle_range_check(bool on)
-  {
-    in_range_read= on;
-  }
   friend my_bool index_cond_func_myisam(void *arg);
 };
 
diff -Nrup a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c
--- a/storage/myisam/mi_key.c	2007-08-26 15:31:22 +04:00
+++ b/storage/myisam/mi_key.c	2008-01-11 01:04:54 +03:00
@@ -238,36 +238,6 @@ uint _mi_pack_key(register MI_INFO *info
     uint char_length;
     uchar *pos;
     CHARSET_INFO *cs=keyseg->charset;
-    /* psergey: we probably don't need all this as we will be cloning
-     handlers instead*/
-#if 0     
-    if (!type)
-    {
-      /*
-        Decode the ROWID value back to to file pointer. The if-check below is
-        needed to distinguish between the cases of 
-          a) when this function is called with k_length=USE_WHOLE_KEY (the
-             packed tuple doesn't have rowid), and 
-          b) when this function is called with tuple+rowid
-
-        The right check ought to be "k_length == length" but sergefp has
-        discovered that rowid key segment length may be inequal to 
-        ha_myisam->ref_length, which forces us to use the below ugly check:
-      */
-      if (k_length > 0 && k_length < MI_MAX_KEY_LENGTH)
-      {
-        my_off_t rowid;
-        pos=old;
-        rowid= my_get_ptr(pos, k_length);
-        _mi_dpointer(info, key, rowid);
-        pos+=length;
-        key+= keyseg->length;
-        k_length= 0;
-        keyseg++;
-      }
-      break;
-    }
-#endif 
     keypart_map>>= 1;
     if (keyseg->null_bit)
     {
diff -Nrup a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c
--- a/storage/myisam/mi_rkey.c	2007-08-26 15:31:22 +04:00
+++ b/storage/myisam/mi_rkey.c	2008-01-11 01:04:54 +03:00
@@ -30,7 +30,6 @@ int mi_rkey(MI_INFO *info, uchar *buf, i
   HA_KEYSEG *last_used_keyseg;
   uint pack_key_length, use_key_length, nextflag;
   uint myisam_search_flag;
-  my_bool key_tuple_has_rowid= FALSE;
   int res= 0;
   DBUG_ENTER("mi_rkey");
   DBUG_PRINT("enter", ("base: 0x%lx  buf: 0x%lx  inx: %d  search_flag: %d",
@@ -62,13 +61,6 @@ int mi_rkey(MI_INFO *info, uchar *buf, i
     key_buff=info->lastkey+info->s->base.max_key_length;
     pack_key_length=_mi_pack_key(info,(uint) inx, key_buff, (uchar*) key,
 				 keypart_map, &last_used_keyseg);
-    /* psergey-merge: this is not needed:
-    if (last_used_keyseg > (info->s->keyinfo[inx].seg +
-                           info->s->keyinfo[inx].keysegs))
-    {
-      key_tuple_has_rowid= TRUE;
-      last_used_keyseg--;
-    } */
     /* Save packed_key_length for use by the MERGE engine. */
     info->pack_key_length= pack_key_length;
     info->last_used_keyseg= (uint16) (last_used_keyseg -
@@ -102,11 +94,6 @@ int mi_rkey(MI_INFO *info, uchar *buf, i
   case HA_KEY_ALG_BTREE:
   default:
     myisam_search_flag= myisam_read_vec[search_flag];
-    if (key_tuple_has_rowid)
-    {
-      /* Fiddle with flags so ha_key_cmp compares the rowid, too */
-      myisam_search_flag &= ~(SEARCH_FIND | SEARCH_NO_FIND);
-    }
     if (!_mi_search(info, keyinfo, key_buff, use_key_length,
                     myisam_search_flag, info->s->state.key_root[inx]))
     {
Thread
bk commit into 6.0 tree (sergefp:1.2774) BUG#30622Sergey Petrunia10 Jan