diff options
-rw-r--r-- | mysql-test/r/func_gconcat.result | 20 | ||||
-rw-r--r-- | mysql-test/t/func_gconcat.test | 16 | ||||
-rw-r--r-- | sql/item_sum.cc | 13 | ||||
-rw-r--r-- | sql/item_sum.h | 532 |
4 files changed, 218 insertions, 363 deletions
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 1ad412209ad..6461c393d51 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -576,3 +576,23 @@ group_concat('x') NULL 1 drop table t1; +CREATE TABLE t1 (id int, a varchar(9)); +INSERT INTO t1 VALUES +(2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, ''); +SELECT GROUP_CONCAT(a) FROM t1; +GROUP_CONCAT(a) +,,x,y,z, +SELECT GROUP_CONCAT(a ORDER BY a) FROM t1; +GROUP_CONCAT(a ORDER BY a) +,,,x,y,z +SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id; +GROUP_CONCAT(a) +,y +,x +z, +SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id; +GROUP_CONCAT(a ORDER BY a) +,y +,x +,z +DROP TABLE t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 896c377662b..a519d51e0b5 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -373,4 +373,20 @@ select * from (select group_concat(a) from t1) t2; select group_concat('x') UNION ALL select 1; drop table t1; +# +# Bug #12863 : missing separators after first empty cancatanated elements +# + +CREATE TABLE t1 (id int, a varchar(9)); +INSERT INTO t1 VALUES + (2, ''), (1, ''), (2, 'x'), (1, 'y'), (3, 'z'), (3, ''); + +SELECT GROUP_CONCAT(a) FROM t1; +SELECT GROUP_CONCAT(a ORDER BY a) FROM t1; + +SELECT GROUP_CONCAT(a) FROM t1 GROUP BY id; +SELECT GROUP_CONCAT(a ORDER BY a) FROM t1 GROUP BY id; + +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 17d82e3fc98..2ed1a18c3b0 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2740,8 +2740,10 @@ int dump_leaf_key(byte* key, element_count count __attribute__((unused)), String *result= &item->result; Item **arg= item->args, **arg_end= item->args + item->arg_count_field; - if (result->length()) - result->append(*item->separator); + if (item->no_appended) + item->no_appended= FALSE; + else + item->result.append(*item->separator); tmp.length(0); @@ -2925,6 +2927,7 @@ void Item_func_group_concat::clear() result.copy(); null_value= TRUE; warning_for_row= FALSE; + no_appended= TRUE; if (tree) reset_tree(tree); /* No need to reset the table as we never call write_row */ @@ -2969,6 +2972,12 @@ bool Item_func_group_concat::add() } +void Item_func_group_concat::reset_field() +{ + DBUG_ASSERT(0); +} + + bool Item_func_group_concat::fix_fields(THD *thd, Item **ref) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 0da9178eabf..d53d8d861ae 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -27,9 +27,9 @@ class Item_sum :public Item_result_field { public: enum Sumfunctype - { COUNT_FUNC, COUNT_DISTINCT_FUNC, SUM_FUNC, SUM_DISTINCT_FUNC, AVG_FUNC, - AVG_DISTINCT_FUNC, MIN_FUNC, MAX_FUNC, UNIQUE_USERS_FUNC, STD_FUNC, - VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC + { 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]; @@ -66,9 +66,6 @@ public: a temporary table. Similar to reset(), but must also store value in result_field. Like reset() it is supposed to reset start value to default. - This set of methods (reult_field(), reset_field, update_field()) of - Item_sum is used only if quick_group is not null. Otherwise - copy_or_same() is used to obtain a copy of this item. */ virtual void reset_field()=0; /* @@ -79,24 +76,9 @@ public: virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } - /* - This method is used for debug purposes to print the name of an - item to the debug log. The second use of this method is as - a helper function of print(), where it is applicable. - To suit both goals it should return a meaningful, - distinguishable and sintactically correct string. This method - should not be used for runtime type identification, use enum - {Sum}Functype and Item_func::functype()/Item_sum::sum_func() - instead. - - NOTE: for Items inherited from Item_sum, func_name() return part of - function name till first argument (including '(') to make difference in - names for functions with 'distinct' clause and without 'distinct' and - also to make printing of items inherited from Item_sum uniform. - */ - virtual const char *func_name() const= 0; + 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; } @@ -108,8 +90,7 @@ public: virtual bool setup(THD *thd) {return 0;} virtual void make_unique() {} Item *get_tmp_table_item(THD *thd); - virtual Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length); + bool walk (Item_processor processor, byte *argument); }; @@ -122,14 +103,10 @@ public: Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(List<Item> &list) :Item_sum(list) {} Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {} - bool fix_fields(THD *, Item **); + bool fix_fields(THD *, TABLE_LIST *, Item **); longlong val_int() - { - DBUG_ASSERT(fixed == 1); - return (longlong) val_real(); /* Real as default */ - } + { DBUG_ASSERT(fixed == 1); return (longlong) val(); } /* Real as default */ String *val_str(String*str); - my_decimal *val_decimal(my_decimal *); void reset_field(); }; @@ -140,9 +117,8 @@ public: Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(List<Item> &list) :Item_sum_num(list) {} Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {} - double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } + double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } String *val_str(String*str); - my_decimal *val_decimal(my_decimal *); enum Item_result result_type () const { return INT_RESULT; } void fix_length_and_dec() { decimals=0; max_length=21; maybe_null=null_value=0; } @@ -151,115 +127,25 @@ public: class Item_sum_sum :public Item_sum_num { -protected: - Item_result hybrid_type; double sum; - my_decimal dec_buffs[2]; - uint curr_dec_buff; - void fix_length_and_dec(); + void fix_length_and_dec() { maybe_null=null_value=1; } -public: - Item_sum_sum(Item *item_par) :Item_sum_num(item_par) {} - Item_sum_sum(THD *thd, Item_sum_sum *item); + 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 clear(); bool add(); - double val_real(); - longlong val_int(); - String *val_str(String*str); - my_decimal *val_decimal(my_decimal *); - enum Item_result result_type () const { return hybrid_type; } + double val(); void reset_field(); void update_field(); void no_rows_in_result() {} - const char *func_name() const { return "sum("; } + const char *func_name() const { return "sum"; } Item *copy_or_same(THD* thd); }; - -/* Common class for SUM(DISTINCT), AVG(DISTINCT) */ - -class Unique; - -class Item_sum_distinct :public Item_sum_num -{ -protected: - /* storage for the summation result */ - ulonglong count; - Hybrid_type val; - /* storage for unique elements */ - Unique *tree; - TABLE *table; - enum enum_field_types table_field_type; - uint tree_key_length; -protected: - Item_sum_distinct(THD *thd, Item_sum_distinct *item); -public: - Item_sum_distinct(Item *item_par); - ~Item_sum_distinct(); - - bool setup(THD *thd); - void clear(); - void cleanup(); - bool add(); - double val_real(); - my_decimal *val_decimal(my_decimal *); - longlong val_int(); - String *val_str(String *str); - - /* XXX: does it need make_unique? */ - - enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } - void reset_field() {} // not used - void update_field() {} // not used - virtual void no_rows_in_result() {} - void fix_length_and_dec(); - enum Item_result result_type () const { return val.traits->type(); } - virtual void calculate_val_and_count(); - virtual bool unique_walk_function(void *elem); -}; - - -/* - Item_sum_sum_distinct - implementation of SUM(DISTINCT expr). - See also: MySQL manual, chapter 'Adding New Functions To MySQL' - and comments in item_sum.cc. -*/ - -class Item_sum_sum_distinct :public Item_sum_distinct -{ -private: - Item_sum_sum_distinct(THD *thd, Item_sum_sum_distinct *item) - :Item_sum_distinct(thd, item) {} -public: - Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {} - - enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } - const char *func_name() const { return "sum(distinct "; } - Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); } -}; - - -/* Item_sum_avg_distinct - SELECT AVG(DISTINCT expr) FROM ... */ - -class Item_sum_avg_distinct: public Item_sum_distinct -{ -private: - Item_sum_avg_distinct(THD *thd, Item_sum_avg_distinct *original) - :Item_sum_distinct(thd, original) {} -public: - uint prec_increment; - Item_sum_avg_distinct(Item *item_arg) : Item_sum_distinct(item_arg) {} - - void fix_length_and_dec(); - virtual void calculate_val_and_count(); - enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; } - const char *func_name() const { return "avg(distinct "; } - Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); } -}; - - class Item_sum_count :public Item_sum_int { longlong count; @@ -284,7 +170,7 @@ class Item_sum_count :public Item_sum_int void reset_field(); void cleanup(); void update_field(); - const char *func_name() const { return "count("; } + const char *func_name() const { return "count"; } Item *copy_or_same(THD* thd); }; @@ -294,55 +180,80 @@ class TMP_TABLE_PARAM; class Item_sum_count_distinct :public Item_sum_int { TABLE *table; + table_map used_table_cache; uint32 *field_lengths; TMP_TABLE_PARAM *tmp_table_param; - /* - 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 - */ - Unique *tree; + 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; - uint tree_key_length; + 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 + */ + 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 + */ + 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: + public: Item_sum_count_distinct(List<Item> &list) - :Item_sum_int(list), table(0), field_lengths(0), tmp_table_param(0), - tree(0), original(0), always_null(FALSE) + :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), tree_key_length(item->tree_key_length), + 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) {} - ~Item_sum_count_distinct(); - void cleanup(); + table_map used_tables() const { return used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } 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 "; } + 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() {} + void print(String *str); }; @@ -354,55 +265,43 @@ class Item_avg_field :public Item_result_field { public: Field *field; - Item_result hybrid_type; - uint f_precision, f_scale, dec_bin_size; - uint prec_increment; - Item_avg_field(Item_result res_type, Item_sum_avg *item); + Item_avg_field(Item_sum_avg *item); enum Type type() const { return FIELD_AVG_ITEM; } - double val_real(); - longlong val_int(); - my_decimal *val_decimal(my_decimal *); + double 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*); - enum_field_types field_type() const - { - return hybrid_type == DECIMAL_RESULT ? - MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE; - } + enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } void fix_length_and_dec() {} - enum Item_result result_type () const { return hybrid_type; } }; -class Item_sum_avg :public Item_sum_sum +class Item_sum_avg :public Item_sum_num { -public: + void fix_length_and_dec() + { + decimals=min(decimals+4, NOT_FIXED_DEC); + maybe_null=1; + } + + double sum; ulonglong count; - uint prec_increment; - uint f_precision, f_scale, dec_bin_size; - Item_sum_avg(Item *item_par) :Item_sum_sum(item_par), count(0) {} + public: + 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_sum(thd, item), count(item->count), - prec_increment(item->prec_increment) {} - - void fix_length_and_dec(); + :Item_sum_num(thd, item), sum(item->sum), count(item->count) {} enum Sumfunctype sum_func () const {return AVG_FUNC;} void clear(); bool add(); - double val_real(); - // In SPs we might force the "wrong" type with select into a declare variable - longlong val_int() { return (longlong)val_real(); } - my_decimal *val_decimal(my_decimal *); - String *val_str(String *str); + double val(); void reset_field(); void update_field(); Item *result_item(Field *field) - { return new Item_avg_field(hybrid_type, this); } + { return new Item_avg_field(this); } void no_rows_in_result() {} - const char *func_name() const { return "avg("; } + const char *func_name() const { return "avg"; } Item *copy_or_same(THD* thd); - Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); }; class Item_sum_variance; @@ -411,27 +310,14 @@ class Item_variance_field :public Item_result_field { public: Field *field; - Item_result hybrid_type; - uint f_precision0, f_scale0; - uint f_precision1, f_scale1; - uint dec_bin_size0, dec_bin_size1; - uint sample; - uint prec_increment; Item_variance_field(Item_sum_variance *item); enum Type type() const {return FIELD_VARIANCE_ITEM; } - double val_real(); - longlong val_int() - { /* can't be fix_fields()ed */ return (longlong) val_real(); } + double val(); + longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); } String *val_str(String*); - my_decimal *val_decimal(my_decimal *); bool is_null() { (void) val_int(); return null_value; } - enum_field_types field_type() const - { - return hybrid_type == DECIMAL_RESULT ? - MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE; - } + enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } void fix_length_and_dec() {} - enum Item_result result_type () const { return hybrid_type; } }; @@ -449,39 +335,30 @@ public: class Item_sum_variance : public Item_sum_num { - void fix_length_and_dec(); - -public: - Item_result hybrid_type; double sum, sum_sqr; - my_decimal dec_sum[2], dec_sqr[2]; - int cur_dec; ulonglong count; - uint f_precision0, f_scale0; - uint f_precision1, f_scale1; - uint dec_bin_size0, dec_bin_size1; - uint sample; - uint prec_increment; - - Item_sum_variance(Item *item_par, uint sample_arg) :Item_sum_num(item_par), - hybrid_type(REAL_RESULT), cur_dec(0), count(0), sample(sample_arg) - {} - Item_sum_variance(THD *thd, Item_sum_variance *item); + void fix_length_and_dec() + { + decimals=min(decimals+4, NOT_FIXED_DEC); + maybe_null=1; + } + + public: + 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_real(); - my_decimal *val_decimal(my_decimal *); + double val(); void reset_field(); void update_field(); Item *result_item(Field *field) { return new Item_variance_field(this); } void no_rows_in_result() {} - const char *func_name() const - { return sample ? "var_samp(" : "variance("; } + const char *func_name() const { return "variance"; } Item *copy_or_same(THD* thd); - Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); - enum Item_result result_type () const { return hybrid_type; } }; class Item_sum_std; @@ -491,10 +368,7 @@ 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_real(); - my_decimal *val_decimal(my_decimal *); - enum Item_result result_type () const { return REAL_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} + double val(); }; /* @@ -504,30 +378,26 @@ public: class Item_sum_std :public Item_sum_variance { public: - Item_sum_std(Item *item_par, uint sample_arg) - :Item_sum_variance(item_par, sample_arg) {} + 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_real(); + double val(); Item *result_item(Field *field) { return new Item_std_field(this); } - const char *func_name() const { return "std("; } + const char *func_name() const { return "std"; } Item *copy_or_same(THD* thd); - enum Item_result result_type () const { return REAL_RESULT; } - enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} }; // This class is a string or number function depending on num_func class Item_sum_hybrid :public Item_sum { -protected: + protected: String value,tmp_value; double sum; longlong sum_int; - my_decimal sum_dec; Item_result hybrid_type; enum_field_types hybrid_field_type; int cmp_sign; @@ -538,18 +408,22 @@ protected: 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), - was_values(TRUE) + cmp_sign(sign), used_table_cache(~(table_map) 0), was_values(TRUE) { collation.set(&my_charset_bin); } - Item_sum_hybrid(THD *thd, Item_sum_hybrid *item); - bool fix_fields(THD *, Item **); + 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), + was_values(TRUE) + { collation.set(item->collation); } + 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 clear(); - double val_real(); + double val(); longlong val_int(); - my_decimal *val_decimal(my_decimal *); void reset_field(); String *val_str(String *); void make_const() { used_table_cache=0; } @@ -560,12 +434,9 @@ protected: void min_max_update_str_field(); void min_max_update_real_field(); void min_max_update_int_field(); - void min_max_update_decimal_field(); void cleanup(); bool any_value() { return was_values; } void no_rows_in_result(); - Field *create_tmp_field(bool group, TABLE *table, - uint convert_blob_length); }; @@ -577,7 +448,7 @@ public: enum Sumfunctype sum_func () const {return MIN_FUNC;} bool add(); - const char *func_name() const { return "min("; } + const char *func_name() const { return "min"; } Item *copy_or_same(THD* thd); }; @@ -590,7 +461,7 @@ public: enum Sumfunctype sum_func () const {return MAX_FUNC;} bool add(); - const char *func_name() const { return "max("; } + const char *func_name() const { return "max"; } Item *copy_or_same(THD* thd); }; @@ -611,7 +482,7 @@ public: void reset_field(); void update_field(); void fix_length_and_dec() - { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; } + { decimals=0; max_length=21; unsigned_flag=1; maybe_null=null_value=0; } }; @@ -621,7 +492,7 @@ 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("; } + const char *func_name() const { return "bit_or"; } Item *copy_or_same(THD* thd); }; @@ -632,7 +503,7 @@ class Item_sum_and :public Item_sum_bit 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("; } + const char *func_name() const { return "bit_and"; } Item *copy_or_same(THD* thd); }; @@ -642,7 +513,7 @@ class Item_sum_xor :public Item_sum_bit 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("; } + const char *func_name() const { return "bit_xor"; } Item *copy_or_same(THD* thd); }; @@ -659,21 +530,18 @@ protected: udf_handler udf; public: - Item_udf_sum(udf_func *udf_arg) - :Item_sum(), udf(udf_arg) - { quick_group=0; } - Item_udf_sum(udf_func *udf_arg, List<Item> &list) - :Item_sum(list), udf(udf_arg) + Item_udf_sum(udf_func *udf_arg) :Item_sum(), udf(udf_arg) { quick_group=0;} + Item_udf_sum( udf_func *udf_arg, List<Item> &list ) + :Item_sum( list ), udf(udf_arg) { quick_group=0;} Item_udf_sum(THD *thd, Item_udf_sum *item) - :Item_sum(thd, item), udf(item->udf) - { udf.not_original= TRUE; } + :Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; } const char *func_name() const { return udf.name(); } - bool fix_fields(THD *thd, Item **ref) + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { DBUG_ASSERT(fixed == 0); fixed= 1; - return udf.fix_fields(thd, this, this->arg_count, this->args); + 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; } @@ -683,27 +551,21 @@ public: void reset_field() {}; void update_field() {}; void cleanup(); - void print(String *str); }; class Item_sum_udf_float :public Item_udf_sum { public: - Item_sum_udf_float(udf_func *udf_arg) - :Item_udf_sum(udf_arg) {} + 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_udf_sum(udf_arg,list) {} 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_real(); - } - double val_real(); + { DBUG_ASSERT(fixed == 1); return (longlong) Item_sum_udf_float::val(); } + double val(); String *val_str(String*str); - my_decimal *val_decimal(my_decimal *); void fix_length_and_dec() { fix_num_length_and_dec(); } Item *copy_or_same(THD* thd); }; @@ -712,17 +574,15 @@ class Item_sum_udf_float :public Item_udf_sum class Item_sum_udf_int :public Item_udf_sum { public: - Item_sum_udf_int(udf_func *udf_arg) - :Item_udf_sum(udf_arg) {} + 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_udf_sum(udf_arg,list) {} Item_sum_udf_int(THD *thd, Item_sum_udf_int *item) :Item_udf_sum(thd, item) {} longlong val_int(); - double val_real() + double val() { DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); } String *val_str(String*str); - my_decimal *val_decimal(my_decimal *); 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); @@ -732,72 +592,43 @@ public: class Item_sum_udf_str :public Item_udf_sum { public: - Item_sum_udf_str(udf_func *udf_arg) - :Item_udf_sum(udf_arg) {} + 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(THD *thd, Item_sum_udf_str *item) :Item_udf_sum(thd, item) {} String *val_str(String *); - double val_real() + double val() { - int err_not_used; + int err; char *end_not_used; String *res; res=val_str(&str_value); return res ? my_strntod(res->charset(),(char*) res->ptr(),res->length(), - &end_not_used, &err_not_used) : 0.0; + &end_not_used, &err) : 0.0; } longlong val_int() { - int err_not_used; - char *end; - String *res; - CHARSET_INFO *cs; - - if (!(res= val_str(&str_value))) - return 0; /* Null value */ - cs= res->charset(); - end= (char*) res->ptr()+res->length(); - return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used); + int err; + String *res; res=val_str(&str_value); + return res ? my_strntoll(res->charset(),res->ptr(),res->length(),10, (char**) 0, &err) : (longlong) 0; } - my_decimal *val_decimal(my_decimal *dec); enum Item_result result_type () const { return STRING_RESULT; } void fix_length_and_dec(); Item *copy_or_same(THD* thd); }; - -class Item_sum_udf_decimal :public Item_udf_sum -{ -public: - Item_sum_udf_decimal(udf_func *udf_arg) - :Item_udf_sum(udf_arg) {} - Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) - :Item_udf_sum(udf_arg, list) {} - Item_sum_udf_decimal(THD *thd, Item_sum_udf_decimal *item) - :Item_udf_sum(thd, item) {} - String *val_str(String *); - double val_real(); - longlong val_int(); - my_decimal *val_decimal(my_decimal *); - enum Item_result result_type () const { return DECIMAL_RESULT; } - void fix_length_and_dec() { fix_num_length_and_dec(); } - Item *copy_or_same(THD* thd); -}; - #else /* Dummy functions to get sql_yacc.cc compiled */ 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) :Item_sum_num() {} Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} 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_real() { DBUG_ASSERT(fixed == 1); return 0.0; } + double val() { DBUG_ASSERT(fixed == 1); return 0.0; } void clear() {} bool add() { return 0; } void update_field() {} @@ -807,50 +638,29 @@ class Item_sum_udf_float :public Item_sum_num 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) :Item_sum_num() {} Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {} 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() { DBUG_ASSERT(fixed == 1); return 0; } - double val_real() { DBUG_ASSERT(fixed == 1); return 0; } + double val() { DBUG_ASSERT(fixed == 1); return 0; } void clear() {} bool add() { return 0; } void update_field() {} }; -class Item_sum_udf_decimal :public Item_sum_num -{ - public: - Item_sum_udf_decimal(udf_func *udf_arg) - :Item_sum_num() {} - Item_sum_udf_decimal(udf_func *udf_arg, List<Item> &list) - :Item_sum_num() {} - Item_sum_udf_decimal(THD *thd, Item_sum_udf_float *item) - :Item_sum_num(thd, item) {} - enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } - double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } - my_decimal *val_decimal(my_decimal *) { DBUG_ASSERT(fixed == 1); return 0; } - void clear() {} - bool add() { return 0; } - void update_field() {} -}; - - 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(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(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_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.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; } @@ -866,26 +676,15 @@ 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; - String result; - String *separator; - TREE tree_base; - TREE *tree; - TABLE *table; - ORDER **order; - Name_resolution_context *context; - uint arg_count_order; // total count of ORDER BY items - uint arg_count_field; // count of arguments - uint count_cut_values; + uint key_length; + bool tree_mode; bool distinct; bool warning_for_row; bool always_null; - /* - Following is 0 normal object and pointer to original one for copy - (to correctly free resources) - */ - Item_func_group_concat *original; friend int group_concat_key_cmp_with_distinct(void* arg, byte* key1, byte* key2); @@ -894,17 +693,34 @@ class Item_func_group_concat : public Item_sum friend int group_concat_key_cmp_with_distinct_and_order(void* arg, byte* key1, byte* key2); - friend int dump_leaf_key(byte* key, - element_count count __attribute__((unused)), + friend int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), Item_func_group_concat *group_concat_item); -public: - Item_func_group_concat(Name_resolution_context *context_arg, - bool is_distinct, List<Item> *is_select, - SQL_LIST *is_order, String *is_separator); - + public: + String result; + String *separator; + TREE tree_base; + TREE *tree; + TABLE *table; + ORDER **order; + TABLE_LIST *tables_list; + ulong group_concat_max_len; + uint arg_count_order; + uint arg_count_field; + uint field_list_offset; + uint count_cut_values; + bool no_appended; + /* + 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() {} + ~Item_func_group_concat(); void cleanup(); enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;} @@ -912,12 +728,12 @@ public: virtual Item_result result_type () const { return STRING_RESULT; } void clear(); bool add(); - void reset_field() {} // not used - void update_field() {} // not used - bool fix_fields(THD *,Item **); + void reset_field(); + bool fix_fields(THD *, TABLE_LIST *, Item **); bool setup(THD *thd); void make_unique(); - double val_real() + virtual void update_field() {} + double val() { String *res; res=val_str(&str_value); return res ? my_atof(res->c_ptr()) : 0.0; @@ -932,14 +748,8 @@ public: end_ptr= (char*) res->ptr()+ res->length(); return my_strtoll10(res->ptr(), &end_ptr, &error); } - my_decimal *val_decimal(my_decimal *decimal_value) - { - return val_decimal_from_string(decimal_value); - } String* val_str(String* str); Item *copy_or_same(THD* thd); void no_rows_in_result() {} void print(String *str); - virtual bool change_context_processor(byte *cntx) - { context= (Name_resolution_context *)cntx; return FALSE; } }; |