Commit c6b4d7a7 authored by tnurnberg@mysql.com/white.intern.koehntopp.de's avatar tnurnberg@mysql.com/white.intern.koehntopp.de
Browse files

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.
parent 140ca595
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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;
+18 −0
Original line number Diff line number Diff line
@@ -204,6 +204,24 @@ SELECT NAME_CONST('test', 1.0);
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
+6 −3
Original line number Diff line number Diff line
@@ -117,7 +117,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
          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
@@ -370,7 +371,8 @@ void ndb_serialize_cond(const Item *item, void *arg)
          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)
              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, void *arg)
            context->expect(Item::FUNC_ITEM);
            break;
          }
          case Item_func::NEG_FUNC:
          case Item_func::UNKNOWN_FUNC:
          {
            DBUG_PRINT("info", ("UNKNOWN_FUNC %s", 
+1 −0
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ class Ndb_item : public Sql_alloc
    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; }
+26 −1
Original line number Diff line number Diff line
@@ -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;
}


Loading