List:Internals« Previous MessageNext Message »
From:Martin Skold Date:May 18 2005 12:32pm
Subject:bk commit into 5.0 tree (mskold:1.1953)
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of marty. When marty 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
  1.1953 05/05/18 14:32:05 mskold@stripped +4 -0
  Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions

  sql/ha_ndbcluster.h
    1.83 05/05/18 14:31:45 mskold@stripped +33 -3
    Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions

  sql/ha_ndbcluster.cc
    1.188 05/05/18 14:31:45 mskold@stripped +728 -510
    Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions

  mysql-test/t/ndb_condition_pushdown.test
    1.13 05/05/18 14:31:45 mskold@stripped +296 -0
    Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions

  mysql-test/r/ndb_condition_pushdown.result
    1.12 05/05/18 14:31:45 mskold@stripped +309 -1
    Added support for BETWEEN and IN in condition pushdown to ndbcluster by rewriting them as AND and OR expressions

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	mskold
# Host:	blowfish.ndb.mysql.com
# Root:	/usr/local/home/marty/MySQL/mysql-5.0

--- 1.187/sql/ha_ndbcluster.cc	Sun May  8 22:41:59 2005
+++ 1.188/sql/ha_ndbcluster.cc	Wed May 18 14:31:45 2005
@@ -6184,572 +6184,784 @@
       context->supported= FALSE;
       break;
     }
-
+    
     DBUG_VOID_RETURN;
   }
   
   if (context->supported)
   {
-    Ndb_cond_stack *ndb_stack= context->stack_ptr;
-    Ndb_cond *prev_cond= context->cond_ptr;
-    Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond();
-    if (!ndb_stack->ndb_cond)
-      ndb_stack->ndb_cond= curr_cond;
-    curr_cond->prev= prev_cond;
-    if (prev_cond) prev_cond->next= curr_cond;
-
-    // Check for end of AND/OR expression
-    if (!item)
+    Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+    const Item_func *func_item;
+    // Check if we are rewriting some unsupported function call
+    if (rewrite_context &&
+        (func_item= rewrite_context->func_item) &&
+        rewrite_context->count++ == 0)
     {
-      // End marker for condition group
-      DBUG_PRINT("info", ("End of condition group"));
-      curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
-    }
-    else
-      switch(item->type()) {
-      case(Item::FIELD_ITEM): {
-        Item_field *field_item= (Item_field *) item;
-        Field *field= field_item->field;
-        enum_field_types type= field->type();
+      switch(func_item->functype()) {
+      case(Item_func::BETWEEN):
         /*
-          Check that the field is part of the table of the handler
-          instance and that we expect a field with of this result type.
+          Rewrite 
+          <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
+          to <field>|<const> > <const1>|<field1> AND 
+          <field>|<const> < <const2>|<field2>
+          or actually in prefix format
+          BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), 
+          LT(<field>|<const>, <const2>|<field2>), END()
         */
-        if (context->table == field->table)
-        {       
-          const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
-          DBUG_PRINT("info", ("FIELD_ITEM"));
-          DBUG_PRINT("info", ("table %s", tab->getName()));
-          DBUG_PRINT("info", ("column %s", field->field_name));
-          DBUG_PRINT("info", ("result type %d", field->result_type()));
-          
-          // Check that we are expecting a field and with the correct
-          // result type
-          if(context->expecting(Item::FIELD_ITEM) &&
-             (context->expecting_field_result(field->result_type()) ||
-              // Date and year can be written as strings
-              (type == MYSQL_TYPE_TIME ||
-               type == MYSQL_TYPE_DATE || 
-               type == MYSQL_TYPE_YEAR ||
-               type == MYSQL_TYPE_DATETIME)
-              ? context->expecting_field_result(STRING_RESULT) : true)
-             // Bit fields no yet supported in scan filter
-             && type != MYSQL_TYPE_BIT)
-          {
-            const NDBCOL *col= tab->getColumn(field->field_name);
-            DBUG_ASSERT(col);
-            curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo());
-            context->dont_expect(Item::FIELD_ITEM);
-            context->expect_no_field_result();
-            if (context->expect_mask)
-            {
-              // We have not seen second argument yet
-              if (type == MYSQL_TYPE_TIME ||
-                  type == MYSQL_TYPE_DATE || 
-                  type == MYSQL_TYPE_YEAR ||
-                  type == MYSQL_TYPE_DATETIME)
-              {
-                context->expect_only(Item::STRING_ITEM);
-                context->expect(Item::INT_ITEM);
-              }
-              else
-                switch(field->result_type()) {
-                case(STRING_RESULT):
-                  // Expect char string or binary string
-                  context->expect_only(Item::STRING_ITEM);
-                  context->expect(Item::VARBIN_ITEM);
-                  context->expect_collation(field_item->collation.collation);
-                  break;
-                case(REAL_RESULT):
-                  context->expect_only(Item::REAL_ITEM);
-                  context->expect(Item::DECIMAL_ITEM);
-                  break;
-                case(INT_RESULT):
-                  context->expect_only(Item::INT_ITEM);
-                  context->expect(Item::VARBIN_ITEM);
-                  break;
-                case(DECIMAL_RESULT):
-                  context->expect_only(Item::DECIMAL_ITEM);
-                  context->expect(Item::REAL_ITEM);
-                  break;
-                default:
-                  break;
-                }    
+      case(Item_func::IN_FUNC): {
+        /*
+          Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
+          to <field>|<const> = <const1>|<field1> OR 
+          <field> = <const2>|<field2> ...
+          or actually in prefix format
+          BEGIN(OR) EQ(<field>|<const>, <const1><field1>), 
+          EQ(<field>|<const>, <const2>|<field2>), ... END()
+          Each part of the disjunction is added for each call
+          to ndb_serialize_cond and end of rewrite statement 
+          is wrapped in end of ndb_serialize_cond
+        */
+        if (context->expecting(item->type()))
+        {
+          // This is the <field>|<const> item, save it in the rewrite context
+          rewrite_context->left_hand_item= item;
+          if (item->type() == Item::FUNC_ITEM)
+          {
+            Item_func *func_item= (Item_func *) item;
+            if (func_item->functype() == Item_func::UNKNOWN_FUNC &&
+                func_item->const_item())
+            {
+              // Skip any arguments since we will evaluate function instead
+              DBUG_PRINT("info", ("Skip until end of arguments marker"));
+              context->skip= func_item->argument_count();
             }
             else
             {
-              // Expect another logical expression
-              context->expect_only(Item::FUNC_ITEM);
-              context->expect(Item::COND_ITEM);
-              // Check that field and string constant collations are the same
-              if ((field->result_type() == STRING_RESULT) &&
-                  !context->expecting_collation(item->collation.collation))
-              {
-                DBUG_PRINT("info", ("Found non-matching collation %s",  
-                                    item->collation.collation->name)); 
-                context->supported= FALSE;                
-              }
+              DBUG_PRINT("info", ("Found unsupported functional expression in BETWEEN|IN"));
+              context->supported= FALSE;
+              DBUG_VOID_RETURN;
+              
             }
-            break;
           }
         }
-        DBUG_PRINT("info", ("Was not expecting field of type %u",
-                            field->result_type()));
-        context->supported= FALSE;
-        break;
-      }
-      case(Item::FUNC_ITEM): {
-        Item_func *func_item= (Item_func *) item;
-        // Check that we expect a function or functional expression here
-        if (context->expecting(Item::FUNC_ITEM) || 
-            func_item->functype() == Item_func::UNKNOWN_FUNC)
-          context->expect_nothing();
         else
         {
-          // Did not expect function here
+          // Non-supported BETWEEN|IN expression
+          DBUG_PRINT("info", ("Found unexpected item of type %u in BETWEEN|IN",
+                              item->type()));
           context->supported= FALSE;
-          break;
+          DBUG_VOID_RETURN;
         }
-
+        break;
+      }
+      default:
+        context->supported= FALSE;
+        break;
+      }
+      DBUG_VOID_RETURN;
+    }
+    else
+    {
+      Ndb_cond_stack *ndb_stack= context->stack_ptr;
+      Ndb_cond *prev_cond= context->cond_ptr;
+      Ndb_cond *curr_cond= context->cond_ptr= new Ndb_cond();
+      if (!ndb_stack->ndb_cond)
+        ndb_stack->ndb_cond= curr_cond;
+      curr_cond->prev= prev_cond;
+      if (prev_cond) prev_cond->next= curr_cond;
+    // Check if we are rewriting some unsupported function call
+      if (context->rewrite_stack)
+      {
+        Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+        const Item_func *func_item= rewrite_context->func_item;
         switch(func_item->functype()) {
-        case(Item_func::EQ_FUNC): {
+        case(Item_func::BETWEEN): {
+        /*
+          Rewrite 
+          <field>|<const> BETWEEN <const1>|<field1> AND <const2>|<field2>
+          to <field>|<const> > <const1>|<field1> AND 
+          <field>|<const> < <const2>|<field2>
+          or actually in prefix format
+          BEGIN(AND) GT(<field>|<const>, <const1>|<field1>), 
+          LT(<field>|<const>, <const2>|<field2>), END()
+        */
+          if (rewrite_context->count == 2)
+          {
+            // Lower limit of BETWEEN
+            DBUG_PRINT("info", ("GE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(Item_func::GE_FUNC, 2);
+          }
+          else if (rewrite_context->count == 3)
+          {
+            // Upper limit of BETWEEN
+            DBUG_PRINT("info", ("LE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(Item_func::LE_FUNC, 2);
+          }
+          else
+          {
+            // Illegal BETWEEN expression
+            DBUG_PRINT("info", ("Illegal BETWEEN expression"));
+            context->supported= FALSE;
+            DBUG_VOID_RETURN;
+          }
+          break;
+        }
+        case(Item_func::IN_FUNC): {
+          /*
+            Rewrite <field>|<const> IN(<const1>|<field1>, <const2>|<field2>,..)
+            to <field>|<const> = <const1>|<field1> OR 
+            <field> = <const2>|<field2> ...
+            or actually in prefix format
+            BEGIN(OR) EQ(<field>|<const>, <const1><field1>), 
+            EQ(<field>|<const>, <const2>|<field2>), ... END()
+            Each part of the disjunction is added for each call
+            to ndb_serialize_cond and end of rewrite statement 
+            is wrapped in end of ndb_serialize_cond
+          */
           DBUG_PRINT("info", ("EQ_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(), 
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::NE_FUNC): {
-          DBUG_PRINT("info", ("NE_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::LT_FUNC): {
-          DBUG_PRINT("info", ("LT_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::LE_FUNC): {
-          DBUG_PRINT("info", ("LE_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::GE_FUNC): {
-          DBUG_PRINT("info", ("GE_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::GT_FUNC): {
-          DBUG_PRINT("info", ("GT_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::REAL_ITEM);
-          context->expect(Item::DECIMAL_ITEM);
-          context->expect(Item::INT_ITEM);
-          context->expect(Item::VARBIN_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::LIKE_FUNC): {
-          DBUG_PRINT("info", ("LIKE_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          break;
-        }
-        case(Item_func::NOTLIKE_FUNC): {
-          DBUG_PRINT("info", ("NOTLIKE_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::STRING_ITEM);
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          break;
-        }
-        case(Item_func::ISNULL_FUNC): {
-          DBUG_PRINT("info", ("ISNULL_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);      
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::ISNOTNULL_FUNC): {
-          DBUG_PRINT("info", ("ISNOTNULL_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);     
-          context->expect(Item::FIELD_ITEM);
-          context->expect_field_result(STRING_RESULT);
-          context->expect_field_result(REAL_RESULT);
-          context->expect_field_result(INT_RESULT);
-          context->expect_field_result(DECIMAL_RESULT);
-          break;
-        }
-        case(Item_func::NOT_FUNC): {
-          DBUG_PRINT("info", ("NOT_FUNC"));      
-          curr_cond->ndb_item= new Ndb_item(func_item->functype(),
-                                            func_item);     
-          context->expect(Item::FUNC_ITEM);
-          context->expect(Item::COND_ITEM);
-          break;
-        }
-        case(Item_func::UNKNOWN_FUNC): {
-          DBUG_PRINT("info", ("UNKNOWN_FUNC %s", 
-                              func_item->const_item()?"const":""));  
-          DBUG_PRINT("info", ("result type %d", func_item->result_type()));
-          if (func_item->const_item())
-            switch(func_item->result_type()) {
-            case(STRING_RESULT): {
-              NDB_ITEM_QUALIFICATION q;
-              q.value_type= Item::STRING_ITEM;
-              curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); 
-              if (context->expect_field_result_mask)
+          curr_cond->ndb_item= new Ndb_item(Item_func::EQ_FUNC, 2);
+          break;
+        }
+        default:
+          context->supported= FALSE;
+        }
+        // Handle left hand <field>|<const>
+        context->rewrite_stack= NULL; // Disable rewrite mode
+        context->expect_only(Item::FIELD_ITEM);
+        context->expect_field_result(STRING_RESULT);
+        context->expect_field_result(REAL_RESULT);
+        context->expect_field_result(INT_RESULT);
+        context->expect_field_result(DECIMAL_RESULT);
+        context->expect(Item::INT_ITEM);
+        context->expect(Item::STRING_ITEM);
+        context->expect(Item::VARBIN_ITEM);
+        context->expect(Item::FUNC_ITEM);
+        ndb_serialize_cond(rewrite_context->left_hand_item, arg);
+        context->skip= 0; // Any FUNC_ITEM expression has already been parsed
+        context->rewrite_stack= rewrite_context; // Enable rewrite mode
+        if (!context->supported)
+          DBUG_VOID_RETURN;
+
+        prev_cond= context->cond_ptr;
+        curr_cond= context->cond_ptr= new Ndb_cond();
+        prev_cond->next= curr_cond;
+      }
+      
+      // Check for end of AND/OR expression
+      if (!item)
+      {
+        // End marker for condition group
+        DBUG_PRINT("info", ("End of condition group"));
+        curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
+      }
+      else
+        switch(item->type()) {
+        case(Item::FIELD_ITEM): {
+          Item_field *field_item= (Item_field *) item;
+          Field *field= field_item->field;
+          enum_field_types type= field->type();
+          /*
+            Check that the field is part of the table of the handler
+            instance and that we expect a field with of this result type.
+          */
+          if (context->table == field->table)
+          {       
+            const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
+            DBUG_PRINT("info", ("FIELD_ITEM"));
+            DBUG_PRINT("info", ("table %s", tab->getName()));
+            DBUG_PRINT("info", ("column %s", field->field_name));
+            DBUG_PRINT("info", ("result type %d", field->result_type()));
+            
+            // Check that we are expecting a field and with the correct
+            // result type
+            if (context->expecting(Item::FIELD_ITEM) &&
+                (context->expecting_field_result(field->result_type()) ||
+                 // Date and year can be written as strings
+                 ((type == MYSQL_TYPE_TIME ||
+                   type == MYSQL_TYPE_DATE || 
+                   type == MYSQL_TYPE_YEAR ||
+                   type == MYSQL_TYPE_DATETIME)
+                  ? context->expecting_field_result(STRING_RESULT) : true)) &&
+                // Bit fields no yet supported in scan filter
+                type != MYSQL_TYPE_BIT)
+            {
+              const NDBCOL *col= tab->getColumn(field->field_name);
+              DBUG_ASSERT(col);
+              curr_cond->ndb_item= new Ndb_item(field, col->getColumnNo());
+              context->dont_expect(Item::FIELD_ITEM);
+              context->expect_no_field_result();
+              if (context->expect_mask)
               {
-                // We have not seen the field argument yet
-                context->expect_only(Item::FIELD_ITEM);
-                context->expect_only_field_result(STRING_RESULT);
-                context->expect_collation(func_item->collation.collation);
+                // We have not seen second argument yet
+                if (type == MYSQL_TYPE_TIME ||
+                    type == MYSQL_TYPE_DATE || 
+                    type == MYSQL_TYPE_YEAR ||
+                    type == MYSQL_TYPE_DATETIME)
+                {
+                  context->expect_only(Item::STRING_ITEM);
+                  context->expect(Item::INT_ITEM);
+                }
+                else
+                  switch(field->result_type()) {
+                  case(STRING_RESULT):
+                    // Expect char string or binary string
+                    context->expect_only(Item::STRING_ITEM);
+                    context->expect(Item::VARBIN_ITEM);
+                    context->expect_collation(field_item->collation.collation);
+                    break;
+                  case(REAL_RESULT):
+                    context->expect_only(Item::REAL_ITEM);
+                    context->expect(Item::DECIMAL_ITEM);
+                    break;
+                  case(INT_RESULT):
+                    context->expect_only(Item::INT_ITEM);
+                    context->expect(Item::VARBIN_ITEM);
+                    break;
+                  case(DECIMAL_RESULT):
+                    context->expect_only(Item::DECIMAL_ITEM);
+                    context->expect(Item::REAL_ITEM);
+                    break;
+                  default:
+                    break;
+                  }    
               }
               else
               {
                 // Expect another logical expression
                 context->expect_only(Item::FUNC_ITEM);
                 context->expect(Item::COND_ITEM);
-                // Check that string result have correct collation
-                if (!context->expecting_collation(item->collation.collation))
+                // Check that field and string constant collations are the same
+                if ((field->result_type() == STRING_RESULT) &&
+                    !context->expecting_collation(item->collation.collation)
+                    && type != MYSQL_TYPE_TIME
+                    && type != MYSQL_TYPE_DATE
+                    && type != MYSQL_TYPE_YEAR
+                    && type != MYSQL_TYPE_DATETIME)
                 {
                   DBUG_PRINT("info", ("Found non-matching collation %s",  
-                                      item->collation.collation->name));
-                  context->supported= FALSE;
+                                      item->collation.collation->name)); 
+                  context->supported= FALSE;                
                 }
               }
-              // Skip any arguments since we will evaluate function instead
-              DBUG_PRINT("info", ("Skip until end of arguments marker"));
-              context->skip= func_item->argument_count();
-              break;
-            }
-            case(REAL_RESULT): {
-              NDB_ITEM_QUALIFICATION q;
-              q.value_type= Item::REAL_ITEM;
-              curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-              if (context->expect_field_result_mask) 
-              {
-                // We have not seen the field argument yet
-                context->expect_only(Item::FIELD_ITEM);
-                context->expect_only_field_result(REAL_RESULT);
-              }
-              else
-              {
-                // Expect another logical expression
-                context->expect_only(Item::FUNC_ITEM);
-                context->expect(Item::COND_ITEM);
-              }
-
-              // Skip any arguments since we will evaluate function instead
-              DBUG_PRINT("info", ("Skip until end of arguments marker"));
-              context->skip= func_item->argument_count();
-              break;
-            }
-            case(INT_RESULT): {
-              NDB_ITEM_QUALIFICATION q;
-              q.value_type= Item::INT_ITEM;
-              curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-              if (context->expect_field_result_mask) 
-              {
-                // We have not seen the field argument yet
-                context->expect_only(Item::FIELD_ITEM);
-                context->expect_only_field_result(INT_RESULT);
-              }
-              else
-              {
-                // Expect another logical expression
-                context->expect_only(Item::FUNC_ITEM);
-                context->expect(Item::COND_ITEM);
-              }
-              
-              // Skip any arguments since we will evaluate function instead
-              DBUG_PRINT("info", ("Skip until end of arguments marker"));
-              context->skip= func_item->argument_count();
-              break;
-            }
-            case(DECIMAL_RESULT): {
-              NDB_ITEM_QUALIFICATION q;
-              q.value_type= Item::DECIMAL_ITEM;
-              curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-              if (context->expect_field_result_mask) 
-              {
-                // We have not seen the field argument yet
-                context->expect_only(Item::FIELD_ITEM);
-                context->expect_only_field_result(DECIMAL_RESULT);
-              }
-              else
-              {
-                // Expect another logical expression
-                context->expect_only(Item::FUNC_ITEM);
-                context->expect(Item::COND_ITEM);
-              }
-              // Skip any arguments since we will evaluate function instead
-              DBUG_PRINT("info", ("Skip until end of arguments marker"));
-              context->skip= func_item->argument_count();
               break;
             }
-            default:
-              break;
+            else
+            {
+              DBUG_PRINT("info", ("Was not expecting field of type %u",
+                                  field->result_type()));
+              context->supported= FALSE;
             }
+          }
           else
-            // Function does not return constant expression
+          {
+            DBUG_PRINT("info", ("Was not expecting field from table %s(%s)",
+                                context->table->s->table_name, 
+                                field->table->s->table_name));
             context->supported= FALSE;
+          }
           break;
         }
-        default: {
-          DBUG_PRINT("info", ("Found func_item of type %d", 
-                              func_item->functype()));
-          context->supported= FALSE;
-        }
-        }
-        break;
-      }
-      case(Item::STRING_ITEM):
-        DBUG_PRINT("info", ("STRING_ITEM")); 
-        if (context->expecting(Item::STRING_ITEM)) 
-        {
-#ifndef DBUG_OFF
-          char buff[256];
-          String str(buff,(uint32) sizeof(buff), system_charset_info);
-          str.length(0);
-          Item_string *string_item= (Item_string *) item;
-          DBUG_PRINT("info", ("value \"%s\"", 
-                              string_item->val_str(&str)->ptr()));
-#endif
-          NDB_ITEM_QUALIFICATION q;
-          q.value_type= Item::STRING_ITEM;
-          curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);      
-          if (context->expect_field_result_mask)
+        case(Item::FUNC_ITEM): {
+          Item_func *func_item= (Item_func *) item;
+          // Check that we expect a function or functional expression here
+          if (context->expecting(Item::FUNC_ITEM) || 
+              func_item->functype() == Item_func::UNKNOWN_FUNC)
+            context->expect_nothing();
+          else
           {
-            // We have not seen the field argument yet
-            context->expect_only(Item::FIELD_ITEM);
-            context->expect_only_field_result(STRING_RESULT);
-            context->expect_collation(item->collation.collation);
+            // Did not expect function here
+            context->supported= FALSE;
+            break;
           }
-          else 
-          {
-            // Expect another logical expression
-            context->expect_only(Item::FUNC_ITEM);
-            context->expect(Item::COND_ITEM);
-            // Check that we are comparing with a field with same collation
-            if (!context->expecting_collation(item->collation.collation))
-            {
-              DBUG_PRINT("info", ("Found non-matching collation %s",  
-                                  item->collation.collation->name));
-              context->supported= FALSE;
-            }
+          
+          switch(func_item->functype()) {
+          case(Item_func::EQ_FUNC): {
+            DBUG_PRINT("info", ("EQ_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(), 
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
           }
-        }
-        else
-          context->supported= FALSE;
-        break;
-      case(Item::INT_ITEM): 
-        DBUG_PRINT("info", ("INT_ITEM"));
-        if (context->expecting(Item::INT_ITEM)) 
-        {
-          Item_int *int_item= (Item_int *) item;      
-          DBUG_PRINT("info", ("value %d", int_item->value));
-          NDB_ITEM_QUALIFICATION q;
-          q.value_type= Item::INT_ITEM;
-          curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-          if (context->expect_field_result_mask) 
-          {
-            // We have not seen the field argument yet
-            context->expect_only(Item::FIELD_ITEM);
-            context->expect_only_field_result(INT_RESULT);
+          case(Item_func::NE_FUNC): {
+            DBUG_PRINT("info", ("NE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
           }
-          else
-          {
-            // Expect another logical expression
-            context->expect_only(Item::FUNC_ITEM);
+          case(Item_func::LT_FUNC): {
+            DBUG_PRINT("info", ("LT_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::LE_FUNC): {
+            DBUG_PRINT("info", ("LE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::GE_FUNC): {
+            DBUG_PRINT("info", ("GE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::GT_FUNC): {
+            DBUG_PRINT("info", ("GT_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::REAL_ITEM);
+            context->expect(Item::DECIMAL_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::LIKE_FUNC): {
+            DBUG_PRINT("info", ("LIKE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::NOTLIKE_FUNC): {
+            DBUG_PRINT("info", ("NOTLIKE_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::ISNULL_FUNC): {
+            DBUG_PRINT("info", ("ISNULL_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);      
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            break;
+          }
+          case(Item_func::ISNOTNULL_FUNC): {
+            DBUG_PRINT("info", ("ISNOTNULL_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);     
+            context->expect(Item::FIELD_ITEM);
+            context->expect_field_result(STRING_RESULT);
+            context->expect_field_result(REAL_RESULT);
+            context->expect_field_result(INT_RESULT);
+            context->expect_field_result(DECIMAL_RESULT);
+            break;
+          }
+          case(Item_func::NOT_FUNC): {
+            DBUG_PRINT("info", ("NOT_FUNC"));      
+            curr_cond->ndb_item= new Ndb_item(func_item->functype(),
+                                              func_item);     
+            context->expect(Item::FUNC_ITEM);
             context->expect(Item::COND_ITEM);
+            break;
           }
-        }
-        else
-          context->supported= FALSE;
-        break;
-      case(Item::REAL_ITEM):
-        DBUG_PRINT("info", ("REAL_ITEM %s"));
-        if (context->expecting(Item::REAL_ITEM)) 
-        {
-          Item_float *float_item= (Item_float *) item;      
-          DBUG_PRINT("info", ("value %f", float_item->value));
-          NDB_ITEM_QUALIFICATION q;
-          q.value_type= Item::REAL_ITEM;
-          curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-          if (context->expect_field_result_mask) 
-          {
-            // We have not seen the field argument yet
+          case(Item_func::BETWEEN) : {
+            DBUG_PRINT("info", ("BETWEEN, rewriting using AND"));
+            Ndb_rewrite_context *rewrite_context= 
+              new Ndb_rewrite_context(func_item);
+            rewrite_context->next= context->rewrite_stack;
+            context->rewrite_stack= rewrite_context;
+            DBUG_PRINT("info", ("COND_AND_FUNC"));
+            curr_cond->ndb_item= new Ndb_item(Item_func::COND_AND_FUNC, 
+                                              func_item->argument_count() - 1);
             context->expect_only(Item::FIELD_ITEM);
-            context->expect_only_field_result(REAL_RESULT);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::IN_FUNC) : {
+            DBUG_PRINT("info", ("IN_FUNC, rewriting using OR"));
+            Ndb_rewrite_context *rewrite_context= 
+              new Ndb_rewrite_context(func_item);
+            rewrite_context->next= context->rewrite_stack;
+            context->rewrite_stack= rewrite_context;
+            DBUG_PRINT("info", ("COND_OR_FUNC"));
+            curr_cond->ndb_item= new Ndb_item(Item_func::COND_OR_FUNC, 
+                                              func_item->argument_count() - 1);
+            context->expect_only(Item::FIELD_ITEM);
+            context->expect(Item::INT_ITEM);
+            context->expect(Item::STRING_ITEM);
+            context->expect(Item::VARBIN_ITEM);
+            context->expect(Item::FUNC_ITEM);
+            break;
+          }
+          case(Item_func::UNKNOWN_FUNC): {
+            DBUG_PRINT("info", ("UNKNOWN_FUNC %s", 
+                                func_item->const_item()?"const":""));  
+            DBUG_PRINT("info", ("result type %d", func_item->result_type()));
+            if (func_item->const_item())
+              switch(func_item->result_type()) {
+              case(STRING_RESULT): {
+                NDB_ITEM_QUALIFICATION q;
+                q.value_type= Item::STRING_ITEM;
+                curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item); 
+                if (context->expect_field_result_mask)
+                {
+                  // We have not seen the field argument yet
+                  context->expect_only(Item::FIELD_ITEM);
+                  context->expect_only_field_result(STRING_RESULT);
+                  context->expect_collation(func_item->collation.collation);
+                }
+                else
+                {
+                  // Expect another logical expression
+                  context->expect_only(Item::FUNC_ITEM);
+                  context->expect(Item::COND_ITEM);
+                  // Check that string result have correct collation
+                  if (!context->expecting_collation(item->collation.collation))
+                  {
+                    DBUG_PRINT("info", ("Found non-matching collation %s",  
+                                        item->collation.collation->name));
+                    context->supported= FALSE;
+                  }
+                }
+                // Skip any arguments since we will evaluate function instead
+                DBUG_PRINT("info", ("Skip until end of arguments marker"));
+                context->skip= func_item->argument_count();
+                break;
+              }
+              case(REAL_RESULT): {
+                NDB_ITEM_QUALIFICATION q;
+                q.value_type= Item::REAL_ITEM;
+                curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+                if (context->expect_field_result_mask) 
+                {
+                  // We have not seen the field argument yet
+                  context->expect_only(Item::FIELD_ITEM);
+                  context->expect_only_field_result(REAL_RESULT);
+                }
+                else
+                {
+                  // Expect another logical expression
+                  context->expect_only(Item::FUNC_ITEM);
+                  context->expect(Item::COND_ITEM);
+                }
+                
+                // Skip any arguments since we will evaluate function instead
+                DBUG_PRINT("info", ("Skip until end of arguments marker"));
+                context->skip= func_item->argument_count();
+                break;
+              }
+              case(INT_RESULT): {
+                NDB_ITEM_QUALIFICATION q;
+                q.value_type= Item::INT_ITEM;
+                curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+                if (context->expect_field_result_mask) 
+                {
+                  // We have not seen the field argument yet
+                  context->expect_only(Item::FIELD_ITEM);
+                  context->expect_only_field_result(INT_RESULT);
+                }
+                else
+                {
+                  // Expect another logical expression
+                  context->expect_only(Item::FUNC_ITEM);
+                  context->expect(Item::COND_ITEM);
+                }
+                
+                // Skip any arguments since we will evaluate function instead
+                DBUG_PRINT("info", ("Skip until end of arguments marker"));
+                context->skip= func_item->argument_count();
+                break;
+              }
+              case(DECIMAL_RESULT): {
+                NDB_ITEM_QUALIFICATION q;
+                q.value_type= Item::DECIMAL_ITEM;
+                curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+                if (context->expect_field_result_mask) 
+                {
+                  // We have not seen the field argument yet
+                  context->expect_only(Item::FIELD_ITEM);
+                  context->expect_only_field_result(DECIMAL_RESULT);
+                }
+                else
+                {
+                  // Expect another logical expression
+                  context->expect_only(Item::FUNC_ITEM);
+                  context->expect(Item::COND_ITEM);
+                }
+                // Skip any arguments since we will evaluate function instead
+                DBUG_PRINT("info", ("Skip until end of arguments marker"));
+                context->skip= func_item->argument_count();
+                break;
+              }
+              default:
+                break;
+              }
+            else
+              // Function does not return constant expression
+              context->supported= FALSE;
+            break;
+          }
+          default: {
+            DBUG_PRINT("info", ("Found func_item of type %d", 
+                                func_item->functype()));
+            context->supported= FALSE;
           }
-          else
-          {
-            // Expect another logical expression
-            context->expect_only(Item::FUNC_ITEM);
-            context->expect(Item::COND_ITEM);
           }
+          break;
         }
-        else
-          context->supported= FALSE;
-        break;
-      case(Item::VARBIN_ITEM):
-        DBUG_PRINT("info", ("VARBIN_ITEM"));
-        if (context->expecting(Item::VARBIN_ITEM)) 
-        {
+        case(Item::STRING_ITEM):
+          DBUG_PRINT("info", ("STRING_ITEM")); 
+          if (context->expecting(Item::STRING_ITEM)) 
+          {
 #ifndef DBUG_OFF
-          char buff[256];
-          String str(buff,(uint32) sizeof(buff), system_charset_info);
-          str.length(0);
-          Item_hex_string *varbin_item= (Item_hex_string *) item;      
-          DBUG_PRINT("info", ("value \"%s\"", 
-                              varbin_item->val_str(&str)->ptr()));
+            char buff[256];
+            String str(buff,(uint32) sizeof(buff), system_charset_info);
+            str.length(0);
+            Item_string *string_item= (Item_string *) item;
+            DBUG_PRINT("info", ("value \"%s\"", 
+                                string_item->val_str(&str)->ptr()));
 #endif
-          NDB_ITEM_QUALIFICATION q;
-          q.value_type= Item::VARBIN_ITEM;
-          curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);      
-          if (context->expect_field_result_mask)
+            NDB_ITEM_QUALIFICATION q;
+            q.value_type= Item::STRING_ITEM;
+            curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);      
+            if (context->expect_field_result_mask)
+            {
+              // We have not seen the field argument yet
+              context->expect_only(Item::FIELD_ITEM);
+              context->expect_only_field_result(STRING_RESULT);
+              context->expect_collation(item->collation.collation);
+            }
+            else 
+            {
+              // Expect another logical expression
+              context->expect_only(Item::FUNC_ITEM);
+              context->expect(Item::COND_ITEM);
+              // Check that we are comparing with a field with same collation
+              if (!context->expecting_collation(item->collation.collation))
+              {
+                DBUG_PRINT("info", ("Found non-matching collation %s",  
+                                    item->collation.collation->name));
+                context->supported= FALSE;
+              }
+            }
+          }
+          else
+            context->supported= FALSE;
+          break;
+        case(Item::INT_ITEM): 
+          DBUG_PRINT("info", ("INT_ITEM"));
+          if (context->expecting(Item::INT_ITEM)) 
           {
-            // We have not seen the field argument yet
-            context->expect_only(Item::FIELD_ITEM);
-            context->expect_only_field_result(STRING_RESULT);
+            Item_int *int_item= (Item_int *) item;      
+            DBUG_PRINT("info", ("value %d", int_item->value));
+            NDB_ITEM_QUALIFICATION q;
+            q.value_type= Item::INT_ITEM;
+            curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+            if (context->expect_field_result_mask) 
+            {
+              // We have not seen the field argument yet
+              context->expect_only(Item::FIELD_ITEM);
+              context->expect_only_field_result(INT_RESULT);
+            }
+            else
+            {
+              // Expect another logical expression
+              context->expect_only(Item::FUNC_ITEM);
+              context->expect(Item::COND_ITEM);
+            }
           }
           else
+            context->supported= FALSE;
+          break;
+        case(Item::REAL_ITEM):
+          DBUG_PRINT("info", ("REAL_ITEM %s"));
+          if (context->expecting(Item::REAL_ITEM)) 
           {
-            // Expect another logical expression
-            context->expect_only(Item::FUNC_ITEM);
-            context->expect(Item::COND_ITEM);
+            Item_float *float_item= (Item_float *) item;      
+            DBUG_PRINT("info", ("value %f", float_item->value));
+            NDB_ITEM_QUALIFICATION q;
+            q.value_type= Item::REAL_ITEM;
+            curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+            if (context->expect_field_result_mask) 
+            {
+              // We have not seen the field argument yet
+              context->expect_only(Item::FIELD_ITEM);
+              context->expect_only_field_result(REAL_RESULT);
+            }
+            else
+            {
+              // Expect another logical expression
+              context->expect_only(Item::FUNC_ITEM);
+              context->expect(Item::COND_ITEM);
+            }
           }
-        }
-        else
-          context->supported= FALSE;
-        break;
-      case(Item::DECIMAL_ITEM):
-        DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
-        if (context->expecting(Item::DECIMAL_ITEM)) 
-        {
-          Item_decimal *decimal_item= (Item_decimal *) item;      
-          DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
-          NDB_ITEM_QUALIFICATION q;
-          q.value_type= Item::DECIMAL_ITEM;
-          curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
-          if (context->expect_field_result_mask) 
+          else
+            context->supported= FALSE;
+          break;
+        case(Item::VARBIN_ITEM):
+          DBUG_PRINT("info", ("VARBIN_ITEM"));
+          if (context->expecting(Item::VARBIN_ITEM)) 
           {
-            // We have not seen the field argument yet
-            context->expect_only(Item::FIELD_ITEM);
-            context->expect_only_field_result(REAL_RESULT);
-            context->expect_field_result(DECIMAL_RESULT);
+            NDB_ITEM_QUALIFICATION q;
+            q.value_type= Item::VARBIN_ITEM;
+            curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);      
+            if (context->expect_field_result_mask)
+            {
+              // We have not seen the field argument yet
+              context->expect_only(Item::FIELD_ITEM);
+              context->expect_only_field_result(STRING_RESULT);
+            }
+            else
+            {
+              // Expect another logical expression
+              context->expect_only(Item::FUNC_ITEM);
+              context->expect(Item::COND_ITEM);
+            }
           }
           else
+            context->supported= FALSE;
+          break;
+        case(Item::DECIMAL_ITEM):
+          DBUG_PRINT("info", ("DECIMAL_ITEM %s"));
+          if (context->expecting(Item::DECIMAL_ITEM)) 
           {
-            // Expect another logical expression
-            context->expect_only(Item::FUNC_ITEM);
-            context->expect(Item::COND_ITEM);
+            Item_decimal *decimal_item= (Item_decimal *) item;      
+            DBUG_PRINT("info", ("value %f", decimal_item->val_real()));
+            NDB_ITEM_QUALIFICATION q;
+            q.value_type= Item::DECIMAL_ITEM;
+            curr_cond->ndb_item= new Ndb_item(NDB_VALUE, q, item);
+            if (context->expect_field_result_mask) 
+            {
+              // We have not seen the field argument yet
+              context->expect_only(Item::FIELD_ITEM);
+              context->expect_only_field_result(REAL_RESULT);
+              context->expect_field_result(DECIMAL_RESULT);
+            }
+            else
+            {
+              // Expect another logical expression
+              context->expect_only(Item::FUNC_ITEM);
+              context->expect(Item::COND_ITEM);
+            }
           }
+          else
+            context->supported= FALSE;
+          break;
+        case(Item::COND_ITEM): {
+          Item_cond *cond_item= (Item_cond *) item;
+          
+          if (context->expecting(Item::COND_ITEM))
+            switch(cond_item->functype()) {
+            case(Item_func::COND_AND_FUNC):
+              DBUG_PRINT("info", ("COND_AND_FUNC"));
+              curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
+                                                cond_item);      
+              break;
+            case(Item_func::COND_OR_FUNC):
+              DBUG_PRINT("info", ("COND_OR_FUNC"));
+              curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
+                                                cond_item);      
+              break;
+            default:
+              DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
+              context->supported= FALSE;
+              break;
+            }
+          else
+            // Did not expect condition
+            context->supported= FALSE;          
+          break;
         }
-        else
+        default: {
+          DBUG_PRINT("info", ("Found item of type %d", item->type()));
           context->supported= FALSE;
-        break;
-      case(Item::COND_ITEM): {
-        Item_cond *cond_item= (Item_cond *) item;
-
-        if (context->expecting(Item::COND_ITEM))
-          switch(cond_item->functype()) {
-          case(Item_func::COND_AND_FUNC):
-            DBUG_PRINT("info", ("COND_AND_FUNC"));
-            curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
-                                              cond_item);      
-            break;
-          case(Item_func::COND_OR_FUNC):
-            DBUG_PRINT("info", ("COND_OR_FUNC"));
-            curr_cond->ndb_item= new Ndb_item(cond_item->functype(),
-                                              cond_item);      
-            break;
-          default:
-            DBUG_PRINT("info", ("COND_ITEM %d", cond_item->functype()));
-            context->supported= FALSE;
-            break;
-          }
-        else
-          // Did not expect condition
-          context->supported= FALSE;          
-        break;
-      }
-      default: {
-        DBUG_PRINT("info", ("Found item of type %d", item->type()));
-        context->supported= FALSE;
-      }
+        }
+        }
+      
+      if (context->supported && context->rewrite_stack)
+      {
+        Ndb_rewrite_context *rewrite_context= context->rewrite_stack;
+        if (rewrite_context->count == 
+            rewrite_context->func_item->argument_count())
+        {
+          // Rewrite is done, wrap an END() at the en
+          DBUG_PRINT("info", ("End of condition group"));
+          prev_cond= curr_cond;
+          curr_cond= context->cond_ptr= new Ndb_cond();
+          prev_cond->next= curr_cond;
+          curr_cond->ndb_item= new Ndb_item(NDB_END_COND);
+          // Pop rewrite stack
+          context->rewrite_stack= context->rewrite_stack->next;
+        }
       }
+    }
   }
-  
+ 
   DBUG_VOID_RETURN;
 }
 
@@ -7065,14 +7277,20 @@
   bool simple_cond= TRUE;
   DBUG_ENTER("build_scan_filter");  
 
-  switch(cond->ndb_item->type) {
-  case(Item_func::COND_AND_FUNC):
-  case(Item_func::COND_OR_FUNC):
-    simple_cond= FALSE;
-    break;
-  default:
-    break;
-  }
+    switch(cond->ndb_item->type) {
+    case(NDB_FUNCTION):
+      switch(cond->ndb_item->qualification.function_type) {
+      case(Item_func::COND_AND_FUNC):
+      case(Item_func::COND_OR_FUNC):
+        simple_cond= FALSE;
+        break;
+      default:
+        break;
+      }
+      break;
+    default:
+      break;
+    }
   if (simple_cond && filter->begin() == -1)
     DBUG_RETURN(1);
   if (build_scan_filter_group(cond, filter))

--- 1.82/sql/ha_ndbcluster.h	Thu Apr 28 10:28:51 2005
+++ 1.83/sql/ha_ndbcluster.h	Wed May 18 14:31:45 2005
@@ -86,6 +86,7 @@
 typedef union ndb_item_value {
   const Item *item;
   NDB_ITEM_FIELD_VALUE *field_value;
+  uint arg_count;
 } NDB_ITEM_VALUE;
 
 struct negated_function_mapping
@@ -144,6 +145,7 @@
     }
     case(NDB_FUNCTION):
       value.item= item_value;
+      value.arg_count= ((Item_func *) item_value)->argument_count();
       break;
     case(NDB_END_COND):
       break;
@@ -162,6 +164,13 @@
   {
     qualification.function_type= func_type;
     value.item= item_value;
+    value.arg_count= ((Item_func *) item_value)->argument_count();
+  };
+  Ndb_item(Item_func::Functype func_type, uint no_args) 
+    : type(NDB_FUNCTION)
+  {
+    qualification.function_type= func_type;
+    value.arg_count= no_args;
   };
   ~Ndb_item()
   { 
@@ -194,7 +203,7 @@
 
   int argument_count() 
   { 
-    return ((Item_func *) value.item)->argument_count(); 
+    return value.arg_count;
   };
 
   const char* get_val() 
@@ -273,12 +282,28 @@
   { 
     if (ndb_cond) delete ndb_cond; 
     ndb_cond= NULL; 
+    if (next) delete next;
     next= NULL; 
   };
   Ndb_cond *ndb_cond;
   Ndb_cond_stack *next;
 };
 
+class Ndb_rewrite_context
+{
+public:
+  Ndb_rewrite_context(Item_func *func) 
+    : func_item(func), left_hand_item(NULL), count(0) {};
+  ~Ndb_rewrite_context()
+  {
+    if (next) delete next;
+  }
+  const Item_func *func_item;
+  const Item *left_hand_item;
+  uint count;
+  Ndb_rewrite_context *next;
+};
+
 /*
   This class is used for storing the context when traversing
   the Item tree. It stores a reference to the table the condition
@@ -292,11 +317,16 @@
   Ndb_cond_traverse_context(TABLE *tab, void* ndb_tab, Ndb_cond_stack* stack)
     : table(tab), ndb_table(ndb_tab), 
     supported(TRUE), stack_ptr(stack), cond_ptr(NULL),
-    expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL)
+    expect_mask(0), expect_field_result_mask(0), skip(0), collation(NULL),
+    rewrite_stack(NULL)
   {
     if (stack)
       cond_ptr= stack->ndb_cond;
   };
+  ~Ndb_cond_traverse_context()
+  {
+    if (rewrite_stack) delete rewrite_stack;
+  }
   void expect(Item::Type type)
   {
     expect_mask|= (1 << type);
@@ -357,7 +387,7 @@
   uint expect_field_result_mask;
   uint skip;
   CHARSET_INFO* collation;
-
+  Ndb_rewrite_context *rewrite_stack;
 };
 
 /*

--- 1.11/mysql-test/r/ndb_condition_pushdown.result	Mon May  9 18:44:22 2005
+++ 1.12/mysql-test/r/ndb_condition_pushdown.result	Wed May 18 14:31:45 2005
@@ -251,6 +251,108 @@
 1
 3
 4
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+(bits between b'001' and b'011') and
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+auto
+1
+3
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+(b'001' between bits and bits) and
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+auto
+1
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+bits in(b'001',b'011') and
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+auto
+1
+3
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+b'001' in(bits) and
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
+order by auto;
+auto
+1
 select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
 pk1	attr1	attr2	attr3
 2	2	NULL	NULL
@@ -1023,6 +1125,212 @@
 1
 3
 4
+explain 
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	medium_index	medium_index	3	NULL	10	Using where with pushed condition; Using filesort
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+auto
+1
+3
+explain
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+/* (b'001' between bits and bits) and */
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	Using where with pushed condition; Using filesort
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+/* (b'001' between bits and bits) and */
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+auto
+1
+explain
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+/* bits in(b'001',b'011') and */
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	medium_index	medium_index	3	NULL	20	Using where with pushed condition; Using filesort
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+/* bits in(b'001',b'011') and */
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+auto
+1
+3
+explain
+select auto from t1 where
+"aaaa" in(string) and 
+"aaaa" in(vstring) and 
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+/* b'001' in(bits) and */
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
+order by auto;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	ALL	NULL	NULL	NULL	NULL	4	Using where with pushed condition; Using filesort
+select auto from t1 where
+"aaaa" in(string) and 
+"aaaa" in(vstring) and 
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+/* b'001' in(bits) and */
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
+order by auto;
+auto
+1
 update t1
 set medium = 17
 where 
@@ -1138,7 +1446,7 @@
 explain
 select * from t2 where (attr1 < 2) = (attr2 < 2) order by pk1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	6	Using where; Using filesort
+1	SIMPLE	t2	ALL	NULL	NULL	NULL	NULL	6	Using where with pushed condition; Using filesort
 explain
 select * from t3 left join t4 on t4.attr2 = t3.attr2 where t4.attr1 > 1 and t4.attr3 < 5 or t4.attr1 is null order by t4.pk1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra

--- 1.12/mysql-test/t/ndb_condition_pushdown.test	Mon May  9 18:44:22 2005
+++ 1.13/mysql-test/t/ndb_condition_pushdown.test	Wed May 18 14:31:45 2005
@@ -249,6 +249,104 @@
 vbin not like concat(0xBB, '%')
 order by auto;
 
+# BETWEEN
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+(bits between b'001' and b'011') and
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+(b'001' between bits and bits) and
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+
+# IN
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+bits in(b'001',b'011') and
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+
+select auto from t1 where
+"aaaa" in(string) and
+"aaaa" in(vstring) and
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+b'001' in(bits) and
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
+order by auto;
+
 # Various tests 
 select * from t2 where attr3 is null or attr1 > 2 and pk1= 3 order by pk1;
 select * from t2 where attr3 is not null and attr1 > 2 order by pk1;
@@ -953,6 +1051,204 @@
 vstring not like "b%" and
 bin not like concat(0xBB, '%') and
 vbin not like concat(0xBB, '%')
+order by auto;
+
+# BETWEEN
+explain 
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+
+select auto from t1 where
+(string between "aaaa" and "cccc") and 
+(vstring between "aaaa" and "cccc") and 
+(bin between 0xAAAA and 0xCCCC) and 
+(vbin between 0xAAAA and 0xCCCC) and 
+(tiny between -3 and -1) and 
+(short between -3 and -1) and 
+(medium between -3 and -1) and 
+(long_int between -3 and -1) and 
+(longlong between -3 and -1) and 
+(utiny between 1 and 3) and 
+(ushort between 1 and 3) and 
+(umedium between 1 and 3) and 
+(ulong between 1 and 3) and 
+(ulonglong between 1 and 3) and 
+/* (bits between b'001' and b'011') and */
+(options between 'one' and 'three') and 
+(flags between 'one' and 'one,two,three') and 
+(date_field between '1901-01-01' and '1903-03-03') and
+(year_field between '1901' and '1903') and
+(time_field between '01:01:01' and '03:03:03') and 
+(date_time between '1901-01-01 01:01:01' and '1903-03-03 03:03:03') 
+order by auto;
+
+explain
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+/* (b'001' between bits and bits) and */
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+
+select auto from t1 where
+("aaaa" between string and string) and 
+("aaaa" between vstring and vstring) and 
+(0xAAAA between bin and bin) and 
+(0xAAAA between vbin and vbin) and 
+(-1 between tiny and tiny) and 
+(-1 between short and short) and 
+(-1 between medium and medium) and 
+(-1 between long_int and long_int) and 
+(-1 between longlong and longlong) and 
+(1 between utiny and utiny) and 
+(1 between ushort and ushort) and 
+(1 between umedium and umedium) and 
+(1 between ulong and ulong) and 
+(1 between ulonglong and ulonglong) and 
+/* (b'001' between bits and bits) and */
+('one' between options and options) and 
+('one' between flags and flags) and 
+('1901-01-01' between date_field and date_field) and
+('1901' between year_field and year_field) and
+('01:01:01' between time_field and time_field) and 
+('1901-01-01 01:01:01' between date_time and date_time) 
+order by auto;
+
+# IN
+explain
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+/* bits in(b'001',b'011') and */
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+
+select auto from t1 where
+string in("aaaa","cccc") and 
+vstring in("aaaa","cccc") and 
+bin in(0xAAAA,0xCCCC) and 
+vbin in(0xAAAA,0xCCCC) and 
+tiny in(-1,-3) and 
+short in(-1,-3) and 
+medium in(-1,-3) and 
+long_int in(-1,-3) and 
+longlong in(-1,-3) and 
+utiny in(1,3) and 
+ushort in(1,3) and 
+umedium in(1,3) and 
+ulong in(1,3) and 
+ulonglong in(1,3) and 
+/* bits in(b'001',b'011') and */
+options in('one','three') and 
+flags in('one','one,two,three') and 
+date_field in('1901-01-01','1903-03-03') and
+year_field in('1901','1903') and
+time_field in('01:01:01','03:03:03') and 
+date_time in('1901-01-01 01:01:01','1903-03-03 03:03:03') 
+order by auto;
+
+explain
+select auto from t1 where
+"aaaa" in(string) and 
+"aaaa" in(vstring) and 
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+/* b'001' in(bits) and */
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
+order by auto;
+
+select auto from t1 where
+"aaaa" in(string) and 
+"aaaa" in(vstring) and 
+0xAAAA in(bin) and 
+0xAAAA in(vbin) and 
+/* -1 in(tiny) and */
+/* -1 in (short) and */
+/* -1 in(medium) and */
+/* -1 in(long_int) and */
+/* -1 in(longlong) and */
+1 in(utiny) and 
+1 in(ushort) and 
+1 in(umedium) and 
+1 in(ulong) and 
+1 in(ulonglong) and 
+/* b'001' in(bits) and */
+'one' in(options) and 
+'one' in(flags) and 
+'1901-01-01' in(date_field) and
+'1901' in(year_field) and
+'01:01:01' in(time_field) and 
+'1901-01-01 01:01:01' in(date_time) 
 order by auto;
 
 # Update test
Thread
bk commit into 5.0 tree (mskold:1.1953)Martin Skold18 May