MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Tatjana A Nuernberg Date:February 28 2008 12:55pm
Subject:bk commit into 5.0 tree (tnurnberg:1.2595) BUG#34749
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of tnurnberg.  When tnurnberg does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-28 13:54:58+01:00, tnurnberg@stripped +7 -0
  Bug#34749: Server crash when using NAME_CONST() with an aggregate function
  
  NAME_CONST('whatever', -1) * MAX(whatever) bombed since -1 was
  not seen as constant, but as FUNCTION_UNARY_MINUS(constant)
  while we are at the same time pretending it was a basic const
  item. This confused the aggregate handlers in exciting ways.
  We now make NAME_CONST() behave more consistently.

  mysql-test/r/func_misc.result@stripped, 2008-02-28 13:54:56+01:00, tnurnberg@stripped +19 -0
    show that a combination of NAME_CONST('x', -y) and an aggregate
    no longer crashes the server

  mysql-test/t/func_misc.test@stripped, 2008-02-28 13:54:56+01:00, tnurnberg@stripped +18 -0
    show that a combination of NAME_CONST('x', -y) and an aggregate
    no longer crashes the server

  sql/ha_ndbcluster_cond.cc@stripped, 2008-02-28 13:54:56+01:00, tnurnberg@stripped +6 -3
    tell cluster about "new" function type NEG_FUNC
    (this was previous identified as UNKNOWN_FUNC,
    so we just handle it the same way, that's all.)

  sql/ha_ndbcluster_cond.h@stripped, 2008-02-28 13:54:56+01:00, tnurnberg@stripped +1 -0
    tell cluster about "new" function type NEG_FUNC
    (this was previous identified as UNKNOWN_FUNC,
    so we just handle it the same way, that's all.)

  sql/item.cc@stripped, 2008-02-28 13:54:56+01:00, tnurnberg@stripped +26 -1
    make NAME_CONST() transparent in that type() of
    -constant is that of constant, not that of unary
    minus (id est, FUNC_ITEM).

  sql/item.h@stripped, 2008-02-28 13:54:57+01:00, tnurnberg@stripped +1 -8
    Move constructor to item.cc

  sql/item_func.h@stripped, 2008-02-28 13:54:57+01:00, tnurnberg@stripped +3 -2
    Revert Bug#30832; we can apply the magic more narrowly
    (just for NAME_CONST() rather than all Item_func_neg).
    
    Introduce new function type "NEG_FUNC."

diff -Nrup a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result
--- a/mysql-test/r/func_misc.result	2007-12-13 12:47:21 +01:00
+++ b/mysql-test/r/func_misc.result	2008-02-28 13:54:56 +01:00
@@ -207,6 +207,25 @@ test
 SELECT NAME_CONST('test', 'test');
 test
 test
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+SELECT NAME_CONST('flag',1)    * MAX(a) FROM t1;
+NAME_CONST('flag',1)    * MAX(a)
+3
+SELECT NAME_CONST('flag',1.5)  * MAX(a) FROM t1;
+NAME_CONST('flag',1.5)  * MAX(a)
+4.5
+SELECT NAME_CONST('flag',-1)   * MAX(a) FROM t1;
+NAME_CONST('flag',-1)   * MAX(a)
+-3
+SELECT NAME_CONST('flag',-1.5) * MAX(a) FROM t1;
+NAME_CONST('flag',-1.5) * MAX(a)
+-4.5
+SELECT NAME_CONST('flag', SQRT(4)) * MAX(a) FROM t1;
+ERROR HY000: Incorrect arguments to NAME_CONST
+SELECT NAME_CONST('flag',-SQRT(4)) * MAX(a) FROM t1;
+ERROR HY000: Incorrect arguments to NAME_CONST
+DROP TABLE t1;
 CREATE TABLE t1 (a int);
 INSERT INTO t1 VALUES (5), (2);
 SELECT NAME_CONST(x,2) FROM (SELECT a x FROM t1) t;
diff -Nrup a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test
--- a/mysql-test/t/func_misc.test	2007-12-13 12:47:21 +01:00
+++ b/mysql-test/t/func_misc.test	2008-02-28 13:54:56 +01:00
@@ -205,6 +205,24 @@ SELECT NAME_CONST('test', -1.0);
 SELECT NAME_CONST('test', 'test');
 
 #
+# Bug #34749: Server crash when using NAME_CONST() with an aggregate function
+#
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1),(2),(3);
+# NAME_CONST() + aggregate.
+SELECT NAME_CONST('flag',1)    * MAX(a) FROM t1;
+SELECT NAME_CONST('flag',1.5)  * MAX(a) FROM t1;
+# Now, wrap the INT_ITEM in Item_func_neg and watch the pretty explosions
+SELECT NAME_CONST('flag',-1)   * MAX(a) FROM t1;
+SELECT NAME_CONST('flag',-1.5) * MAX(a) FROM t1;
+--error ER_WRONG_ARGUMENTS
+SELECT NAME_CONST('flag', SQRT(4)) * MAX(a) FROM t1;
+--error ER_WRONG_ARGUMENTS
+SELECT NAME_CONST('flag',-SQRT(4)) * MAX(a) FROM t1;
+DROP TABLE t1;
+
+#
 # Bug #27545: erroneous usage of NAME_CONST with a name as the first parameter 
 #             resolved against a column name of a derived table hangs the client
 #
diff -Nrup a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc
--- a/sql/ha_ndbcluster_cond.cc	2007-10-04 10:52:14 +02:00
+++ b/sql/ha_ndbcluster_cond.cc	2008-02-28 13:54:56 +01:00
@@ -117,7 +117,8 @@ void ndb_serialize_cond(const Item *item
           if (item->type() == Item::FUNC_ITEM)
           {
             Item_func *func_item= (Item_func *) item;
-            if (func_item->functype() == Item_func::UNKNOWN_FUNC &&
+            if ((func_item->functype() == Item_func::UNKNOWN_FUNC ||
+                 func_item->functype() == Item_func::NEG_FUNC) &&
                 func_item->const_item())
             {
               // Skip any arguments since we will evaluate function instead
@@ -369,8 +370,9 @@ void ndb_serialize_cond(const Item *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)
+          if (context->expecting(Item::FUNC_ITEM) ||
+              func_item->functype() == Item_func::UNKNOWN_FUNC ||
+              func_item->functype() == Item_func::NEG_FUNC)
             context->expect_nothing();
           else
           {
@@ -584,6 +586,7 @@ void ndb_serialize_cond(const Item *item
             context->expect(Item::FUNC_ITEM);
             break;
           }
+          case Item_func::NEG_FUNC:
           case Item_func::UNKNOWN_FUNC:
           {
             DBUG_PRINT("info", ("UNKNOWN_FUNC %s", 
diff -Nrup a/sql/ha_ndbcluster_cond.h b/sql/ha_ndbcluster_cond.h
--- a/sql/ha_ndbcluster_cond.h	2007-06-19 13:56:00 +02:00
+++ b/sql/ha_ndbcluster_cond.h	2008-02-28 13:54:56 +01:00
@@ -228,6 +228,7 @@ public:
     case (Item_func::ISNOTNULL_FUNC): { return NDB_ISNOTNULL_FUNC; }
     case (Item_func::LIKE_FUNC): { return NDB_LIKE_FUNC; }
     case (Item_func::NOT_FUNC): { return NDB_NOT_FUNC; }
+    case (Item_func::NEG_FUNC): { return NDB_UNKNOWN_FUNC; }
     case (Item_func::UNKNOWN_FUNC): { return NDB_UNKNOWN_FUNC; }
     case (Item_func::COND_AND_FUNC): { return NDB_COND_AND_FUNC; }
     case (Item_func::COND_OR_FUNC): { return NDB_COND_OR_FUNC; }
diff -Nrup a/sql/item.cc b/sql/item.cc
--- a/sql/item.cc	2008-01-11 18:57:33 +01:00
+++ b/sql/item.cc	2008-02-28 13:54:56 +01:00
@@ -1207,6 +1207,22 @@ bool Item_name_const::is_null()
   return value_item->is_null();
 }
 
+
+Item_name_const::Item_name_const(Item *name_arg, Item *val):
+    value_item(val), name_item(name_arg)
+{
+  if (!(valid_args= name_item->basic_const_item() &&
+                    (value_item->basic_const_item() ||
+                     ((value_item->type() == FUNC_ITEM) &&
+                      (((Item_func *) value_item)->functype() ==
+                                                 Item_func::NEG_FUNC) &&
+                      (((Item_func *) value_item)->key_item()->type() !=
+                       FUNC_ITEM)))))
+    my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST");
+  Item::maybe_null= TRUE;
+}
+
+
 Item::Type Item_name_const::type() const
 {
   /*
@@ -1218,8 +1234,17 @@ Item::Type Item_name_const::type() const
     if (item->type() == FIELD_ITEM) 
       ((Item_field *) item)->... 
     we return NULL_ITEM in the case to avoid wrong casting.
+
+    valid_args guarantees value_item->basic_const_item(); if type is
+    FUNC_ITEM, then we have a fudged item_func_neg() on our hands
+    and return the underlying type.
   */
-  return valid_args ? value_item->type() : NULL_ITEM;
+  return valid_args ?
+             (((value_item->type() == FUNC_ITEM) &&
+               (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ?
+             ((Item_func *) value_item)->key_item()->type() :
+             value_item->type()) :
+           NULL_ITEM;
 }
 
 
diff -Nrup a/sql/item.h b/sql/item.h
--- a/sql/item.h	2007-12-13 11:49:11 +01:00
+++ b/sql/item.h	2008-02-28 13:54:57 +01:00
@@ -1113,14 +1113,7 @@ class Item_name_const : public Item
   Item *name_item;
   bool valid_args;
 public:
-  Item_name_const(Item *name_arg, Item *val):
-    value_item(val), name_item(name_arg)
-  {
-    if (!(valid_args= name_item->basic_const_item() & 
-                      value_item->basic_const_item()))
-      my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST");
-    Item::maybe_null= TRUE;
-  }
+  Item_name_const(Item *name_arg, Item *val);
 
   bool fix_fields(THD *, Item **);
 
diff -Nrup a/sql/item_func.h b/sql/item_func.h
--- a/sql/item_func.h	2007-12-13 11:49:11 +01:00
+++ b/sql/item_func.h	2008-02-28 13:54:57 +01:00
@@ -54,7 +54,8 @@ public:
                   NOT_FUNC, NOT_ALL_FUNC,
                   NOW_FUNC, TRIG_COND_FUNC,
                   SUSERVAR_FUNC, GUSERVAR_FUNC, COLLATE_FUNC,
-                  EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC };
+                  EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC,
+                  NEG_FUNC };
   enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL,
                        OPTIMIZE_EQUAL };
   enum Type type() const { return FUNC_ITEM; }
@@ -466,7 +467,7 @@ public:
   longlong int_op();
   my_decimal *decimal_op(my_decimal *);
   const char *func_name() const { return "-"; }
-  virtual bool basic_const_item() const { return args[0]->basic_const_item(); }
+  enum Functype functype() const   { return NEG_FUNC; }
   void fix_length_and_dec();
   void fix_num_length_and_dec();
   uint decimal_precision() const { return args[0]->decimal_precision(); }
Thread
bk commit into 5.0 tree (tnurnberg:1.2595) BUG#34749Tatjana A Nuernberg28 Feb