summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_gconcat.result20
-rw-r--r--mysql-test/t/func_gconcat.test16
-rw-r--r--sql/item_sum.cc13
-rw-r--r--sql/item_sum.h532
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; }
};