From c6b4d7a7c41a2469a69e0d2a8a883c83cbff3ea9 Mon Sep 17 00:00:00 2001 From: "tnurnberg@mysql.com/white.intern.koehntopp.de" <> Date: Thu, 28 Feb 2008 14:23:22 +0100 Subject: 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. --- sql/ha_ndbcluster_cond.cc | 9 ++++++--- sql/ha_ndbcluster_cond.h | 1 + sql/item.cc | 27 ++++++++++++++++++++++++++- sql/item.h | 9 +-------- sql/item_func.h | 5 +++-- 5 files changed, 37 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/ha_ndbcluster_cond.cc b/sql/ha_ndbcluster_cond.cc index c7b185a92f0..f5b41959b40 100644 --- a/sql/ha_ndbcluster_cond.cc +++ b/sql/ha_ndbcluster_cond.cc @@ -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 @@ -369,8 +370,9 @@ 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) + 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, void *arg) context->expect(Item::FUNC_ITEM); break; } + case Item_func::NEG_FUNC: case Item_func::UNKNOWN_FUNC: { DBUG_PRINT("info", ("UNKNOWN_FUNC %s", diff --git a/sql/ha_ndbcluster_cond.h b/sql/ha_ndbcluster_cond.h index 6baf6945b58..6504df8d9d4 100644 --- a/sql/ha_ndbcluster_cond.h +++ b/sql/ha_ndbcluster_cond.h @@ -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 --git a/sql/item.cc b/sql/item.cc index 713e7709bcb..acd8053cbdf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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 --git a/sql/item.h b/sql/item.h index 5f511557f47..9af98e0efdb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -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 --git a/sql/item_func.h b/sql/item_func.h index 940586fce01..6dcf32cba07 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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(); } -- cgit v1.2.1