1 | /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. |
2 | Copyright (c) 2008, 2015, MariaDB |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
16 | |
17 | |
18 | /** |
19 | @file |
20 | |
21 | @brief |
22 | Sum functions (COUNT, MIN...) |
23 | */ |
24 | |
25 | #ifdef USE_PRAGMA_IMPLEMENTATION |
26 | #pragma implementation // gcc: Class implementation |
27 | #endif |
28 | |
29 | #include "mariadb.h" |
30 | #include "sql_priv.h" |
31 | #include "sql_select.h" |
32 | #include "uniques.h" |
33 | #include "sp_rcontext.h" |
34 | #include "sp.h" |
35 | #include "sql_parse.h" |
36 | #include "sp_head.h" |
37 | |
38 | /** |
39 | Calculate the affordable RAM limit for structures like TREE or Unique |
40 | used in Item_sum_* |
41 | */ |
42 | |
43 | size_t Item_sum::ram_limitation(THD *thd) |
44 | { |
45 | return (size_t)MY_MIN(thd->variables.tmp_memory_table_size, |
46 | thd->variables.max_heap_table_size); |
47 | } |
48 | |
49 | |
50 | /** |
51 | Prepare an aggregate function item for checking context conditions. |
52 | |
53 | The function initializes the members of the Item_sum object created |
54 | for a set function that are used to check validity of the set function |
55 | occurrence. |
56 | If the set function is not allowed in any subquery where it occurs |
57 | an error is reported immediately. |
58 | |
59 | @param thd reference to the thread context info |
60 | |
61 | @note |
62 | This function is to be called for any item created for a set function |
63 | object when the traversal of trees built for expressions used in the query |
64 | is performed at the phase of context analysis. This function is to |
65 | be invoked at the descent of this traversal. |
66 | @retval |
67 | TRUE if an error is reported |
68 | @retval |
69 | FALSE otherwise |
70 | */ |
71 | |
72 | bool Item_sum::init_sum_func_check(THD *thd) |
73 | { |
74 | SELECT_LEX *curr_sel= thd->lex->current_select; |
75 | if (!curr_sel->name_visibility_map) |
76 | { |
77 | for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select()) |
78 | { |
79 | curr_sel->name_visibility_map|= (1 << sl-> nest_level); |
80 | } |
81 | } |
82 | if (!(thd->lex->allow_sum_func & curr_sel->name_visibility_map)) |
83 | { |
84 | my_message(ER_INVALID_GROUP_FUNC_USE, ER_THD(thd, ER_INVALID_GROUP_FUNC_USE), |
85 | MYF(0)); |
86 | return TRUE; |
87 | } |
88 | /* Set a reference to the nesting set function if there is any */ |
89 | in_sum_func= thd->lex->in_sum_func; |
90 | /* Save a pointer to object to be used in items for nested set functions */ |
91 | thd->lex->in_sum_func= this; |
92 | nest_level= thd->lex->current_select->nest_level; |
93 | ref_by= 0; |
94 | aggr_level= -1; |
95 | aggr_sel= NULL; |
96 | max_arg_level= -1; |
97 | max_sum_func_level= -1; |
98 | outer_fields.empty(); |
99 | return FALSE; |
100 | } |
101 | |
102 | /** |
103 | Check constraints imposed on a usage of a set function. |
104 | |
105 | The method verifies whether context conditions imposed on a usage |
106 | of any set function are met for this occurrence. |
107 | |
108 | The function first checks if we are using any window functions as |
109 | arguments to the set function. In that case it returns an error. |
110 | |
111 | Afterwards, it checks whether the set function occurs in the position where it |
112 | can be aggregated and, when it happens to occur in argument of another |
113 | set function, the method checks that these two functions are aggregated in |
114 | different subqueries. |
115 | If the context conditions are not met the method reports an error. |
116 | If the set function is aggregated in some outer subquery the method |
117 | adds it to the chain of items for such set functions that is attached |
118 | to the the st_select_lex structure for this subquery. |
119 | |
120 | A number of designated members of the object are used to check the |
121 | conditions. They are specified in the comment before the Item_sum |
122 | class declaration. |
123 | Additionally a bitmap variable called allow_sum_func is employed. |
124 | It is included into the thd->lex structure. |
125 | The bitmap contains 1 at n-th position if the set function happens |
126 | to occur under a construct of the n-th level subquery where usage |
127 | of set functions are allowed (i.e either in the SELECT list or |
128 | in the HAVING clause of the corresponding subquery) |
129 | Consider the query: |
130 | @code |
131 | SELECT SUM(t1.b) FROM t1 GROUP BY t1.a |
132 | HAVING t1.a IN (SELECT t2.c FROM t2 WHERE AVG(t1.b) > 20) AND |
133 | t1.a > (SELECT MIN(t2.d) FROM t2); |
134 | @endcode |
135 | allow_sum_func will contain: |
136 | - for SUM(t1.b) - 1 at the first position |
137 | - for AVG(t1.b) - 1 at the first position, 0 at the second position |
138 | - for MIN(t2.d) - 1 at the first position, 1 at the second position. |
139 | |
140 | @param thd reference to the thread context info |
141 | @param ref location of the pointer to this item in the embedding expression |
142 | |
143 | @note |
144 | This function is to be called for any item created for a set function |
145 | object when the traversal of trees built for expressions used in the query |
146 | is performed at the phase of context analysis. This function is to |
147 | be invoked at the ascent of this traversal. |
148 | |
149 | @retval |
150 | TRUE if an error is reported |
151 | @retval |
152 | FALSE otherwise |
153 | */ |
154 | |
155 | bool Item_sum::check_sum_func(THD *thd, Item **ref) |
156 | { |
157 | SELECT_LEX *curr_sel= thd->lex->current_select; |
158 | nesting_map allow_sum_func= (thd->lex->allow_sum_func & |
159 | curr_sel->name_visibility_map); |
160 | bool invalid= FALSE; |
161 | DBUG_ASSERT(curr_sel->name_visibility_map); // should be set already |
162 | |
163 | /* |
164 | Window functions can not be used as arguments to sum functions. |
165 | Aggregation happes before window function computation, so there |
166 | are no values to aggregate over. |
167 | */ |
168 | if (with_window_func) |
169 | { |
170 | my_message(ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG, |
171 | ER_THD(thd, ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG), |
172 | MYF(0)); |
173 | return TRUE; |
174 | } |
175 | |
176 | if (window_func_sum_expr_flag) |
177 | return false; |
178 | /* |
179 | The value of max_arg_level is updated if an argument of the set function |
180 | contains a column reference resolved against a subquery whose level is |
181 | greater than the current value of max_arg_level. |
182 | max_arg_level cannot be greater than nest level. |
183 | nest level is always >= 0 |
184 | */ |
185 | if (nest_level == max_arg_level) |
186 | { |
187 | /* |
188 | The function must be aggregated in the current subquery, |
189 | If it is there under a construct where it is not allowed |
190 | we report an error. |
191 | */ |
192 | invalid= !(allow_sum_func & ((nesting_map)1 << max_arg_level)); |
193 | } |
194 | else if (max_arg_level >= 0 || |
195 | !(allow_sum_func & ((nesting_map)1 << nest_level))) |
196 | { |
197 | /* |
198 | The set function can be aggregated only in outer subqueries. |
199 | Try to find a subquery where it can be aggregated; |
200 | If we fail to find such a subquery report an error. |
201 | */ |
202 | if (register_sum_func(thd, ref)) |
203 | return TRUE; |
204 | invalid= aggr_level < 0 && |
205 | !(allow_sum_func & ((nesting_map)1 << nest_level)); |
206 | if (!invalid && thd->variables.sql_mode & MODE_ANSI) |
207 | invalid= aggr_level < 0 && max_arg_level < nest_level; |
208 | } |
209 | if (!invalid && aggr_level < 0) |
210 | { |
211 | aggr_level= nest_level; |
212 | aggr_sel= curr_sel; |
213 | } |
214 | /* |
215 | By this moment we either found a subquery where the set function is |
216 | to be aggregated and assigned a value that is >= 0 to aggr_level, |
217 | or set the value of 'invalid' to TRUE to report later an error. |
218 | */ |
219 | /* |
220 | Additionally we have to check whether possible nested set functions |
221 | are acceptable here: they are not, if the level of aggregation of |
222 | some of them is less than aggr_level. |
223 | */ |
224 | if (!invalid) |
225 | invalid= aggr_level <= max_sum_func_level; |
226 | if (invalid) |
227 | { |
228 | my_message(ER_INVALID_GROUP_FUNC_USE, |
229 | ER_THD(thd, ER_INVALID_GROUP_FUNC_USE), |
230 | MYF(0)); |
231 | return TRUE; |
232 | } |
233 | |
234 | if (in_sum_func) |
235 | { |
236 | /* |
237 | If the set function is nested adjust the value of |
238 | max_sum_func_level for the nesting set function. |
239 | We take into account only enclosed set functions that are to be |
240 | aggregated on the same level or above of the nest level of |
241 | the enclosing set function. |
242 | But we must always pass up the max_sum_func_level because it is |
243 | the maximum nested level of all directly and indirectly enclosed |
244 | set functions. We must do that even for set functions that are |
245 | aggregated inside of their enclosing set function's nest level |
246 | because the enclosing function may contain another enclosing |
247 | function that is to be aggregated outside or on the same level |
248 | as its parent's nest level. |
249 | */ |
250 | if (in_sum_func->nest_level >= aggr_level) |
251 | set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); |
252 | set_if_bigger(in_sum_func->max_sum_func_level, max_sum_func_level); |
253 | } |
254 | |
255 | /* |
256 | Check that non-aggregated fields and sum functions aren't mixed in the |
257 | same select in the ONLY_FULL_GROUP_BY mode. |
258 | */ |
259 | if (outer_fields.elements) |
260 | { |
261 | Item_field *field; |
262 | /* |
263 | Here we compare the nesting level of the select to which an outer field |
264 | belongs to with the aggregation level of the sum function. All fields in |
265 | the outer_fields list are checked. |
266 | |
267 | If the nesting level is equal to the aggregation level then the field is |
268 | aggregated by this sum function. |
269 | If the nesting level is less than the aggregation level then the field |
270 | belongs to an outer select. In this case if there is an embedding sum |
271 | function add current field to functions outer_fields list. If there is |
272 | no embedding function then the current field treated as non aggregated |
273 | and the select it belongs to is marked accordingly. |
274 | If the nesting level is greater than the aggregation level then it means |
275 | that this field was added by an inner sum function. |
276 | Consider an example: |
277 | |
278 | select avg ( <-- we are here, checking outer.f1 |
279 | select ( |
280 | select sum(outer.f1 + inner.f1) from inner |
281 | ) from outer) |
282 | from most_outer; |
283 | |
284 | In this case we check that no aggregate functions are used in the |
285 | select the field belongs to. If there are some then an error is |
286 | raised. |
287 | */ |
288 | List_iterator<Item_field> of(outer_fields); |
289 | while ((field= of++)) |
290 | { |
291 | SELECT_LEX *sel= field->field->table->pos_in_table_list->select_lex; |
292 | if (sel->nest_level < aggr_level) |
293 | { |
294 | if (in_sum_func) |
295 | { |
296 | /* |
297 | Let upper function decide whether this field is a non |
298 | aggregated one. |
299 | */ |
300 | in_sum_func->outer_fields.push_back(field, thd->mem_root); |
301 | } |
302 | else |
303 | sel->set_non_agg_field_used(true); |
304 | } |
305 | if (sel->nest_level > aggr_level && |
306 | (sel->agg_func_used()) && |
307 | !sel->group_list.elements) |
308 | { |
309 | my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, |
310 | ER_THD(thd, ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); |
311 | return TRUE; |
312 | } |
313 | } |
314 | } |
315 | aggr_sel->set_agg_func_used(true); |
316 | if (sum_func() == SP_AGGREGATE_FUNC) |
317 | aggr_sel->set_custom_agg_func_used(true); |
318 | update_used_tables(); |
319 | thd->lex->in_sum_func= in_sum_func; |
320 | return FALSE; |
321 | } |
322 | |
323 | /** |
324 | Attach a set function to the subquery where it must be aggregated. |
325 | |
326 | The function looks for an outer subquery where the set function must be |
327 | aggregated. If it finds such a subquery then aggr_level is set to |
328 | the nest level of this subquery and the item for the set function |
329 | is added to the list of set functions used in nested subqueries |
330 | inner_sum_func_list defined for each subquery. When the item is placed |
331 | there the field 'ref_by' is set to ref. |
332 | |
333 | @note |
334 | Now we 'register' only set functions that are aggregated in outer |
335 | subqueries. Actually it makes sense to link all set function for |
336 | a subquery in one chain. It would simplify the process of 'splitting' |
337 | for set functions. |
338 | |
339 | @param thd reference to the thread context info |
340 | @param ref location of the pointer to this item in the embedding expression |
341 | |
342 | @retval |
343 | FALSE if the executes without failures (currently always) |
344 | @retval |
345 | TRUE otherwise |
346 | */ |
347 | |
348 | bool Item_sum::register_sum_func(THD *thd, Item **ref) |
349 | { |
350 | SELECT_LEX *sl; |
351 | nesting_map allow_sum_func= thd->lex->allow_sum_func; |
352 | for (sl= thd->lex->current_select->context.outer_select() ; |
353 | sl && sl->nest_level > max_arg_level; |
354 | sl= sl->context.outer_select()) |
355 | { |
356 | if (aggr_level < 0 && |
357 | (allow_sum_func & ((nesting_map)1 << sl->nest_level))) |
358 | { |
359 | /* Found the most nested subquery where the function can be aggregated */ |
360 | aggr_level= sl->nest_level; |
361 | aggr_sel= sl; |
362 | } |
363 | } |
364 | if (sl && (allow_sum_func & ((nesting_map)1 << sl->nest_level))) |
365 | { |
366 | /* |
367 | We reached the subquery of level max_arg_level and checked |
368 | that the function can be aggregated here. |
369 | The set function will be aggregated in this subquery. |
370 | */ |
371 | aggr_level= sl->nest_level; |
372 | aggr_sel= sl; |
373 | |
374 | } |
375 | if (aggr_level >= 0) |
376 | { |
377 | ref_by= ref; |
378 | /* Add the object to the list of registered objects assigned to aggr_sel */ |
379 | if (!aggr_sel->inner_sum_func_list) |
380 | next= this; |
381 | else |
382 | { |
383 | next= aggr_sel->inner_sum_func_list->next; |
384 | aggr_sel->inner_sum_func_list->next= this; |
385 | } |
386 | aggr_sel->inner_sum_func_list= this; |
387 | aggr_sel->with_sum_func= 1; |
388 | |
389 | /* |
390 | Mark Item_subselect(s) as containing aggregate function all the way up |
391 | to aggregate function's calculation context. |
392 | Note that we must not mark the Item of calculation context itself |
393 | because with_sum_func on the calculation context st_select_lex is |
394 | already set above. |
395 | |
396 | with_sum_func being set for an Item means that this Item refers |
397 | (somewhere in it, e.g. one of its arguments if it's a function) directly |
398 | or through intermediate items to an aggregate function that is calculated |
399 | in a context "outside" of the Item (e.g. in the current or outer select). |
400 | |
401 | with_sum_func being set for an st_select_lex means that this st_select_lex |
402 | has aggregate functions directly referenced (i.e. not through a sub-select). |
403 | */ |
404 | for (sl= thd->lex->current_select; |
405 | sl && sl != aggr_sel && sl->master_unit()->item; |
406 | sl= sl->master_unit()->outer_select() ) |
407 | sl->master_unit()->item->with_sum_func= 1; |
408 | } |
409 | thd->lex->current_select->mark_as_dependent(thd, aggr_sel, NULL); |
410 | |
411 | if ((thd->lex->describe & DESCRIBE_EXTENDED) && aggr_sel) |
412 | { |
413 | push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, |
414 | ER_WARN_AGGFUNC_DEPENDENCE, |
415 | ER_THD(thd, ER_WARN_AGGFUNC_DEPENDENCE), |
416 | func_name(), |
417 | thd->lex->current_select->select_number, |
418 | aggr_sel->select_number); |
419 | } |
420 | return FALSE; |
421 | } |
422 | |
423 | |
424 | bool Item_sum::collect_outer_ref_processor(void *param) |
425 | { |
426 | Collect_deps_prm *prm= (Collect_deps_prm *)param; |
427 | SELECT_LEX *ds; |
428 | if ((ds= depended_from()) && |
429 | ds->nest_level_base == prm->nest_level_base && |
430 | ds->nest_level < prm->nest_level) |
431 | { |
432 | if (prm->collect) |
433 | prm->parameters->add_unique(this, &cmp_items); |
434 | else |
435 | prm->count++; |
436 | } |
437 | return FALSE; |
438 | } |
439 | |
440 | |
441 | Item_sum::Item_sum(THD *thd, List<Item> &list): Item_func_or_sum(thd, list) |
442 | { |
443 | if (!(orig_args= (Item **) thd->alloc(sizeof(Item *) * arg_count))) |
444 | { |
445 | args= NULL; |
446 | } |
447 | mark_as_sum_func(); |
448 | init_aggregator(); |
449 | list.empty(); // Fields are used |
450 | } |
451 | |
452 | |
453 | /** |
454 | Constructor used in processing select with temporary tebles. |
455 | */ |
456 | |
457 | Item_sum::Item_sum(THD *thd, Item_sum *item): |
458 | Item_func_or_sum(thd, item), |
459 | aggr_sel(item->aggr_sel), |
460 | nest_level(item->nest_level), aggr_level(item->aggr_level), |
461 | quick_group(item->quick_group), |
462 | orig_args(NULL) |
463 | { |
464 | if (arg_count <= 2) |
465 | { |
466 | orig_args=tmp_orig_args; |
467 | } |
468 | else |
469 | { |
470 | if (!(orig_args= (Item**) thd->alloc(sizeof(Item*)*arg_count))) |
471 | return; |
472 | } |
473 | memcpy(orig_args, item->orig_args, sizeof(Item*)*arg_count); |
474 | init_aggregator(); |
475 | with_distinct= item->with_distinct; |
476 | if (item->aggr) |
477 | set_aggregator(item->aggr->Aggrtype()); |
478 | } |
479 | |
480 | |
481 | void Item_sum::mark_as_sum_func() |
482 | { |
483 | SELECT_LEX *cur_select= current_thd->lex->current_select; |
484 | cur_select->n_sum_items++; |
485 | cur_select->with_sum_func= 1; |
486 | const_item_cache= false; |
487 | with_sum_func= 1; |
488 | with_field= 0; |
489 | window_func_sum_expr_flag= false; |
490 | } |
491 | |
492 | |
493 | void Item_sum::print(String *str, enum_query_type query_type) |
494 | { |
495 | /* orig_args is not filled with valid values until fix_fields() */ |
496 | Item **pargs= fixed ? orig_args : args; |
497 | str->append(func_name()); |
498 | /* |
499 | TODO: |
500 | The fact that func_name() may return a name with an extra '(' |
501 | is really annoying. This shoud be fixed. |
502 | */ |
503 | if (!is_aggr_sum_func()) |
504 | str->append('('); |
505 | for (uint i=0 ; i < arg_count ; i++) |
506 | { |
507 | if (i) |
508 | str->append(','); |
509 | pargs[i]->print(str, query_type); |
510 | } |
511 | str->append(')'); |
512 | } |
513 | |
514 | void Item_sum::fix_num_length_and_dec() |
515 | { |
516 | decimals=0; |
517 | for (uint i=0 ; i < arg_count ; i++) |
518 | set_if_bigger(decimals,args[i]->decimals); |
519 | max_length=float_length(decimals); |
520 | } |
521 | |
522 | Item *Item_sum::get_tmp_table_item(THD *thd) |
523 | { |
524 | Item_sum* sum_item= (Item_sum *) copy_or_same(thd); |
525 | if (sum_item && sum_item->result_field) // If not a const sum func |
526 | { |
527 | Field *result_field_tmp= sum_item->result_field; |
528 | for (uint i=0 ; i < sum_item->arg_count ; i++) |
529 | { |
530 | Item *arg= sum_item->args[i]; |
531 | if (!arg->const_item()) |
532 | { |
533 | if (arg->type() == Item::FIELD_ITEM) |
534 | ((Item_field*) arg)->field= result_field_tmp++; |
535 | else |
536 | sum_item->args[i]= new (thd->mem_root) Item_temptable_field(thd, result_field_tmp++); |
537 | } |
538 | } |
539 | } |
540 | return sum_item; |
541 | } |
542 | |
543 | |
544 | void Item_sum::update_used_tables () |
545 | { |
546 | if (!Item_sum::const_item()) |
547 | { |
548 | used_tables_cache= 0; |
549 | for (uint i=0 ; i < arg_count ; i++) |
550 | { |
551 | args[i]->update_used_tables(); |
552 | used_tables_cache|= args[i]->used_tables(); |
553 | } |
554 | /* |
555 | MariaDB: don't run the following { |
556 | |
557 | used_tables_cache&= PSEUDO_TABLE_BITS; |
558 | |
559 | // the aggregate function is aggregated into its local context |
560 | used_tables_cache|= ((table_map)1 << aggr_sel->join->tables) - 1; |
561 | |
562 | } because if we do it, table elimination will assume that |
563 | - constructs like "COUNT(*)" use columns from all tables |
564 | - so, it is not possible to eliminate any table |
565 | our solution for COUNT(*) is that it has |
566 | item->used_tables() == 0 && !item->const_item() |
567 | */ |
568 | } |
569 | } |
570 | |
571 | |
572 | Item *Item_sum::set_arg(uint i, THD *thd, Item *new_val) |
573 | { |
574 | thd->change_item_tree(args + i, new_val); |
575 | return new_val; |
576 | } |
577 | |
578 | |
579 | int Item_sum::set_aggregator(Aggregator::Aggregator_type aggregator) |
580 | { |
581 | /* |
582 | Dependent subselects may be executed multiple times, making |
583 | set_aggregator to be called multiple times. The aggregator type |
584 | will be the same, but it needs to be reset so that it is |
585 | reevaluated with the new dependent data. |
586 | This function may also be called multiple times during query optimization. |
587 | In this case, the type may change, so we delete the old aggregator, |
588 | and create a new one. |
589 | */ |
590 | if (aggr && aggregator == aggr->Aggrtype()) |
591 | { |
592 | aggr->clear(); |
593 | return FALSE; |
594 | } |
595 | |
596 | delete aggr; |
597 | switch (aggregator) |
598 | { |
599 | case Aggregator::DISTINCT_AGGREGATOR: |
600 | aggr= new Aggregator_distinct(this); |
601 | break; |
602 | case Aggregator::SIMPLE_AGGREGATOR: |
603 | aggr= new Aggregator_simple(this); |
604 | break; |
605 | }; |
606 | return aggr ? FALSE : TRUE; |
607 | } |
608 | |
609 | |
610 | void Item_sum::cleanup() |
611 | { |
612 | if (aggr) |
613 | { |
614 | delete aggr; |
615 | aggr= NULL; |
616 | } |
617 | Item_result_field::cleanup(); |
618 | const_item_cache= false; |
619 | } |
620 | |
621 | Item *Item_sum::result_item(THD *thd, Field *field) |
622 | { |
623 | return new (thd->mem_root) Item_field(thd, field); |
624 | } |
625 | |
626 | bool Item_sum::check_vcol_func_processor(void *arg) |
627 | { |
628 | return mark_unsupported_function(func_name(), |
629 | is_aggr_sum_func() ? ")" : "()" , |
630 | arg, VCOL_IMPOSSIBLE); |
631 | } |
632 | |
633 | |
634 | /** |
635 | Compare keys consisting of single field that cannot be compared as binary. |
636 | |
637 | Used by the Unique class to compare keys. Will do correct comparisons |
638 | for all field types. |
639 | |
640 | @param arg Pointer to the relevant Field class instance |
641 | @param key1 left key image |
642 | @param key2 right key image |
643 | @return comparison result |
644 | @retval < 0 if key1 < key2 |
645 | @retval = 0 if key1 = key2 |
646 | @retval > 0 if key1 > key2 |
647 | */ |
648 | |
649 | int simple_str_key_cmp(void* arg, uchar* key1, uchar* key2) |
650 | { |
651 | Field *f= (Field*) arg; |
652 | return f->cmp(key1, key2); |
653 | } |
654 | |
655 | |
656 | C_MODE_START |
657 | |
658 | int count_distinct_walk(void *elem, element_count count, void *arg) |
659 | { |
660 | (*((ulonglong*)arg))++; |
661 | return 0; |
662 | } |
663 | |
664 | C_MODE_END |
665 | |
666 | |
667 | /** |
668 | Correctly compare composite keys. |
669 | |
670 | Used by the Unique class to compare keys. Will do correct comparisons |
671 | for composite keys with various field types. |
672 | |
673 | @param arg Pointer to the relevant Aggregator_distinct instance |
674 | @param key1 left key image |
675 | @param key2 right key image |
676 | @return comparison result |
677 | @retval <0 if key1 < key2 |
678 | @retval =0 if key1 = key2 |
679 | @retval >0 if key1 > key2 |
680 | */ |
681 | |
682 | int Aggregator_distinct::composite_key_cmp(void* arg, uchar* key1, uchar* key2) |
683 | { |
684 | Aggregator_distinct *aggr= (Aggregator_distinct *) arg; |
685 | Field **field = aggr->table->field; |
686 | Field **field_end= field + aggr->table->s->fields; |
687 | uint32 *lengths=aggr->field_lengths; |
688 | for (; field < field_end; ++field) |
689 | { |
690 | Field* f = *field; |
691 | int len = *lengths++; |
692 | int res = f->cmp(key1, key2); |
693 | if (res) |
694 | return res; |
695 | key1 += len; |
696 | key2 += len; |
697 | } |
698 | return 0; |
699 | } |
700 | |
701 | |
702 | /***************************************************************************/ |
703 | |
704 | C_MODE_START |
705 | |
706 | /* Declarations for auxilary C-callbacks */ |
707 | |
708 | int simple_raw_key_cmp(void* arg, const void* key1, const void* key2) |
709 | { |
710 | return memcmp(key1, key2, *(uint *) arg); |
711 | } |
712 | |
713 | |
714 | static int item_sum_distinct_walk_for_count(void *element, |
715 | element_count num_of_dups, |
716 | void *item) |
717 | { |
718 | return ((Aggregator_distinct*) (item))->unique_walk_function_for_count(element); |
719 | } |
720 | |
721 | |
722 | static int item_sum_distinct_walk(void *element, element_count num_of_dups, |
723 | void *item) |
724 | { |
725 | return ((Aggregator_distinct*) (item))->unique_walk_function(element); |
726 | } |
727 | |
728 | C_MODE_END |
729 | |
730 | /***************************************************************************/ |
731 | /** |
732 | Called before feeding the first row. Used to allocate/setup |
733 | the internal structures used for aggregation. |
734 | |
735 | @param thd Thread descriptor |
736 | @return status |
737 | @retval FALSE success |
738 | @retval TRUE faliure |
739 | |
740 | Prepares Aggregator_distinct to process the incoming stream. |
741 | Creates the temporary table and the Unique class if needed. |
742 | Called by Item_sum::aggregator_setup() |
743 | */ |
744 | |
745 | bool Aggregator_distinct::setup(THD *thd) |
746 | { |
747 | endup_done= FALSE; |
748 | /* |
749 | Setup can be called twice for ROLLUP items. This is a bug. |
750 | Please add DBUG_ASSERT(tree == 0) here when it's fixed. |
751 | */ |
752 | if (tree || table || tmp_table_param) |
753 | return FALSE; |
754 | |
755 | if (item_sum->setup(thd)) |
756 | return TRUE; |
757 | if (item_sum->sum_func() == Item_sum::COUNT_FUNC || |
758 | item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC) |
759 | { |
760 | List<Item> list; |
761 | SELECT_LEX *select_lex= thd->lex->current_select; |
762 | |
763 | if (!(tmp_table_param= new TMP_TABLE_PARAM)) |
764 | return TRUE; |
765 | |
766 | /* Create a table with an unique key over all parameters */ |
767 | for (uint i=0; i < item_sum->get_arg_count() ; i++) |
768 | { |
769 | Item *item=item_sum->get_arg(i); |
770 | if (list.push_back(item, thd->mem_root)) |
771 | return TRUE; // End of memory |
772 | if (item->const_item() && item->is_null()) |
773 | always_null= true; |
774 | } |
775 | if (always_null) |
776 | return FALSE; |
777 | count_field_types(select_lex, tmp_table_param, list, 0); |
778 | tmp_table_param->force_copy_fields= item_sum->has_force_copy_fields(); |
779 | DBUG_ASSERT(table == 0); |
780 | /* |
781 | Make create_tmp_table() convert BIT columns to BIGINT. |
782 | This is needed because BIT fields store parts of their data in table's |
783 | null bits, and we don't have methods to compare two table records, which |
784 | is needed by Unique which is used when HEAP table is used. |
785 | */ |
786 | { |
787 | List_iterator_fast<Item> li(list); |
788 | Item *item; |
789 | while ((item= li++)) |
790 | { |
791 | if (item->type() == Item::FIELD_ITEM && |
792 | ((Item_field*)item)->field->type() == FIELD_TYPE_BIT) |
793 | item->marker=4; |
794 | } |
795 | } |
796 | if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1, |
797 | 0, |
798 | (select_lex->options | thd->variables.option_bits), |
799 | HA_POS_ERROR, &empty_clex_str))) |
800 | return TRUE; |
801 | table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows |
802 | table->no_rows=1; |
803 | |
804 | if (table->s->db_type() == heap_hton) |
805 | { |
806 | /* |
807 | No blobs, otherwise it would have been MyISAM: set up a compare |
808 | function and its arguments to use with Unique. |
809 | */ |
810 | qsort_cmp2 compare_key; |
811 | void* cmp_arg; |
812 | Field **field= table->field; |
813 | Field **field_end= field + table->s->fields; |
814 | bool all_binary= TRUE; |
815 | |
816 | for (tree_key_length= 0; field < field_end; ++field) |
817 | { |
818 | Field *f= *field; |
819 | enum enum_field_types type= f->type(); |
820 | tree_key_length+= f->pack_length(); |
821 | if ((type == MYSQL_TYPE_VARCHAR) || |
822 | (!f->binary() && (type == MYSQL_TYPE_STRING || |
823 | type == MYSQL_TYPE_VAR_STRING))) |
824 | { |
825 | all_binary= FALSE; |
826 | break; |
827 | } |
828 | } |
829 | if (all_binary) |
830 | { |
831 | cmp_arg= (void*) &tree_key_length; |
832 | compare_key= (qsort_cmp2) simple_raw_key_cmp; |
833 | } |
834 | else |
835 | { |
836 | if (table->s->fields == 1) |
837 | { |
838 | /* |
839 | If we have only one field, which is the most common use of |
840 | count(distinct), it is much faster to use a simpler key |
841 | compare method that can take advantage of not having to worry |
842 | about other fields. |
843 | */ |
844 | compare_key= (qsort_cmp2) simple_str_key_cmp; |
845 | cmp_arg= (void*) table->field[0]; |
846 | /* tree_key_length has been set already */ |
847 | } |
848 | else |
849 | { |
850 | uint32 *length; |
851 | compare_key= (qsort_cmp2) composite_key_cmp; |
852 | cmp_arg= (void*) this; |
853 | field_lengths= (uint32*) thd->alloc(table->s->fields * sizeof(uint32)); |
854 | for (tree_key_length= 0, length= field_lengths, field= table->field; |
855 | field < field_end; ++field, ++length) |
856 | { |
857 | *length= (*field)->pack_length(); |
858 | tree_key_length+= *length; |
859 | } |
860 | } |
861 | } |
862 | DBUG_ASSERT(tree == 0); |
863 | tree= new Unique(compare_key, cmp_arg, tree_key_length, |
864 | item_sum->ram_limitation(thd)); |
865 | /* |
866 | The only time tree_key_length could be 0 is if someone does |
867 | count(distinct) on a char(0) field - stupid thing to do, |
868 | but this has to be handled - otherwise someone can crash |
869 | the server with a DoS attack |
870 | */ |
871 | if (! tree) |
872 | return TRUE; |
873 | } |
874 | return FALSE; |
875 | } |
876 | else |
877 | { |
878 | Item *arg; |
879 | DBUG_ENTER("Aggregator_distinct::setup" ); |
880 | /* It's legal to call setup() more than once when in a subquery */ |
881 | if (tree) |
882 | DBUG_RETURN(FALSE); |
883 | |
884 | /* |
885 | Virtual table and the tree are created anew on each re-execution of |
886 | PS/SP. Hence all further allocations are performed in the runtime |
887 | mem_root. |
888 | */ |
889 | |
890 | item_sum->null_value= item_sum->maybe_null= 1; |
891 | item_sum->quick_group= 0; |
892 | |
893 | DBUG_ASSERT(item_sum->get_arg(0)->fixed); |
894 | |
895 | arg= item_sum->get_arg(0); |
896 | if (arg->const_item()) |
897 | { |
898 | (void) arg->is_null(); |
899 | if (arg->null_value) |
900 | always_null= true; |
901 | } |
902 | |
903 | if (always_null) |
904 | DBUG_RETURN(FALSE); |
905 | |
906 | Field *field= arg->type_handler()-> |
907 | make_num_distinct_aggregator_field(thd->mem_root, arg); |
908 | if (!field || !(table= create_virtual_tmp_table(thd, field))) |
909 | DBUG_RETURN(TRUE); |
910 | |
911 | /* XXX: check that the case of CHAR(0) works OK */ |
912 | tree_key_length= table->s->reclength - table->s->null_bytes; |
913 | |
914 | /* |
915 | Unique handles all unique elements in a tree until they can't fit |
916 | in. Then the tree is dumped to the temporary file. We can use |
917 | simple_raw_key_cmp because the table contains numbers only; decimals |
918 | are converted to binary representation as well. |
919 | */ |
920 | tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length, |
921 | item_sum->ram_limitation(thd)); |
922 | |
923 | DBUG_RETURN(tree == 0); |
924 | } |
925 | } |
926 | |
927 | |
928 | /** |
929 | Invalidate calculated value and clear the distinct rows. |
930 | |
931 | Frees space used by the internal data structures. |
932 | Removes the accumulated distinct rows. Invalidates the calculated result. |
933 | */ |
934 | |
935 | void Aggregator_distinct::clear() |
936 | { |
937 | endup_done= FALSE; |
938 | item_sum->clear(); |
939 | if (tree) |
940 | tree->reset(); |
941 | /* tree and table can be both null only if always_null */ |
942 | if (item_sum->sum_func() == Item_sum::COUNT_FUNC || |
943 | item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC) |
944 | { |
945 | if (!tree && table) |
946 | { |
947 | table->file->extra(HA_EXTRA_NO_CACHE); |
948 | table->file->ha_delete_all_rows(); |
949 | table->file->extra(HA_EXTRA_WRITE_CACHE); |
950 | } |
951 | } |
952 | else |
953 | { |
954 | item_sum->null_value= 1; |
955 | } |
956 | } |
957 | |
958 | |
959 | /** |
960 | Process incoming row. |
961 | |
962 | Add it to Unique/temp hash table if it's unique. Skip the row if |
963 | not unique. |
964 | Prepare Aggregator_distinct to process the incoming stream. |
965 | Create the temporary table and the Unique class if needed. |
966 | Called by Item_sum::aggregator_add(). |
967 | To actually get the result value in item_sum's buffers |
968 | Aggregator_distinct::endup() must be called. |
969 | |
970 | @return status |
971 | @retval FALSE success |
972 | @retval TRUE failure |
973 | */ |
974 | |
975 | bool Aggregator_distinct::add() |
976 | { |
977 | if (always_null) |
978 | return 0; |
979 | |
980 | if (item_sum->sum_func() == Item_sum::COUNT_FUNC || |
981 | item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC) |
982 | { |
983 | int error; |
984 | copy_fields(tmp_table_param); |
985 | if (copy_funcs(tmp_table_param->items_to_copy, table->in_use)) |
986 | return TRUE; |
987 | |
988 | for (Field **field=table->field ; *field ; field++) |
989 | if ((*field)->is_real_null(0)) |
990 | return 0; // Don't count NULL |
991 | |
992 | if (tree) |
993 | { |
994 | /* |
995 | The first few bytes of record (at least one) are just markers |
996 | for deleted and NULLs. We want to skip them since they will |
997 | bloat the tree without providing any valuable info. Besides, |
998 | key_length used to initialize the tree didn't include space for them. |
999 | */ |
1000 | return tree->unique_add(table->record[0] + table->s->null_bytes); |
1001 | } |
1002 | if (unlikely((error= table->file->ha_write_tmp_row(table->record[0]))) && |
1003 | table->file->is_fatal_error(error, HA_CHECK_DUP)) |
1004 | return TRUE; |
1005 | return FALSE; |
1006 | } |
1007 | else |
1008 | { |
1009 | item_sum->get_arg(0)->save_in_field(table->field[0], FALSE); |
1010 | if (table->field[0]->is_null()) |
1011 | return 0; |
1012 | DBUG_ASSERT(tree); |
1013 | item_sum->null_value= 0; |
1014 | /* |
1015 | '0' values are also stored in the tree. This doesn't matter |
1016 | for SUM(DISTINCT), but is important for AVG(DISTINCT) |
1017 | */ |
1018 | return tree->unique_add(table->field[0]->ptr); |
1019 | } |
1020 | } |
1021 | |
1022 | |
1023 | /** |
1024 | Calculate the aggregate function value. |
1025 | |
1026 | Since Distinct_aggregator::add() just collects the distinct rows, |
1027 | we must go over the distinct rows and feed them to the aggregation |
1028 | function before returning its value. |
1029 | This is what endup () does. It also sets the result validity flag |
1030 | endup_done to TRUE so it will not recalculate the aggregate value |
1031 | again if the Item_sum hasn't been reset. |
1032 | */ |
1033 | |
1034 | void Aggregator_distinct::endup() |
1035 | { |
1036 | /* prevent consecutive recalculations */ |
1037 | if (endup_done) |
1038 | return; |
1039 | |
1040 | /* we are going to calculate the aggregate value afresh */ |
1041 | item_sum->clear(); |
1042 | |
1043 | /* The result will definitely be null : no more calculations needed */ |
1044 | if (always_null) |
1045 | return; |
1046 | |
1047 | if (item_sum->sum_func() == Item_sum::COUNT_FUNC || |
1048 | item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC) |
1049 | { |
1050 | DBUG_ASSERT(item_sum->fixed == 1); |
1051 | Item_sum_count *sum= (Item_sum_count *)item_sum; |
1052 | if (tree && tree->elements == 0) |
1053 | { |
1054 | /* everything fits in memory */ |
1055 | sum->count= (longlong) tree->elements_in_tree(); |
1056 | endup_done= TRUE; |
1057 | } |
1058 | if (!tree) |
1059 | { |
1060 | /* there were blobs */ |
1061 | table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); |
1062 | sum->count= table->file->stats.records; |
1063 | endup_done= TRUE; |
1064 | } |
1065 | } |
1066 | |
1067 | /* |
1068 | We don't have a tree only if 'setup()' hasn't been called; |
1069 | this is the case of sql_executor.cc:return_zero_rows. |
1070 | */ |
1071 | if (tree && !endup_done) |
1072 | { |
1073 | /* |
1074 | All tree's values are not NULL. |
1075 | Note that value of field is changed as we walk the tree, in |
1076 | Aggregator_distinct::unique_walk_function, but it's always not NULL. |
1077 | */ |
1078 | table->field[0]->set_notnull(); |
1079 | /* go over the tree of distinct keys and calculate the aggregate value */ |
1080 | use_distinct_values= TRUE; |
1081 | tree_walk_action func; |
1082 | if (item_sum->sum_func() == Item_sum::COUNT_DISTINCT_FUNC) |
1083 | func= item_sum_distinct_walk_for_count; |
1084 | else |
1085 | func= item_sum_distinct_walk; |
1086 | tree->walk(table, func, (void*) this); |
1087 | use_distinct_values= FALSE; |
1088 | } |
1089 | /* prevent consecutive recalculations */ |
1090 | endup_done= TRUE; |
1091 | } |
1092 | |
1093 | |
1094 | String * |
1095 | Item_sum_num::val_str(String *str) |
1096 | { |
1097 | return val_string_from_real(str); |
1098 | } |
1099 | |
1100 | |
1101 | my_decimal *Item_sum_num::val_decimal(my_decimal *decimal_value) |
1102 | { |
1103 | return val_decimal_from_real(decimal_value); |
1104 | } |
1105 | |
1106 | |
1107 | String * |
1108 | Item_sum_int::val_str(String *str) |
1109 | { |
1110 | return val_string_from_int(str); |
1111 | } |
1112 | |
1113 | |
1114 | my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value) |
1115 | { |
1116 | return val_decimal_from_int(decimal_value); |
1117 | } |
1118 | |
1119 | |
1120 | bool |
1121 | Item_sum_num::fix_fields(THD *thd, Item **ref) |
1122 | { |
1123 | DBUG_ASSERT(fixed == 0); |
1124 | |
1125 | if (init_sum_func_check(thd)) |
1126 | return TRUE; |
1127 | |
1128 | decimals=0; |
1129 | maybe_null= sum_func() != COUNT_FUNC; |
1130 | for (uint i=0 ; i < arg_count ; i++) |
1131 | { |
1132 | if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) |
1133 | return TRUE; |
1134 | set_if_bigger(decimals, args[i]->decimals); |
1135 | m_with_subquery|= args[i]->with_subquery(); |
1136 | with_param|= args[i]->with_param; |
1137 | with_window_func|= args[i]->with_window_func; |
1138 | } |
1139 | result_field=0; |
1140 | max_length=float_length(decimals); |
1141 | null_value=1; |
1142 | fix_length_and_dec(); |
1143 | |
1144 | if (check_sum_func(thd, ref)) |
1145 | return TRUE; |
1146 | |
1147 | memcpy (orig_args, args, sizeof (Item *) * arg_count); |
1148 | fixed= 1; |
1149 | return FALSE; |
1150 | } |
1151 | |
1152 | |
1153 | bool |
1154 | Item_sum_hybrid::fix_fields(THD *thd, Item **ref) |
1155 | { |
1156 | DBUG_ENTER("Item_sum_hybrid::fix_fields" ); |
1157 | DBUG_ASSERT(fixed == 0); |
1158 | |
1159 | Item *item= args[0]; |
1160 | |
1161 | if (init_sum_func_check(thd)) |
1162 | DBUG_RETURN(TRUE); |
1163 | |
1164 | // 'item' can be changed during fix_fields |
1165 | if ((!item->fixed && item->fix_fields(thd, args)) || |
1166 | (item= args[0])->check_cols(1)) |
1167 | DBUG_RETURN(TRUE); |
1168 | |
1169 | m_with_subquery= args[0]->with_subquery(); |
1170 | with_param= args[0]->with_param; |
1171 | with_window_func|= args[0]->with_window_func; |
1172 | |
1173 | fix_length_and_dec(); |
1174 | if (!is_window_func_sum_expr()) |
1175 | setup_hybrid(thd, args[0], NULL); |
1176 | result_field=0; |
1177 | |
1178 | if (check_sum_func(thd, ref)) |
1179 | DBUG_RETURN(TRUE); |
1180 | |
1181 | orig_args[0]= args[0]; |
1182 | fixed= 1; |
1183 | DBUG_RETURN(FALSE); |
1184 | } |
1185 | |
1186 | |
1187 | void Item_sum_hybrid::fix_length_and_dec() |
1188 | { |
1189 | DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type()); |
1190 | DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type()); |
1191 | (void) args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this); |
1192 | } |
1193 | |
1194 | |
1195 | /** |
1196 | MIN/MAX function setup. |
1197 | |
1198 | @param item argument of MIN/MAX function |
1199 | @param value_arg calculated value of MIN/MAX function |
1200 | |
1201 | @details |
1202 | Setup cache/comparator of MIN/MAX functions. When called by the |
1203 | copy_or_same function value_arg parameter contains calculated value |
1204 | of the original MIN/MAX object and it is saved in this object's cache. |
1205 | |
1206 | We mark the value and arg_cache with 'RAND_TABLE_BIT' to ensure |
1207 | that Arg_comparator::compare_datetime() doesn't allocate new |
1208 | item inside of Arg_comparator. This would cause compare_datetime() |
1209 | and Item_sum_min::add() to use different values! |
1210 | */ |
1211 | |
1212 | void Item_sum_hybrid::setup_hybrid(THD *thd, Item *item, Item *value_arg) |
1213 | { |
1214 | DBUG_ENTER("Item_sum_hybrid::setup_hybrid" ); |
1215 | if (!(value= item->get_cache(thd))) |
1216 | DBUG_VOID_RETURN; |
1217 | value->setup(thd, item); |
1218 | value->store(value_arg); |
1219 | /* Don't cache value, as it will change */ |
1220 | if (!item->const_item()) |
1221 | value->set_used_tables(RAND_TABLE_BIT); |
1222 | if (!(arg_cache= item->get_cache(thd))) |
1223 | DBUG_VOID_RETURN; |
1224 | arg_cache->setup(thd, item); |
1225 | /* Don't cache value, as it will change */ |
1226 | if (!item->const_item()) |
1227 | arg_cache->set_used_tables(RAND_TABLE_BIT); |
1228 | cmp= new Arg_comparator(); |
1229 | if (cmp) |
1230 | cmp->set_cmp_func(this, (Item**)&arg_cache, (Item**)&value, FALSE); |
1231 | DBUG_VOID_RETURN; |
1232 | } |
1233 | |
1234 | |
1235 | Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) |
1236 | { |
1237 | DBUG_ENTER("Item_sum_hybrid::create_tmp_field" ); |
1238 | |
1239 | if (args[0]->type() == Item::FIELD_ITEM) |
1240 | { |
1241 | Field *field= ((Item_field*) args[0])->field; |
1242 | if ((field= create_tmp_field_from_field(table->in_use, field, &name, |
1243 | table, NULL))) |
1244 | field->flags&= ~NOT_NULL_FLAG; |
1245 | DBUG_RETURN(field); |
1246 | } |
1247 | DBUG_RETURN(tmp_table_field_from_field_type(table)); |
1248 | } |
1249 | |
1250 | /*********************************************************************** |
1251 | ** Item_sum_sp class |
1252 | ***********************************************************************/ |
1253 | |
1254 | Item_sum_sp::Item_sum_sp(THD *thd, Name_resolution_context *context_arg, |
1255 | sp_name *name_arg, sp_head *sp, List<Item> &list) |
1256 | :Item_sum(thd, list), Item_sp(thd, context_arg, name_arg) |
1257 | { |
1258 | maybe_null= 1; |
1259 | quick_group= 0; |
1260 | m_sp= sp; |
1261 | } |
1262 | |
1263 | Item_sum_sp::Item_sum_sp(THD *thd, Name_resolution_context *context_arg, |
1264 | sp_name *name_arg, sp_head *sp) |
1265 | :Item_sum(thd), Item_sp(thd, context_arg, name_arg) |
1266 | { |
1267 | maybe_null= 1; |
1268 | quick_group= 0; |
1269 | m_sp= sp; |
1270 | } |
1271 | |
1272 | Item_sum_sp::Item_sum_sp(THD *thd, Item_sum_sp *item): |
1273 | Item_sum(thd, item), Item_sp(thd, item) |
1274 | { |
1275 | maybe_null= item->maybe_null; |
1276 | quick_group= item->quick_group; |
1277 | } |
1278 | |
1279 | bool |
1280 | Item_sum_sp::fix_fields(THD *thd, Item **ref) |
1281 | { |
1282 | DBUG_ASSERT(fixed == 0); |
1283 | if (init_sum_func_check(thd)) |
1284 | return TRUE; |
1285 | decimals= 0; |
1286 | |
1287 | m_sp= m_sp ? m_sp : sp_handler_function.sp_find_routine(thd, m_name, true); |
1288 | |
1289 | if (!m_sp) |
1290 | { |
1291 | my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr()); |
1292 | context->process_error(thd); |
1293 | return TRUE; |
1294 | } |
1295 | |
1296 | if (init_result_field(thd, max_length, maybe_null, &null_value, &name)) |
1297 | return TRUE; |
1298 | |
1299 | for (uint i= 0 ; i < arg_count ; i++) |
1300 | { |
1301 | if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) |
1302 | return TRUE; |
1303 | set_if_bigger(decimals, args[i]->decimals); |
1304 | m_with_subquery|= args[i]->with_subquery(); |
1305 | with_window_func|= args[i]->with_window_func; |
1306 | } |
1307 | result_field= NULL; |
1308 | max_length= float_length(decimals); |
1309 | null_value= 1; |
1310 | fix_length_and_dec(); |
1311 | |
1312 | if (check_sum_func(thd, ref)) |
1313 | return TRUE; |
1314 | |
1315 | memcpy(orig_args, args, sizeof(Item *) * arg_count); |
1316 | fixed= 1; |
1317 | return FALSE; |
1318 | } |
1319 | |
1320 | /** |
1321 | Execute function to store value in result field. |
1322 | This is called when we need the value to be returned for the function. |
1323 | Here we send a signal in form of the server status that all rows have been |
1324 | fetched and now we have to exit from the function with the return value. |
1325 | @return Function returns error status. |
1326 | @retval FALSE on success. |
1327 | @retval TRUE if an error occurred. |
1328 | */ |
1329 | |
1330 | bool |
1331 | Item_sum_sp::execute() |
1332 | { |
1333 | THD *thd= current_thd; |
1334 | bool res; |
1335 | uint old_server_status= thd->server_status; |
1336 | |
1337 | /* We set server status so we can send a signal to exit from the |
1338 | function with the return value. */ |
1339 | |
1340 | thd->server_status= SERVER_STATUS_LAST_ROW_SENT; |
1341 | res= Item_sp::execute(thd, &null_value, args, arg_count); |
1342 | thd->server_status= old_server_status; |
1343 | return res; |
1344 | } |
1345 | |
1346 | /** |
1347 | Handles the aggregation of the values. |
1348 | @note: See class description for more details on how and why this is done. |
1349 | @return The error state. |
1350 | @retval FALSE on success. |
1351 | @retval TRUE if an error occurred. |
1352 | */ |
1353 | |
1354 | bool |
1355 | Item_sum_sp::add() |
1356 | { |
1357 | return execute_impl(current_thd, args, arg_count); |
1358 | } |
1359 | |
1360 | |
1361 | void |
1362 | Item_sum_sp::clear() |
1363 | { |
1364 | delete func_ctx; |
1365 | func_ctx= NULL; |
1366 | sp_query_arena->free_items(); |
1367 | free_root(&sp_mem_root, MYF(0)); |
1368 | } |
1369 | |
1370 | const Type_handler *Item_sum_sp::type_handler() const |
1371 | { |
1372 | DBUG_ENTER("Item_sum_sp::type_handler" ); |
1373 | DBUG_PRINT("info" , ("m_sp = %p" , (void *) m_sp)); |
1374 | DBUG_ASSERT(sp_result_field); |
1375 | // This converts ENUM/SET to STRING |
1376 | const Type_handler *handler= sp_result_field->type_handler(); |
1377 | DBUG_RETURN(handler->type_handler_for_item_field()); |
1378 | } |
1379 | |
1380 | void |
1381 | Item_sum_sp::cleanup() |
1382 | { |
1383 | Item_sp::cleanup(); |
1384 | Item_sum::cleanup(); |
1385 | } |
1386 | |
1387 | /** |
1388 | Initialize local members with values from the Field interface. |
1389 | @note called from Item::fix_fields. |
1390 | */ |
1391 | |
1392 | void |
1393 | Item_sum_sp::fix_length_and_dec() |
1394 | { |
1395 | DBUG_ENTER("Item_sum_sp::fix_length_and_dec" ); |
1396 | DBUG_ASSERT(sp_result_field); |
1397 | Type_std_attributes::set(sp_result_field->type_std_attributes()); |
1398 | Item_sum::fix_length_and_dec(); |
1399 | DBUG_VOID_RETURN; |
1400 | } |
1401 | |
1402 | const char * |
1403 | Item_sum_sp::func_name() const |
1404 | { |
1405 | THD *thd= current_thd; |
1406 | return Item_sp::func_name(thd); |
1407 | } |
1408 | |
1409 | Item* Item_sum_sp::copy_or_same(THD *thd) |
1410 | { |
1411 | Item_sum_sp *copy_item= new (thd->mem_root) Item_sum_sp(thd, this); |
1412 | copy_item->init_result_field(thd, max_length, maybe_null, |
1413 | ©_item->null_value, ©_item->name); |
1414 | return copy_item; |
1415 | } |
1416 | |
1417 | /*********************************************************************** |
1418 | ** reset and add of sum_func |
1419 | ***********************************************************************/ |
1420 | |
1421 | /** |
1422 | @todo |
1423 | check if the following assignments are really needed |
1424 | */ |
1425 | Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item) |
1426 | :Item_sum_num(thd, item), |
1427 | Type_handler_hybrid_field_type(item), |
1428 | direct_added(FALSE), direct_reseted_field(FALSE), |
1429 | curr_dec_buff(item->curr_dec_buff), |
1430 | count(item->count) |
1431 | { |
1432 | /* TODO: check if the following assignments are really needed */ |
1433 | if (result_type() == DECIMAL_RESULT) |
1434 | { |
1435 | my_decimal2decimal(item->dec_buffs, dec_buffs); |
1436 | my_decimal2decimal(item->dec_buffs + 1, dec_buffs + 1); |
1437 | } |
1438 | else |
1439 | sum= item->sum; |
1440 | } |
1441 | |
1442 | Item *Item_sum_sum::copy_or_same(THD* thd) |
1443 | { |
1444 | return new (thd->mem_root) Item_sum_sum(thd, this); |
1445 | } |
1446 | |
1447 | |
1448 | void Item_sum_sum::cleanup() |
1449 | { |
1450 | DBUG_ENTER("Item_sum_sum::cleanup" ); |
1451 | direct_added= direct_reseted_field= FALSE; |
1452 | Item_sum_num::cleanup(); |
1453 | DBUG_VOID_RETURN; |
1454 | } |
1455 | |
1456 | |
1457 | void Item_sum_sum::clear() |
1458 | { |
1459 | DBUG_ENTER("Item_sum_sum::clear" ); |
1460 | null_value=1; |
1461 | count= 0; |
1462 | if (result_type() == DECIMAL_RESULT) |
1463 | { |
1464 | curr_dec_buff= 0; |
1465 | my_decimal_set_zero(dec_buffs); |
1466 | } |
1467 | else |
1468 | sum= 0.0; |
1469 | DBUG_VOID_RETURN; |
1470 | } |
1471 | |
1472 | |
1473 | void Item_sum_sum::fix_length_and_dec_double() |
1474 | { |
1475 | set_handler(&type_handler_double); // Change FLOAT to DOUBLE |
1476 | decimals= args[0]->decimals; |
1477 | sum= 0.0; |
1478 | } |
1479 | |
1480 | |
1481 | void Item_sum_sum::fix_length_and_dec_decimal() |
1482 | { |
1483 | set_handler(&type_handler_newdecimal); // Change temporal to new DECIMAL |
1484 | decimals= args[0]->decimals; |
1485 | /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */ |
1486 | int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS; |
1487 | max_length= my_decimal_precision_to_length_no_truncation(precision, |
1488 | decimals, |
1489 | unsigned_flag); |
1490 | curr_dec_buff= 0; |
1491 | my_decimal_set_zero(dec_buffs); |
1492 | } |
1493 | |
1494 | |
1495 | void Item_sum_sum::fix_length_and_dec() |
1496 | { |
1497 | DBUG_ENTER("Item_sum_sum::fix_length_and_dec" ); |
1498 | maybe_null=null_value=1; |
1499 | args[0]->cast_to_int_type_handler()->Item_sum_sum_fix_length_and_dec(this); |
1500 | DBUG_PRINT("info" , ("Type: %s (%d, %d)" , type_handler()->name().ptr(), |
1501 | max_length, (int) decimals)); |
1502 | DBUG_VOID_RETURN; |
1503 | } |
1504 | |
1505 | |
1506 | void Item_sum_sum::direct_add(my_decimal *add_sum_decimal) |
1507 | { |
1508 | DBUG_ENTER("Item_sum_sum::direct_add" ); |
1509 | DBUG_PRINT("info" , ("add_sum_decimal: %p" , add_sum_decimal)); |
1510 | direct_added= TRUE; |
1511 | direct_reseted_field= FALSE; |
1512 | if (add_sum_decimal) |
1513 | { |
1514 | direct_sum_is_null= FALSE; |
1515 | direct_sum_decimal= *add_sum_decimal; |
1516 | } |
1517 | else |
1518 | { |
1519 | direct_sum_is_null= TRUE; |
1520 | direct_sum_decimal= decimal_zero; |
1521 | } |
1522 | DBUG_VOID_RETURN; |
1523 | } |
1524 | |
1525 | |
1526 | void Item_sum_sum::direct_add(double add_sum_real, bool add_sum_is_null) |
1527 | { |
1528 | DBUG_ENTER("Item_sum_sum::direct_add" ); |
1529 | DBUG_PRINT("info" , ("add_sum_real: %f" , add_sum_real)); |
1530 | direct_added= TRUE; |
1531 | direct_reseted_field= FALSE; |
1532 | direct_sum_is_null= add_sum_is_null; |
1533 | direct_sum_real= add_sum_real; |
1534 | DBUG_VOID_RETURN; |
1535 | } |
1536 | |
1537 | |
1538 | bool Item_sum_sum::add() |
1539 | { |
1540 | DBUG_ENTER("Item_sum_sum::add" ); |
1541 | add_helper(false); |
1542 | DBUG_RETURN(0); |
1543 | } |
1544 | |
1545 | void Item_sum_sum::add_helper(bool perform_removal) |
1546 | { |
1547 | DBUG_ENTER("Item_sum_sum::add_helper" ); |
1548 | |
1549 | if (result_type() == DECIMAL_RESULT) |
1550 | { |
1551 | if (unlikely(direct_added)) |
1552 | { |
1553 | /* Add value stored by Item_sum_sum::direct_add */ |
1554 | DBUG_ASSERT(!perform_removal); |
1555 | |
1556 | direct_added= FALSE; |
1557 | if (likely(!direct_sum_is_null)) |
1558 | { |
1559 | my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1), |
1560 | &direct_sum_decimal, dec_buffs + curr_dec_buff); |
1561 | curr_dec_buff^= 1; |
1562 | null_value= 0; |
1563 | } |
1564 | } |
1565 | else |
1566 | { |
1567 | direct_reseted_field= FALSE; |
1568 | my_decimal value; |
1569 | const my_decimal *val= aggr->arg_val_decimal(&value); |
1570 | if (!aggr->arg_is_null(true)) |
1571 | { |
1572 | if (perform_removal) |
1573 | { |
1574 | if (count > 0) |
1575 | { |
1576 | my_decimal_sub(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff ^ 1), |
1577 | dec_buffs + curr_dec_buff, val); |
1578 | count--; |
1579 | } |
1580 | else |
1581 | DBUG_VOID_RETURN; |
1582 | } |
1583 | else |
1584 | { |
1585 | count++; |
1586 | my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff ^ 1), |
1587 | val, dec_buffs + curr_dec_buff); |
1588 | } |
1589 | curr_dec_buff^= 1; |
1590 | null_value= (count > 0) ? 0 : 1; |
1591 | } |
1592 | } |
1593 | } |
1594 | else |
1595 | { |
1596 | if (unlikely(direct_added)) |
1597 | { |
1598 | /* Add value stored by Item_sum_sum::direct_add */ |
1599 | DBUG_ASSERT(!perform_removal); |
1600 | |
1601 | direct_added= FALSE; |
1602 | if (!direct_sum_is_null) |
1603 | { |
1604 | sum+= direct_sum_real; |
1605 | null_value= 0; |
1606 | } |
1607 | } |
1608 | else |
1609 | { |
1610 | direct_reseted_field= FALSE; |
1611 | if (perform_removal && count > 0) |
1612 | sum-= aggr->arg_val_real(); |
1613 | else |
1614 | sum+= aggr->arg_val_real(); |
1615 | if (!aggr->arg_is_null(true)) |
1616 | { |
1617 | if (perform_removal) |
1618 | { |
1619 | if (count > 0) |
1620 | { |
1621 | count--; |
1622 | } |
1623 | } |
1624 | else |
1625 | count++; |
1626 | |
1627 | null_value= (count > 0) ? 0 : 1; |
1628 | } |
1629 | } |
1630 | } |
1631 | DBUG_VOID_RETURN; |
1632 | } |
1633 | |
1634 | |
1635 | longlong Item_sum_sum::val_int() |
1636 | { |
1637 | DBUG_ASSERT(fixed == 1); |
1638 | if (aggr) |
1639 | aggr->endup(); |
1640 | if (result_type() == DECIMAL_RESULT) |
1641 | { |
1642 | longlong result; |
1643 | my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag, |
1644 | &result); |
1645 | return result; |
1646 | } |
1647 | return val_int_from_real(); |
1648 | } |
1649 | |
1650 | |
1651 | double Item_sum_sum::val_real() |
1652 | { |
1653 | DBUG_ASSERT(fixed == 1); |
1654 | if (aggr) |
1655 | aggr->endup(); |
1656 | if (result_type() == DECIMAL_RESULT) |
1657 | my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum); |
1658 | return sum; |
1659 | } |
1660 | |
1661 | |
1662 | String *Item_sum_sum::val_str(String *str) |
1663 | { |
1664 | if (aggr) |
1665 | aggr->endup(); |
1666 | if (result_type() == DECIMAL_RESULT) |
1667 | return val_string_from_decimal(str); |
1668 | return val_string_from_real(str); |
1669 | } |
1670 | |
1671 | |
1672 | my_decimal *Item_sum_sum::val_decimal(my_decimal *val) |
1673 | { |
1674 | if (aggr) |
1675 | aggr->endup(); |
1676 | if (result_type() == DECIMAL_RESULT) |
1677 | return null_value ? NULL : (dec_buffs + curr_dec_buff); |
1678 | return val_decimal_from_real(val); |
1679 | } |
1680 | |
1681 | void Item_sum_sum::remove() |
1682 | { |
1683 | DBUG_ENTER("Item_sum_sum::remove" ); |
1684 | add_helper(true); |
1685 | DBUG_VOID_RETURN; |
1686 | } |
1687 | |
1688 | /** |
1689 | Aggregate a distinct row from the distinct hash table. |
1690 | |
1691 | Called for each row into the hash table 'Aggregator_distinct::table'. |
1692 | Includes the current distinct row into the calculation of the |
1693 | aggregate value. Uses the Field classes to get the value from the row. |
1694 | This function is used for AVG/SUM(DISTINCT). For COUNT(DISTINCT) |
1695 | it's called only when there are no blob arguments and the data don't |
1696 | fit into memory (so Unique makes persisted trees on disk). |
1697 | |
1698 | @param element pointer to the row data. |
1699 | |
1700 | @return status |
1701 | @retval FALSE success |
1702 | @retval TRUE failure |
1703 | */ |
1704 | |
1705 | bool Aggregator_distinct::unique_walk_function(void *element) |
1706 | { |
1707 | memcpy(table->field[0]->ptr, element, tree_key_length); |
1708 | item_sum->add(); |
1709 | return 0; |
1710 | } |
1711 | |
1712 | |
1713 | /* |
1714 | A variant of unique_walk_function() that is to be used with Item_sum_count. |
1715 | |
1716 | COUNT is a special aggregate function: it doesn't need the values, it only |
1717 | needs to count them. COUNT needs to know the values are not NULLs, but NULL |
1718 | values are not put into the Unique, so we don't need to check for NULLs here. |
1719 | */ |
1720 | |
1721 | bool Aggregator_distinct::unique_walk_function_for_count(void *element) |
1722 | { |
1723 | Item_sum_count *sum= (Item_sum_count *)item_sum; |
1724 | sum->count++; |
1725 | return 0; |
1726 | } |
1727 | |
1728 | |
1729 | Aggregator_distinct::~Aggregator_distinct() |
1730 | { |
1731 | if (tree) |
1732 | { |
1733 | delete tree; |
1734 | tree= NULL; |
1735 | } |
1736 | if (table) |
1737 | { |
1738 | free_tmp_table(table->in_use, table); |
1739 | table=NULL; |
1740 | } |
1741 | if (tmp_table_param) |
1742 | { |
1743 | delete tmp_table_param; |
1744 | tmp_table_param= NULL; |
1745 | } |
1746 | } |
1747 | |
1748 | |
1749 | my_decimal *Aggregator_simple::arg_val_decimal(my_decimal *value) |
1750 | { |
1751 | return item_sum->args[0]->val_decimal(value); |
1752 | } |
1753 | |
1754 | |
1755 | double Aggregator_simple::arg_val_real() |
1756 | { |
1757 | return item_sum->args[0]->val_real(); |
1758 | } |
1759 | |
1760 | |
1761 | bool Aggregator_simple::arg_is_null(bool use_null_value) |
1762 | { |
1763 | Item **item= item_sum->args; |
1764 | const uint item_count= item_sum->arg_count; |
1765 | if (use_null_value) |
1766 | { |
1767 | for (uint i= 0; i < item_count; i++) |
1768 | { |
1769 | if (item[i]->null_value) |
1770 | return true; |
1771 | } |
1772 | } |
1773 | else |
1774 | { |
1775 | for (uint i= 0; i < item_count; i++) |
1776 | { |
1777 | if (item[i]->maybe_null && item[i]->is_null()) |
1778 | return true; |
1779 | } |
1780 | } |
1781 | return false; |
1782 | } |
1783 | |
1784 | |
1785 | my_decimal *Aggregator_distinct::arg_val_decimal(my_decimal * value) |
1786 | { |
1787 | return use_distinct_values ? table->field[0]->val_decimal(value) : |
1788 | item_sum->args[0]->val_decimal(value); |
1789 | } |
1790 | |
1791 | |
1792 | double Aggregator_distinct::arg_val_real() |
1793 | { |
1794 | return use_distinct_values ? table->field[0]->val_real() : |
1795 | item_sum->args[0]->val_real(); |
1796 | } |
1797 | |
1798 | |
1799 | bool Aggregator_distinct::arg_is_null(bool use_null_value) |
1800 | { |
1801 | if (use_distinct_values) |
1802 | { |
1803 | const bool rc= table->field[0]->is_null(); |
1804 | DBUG_ASSERT(!rc); // NULLs are never stored in 'tree' |
1805 | return rc; |
1806 | } |
1807 | return use_null_value ? |
1808 | item_sum->args[0]->null_value : |
1809 | (item_sum->args[0]->maybe_null && item_sum->args[0]->is_null()); |
1810 | } |
1811 | |
1812 | |
1813 | Item *Item_sum_count::copy_or_same(THD* thd) |
1814 | { |
1815 | DBUG_ENTER("Item_sum_count::copy_or_same" ); |
1816 | DBUG_RETURN(new (thd->mem_root) Item_sum_count(thd, this)); |
1817 | } |
1818 | |
1819 | |
1820 | void Item_sum_count::direct_add(longlong add_count) |
1821 | { |
1822 | DBUG_ENTER("Item_sum_count::direct_add" ); |
1823 | DBUG_PRINT("info" , ("add_count: %lld" , add_count)); |
1824 | direct_counted= TRUE; |
1825 | direct_reseted_field= FALSE; |
1826 | direct_count= add_count; |
1827 | DBUG_VOID_RETURN; |
1828 | } |
1829 | |
1830 | |
1831 | void Item_sum_count::clear() |
1832 | { |
1833 | DBUG_ENTER("Item_sum_count::clear" ); |
1834 | count= 0; |
1835 | DBUG_VOID_RETURN; |
1836 | } |
1837 | |
1838 | |
1839 | bool Item_sum_count::add() |
1840 | { |
1841 | DBUG_ENTER("Item_sum_count::add" ); |
1842 | if (direct_counted) |
1843 | { |
1844 | direct_counted= FALSE; |
1845 | count+= direct_count; |
1846 | } |
1847 | else |
1848 | { |
1849 | direct_reseted_field= FALSE; |
1850 | if (aggr->arg_is_null(false)) |
1851 | DBUG_RETURN(0); |
1852 | count++; |
1853 | } |
1854 | DBUG_RETURN(0); |
1855 | } |
1856 | |
1857 | |
1858 | /* |
1859 | Remove a row. This is used by window functions. |
1860 | */ |
1861 | |
1862 | void Item_sum_count::remove() |
1863 | { |
1864 | DBUG_ASSERT(aggr->Aggrtype() == Aggregator::SIMPLE_AGGREGATOR); |
1865 | if (aggr->arg_is_null(false)) |
1866 | return; |
1867 | if (count > 0) |
1868 | count--; |
1869 | } |
1870 | |
1871 | longlong Item_sum_count::val_int() |
1872 | { |
1873 | DBUG_ENTER("Item_sum_count::val_int" ); |
1874 | DBUG_ASSERT(fixed == 1); |
1875 | if (aggr) |
1876 | aggr->endup(); |
1877 | DBUG_RETURN((longlong)count); |
1878 | } |
1879 | |
1880 | |
1881 | void Item_sum_count::cleanup() |
1882 | { |
1883 | DBUG_ENTER("Item_sum_count::cleanup" ); |
1884 | count= 0; |
1885 | direct_counted= FALSE; |
1886 | direct_reseted_field= FALSE; |
1887 | Item_sum_int::cleanup(); |
1888 | DBUG_VOID_RETURN; |
1889 | } |
1890 | |
1891 | |
1892 | /* |
1893 | Avgerage |
1894 | */ |
1895 | |
1896 | void Item_sum_avg::fix_length_and_dec_decimal() |
1897 | { |
1898 | Item_sum_sum::fix_length_and_dec_decimal(); |
1899 | int precision= args[0]->decimal_precision() + prec_increment; |
1900 | decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE); |
1901 | max_length= my_decimal_precision_to_length_no_truncation(precision, |
1902 | decimals, |
1903 | unsigned_flag); |
1904 | f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION); |
1905 | f_scale= args[0]->decimals; |
1906 | dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale); |
1907 | } |
1908 | |
1909 | |
1910 | void Item_sum_avg::fix_length_and_dec_double() |
1911 | { |
1912 | Item_sum_sum::fix_length_and_dec_double(); |
1913 | decimals= MY_MIN(args[0]->decimals + prec_increment, |
1914 | FLOATING_POINT_DECIMALS); |
1915 | max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals)); |
1916 | } |
1917 | |
1918 | |
1919 | void Item_sum_avg::fix_length_and_dec() |
1920 | { |
1921 | DBUG_ENTER("Item_sum_avg::fix_length_and_dec" ); |
1922 | prec_increment= current_thd->variables.div_precincrement; |
1923 | maybe_null=null_value=1; |
1924 | args[0]->cast_to_int_type_handler()->Item_sum_avg_fix_length_and_dec(this); |
1925 | DBUG_PRINT("info" , ("Type: %s (%d, %d)" , type_handler()->name().ptr(), |
1926 | max_length, (int) decimals)); |
1927 | DBUG_VOID_RETURN; |
1928 | } |
1929 | |
1930 | |
1931 | Item *Item_sum_avg::copy_or_same(THD* thd) |
1932 | { |
1933 | return new (thd->mem_root) Item_sum_avg(thd, this); |
1934 | } |
1935 | |
1936 | |
1937 | Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) |
1938 | { |
1939 | |
1940 | if (group) |
1941 | { |
1942 | /* |
1943 | We must store both value and counter in the temporary table in one field. |
1944 | The easiest way is to do this is to store both value in a string |
1945 | and unpack on access. |
1946 | */ |
1947 | Field *field= new (table->in_use->mem_root) |
1948 | Field_string(((result_type() == DECIMAL_RESULT) ? |
1949 | dec_bin_size : sizeof(double)) + sizeof(longlong), |
1950 | 0, &name, &my_charset_bin); |
1951 | if (field) |
1952 | field->init(table); |
1953 | return field; |
1954 | } |
1955 | return tmp_table_field_from_field_type(table); |
1956 | } |
1957 | |
1958 | |
1959 | void Item_sum_avg::clear() |
1960 | { |
1961 | Item_sum_sum::clear(); |
1962 | count=0; |
1963 | } |
1964 | |
1965 | |
1966 | bool Item_sum_avg::add() |
1967 | { |
1968 | if (Item_sum_sum::add()) |
1969 | return TRUE; |
1970 | if (!aggr->arg_is_null(true)) |
1971 | count++; |
1972 | return FALSE; |
1973 | } |
1974 | |
1975 | void Item_sum_avg::remove() |
1976 | { |
1977 | Item_sum_sum::remove(); |
1978 | if (!aggr->arg_is_null(true)) |
1979 | { |
1980 | if (count > 0) |
1981 | count--; |
1982 | } |
1983 | } |
1984 | |
1985 | double Item_sum_avg::val_real() |
1986 | { |
1987 | DBUG_ASSERT(fixed == 1); |
1988 | if (aggr) |
1989 | aggr->endup(); |
1990 | if (!count) |
1991 | { |
1992 | null_value=1; |
1993 | return 0.0; |
1994 | } |
1995 | return Item_sum_sum::val_real() / ulonglong2double(count); |
1996 | } |
1997 | |
1998 | |
1999 | my_decimal *Item_sum_avg::val_decimal(my_decimal *val) |
2000 | { |
2001 | my_decimal cnt; |
2002 | const my_decimal *sum_dec; |
2003 | DBUG_ASSERT(fixed == 1); |
2004 | if (aggr) |
2005 | aggr->endup(); |
2006 | if (!count) |
2007 | { |
2008 | null_value=1; |
2009 | return NULL; |
2010 | } |
2011 | |
2012 | /* |
2013 | For non-DECIMAL result_type() the division will be done in |
2014 | Item_sum_avg::val_real(). |
2015 | */ |
2016 | if (result_type() != DECIMAL_RESULT) |
2017 | return val_decimal_from_real(val); |
2018 | |
2019 | sum_dec= dec_buffs + curr_dec_buff; |
2020 | int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt); |
2021 | my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment); |
2022 | return val; |
2023 | } |
2024 | |
2025 | |
2026 | String *Item_sum_avg::val_str(String *str) |
2027 | { |
2028 | if (aggr) |
2029 | aggr->endup(); |
2030 | if (result_type() == DECIMAL_RESULT) |
2031 | return val_string_from_decimal(str); |
2032 | return val_string_from_real(str); |
2033 | } |
2034 | |
2035 | |
2036 | /* |
2037 | Standard deviation |
2038 | */ |
2039 | |
2040 | double Item_sum_std::val_real() |
2041 | { |
2042 | DBUG_ASSERT(fixed == 1); |
2043 | double nr= Item_sum_variance::val_real(); |
2044 | if (my_isinf(nr)) |
2045 | return DBL_MAX; |
2046 | DBUG_ASSERT(nr >= 0.0); |
2047 | return sqrt(nr); |
2048 | } |
2049 | |
2050 | Item *Item_sum_std::copy_or_same(THD* thd) |
2051 | { |
2052 | return new (thd->mem_root) Item_sum_std(thd, this); |
2053 | } |
2054 | |
2055 | |
2056 | Item *Item_sum_std::result_item(THD *thd, Field *field) |
2057 | { |
2058 | return new (thd->mem_root) Item_std_field(thd, this); |
2059 | } |
2060 | |
2061 | |
2062 | /* |
2063 | Variance |
2064 | */ |
2065 | |
2066 | |
2067 | /** |
2068 | Variance implementation for floating-point implementations, without |
2069 | catastrophic cancellation, from Knuth's _TAoCP_, 3rd ed, volume 2, pg232. |
2070 | This alters the value at m, s, and increments count. |
2071 | */ |
2072 | |
2073 | /* |
2074 | These two functions are used by the Item_sum_variance and the |
2075 | Item_variance_field classes, which are unrelated, and each need to calculate |
2076 | variance. The difference between the two classes is that the first is used |
2077 | for a mundane SELECT, while the latter is used in a GROUPing SELECT. |
2078 | */ |
2079 | static void variance_fp_recurrence_next(double *m, double *s, ulonglong *count, double nr) |
2080 | { |
2081 | *count += 1; |
2082 | |
2083 | if (*count == 1) |
2084 | { |
2085 | *m= nr; |
2086 | *s= 0; |
2087 | } |
2088 | else |
2089 | { |
2090 | double m_kminusone= *m; |
2091 | *m= m_kminusone + (nr - m_kminusone) / (double) *count; |
2092 | *s= *s + (nr - m_kminusone) * (nr - *m); |
2093 | } |
2094 | } |
2095 | |
2096 | |
2097 | static double variance_fp_recurrence_result(double s, ulonglong count, bool is_sample_variance) |
2098 | { |
2099 | if (count == 1) |
2100 | return 0.0; |
2101 | |
2102 | if (is_sample_variance) |
2103 | return s / (count - 1); |
2104 | |
2105 | /* else, is a population variance */ |
2106 | return s / count; |
2107 | } |
2108 | |
2109 | |
2110 | Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item): |
2111 | Item_sum_num(thd, item), |
2112 | count(item->count), sample(item->sample), |
2113 | prec_increment(item->prec_increment) |
2114 | { |
2115 | recurrence_m= item->recurrence_m; |
2116 | recurrence_s= item->recurrence_s; |
2117 | } |
2118 | |
2119 | |
2120 | void Item_sum_variance::fix_length_and_dec_double() |
2121 | { |
2122 | DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double); |
2123 | decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS); |
2124 | } |
2125 | |
2126 | |
2127 | void Item_sum_variance::fix_length_and_dec_decimal() |
2128 | { |
2129 | DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double); |
2130 | int precision= args[0]->decimal_precision() * 2 + prec_increment; |
2131 | decimals= MY_MIN(args[0]->decimals + prec_increment, |
2132 | FLOATING_POINT_DECIMALS - 1); |
2133 | max_length= my_decimal_precision_to_length_no_truncation(precision, |
2134 | decimals, |
2135 | unsigned_flag); |
2136 | } |
2137 | |
2138 | |
2139 | void Item_sum_variance::fix_length_and_dec() |
2140 | { |
2141 | DBUG_ENTER("Item_sum_variance::fix_length_and_dec" ); |
2142 | maybe_null= null_value= 1; |
2143 | prec_increment= current_thd->variables.div_precincrement; |
2144 | |
2145 | /* |
2146 | According to the SQL2003 standard (Part 2, Foundations; sec 10.9, |
2147 | aggregate function; paragraph 7h of Syntax Rules), "the declared |
2148 | type of the result is an implementation-defined aproximate numeric |
2149 | type. |
2150 | */ |
2151 | |
2152 | args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this); |
2153 | DBUG_PRINT("info" , ("Type: %s (%d, %d)" , type_handler()->name().ptr(), |
2154 | max_length, (int)decimals)); |
2155 | DBUG_VOID_RETURN; |
2156 | } |
2157 | |
2158 | |
2159 | Item *Item_sum_variance::copy_or_same(THD* thd) |
2160 | { |
2161 | return new (thd->mem_root) Item_sum_variance(thd, this); |
2162 | } |
2163 | |
2164 | |
2165 | /** |
2166 | Create a new field to match the type of value we're expected to yield. |
2167 | If we're grouping, then we need some space to serialize variables into, to |
2168 | pass around. |
2169 | */ |
2170 | Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table) |
2171 | { |
2172 | Field *field; |
2173 | if (group) |
2174 | { |
2175 | /* |
2176 | We must store both value and counter in the temporary table in one field. |
2177 | The easiest way is to do this is to store both value in a string |
2178 | and unpack on access. |
2179 | */ |
2180 | field= new Field_string(sizeof(double)*2 + sizeof(longlong), 0, |
2181 | &name, &my_charset_bin); |
2182 | } |
2183 | else |
2184 | field= new Field_double(max_length, maybe_null, &name, decimals, |
2185 | TRUE); |
2186 | |
2187 | if (field != NULL) |
2188 | field->init(table); |
2189 | |
2190 | return field; |
2191 | } |
2192 | |
2193 | |
2194 | void Item_sum_variance::clear() |
2195 | { |
2196 | count= 0; |
2197 | } |
2198 | |
2199 | bool Item_sum_variance::add() |
2200 | { |
2201 | /* |
2202 | Why use a temporary variable? We don't know if it is null until we |
2203 | evaluate it, which has the side-effect of setting null_value . |
2204 | */ |
2205 | double nr= args[0]->val_real(); |
2206 | |
2207 | if (!args[0]->null_value) |
2208 | variance_fp_recurrence_next(&recurrence_m, &recurrence_s, &count, nr); |
2209 | return 0; |
2210 | } |
2211 | |
2212 | double Item_sum_variance::val_real() |
2213 | { |
2214 | DBUG_ASSERT(fixed == 1); |
2215 | |
2216 | /* |
2217 | 'sample' is a 1/0 boolean value. If it is 1/true, id est this is a sample |
2218 | variance call, then we should set nullness when the count of the items |
2219 | is one or zero. If it's zero, i.e. a population variance, then we only |
2220 | set nullness when the count is zero. |
2221 | |
2222 | Another way to read it is that 'sample' is the numerical threshhold, at and |
2223 | below which a 'count' number of items is called NULL. |
2224 | */ |
2225 | DBUG_ASSERT((sample == 0) || (sample == 1)); |
2226 | if (count <= sample) |
2227 | { |
2228 | null_value=1; |
2229 | return 0.0; |
2230 | } |
2231 | |
2232 | null_value=0; |
2233 | return variance_fp_recurrence_result(recurrence_s, count, sample); |
2234 | } |
2235 | |
2236 | |
2237 | my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf) |
2238 | { |
2239 | DBUG_ASSERT(fixed == 1); |
2240 | return val_decimal_from_real(dec_buf); |
2241 | } |
2242 | |
2243 | |
2244 | void Item_sum_variance::reset_field() |
2245 | { |
2246 | double nr; |
2247 | uchar *res= result_field->ptr; |
2248 | |
2249 | nr= args[0]->val_real(); /* sets null_value as side-effect */ |
2250 | |
2251 | if (args[0]->null_value) |
2252 | bzero(res,sizeof(double)*2+sizeof(longlong)); |
2253 | else |
2254 | { |
2255 | /* Serialize format is (double)m, (double)s, (longlong)count */ |
2256 | ulonglong tmp_count; |
2257 | double tmp_s; |
2258 | float8store(res, nr); /* recurrence variable m */ |
2259 | tmp_s= 0.0; |
2260 | float8store(res + sizeof(double), tmp_s); |
2261 | tmp_count= 1; |
2262 | int8store(res + sizeof(double)*2, tmp_count); |
2263 | } |
2264 | } |
2265 | |
2266 | |
2267 | void Item_sum_variance::update_field() |
2268 | { |
2269 | ulonglong field_count; |
2270 | uchar *res=result_field->ptr; |
2271 | |
2272 | double nr= args[0]->val_real(); /* sets null_value as side-effect */ |
2273 | |
2274 | if (args[0]->null_value) |
2275 | return; |
2276 | |
2277 | /* Serialize format is (double)m, (double)s, (longlong)count */ |
2278 | double field_recurrence_m, field_recurrence_s; |
2279 | float8get(field_recurrence_m, res); |
2280 | float8get(field_recurrence_s, res + sizeof(double)); |
2281 | field_count=sint8korr(res+sizeof(double)*2); |
2282 | |
2283 | variance_fp_recurrence_next(&field_recurrence_m, &field_recurrence_s, &field_count, nr); |
2284 | |
2285 | float8store(res, field_recurrence_m); |
2286 | float8store(res + sizeof(double), field_recurrence_s); |
2287 | res+= sizeof(double)*2; |
2288 | int8store(res,field_count); |
2289 | } |
2290 | |
2291 | |
2292 | Item *Item_sum_variance::result_item(THD *thd, Field *field) |
2293 | { |
2294 | return new (thd->mem_root) Item_variance_field(thd, this); |
2295 | } |
2296 | |
2297 | /* min & max */ |
2298 | |
2299 | void Item_sum_hybrid::clear() |
2300 | { |
2301 | DBUG_ENTER("Item_sum_hybrid::clear" ); |
2302 | value->clear(); |
2303 | null_value= 1; |
2304 | DBUG_VOID_RETURN; |
2305 | } |
2306 | |
2307 | |
2308 | bool |
2309 | Item_sum_hybrid::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) |
2310 | { |
2311 | DBUG_ASSERT(fixed == 1); |
2312 | if (null_value) |
2313 | return true; |
2314 | bool retval= value->get_date(ltime, fuzzydate); |
2315 | if ((null_value= value->null_value)) |
2316 | DBUG_ASSERT(retval == true); |
2317 | return retval; |
2318 | } |
2319 | |
2320 | |
2321 | void Item_sum_hybrid::direct_add(Item *item) |
2322 | { |
2323 | DBUG_ENTER("Item_sum_hybrid::direct_add" ); |
2324 | DBUG_PRINT("info" , ("item: %p" , item)); |
2325 | direct_added= TRUE; |
2326 | direct_item= item; |
2327 | DBUG_VOID_RETURN; |
2328 | } |
2329 | |
2330 | |
2331 | double Item_sum_hybrid::val_real() |
2332 | { |
2333 | DBUG_ENTER("Item_sum_hybrid::val_real" ); |
2334 | DBUG_ASSERT(fixed == 1); |
2335 | if (null_value) |
2336 | DBUG_RETURN(0.0); |
2337 | double retval= value->val_real(); |
2338 | if ((null_value= value->null_value)) |
2339 | DBUG_ASSERT(retval == 0.0); |
2340 | DBUG_RETURN(retval); |
2341 | } |
2342 | |
2343 | longlong Item_sum_hybrid::val_int() |
2344 | { |
2345 | DBUG_ENTER("Item_sum_hybrid::val_int" ); |
2346 | DBUG_ASSERT(fixed == 1); |
2347 | if (null_value) |
2348 | DBUG_RETURN(0); |
2349 | longlong retval= value->val_int(); |
2350 | if ((null_value= value->null_value)) |
2351 | DBUG_ASSERT(retval == 0); |
2352 | DBUG_RETURN(retval); |
2353 | } |
2354 | |
2355 | |
2356 | my_decimal *Item_sum_hybrid::val_decimal(my_decimal *val) |
2357 | { |
2358 | DBUG_ENTER("Item_sum_hybrid::val_decimal" ); |
2359 | DBUG_ASSERT(fixed == 1); |
2360 | if (null_value) |
2361 | DBUG_RETURN(0); |
2362 | my_decimal *retval= value->val_decimal(val); |
2363 | if ((null_value= value->null_value)) |
2364 | DBUG_ASSERT(retval == NULL); |
2365 | DBUG_RETURN(retval); |
2366 | } |
2367 | |
2368 | |
2369 | String * |
2370 | Item_sum_hybrid::val_str(String *str) |
2371 | { |
2372 | DBUG_ENTER("Item_sum_hybrid::val_str" ); |
2373 | DBUG_ASSERT(fixed == 1); |
2374 | if (null_value) |
2375 | DBUG_RETURN(0); |
2376 | String *retval= value->val_str(str); |
2377 | if ((null_value= value->null_value)) |
2378 | DBUG_ASSERT(retval == NULL); |
2379 | DBUG_RETURN(retval); |
2380 | } |
2381 | |
2382 | |
2383 | void Item_sum_hybrid::cleanup() |
2384 | { |
2385 | DBUG_ENTER("Item_sum_hybrid::cleanup" ); |
2386 | Item_sum::cleanup(); |
2387 | if (cmp) |
2388 | delete cmp; |
2389 | cmp= 0; |
2390 | /* |
2391 | by default it is TRUE to avoid TRUE reporting by |
2392 | Item_func_not_all/Item_func_nop_all if this item was never called. |
2393 | |
2394 | no_rows_in_result() set it to FALSE if was not results found. |
2395 | If some results found it will be left unchanged. |
2396 | */ |
2397 | was_values= TRUE; |
2398 | DBUG_VOID_RETURN; |
2399 | } |
2400 | |
2401 | void Item_sum_hybrid::no_rows_in_result() |
2402 | { |
2403 | DBUG_ENTER("Item_sum_hybrid::no_rows_in_result" ); |
2404 | /* We may be called here twice in case of ref field in function */ |
2405 | if (was_values) |
2406 | { |
2407 | was_values= FALSE; |
2408 | was_null_value= value->null_value; |
2409 | clear(); |
2410 | } |
2411 | DBUG_VOID_RETURN; |
2412 | } |
2413 | |
2414 | void Item_sum_hybrid::restore_to_before_no_rows_in_result() |
2415 | { |
2416 | if (!was_values) |
2417 | { |
2418 | was_values= TRUE; |
2419 | null_value= value->null_value= was_null_value; |
2420 | } |
2421 | } |
2422 | |
2423 | |
2424 | Item *Item_sum_min::copy_or_same(THD* thd) |
2425 | { |
2426 | DBUG_ENTER("Item_sum_min::copy_or_same" ); |
2427 | Item_sum_min *item= new (thd->mem_root) Item_sum_min(thd, this); |
2428 | item->setup_hybrid(thd, args[0], value); |
2429 | DBUG_RETURN(item); |
2430 | } |
2431 | |
2432 | |
2433 | bool Item_sum_min::add() |
2434 | { |
2435 | Item *UNINIT_VAR(tmp_item); |
2436 | DBUG_ENTER("Item_sum_min::add" ); |
2437 | DBUG_PRINT("enter" , ("this: %p" , this)); |
2438 | |
2439 | if (unlikely(direct_added)) |
2440 | { |
2441 | /* Change to use direct_item */ |
2442 | tmp_item= arg_cache->get_item(); |
2443 | arg_cache->store(direct_item); |
2444 | } |
2445 | DBUG_PRINT("info" , ("null_value: %s" , null_value ? "TRUE" : "FALSE" )); |
2446 | /* args[0] < value */ |
2447 | arg_cache->cache_value(); |
2448 | if (!arg_cache->null_value && |
2449 | (null_value || cmp->compare() < 0)) |
2450 | { |
2451 | value->store(arg_cache); |
2452 | value->cache_value(); |
2453 | null_value= 0; |
2454 | } |
2455 | if (unlikely(direct_added)) |
2456 | { |
2457 | /* Restore original item */ |
2458 | direct_added= FALSE; |
2459 | arg_cache->store(tmp_item); |
2460 | } |
2461 | DBUG_RETURN(0); |
2462 | } |
2463 | |
2464 | |
2465 | Item *Item_sum_max::copy_or_same(THD* thd) |
2466 | { |
2467 | Item_sum_max *item= new (thd->mem_root) Item_sum_max(thd, this); |
2468 | item->setup_hybrid(thd, args[0], value); |
2469 | return item; |
2470 | } |
2471 | |
2472 | |
2473 | bool Item_sum_max::add() |
2474 | { |
2475 | Item * UNINIT_VAR(tmp_item); |
2476 | DBUG_ENTER("Item_sum_max::add" ); |
2477 | DBUG_PRINT("enter" , ("this: %p" , this)); |
2478 | |
2479 | if (unlikely(direct_added)) |
2480 | { |
2481 | /* Change to use direct_item */ |
2482 | tmp_item= arg_cache->get_item(); |
2483 | arg_cache->store(direct_item); |
2484 | } |
2485 | /* args[0] > value */ |
2486 | arg_cache->cache_value(); |
2487 | DBUG_PRINT("info" , ("null_value: %s" , null_value ? "TRUE" : "FALSE" )); |
2488 | if (!arg_cache->null_value && |
2489 | (null_value || cmp->compare() > 0)) |
2490 | { |
2491 | value->store(arg_cache); |
2492 | value->cache_value(); |
2493 | null_value= 0; |
2494 | } |
2495 | if (unlikely(direct_added)) |
2496 | { |
2497 | /* Restore original item */ |
2498 | direct_added= FALSE; |
2499 | arg_cache->store(tmp_item); |
2500 | } |
2501 | DBUG_RETURN(0); |
2502 | } |
2503 | |
2504 | |
2505 | /* bit_or and bit_and */ |
2506 | |
2507 | longlong Item_sum_bit::val_int() |
2508 | { |
2509 | DBUG_ASSERT(fixed == 1); |
2510 | return (longlong) bits; |
2511 | } |
2512 | |
2513 | |
2514 | void Item_sum_bit::clear() |
2515 | { |
2516 | bits= reset_bits; |
2517 | if (as_window_function) |
2518 | clear_as_window(); |
2519 | } |
2520 | |
2521 | Item *Item_sum_or::copy_or_same(THD* thd) |
2522 | { |
2523 | return new (thd->mem_root) Item_sum_or(thd, this); |
2524 | } |
2525 | |
2526 | bool Item_sum_bit::clear_as_window() |
2527 | { |
2528 | memset(bit_counters, 0, sizeof(bit_counters)); |
2529 | num_values_added= 0; |
2530 | set_bits_from_counters(); |
2531 | return 0; |
2532 | } |
2533 | |
2534 | bool Item_sum_bit::remove_as_window(ulonglong value) |
2535 | { |
2536 | DBUG_ASSERT(as_window_function); |
2537 | if (num_values_added == 0) |
2538 | return 0; // Nothing to remove. |
2539 | |
2540 | for (int i= 0; i < NUM_BIT_COUNTERS; i++) |
2541 | { |
2542 | if (!bit_counters[i]) |
2543 | { |
2544 | // Don't attempt to remove values that were never added. |
2545 | DBUG_ASSERT((value & (1ULL << i)) == 0); |
2546 | continue; |
2547 | } |
2548 | bit_counters[i]-= (value & (1ULL << i)) ? 1 : 0; |
2549 | } |
2550 | |
2551 | // Prevent overflow; |
2552 | num_values_added = MY_MIN(num_values_added, num_values_added - 1); |
2553 | set_bits_from_counters(); |
2554 | return 0; |
2555 | } |
2556 | |
2557 | bool Item_sum_bit::add_as_window(ulonglong value) |
2558 | { |
2559 | DBUG_ASSERT(as_window_function); |
2560 | for (int i= 0; i < NUM_BIT_COUNTERS; i++) |
2561 | { |
2562 | bit_counters[i]+= (value & (1ULL << i)) ? 1 : 0; |
2563 | } |
2564 | // Prevent overflow; |
2565 | num_values_added = MY_MAX(num_values_added, num_values_added + 1); |
2566 | set_bits_from_counters(); |
2567 | return 0; |
2568 | } |
2569 | |
2570 | void Item_sum_or::set_bits_from_counters() |
2571 | { |
2572 | ulonglong value= 0; |
2573 | for (int i= 0; i < NUM_BIT_COUNTERS; i++) |
2574 | { |
2575 | value|= bit_counters[i] > 0 ? (1 << i) : 0; |
2576 | } |
2577 | bits= value | reset_bits; |
2578 | } |
2579 | |
2580 | bool Item_sum_or::add() |
2581 | { |
2582 | ulonglong value= (ulonglong) args[0]->val_int(); |
2583 | if (!args[0]->null_value) |
2584 | { |
2585 | if (as_window_function) |
2586 | return add_as_window(value); |
2587 | bits|=value; |
2588 | } |
2589 | return 0; |
2590 | } |
2591 | |
2592 | void Item_sum_xor::set_bits_from_counters() |
2593 | { |
2594 | ulonglong value= 0; |
2595 | for (int i= 0; i < NUM_BIT_COUNTERS; i++) |
2596 | { |
2597 | value|= (bit_counters[i] % 2) ? (1 << i) : 0; |
2598 | } |
2599 | bits= value ^ reset_bits; |
2600 | } |
2601 | |
2602 | Item *Item_sum_xor::copy_or_same(THD* thd) |
2603 | { |
2604 | return new (thd->mem_root) Item_sum_xor(thd, this); |
2605 | } |
2606 | |
2607 | |
2608 | bool Item_sum_xor::add() |
2609 | { |
2610 | ulonglong value= (ulonglong) args[0]->val_int(); |
2611 | if (!args[0]->null_value) |
2612 | { |
2613 | if (as_window_function) |
2614 | return add_as_window(value); |
2615 | bits^=value; |
2616 | } |
2617 | return 0; |
2618 | } |
2619 | |
2620 | void Item_sum_and::set_bits_from_counters() |
2621 | { |
2622 | ulonglong value= 0; |
2623 | if (!num_values_added) |
2624 | { |
2625 | bits= reset_bits; |
2626 | return; |
2627 | } |
2628 | |
2629 | for (int i= 0; i < NUM_BIT_COUNTERS; i++) |
2630 | { |
2631 | // We've only added values of 1 for this bit. |
2632 | if (bit_counters[i] == num_values_added) |
2633 | value|= (1ULL << i); |
2634 | } |
2635 | bits= value & reset_bits; |
2636 | } |
2637 | Item *Item_sum_and::copy_or_same(THD* thd) |
2638 | { |
2639 | return new (thd->mem_root) Item_sum_and(thd, this); |
2640 | } |
2641 | |
2642 | |
2643 | bool Item_sum_and::add() |
2644 | { |
2645 | ulonglong value= (ulonglong) args[0]->val_int(); |
2646 | if (!args[0]->null_value) |
2647 | { |
2648 | if (as_window_function) |
2649 | return add_as_window(value); |
2650 | bits&=value; |
2651 | } |
2652 | return 0; |
2653 | } |
2654 | |
2655 | /************************************************************************ |
2656 | ** reset result of a Item_sum with is saved in a tmp_table |
2657 | *************************************************************************/ |
2658 | |
2659 | void Item_sum_num::reset_field() |
2660 | { |
2661 | double nr= args[0]->val_real(); |
2662 | uchar *res=result_field->ptr; |
2663 | |
2664 | if (maybe_null) |
2665 | { |
2666 | if (args[0]->null_value) |
2667 | { |
2668 | nr=0.0; |
2669 | result_field->set_null(); |
2670 | } |
2671 | else |
2672 | result_field->set_notnull(); |
2673 | } |
2674 | float8store(res,nr); |
2675 | } |
2676 | |
2677 | |
2678 | void Item_sum_hybrid::reset_field() |
2679 | { |
2680 | Item *UNINIT_VAR(tmp_item), *arg0; |
2681 | DBUG_ENTER("Item_sum_hybrid::reset_field" ); |
2682 | |
2683 | arg0= args[0]; |
2684 | if (unlikely(direct_added)) |
2685 | { |
2686 | /* Switch to use direct item */ |
2687 | tmp_item= value->get_item(); |
2688 | value->store(direct_item); |
2689 | arg0= direct_item; |
2690 | } |
2691 | |
2692 | switch(result_type()) { |
2693 | case STRING_RESULT: |
2694 | { |
2695 | char buff[MAX_FIELD_WIDTH]; |
2696 | String tmp(buff,sizeof(buff),result_field->charset()),*res; |
2697 | |
2698 | res= arg0->val_str(&tmp); |
2699 | if (arg0->null_value) |
2700 | { |
2701 | result_field->set_null(); |
2702 | result_field->reset(); |
2703 | } |
2704 | else |
2705 | { |
2706 | result_field->set_notnull(); |
2707 | result_field->store(res->ptr(),res->length(),tmp.charset()); |
2708 | } |
2709 | break; |
2710 | } |
2711 | case INT_RESULT: |
2712 | { |
2713 | longlong nr= arg0->val_int(); |
2714 | |
2715 | if (maybe_null) |
2716 | { |
2717 | if (arg0->null_value) |
2718 | { |
2719 | nr=0; |
2720 | result_field->set_null(); |
2721 | } |
2722 | else |
2723 | result_field->set_notnull(); |
2724 | } |
2725 | DBUG_PRINT("info" , ("nr: %lld" , nr)); |
2726 | result_field->store(nr, unsigned_flag); |
2727 | break; |
2728 | } |
2729 | case REAL_RESULT: |
2730 | { |
2731 | double nr= arg0->val_real(); |
2732 | |
2733 | if (maybe_null) |
2734 | { |
2735 | if (arg0->null_value) |
2736 | { |
2737 | nr=0.0; |
2738 | result_field->set_null(); |
2739 | } |
2740 | else |
2741 | result_field->set_notnull(); |
2742 | } |
2743 | result_field->store(nr); |
2744 | break; |
2745 | } |
2746 | case DECIMAL_RESULT: |
2747 | { |
2748 | my_decimal value_buff, *arg_dec= arg0->val_decimal(&value_buff); |
2749 | |
2750 | if (maybe_null) |
2751 | { |
2752 | if (arg0->null_value) |
2753 | result_field->set_null(); |
2754 | else |
2755 | result_field->set_notnull(); |
2756 | } |
2757 | /* |
2758 | We must store zero in the field as we will use the field value in |
2759 | add() |
2760 | */ |
2761 | if (!arg_dec) // Null |
2762 | arg_dec= &decimal_zero; |
2763 | result_field->store_decimal(arg_dec); |
2764 | break; |
2765 | } |
2766 | case ROW_RESULT: |
2767 | case TIME_RESULT: |
2768 | DBUG_ASSERT(0); |
2769 | } |
2770 | |
2771 | if (unlikely(direct_added)) |
2772 | { |
2773 | direct_added= FALSE; |
2774 | value->store(tmp_item); |
2775 | } |
2776 | DBUG_VOID_RETURN; |
2777 | } |
2778 | |
2779 | |
2780 | void Item_sum_sum::reset_field() |
2781 | { |
2782 | my_bool null_flag; |
2783 | DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); |
2784 | if (result_type() == DECIMAL_RESULT) |
2785 | { |
2786 | my_decimal value, *arg_val; |
2787 | if (unlikely(direct_added)) |
2788 | arg_val= &direct_sum_decimal; |
2789 | else |
2790 | { |
2791 | if (!(arg_val= args[0]->val_decimal(&value))) |
2792 | arg_val= &decimal_zero; // Null |
2793 | } |
2794 | result_field->store_decimal(arg_val); |
2795 | } |
2796 | else |
2797 | { |
2798 | DBUG_ASSERT(result_type() == REAL_RESULT); |
2799 | double nr= likely(!direct_added) ? args[0]->val_real() : direct_sum_real; |
2800 | float8store(result_field->ptr, nr); |
2801 | } |
2802 | |
2803 | if (unlikely(direct_added)) |
2804 | { |
2805 | direct_added= FALSE; |
2806 | direct_reseted_field= TRUE; |
2807 | null_flag= direct_sum_is_null; |
2808 | } |
2809 | else |
2810 | null_flag= args[0]->null_value; |
2811 | |
2812 | if (null_flag) |
2813 | result_field->set_null(); |
2814 | else |
2815 | result_field->set_notnull(); |
2816 | } |
2817 | |
2818 | |
2819 | void Item_sum_count::reset_field() |
2820 | { |
2821 | DBUG_ENTER("Item_sum_count::reset_field" ); |
2822 | uchar *res=result_field->ptr; |
2823 | longlong nr=0; |
2824 | DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); |
2825 | |
2826 | if (unlikely(direct_counted)) |
2827 | { |
2828 | nr= direct_count; |
2829 | direct_counted= FALSE; |
2830 | direct_reseted_field= TRUE; |
2831 | } |
2832 | else if (!args[0]->maybe_null || !args[0]->is_null()) |
2833 | nr= 1; |
2834 | DBUG_PRINT("info" , ("nr: %lld" , nr)); |
2835 | int8store(res,nr); |
2836 | DBUG_VOID_RETURN; |
2837 | } |
2838 | |
2839 | |
2840 | void Item_sum_avg::reset_field() |
2841 | { |
2842 | uchar *res=result_field->ptr; |
2843 | DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); |
2844 | if (result_type() == DECIMAL_RESULT) |
2845 | { |
2846 | longlong tmp; |
2847 | my_decimal value, *arg_dec= args[0]->val_decimal(&value); |
2848 | if (args[0]->null_value) |
2849 | { |
2850 | arg_dec= &decimal_zero; |
2851 | tmp= 0; |
2852 | } |
2853 | else |
2854 | tmp= 1; |
2855 | my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec, res, f_precision, f_scale); |
2856 | res+= dec_bin_size; |
2857 | int8store(res, tmp); |
2858 | } |
2859 | else |
2860 | { |
2861 | double nr= args[0]->val_real(); |
2862 | |
2863 | if (args[0]->null_value) |
2864 | bzero(res,sizeof(double)+sizeof(longlong)); |
2865 | else |
2866 | { |
2867 | longlong tmp= 1; |
2868 | float8store(res,nr); |
2869 | res+=sizeof(double); |
2870 | int8store(res,tmp); |
2871 | } |
2872 | } |
2873 | } |
2874 | |
2875 | |
2876 | void Item_sum_bit::reset_field() |
2877 | { |
2878 | reset_and_add(); |
2879 | int8store(result_field->ptr, bits); |
2880 | } |
2881 | |
2882 | void Item_sum_bit::update_field() |
2883 | { |
2884 | // We never call update_field when computing the function as a window |
2885 | // function. Setting bits to a random value invalidates the bits counters and |
2886 | // the result of the bit function becomes erroneous. |
2887 | DBUG_ASSERT(!as_window_function); |
2888 | uchar *res=result_field->ptr; |
2889 | bits= uint8korr(res); |
2890 | add(); |
2891 | int8store(res, bits); |
2892 | } |
2893 | |
2894 | |
2895 | /** |
2896 | calc next value and merge it with field_value. |
2897 | */ |
2898 | |
2899 | void Item_sum_sum::update_field() |
2900 | { |
2901 | DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); |
2902 | if (result_type() == DECIMAL_RESULT) |
2903 | { |
2904 | my_decimal value, *arg_val; |
2905 | my_bool null_flag; |
2906 | if (unlikely(direct_added || direct_reseted_field)) |
2907 | { |
2908 | direct_added= direct_reseted_field= FALSE; |
2909 | arg_val= &direct_sum_decimal; |
2910 | null_flag= direct_sum_is_null; |
2911 | } |
2912 | else |
2913 | { |
2914 | arg_val= args[0]->val_decimal(&value); |
2915 | null_flag= args[0]->null_value; |
2916 | } |
2917 | |
2918 | if (!null_flag) |
2919 | { |
2920 | if (!result_field->is_null()) |
2921 | { |
2922 | my_decimal field_value; |
2923 | my_decimal *field_val= result_field->val_decimal(&field_value); |
2924 | my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, field_val); |
2925 | result_field->store_decimal(dec_buffs); |
2926 | } |
2927 | else |
2928 | { |
2929 | result_field->store_decimal(arg_val); |
2930 | result_field->set_notnull(); |
2931 | } |
2932 | } |
2933 | } |
2934 | else |
2935 | { |
2936 | double old_nr,nr; |
2937 | uchar *res= result_field->ptr; |
2938 | my_bool null_flag; |
2939 | |
2940 | float8get(old_nr,res); |
2941 | if (unlikely(direct_added || direct_reseted_field)) |
2942 | { |
2943 | direct_added= direct_reseted_field= FALSE; |
2944 | null_flag= direct_sum_is_null; |
2945 | nr= direct_sum_real; |
2946 | } |
2947 | else |
2948 | { |
2949 | nr= args[0]->val_real(); |
2950 | null_flag= args[0]->null_value; |
2951 | } |
2952 | if (!null_flag) |
2953 | { |
2954 | old_nr+=nr; |
2955 | result_field->set_notnull(); |
2956 | } |
2957 | float8store(res,old_nr); |
2958 | } |
2959 | } |
2960 | |
2961 | |
2962 | void Item_sum_count::update_field() |
2963 | { |
2964 | DBUG_ENTER("Item_sum_count::update_field" ); |
2965 | longlong nr; |
2966 | uchar *res=result_field->ptr; |
2967 | |
2968 | nr=sint8korr(res); |
2969 | if (unlikely(direct_counted || direct_reseted_field)) |
2970 | { |
2971 | direct_counted= direct_reseted_field= FALSE; |
2972 | nr+= direct_count; |
2973 | } |
2974 | else if (!args[0]->maybe_null || !args[0]->is_null()) |
2975 | nr++; |
2976 | DBUG_PRINT("info" , ("nr: %lld" , nr)); |
2977 | int8store(res,nr); |
2978 | DBUG_VOID_RETURN; |
2979 | } |
2980 | |
2981 | |
2982 | void Item_sum_avg::update_field() |
2983 | { |
2984 | longlong field_count; |
2985 | uchar *res=result_field->ptr; |
2986 | |
2987 | DBUG_ASSERT (aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); |
2988 | |
2989 | if (result_type() == DECIMAL_RESULT) |
2990 | { |
2991 | my_decimal value, *arg_val= args[0]->val_decimal(&value); |
2992 | if (!args[0]->null_value) |
2993 | { |
2994 | binary2my_decimal(E_DEC_FATAL_ERROR, res, |
2995 | dec_buffs + 1, f_precision, f_scale); |
2996 | field_count= sint8korr(res + dec_bin_size); |
2997 | my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, dec_buffs + 1); |
2998 | my_decimal2binary(E_DEC_FATAL_ERROR, dec_buffs, |
2999 | res, f_precision, f_scale); |
3000 | res+= dec_bin_size; |
3001 | field_count++; |
3002 | int8store(res, field_count); |
3003 | } |
3004 | } |
3005 | else |
3006 | { |
3007 | double nr; |
3008 | |
3009 | nr= args[0]->val_real(); |
3010 | if (!args[0]->null_value) |
3011 | { |
3012 | double old_nr; |
3013 | float8get(old_nr, res); |
3014 | field_count= sint8korr(res + sizeof(double)); |
3015 | old_nr+= nr; |
3016 | float8store(res,old_nr); |
3017 | res+= sizeof(double); |
3018 | field_count++; |
3019 | int8store(res, field_count); |
3020 | } |
3021 | } |
3022 | } |
3023 | |
3024 | |
3025 | Item *Item_sum_avg::result_item(THD *thd, Field *field) |
3026 | { |
3027 | return |
3028 | result_type() == DECIMAL_RESULT ? |
3029 | (Item_avg_field*) new (thd->mem_root) Item_avg_field_decimal(thd, this) : |
3030 | (Item_avg_field*) new (thd->mem_root) Item_avg_field_double(thd, this); |
3031 | } |
3032 | |
3033 | |
3034 | void Item_sum_hybrid::update_field() |
3035 | { |
3036 | DBUG_ENTER("Item_sum_hybrid::update_field" ); |
3037 | Item *UNINIT_VAR(tmp_item); |
3038 | if (unlikely(direct_added)) |
3039 | { |
3040 | tmp_item= args[0]; |
3041 | args[0]= direct_item; |
3042 | } |
3043 | switch (result_type()) { |
3044 | case STRING_RESULT: |
3045 | min_max_update_str_field(); |
3046 | break; |
3047 | case INT_RESULT: |
3048 | min_max_update_int_field(); |
3049 | break; |
3050 | case DECIMAL_RESULT: |
3051 | min_max_update_decimal_field(); |
3052 | break; |
3053 | default: |
3054 | min_max_update_real_field(); |
3055 | } |
3056 | if (unlikely(direct_added)) |
3057 | { |
3058 | direct_added= FALSE; |
3059 | args[0]= tmp_item; |
3060 | } |
3061 | DBUG_VOID_RETURN; |
3062 | } |
3063 | |
3064 | |
3065 | void |
3066 | Item_sum_hybrid::min_max_update_str_field() |
3067 | { |
3068 | DBUG_ENTER("Item_sum_hybrid::min_max_update_str_field" ); |
3069 | DBUG_ASSERT(cmp); |
3070 | String *res_str=args[0]->val_str(&cmp->value1); |
3071 | |
3072 | if (!args[0]->null_value) |
3073 | { |
3074 | result_field->val_str(&cmp->value2); |
3075 | |
3076 | if (result_field->is_null() || |
3077 | (cmp_sign * sortcmp(res_str,&cmp->value2,collation.collation)) < 0) |
3078 | result_field->store(res_str->ptr(),res_str->length(),res_str->charset()); |
3079 | result_field->set_notnull(); |
3080 | } |
3081 | DBUG_VOID_RETURN; |
3082 | } |
3083 | |
3084 | |
3085 | void |
3086 | Item_sum_hybrid::min_max_update_real_field() |
3087 | { |
3088 | double nr,old_nr; |
3089 | |
3090 | DBUG_ENTER("Item_sum_hybrid::min_max_update_real_field" ); |
3091 | old_nr=result_field->val_real(); |
3092 | nr= args[0]->val_real(); |
3093 | if (!args[0]->null_value) |
3094 | { |
3095 | if (result_field->is_null(0) || |
3096 | (cmp_sign > 0 ? old_nr > nr : old_nr < nr)) |
3097 | old_nr=nr; |
3098 | result_field->set_notnull(); |
3099 | } |
3100 | else if (result_field->is_null(0)) |
3101 | result_field->set_null(); |
3102 | result_field->store(old_nr); |
3103 | DBUG_VOID_RETURN; |
3104 | } |
3105 | |
3106 | |
3107 | void |
3108 | Item_sum_hybrid::min_max_update_int_field() |
3109 | { |
3110 | longlong nr,old_nr; |
3111 | |
3112 | DBUG_ENTER("Item_sum_hybrid::min_max_update_int_field" ); |
3113 | old_nr=result_field->val_int(); |
3114 | nr=args[0]->val_int(); |
3115 | if (!args[0]->null_value) |
3116 | { |
3117 | if (result_field->is_null(0)) |
3118 | old_nr=nr; |
3119 | else |
3120 | { |
3121 | bool res=(unsigned_flag ? |
3122 | (ulonglong) old_nr > (ulonglong) nr : |
3123 | old_nr > nr); |
3124 | /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */ |
3125 | if ((cmp_sign > 0) ^ (!res)) |
3126 | old_nr=nr; |
3127 | } |
3128 | result_field->set_notnull(); |
3129 | } |
3130 | else if (result_field->is_null(0)) |
3131 | result_field->set_null(); |
3132 | DBUG_PRINT("info" , ("nr: %lld" , old_nr)); |
3133 | result_field->store(old_nr, unsigned_flag); |
3134 | DBUG_VOID_RETURN; |
3135 | } |
3136 | |
3137 | |
3138 | /** |
3139 | @todo |
3140 | optimize: do not get result_field in case of args[0] is NULL |
3141 | */ |
3142 | void |
3143 | Item_sum_hybrid::min_max_update_decimal_field() |
3144 | { |
3145 | DBUG_ENTER("Item_sum_hybrid::min_max_update_decimal_field" ); |
3146 | my_decimal old_val, nr_val; |
3147 | const my_decimal *old_nr; |
3148 | const my_decimal *nr= args[0]->val_decimal(&nr_val); |
3149 | if (!args[0]->null_value) |
3150 | { |
3151 | if (result_field->is_null(0)) |
3152 | old_nr=nr; |
3153 | else |
3154 | { |
3155 | old_nr= result_field->val_decimal(&old_val); |
3156 | bool res= my_decimal_cmp(old_nr, nr) > 0; |
3157 | /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */ |
3158 | if ((cmp_sign > 0) ^ (!res)) |
3159 | old_nr=nr; |
3160 | } |
3161 | result_field->set_notnull(); |
3162 | result_field->store_decimal(old_nr); |
3163 | } |
3164 | else if (result_field->is_null(0)) |
3165 | result_field->set_null(); |
3166 | DBUG_VOID_RETURN; |
3167 | } |
3168 | |
3169 | |
3170 | double Item_avg_field_double::val_real() |
3171 | { |
3172 | // fix_fields() never calls for this Item |
3173 | double nr; |
3174 | longlong count; |
3175 | uchar *res; |
3176 | |
3177 | float8get(nr,field->ptr); |
3178 | res= (field->ptr+sizeof(double)); |
3179 | count= sint8korr(res); |
3180 | |
3181 | if ((null_value= !count)) |
3182 | return 0.0; |
3183 | return nr/(double) count; |
3184 | } |
3185 | |
3186 | |
3187 | my_decimal *Item_avg_field_decimal::val_decimal(my_decimal *dec_buf) |
3188 | { |
3189 | // fix_fields() never calls for this Item |
3190 | longlong count= sint8korr(field->ptr + dec_bin_size); |
3191 | if ((null_value= !count)) |
3192 | return 0; |
3193 | |
3194 | my_decimal dec_count, dec_field; |
3195 | binary2my_decimal(E_DEC_FATAL_ERROR, |
3196 | field->ptr, &dec_field, f_precision, f_scale); |
3197 | int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count); |
3198 | my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, |
3199 | &dec_field, &dec_count, prec_increment); |
3200 | return dec_buf; |
3201 | } |
3202 | |
3203 | |
3204 | double Item_std_field::val_real() |
3205 | { |
3206 | double nr; |
3207 | // fix_fields() never calls for this Item |
3208 | nr= Item_variance_field::val_real(); |
3209 | DBUG_ASSERT(nr >= 0.0); |
3210 | return sqrt(nr); |
3211 | } |
3212 | |
3213 | |
3214 | double Item_variance_field::val_real() |
3215 | { |
3216 | // fix_fields() never calls for this Item |
3217 | double recurrence_s; |
3218 | ulonglong count; |
3219 | float8get(recurrence_s, (field->ptr + sizeof(double))); |
3220 | count=sint8korr(field->ptr+sizeof(double)*2); |
3221 | |
3222 | if ((null_value= (count <= sample))) |
3223 | return 0.0; |
3224 | |
3225 | return variance_fp_recurrence_result(recurrence_s, count, sample); |
3226 | } |
3227 | |
3228 | |
3229 | /**************************************************************************** |
3230 | ** Functions to handle dynamic loadable aggregates |
3231 | ** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su> |
3232 | ** Adapted for UDAs by: Andreas F. Bobak <bobak@relog.ch>. |
3233 | ** Rewritten by: Monty. |
3234 | ****************************************************************************/ |
3235 | |
3236 | #ifdef HAVE_DLOPEN |
3237 | |
3238 | void Item_udf_sum::clear() |
3239 | { |
3240 | DBUG_ENTER("Item_udf_sum::clear" ); |
3241 | udf.clear(); |
3242 | DBUG_VOID_RETURN; |
3243 | } |
3244 | |
3245 | bool Item_udf_sum::add() |
3246 | { |
3247 | my_bool tmp_null_value; |
3248 | DBUG_ENTER("Item_udf_sum::add" ); |
3249 | udf.add(&tmp_null_value); |
3250 | null_value= tmp_null_value; |
3251 | DBUG_RETURN(0); |
3252 | } |
3253 | |
3254 | void Item_udf_sum::cleanup() |
3255 | { |
3256 | /* |
3257 | udf_handler::cleanup() nicely handles case when we have not |
3258 | original item but one created by copy_or_same() method. |
3259 | */ |
3260 | udf.cleanup(); |
3261 | Item_sum::cleanup(); |
3262 | } |
3263 | |
3264 | |
3265 | void Item_udf_sum::print(String *str, enum_query_type query_type) |
3266 | { |
3267 | str->append(func_name()); |
3268 | str->append('('); |
3269 | for (uint i=0 ; i < arg_count ; i++) |
3270 | { |
3271 | if (i) |
3272 | str->append(','); |
3273 | args[i]->print(str, query_type); |
3274 | } |
3275 | str->append(')'); |
3276 | } |
3277 | |
3278 | |
3279 | Item *Item_sum_udf_float::copy_or_same(THD* thd) |
3280 | { |
3281 | return new (thd->mem_root) Item_sum_udf_float(thd, this); |
3282 | } |
3283 | |
3284 | double Item_sum_udf_float::val_real() |
3285 | { |
3286 | my_bool tmp_null_value; |
3287 | double res; |
3288 | DBUG_ASSERT(fixed == 1); |
3289 | DBUG_ENTER("Item_sum_udf_float::val" ); |
3290 | DBUG_PRINT("enter" ,("result_type: %d arg_count: %d" , |
3291 | args[0]->result_type(), arg_count)); |
3292 | res= udf.val(&tmp_null_value); |
3293 | null_value= tmp_null_value; |
3294 | DBUG_RETURN(res); |
3295 | } |
3296 | |
3297 | |
3298 | String *Item_sum_udf_float::val_str(String *str) |
3299 | { |
3300 | return val_string_from_real(str); |
3301 | } |
3302 | |
3303 | |
3304 | my_decimal *Item_sum_udf_float::val_decimal(my_decimal *dec) |
3305 | { |
3306 | return val_decimal_from_real(dec); |
3307 | } |
3308 | |
3309 | |
3310 | String *Item_sum_udf_decimal::val_str(String *str) |
3311 | { |
3312 | return val_string_from_decimal(str); |
3313 | } |
3314 | |
3315 | |
3316 | double Item_sum_udf_decimal::val_real() |
3317 | { |
3318 | return val_real_from_decimal(); |
3319 | } |
3320 | |
3321 | |
3322 | longlong Item_sum_udf_decimal::val_int() |
3323 | { |
3324 | return val_int_from_decimal(); |
3325 | } |
3326 | |
3327 | |
3328 | my_decimal *Item_sum_udf_decimal::val_decimal(my_decimal *dec_buf) |
3329 | { |
3330 | my_decimal *res; |
3331 | my_bool tmp_null_value; |
3332 | DBUG_ASSERT(fixed == 1); |
3333 | DBUG_ENTER("Item_func_udf_decimal::val_decimal" ); |
3334 | DBUG_PRINT("enter" ,("result_type: %d arg_count: %d" , |
3335 | args[0]->result_type(), arg_count)); |
3336 | |
3337 | res= udf.val_decimal(&tmp_null_value, dec_buf); |
3338 | null_value= tmp_null_value; |
3339 | DBUG_RETURN(res); |
3340 | } |
3341 | |
3342 | |
3343 | Item *Item_sum_udf_decimal::copy_or_same(THD* thd) |
3344 | { |
3345 | return new (thd->mem_root) Item_sum_udf_decimal(thd, this); |
3346 | } |
3347 | |
3348 | |
3349 | Item *Item_sum_udf_int::copy_or_same(THD* thd) |
3350 | { |
3351 | return new (thd->mem_root) Item_sum_udf_int(thd, this); |
3352 | } |
3353 | |
3354 | longlong Item_sum_udf_int::val_int() |
3355 | { |
3356 | my_bool tmp_null_value; |
3357 | longlong res; |
3358 | DBUG_ASSERT(fixed == 1); |
3359 | DBUG_ENTER("Item_sum_udf_int::val_int" ); |
3360 | DBUG_PRINT("enter" ,("result_type: %d arg_count: %d" , |
3361 | args[0]->result_type(), arg_count)); |
3362 | res= udf.val_int(&tmp_null_value); |
3363 | null_value= tmp_null_value; |
3364 | DBUG_RETURN(res); |
3365 | } |
3366 | |
3367 | |
3368 | String *Item_sum_udf_int::val_str(String *str) |
3369 | { |
3370 | return val_string_from_int(str); |
3371 | } |
3372 | |
3373 | my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec) |
3374 | { |
3375 | return val_decimal_from_int(dec); |
3376 | } |
3377 | |
3378 | |
3379 | /** Default max_length is max argument length. */ |
3380 | |
3381 | void Item_sum_udf_str::fix_length_and_dec() |
3382 | { |
3383 | DBUG_ENTER("Item_sum_udf_str::fix_length_and_dec" ); |
3384 | max_length=0; |
3385 | for (uint i = 0; i < arg_count; i++) |
3386 | set_if_bigger(max_length,args[i]->max_length); |
3387 | DBUG_VOID_RETURN; |
3388 | } |
3389 | |
3390 | |
3391 | Item *Item_sum_udf_str::copy_or_same(THD* thd) |
3392 | { |
3393 | return new (thd->mem_root) Item_sum_udf_str(thd, this); |
3394 | } |
3395 | |
3396 | |
3397 | my_decimal *Item_sum_udf_str::val_decimal(my_decimal *dec) |
3398 | { |
3399 | return val_decimal_from_string(dec); |
3400 | } |
3401 | |
3402 | String *Item_sum_udf_str::val_str(String *str) |
3403 | { |
3404 | DBUG_ASSERT(fixed == 1); |
3405 | DBUG_ENTER("Item_sum_udf_str::str" ); |
3406 | String *res=udf.val_str(str,&str_value); |
3407 | null_value = !res; |
3408 | DBUG_RETURN(res); |
3409 | } |
3410 | |
3411 | #endif /* HAVE_DLOPEN */ |
3412 | |
3413 | |
3414 | /***************************************************************************** |
3415 | GROUP_CONCAT function |
3416 | |
3417 | SQL SYNTAX: |
3418 | GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...] |
3419 | [SEPARATOR str_const]) |
3420 | |
3421 | concat of values from "group by" operation |
3422 | |
3423 | BUGS |
3424 | Blobs doesn't work with DISTINCT or ORDER BY |
3425 | *****************************************************************************/ |
3426 | |
3427 | |
3428 | |
3429 | /** |
3430 | Compares the values for fields in expr list of GROUP_CONCAT. |
3431 | @note |
3432 | |
3433 | GROUP_CONCAT([DISTINCT] expr [,expr ...] |
3434 | [ORDER BY {unsigned_integer | col_name | expr} |
3435 | [ASC | DESC] [,col_name ...]] |
3436 | [SEPARATOR str_val]) |
3437 | |
3438 | @return |
3439 | @retval -1 : key1 < key2 |
3440 | @retval 0 : key1 = key2 |
3441 | @retval 1 : key1 > key2 |
3442 | */ |
3443 | |
3444 | extern "C" |
3445 | int group_concat_key_cmp_with_distinct(void* arg, const void* key1, |
3446 | const void* key2) |
3447 | { |
3448 | Item_func_group_concat *item_func= (Item_func_group_concat*)arg; |
3449 | |
3450 | for (uint i= 0; i < item_func->arg_count_field; i++) |
3451 | { |
3452 | Item *item= item_func->args[i]; |
3453 | /* |
3454 | If item is a const item then either get_tmp_table_field returns 0 |
3455 | or it is an item over a const table. |
3456 | */ |
3457 | if (item->const_item()) |
3458 | continue; |
3459 | /* |
3460 | We have to use get_tmp_table_field() instead of |
3461 | real_item()->get_tmp_table_field() because we want the field in |
3462 | the temporary table, not the original field |
3463 | */ |
3464 | Field *field= item->get_tmp_table_field(); |
3465 | |
3466 | if (!field) |
3467 | continue; |
3468 | |
3469 | uint offset= (field->offset(field->table->record[0]) - |
3470 | field->table->s->null_bytes); |
3471 | int res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset); |
3472 | if (res) |
3473 | return res; |
3474 | } |
3475 | return 0; |
3476 | } |
3477 | |
3478 | |
3479 | /** |
3480 | function of sort for syntax: GROUP_CONCAT(expr,... ORDER BY col,... ) |
3481 | */ |
3482 | |
3483 | extern "C" |
3484 | int group_concat_key_cmp_with_order(void* arg, const void* key1, |
3485 | const void* key2) |
3486 | { |
3487 | Item_func_group_concat* grp_item= (Item_func_group_concat*) arg; |
3488 | ORDER **order_item, **end; |
3489 | |
3490 | for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order; |
3491 | order_item < end; |
3492 | order_item++) |
3493 | { |
3494 | Item *item= *(*order_item)->item; |
3495 | /* |
3496 | If field_item is a const item then either get_tmp_table_field returns 0 |
3497 | or it is an item over a const table. |
3498 | */ |
3499 | if (item->const_item()) |
3500 | continue; |
3501 | /* |
3502 | If item is a const item then either get_tmp_table_field returns 0 |
3503 | or it is an item over a const table. |
3504 | */ |
3505 | if (item->const_item()) |
3506 | continue; |
3507 | /* |
3508 | We have to use get_tmp_table_field() instead of |
3509 | real_item()->get_tmp_table_field() because we want the field in |
3510 | the temporary table, not the original field |
3511 | |
3512 | Note that for the case of ROLLUP, field may point to another table |
3513 | tham grp_item->table. This is however ok as the table definitions are |
3514 | the same. |
3515 | */ |
3516 | Field *field= item->get_tmp_table_field(); |
3517 | if (!field) |
3518 | continue; |
3519 | |
3520 | uint offset= (field->offset(field->table->record[0]) - |
3521 | field->table->s->null_bytes); |
3522 | int res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset); |
3523 | if (res) |
3524 | return ((*order_item)->direction == ORDER::ORDER_ASC) ? res : -res; |
3525 | } |
3526 | /* |
3527 | We can't return 0 because in that case the tree class would remove this |
3528 | item as double value. This would cause problems for case-changes and |
3529 | if the returned values are not the same we do the sort on. |
3530 | */ |
3531 | return 1; |
3532 | } |
3533 | |
3534 | |
3535 | /** |
3536 | Append data from current leaf to item->result. |
3537 | */ |
3538 | |
3539 | extern "C" |
3540 | int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)), |
3541 | void* item_arg) |
3542 | { |
3543 | Item_func_group_concat *item= (Item_func_group_concat *) item_arg; |
3544 | TABLE *table= item->table; |
3545 | uint max_length= (uint)table->in_use->variables.group_concat_max_len; |
3546 | String tmp((char *)table->record[1], table->s->reclength, |
3547 | default_charset_info); |
3548 | String tmp2; |
3549 | uchar *key= (uchar *) key_arg; |
3550 | String *result= &item->result; |
3551 | Item **arg= item->args, **arg_end= item->args + item->arg_count_field; |
3552 | uint old_length= result->length(); |
3553 | |
3554 | ulonglong *offset_limit= &item->copy_offset_limit; |
3555 | ulonglong *row_limit = &item->copy_row_limit; |
3556 | if (item->limit_clause && !(*row_limit)) |
3557 | return 1; |
3558 | |
3559 | if (item->no_appended) |
3560 | item->no_appended= FALSE; |
3561 | else |
3562 | result->append(*item->separator); |
3563 | |
3564 | tmp.length(0); |
3565 | |
3566 | if (item->limit_clause && (*offset_limit)) |
3567 | { |
3568 | item->row_count++; |
3569 | item->no_appended= TRUE; |
3570 | (*offset_limit)--; |
3571 | return 0; |
3572 | } |
3573 | |
3574 | for (; arg < arg_end; arg++) |
3575 | { |
3576 | String *res; |
3577 | /* |
3578 | We have to use get_tmp_table_field() instead of |
3579 | real_item()->get_tmp_table_field() because we want the field in |
3580 | the temporary table, not the original field |
3581 | We also can't use table->field array to access the fields |
3582 | because it contains both order and arg list fields. |
3583 | */ |
3584 | if ((*arg)->const_item()) |
3585 | res= (*arg)->val_str(&tmp); |
3586 | else |
3587 | { |
3588 | Field *field= (*arg)->get_tmp_table_field(); |
3589 | if (field) |
3590 | { |
3591 | uint offset= (field->offset(field->table->record[0]) - |
3592 | table->s->null_bytes); |
3593 | DBUG_ASSERT(offset < table->s->reclength); |
3594 | res= field->val_str(&tmp, key + offset); |
3595 | } |
3596 | else |
3597 | res= (*arg)->val_str(&tmp); |
3598 | } |
3599 | if (res) |
3600 | result->append(*res); |
3601 | } |
3602 | |
3603 | if (item->limit_clause) |
3604 | (*row_limit)--; |
3605 | item->row_count++; |
3606 | |
3607 | /* stop if length of result more than max_length */ |
3608 | if (result->length() > max_length) |
3609 | { |
3610 | CHARSET_INFO *cs= item->collation.collation; |
3611 | const char *ptr= result->ptr(); |
3612 | THD *thd= current_thd; |
3613 | /* |
3614 | It's ok to use item->result.length() as the fourth argument |
3615 | as this is never used to limit the length of the data. |
3616 | Cut is done with the third argument. |
3617 | */ |
3618 | size_t add_length= Well_formed_prefix(cs, |
3619 | ptr + old_length, |
3620 | ptr + max_length, |
3621 | result->length()).length(); |
3622 | result->length(old_length + add_length); |
3623 | item->warning_for_row= TRUE; |
3624 | push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, |
3625 | ER_CUT_VALUE_GROUP_CONCAT, |
3626 | ER_THD(thd, ER_CUT_VALUE_GROUP_CONCAT), |
3627 | item->row_count); |
3628 | |
3629 | /** |
3630 | To avoid duplicated warnings in Item_func_group_concat::val_str() |
3631 | */ |
3632 | if (table && table->blob_storage) |
3633 | table->blob_storage->set_truncated_value(false); |
3634 | return 1; |
3635 | } |
3636 | return 0; |
3637 | } |
3638 | |
3639 | |
3640 | /** |
3641 | Constructor of Item_func_group_concat. |
3642 | |
3643 | @param distinct_arg distinct |
3644 | @param select_list list of expression for show values |
3645 | @param order_list list of sort columns |
3646 | @param separator_arg string value of separator. |
3647 | */ |
3648 | |
3649 | Item_func_group_concat:: |
3650 | Item_func_group_concat(THD *thd, Name_resolution_context *context_arg, |
3651 | bool distinct_arg, List<Item> *select_list, |
3652 | const SQL_I_List<ORDER> &order_list, |
3653 | String *separator_arg, bool limit_clause, |
3654 | Item *row_limit_arg, Item *offset_limit_arg) |
3655 | :Item_sum(thd), tmp_table_param(0), separator(separator_arg), tree(0), |
3656 | unique_filter(NULL), table(0), |
3657 | order(0), context(context_arg), |
3658 | arg_count_order(order_list.elements), |
3659 | arg_count_field(select_list->elements), |
3660 | row_count(0), |
3661 | distinct(distinct_arg), |
3662 | warning_for_row(FALSE), |
3663 | force_copy_fields(0), row_limit(NULL), |
3664 | offset_limit(NULL), limit_clause(limit_clause), |
3665 | copy_offset_limit(0), copy_row_limit(0), original(0) |
3666 | { |
3667 | Item *item_select; |
3668 | Item **arg_ptr; |
3669 | |
3670 | quick_group= FALSE; |
3671 | arg_count= arg_count_field + arg_count_order; |
3672 | |
3673 | /* |
3674 | We need to allocate: |
3675 | args - arg_count_field+arg_count_order |
3676 | (for possible order items in temporary tables) |
3677 | order - arg_count_order |
3678 | */ |
3679 | if (!(args= (Item**) thd->alloc(sizeof(Item*) * arg_count * 2 + |
3680 | sizeof(ORDER*)*arg_count_order))) |
3681 | return; |
3682 | |
3683 | order= (ORDER**)(args + arg_count); |
3684 | |
3685 | /* fill args items of show and sort */ |
3686 | List_iterator_fast<Item> li(*select_list); |
3687 | |
3688 | for (arg_ptr=args ; (item_select= li++) ; arg_ptr++) |
3689 | *arg_ptr= item_select; |
3690 | |
3691 | if (arg_count_order) |
3692 | { |
3693 | ORDER **order_ptr= order; |
3694 | for (ORDER *order_item= order_list.first; |
3695 | order_item != NULL; |
3696 | order_item= order_item->next) |
3697 | { |
3698 | (*order_ptr++)= order_item; |
3699 | *arg_ptr= *order_item->item; |
3700 | order_item->item= arg_ptr++; |
3701 | } |
3702 | } |
3703 | |
3704 | /* orig_args is only used for print() */ |
3705 | orig_args= (Item**) (order + arg_count_order); |
3706 | memcpy(orig_args, args, sizeof(Item*) * arg_count); |
3707 | if (limit_clause) |
3708 | { |
3709 | row_limit= row_limit_arg; |
3710 | offset_limit= offset_limit_arg; |
3711 | } |
3712 | } |
3713 | |
3714 | |
3715 | Item_func_group_concat::Item_func_group_concat(THD *thd, |
3716 | Item_func_group_concat *item) |
3717 | :Item_sum(thd, item), |
3718 | tmp_table_param(item->tmp_table_param), |
3719 | separator(item->separator), |
3720 | tree(item->tree), |
3721 | unique_filter(item->unique_filter), |
3722 | table(item->table), |
3723 | context(item->context), |
3724 | arg_count_order(item->arg_count_order), |
3725 | arg_count_field(item->arg_count_field), |
3726 | row_count(item->row_count), |
3727 | distinct(item->distinct), |
3728 | warning_for_row(item->warning_for_row), |
3729 | always_null(item->always_null), |
3730 | force_copy_fields(item->force_copy_fields), |
3731 | row_limit(item->row_limit), offset_limit(item->offset_limit), |
3732 | limit_clause(item->limit_clause),copy_offset_limit(item->copy_offset_limit), |
3733 | copy_row_limit(item->copy_row_limit), original(item) |
3734 | { |
3735 | quick_group= item->quick_group; |
3736 | result.set_charset(collation.collation); |
3737 | |
3738 | /* |
3739 | Since the ORDER structures pointed to by the elements of the 'order' array |
3740 | may be modified in find_order_in_list() called from |
3741 | Item_func_group_concat::setup(), create a copy of those structures so that |
3742 | such modifications done in this object would not have any effect on the |
3743 | object being copied. |
3744 | */ |
3745 | ORDER *tmp; |
3746 | if (!(tmp= (ORDER *) thd->alloc(sizeof(ORDER *) * arg_count_order + |
3747 | sizeof(ORDER) * arg_count_order))) |
3748 | return; |
3749 | order= (ORDER **)(tmp + arg_count_order); |
3750 | for (uint i= 0; i < arg_count_order; i++, tmp++) |
3751 | { |
3752 | /* |
3753 | Compiler generated copy constructor is used to |
3754 | to copy all the members of ORDER struct. |
3755 | It's also necessary to update ORDER::next pointer |
3756 | so that it points to new ORDER element. |
3757 | */ |
3758 | new (tmp) st_order(*(item->order[i])); |
3759 | tmp->next= (i + 1 == arg_count_order) ? NULL : (tmp + 1); |
3760 | order[i]= tmp; |
3761 | } |
3762 | } |
3763 | |
3764 | |
3765 | void Item_func_group_concat::cleanup() |
3766 | { |
3767 | DBUG_ENTER("Item_func_group_concat::cleanup" ); |
3768 | Item_sum::cleanup(); |
3769 | |
3770 | /* |
3771 | Free table and tree if they belong to this item (if item have not pointer |
3772 | to original item from which was made copy => it own its objects ) |
3773 | */ |
3774 | if (!original) |
3775 | { |
3776 | delete tmp_table_param; |
3777 | tmp_table_param= 0; |
3778 | if (table) |
3779 | { |
3780 | THD *thd= table->in_use; |
3781 | if (table->blob_storage) |
3782 | delete table->blob_storage; |
3783 | free_tmp_table(thd, table); |
3784 | table= 0; |
3785 | if (tree) |
3786 | { |
3787 | delete_tree(tree, 0); |
3788 | tree= 0; |
3789 | } |
3790 | if (unique_filter) |
3791 | { |
3792 | delete unique_filter; |
3793 | unique_filter= NULL; |
3794 | } |
3795 | } |
3796 | DBUG_ASSERT(tree == 0); |
3797 | } |
3798 | /* |
3799 | As the ORDER structures pointed to by the elements of the |
3800 | 'order' array may be modified in find_order_in_list() called |
3801 | from Item_func_group_concat::setup() to point to runtime |
3802 | created objects, we need to reset them back to the original |
3803 | arguments of the function. |
3804 | */ |
3805 | ORDER **order_ptr= order; |
3806 | for (uint i= 0; i < arg_count_order; i++) |
3807 | { |
3808 | (*order_ptr)->item= &args[arg_count_field + i]; |
3809 | order_ptr++; |
3810 | } |
3811 | DBUG_VOID_RETURN; |
3812 | } |
3813 | |
3814 | |
3815 | Item *Item_func_group_concat::copy_or_same(THD* thd) |
3816 | { |
3817 | return new (thd->mem_root) Item_func_group_concat(thd, this); |
3818 | } |
3819 | |
3820 | |
3821 | void Item_func_group_concat::clear() |
3822 | { |
3823 | result.length(0); |
3824 | result.copy(); |
3825 | null_value= TRUE; |
3826 | warning_for_row= FALSE; |
3827 | no_appended= TRUE; |
3828 | if (offset_limit) |
3829 | copy_offset_limit= offset_limit->val_int(); |
3830 | if (row_limit) |
3831 | copy_row_limit= row_limit->val_int(); |
3832 | if (tree) |
3833 | reset_tree(tree); |
3834 | if (unique_filter) |
3835 | unique_filter->reset(); |
3836 | if (table && table->blob_storage) |
3837 | table->blob_storage->reset(); |
3838 | /* No need to reset the table as we never call write_row */ |
3839 | } |
3840 | |
3841 | |
3842 | bool Item_func_group_concat::add() |
3843 | { |
3844 | if (always_null) |
3845 | return 0; |
3846 | copy_fields(tmp_table_param); |
3847 | if (copy_funcs(tmp_table_param->items_to_copy, table->in_use)) |
3848 | return TRUE; |
3849 | |
3850 | for (uint i= 0; i < arg_count_field; i++) |
3851 | { |
3852 | Item *show_item= args[i]; |
3853 | if (show_item->const_item()) |
3854 | continue; |
3855 | |
3856 | Field *field= show_item->get_tmp_table_field(); |
3857 | if (field && field->is_null_in_record((const uchar*) table->record[0])) |
3858 | return 0; // Skip row if it contains null |
3859 | } |
3860 | |
3861 | null_value= FALSE; |
3862 | bool row_eligible= TRUE; |
3863 | |
3864 | if (distinct) |
3865 | { |
3866 | /* Filter out duplicate rows. */ |
3867 | uint count= unique_filter->elements_in_tree(); |
3868 | unique_filter->unique_add(table->record[0] + table->s->null_bytes); |
3869 | if (count == unique_filter->elements_in_tree()) |
3870 | row_eligible= FALSE; |
3871 | } |
3872 | |
3873 | TREE_ELEMENT *el= 0; // Only for safety |
3874 | if (row_eligible && tree) |
3875 | { |
3876 | el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0, |
3877 | tree->custom_arg); |
3878 | /* check if there was enough memory to insert the row */ |
3879 | if (!el) |
3880 | return 1; |
3881 | } |
3882 | /* |
3883 | If the row is not a duplicate (el->count == 1) |
3884 | we can dump the row here in case of GROUP_CONCAT(DISTINCT...) |
3885 | instead of doing tree traverse later. |
3886 | */ |
3887 | if (row_eligible && !warning_for_row && |
3888 | (!tree || (el->count == 1 && distinct && !arg_count_order))) |
3889 | dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this); |
3890 | |
3891 | return 0; |
3892 | } |
3893 | |
3894 | |
3895 | bool |
3896 | Item_func_group_concat::fix_fields(THD *thd, Item **ref) |
3897 | { |
3898 | uint i; /* for loop variable */ |
3899 | DBUG_ASSERT(fixed == 0); |
3900 | |
3901 | if (init_sum_func_check(thd)) |
3902 | return TRUE; |
3903 | |
3904 | maybe_null= 1; |
3905 | |
3906 | /* |
3907 | Fix fields for select list and ORDER clause |
3908 | */ |
3909 | |
3910 | for (i=0 ; i < arg_count ; i++) |
3911 | { |
3912 | if ((!args[i]->fixed && |
3913 | args[i]->fix_fields(thd, args + i)) || |
3914 | args[i]->check_cols(1)) |
3915 | return TRUE; |
3916 | m_with_subquery|= args[i]->with_subquery(); |
3917 | with_param|= args[i]->with_param; |
3918 | with_window_func|= args[i]->with_window_func; |
3919 | } |
3920 | |
3921 | /* skip charset aggregation for order columns */ |
3922 | if (agg_arg_charsets_for_string_result(collation, |
3923 | args, arg_count - arg_count_order)) |
3924 | return 1; |
3925 | |
3926 | result.set_charset(collation.collation); |
3927 | result_field= 0; |
3928 | null_value= 1; |
3929 | max_length= (uint32)(thd->variables.group_concat_max_len |
3930 | / collation.collation->mbminlen |
3931 | * collation.collation->mbmaxlen); |
3932 | |
3933 | uint32 offset; |
3934 | if (separator->needs_conversion(separator->length(), separator->charset(), |
3935 | collation.collation, &offset)) |
3936 | { |
3937 | uint32 buflen= collation.collation->mbmaxlen * separator->length(); |
3938 | uint errors, conv_length; |
3939 | char *buf; |
3940 | String *new_separator; |
3941 | |
3942 | if (!(buf= (char*) thd->stmt_arena->alloc(buflen)) || |
3943 | !(new_separator= new(thd->stmt_arena->mem_root) |
3944 | String(buf, buflen, collation.collation))) |
3945 | return TRUE; |
3946 | |
3947 | conv_length= copy_and_convert(buf, buflen, collation.collation, |
3948 | separator->ptr(), separator->length(), |
3949 | separator->charset(), &errors); |
3950 | new_separator->length(conv_length); |
3951 | separator= new_separator; |
3952 | } |
3953 | |
3954 | if (check_sum_func(thd, ref)) |
3955 | return TRUE; |
3956 | |
3957 | fixed= 1; |
3958 | return FALSE; |
3959 | } |
3960 | |
3961 | |
3962 | bool Item_func_group_concat::setup(THD *thd) |
3963 | { |
3964 | List<Item> list; |
3965 | SELECT_LEX *select_lex= thd->lex->current_select; |
3966 | const bool order_or_distinct= MY_TEST(arg_count_order > 0 || distinct); |
3967 | DBUG_ENTER("Item_func_group_concat::setup" ); |
3968 | |
3969 | /* |
3970 | Currently setup() can be called twice. Please add |
3971 | assertion here when this is fixed. |
3972 | */ |
3973 | if (table || tree) |
3974 | DBUG_RETURN(FALSE); |
3975 | |
3976 | if (!(tmp_table_param= new TMP_TABLE_PARAM)) |
3977 | DBUG_RETURN(TRUE); |
3978 | |
3979 | /* Push all not constant fields to the list and create a temp table */ |
3980 | always_null= 0; |
3981 | for (uint i= 0; i < arg_count_field; i++) |
3982 | { |
3983 | Item *item= args[i]; |
3984 | if (list.push_back(item, thd->mem_root)) |
3985 | DBUG_RETURN(TRUE); |
3986 | if (item->const_item()) |
3987 | { |
3988 | if (item->is_null()) |
3989 | { |
3990 | always_null= 1; |
3991 | DBUG_RETURN(FALSE); |
3992 | } |
3993 | } |
3994 | } |
3995 | |
3996 | List<Item> all_fields(list); |
3997 | /* |
3998 | Try to find every ORDER expression in the list of GROUP_CONCAT |
3999 | arguments. If an expression is not found, prepend it to |
4000 | "all_fields". The resulting field list is used as input to create |
4001 | tmp table columns. |
4002 | */ |
4003 | if (arg_count_order) |
4004 | { |
4005 | uint n_elems= arg_count_order + all_fields.elements; |
4006 | ref_pointer_array= static_cast<Item**>(thd->alloc(sizeof(Item*) * n_elems)); |
4007 | if (!ref_pointer_array) |
4008 | DBUG_RETURN(TRUE); |
4009 | memcpy(ref_pointer_array, args, arg_count * sizeof(Item*)); |
4010 | if (setup_order(thd, Ref_ptr_array(ref_pointer_array, n_elems), |
4011 | context->table_list, list, all_fields, *order)) |
4012 | DBUG_RETURN(TRUE); |
4013 | } |
4014 | |
4015 | count_field_types(select_lex, tmp_table_param, all_fields, 0); |
4016 | tmp_table_param->force_copy_fields= force_copy_fields; |
4017 | DBUG_ASSERT(table == 0); |
4018 | if (order_or_distinct) |
4019 | { |
4020 | /* |
4021 | Force the create_tmp_table() to convert BIT columns to INT |
4022 | as we cannot compare two table records containg BIT fields |
4023 | stored in the the tree used for distinct/order by. |
4024 | Moreover we don't even save in the tree record null bits |
4025 | where BIT fields store parts of their data. |
4026 | */ |
4027 | List_iterator_fast<Item> li(all_fields); |
4028 | Item *item; |
4029 | while ((item= li++)) |
4030 | { |
4031 | if (item->type() == Item::FIELD_ITEM && |
4032 | ((Item_field*) item)->field->type() == FIELD_TYPE_BIT) |
4033 | item->marker= 4; |
4034 | } |
4035 | } |
4036 | |
4037 | /* |
4038 | We have to create a temporary table to get descriptions of fields |
4039 | (types, sizes and so on). |
4040 | |
4041 | Note that in the table, we first have the ORDER BY fields, then the |
4042 | field list. |
4043 | */ |
4044 | if (!(table= create_tmp_table(thd, tmp_table_param, all_fields, |
4045 | (ORDER*) 0, 0, TRUE, |
4046 | (select_lex->options | |
4047 | thd->variables.option_bits), |
4048 | HA_POS_ERROR, &empty_clex_str))) |
4049 | DBUG_RETURN(TRUE); |
4050 | table->file->extra(HA_EXTRA_NO_ROWS); |
4051 | table->no_rows= 1; |
4052 | |
4053 | /** |
4054 | Initialize blob_storage if GROUP_CONCAT is used |
4055 | with ORDER BY | DISTINCT and BLOB field count > 0. |
4056 | */ |
4057 | if (order_or_distinct && table->s->blob_fields) |
4058 | table->blob_storage= new Blob_mem_storage(); |
4059 | |
4060 | /* |
4061 | Need sorting or uniqueness: init tree and choose a function to sort. |
4062 | Don't reserve space for NULLs: if any of gconcat arguments is NULL, |
4063 | the row is not added to the result. |
4064 | */ |
4065 | uint tree_key_length= table->s->reclength - table->s->null_bytes; |
4066 | |
4067 | if (arg_count_order) |
4068 | { |
4069 | tree= &tree_base; |
4070 | /* |
4071 | Create a tree for sorting. The tree is used to sort (according to the |
4072 | syntax of this function). If there is no ORDER BY clause, we don't |
4073 | create this tree. |
4074 | */ |
4075 | init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size, |
4076 | thd->variables.sortbuff_size/16), 0, |
4077 | tree_key_length, |
4078 | group_concat_key_cmp_with_order, NULL, (void*) this, |
4079 | MYF(MY_THREAD_SPECIFIC)); |
4080 | } |
4081 | |
4082 | if (distinct) |
4083 | unique_filter= new Unique(group_concat_key_cmp_with_distinct, |
4084 | (void*)this, |
4085 | tree_key_length, |
4086 | ram_limitation(thd)); |
4087 | if ((row_limit && row_limit->cmp_type() != INT_RESULT) || |
4088 | (offset_limit && offset_limit->cmp_type() != INT_RESULT)) |
4089 | { |
4090 | my_error(ER_INVALID_VALUE_TO_LIMIT, MYF(0)); |
4091 | DBUG_RETURN(TRUE); |
4092 | } |
4093 | |
4094 | DBUG_RETURN(FALSE); |
4095 | } |
4096 | |
4097 | |
4098 | /* This is used by rollup to create a separate usable copy of the function */ |
4099 | |
4100 | void Item_func_group_concat::make_unique() |
4101 | { |
4102 | tmp_table_param= 0; |
4103 | table=0; |
4104 | original= 0; |
4105 | force_copy_fields= 1; |
4106 | tree= 0; |
4107 | } |
4108 | |
4109 | |
4110 | String* Item_func_group_concat::val_str(String* str) |
4111 | { |
4112 | DBUG_ASSERT(fixed == 1); |
4113 | if (null_value) |
4114 | return 0; |
4115 | if (no_appended && tree) |
4116 | /* Tree is used for sorting as in ORDER BY */ |
4117 | tree_walk(tree, &dump_leaf_key, this, left_root_right); |
4118 | |
4119 | if (table && table->blob_storage && |
4120 | table->blob_storage->is_truncated_value()) |
4121 | { |
4122 | warning_for_row= true; |
4123 | push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, |
4124 | ER_CUT_VALUE_GROUP_CONCAT, ER(ER_CUT_VALUE_GROUP_CONCAT), |
4125 | row_count); |
4126 | } |
4127 | |
4128 | return &result; |
4129 | } |
4130 | |
4131 | |
4132 | void Item_func_group_concat::print(String *str, enum_query_type query_type) |
4133 | { |
4134 | str->append(STRING_WITH_LEN("group_concat(" )); |
4135 | if (distinct) |
4136 | str->append(STRING_WITH_LEN("distinct " )); |
4137 | for (uint i= 0; i < arg_count_field; i++) |
4138 | { |
4139 | if (i) |
4140 | str->append(','); |
4141 | orig_args[i]->print(str, query_type); |
4142 | } |
4143 | if (arg_count_order) |
4144 | { |
4145 | str->append(STRING_WITH_LEN(" order by " )); |
4146 | for (uint i= 0 ; i < arg_count_order ; i++) |
4147 | { |
4148 | if (i) |
4149 | str->append(','); |
4150 | orig_args[i + arg_count_field]->print(str, query_type); |
4151 | if (order[i]->direction == ORDER::ORDER_ASC) |
4152 | str->append(STRING_WITH_LEN(" ASC" )); |
4153 | else |
4154 | str->append(STRING_WITH_LEN(" DESC" )); |
4155 | } |
4156 | } |
4157 | str->append(STRING_WITH_LEN(" separator \'" )); |
4158 | str->append_for_single_quote(separator->ptr(), separator->length()); |
4159 | str->append(STRING_WITH_LEN("\')" )); |
4160 | } |
4161 | |
4162 | |
4163 | Item_func_group_concat::~Item_func_group_concat() |
4164 | { |
4165 | if (!original && unique_filter) |
4166 | delete unique_filter; |
4167 | } |
4168 | |