MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Frazer Clement Date:March 16 2009 6:09pm
Subject:bzr commit into mysql-5.1-telco-6.2 branch (frazer:2877) Bug#42857
View as plain text  
#At file:///home/frazer/bzr/mysql-5.1-telco-6.2/

 2877 Frazer Clement	2009-03-16
      Bug#42857 Got error 4541 Indexbound has no bound information from NDBCLUSTER
      
      MySQLD calls NdbIndexScanOperation::setBound() with an empty ('open range')
      IndexBound with the query given.
      
      setBound() is modified to handle this by inserting an 'open range' bound
      which is actually a lower bound of LE NULL on the first column in the index.
      
      The example testcase is added to ndb_index_ordered.
      modified:
        mysql-test/suite/ndb/r/ndb_index_ordered.result
        mysql-test/suite/ndb/t/ndb_index_ordered.test
        storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp
        storage/ndb/src/ndbapi/NdbScanOperation.cpp
        storage/ndb/src/ndbapi/ndberror.c

=== modified file 'mysql-test/suite/ndb/r/ndb_index_ordered.result'
--- a/mysql-test/suite/ndb/r/ndb_index_ordered.result	2007-06-27 12:28:02 +0000
+++ b/mysql-test/suite/ndb/r/ndb_index_ordered.result	2009-03-16 18:08:48 +0000
@@ -852,3 +852,12 @@ PRIMARY KEY (DishID)
 create index i on nationaldish(countrycode,calories) using hash;
 ERROR 42000: Table 'nationaldish' uses an extension that doesn't exist in this MySQL version
 drop table nationaldish;
+drop table if exists t1;
+Warnings:
+Note	1051	Unknown table 't1'
+create table t1(c1 varchar(20) primary key, c2 char(20)) engine=ndbcluster;
+insert into t1(c1,c2) values ('ddd','jg');
+select * from t1 where  (c2 < 'b' AND c1 <> 'g')  OR  (c2 <> 'a' AND c1 <> 'd');
+c1	c2
+ddd	jg
+drop table t1;

=== modified file 'mysql-test/suite/ndb/t/ndb_index_ordered.test'
--- a/mysql-test/suite/ndb/t/ndb_index_ordered.test	2007-07-04 20:38:53 +0000
+++ b/mysql-test/suite/ndb/t/ndb_index_ordered.test	2009-03-16 18:08:48 +0000
@@ -478,3 +478,12 @@ create table nationaldish (DishID int(10
 create index i on nationaldish(countrycode,calories) using hash;
 
 drop table nationaldish;
+
+# bug#42857 Got error 4541 -IndexBound has no bound information- from NDBCLUSTER
+# Test that query returns results expected
+
+drop table if exists t1;
+create table t1(c1 varchar(20) primary key, c2 char(20)) engine=ndbcluster;
+insert into t1(c1,c2) values ('ddd','jg');
+select * from t1 where  (c2 < 'b' AND c1 <> 'g')  OR  (c2 <> 'a' AND c1 <> 'd');
+drop table t1;

=== modified file 'storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp'
--- a/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp	2008-08-07 06:24:52 +0000
+++ b/storage/ndb/include/ndbapi/NdbIndexScanOperation.hpp	2009-03-16 18:08:48 +0000
@@ -266,6 +266,7 @@ private:
                              Uint32 column_index,
                              const char *row,
                              Uint32 bound_type);
+  int insert_open_bound(const NdbRecord* key_record);
 
   virtual int equal_impl(const NdbColumnImpl*, const char*);
   virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);

=== modified file 'storage/ndb/src/ndbapi/NdbScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2009-02-10 08:05:16 +0000
+++ b/storage/ndb/src/ndbapi/NdbScanOperation.cpp	2009-03-16 18:08:48 +0000
@@ -611,14 +611,12 @@ NdbIndexScanOperation::setBound(const Nd
     return -1;
   }
 
-  if (((bound.low_key == NULL) && (bound.high_key == NULL)) ||
-      ((bound.low_key_count == 0) && (bound.high_key_count == 0)))
-  {
-    /* IndexBound passed has no bound information */
-    setErrorCodeAbort(4541);
-    return -1;
-  }
-
+  /* Has the user supplied an open range (no bounds)? */
+  const bool openRange= (((bound.low_key == NULL) && 
+                          (bound.high_key == NULL)) ||
+                         ((bound.low_key_count == 0) && 
+                          (bound.high_key_count == 0)));
+  
   m_num_bounds++;
 
   if (unlikely((m_num_bounds > 1) &&
@@ -670,28 +668,39 @@ NdbIndexScanOperation::setBound(const Nd
     return -1;
   }
 
-  for (j= 0; j<key_count; j++)
+  if (likely(!openRange))
   {
-    Uint32 bound_type;
-    /* If key is part of lower bound */
-    if (bound.low_key && j<bound.low_key_count)
-    {
-      /* Inclusive if defined, or matching rows can include this value */
-      bound_type= bound.low_inclusive  || j+1 < bound.low_key_count ?
-        BoundLE : BoundLT;
-      ndbrecord_insert_bound(key_record, key_record->key_indexes[j],
-                             bound.low_key, bound_type);
-    }
-    /* If key is part of upper bound */
-    if (bound.high_key && j<bound.high_key_count)
-    {
-      /* Inclusive if defined, or matching rows can include this value */
-      bound_type= bound.high_inclusive  || j+1 < bound.high_key_count ?
-        BoundGE : BoundGT;
-      ndbrecord_insert_bound(key_record, key_record->key_indexes[j],
-                             bound.high_key, bound_type);
+    for (j= 0; j<key_count; j++)
+    {
+      Uint32 bound_type;
+      /* If key is part of lower bound */
+      if (bound.low_key && j<bound.low_key_count)
+      {
+        /* Inclusive if defined, or matching rows can include this value */
+        bound_type= bound.low_inclusive  || j+1 < bound.low_key_count ?
+          BoundLE : BoundLT;
+        ndbrecord_insert_bound(key_record, key_record->key_indexes[j],
+                               bound.low_key, bound_type);
+      }
+      /* If key is part of upper bound */
+      if (bound.high_key && j<bound.high_key_count)
+      {
+        /* Inclusive if defined, or matching rows can include this value */
+        bound_type= bound.high_inclusive  || j+1 < bound.high_key_count ?
+          BoundGE : BoundGT;
+        ndbrecord_insert_bound(key_record, key_record->key_indexes[j],
+                               bound.high_key, bound_type);
+      }
     }
   }
+  else
+  {
+    /* Open range - all rows must be returned.
+     * To encode this, we'll request all rows where the first
+     * key column value is >= NULL
+     */
+    insert_open_bound(key_record);
+  }
 
   /* Set the length of this bound
    * Length = bound end - bound start
@@ -730,8 +739,11 @@ NdbIndexScanOperation::setBound(const Nd
                                     bound.low_key,
                                     bound.high_key,
                                     distkey_min))
+    {
+      assert(! openRange);
       setDistKeyFromRange(key_record, m_attribute_record,
                           bound.low_key, distkey_min);
+    }
   }
   return 0;
 } // ::setBound();
@@ -2987,6 +2999,32 @@ NdbIndexScanOperation::ndbrecord_insert_
   return 0;
 }
 
+int
+NdbIndexScanOperation::insert_open_bound(const NdbRecord* key_record)
+{
+  /* We want to insert an open bound into a scan
+   * This is done by requesting all rows with first key column
+   * >= NULL (so, confusingly, bound is <= NULL)
+   * Sending this as bound info for an open bound allows us to 
+   * also send the range number etc so that MRR scans can include
+   * open ranges.
+   * Note that MRR scans with open ranges are an inefficient use of
+   * MRR.  Really the application should realise that all rows are
+   * being processed and only fetch them once.
+   */
+  const NdbRecord::Attr *column= &key_record->columns[0];
+  
+  /* Create NULL attribute header. */
+  AttributeHeader ah(column->index_attrId, 0);
+  
+  Uint32 buf[2] = { NdbIndexScanOperation::BoundLE, ah.m_value };
+  insertBOUNDS(buf, 2);
+  
+  theTupKeyLen+= 2;
+  
+  return 0;
+}
+
 /* IndexScan readTuples - part of old scan API
  * This call does the minimum amount of validation and state
  * storage possible.  Most of the scan initialisation is done

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2009-03-13 07:51:21 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2009-03-16 18:08:48 +0000
@@ -589,7 +589,7 @@ ErrorBundle ErrorCodes[] = {
   { 4538, DMEC, AE, "NdbInterpretedCode instruction requires that table is set" },
   { 4539, DMEC, AE, "NdbInterpretedCode not supported for operation type" },
   { 4540, DMEC, AE, "Attempt to pass an Index column to createRecord.  Use base table columns only" },
-  { 4541, DMEC, AE, "IndexBound has no bound information" },
+  { 4541, DMEC, AE, "IndexBound has no bound information" }, // No longer generated
 
   { 4200, DMEC, AE, "Status Error when defining an operation" },
   { 4201, DMEC, AE, "Variable Arrays not yet supported" },

Thread
bzr commit into mysql-5.1-telco-6.2 branch (frazer:2877) Bug#42857Frazer Clement16 Mar