diff options
Diffstat (limited to 'sql/item_sum.h')
-rw-r--r-- | sql/item_sum.h | 418 |
1 files changed, 315 insertions, 103 deletions
diff --git a/sql/item_sum.h b/sql/item_sum.h index 6835b1e8fae..9593c8ddbba 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -26,34 +26,42 @@ class Item_sum :public Item_result_field { public: - enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, - MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,SUM_BIT_FUNC, - UDF_SUM_FUNC }; - - Item **args,*tmp_args[2]; + enum Sumfunctype + { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC, + MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC, + UDF_SUM_FUNC, GROUP_CONCAT_FUNC + }; + + Item **args, *tmp_args[2]; + Item **args_copy; /* copy of arguments for PS */ uint arg_count; bool quick_group; /* If incremental update of fields */ - Item_sum() : arg_count(0),quick_group(1) { with_sum_func=1; } - Item_sum(Item *a) :quick_group(1) + void mark_as_sum_func(); + Item_sum() :args_copy(0), arg_count(0), quick_group(1) + { + mark_as_sum_func(); + } + Item_sum(Item *a) + :args(tmp_args), args_copy(0), arg_count(1), quick_group(1) { - arg_count=1; - args=tmp_args; args[0]=a; - with_sum_func = 1; + mark_as_sum_func(); } - Item_sum( Item *a, Item *b ) :quick_group(1) + Item_sum( Item *a, Item *b ) + :args(tmp_args), args_copy(0), arg_count(2), quick_group(1) { - arg_count=2; - args=tmp_args; args[0]=a; args[1]=b; - with_sum_func=1; + mark_as_sum_func(); } Item_sum(List<Item> &list); - ~Item_sum() { result_field=0; } + //Copy constructor, need to perform subselects with temporary tables + Item_sum(THD *thd, Item_sum *item); + void cleanup(); enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; - virtual void reset()=0; + inline bool reset() { clear(); return add(); }; + virtual void clear()= 0; virtual bool add()=0; /* Called when new group is started and results are being saved in @@ -72,7 +80,7 @@ public: virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } virtual const char *func_name() const { return "?"; } virtual Item *result_item(Field *field) - { return new Item_field(field);} + { return new Item_field(field);} table_map used_tables() const { return ~(table_map) 0; } /* Not used */ bool const_item() const { return 0; } bool is_null() { return null_value; } @@ -82,7 +90,12 @@ public: void fix_num_length_and_dec(); void no_rows_in_result() { reset(); } virtual bool setup(THD *thd) {return 0;} - unsigned int size_of() { return sizeof(*this);} + virtual void make_unique() {} + Item *get_tmp_table_item(THD *thd); + bool save_args_for_prepared_statements(THD *); + bool save_args(Statement* stmt); + + bool walk (Item_processor processor, byte *argument); }; @@ -93,11 +106,12 @@ public: Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List<Item> &list) :Item_sum(list) {} - bool fix_fields(THD *,struct st_table_list *); - longlong val_int() { return (longlong) val(); } /* Real as default */ + Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} + bool fix_fields(THD *, TABLE_LIST *, Item **); + longlong val_int() + { DBUG_ASSERT(fixed == 1); return (longlong) val(); } /* Real as default */ String *val_str(String*str); void reset_field(); - unsigned int size_of() { return sizeof(*this);} }; @@ -106,10 +120,10 @@ class Item_sum_int :public Item_sum_num public: Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(List<Item> &list) :Item_sum_num(list) {} - double val() { return (double) val_int(); } + Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} + double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } - unsigned int size_of() { return sizeof(*this);} void fix_length_and_dec() { decimals=0; max_length=21; maybe_null=null_value=0; } }; @@ -122,15 +136,17 @@ class Item_sum_sum :public Item_sum_num public: Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {} + Item_sum_sum(THD *thd, Item_sum_sum *item) + :Item_sum_num(thd, item), sum(item->sum) {} enum Sumfunctype sum_func () const {return SUM_FUNC;} - void reset(); + void clear(); bool add(); double val(); void reset_field(); void update_field(); void no_rows_in_result() {} const char *func_name() const { return "sum"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; @@ -143,10 +159,14 @@ class Item_sum_count :public Item_sum_int Item_sum_count(Item *item_par) :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0) {} + Item_sum_count(THD *thd, Item_sum_count *item) + :Item_sum_int(thd, item), count(item->count), + used_table_cache(item->used_table_cache) + {} table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_FUNC; } - void reset(); + void clear(); void no_rows_in_result() { count=0; } bool add(); void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; } @@ -154,7 +174,7 @@ class Item_sum_count :public Item_sum_int void reset_field(); void update_field(); const char *func_name() const { return "count"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; @@ -164,51 +184,79 @@ class Item_sum_count_distinct :public Item_sum_int { TABLE *table; table_map used_table_cache; - bool fix_fields(THD *thd,TABLE_LIST *tables); uint32 *field_lengths; TMP_TABLE_PARAM *tmp_table_param; - TREE tree; - uint key_length; + TREE tree_base; + TREE *tree; + /* + Following is 0 normal object and pointer to original one for copy + (to correctly free resources) + */ + Item_sum_count_distinct *original; - // calculated based on max_heap_table_size. If reached, - // walk the tree and dump it into MyISAM table + uint key_length; + CHARSET_INFO *key_charset; + + /* + Calculated based on max_heap_table_size. If reached, + walk the tree and dump it into MyISAM table + */ uint max_elements_in_tree; - // the first few bytes of record ( at least one) - // are just markers for deleted and NULLs. We want to skip them since - // they will just bloat the tree without providing any valuable info + /* + The first few bytes of record ( at least one) + are just markers for deleted and NULLs. We want to skip them since + they will just bloat the tree without providing any valuable info + */ int rec_offset; - // If there are no blobs, we can use a tree, which - // is faster than heap table. In that case, we still use the table - // to help get things set up, but we insert nothing in it + /* + If there are no blobs, we can use a tree, which + is faster than heap table. In that case, we still use the table + to help get things set up, but we insert nothing in it + */ bool use_tree; bool always_null; // Set to 1 if the result is always NULL int tree_to_myisam(); friend int composite_key_cmp(void* arg, byte* key1, byte* key2); + friend int simple_str_key_cmp(void* arg, byte* key1, byte* key2); + friend int simple_raw_key_cmp(void* arg, byte* key1, byte* key2); friend int dump_leaf(byte* key, uint32 count __attribute__((unused)), Item_sum_count_distinct* item); public: Item_sum_count_distinct(List<Item> &list) - :Item_sum_int(list),table(0),used_table_cache(~(table_map) 0), - tmp_table_param(0),use_tree(0),always_null(0) - { quick_group=0; } - ~Item_sum_count_distinct(); + :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0), + tmp_table_param(0), tree(&tree_base), original(0), use_tree(0), + always_null(0) + { quick_group= 0; } + Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) + :Item_sum_int(thd, item), table(item->table), + used_table_cache(item->used_table_cache), + field_lengths(item->field_lengths), + tmp_table_param(item->tmp_table_param), + tree(item->tree), original(item), key_length(item->key_length), + max_elements_in_tree(item->max_elements_in_tree), + rec_offset(item->rec_offset), use_tree(item->use_tree), + always_null(item->always_null) + {} + void cleanup(); table_map used_tables() const { return used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } - void reset(); + void clear(); bool add(); longlong val_int(); void reset_field() { return ;} // Never called void update_field() { return ; } // Never called const char *func_name() const { return "count_distinct"; } bool setup(THD *thd); + void make_unique(); + Item *copy_or_same(THD* thd); void no_rows_in_result() {} - unsigned int size_of() { return sizeof(*this);} + void print(String *str); }; @@ -223,12 +271,11 @@ public: Item_avg_field(Item_sum_avg *item); enum Type type() const { return FIELD_AVG_ITEM; } double val(); - longlong val_int() { return (longlong) val(); } + longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); } bool is_null() { (void) val_int(); return null_value; } String *val_str(String*); - void make_field(Send_field *field); + enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } void fix_length_and_dec() {} - unsigned int size_of() { return sizeof(*this);} }; @@ -240,9 +287,11 @@ class Item_sum_avg :public Item_sum_num ulonglong count; public: - Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {} + Item_sum_avg(Item *item_par) :Item_sum_num(item_par), sum(0.0), count(0) {} + Item_sum_avg(THD *thd, Item_sum_avg *item) + :Item_sum_num(thd, item), sum(item->sum), count(item->count) {} enum Sumfunctype sum_func () const {return AVG_FUNC;} - void reset(); + void clear(); bool add(); double val(); void reset_field(); @@ -251,47 +300,89 @@ class Item_sum_avg :public Item_sum_num { return new Item_avg_field(this); } void no_rows_in_result() {} const char *func_name() const { return "avg"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; -class Item_sum_std; +class Item_sum_variance; -class Item_std_field :public Item_result_field +class Item_variance_field :public Item_result_field { public: Field *field; - Item_std_field(Item_sum_std *item); - enum Type type() const { return FIELD_STD_ITEM; } + Item_variance_field(Item_sum_variance *item); + enum Type type() const {return FIELD_VARIANCE_ITEM; } double val(); - longlong val_int() { return (longlong) val(); } + longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); } String *val_str(String*); bool is_null() { (void) val_int(); return null_value; } - void make_field(Send_field *field); + enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } void fix_length_and_dec() {} - unsigned int size_of() { return sizeof(*this);} }; -class Item_sum_std :public Item_sum_num + +/* + variance(a) = + + = sum (ai - avg(a))^2 / count(a) ) + = sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a) + = (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) = + = (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) = + = (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) = + = (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) = + = (sum(ai^2) - sum(a)^2/count(a))/count(a) +*/ + +class Item_sum_variance : public Item_sum_num { - double sum; - double sum_sqr; + double sum, sum_sqr; ulonglong count; void fix_length_and_dec() { decimals+=4; maybe_null=1; } public: - Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {} - enum Sumfunctype sum_func () const { return STD_FUNC; } - void reset(); + Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {} + Item_sum_variance(THD *thd, Item_sum_variance *item): + Item_sum_num(thd, item), sum(item->sum), sum_sqr(item->sum_sqr), + count(item->count) {} + enum Sumfunctype sum_func () const { return VARIANCE_FUNC; } + void clear(); bool add(); double val(); void reset_field(); void update_field(); Item *result_item(Field *field) - { return new Item_std_field(this); } - const char *func_name() const { return "std"; } - unsigned int size_of() { return sizeof(*this);} + { return new Item_variance_field(this); } + const char *func_name() const { return "variance"; } + Item *copy_or_same(THD* thd); +}; + +class Item_sum_std; + +class Item_std_field :public Item_variance_field +{ +public: + Item_std_field(Item_sum_std *item); + enum Type type() const { return FIELD_STD_ITEM; } + double val(); }; +/* + standard_deviation(a) = sqrt(variance(a)) +*/ + +class Item_sum_std :public Item_sum_variance +{ + public: + Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {} + Item_sum_std(THD *thd, Item_sum_std *item) + :Item_sum_variance(thd, item) + {} + enum Sumfunctype sum_func () const { return STD_FUNC; } + double val(); + Item *result_item(Field *field) + { return new Item_std_field(this); } + const char *func_name() const { return "std"; } + Item *copy_or_same(THD* thd); +}; // This class is a string or number function depending on num_func @@ -302,24 +393,33 @@ class Item_sum_hybrid :public Item_sum double sum; longlong sum_int; Item_result hybrid_type; + enum_field_types hybrid_field_type; int cmp_sign; table_map used_table_cache; + CHARSET_INFO *cmp_charset; public: - Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign), - used_table_cache(~(table_map) 0) + Item_sum_hybrid(Item *item_par,int sign) + :Item_sum(item_par), sum(0.0), sum_int(0), + hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG), + cmp_sign(sign), used_table_cache(~(table_map) 0), + cmp_charset(&my_charset_bin) {} - bool fix_fields(THD *,struct st_table_list *); + Item_sum_hybrid(THD *thd, Item_sum_hybrid *item): + Item_sum(thd, item), value(item->value), + sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type), + hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign), + used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {} + bool fix_fields(THD *, TABLE_LIST *, Item **); table_map used_tables() const { return used_table_cache; } bool const_item() const { return !used_table_cache; } - void reset() + void clear() { sum=0.0; sum_int=0; value.length(0); null_value=1; - add(); } double val(); longlong val_int(); @@ -328,11 +428,11 @@ class Item_sum_hybrid :public Item_sum void make_const() { used_table_cache=0; } bool keep_field_type(void) const { return 1; } enum Item_result result_type () const { return hybrid_type; } + enum enum_field_types field_type() const { return hybrid_field_type; } void update_field(); void min_max_update_str_field(); void min_max_update_real_field(); void min_max_update_int_field(); - unsigned int size_of() { return sizeof(*this);} }; @@ -340,11 +440,12 @@ class Item_sum_min :public Item_sum_hybrid { public: Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {} + Item_sum_min(THD *thd, Item_sum_min *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MIN_FUNC;} bool add(); const char *func_name() const { return "min"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; @@ -352,11 +453,12 @@ class Item_sum_max :public Item_sum_hybrid { public: Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {} + Item_sum_max(THD *thd, Item_sum_max *item) :Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func () const {return MAX_FUNC;} bool add(); const char *func_name() const { return "max"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; @@ -368,12 +470,13 @@ protected: public: Item_sum_bit(Item *item_par,ulonglong reset_arg) :Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {} + Item_sum_bit(THD *thd, Item_sum_bit *item): + Item_sum_int(thd, item), reset_bits(item->reset_bits), bits(item->bits) {} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;} - void reset(); + void clear(); longlong val_int(); void reset_field(); void update_field(); - unsigned int size_of() { return sizeof(*this);} void fix_length_and_dec() { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -383,24 +486,38 @@ class Item_sum_or :public Item_sum_bit { public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} + Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_or"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); }; class Item_sum_and :public Item_sum_bit { -public: + public: Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} + Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} bool add(); const char *func_name() const { return "bit_and"; } - unsigned int size_of() { return sizeof(*this);} + Item *copy_or_same(THD* thd); +}; + +class Item_sum_xor :public Item_sum_bit +{ + public: + Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} + Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} + bool add(); + const char *func_name() const { return "bit_xor"; } + Item *copy_or_same(THD* thd); }; + /* -** user defined aggregates + User defined aggregates */ + #ifdef HAVE_DLOPEN class Item_udf_sum : public Item_sum @@ -413,20 +530,22 @@ public: Item_udf_sum( udf_func *udf_arg, List<Item> &list ) :Item_sum( list ), udf(udf_arg) { quick_group=0;} - ~Item_udf_sum() {} + Item_udf_sum(THD *thd, Item_udf_sum *item) + :Item_sum(thd, item), udf(item->udf) {} const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd,struct st_table_list *tables) + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { + DBUG_ASSERT(fixed == 0); + fixed= 1; return udf.fix_fields(thd,tables,this,this->arg_count,this->args); } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } virtual bool have_field_update(void) const { return 0; } - void reset(); + void clear(); bool add(); void reset_field() {}; void update_field() {}; - unsigned int size_of() { return sizeof(*this);} }; @@ -436,11 +555,14 @@ class Item_sum_udf_float :public Item_udf_sum Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - ~Item_sum_udf_float() {} - longlong val_int() { return (longlong) Item_sum_udf_float::val(); } + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) + :Item_udf_sum(thd, item) {} + longlong val_int() + { DBUG_ASSERT(fixed == 1); return (longlong) Item_sum_udf_float::val(); } double val(); String *val_str(String*str); void fix_length_and_dec() { fix_num_length_and_dec(); } + Item *copy_or_same(THD* thd); }; @@ -450,12 +572,15 @@ public: Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - ~Item_sum_udf_int() {} + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) + :Item_udf_sum(thd, item) {} longlong val_int(); - double val() { return (double) Item_sum_udf_int::val_int(); } + double val() + { DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); } String *val_str(String*str); enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() { decimals=0; max_length=21; } + Item *copy_or_same(THD* thd); }; @@ -465,20 +590,25 @@ public: Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {} Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_udf_sum(udf_arg,list) {} - ~Item_sum_udf_str() {} + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) + :Item_udf_sum(thd, item) {} String *val_str(String *); double val() { + int err; String *res; res=val_str(&str_value); - return res ? atof(res->c_ptr()) : 0.0; + return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), + (char**) 0, &err) : 0.0; } longlong val_int() { + int err; String *res; res=val_str(&str_value); - return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; + return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10, (char**) 0, &err) : (longlong) 0; } enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); + Item *copy_or_same(THD* thd); }; #else /* Dummy functions to get sql_yacc.cc compiled */ @@ -488,10 +618,11 @@ class Item_sum_udf_float :public Item_sum_num public: Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - ~Item_sum_udf_float() {} + Item_sum_udf_float(THD *thd, Item_sum_udf_float *item) + :Item_sum_num(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } - double val() { return 0.0; } - void reset() {} + double val() { DBUG_ASSERT(fixed == 1); return 0.0; } + void clear() {} bool add() { return 0; } void update_field() {} }; @@ -502,11 +633,12 @@ class Item_sum_udf_int :public Item_sum_num public: Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - ~Item_sum_udf_int() {} + Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) + :Item_sum_num(thd, item) {} enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } - longlong val_int() { return 0; } - double val() { return 0; } - void reset() {} + longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; } + double val() { DBUG_ASSERT(fixed == 1); return 0; } + void clear() {} bool add() { return 0; } void update_field() {} }; @@ -517,16 +649,96 @@ class Item_sum_udf_str :public Item_sum_num public: Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {} Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} - ~Item_sum_udf_str() {} - String *val_str(String *) { null_value=1; return 0; } - double val() { null_value=1; return 0.0; } - longlong val_int() { null_value=1; return 0; } + Item_sum_udf_str(THD *thd, Item_sum_udf_str *item) + :Item_sum_num(thd, item) {} + String *val_str(String *) + { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } + double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; } + longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; } enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec() { maybe_null=1; max_length=0; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } - void reset() {} + void clear() {} bool add() { return 0; } void update_field() {} }; #endif /* HAVE_DLOPEN */ + +class MYSQL_ERROR; + +class Item_func_group_concat : public Item_sum +{ + THD *item_thd; + TMP_TABLE_PARAM *tmp_table_param; + uint max_elements_in_tree; + MYSQL_ERROR *warning; + bool warning_available; + uint key_length; + bool tree_mode; + bool distinct; + bool warning_for_row; + bool always_null; + + friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1, + byte* key2); + friend int group_concat_key_cmp_with_order(void* arg, byte* key1, + byte* key2); + friend int group_concat_key_cmp_with_distinct_and_order(void* arg, + byte* key1, + byte* key2); + friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), + Item_func_group_concat *group_concat_item); + + public: + String result; + String *separator; + TREE tree_base; + TREE *tree; + TABLE *table; + ORDER **order; + TABLE_LIST *tables_list; + ulong group_concat_max_len; + uint show_elements; + uint arg_count_order; + uint arg_count_field; + uint field_list_offset; + uint count_cut_values; + /* + Following is 0 normal object and pointer to original one for copy + (to correctly free resources) + */ + Item_func_group_concat *original; + + Item_func_group_concat(bool is_distinct,List<Item> *is_select, + SQL_LIST *is_order,String *is_separator); + + Item_func_group_concat(THD *thd, Item_func_group_concat *item); + ~Item_func_group_concat(); + void cleanup(); + + enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} + const char *func_name() const { return "group_concat"; } + virtual Item_result result_type () const { return STRING_RESULT; } + void clear(); + bool add(); + void reset_field(); + bool fix_fields(THD *, TABLE_LIST *, Item **); + bool setup(THD *thd); + void make_unique(); + virtual void update_field() {} + double val() + { + String *res; res=val_str(&str_value); + return res ? my_atof(res->c_ptr()) : 0.0; + } + longlong val_int() + { + String *res; res=val_str(&str_value); + return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0; + } + String* val_str(String* str); + Item *copy_or_same(THD* thd); + void no_rows_in_result() {} + void print(String *str); +}; |