--- mysql/sql/item_func.cc +++ mysql/sql/item_func.cc @@ -2802,6 +2802,27 @@ } +bool udf_handler::make_unique(THD *thd) +{ + if (u_d->func_init) + { + thd->net.last_error[0]=0; + Udf_func_init init= u_d->func_init; + if ((error=(uchar) init(&initid, &f_args, thd->net.last_error))) + { + my_error(ER_CANT_INITIALIZE_UDF, MYF(0), + u_d->name.str, thd->net.last_error); + free_udf(u_d); + DBUG_RETURN(FALSE); + } + udf_inc_usage_count(u_d); + not_original = FALSE; + buffers = NULL; + } + return TRUE; +} + + bool udf_handler::fix_fields(THD *thd, Item_result_field *func, uint arg_count, Item **arguments) --- mysql/sql/item_sum.cc +++ mysql/sql/item_sum.cc @@ -2380,7 +2380,7 @@ the function. */ -void Item_sum_count_distinct::make_unique() +bool Item_sum_count_distinct::make_unique(THD *thd) { table=0; original= 0; @@ -2389,6 +2389,8 @@ is_evaluated= FALSE; tmp_table_param= 0; always_null= FALSE; + + return TRUE; } @@ -2644,6 +2646,12 @@ } +bool Item_udf_sum::make_unique(THD *thd) +{ + return udf.make_unique(thd); +} + + void Item_udf_sum::print(String *str, enum_query_type query_type) { str->append(func_name()); @@ -3366,13 +3374,15 @@ /* This is used by rollup to create a separate usable copy of the function */ -void Item_func_group_concat::make_unique() +bool Item_func_group_concat::make_unique(THD *thd) { tmp_table_param= 0; table=0; original= 0; force_copy_fields= 1; tree= 0; + + return TRUE; } --- mysql/sql/item_sum.h +++ mysql/sql/item_sum.h @@ -354,7 +354,7 @@ void no_rows_in_result() { clear(); } virtual bool setup(THD* thd) {return 0;} - virtual void make_unique() {} + virtual bool make_unique(THD *thd) {return TRUE;} Item *get_tmp_table_item(THD *thd); virtual Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); @@ -617,7 +617,7 @@ void update_field() { return ; } // Never called const char *func_name() const { return "count(distinct "; } bool setup(THD *thd); - void make_unique(); + bool make_unique(THD *thd); Item *copy_or_same(THD* thd); void no_rows_in_result() {} }; @@ -989,6 +989,7 @@ virtual bool have_field_update(void) const { return 0; } void clear(); + bool make_unique(THD *thd); bool add(); void reset_field() {}; void update_field() {}; @@ -1243,7 +1244,7 @@ void update_field() { DBUG_ASSERT(0); } // not used bool fix_fields(THD *,Item **); bool setup(THD *thd); - void make_unique(); + bool make_unique(THD *thd); double val_real() { String *res; res=val_str(&str_value); --- mysql/sql/sql_select.cc +++ mysql/sql/sql_select.cc @@ -16011,6 +16011,7 @@ List_iterator_fast it(fields_arg); Item *first_field= sel_fields.head(); uint level; + bool res; /* Create field lists for the different levels @@ -16078,7 +16079,11 @@ sub selects. */ item= item->copy_or_same(thd); - ((Item_sum*) item)->make_unique(); + res = ((Item_sum*) item)->make_unique(thd); + if (!res) { + delete item; + return 1; + } *(*func)= (Item_sum*) item; (*func)++; } --- mysql/sql/sql_udf.cc +++ mysql/sql/sql_udf.cc @@ -312,6 +312,20 @@ } +void udf_inc_usage_count(udf_func *udf) +{ + DBUG_ENTER("free_udf"); + + if (!initialized) + DBUG_VOID_RETURN; + + rw_wrlock(&THR_LOCK_udf); + udf->usage_count++; + rw_unlock(&THR_LOCK_udf); + + DBUG_VOID_RETURN; +} + /* This is only called if using_udf_functions != 0 */ udf_func *find_udf(const char *name,uint length,bool mark_used) --- mysql/sql/sql_udf.h +++ mysql/sql/sql_udf.h @@ -74,6 +74,7 @@ bool get_arguments(); bool fix_fields(THD *thd, Item_result_field *item, uint arg_count, Item **args); + bool make_unique(THD *thd); void cleanup(); double val(my_bool *null_value) { @@ -137,6 +138,7 @@ void udf_init(void),udf_free(void); udf_func *find_udf(const char *name, uint len=0,bool mark_used=0); void free_udf(udf_func *udf); +void udf_inc_usage_count(udf_func *udf); int mysql_create_function(THD *thd,udf_func *udf); int mysql_drop_function(THD *thd,const LEX_STRING *name); #endif