MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:igor Date:July 1 2007 10:33pm
Subject:bk commit into 5.0 tree (igor:1.2513) BUG#25798
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of igor. When igor 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, 2007-07-01 15:33:28-07:00, igor@stripped +5 -0
  Fixed bug #25798.
  This bug may manifest itself not only with the queries for which
  the index-merge access method is chosen. It also may display
  itself for queries with DISTINCT.
  
  The bug was in how the Unique::get method used the merge_buffers
  function. To compare elements in the the queue employed by
  merge_buffers() it must use the buffpek_compare function rather
  than the function for binary comparison. 

  mysql-test/r/innodb_mysql.result@stripped, 2007-07-01 15:33:21-07:00, igor@stripped +51 -0
    Added a test case for bug #25798.

  mysql-test/t/innodb_mysql.test@stripped, 2007-07-01 15:33:22-07:00, igor@stripped +54 -0
    Added a test case for bug #25798.

  sql/filesort.cc@stripped, 2007-07-01 15:33:22-07:00, igor@stripped +14 -4
    Fixed bug #25798.
    The function merge_buffers() when called from the Uniques::get method
    must use function buffpek_compare to compare elements in the queue it
    employs. The pointer to buffpek_compare and the info for the function
    that compares sorted records are passed to merge_buffers through certain 
    designated fields of the SORTPARAM structure.

  sql/sql_sort.h@stripped, 2007-07-01 15:33:22-07:00, igor@stripped +9 -0
    Fixed bug #25798.
    Added fields to the SORTPARAM structure to be used in the function 
    merge_buffers when called by the Uniques::get method. 

  sql/uniques.cc@stripped, 2007-07-01 15:33:22-07:00, igor@stripped +6 -7
    Fixed bug 25798.
    The function merge_buffers() when called from the Uniques::get method
    must use function buffpek_compare to compare elements in the queue it
    employes.

diff -Nrup a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result
--- a/mysql-test/r/innodb_mysql.result	2007-06-25 00:44:51 -07:00
+++ b/mysql-test/r/innodb_mysql.result	2007-07-01 15:33:21 -07:00
@@ -676,4 +676,55 @@ INSERT INTO t1 VALUES (1);
 switch to connection default
 SET AUTOCOMMIT=default;
 DROP TABLE t1,t2;
+CREATE TABLE t1 (
+id int NOT NULL auto_increment PRIMARY KEY,
+b int NOT NULL,
+c datetime NOT NULL,
+INDEX idx_b(b),
+INDEX idx_c(c)
+) ENGINE=InnoDB;
+CREATE TABLE t2 (
+b int NOT NULL auto_increment PRIMARY KEY,
+c datetime NOT NULL
+) ENGINE= MyISAM;
+INSERT INTO t2(c) VALUES ('2007-01-01');
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+UPDATE t2 SET c='2007-01-02';
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+UPDATE t2 SET c='2007-01-03';
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+set @@sort_buffer_size=8192;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+3072
+EXPLAIN 
+SELECT COUNT(*) FROM t1 
+WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	idx_b,idx_c	NULL	NULL	NULL	3263	Using where
+SELECT COUNT(*) FROM t1 
+WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+COUNT(*)
+3072
+EXPLAIN 
+SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c) 
+WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	index_merge	idx_b,idx_c	idx_c,idx_b	8,4	NULL	3262	Using sort_union(idx_c,idx_b); Using where
+SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c)
+WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+COUNT(*)
+3072
+set @@sort_buffer_size=default;
+DROP TABLE t1,t2;
 End of 5.0 tests
diff -Nrup a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test
--- a/mysql-test/t/innodb_mysql.test	2007-06-25 00:44:51 -07:00
+++ b/mysql-test/t/innodb_mysql.test	2007-07-01 15:33:22 -07:00
@@ -670,5 +670,59 @@ DISCONNECT c1;
 DISCONNECT c2;
 DROP TABLE t1,t2;
 
+#
+# Bug #25798: a query with forced index merge returns wrong result 
+#
+
+CREATE TABLE t1 (
+  id int NOT NULL auto_increment PRIMARY KEY,
+  b int NOT NULL,
+  c datetime NOT NULL,
+  INDEX idx_b(b),
+  INDEX idx_c(c)
+) ENGINE=InnoDB;
+
+CREATE TABLE t2 (
+  b int NOT NULL auto_increment PRIMARY KEY,
+  c datetime NOT NULL
+) ENGINE= MyISAM;
+
+INSERT INTO t2(c) VALUES ('2007-01-01');
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+INSERT INTO t2(c) SELECT c FROM t2;
+
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+UPDATE t2 SET c='2007-01-02';
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+UPDATE t2 SET c='2007-01-03';
+INSERT INTO t1(b,c) SELECT b,c FROM t2;
+
+set @@sort_buffer_size=8192;
+
+SELECT COUNT(*) FROM t1;
+
+EXPLAIN 
+SELECT COUNT(*) FROM t1 
+  WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+SELECT COUNT(*) FROM t1 
+  WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+
+EXPLAIN 
+SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c) 
+  WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c)
+  WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1;
+
+set @@sort_buffer_size=default;
+
+DROP TABLE t1,t2;
 
 --echo End of 5.0 tests
diff -Nrup a/sql/filesort.cc b/sql/filesort.cc
--- a/sql/filesort.cc	2007-06-07 22:35:28 -07:00
+++ b/sql/filesort.cc	2007-07-01 15:33:22 -07:00
@@ -1052,6 +1052,7 @@ int merge_buffers(SORTPARAM *param, IO_C
   BUFFPEK *buffpek;
   QUEUE queue;
   qsort2_cmp cmp;
+  void *first_cmp_arg;
   volatile THD::killed_state *killed= &current_thd->killed;
   THD::killed_state not_killable;
   DBUG_ENTER("merge_buffers");
@@ -1077,9 +1078,18 @@ int merge_buffers(SORTPARAM *param, IO_C
   /* The following will fire if there is not enough space in sort_buffer */
   DBUG_ASSERT(maxcount!=0);
   
+  if (param->unique_buff)
+  {
+    cmp= param->compare;
+    first_cmp_arg= (void *) &param->cmp_context;
+  }
+  else
+  {
+    cmp= get_ptr_compare(sort_length);
+    first_cmp_arg= (void*) &sort_length;
+  }
   if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
-                 (queue_compare) (cmp= get_ptr_compare(sort_length)),
-                 (void*) &sort_length))
+                 (queue_compare) cmp, first_cmp_arg))
     DBUG_RETURN(1);                                /* purecov: inspected */
   for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
   {
@@ -1132,7 +1142,7 @@ int merge_buffers(SORTPARAM *param, IO_C
       buffpek= (BUFFPEK*) queue_top(&queue);
       if (cmp)                                        // Remove duplicates
       {
-        if (!(*cmp)(&sort_length, &(param->unique_buff),
+        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
                     (uchar**) &buffpek->key))
               goto skip_duplicate;
             memcpy(param->unique_buff, (uchar*) buffpek->key, rec_length);
@@ -1184,7 +1194,7 @@ int merge_buffers(SORTPARAM *param, IO_C
   */
   if (cmp)
   {
-    if (!(*cmp)(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
+    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
     {
       buffpek->key+= rec_length;         // Remove duplicate
       --buffpek->mem_count;
diff -Nrup a/sql/sql_sort.h b/sql/sql_sort.h
--- a/sql/sql_sort.h	2006-12-23 11:04:27 -08:00
+++ b/sql/sql_sort.h	2007-07-01 15:33:22 -07:00
@@ -50,6 +50,12 @@ typedef struct st_buffpek {		/* Struktur
   ulong max_keys;			/* Max keys in buffert */
 } BUFFPEK;
 
+struct BUFFPEK_COMPARE_CONTEXT
+{
+  qsort_cmp2 key_compare;
+  void *key_compare_arg;
+};
+
 typedef struct st_sort_param {
   uint rec_length;          /* Length of sorted records */
   uint sort_length;			/* Length of sorted columns */
@@ -65,6 +71,9 @@ typedef struct st_sort_param {
   uchar *unique_buff;
   bool not_killable;
   char* tmp_buffer;
+  /* The fields below are used only by Unique class */
+  qsort2_cmp compare;
+  BUFFPEK_COMPARE_CONTEXT cmp_context;
 } SORTPARAM;
 
 
diff -Nrup a/sql/uniques.cc b/sql/uniques.cc
--- a/sql/uniques.cc	2006-12-23 11:04:28 -08:00
+++ b/sql/uniques.cc	2007-07-01 15:33:22 -07:00
@@ -361,17 +361,12 @@ Unique::reset()
 }
 
 /*
-  The comparison function, passed to queue_init() in merge_walk() must
+  The comparison function, passed to queue_init() in merge_walk() and in
+  merge_buffers() when the latter is called from Uniques::get() must
   use comparison function of Uniques::tree, but compare members of struct
   BUFFPEK.
 */
 
-struct BUFFPEK_COMPARE_CONTEXT
-{
-  qsort_cmp2 key_compare;
-  void *key_compare_arg;
-};
-
 C_MODE_START
 
 static int buffpek_compare(void *arg, byte *key_ptr1, byte *key_ptr2)
@@ -629,6 +624,10 @@ bool Unique::get(TABLE *table)
     return 1;
   sort_param.unique_buff= sort_buffer+(sort_param.keys*
 				       sort_param.sort_length);
+
+  sort_param.compare= (qsort2_cmp) buffpek_compare;
+  sort_param.cmp_context.key_compare= tree.compare;
+  sort_param.cmp_context.key_compare_arg= tree.custom_arg;
 
   /* Merge the buffers to one file, removing duplicates */
   if (merge_many_buff(&sort_param,sort_buffer,file_ptr,&maxbuffer,&file))
Thread
bk commit into 5.0 tree (igor:1.2513) BUG#25798igor1 Jul