diff options
author | unknown <wax@kishkin.ru> | 2003-06-03 17:07:46 +0600 |
---|---|---|
committer | unknown <wax@kishkin.ru> | 2003-06-03 17:07:46 +0600 |
commit | 284a6abeea27640bf7a726c06c90c5af9db09cf7 (patch) | |
tree | f843ad0e54bde2b08179141dbc0431f17a5aefd6 | |
parent | 27d95e9687e840c98235a89ff7aea880bb905f44 (diff) | |
parent | fbd157fa5754c5c1dac01ad824531aeb434426d7 (diff) | |
download | mariadb-git-284a6abeea27640bf7a726c06c90c5af9db09cf7.tar.gz |
Merge kishkin.ru:/home/wax/mysql-4n into kishkin.ru:/home/wax/mysql-4g
sql/field.cc:
Auto merged
sql/field.h:
Auto merged
sql/item_sum.cc:
Auto merged
sql/item_sum.h:
Auto merged
-rw-r--r-- | mysql-test/r/func_gconcat.result | 20 | ||||
-rw-r--r-- | mysql-test/t/func_gconcat.test | 16 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 1 | ||||
-rw-r--r-- | sql/item_sum.cc | 102 | ||||
-rw-r--r-- | sql/item_sum.h | 29 |
6 files changed, 116 insertions, 54 deletions
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 0dc84f090f1..f2246f2e514 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -154,8 +154,26 @@ Warning 1258 1 line(s) was(were) cut by group_concat() show warnings; Level Code Message Warning 1258 1 line(s) was(were) cut by group_concat() +set group_concat_max_len = 1024; +drop table if exists T_URL; +Warnings: +Note 1051 Unknown table 'T_URL' +create table T_URL ( URL_ID int(11), URL varchar(80)); +drop table if exists T_REQUEST; +Warnings: +Note 1051 Unknown table 'T_REQUEST' +create table T_REQUEST ( REQ_ID int(11), URL_ID int(11)); +insert into T_URL values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com'); +insert into T_REQUEST values (1,4), (5,4), (5,5); +select REQ_ID, Group_Concat(URL) as URL from T_URL, T_REQUEST where +T_REQUEST.URL_ID = T_URL.URL_ID group by REQ_ID; +REQ_ID URL +1 www.host.com +5 www.host.com,www.google.com,www.help.com +drop table T_URL; +drop table T_REQUEST; select group_concat(sum(a)) from t1 group by grp; Invalid use of group function select grp,group_concat(c order by 2) from t1 group by grp; Unknown column '2' in 'group statement' -drop table if exists t1; +drop table t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 0a95410e842..a5a7abe3b01 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -68,6 +68,20 @@ select grp,group_concat(c order by c) from t1 group by grp; set group_concat_max_len = 5; select grp,group_concat(c) from t1 group by grp; show warnings; +set group_concat_max_len = 1024; + +# Test variable length + +drop table if exists T_URL; +create table T_URL ( URL_ID int(11), URL varchar(80)); +drop table if exists T_REQUEST; +create table T_REQUEST ( REQ_ID int(11), URL_ID int(11)); +insert into T_URL values (4,'www.host.com'), (5,'www.google.com'),(5,'www.help.com'); +insert into T_REQUEST values (1,4), (5,4), (5,5); +select REQ_ID, Group_Concat(URL) as URL from T_URL, T_REQUEST where +T_REQUEST.URL_ID = T_URL.URL_ID group by REQ_ID; +drop table T_URL; +drop table T_REQUEST; # Test errors @@ -76,4 +90,4 @@ select group_concat(sum(a)) from t1 group by grp; --error 1054 select grp,group_concat(c order by 2) from t1 group by grp; -drop table if exists t1; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 044684b2675..04859dd22e0 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -183,7 +183,7 @@ Field::Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg, field_name(field_name_arg), query_id(0),key_start(0),part_of_key(0),part_of_sortkey(0), unireg_check(unireg_check_arg), - field_length(length_arg),null_bit(null_bit_arg) + field_length(length_arg),null_bit(null_bit_arg),abs_offset(0) { flags=null_ptr ? 0: NOT_NULL_FLAG; comment.str= (char*) ""; diff --git a/sql/field.h b/sql/field.h index 4456eb36731..21f2ab4b6e9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -62,6 +62,7 @@ public: uint32 field_length; // Length of field uint16 flags; uchar null_bit; // Bit used to test null bit + uint abs_offset; // use only in group_concat Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg, utype unireg_check_arg, const char *field_name_arg, diff --git a/sql/item_sum.cc b/sql/item_sum.cc index fa8bf7e6e0f..e5be3809230 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1351,27 +1351,28 @@ String *Item_sum_udf_str::val_str(String *str) GROUP_CONCAT(DISTINCT expr,...) */ -static int group_concat_key_cmp_with_distinct(void* arg, byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct(void* arg, byte* key1, + byte* key2) { Item_func_group_concat* item= (Item_func_group_concat*)arg; + for (uint i= 0; i < item->arg_count_field; i++) { - Item *field_item= item->expr[i]; + Item *field_item= item->args[i]; Field *field= field_item->tmp_table_field(); if (field) { - uint offset= field->offset(); + uint offset= field->abs_offset; int res= field->key_cmp(key1 + offset, key2 + offset); /* if key1 and key2 is not equal than field->key_cmp return offset. This - function must return value 1 for this case. + function must return value 1 for this case. */ if (res) return 1; } - } + } return 0; } @@ -1381,9 +1382,10 @@ static int group_concat_key_cmp_with_distinct(void* arg, byte* key1, GROUP_CONCAT(expr,... ORDER BY col,... ) */ -static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) +int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) { Item_func_group_concat* item= (Item_func_group_concat*)arg; + for (uint i=0; i < item->arg_count_order; i++) { ORDER *order_item= item->order[i]; @@ -1391,14 +1393,14 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) Field *field= item->tmp_table_field(); if (field) { - uint offset= field->offset(); + uint offset= field->abs_offset; bool dir= order_item->asc; int res= field->key_cmp(key1 + offset, key2 + offset); if (res) return dir ? res : -res; } - } + } /* We can't return 0 because tree class remove this item as double value. */ @@ -1411,9 +1413,8 @@ static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... ) */ -static int group_concat_key_cmp_with_distinct_and_order(void* arg, - byte* key1, - byte* key2) +int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1, + byte* key2) { if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) return 0; @@ -1426,24 +1427,23 @@ static int group_concat_key_cmp_with_distinct_and_order(void* arg, item is pointer to Item_func_group_concat */ -static int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), +int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), Item_func_group_concat *group_concat_item) { char buff[MAX_FIELD_WIDTH]; String tmp((char *)&buff,sizeof(buff),default_charset_info); String tmp2((char *)&buff,sizeof(buff),default_charset_info); - + tmp.length(0); for (uint i= 0; i < group_concat_item->arg_show_fields; i++) { - Item *show_item= group_concat_item->expr[i]; + Item *show_item= group_concat_item->args[i]; if (!show_item->const_item()) { Field *f= show_item->tmp_table_field(); - uint offset= f->offset(); char *sv= f->ptr; - f->ptr= (char *)key + offset; + f->ptr= (char *)key + f->abs_offset; String *res= f->val_str(&tmp,&tmp2); group_concat_item->result.append(*res); f->ptr= sv; @@ -1493,9 +1493,14 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, List<Item> *is_select, SQL_LIST *is_order, String *is_separator) - :Item_sum(), tmp_table_param(0), warning_available(false), - separator(is_separator), tree(&tree_base), table(0), - count_cut_values(0), tree_mode(0), distinct(is_distinct) + :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0), + warning_available(0), key_length(0), rec_offset(0), + tree_mode(0), distinct(is_distinct), warning_for_row(0), + separator(is_separator), tree(&tree_base), table(0), + order(0), tables_list(0), group_concat_max_len(0), + show_elements(0), arg_count_order(0), arg_count_field(0), + arg_show_fields(0), count_cut_values(0) + { original= 0; quick_group= 0; @@ -1511,16 +1516,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, We need to allocate: args - arg_count+arg_count_order (for possible order items in temporare tables) - expr - arg_count_field order - arg_count_order */ - args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order+ - arg_count_field)+ + args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+ sizeof(ORDER*)*arg_count_order); if (!args) - return; // thd->fatal is set - expr= args; - expr+= arg_count+arg_count_order; + return; /* fill args items of show and sort */ int i= 0; @@ -1528,12 +1529,12 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct, Item *item_select; for ( ; (item_select= li++) ; i++) - args[i]= expr[i]= item_select; + args[i]= item_select; if (arg_count_order) { i= 0; - order= (ORDER**)(expr + arg_count_field); + order= (ORDER**)(args + arg_count + arg_count_order); for (ORDER *order_item= (ORDER*) is_order->first; order_item != NULL; order_item= order_item->next) @@ -1588,13 +1589,15 @@ void Item_func_group_concat::reset() bool Item_func_group_concat::add() { + if (always_null) + return 0; copy_fields(tmp_table_param); copy_funcs(tmp_table_param->items_to_copy); bool record_is_null= TRUE; for (uint i= 0; i < arg_show_fields; i++) { - Item *show_item= expr[i]; + Item *show_item= args[i]; if (!show_item->const_item()) { Field *f= show_item->tmp_table_field(); @@ -1610,13 +1613,13 @@ bool Item_func_group_concat::add() null_value= FALSE; if (tree_mode) { - if (!tree_insert(tree, table->record[0], 0,tree->custom_arg)) + if (!tree_insert(tree, table->record[0] + rec_offset, 0, tree->custom_arg)) return 1; } else { if (result.length() <= group_concat_max_len && !warning_for_row) - dump_leaf_key(table->record[0],1, + dump_leaf_key(table->record[0] + rec_offset, 1, (Item_func_group_concat*)this); } return 0; @@ -1649,12 +1652,6 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; maybe_null |= args[i]->maybe_null; } - for (i= 0 ; i < arg_count_field ; i++) - { - if (expr[i]->fix_fields(thd, tables, expr + i) || expr[i]->check_cols(1)) - return 1; - maybe_null |= expr[i]->maybe_null; - } /* Fix fields for order clause in function: GROUP_CONCAT(expr,... ORDER BY col,... ) @@ -1688,6 +1685,7 @@ bool Item_func_group_concat::setup(THD *thd) /* all not constant fields are push to list and create temp table */ + always_null= 0; for (uint i= 0; i < arg_count; i++) { Item *item= args[i]; @@ -1700,6 +1698,8 @@ bool Item_func_group_concat::setup(THD *thd) always_null= 1; } } + if (always_null) + return 0; List<Item> all_fields(list); if (arg_count_order) @@ -1719,12 +1719,25 @@ bool Item_func_group_concat::setup(THD *thd) return 1; table->file->extra(HA_EXTRA_NO_ROWS); table->no_rows= 1; - qsort_cmp2 compare_key; - - tree_mode= distinct || arg_count_order; + + + Field** field, **field_end; + field_end = (field = table->field) + table->fields; + uint offset = 0; + for (key_length = 0; field < field_end; ++field) + { + uint32 length= (*field)->pack_length(); + (*field)->abs_offset= offset; + offset+= length; + key_length += length; + } + rec_offset = table->reclength - key_length; + /* choise function of sort */ + tree_mode= distinct || arg_count_order; + qsort_cmp2 compare_key; if (tree_mode) { if (arg_count_order) @@ -1748,9 +1761,9 @@ bool Item_func_group_concat::setup(THD *thd) */ init_tree(tree, min(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - table->reclength, compare_key, 0, NULL, (void*) this); - max_elements_in_tree= ((table->reclength) ? - thd->variables.max_heap_table_size/table->reclength : 1); + key_length, compare_key, 0, NULL, (void*) this); + max_elements_in_tree= ((key_length) ? + thd->variables.max_heap_table_size/key_length : 1); }; item_thd= thd; @@ -1791,3 +1804,6 @@ String* Item_func_group_concat::val_str(String* str) } return &result; } + + + diff --git a/sql/item_sum.h b/sql/item_sum.h index f996f980fff..7deec8de564 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -642,13 +642,28 @@ class Item_func_group_concat : public Item_sum uint max_elements_in_tree; MYSQL_ERROR *warning; bool warning_available; + uint key_length; + int rec_offset; + 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; - Item **expr; ORDER **order; TABLE_LIST *tables_list; ulong group_concat_max_len; @@ -657,9 +672,6 @@ class Item_func_group_concat : public Item_sum uint arg_count_field; uint arg_show_fields; uint count_cut_values; - bool tree_mode, distinct; - bool warning_for_row; - bool always_null; /* Following is 0 normal object and pointer to original one for copy (to correctly free resources) @@ -675,10 +687,14 @@ class Item_func_group_concat : public Item_sum max_elements_in_tree(item.max_elements_in_tree), warning(item.warning), warning_available(item.warning_available), + key_length(item.key_length), + rec_offset(item.rec_offset), + tree_mode(0), + distinct(item.distinct), + warning_for_row(item.warning_for_row), separator(item.separator), tree(item.tree), table(item.table), - expr(item.expr), order(item.order), tables_list(item.tables_list), group_concat_max_len(item.group_concat_max_len), @@ -687,9 +703,6 @@ class Item_func_group_concat : public Item_sum arg_count_field(item.arg_count_field), arg_show_fields(item.arg_show_fields), count_cut_values(item.count_cut_values), - tree_mode(0), - distinct(item.distinct), - warning_for_row(item.warning_for_row), original(&item) { quick_group = 0; |