diff options
author | unknown <tsmith@ramayana.hindu.god> | 2008-01-22 15:56:15 -0700 |
---|---|---|
committer | unknown <tsmith@ramayana.hindu.god> | 2008-01-22 15:56:15 -0700 |
commit | 6c26935035ce6fc646fc448dc181d9a3a870cd54 (patch) | |
tree | 22de11d4d65b9eb7c56b5e80669f19cf9ff242f4 /sql/item_sum.cc | |
parent | 74c9f82afb1d145636b91eff4b26131fd60e4f68 (diff) | |
parent | 37ff91b3bfdb946743e36ddd13bfda71598f45a8 (diff) | |
download | mariadb-git-6c26935035ce6fc646fc448dc181d9a3a870cd54.tar.gz |
Merge ramayana.hindu.god:/home/tsmith/m/bk/51
into ramayana.hindu.god:/home/tsmith/m/bk/maint/51
client/mysqldump.c:
Auto merged
configure.in:
Auto merged
sql/field.cc:
Auto merged
sql/filesort.cc:
Auto merged
sql/item.cc:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/log.cc:
Auto merged
sql/repl_failsafe.cc:
Auto merged
sql/set_var.cc:
Auto merged
sql/sp.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_select.cc:
Auto merged
sql/sql_show.cc:
Auto merged
sql/sql_yacc.yy:
Auto merged
sql/item_sum.cc:
Manual merge.
Diffstat (limited to 'sql/item_sum.cc')
-rw-r--r-- | sql/item_sum.cc | 156 |
1 files changed, 82 insertions, 74 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 19c71cbc48d..91198d0fb7e 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -632,7 +632,7 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, */ switch (args[0]->field_type()) { case MYSQL_TYPE_DATE: - field= new Field_date(maybe_null, name, collation.collation); + field= new Field_newdate(maybe_null, name, collation.collation); break; case MYSQL_TYPE_TIME: field= new Field_time(maybe_null, name, collation.collation); @@ -2863,44 +2863,51 @@ String *Item_sum_udf_str::val_str(String *str) concat of values from "group by" operation BUGS - DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields - in expression list Blobs doesn't work with DISTINCT or ORDER BY *****************************************************************************/ -/** - function of sort for syntax: GROUP_CONCAT(DISTINCT expr,...) + + +/** + Compares the values for fields in expr list of GROUP_CONCAT. + @note + + GROUP_CONCAT([DISTINCT] expr [,expr ...] + [ORDER BY {unsigned_integer | col_name | expr} + [ASC | DESC] [,col_name ...]] + [SEPARATOR str_val]) + + @return + @retval -1 : key1 < key2 + @retval 0 : key1 = key2 + @retval 1 : key1 > key2 */ -int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, - uchar* key2) +int group_concat_key_cmp_with_distinct(void* arg, const void* key1, + const void* key2) { - Item_func_group_concat* grp_item= (Item_func_group_concat*)arg; - TABLE *table= grp_item->table; - Item **field_item, **end; + Item_func_group_concat *item_func= (Item_func_group_concat*)arg; + TABLE *table= item_func->table; - for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field; - field_item < end; - field_item++) + for (uint i= 0; i < item_func->arg_count_field; i++) { + Item *item= item_func->args[i]; + /* + If field_item is a const item then either get_tp_table_field returns 0 + or it is an item over a const table. + */ + if (item->const_item()) + continue; /* We have to use get_tmp_table_field() instead of real_item()->get_tmp_table_field() because we want the field in the temporary table, not the original field */ - Field *field= (*field_item)->get_tmp_table_field(); - /* - If field_item is a const item then either get_tmp_table_field returns 0 - or it is an item over a const table. - */ - if (field && !(*field_item)->const_item()) - { - int res; - uint offset= (field->offset(field->table->record[0]) - - table->s->null_bytes); - if ((res= field->cmp(key1 + offset, key2 + offset))) - return res; - } + Field *field= item->get_tmp_table_field(); + int res; + uint offset= field->offset(field->table->record[0])-table->s->null_bytes; + if((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset))) + return res; } return 0; } @@ -2910,7 +2917,8 @@ int group_concat_key_cmp_with_distinct(void* arg, uchar* key1, function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... ) */ -int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) +int group_concat_key_cmp_with_order(void* arg, const void* key1, + const void* key2) { Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; ORDER **order_item, **end; @@ -2936,7 +2944,7 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) int res; uint offset= (field->offset(field->table->record[0]) - table->s->null_bytes); - if ((res= field->cmp(key1 + offset, key2 + offset))) + if ((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset))) return (*order_item)->asc ? res : -res; } } @@ -2950,25 +2958,6 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2) /** - function of sort for syntax: - GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... ). - - @bug - This doesn't work in the case when the order by contains data that - is not part of the field list because tree-insert will not notice - the duplicated values when inserting things sorted by ORDER BY -*/ - -int group_concat_key_cmp_with_distinct_and_order(void* arg,uchar* key1, - uchar* key2) -{ - if (!group_concat_key_cmp_with_distinct(arg,key1,key2)) - return 0; - return(group_concat_key_cmp_with_order(arg,key1,key2)); -} - - -/** Append data from current leaf to item->result. */ @@ -3054,7 +3043,7 @@ Item_func_group_concat(Name_resolution_context *context_arg, bool distinct_arg, List<Item> *select_list, SQL_LIST *order_list, String *separator_arg) :tmp_table_param(0), warning(0), - separator(separator_arg), tree(0), table(0), + separator(separator_arg), tree(0), unique_filter(NULL), table(0), order(0), context(context_arg), arg_count_order(order_list ? order_list->elements : 0), arg_count_field(select_list->elements), @@ -3109,6 +3098,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd, warning(item->warning), separator(item->separator), tree(item->tree), + unique_filter(item->unique_filter), table(item->table), order(item->order), context(item->context), @@ -3159,6 +3149,11 @@ void Item_func_group_concat::cleanup() delete_tree(tree); tree= 0; } + if (unique_filter) + { + delete unique_filter; + unique_filter= NULL; + } if (warning) { char warn_buff[MYSQL_ERRMSG_SIZE]; @@ -3188,6 +3183,8 @@ void Item_func_group_concat::clear() no_appended= TRUE; if (tree) reset_tree(tree); + if (distinct) + unique_filter->reset(); /* No need to reset the table as we never call write_row */ } @@ -3211,9 +3208,19 @@ bool Item_func_group_concat::add() } null_value= FALSE; + bool row_eligible= TRUE; + + if (distinct) + { + /* Filter out duplicate rows. */ + uint count= unique_filter->elements_in_tree(); + unique_filter->unique_add(table->record[0] + table->s->null_bytes); + if (count == unique_filter->elements_in_tree()) + row_eligible= FALSE; + } TREE_ELEMENT *el= 0; // Only for safety - if (tree) + if (row_eligible && tree) el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0, tree->custom_arg); /* @@ -3221,7 +3228,7 @@ bool Item_func_group_concat::add() we can dump the row here in case of GROUP_CONCAT(DISTINCT...) instead of doing tree traverse later. */ - if (!warning_for_row && + if (row_eligible && !warning_for_row && (!tree || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this); @@ -3297,7 +3304,6 @@ bool Item_func_group_concat::setup(THD *thd) { List<Item> list; SELECT_LEX *select_lex= thd->lex->current_select; - qsort_cmp2 compare_key; DBUG_ENTER("Item_func_group_concat::setup"); /* @@ -3387,38 +3393,33 @@ bool Item_func_group_concat::setup(THD *thd) table->file->extra(HA_EXTRA_NO_ROWS); table->no_rows= 1; + /* + Need sorting or uniqueness: init tree and choose a function to sort. + Don't reserve space for NULLs: if any of gconcat arguments is NULL, + the row is not added to the result. + */ + uint tree_key_length= table->s->reclength - table->s->null_bytes; - if (distinct || arg_count_order) + if (arg_count_order) { - /* - Need sorting: init tree and choose a function to sort. - Don't reserve space for NULLs: if any of gconcat arguments is NULL, - the row is not added to the result. - */ - uint tree_key_length= table->s->reclength - table->s->null_bytes; - tree= &tree_base; - if (arg_count_order) - { - if (distinct) - compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order; - else - compare_key= (qsort_cmp2) group_concat_key_cmp_with_order; - } - else - { - compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct; - } /* - Create a tree for sorting. The tree is used to sort and to remove - duplicate values (according to the syntax of this function). If there - is no DISTINCT or ORDER BY clauses, we don't create this tree. + Create a tree for sorting. The tree is used to sort (according to the + syntax of this function). If there is no ORDER BY clause, we don't + create this tree. */ init_tree(tree, (uint) min(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, - tree_key_length, compare_key, 0, NULL, (void*) this); + tree_key_length, + group_concat_key_cmp_with_order , 0, NULL, (void*) this); } + if (distinct) + unique_filter= new Unique(group_concat_key_cmp_with_distinct, + (void*)this, + tree_key_length, + thd->variables.max_heap_table_size); + DBUG_RETURN(FALSE); } @@ -3488,3 +3489,10 @@ void Item_func_group_concat::print(String *str) str->append(*separator); str->append(STRING_WITH_LEN("\')")); } + + +Item_func_group_concat::~Item_func_group_concat() +{ + if (unique_filter) + delete unique_filter; +} |