item_sum.cc 73.1 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3 4 5 6
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
7

bk@work.mysql.com's avatar
bk@work.mysql.com committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16 17 18 19 20 21 22 23 24
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* Sum functions (COUNT, MIN...) */

#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
25
#include "sql_select.h"
26

bk@work.mysql.com's avatar
bk@work.mysql.com committed
27
Item_sum::Item_sum(List<Item> &list)
28
  :arg_count(list.elements)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
29 30 31 32
{
  if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
  {
    uint i=0;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
33
    List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
34 35 36 37 38 39 40
    Item *item;

    while ((item=li++))
    {
      args[i++]= item;
    }
  }
41
  mark_as_sum_func();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
42 43 44
  list.empty();					// Fields are used
}

45 46 47 48 49

/*
  Constructor used in processing select with temporary tebles
*/

50
Item_sum::Item_sum(THD *thd, Item_sum *item):
51 52
  Item_result_field(thd, item), arg_count(item->arg_count),
  quick_group(item->quick_group)
53 54 55 56
{
  if (arg_count <= 2)
    args=tmp_args;
  else
57
    if (!(args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
58
      return;
59 60 61 62
  memcpy(args, item->args, sizeof(Item*)*arg_count);
}


63
void Item_sum::mark_as_sum_func()
64
{
65
  current_thd->lex->current_select->with_sum_func= 1;
66
  with_sum_func= 1;
67
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
68

69

bk@work.mysql.com's avatar
bk@work.mysql.com committed
70 71 72 73
void Item_sum::make_field(Send_field *tmp_field)
{
  if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
  {
74 75 76 77
    ((Item_field*) args[0])->field->make_field(tmp_field);
    tmp_field->db_name=(char*)"";
    tmp_field->org_table_name=tmp_field->table_name=(char*)"";
    tmp_field->org_col_name=tmp_field->col_name=name;
78 79
    if (maybe_null)
      tmp_field->flags&= ~NOT_NULL_FLAG;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
80
  }
81 82
  else
    init_make_field(tmp_field, field_type());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
83 84
}

85

bk@work.mysql.com's avatar
bk@work.mysql.com committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
void Item_sum::print(String *str)
{
  str->append(func_name());
  str->append('(');
  for (uint i=0 ; i < arg_count ; i++)
  {
    if (i)
      str->append(',');
    args[i]->print(str);
  }
  str->append(')');
}

void Item_sum::fix_num_length_and_dec()
{
  decimals=0;
  for (uint i=0 ; i < arg_count ; i++)
    set_if_bigger(decimals,args[i]->decimals);
  max_length=float_length(decimals);
}

107
Item *Item_sum::get_tmp_table_item(THD *thd)
108
{
109
  Item_sum* sum_item= (Item_sum *) copy_or_same(thd);
110 111
  if (sum_item && sum_item->result_field)	   // If not a const sum func
  {
112
    Field *result_field_tmp= sum_item->result_field;
113 114 115 116 117 118
    for (uint i=0 ; i < sum_item->arg_count ; i++)
    {
      Item *arg= sum_item->args[i];
      if (!arg->const_item())
      {
	if (arg->type() == Item::FIELD_ITEM)
119
	  ((Item_field*) arg)->field= result_field_tmp++;
120
	else
121
	  sum_item->args[i]= new Item_field(result_field_tmp++);
122 123 124 125 126
      }
    }
  }
  return sum_item;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
127

128

129 130 131 132 133 134 135 136 137 138 139 140 141 142
bool Item_sum::walk (Item_processor processor, byte *argument)
{
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
      if ((*arg)->walk(processor, argument))
	return 1;
    }
  }
  return (this->*processor)(argument);
}

143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
Field *Item_sum::create_tmp_field(bool group, TABLE *table,
                                  uint convert_blob_length)
{
  switch (result_type()) {
  case REAL_RESULT:
    return new Field_double(max_length,maybe_null,name,table,decimals);
  case INT_RESULT:
    return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag);
  case STRING_RESULT:
    if (max_length > 255 && convert_blob_length)
      return new Field_varstring(convert_blob_length, maybe_null,
                                 name, table,
                                 collation.collation);
    return make_string_field(table);
  case DECIMAL_RESULT:
    return new Field_new_decimal(max_length - (decimals?1:0),
                                 maybe_null, name, table, decimals);
  case ROW_RESULT:
  default:
    // This case should never be choosen
    DBUG_ASSERT(0);
    return 0;
  }
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
170 171 172
String *
Item_sum_num::val_str(String *str)
{
173
  return val_string_from_real(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
174 175 176
}


177 178
my_decimal *Item_sum_num::val_decimal(my_decimal *decimal_value)
{
179
  return val_decimal_from_real(decimal_value);
180 181 182
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
183 184 185
String *
Item_sum_int::val_str(String *str)
{
186 187 188 189 190 191 192
  return val_string_from_int(str);
}


my_decimal *Item_sum_int::val_decimal(my_decimal *decimal_value)
{
  return val_decimal_from_int(decimal_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
193 194 195 196
}


bool
197
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
198
{
199
  DBUG_ASSERT(fixed == 0);
200

bk@work.mysql.com's avatar
bk@work.mysql.com committed
201 202
  if (!thd->allow_sum_func)
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
203 204
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
205
    return TRUE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
206 207 208 209 210 211
  }
  thd->allow_sum_func=0;			// No included group funcs
  decimals=0;
  maybe_null=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
212
    if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
213
      return TRUE;
214
    set_if_bigger(decimals, args[i]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
215 216 217 218 219 220 221
    maybe_null |= args[i]->maybe_null;
  }
  result_field=0;
  max_length=float_length(decimals);
  null_value=1;
  fix_length_and_dec();
  thd->allow_sum_func=1;			// Allow group functions
222
  fixed= 1;
223
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
224 225 226
}


227 228 229 230 231
Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item)
  :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type),
  hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign),
  used_table_cache(item->used_table_cache), was_values(item->was_values)
{
232 233
  /* copy results from old value */
  switch (hybrid_type) {
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
  case INT_RESULT:
    sum_int= item->sum_int;
    break;
  case DECIMAL_RESULT:
    my_decimal2decimal(&item->sum_dec, &sum_dec);
    break;
  case REAL_RESULT:
    sum= item->sum;
    break;
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  collation.set(item->collation);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
250
bool
251
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
252
{
253
  DBUG_ASSERT(fixed == 0);
254

255
  Item *item= args[0];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
256 257
  if (!thd->allow_sum_func)
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
258 259
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
260
    return TRUE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
261 262
  }
  thd->allow_sum_func=0;			// No included group funcs
263 264

  // 'item' can be changed during fix_fields
265
  if (!item->fixed &&
266 267
      item->fix_fields(thd, tables, args) ||
      (item= args[0])->check_cols(1))
268
    return TRUE;
269
  decimals=item->decimals;
270

271
  switch (hybrid_type= item->result_type()) {
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
  case INT_RESULT:
    max_length= 20;
    sum_int= 0;
    break;
  case DECIMAL_RESULT:
    max_length= item->max_length;
    my_decimal_set_zero(&sum_dec);
    break;
  case REAL_RESULT:
    max_length= float_length(decimals);
    sum= 0.0;
    break;
  case STRING_RESULT:
    max_length= item->max_length;
    break;
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  };
291 292
  /* MIN/MAX can return NULL for empty set indepedent of the used column */
  maybe_null= 1;
293
  unsigned_flag=item->unsigned_flag;
294
  collation.set(item->collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
295 296 297 298
  result_field=0;
  null_value=1;
  fix_length_and_dec();
  thd->allow_sum_func=1;			// Allow group functions
299 300 301 302
  if (item->type() == Item::FIELD_ITEM)
    hybrid_field_type= ((Item_field*) item)->field->type();
  else
    hybrid_field_type= Item::field_type();
303
  fixed= 1;
304
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
305 306
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
					 uint convert_blob_length)
{
  if (args[0]->type() == Item::FIELD_ITEM)
  {
    Field *field= ((Item_field*) args[0])->field;
    
    if ((field= create_tmp_field_from_field(current_thd, field, this, table,
					    0, convert_blob_length)))
      field->flags&= ~NOT_NULL_FLAG;
    return field;
  }
  return Item_sum::create_tmp_field(group, table, convert_blob_length);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
322 323 324 325 326

/***********************************************************************
** reset and add of sum_func
***********************************************************************/

327 328 329 330
Item_sum_sum::Item_sum_sum(THD *thd, Item_sum_sum *item) 
  :Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
   curr_dec_buff(item->curr_dec_buff)
{
331
  /* TODO: check if the following assignments are really needed */
332 333 334 335 336 337 338 339 340
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal2decimal(item->dec_buffs, dec_buffs);
    my_decimal2decimal(item->dec_buffs + 1, dec_buffs + 1);
  }
  else
    sum= item->sum;
}

341
Item *Item_sum_sum::copy_or_same(THD* thd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
342
{
343
  return new (thd->mem_root) Item_sum_sum(thd, this);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
344 345
}

346

347
void Item_sum_sum::clear()
348
{
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
  DBUG_ENTER("Item_sum_sum::clear");
  null_value=1;
  if (hybrid_type == DECIMAL_RESULT)
  {
    curr_dec_buff= 0;
    my_decimal_set_zero(dec_buffs);
  }
  else
    sum= 0.0;
  DBUG_VOID_RETURN;
}


void Item_sum_sum::fix_length_and_dec()
{
  DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
  maybe_null=null_value=1;
  decimals= args[0]->decimals;
367
  switch (args[0]->result_type()) {
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
  case REAL_RESULT:
  case STRING_RESULT:
    hybrid_type= REAL_RESULT;
    sum= 0.0;
    break;
  case INT_RESULT:
  case DECIMAL_RESULT:
    /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
    max_length= min(args[0]->max_length + DECIMAL_LONGLONG_DIGITS,
                    DECIMAL_MAX_LENGTH);
    curr_dec_buff= 0;
    hybrid_type= DECIMAL_RESULT;
    my_decimal_set_zero(dec_buffs);
    break;
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  DBUG_PRINT("info", ("Type: %s (%d, %d)",
                      (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
                       hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
                       hybrid_type == INT_RESULT ? "INT_RESULT" :
                       "--ILLEGAL!!!--"),
                      max_length,
                      (int)decimals));
  DBUG_VOID_RETURN;
394 395 396
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
397 398
bool Item_sum_sum::add()
{
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
  DBUG_ENTER("Item_sum_sum::add");
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal value, *val= args[0]->val_decimal(&value);
    if (!args[0]->null_value)
    {
      my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1),
                     val, dec_buffs + curr_dec_buff);
      curr_dec_buff^= 1;
      null_value= 0;
    }
  }
  else
  {
    sum+= args[0]->val_real();
    if (!args[0]->null_value)
      null_value= 0;
  }
  DBUG_RETURN(0);
}


longlong Item_sum_sum::val_int()
{
  DBUG_ASSERT(fixed == 1);
  if (hybrid_type == DECIMAL_RESULT)
  {
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, unsigned_flag,
                   &result);
    return result;
  }
431
  return (longlong) val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
432 433
}

434

435
double Item_sum_sum::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
436
{
437
  DBUG_ASSERT(fixed == 1);
438 439
  if (hybrid_type == DECIMAL_RESULT)
    my_decimal2double(E_DEC_FATAL_ERROR, dec_buffs + curr_dec_buff, &sum);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
440 441 442 443
  return sum;
}


444
String *Item_sum_sum::val_str(String *str)
445 446
{
  if (hybrid_type == DECIMAL_RESULT)
447 448
    return val_string_from_decimal(str);
  return val_string_from_real(str);
449 450 451 452 453
}


my_decimal *Item_sum_sum::val_decimal(my_decimal *val)
{
454 455 456
  if (hybrid_type == DECIMAL_RESULT)
    return (dec_buffs + curr_dec_buff);
  return val_decimal_from_real(val);
457 458
}

459

460 461 462
/* Item_sum_sum_distinct */

Item_sum_sum_distinct::Item_sum_sum_distinct(Item *item)
463
  :Item_sum_sum(item), tree(0)
464 465 466 467 468 469 470 471 472 473 474 475
{
  /*
    quick_group is an optimizer hint, which means that GROUP BY can be
    handled with help of index on grouped columns.
    By setting quick_group to zero we force creation of temporary table
    to perform GROUP BY.
  */
  quick_group= 0;
}


Item_sum_sum_distinct::Item_sum_sum_distinct(THD *thd,
pem@mysql.comhem.se's avatar
pem@mysql.comhem.se committed
476
                                             Item_sum_sum_distinct *original)
477
  :Item_sum_sum(thd, original), tree(0), dec_bin_buff(original->dec_bin_buff)
478 479 480 481 482
{
  quick_group= 0;
}


483 484 485 486 487 488 489 490 491 492 493 494
void Item_sum_sum_distinct::fix_length_and_dec()
{
  Item_sum_sum::fix_length_and_dec();
  if (hybrid_type == DECIMAL_RESULT)
  {
    dec_bin_buff= (byte *)
      sql_alloc(my_decimal_get_binary_size(args[0]->max_length,
                                           args[0]->decimals));
  }
}


495 496 497
Item *
Item_sum_sum_distinct::copy_or_same(THD *thd)
{
monty@mysql.com's avatar
monty@mysql.com committed
498
  return new (thd->mem_root) Item_sum_sum_distinct(thd, this);
499 500 501 502 503 504 505 506 507 508 509
}

C_MODE_START

static int simple_raw_key_cmp(void* arg, const void* key1, const void* key2)
{
  return memcmp(key1, key2, *(uint *) arg);
}

C_MODE_END

510

511 512
bool Item_sum_sum_distinct::setup(THD *thd)
{
513
  DBUG_ENTER("Item_sum_sum_distinct::setup");
514 515 516
  SELECT_LEX *select_lex= thd->lex->current_select;
  /* what does it mean??? */
  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
517
    DBUG_RETURN(1);
518 519 520 521 522 523 524 525 526 527 528 529 530

  DBUG_ASSERT(tree == 0);                 /* setup can not be called twice */

  /*
    Uniques handles all unique elements in a tree until they can't fit in.
    Then thee tree is dumped to the temporary file.
    See class Unique for details.
  */
  null_value= maybe_null= 1;
  /*
    TODO: if underlying item result fits in 4 bytes we can take advantage
    of it and have tree of long/ulong. It gives 10% performance boost
  */
531 532 533 534 535 536 537 538 539 540 541

  /*
    It's safe to use key_length here as even if we do copy_or_same()
    the new item will just share the old items key_length, which will not
    change or disappear during the life time of this item.
  */
  key_length= ((hybrid_type == DECIMAL_RESULT) ?
               my_decimal_get_binary_size(args[0]->max_length,
                                          args[0]->decimals) :
               sizeof(double));
  tree= new Unique(simple_raw_key_cmp, &key_length, key_length,
542
                   thd->variables.max_heap_table_size);
543
  DBUG_PRINT("info", ("tree 0x%lx, key length %d", (ulong)tree,
544
                      key_length));
545
  DBUG_RETURN(tree == 0);
546 547 548 549
}

void Item_sum_sum_distinct::clear()
{
550
  DBUG_ENTER("Item_sum_sum_distinct::clear");
551
  DBUG_ASSERT(tree != 0);                        /* we always have a tree */
552 553
  null_value= 1; 
  tree->reset();
554
  DBUG_VOID_RETURN;
555 556
}

557 558 559 560 561 562 563 564
void Item_sum_sum_distinct::cleanup()
{
  Item_sum_num::cleanup();
  delete tree;
  tree= 0;
}


565 566
bool Item_sum_sum_distinct::add()
{
567 568
  DBUG_ENTER("Item_sum_sum_distinct::add");
  if (hybrid_type == DECIMAL_RESULT)
569
  {
570 571 572
    my_decimal value, *val= args[0]->val_decimal(&value);
    if (!args[0]->null_value)
    {
573
      DBUG_ASSERT(tree != 0);
574
      null_value= 0;
575
      my_decimal2binary(E_DEC_FATAL_ERROR, val, (char *) dec_bin_buff,
576 577 578
                        args[0]->max_length, args[0]->decimals);
      DBUG_RETURN(tree->unique_add(dec_bin_buff));
    }
579
  }
580 581 582 583 584 585
  else
  {
    /* args[0]->val() may reset args[0]->null_value */
    double val= args[0]->val_real();
    if (!args[0]->null_value)
    {
586
      DBUG_ASSERT(tree != 0);
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
      null_value= 0;
      DBUG_PRINT("info", ("real: %lg, tree 0x%lx", val, (ulong)tree));
      if (val)
        DBUG_RETURN(tree->unique_add(&val));
    }
    else
      DBUG_PRINT("info", ("real: NULL"));
  }
  DBUG_RETURN(0);
}


void Item_sum_sum_distinct::add_real(double val)
{
  DBUG_ENTER("Item_sum_sum_distinct::add_real");
  sum+= val;
  DBUG_PRINT("info", ("sum %lg, val %lg", sum, val));
  DBUG_VOID_RETURN;
}


void Item_sum_sum_distinct::add_decimal(byte *val)
{
610
  binary2my_decimal(E_DEC_FATAL_ERROR, (char *) val, &tmp_dec,
611 612 613 614
                    args[0]->max_length, args[0]->decimals);
  my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs + (curr_dec_buff^1),
                 &tmp_dec, dec_buffs + curr_dec_buff);
  curr_dec_buff^= 1;
615 616 617 618
}

C_MODE_START

619 620 621 622 623 624 625 626 627 628
static int sum_sum_distinct_real(void *element, element_count num_of_dups,
                                 void *item_sum_sum_distinct)
{ 
  ((Item_sum_sum_distinct *)
   (item_sum_sum_distinct))->add_real(* (double *) element);
  return 0;
}

static int sum_sum_distinct_decimal(void *element, element_count num_of_dups,
                                    void *item_sum_sum_distinct)
629 630
{ 
  ((Item_sum_sum_distinct *)
631
   (item_sum_sum_distinct))->add_decimal((byte *)element);
632 633 634 635 636
  return 0;
}

C_MODE_END

637

638
double Item_sum_sum_distinct::val_real()
639
{
640
  DBUG_ENTER("Item_sum_sum_distinct::val");
641 642 643 644
  /*
    We don't have a tree only if 'setup()' hasn't been called;
    this is the case of sql_select.cc:return_zero_rows.
  */
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
  if (hybrid_type == DECIMAL_RESULT)
  {
    /* Item_sum_sum_distinct::val_decimal do not use argument */
    my_decimal *val= val_decimal(0);
    if (!null_value)
      my_decimal2double(E_DEC_FATAL_ERROR, val, &sum);
  }
  else
  {
    sum= 0.0;
    DBUG_PRINT("info", ("tree 0x%lx", (ulong)tree));
    if (tree) 
      tree->walk(sum_sum_distinct_real, (void *) this);
  }
  DBUG_RETURN(sum);
660 661
}

662 663 664 665 666 667 668 669 670 671 672 673 674

my_decimal *Item_sum_sum_distinct::val_decimal(my_decimal *fake)
{
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal_set_zero(dec_buffs);
    curr_dec_buff= 0;
    if (tree)
      tree->walk(sum_sum_distinct_decimal, (void *)this);
  }
  else
  {
    double real= val_real();
675 676
    curr_dec_buff= 0;
    double2my_decimal(E_DEC_FATAL_ERROR, real, dec_buffs);
677 678 679 680 681 682 683
  }
  return(dec_buffs + curr_dec_buff);
}


longlong Item_sum_sum_distinct::val_int()
{
684
  longlong result;
685 686 687 688 689
  if (hybrid_type == DECIMAL_RESULT)
  {
    /* Item_sum_sum_distinct::val_decimal do not use argument */
    my_decimal *val= val_decimal(0);
    if (!null_value)
690
      my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
691 692
  }
  else
693 694
    result= (longlong) val_real();
  return result;
695 696 697 698 699 700 701
}


String *Item_sum_sum_distinct::val_str(String *str)
{
  DBUG_ASSERT(fixed == 1);
  if (hybrid_type == DECIMAL_RESULT)
702 703
    return val_string_from_decimal(str);
  return val_string_from_real(str);
704 705 706
}


707 708
/* end of Item_sum_sum_distinct */

709
Item *Item_sum_count::copy_or_same(THD* thd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
710
{
711
  return new (thd->mem_root) Item_sum_count(thd, this);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
712 713
}

714

715
void Item_sum_count::clear()
716
{
717
  count= 0;
718 719 720
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
bool Item_sum_count::add()
{
  if (!args[0]->maybe_null)
    count++;
  else
  {
    (void) args[0]->val_int();
    if (!args[0]->null_value)
      count++;
  }
  return 0;
}

longlong Item_sum_count::val_int()
{
736
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
737 738 739
  return (longlong) count;
}

740 741 742 743 744 745 746 747 748 749

void Item_sum_count::cleanup()
{
  DBUG_ENTER("Item_sum_count::cleanup");
  Item_sum_int::cleanup();
  used_table_cache= ~(table_map) 0;
  DBUG_VOID_RETURN;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
750
/*
751
  Avgerage
bk@work.mysql.com's avatar
bk@work.mysql.com committed
752
*/
753 754 755 756 757 758 759 760 761 762 763 764 765 766
void Item_sum_avg::fix_length_and_dec()
{
  Item_sum_sum::fix_length_and_dec();
  maybe_null=null_value=1;
  decimals= min(args[0]->decimals + 4, NOT_FIXED_DEC);
  if (hybrid_type == DECIMAL_RESULT)
  {
    f_scale= args[0]->decimals;
    max_length= DECIMAL_MAX_LENGTH + (f_scale ? 1 : 0);
    f_precision= DECIMAL_MAX_LENGTH;
    dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
  }
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
767

768
Item *Item_sum_avg::copy_or_same(THD* thd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
769
{
770
  return new (thd->mem_root) Item_sum_avg(thd, this);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
771 772
}

773

774 775 776
Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table,
                                      uint convert_blob_len)
{
777
  if (group)
778
  {
779 780 781 782 783 784 785 786
    /*
      We must store both value and counter in the temporary table in one field.
      The easyest way is to do this is to store both value in a string
      and unpack on access.
    */
    return new Field_string(((hybrid_type == DECIMAL_RESULT) ?
                             dec_bin_size : sizeof(double)) + sizeof(longlong),
                            0, name, table, &my_charset_bin);
787
  }
788 789 790 791
  if (hybrid_type == DECIMAL_RESULT)
    return new Field_new_decimal(f_precision,
                                 maybe_null, name, table, f_scale);
  return new Field_double(max_length, maybe_null, name, table, decimals);
792 793 794
}


795
void Item_sum_avg::clear()
796
{
797 798
  Item_sum_sum::clear();
  count=0;
799 800 801
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
802 803
bool Item_sum_avg::add()
{
804 805
  if (Item_sum_sum::add())
    return TRUE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
806 807
  if (!args[0]->null_value)
    count++;
808
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
809 810
}

811
double Item_sum_avg::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
812
{
813
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
814 815 816 817 818
  if (!count)
  {
    null_value=1;
    return 0.0;
  }
819 820 821 822 823 824
  return Item_sum_sum::val_real() / ulonglong2double(count);
}


my_decimal *Item_sum_avg::val_decimal(my_decimal *val)
{
825 826
  my_decimal sum, cnt;
  const my_decimal *sum_dec;
827 828 829 830 831 832
  DBUG_ASSERT(fixed == 1);
  if (!count)
  {
    null_value=1;
    return NULL;
  }
833
  sum_dec= Item_sum_sum::val_decimal(&sum);
834 835 836 837 838 839 840 841 842
  int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &cnt);
  my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, 4);
  return val;
}


String *Item_sum_avg::val_str(String *str)
{
  if (hybrid_type == DECIMAL_RESULT)
843 844
    return val_string_from_decimal(str);
  return val_string_from_real(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
845 846 847 848
}


/*
849
  Standard deviation
bk@work.mysql.com's avatar
bk@work.mysql.com committed
850 851
*/

852
double Item_sum_std::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
853
{
854
  DBUG_ASSERT(fixed == 1);
855
  double tmp= Item_sum_variance::val_real();
856
  return tmp <= 0.0 ? 0.0 : sqrt(tmp);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
857 858
}

859 860
Item *Item_sum_std::copy_or_same(THD* thd)
{
861
  return new (thd->mem_root) Item_sum_std(thd, this);
862 863 864
}


865
/*
866
  Variance
867 868
*/

869 870 871

Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
  Item_sum_num(thd, item), hybrid_type(item->hybrid_type),
872
    cur_dec(item->cur_dec), count(item->count), sample(item->sample)
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
{
  if (hybrid_type == DECIMAL_RESULT)
  {
    memcpy(dec_sum, item->dec_sum, sizeof(item->dec_sum));
    memcpy(dec_sqr, item->dec_sqr, sizeof(item->dec_sqr));
    for (int i=0; i<2; i++)
    {
      dec_sum[i].fix_buffer_pointer();
      dec_sqr[i].fix_buffer_pointer();
    }
  }
  else
  {
    sum= item->sum;
    sum_sqr= item->sum_sqr;
  }
}


void Item_sum_variance::fix_length_and_dec()
{
894 895
  DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
  maybe_null= null_value= 1;
896
  decimals= args[0]->decimals + 4;
897
  switch (args[0]->result_type()) {
898 899 900 901 902 903 904
  case REAL_RESULT:
  case STRING_RESULT:
    hybrid_type= REAL_RESULT;
    sum= 0.0;
    break;
  case INT_RESULT:
  case DECIMAL_RESULT:
905 906 907 908
    /*
      SUM result can't be longer than length(arg)*2 +
      digits_after_the_point_to_add
    */
909 910 911 912 913
    max_length= args[0]->max_length*2 + 4;
    cur_dec= 0;
    hybrid_type= DECIMAL_RESULT;
    my_decimal_set_zero(dec_sum);
    my_decimal_set_zero(dec_sqr);
914 915 916 917 918 919

    /*
      The maxium value to usable for variance is DECIMAL_MAX_LENGTH/2
      becasue we need to be able to calculate in dec_bin_size1
      column_value * column_value
    */
920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
    f_scale0= args[0]->decimals;
    f_precision0= DECIMAL_MAX_LENGTH / 2;
    f_scale1= min(f_scale0 * 2, NOT_FIXED_DEC - 1);
    f_precision1= DECIMAL_MAX_LENGTH;
    dec_bin_size0= my_decimal_get_binary_size(f_precision0, f_scale0);
    dec_bin_size1= my_decimal_get_binary_size(f_precision1, f_scale1);
    break;
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  DBUG_PRINT("info", ("Type: %s (%d, %d)",
                      (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
                       hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
                       hybrid_type == INT_RESULT ? "INT_RESULT" :
                       "--ILLEGAL!!!--"),
                      max_length,
                      (int)decimals));
  DBUG_VOID_RETURN;
}


942 943
Item *Item_sum_variance::copy_or_same(THD* thd)
{
944
  return new (thd->mem_root) Item_sum_variance(thd, this);
945 946 947
}


948 949 950
Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table,
                                           uint convert_blob_len)
{
951
  if (group)
952
  {
953 954 955 956 957 958 959 960 961
    /*
      We must store both value and counter in the temporary table in one field.
      The easyest way is to do this is to store both value in a string
      and unpack on access.
    */
    return new Field_string(((hybrid_type == DECIMAL_RESULT) ?
                             dec_bin_size0 + dec_bin_size1 :
                             sizeof(double)*2) + sizeof(longlong),
                            0, name, table, &my_charset_bin);
962
  }
963 964 965 966
  if (hybrid_type == DECIMAL_RESULT)
    return new Field_new_decimal(DECIMAL_MAX_LENGTH,
                                 maybe_null, name, table, f_scale1 + 4);
  return new Field_double(max_length, maybe_null,name,table,decimals);
967 968 969
}


970
void Item_sum_variance::clear()
971
{
972 973 974 975 976 977 978 979
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal_set_zero(dec_sum);
    my_decimal_set_zero(dec_sqr);
    cur_dec= 0;
  }
  else
    sum=sum_sqr=0.0; 
980 981 982 983
  count=0; 
}

bool Item_sum_variance::add()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
984
{
985
  if (hybrid_type == DECIMAL_RESULT)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
986
  {
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
    my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf);
    my_decimal sqr_buf;
    if (!args[0]->null_value)
    {
      count++;
      int next_dec= cur_dec ^ 1;
      my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec);
      my_decimal_add(E_DEC_FATAL_ERROR, dec_sqr+next_dec,
                     dec_sqr+cur_dec, &sqr_buf);
      my_decimal_add(E_DEC_FATAL_ERROR, dec_sum+next_dec,
                     dec_sum+cur_dec, dec);
      cur_dec= next_dec;
    }
  }
  else
  {
    double nr= args[0]->val_real();
    if (!args[0]->null_value)
    {
      sum+=nr;
      sum_sqr+=nr*nr;
      count++;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1010 1011 1012 1013
  }
  return 0;
}

1014
double Item_sum_variance::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1015
{
1016
  DBUG_ASSERT(fixed == 1);
1017 1018 1019
  if (hybrid_type == DECIMAL_RESULT)
    return val_real_from_decimal();

1020
  if (count <= sample)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1021 1022 1023 1024
  {
    null_value=1;
    return 0.0;
  }
1025 1026 1027
  null_value=0;
  /* Avoid problems when the precision isn't good enough */
  double tmp=ulonglong2double(count);
1028
  double tmp2= (sum_sqr - sum*sum/tmp)/(tmp - (double)sample);
1029 1030 1031 1032 1033 1034
  return tmp2 <= 0.0 ? 0.0 : tmp2;
}


my_decimal *Item_sum_variance::val_decimal(my_decimal *dec_buf)
{
1035
  my_decimal count_buf, count1_buf, sum_sqr_buf;
1036 1037
  DBUG_ASSERT(fixed ==1 );
  if (hybrid_type == REAL_RESULT)
1038 1039
    return val_decimal_from_real(dec_buf);

1040
  if (count <= sample)
1041 1042 1043 1044 1045 1046
  {
    null_value= 1;
    return 0;
  }
  null_value= 0;
  int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &count_buf);
1047
  int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &count1_buf);
1048 1049 1050 1051
  my_decimal_mul(E_DEC_FATAL_ERROR, &sum_sqr_buf,
                 dec_sum+cur_dec, dec_sum+cur_dec);
  my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count_buf, 2);
  my_decimal_sub(E_DEC_FATAL_ERROR, &sum_sqr_buf, dec_sqr+cur_dec, dec_buf);
1052
  my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &sum_sqr_buf, &count1_buf, 2);
1053 1054 1055
  return dec_buf;
}

1056

1057 1058
void Item_sum_variance::reset_field()
{
1059 1060 1061
  double nr;
  char *res= result_field->ptr;

1062 1063
  if (hybrid_type == DECIMAL_RESULT)
  {
1064 1065 1066 1067
    my_decimal value, *arg_dec, *arg2_dec;
    longlong tmp;

    arg_dec= args[0]->val_decimal(&value);
1068 1069
    if (args[0]->null_value)
    {
1070 1071
      arg_dec= arg2_dec= &decimal_zero;
      tmp= 0;
1072 1073 1074 1075
    }
    else
    {
      my_decimal_mul(E_DEC_FATAL_ERROR, dec_sum, arg_dec, arg_dec);
1076 1077
      arg2_dec= dec_sum;
      tmp= 1;
1078
    }
1079 1080 1081 1082 1083 1084
    my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec,
                      res, f_precision0, f_scale0);
    my_decimal2binary(E_DEC_FATAL_ERROR, arg2_dec,
                      res+dec_bin_size0, f_precision1, f_scale1);
    res+= dec_bin_size0 + dec_bin_size1;
    int8store(res,tmp);
1085 1086
    return;
  }
1087
  nr= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1088 1089 1090 1091 1092

  if (args[0]->null_value)
    bzero(res,sizeof(double)*2+sizeof(longlong));
  else
  {
1093
    longlong tmp;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1094 1095 1096
    float8store(res,nr);
    nr*=nr;
    float8store(res+sizeof(double),nr);
1097
    tmp= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1098 1099 1100 1101
    int8store(res+sizeof(double)*2,tmp);
  }
}

1102

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1103
void Item_sum_variance::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1104 1105 1106
{
  longlong field_count;
  char *res=result_field->ptr;
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal value, *arg_val= args[0]->val_decimal(&value);
    if (!args[0]->null_value)
    {
      binary2my_decimal(E_DEC_FATAL_ERROR, res,
                        dec_sum+1, f_precision0, f_scale0);
      binary2my_decimal(E_DEC_FATAL_ERROR, res+dec_bin_size0,
                        dec_sqr+1, f_precision1, f_scale1);
      field_count= sint8korr(res + (dec_bin_size0 + dec_bin_size1));
      my_decimal_add(E_DEC_FATAL_ERROR, dec_sum, arg_val, dec_sum+1);
      my_decimal_mul(E_DEC_FATAL_ERROR, dec_sum+1, arg_val, arg_val);
      my_decimal_add(E_DEC_FATAL_ERROR, dec_sqr, dec_sqr+1, dec_sum+1);
      field_count++;
      my_decimal2binary(E_DEC_FATAL_ERROR, dec_sum,
                        res, f_precision0, f_scale0);
      my_decimal2binary(E_DEC_FATAL_ERROR, dec_sqr,
                        res+dec_bin_size0, f_precision1, f_scale1);
      res+= dec_bin_size0 + dec_bin_size1;
      int8store(res, field_count);
    }
    return;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1130

1131
  double nr,old_nr,old_sqr;
1132 1133 1134
  float8get(old_nr, res);
  float8get(old_sqr, res+sizeof(double));
  field_count=sint8korr(res+sizeof(double)*2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1135

1136
  nr= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1137 1138 1139 1140 1141 1142 1143 1144
  if (!args[0]->null_value)
  {
    old_nr+=nr;
    old_sqr+=nr*nr;
    field_count++;
  }
  float8store(res,old_nr);
  float8store(res+sizeof(double),old_sqr);
1145 1146
  res+= sizeof(double)*2;
  int8store(res,field_count);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1147 1148
}

1149

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1150 1151
/* min & max */

1152 1153
void Item_sum_hybrid::clear()
{
1154
  switch (hybrid_type) {
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
  case INT_RESULT:
    sum_int= 0;
    break;
  case DECIMAL_RESULT:
    my_decimal_set_zero(&sum_dec);
    break;
  case REAL_RESULT:
    sum= 0.0;
    break;
  default:
    value.length(0);
  }
1167 1168 1169
  null_value= 1;
}

1170
double Item_sum_hybrid::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1171
{
1172
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1173 1174
  if (null_value)
    return 0.0;
1175 1176
  switch (hybrid_type) {
  case STRING_RESULT:
1177 1178 1179
  {
    char *end_not_used;
    int err_not_used;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1180
    String *res;  res=val_str(&str_value);
1181 1182 1183
    return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
			     &end_not_used, &err_not_used) : 0.0);
  }
1184 1185 1186 1187
  case INT_RESULT:
    if (unsigned_flag)
      return ulonglong2double(sum_int);
    return (double) sum_int;
1188 1189 1190
  case DECIMAL_RESULT:
    my_decimal2double(E_DEC_FATAL_ERROR, &sum_dec, &sum);
    return sum;
1191 1192
  case REAL_RESULT:
    return sum;
1193
  case ROW_RESULT:
1194
  default:
1195 1196 1197
    // This case should never be choosen
    DBUG_ASSERT(0);
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1198
  }
1199 1200 1201 1202
}

longlong Item_sum_hybrid::val_int()
{
1203
  DBUG_ASSERT(fixed == 1);
1204 1205
  if (null_value)
    return 0;
1206
  switch (hybrid_type) {
1207 1208 1209 1210 1211 1212
  case INT_RESULT:
    return sum_int;
  case DECIMAL_RESULT:
  {
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, &sum_dec, unsigned_flag, &result);
1213
    return sum_int;
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
  }
  default:
    return (longlong) Item_sum_hybrid::val_real();
  }
}


my_decimal *Item_sum_hybrid::val_decimal(my_decimal *val)
{
  DBUG_ASSERT(fixed == 1);
  if (null_value)
    return 0;
  switch (hybrid_type) {
  case STRING_RESULT:
    string2my_decimal(E_DEC_FATAL_ERROR, &value, val);
    break;
  case REAL_RESULT:
    double2my_decimal(E_DEC_FATAL_ERROR, sum, val);
    break;
  case DECIMAL_RESULT:
    val= &sum_dec;
    break;
  case INT_RESULT:
    int2my_decimal(E_DEC_FATAL_ERROR, sum_int, unsigned_flag, val);
    break;
  case ROW_RESULT:
  default:
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
  }
  return val;					// Keep compiler happy
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1246 1247 1248 1249 1250 1251
}


String *
Item_sum_hybrid::val_str(String *str)
{
1252
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1253 1254
  if (null_value)
    return 0;
1255 1256
  switch (hybrid_type) {
  case STRING_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1257
    return &value;
1258
  case REAL_RESULT:
monty@mysql.com's avatar
monty@mysql.com committed
1259
    str->set(sum,decimals, &my_charset_bin);
1260
    break;
1261 1262 1263
  case DECIMAL_RESULT:
    my_decimal2string(E_DEC_FATAL_ERROR, &sum_dec, 0, 0, 0, str);
    return str;
1264 1265
  case INT_RESULT:
    if (unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
1266
      str->set((ulonglong) sum_int, &my_charset_bin);
1267
    else
monty@mysql.com's avatar
monty@mysql.com committed
1268
      str->set((longlong) sum_int, &my_charset_bin);
1269
    break;
1270
  case ROW_RESULT:
1271
  default:
1272 1273 1274
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
1275 1276
  }
  return str;					// Keep compiler happy
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1277 1278
}

1279

1280 1281 1282 1283 1284
void Item_sum_hybrid::cleanup()
{
  DBUG_ENTER("Item_sum_hybrid::cleanup");
  Item_sum::cleanup();
  used_table_cache= ~(table_map) 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1285

1286
  /*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1287
    by default it is TRUE to avoid TRUE reporting by
1288 1289 1290
    Item_func_not_all/Item_func_nop_all if this item was never called.

    no_rows_in_result() set it to FALSE if was not results found.
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1291
    If some results found it will be left unchanged.
1292 1293
  */
  was_values= TRUE;
1294 1295 1296
  DBUG_VOID_RETURN;
}

1297 1298 1299 1300 1301 1302
void Item_sum_hybrid::no_rows_in_result()
{
  Item_sum::no_rows_in_result();
  was_values= FALSE;
}

1303

1304 1305
Item *Item_sum_min::copy_or_same(THD* thd)
{
1306
  return new (thd->mem_root) Item_sum_min(thd, this);
1307 1308 1309
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
1310 1311
bool Item_sum_min::add()
{
1312 1313
  switch (hybrid_type) {
  case STRING_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1314 1315 1316
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
1317
	(null_value || sortcmp(&value,result,collation.collation) > 0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1318 1319 1320 1321 1322
    {
      value.copy(*result);
      null_value=0;
    }
  }
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
  break;
  case INT_RESULT:
  {
    longlong nr=args[0]->val_int();
    if (!args[0]->null_value && (null_value ||
				 (unsigned_flag && 
				  (ulonglong) nr < (ulonglong) sum_int) ||
				 (!unsigned_flag && nr < sum_int)))
    {
      sum_int=nr;
      null_value=0;
    }
  }
  break;
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
  case DECIMAL_RESULT:
  {
    my_decimal value, *val= args[0]->val_decimal(&value);
    if (!args[0]->null_value &&
        (null_value || (my_decimal_cmp(&sum_dec, val) > 0)))
    {
      my_decimal2decimal(val, &sum_dec);
      null_value= 0;
    }
  }
  break;
1348
  case REAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1349
  {
1350
    double nr= args[0]->val_real();
1351
    if (!args[0]->null_value && (null_value || nr < sum))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1352 1353 1354 1355 1356
    {
      sum=nr;
      null_value=0;
    }
  }
1357
  break;
1358
  case ROW_RESULT:
1359
  default:
1360 1361 1362
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
1363 1364 1365 1366 1367
  }
  return 0;
}


1368 1369
Item *Item_sum_max::copy_or_same(THD* thd)
{
1370
  return new (thd->mem_root) Item_sum_max(thd, this);
1371 1372 1373
}


1374 1375 1376 1377
bool Item_sum_max::add()
{
  switch (hybrid_type) {
  case STRING_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1378 1379 1380
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
1381
	(null_value || sortcmp(&value,result,collation.collation) < 0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1382 1383 1384 1385 1386
    {
      value.copy(*result);
      null_value=0;
    }
  }
1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
  break;
  case INT_RESULT:
  {
    longlong nr=args[0]->val_int();
    if (!args[0]->null_value && (null_value ||
				 (unsigned_flag && 
				  (ulonglong) nr > (ulonglong) sum_int) ||
				 (!unsigned_flag && nr > sum_int)))
    {
      sum_int=nr;
      null_value=0;
    }
  }
  break;
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
  case DECIMAL_RESULT:
  {
    my_decimal value, *val= args[0]->val_decimal(&value);
    if (!args[0]->null_value &&
        (null_value || (my_decimal_cmp(val, &sum_dec) > 0)))
    {
      my_decimal2decimal(val, &sum_dec);
      null_value= 0;
    }
  }
  break;
1412 1413
  case REAL_RESULT:
  {
1414
    double nr= args[0]->val_real();
1415 1416 1417 1418 1419 1420 1421
    if (!args[0]->null_value && (null_value || nr > sum))
    {
      sum=nr;
      null_value=0;
    }
  }
  break;
1422
  case ROW_RESULT:
1423
  default:
1424 1425 1426
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
1427
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1428 1429 1430 1431 1432 1433 1434 1435
  return 0;
}


/* bit_or and bit_and */

longlong Item_sum_bit::val_int()
{
1436
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1437 1438 1439
  return (longlong) bits;
}

1440

1441
void Item_sum_bit::clear()
1442
{
1443
  bits= reset_bits;
1444 1445 1446
}

Item *Item_sum_or::copy_or_same(THD* thd)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1447
{
1448
  return new (thd->mem_root) Item_sum_or(thd, this);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1449 1450
}

1451

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1452 1453 1454 1455 1456 1457 1458 1459
bool Item_sum_or::add()
{
  ulonglong value= (ulonglong) args[0]->val_int();
  if (!args[0]->null_value)
    bits|=value;
  return 0;
}

1460 1461
Item *Item_sum_xor::copy_or_same(THD* thd)
{
1462
  return new (thd->mem_root) Item_sum_xor(thd, this);
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
}


bool Item_sum_xor::add()
{
  ulonglong value= (ulonglong) args[0]->val_int();
  if (!args[0]->null_value)
    bits^=value;
  return 0;
}

1474 1475
Item *Item_sum_and::copy_or_same(THD* thd)
{
1476
  return new (thd->mem_root) Item_sum_and(thd, this);
1477 1478 1479
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
bool Item_sum_and::add()
{
  ulonglong value= (ulonglong) args[0]->val_int();
  if (!args[0]->null_value)
    bits&=value;
  return 0;
}

/************************************************************************
** reset result of a Item_sum with is saved in a tmp_table
*************************************************************************/

void Item_sum_num::reset_field()
{
1494
  double nr= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
  char *res=result_field->ptr;

  if (maybe_null)
  {
    if (args[0]->null_value)
    {
      nr=0.0;
      result_field->set_null();
    }
    else
      result_field->set_notnull();
  }
  float8store(res,nr);
}


void Item_sum_hybrid::reset_field()
{
1513
  switch(hybrid_type) {
1514
  case STRING_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1515 1516
  {
    char buff[MAX_FIELD_WIDTH];
1517
    String tmp(buff,sizeof(buff),result_field->charset()),*res;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527

    res=args[0]->val_str(&tmp);
    if (args[0]->null_value)
    {
      result_field->set_null();
      result_field->reset();
    }
    else
    {
      result_field->set_notnull();
1528
      result_field->store(res->ptr(),res->length(),tmp.charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1529
    }
1530
    break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1531
  }
1532
  case INT_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546
  {
    longlong nr=args[0]->val_int();

    if (maybe_null)
    {
      if (args[0]->null_value)
      {
	nr=0;
	result_field->set_null();
      }
      else
	result_field->set_notnull();
    }
    result_field->store(nr);
1547
    break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1548
  }
1549
  case REAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1550
  {
1551
    double nr= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563

    if (maybe_null)
    {
      if (args[0]->null_value)
      {
	nr=0.0;
	result_field->set_null();
      }
      else
	result_field->set_notnull();
    }
    result_field->store(nr);
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576
    break;
  }
  case DECIMAL_RESULT:
  {
    my_decimal value, *arg_dec= args[0]->val_decimal(&value);

    if (maybe_null)
    {
      if (args[0]->null_value)
        result_field->set_null();
      else
        result_field->set_notnull();
    }
1577 1578 1579 1580 1581 1582 1583
    /*
      We must store zero in the field as we will use the field value in
      add()
    */
    if (!arg_dec)                               // Null
      arg_dec= &decimal_zero;
    result_field->store_decimal(arg_dec);
1584 1585 1586 1587 1588
    break;
  }
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1589 1590 1591 1592 1593 1594
  }
}


void Item_sum_sum::reset_field()
{
1595 1596 1597
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal value, *arg_val= args[0]->val_decimal(&value);
1598 1599 1600
    if (!arg_val)                               // Null
      arg_val= &decimal_zero;
    result_field->store_decimal(arg_val);
1601 1602 1603 1604 1605 1606 1607
  }
  else
  {
    DBUG_ASSERT(hybrid_type == REAL_RESULT);
    double nr= args[0]->val_real();			// Nulls also return 0
    float8store(result_field->ptr, nr);
  }
1608 1609 1610 1611
  if (args[0]->null_value)
    result_field->set_null();
  else
    result_field->set_notnull();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
}


void Item_sum_count::reset_field()
{
  char *res=result_field->ptr;
  longlong nr=0;

  if (!args[0]->maybe_null)
    nr=1;
  else
  {
    (void) args[0]->val_int();
    if (!args[0]->null_value)
      nr=1;
  }
  int8store(res,nr);
}


void Item_sum_avg::reset_field()
{
  char *res=result_field->ptr;
1635 1636
  if (hybrid_type == DECIMAL_RESULT)
  {
1637
    longlong tmp;
1638 1639 1640
    my_decimal value, *arg_dec= args[0]->val_decimal(&value);
    if (args[0]->null_value)
    {
1641 1642
      arg_dec= &decimal_zero;
      tmp= 0;
1643 1644
    }
    else
1645 1646 1647 1648
      tmp= 1;
    my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec, res, f_precision, f_scale);
    res+= dec_bin_size;
    int8store(res, tmp);
1649
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1650 1651
  else
  {
1652 1653 1654 1655 1656 1657
    double nr= args[0]->val_real();

    if (args[0]->null_value)
      bzero(res,sizeof(double)+sizeof(longlong));
    else
    {
1658
      longlong tmp= 1;
1659 1660 1661 1662
      float8store(res,nr);
      res+=sizeof(double);
      int8store(res,tmp);
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1663 1664 1665
  }
}

1666

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1667
void Item_sum_bit::reset_field()
konstantin@mysql.com's avatar
konstantin@mysql.com committed
1668
{
1669 1670
  reset();
  int8store(result_field->ptr, bits);
konstantin@mysql.com's avatar
konstantin@mysql.com committed
1671 1672 1673
}

void Item_sum_bit::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1674 1675
{
  char *res=result_field->ptr;
konstantin@mysql.com's avatar
konstantin@mysql.com committed
1676 1677 1678
  bits= uint8korr(res);
  add();
  int8store(res, bits);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1679 1680
}

1681

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1682 1683 1684 1685
/*
** calc next value and merge it with field_value
*/

1686
void Item_sum_sum::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1687
{
1688
  if (hybrid_type == DECIMAL_RESULT)
1689
  {
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719
    my_decimal value, *arg_val= args[0]->val_decimal(&value);
    if (!args[0]->null_value)
    {
      if (!result_field->is_null())
      {
        my_decimal field_value,
                   *field_val= result_field->val_decimal(&field_value);
        my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, field_val);
        result_field->store_decimal(dec_buffs);
      }
      else
      {
        result_field->store_decimal(arg_val);
        result_field->set_notnull();
      }
    }
  }
  else
  {
    double old_nr,nr;
    char *res=result_field->ptr;

    float8get(old_nr,res);
    nr= args[0]->val_real();
    if (!args[0]->null_value)
    {
      old_nr+=nr;
      result_field->set_notnull();
    }
    float8store(res,old_nr);
1720
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1721 1722 1723
}


1724
void Item_sum_count::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1725 1726 1727 1728
{
  longlong nr;
  char *res=result_field->ptr;

1729
  nr=sint8korr(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741
  if (!args[0]->maybe_null)
    nr++;
  else
  {
    (void) args[0]->val_int();
    if (!args[0]->null_value)
      nr++;
  }
  int8store(res,nr);
}


1742
void Item_sum_avg::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1743 1744 1745
{
  longlong field_count;
  char *res=result_field->ptr;
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757
  if (hybrid_type == DECIMAL_RESULT)
  {
    my_decimal value, *arg_val= args[0]->val_decimal(&value);
    if (!args[0]->null_value)
    {
      binary2my_decimal(E_DEC_FATAL_ERROR, res,
                        dec_buffs + 1, f_precision, f_scale);
      field_count= sint8korr(res + dec_bin_size);
      my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, dec_buffs + 1);
      my_decimal2binary(E_DEC_FATAL_ERROR, dec_buffs,
                        res, f_precision, f_scale);
      res+= dec_bin_size;
1758
      field_count++;
1759 1760 1761 1762 1763
      int8store(res, field_count);
    }
  }
  else
  {
1764
    double nr;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1765

1766 1767 1768
    nr= args[0]->val_real();
    if (!args[0]->null_value)
    {
1769 1770 1771
      double old_nr;
      float8get(old_nr, res);
      field_count= sint8korr(res + sizeof(double));
1772
      old_nr+= nr;
1773 1774
      float8store(res,old_nr);
      res+= sizeof(double);
1775
      field_count++;
1776
      int8store(res, field_count);
1777
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1778 1779 1780
  }
}

1781

1782
void Item_sum_hybrid::update_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1783
{
1784
  switch (hybrid_type) {
1785
  case STRING_RESULT:
1786
    min_max_update_str_field();
1787 1788
    break;
  case INT_RESULT:
1789
    min_max_update_int_field();
1790 1791 1792 1793 1794
    break;
  case DECIMAL_RESULT:
    min_max_update_decimal_field();
    break;
  default:
1795
    min_max_update_real_field();
1796
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1797 1798 1799 1800
}


void
1801
Item_sum_hybrid::min_max_update_str_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1802 1803 1804
{
  String *res_str=args[0]->val_str(&value);

1805
  if (!args[0]->null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1806 1807
  {
    res_str->strip_sp();
1808
    result_field->val_str(&tmp_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1809 1810

    if (result_field->is_null() ||
1811
	(cmp_sign * sortcmp(res_str,&tmp_value,collation.collation)) < 0)
1812
      result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1813 1814 1815 1816 1817 1818
    result_field->set_notnull();
  }
}


void
1819
Item_sum_hybrid::min_max_update_real_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1820 1821 1822 1823
{
  double nr,old_nr;

  old_nr=result_field->val_real();
1824
  nr= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1825 1826
  if (!args[0]->null_value)
  {
1827
    if (result_field->is_null(0) ||
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1828 1829 1830 1831
	(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
      old_nr=nr;
    result_field->set_notnull();
  }
1832
  else if (result_field->is_null(0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1833 1834 1835 1836 1837 1838
    result_field->set_null();
  result_field->store(old_nr);
}


void
1839
Item_sum_hybrid::min_max_update_int_field()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1840 1841 1842 1843 1844 1845 1846
{
  longlong nr,old_nr;

  old_nr=result_field->val_int();
  nr=args[0]->val_int();
  if (!args[0]->null_value)
  {
1847
    if (result_field->is_null(0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1848
      old_nr=nr;
1849 1850 1851 1852 1853 1854
    else
    {
      bool res=(unsigned_flag ?
		(ulonglong) old_nr > (ulonglong) nr :
		old_nr > nr);
      /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1855
      if ((cmp_sign > 0) ^ (!res))
1856 1857
	old_nr=nr;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1858 1859
    result_field->set_notnull();
  }
1860
  else if (result_field->is_null(0))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1861 1862 1863 1864 1865
    result_field->set_null();
  result_field->store(old_nr);
}


1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892
void
Item_sum_hybrid::min_max_update_decimal_field()
{
  /* TODO: optimize: do not get result_field in case of args[0] is NULL */
  my_decimal old_val, nr_val;
  const my_decimal *old_nr= result_field->val_decimal(&old_val);
  const my_decimal *nr= args[0]->val_decimal(&nr_val);
  if (!args[0]->null_value)
  {
    if (result_field->is_null(0))
      old_nr=nr;
    else
    {
      bool res= my_decimal_cmp(old_nr, nr) > 0;
      /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
      if ((cmp_sign > 0) ^ (!res))
        old_nr=nr;
    }
    result_field->set_notnull();
  }
  else if (result_field->is_null(0))
    result_field->set_null();
  result_field->store_decimal(old_nr);
}


Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1893 1894 1895 1896 1897 1898
{
  name=item->name;
  decimals=item->decimals;
  max_length=item->max_length;
  field=item->result_field;
  maybe_null=1;
1899 1900 1901 1902 1903 1904 1905
  hybrid_type= res_type;
  if (hybrid_type == DECIMAL_RESULT)
  {
    f_scale= item->f_scale;
    f_precision= item->f_precision;
    dec_bin_size= item->dec_bin_size;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1906 1907
}

konstantin@mysql.com's avatar
konstantin@mysql.com committed
1908

1909
double Item_avg_field::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1910
{
1911
  // fix_fields() never calls for this Item
1912 1913 1914 1915
  double nr;
  longlong count;
  char *res;

1916
  if (hybrid_type == DECIMAL_RESULT)
1917
    return val_real_from_decimal();
1918

1919 1920 1921 1922 1923 1924 1925
  float8get(nr,field->ptr);
  res= (field->ptr+sizeof(double));
  count= sint8korr(res);

  if ((null_value= !count))
    return 0.0;
  return nr/(double) count;
1926 1927
}

1928

1929 1930
longlong Item_avg_field::val_int()
{
1931
  return (longlong) val_real();
1932 1933 1934
}


1935
my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf)
1936 1937
{
  // fix_fields() never calls for this Item
1938 1939 1940
  if (hybrid_type == REAL_RESULT)
    return val_decimal_from_real(dec_buf);

1941 1942
  longlong count= sint8korr(field->ptr + dec_bin_size);
  if ((null_value= !count))
1943
    return 0;
1944 1945 1946 1947 1948

  my_decimal dec_count, dec_field;
  binary2my_decimal(E_DEC_FATAL_ERROR,
                    field->ptr, &dec_field, f_precision, f_scale);
  int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
1949 1950
  my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_field, &dec_count, 4);
  return dec_buf;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1951 1952
}

1953

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1954 1955
String *Item_avg_field::val_str(String *str)
{
1956
  // fix_fields() never calls for this Item
1957
  if (hybrid_type == DECIMAL_RESULT)
1958 1959
    return val_string_from_decimal(str);
  return val_string_from_real(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1960 1961
}

1962

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1963
Item_std_field::Item_std_field(Item_sum_std *item)
1964 1965 1966 1967
  : Item_variance_field(item)
{
}

1968

1969
double Item_std_field::val_real()
1970
{
1971
  double nr;
1972
  // fix_fields() never calls for this Item
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991
  if (hybrid_type == REAL_RESULT)
  {
    /*
      We can't call Item_variance_field::val_real() on a DECIMAL_RESULT
      as this would call Item_std_field::val_decimal() and we would
      calculate sqrt() twice
    */
    nr= Item_variance_field::val_real();
  }
  else
  {
    my_decimal dec_buf,*dec;
    dec= Item_variance_field::val_decimal(&dec_buf);
    if (!dec)
      nr= 0.0;                                  // NULL; Return 0.0
    else
      my_decimal2double(E_DEC_FATAL_ERROR, dec, &nr);
  }
  return nr <= 0.0 ? 0.0 : sqrt(nr);
1992 1993
}

1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015

my_decimal *Item_std_field::val_decimal(my_decimal *dec_buf)
{
  /*
    We can't call val_decimal_from_real() for DECIMAL_RESULT as
    Item_variance_field::val_real() would cause an infinite loop
  */
  my_decimal tmp_dec, *dec;
  double nr;
  if (hybrid_type == REAL_RESULT)
    return val_decimal_from_real(dec_buf);
  dec= Item_variance_field::val_decimal(dec_buf);
  if (!dec)
    return 0;
  my_decimal2double(E_DEC_FATAL_ERROR, dec, &nr);
  nr= nr <= 0.0 ? 0.0 : sqrt(nr);
  double2my_decimal(E_DEC_FATAL_ERROR, nr, &tmp_dec);
  my_decimal_round(E_DEC_FATAL_ERROR, &tmp_dec, decimals, FALSE, dec_buf);
  return dec_buf;
}


2016
Item_variance_field::Item_variance_field(Item_sum_variance *item)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2017 2018 2019 2020 2021 2022
{
  name=item->name;
  decimals=item->decimals;
  max_length=item->max_length;
  field=item->result_field;
  maybe_null=1;
2023
  sample= item->sample;
2024 2025 2026 2027 2028 2029 2030 2031 2032
  if ((hybrid_type= item->hybrid_type) == DECIMAL_RESULT)
  {
    f_scale0= item->f_scale0;
    f_precision0= item->f_precision0;
    dec_bin_size0= item->dec_bin_size0;
    f_scale1= item->f_scale1;
    f_precision1= item->f_precision1;
    dec_bin_size1= item->dec_bin_size1;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2033 2034
}

2035

2036
double Item_variance_field::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2037
{
2038
  // fix_fields() never calls for this Item
2039
  if (hybrid_type == DECIMAL_RESULT)
2040 2041
    return val_real_from_decimal();

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2042 2043 2044 2045 2046 2047
  double sum,sum_sqr;
  longlong count;
  float8get(sum,field->ptr);
  float8get(sum_sqr,(field->ptr+sizeof(double)));
  count=sint8korr(field->ptr+sizeof(double)*2);

2048
  if ((null_value= (count <= sample)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2049
    return 0.0;
2050

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2051
  double tmp= (double) count;
2052
  double tmp2= (sum_sqr - sum*sum/tmp)/(tmp - (double)sample);
2053
  return tmp2 <= 0.0 ? 0.0 : tmp2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2054 2055
}

2056

2057
String *Item_variance_field::val_str(String *str)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2058
{
2059 2060 2061
  if (hybrid_type == DECIMAL_RESULT)
    return val_string_from_decimal(str);
  return val_string_from_real(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2062 2063
}

2064 2065 2066 2067

my_decimal *Item_variance_field::val_decimal(my_decimal *dec_buf)
{
  // fix_fields() never calls for this Item
2068 2069 2070
  if (hybrid_type == REAL_RESULT)
    return val_decimal_from_real(dec_buf);

2071
  longlong count= sint8korr(field->ptr+dec_bin_size0+dec_bin_size1);
2072
  if ((null_value= (count <= sample)))
2073 2074
    return 0;

2075
  my_decimal dec_count, dec1_count, dec_sum, dec_sqr, tmp;
2076
  int2my_decimal(E_DEC_FATAL_ERROR, count, 0, &dec_count);
2077
  int2my_decimal(E_DEC_FATAL_ERROR, count-sample, 0, &dec1_count);
2078 2079 2080 2081 2082 2083 2084
  binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr,
                    &dec_sum, f_precision0, f_scale0);
  binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr+dec_bin_size0,
                    &dec_sqr, f_precision1, f_scale1);
  my_decimal_mul(E_DEC_FATAL_ERROR, &tmp, &dec_sum, &dec_sum);
  my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &tmp, &dec_count, 2);
  my_decimal_sub(E_DEC_FATAL_ERROR, &dec_sum, &dec_sqr, dec_buf);
2085
  my_decimal_div(E_DEC_FATAL_ERROR, dec_buf, &dec_sum, &dec1_count, 2);
2086 2087 2088 2089
  return dec_buf;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2090 2091 2092 2093
/****************************************************************************
** COUNT(DISTINCT ...)
****************************************************************************/

2094
int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
2095
{
2096 2097 2098
  Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
  CHARSET_INFO *cs=item->key_charset;
  uint len=item->key_length;
bar@bar.mysql.r18.ru's avatar
Fix:  
bar@bar.mysql.r18.ru committed
2099 2100
  return cs->coll->strnncollsp(cs, 
			       (const uchar*) key1, len, 
2101
			       (const uchar*) key2, len, 0);
2102 2103
}

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2104 2105 2106 2107 2108 2109 2110
/*
  Did not make this one static - at least gcc gets confused when
  I try to declare a static function as a friend. If you can figure
  out the syntax to make a static function a friend, make this one
  static
*/

2111 2112 2113
int composite_key_cmp(void* arg, byte* key1, byte* key2)
{
  Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2114
  Field **field    = item->table->field;
2115
  Field **field_end= field + item->table->s->fields;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2116 2117 2118 2119 2120
  uint32 *lengths=item->field_lengths;
  for (; field < field_end; ++field)
  {
    Field* f = *field;
    int len = *lengths++;
2121
    int res = f->cmp((char *) key1, (char *) key2);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2122 2123 2124 2125 2126
    if (res)
      return res;
    key1 += len;
    key2 += len;
  }
2127 2128 2129
  return 0;
}

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2130 2131 2132 2133
/*
  helper function for walking the tree when we dump it to MyISAM -
  tree_walk will call it for each leaf
*/
2134

2135 2136 2137
int dump_leaf(byte* key, uint32 count __attribute__((unused)),
		     Item_sum_count_distinct* item)
{
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2138
  byte* buf = item->table->record[0];
2139
  int error;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2140 2141
  /*
    The first item->rec_offset bytes are taken care of with
2142
    restore_record(table,default_values) in setup()
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2143
  */
2144
  memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
2145 2146
  if ((error = item->table->file->write_row(buf)))
  {
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2147 2148 2149
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
      return 1;
2150 2151 2152
  }
  return 0;
}
2153

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2154

hf@deer.(none)'s avatar
hf@deer.(none) committed
2155
void Item_sum_count_distinct::cleanup()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2156
{
2157
  DBUG_ENTER("Item_sum_count_distinct::cleanup");
hf@deer.(none)'s avatar
hf@deer.(none) committed
2158
  Item_sum_int::cleanup();
2159 2160 2161 2162
  /*
    Free table and tree if they belong to this item (if item have not pointer
    to original item from which was made copy => it own its objects )
  */
2163 2164 2165
  if (!original)
  {
    if (table)
2166
    {
2167
      free_tmp_table(current_thd, table);
2168 2169
      table= 0;
    }
2170
    delete tmp_table_param;
2171
    tmp_table_param= 0;
2172
    if (use_tree)
2173
    {
2174
      delete_tree(tree);
2175 2176
      use_tree= 0;
    }
2177
  }
2178
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2179 2180
}

2181

2182 2183 2184 2185 2186 2187
/* This is used by rollup to create a separate usable copy of the function */

void Item_sum_count_distinct::make_unique()
{
  table=0;
  original= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2188
  use_tree= 0; // to prevent delete_tree call on uninitialized tree
2189 2190 2191 2192
  tree= &tree_base;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2193 2194 2195
bool Item_sum_count_distinct::setup(THD *thd)
{
  List<Item> list;
pem@mysql.com's avatar
pem@mysql.com committed
2196
  SELECT_LEX *select_lex= thd->lex->current_select;
2197 2198 2199
  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
    return 1;
    
2200 2201 2202
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
    return 1;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2203 2204
  /* Create a table with an unique key over all parameters */
  for (uint i=0; i < arg_count ; i++)
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
  {
    Item *item=args[i];
    if (list.push_back(item))
      return 1;					// End of memory
    if (item->const_item())
    {
      (void) item->val_int();
      if (item->null_value)
	always_null=1;
    }
  }
  if (always_null)
    return 0;
2218
  count_field_types(tmp_table_param,list,0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2219 2220 2221 2222 2223
  if (table)
  {
    free_tmp_table(thd, table);
    tmp_table_param->cleanup();
  }
2224
  if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2225
				0,
2226
				select_lex->options | thd->options,
2227
				HA_POS_ERROR, (char*)"")))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2228 2229
    return 1;
  table->file->extra(HA_EXTRA_NO_ROWS);		// Don't update rows
2230
  table->no_rows=1;
2231

monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2232

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2233
  // no blobs, otherwise it would be MyISAM
2234
  if (table->s->db_type == DB_TYPE_HEAP)
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2235 2236 2237
  {
    qsort_cmp2 compare_key;
    void* cmp_arg;
2238

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2239
    // to make things easier for dump_leaf if we ever have to dump to MyISAM
2240
    restore_record(table,s->default_values);
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2241

2242
    if (table->s->fields == 1)
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2243 2244 2245 2246 2247 2248 2249 2250
    {
      /*
	If we have only one field, which is the most common use of
	count(distinct), it is much faster to use a simpler key
	compare method that can take advantage of not having to worry
	about other fields
      */
      Field* field = table->field[0];
2251 2252 2253
      switch (field->type()) {
      case MYSQL_TYPE_STRING:
      case MYSQL_TYPE_VAR_STRING:
2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
	if (field->binary())
	{
	  compare_key = (qsort_cmp2)simple_raw_key_cmp;
	  cmp_arg = (void*) &key_length;
	}
	else
	{
	  /*
	    If we have a string, we must take care of charsets and case
	    sensitivity
	  */
	  compare_key = (qsort_cmp2)simple_str_key_cmp;
	  cmp_arg = (void*) this;
	}
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2268 2269 2270 2271 2272 2273 2274
	break;
      default:
	/*
	  Since at this point we cannot have blobs anything else can
	  be compared with memcmp
	*/
	compare_key = (qsort_cmp2)simple_raw_key_cmp;
2275
	cmp_arg = (void*) &key_length;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2276 2277
	break;
      }
2278 2279 2280
      key_charset = field->charset();
      key_length  = field->pack_length();
      rec_offset  = 1;
2281
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2282 2283 2284 2285
    else // too bad, cannot cheat - there is more than one field
    {
      bool all_binary = 1;
      Field** field, **field_end;
2286
      field_end = (field = table->field) + table->s->fields;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2287 2288
      uint32 *lengths;
      if (!(field_lengths= 
2289
	    (uint32*) thd->alloc(sizeof(uint32) * table->s->fields)))
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2290 2291
	return 1;

2292
      for (key_length = 0, lengths=field_lengths; field < field_end; ++field)
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2293 2294
      {
	uint32 length= (*field)->pack_length();
2295
	key_length += length;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2296 2297 2298 2299
	*lengths++ = length;
	if (!(*field)->binary())
	  all_binary = 0;			// Can't break loop here
      }
2300
      rec_offset= table->s->reclength - key_length;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2301 2302 2303
      if (all_binary)
      {
	compare_key = (qsort_cmp2)simple_raw_key_cmp;
2304
	cmp_arg = (void*) &key_length;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2305 2306 2307 2308
      }
      else
      {
	compare_key = (qsort_cmp2) composite_key_cmp ;
2309
	cmp_arg = (void*) this;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2310 2311 2312
      }
    }

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2313 2314
    if (use_tree)
      delete_tree(tree);
2315 2316
    init_tree(tree, min(thd->variables.max_heap_table_size,
			thd->variables.sortbuff_size/16), 0,
2317
	      key_length, compare_key, 0, NULL, cmp_arg);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2318 2319 2320
    use_tree = 1;

    /*
2321
      The only time key_length could be 0 is if someone does
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2322 2323 2324 2325
      count(distinct) on a char(0) field - stupid thing to do,
      but this has to be handled - otherwise someone can crash
      the server with a DoS attack
    */
2326 2327
    max_elements_in_tree = ((key_length) ? 
			    thd->variables.max_heap_table_size/key_length : 1);
2328 2329 2330 2331 2332 2333

  }
  if (original)
  {
    original->table= table;
    original->use_tree= use_tree;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2334
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2335 2336 2337
  return 0;
}

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2338

2339 2340
int Item_sum_count_distinct::tree_to_myisam()
{
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2341
  if (create_myisam_from_heap(current_thd, table, tmp_table_param,
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2342
			      HA_ERR_RECORD_FILE_FULL, 1) ||
2343
      tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2344
		left_root_right))
2345
    return 1;
2346
  delete_tree(tree);
2347 2348 2349
  use_tree = 0;
  return 0;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2350

2351 2352 2353

Item *Item_sum_count_distinct::copy_or_same(THD* thd) 
{
2354
  return new (thd->mem_root) Item_sum_count_distinct(thd, this);
2355 2356 2357
}


2358
void Item_sum_count_distinct::clear()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2359
{
monty@work.mysql.com's avatar
merge  
monty@work.mysql.com committed
2360
  if (use_tree)
2361
    reset_tree(tree);
monty@work.mysql.com's avatar
merge  
monty@work.mysql.com committed
2362
  else if (table)
2363 2364 2365 2366 2367
  {
    table->file->extra(HA_EXTRA_NO_CACHE);
    table->file->delete_all_rows();
    table->file->extra(HA_EXTRA_WRITE_CACHE);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2368 2369 2370 2371 2372
}

bool Item_sum_count_distinct::add()
{
  int error;
2373 2374
  if (always_null)
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2375
  copy_fields(tmp_table_param);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2376
  copy_funcs(tmp_table_param->items_to_copy);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2377

2378 2379 2380 2381
  for (Field **field=table->field ; *field ; field++)
    if ((*field)->is_real_null(0))
      return 0;					// Don't count NULL

monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2382 2383 2384 2385 2386 2387
  if (use_tree)
  {
    /*
      If the tree got too big, convert to MyISAM, otherwise insert into the
      tree.
    */
2388
    if (tree->elements_in_tree > max_elements_in_tree)
2389
    {
2390
      if (tree_to_myisam())
2391 2392
	return 1;
    }
2393 2394
    else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
			  tree->custom_arg))
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2395 2396
      return 1;
  }
2397
  else if ((error=table->file->write_row(table->record[0])))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2398 2399 2400 2401
  {
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
    {
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2402 2403
      if (create_myisam_from_heap(current_thd, table, tmp_table_param, error,
				  1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2404 2405 2406 2407 2408 2409
	return 1;				// Not a table_is_full error
    }
  }
  return 0;
}

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2410

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2411 2412
longlong Item_sum_count_distinct::val_int()
{
2413
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2414 2415
  if (!table)					// Empty query
    return LL(0);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2416
  if (use_tree)
2417
    return tree->elements_in_tree;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2418 2419 2420 2421
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  return table->file->records;
}

2422 2423 2424

void Item_sum_count_distinct::print(String *str)
{
2425
  str->append("count(distinct ", 15);
2426 2427 2428 2429
  args[0]->print(str);
  str->append(')');
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2430 2431 2432 2433 2434 2435 2436 2437 2438
/****************************************************************************
** Functions to handle dynamic loadable aggregates
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
** Adapted for UDAs by: Andreas F. Bobak <bobak@relog.ch>.
** Rewritten by: Monty.
****************************************************************************/

#ifdef HAVE_DLOPEN

2439
void Item_udf_sum::clear()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2440
{
2441
  DBUG_ENTER("Item_udf_sum::clear");
2442
  udf.clear();
2443
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2444 2445 2446 2447
}

bool Item_udf_sum::add()
{
2448
  DBUG_ENTER("Item_udf_sum::add");
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2449 2450 2451 2452
  udf.add(&null_value);
  DBUG_RETURN(0);
}

2453 2454
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
2455
  return new (thd->mem_root) Item_sum_udf_float(thd, this);
2456 2457
}

2458
double Item_sum_udf_float::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2459
{
2460
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2461 2462 2463 2464 2465 2466
  DBUG_ENTER("Item_sum_udf_float::val");
  DBUG_PRINT("info",("result_type: %d  arg_count: %d",
		     args[0]->result_type(), arg_count));
  DBUG_RETURN(udf.val(&null_value));
}

2467

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2468 2469
String *Item_sum_udf_float::val_str(String *str)
{
2470
  return val_string_from_real(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2471 2472 2473
}


2474
my_decimal *Item_sum_udf_float::val_decimal(my_decimal *dec)
2475
{
2476
  return val_decimal_from_real(dec);
2477 2478 2479
}


2480 2481
String *Item_sum_udf_decimal::val_str(String *str)
{
2482
  return val_string_from_decimal(str);
2483 2484 2485 2486 2487
}


double Item_sum_udf_decimal::val_real()
{
2488
  return val_real_from_decimal();
2489 2490 2491 2492 2493
}


longlong Item_sum_udf_decimal::val_int()
{
2494
  return val_int_from_decimal();
2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
}


my_decimal *Item_sum_udf_decimal::val_decimal(my_decimal *dec_buf)
{
  DBUG_ASSERT(fixed == 1);
  DBUG_ENTER("Item_func_udf_decimal::val_decimal");
  DBUG_PRINT("info",("result_type: %d  arg_count: %d",
                     args[0]->result_type(), arg_count));

  DBUG_RETURN(udf.val_decimal(&null_value, dec_buf));
}


Item *Item_sum_udf_decimal::copy_or_same(THD* thd)
{
  return new (thd->mem_root) Item_sum_udf_decimal(thd, this);
}


2515 2516 2517 2518 2519
Item *Item_sum_udf_int::copy_or_same(THD* thd)
{
  return new (thd->mem_root) Item_sum_udf_int(thd, this);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2520 2521
longlong Item_sum_udf_int::val_int()
{
2522
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2523 2524 2525 2526 2527 2528
  DBUG_ENTER("Item_sum_udf_int::val_int");
  DBUG_PRINT("info",("result_type: %d  arg_count: %d",
		     args[0]->result_type(), arg_count));
  DBUG_RETURN(udf.val_int(&null_value));
}

2529

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2530 2531
String *Item_sum_udf_int::val_str(String *str)
{
2532
  return val_string_from_int(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2533 2534
}

2535 2536 2537 2538 2539 2540
my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec)
{
  return val_decimal_from_int(dec);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551
/* Default max_length is max argument length */

void Item_sum_udf_str::fix_length_and_dec()
{
  DBUG_ENTER("Item_sum_udf_str::fix_length_and_dec");
  max_length=0;
  for (uint i = 0; i < arg_count; i++)
    set_if_bigger(max_length,args[i]->max_length);
  DBUG_VOID_RETURN;
}

2552 2553 2554

Item *Item_sum_udf_str::copy_or_same(THD* thd)
{
2555
  return new (thd->mem_root) Item_sum_udf_str(thd, this);
2556 2557 2558
}


2559 2560 2561 2562 2563
my_decimal *Item_sum_udf_str::val_decimal(my_decimal *dec)
{
  return val_decimal_from_string(dec);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2564 2565
String *Item_sum_udf_str::val_str(String *str)
{
2566
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2567 2568 2569 2570 2571 2572 2573
  DBUG_ENTER("Item_sum_udf_str::str");
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  DBUG_RETURN(res);
}

#endif /* HAVE_DLOPEN */
2574 2575 2576 2577


/*****************************************************************************
 GROUP_CONCAT function
2578 2579 2580 2581 2582

 SQL SYNTAX:
  GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...] 
    [SEPARATOR str_const])

2583
 concat of values from "group by" operation
2584 2585 2586 2587 2588

 BUGS
   DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields
   in expression list
   Blobs doesn't work with DISTINCT or ORDER BY
2589 2590 2591
*****************************************************************************/

/*
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2592 2593
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,...)
2594 2595
*/

wax@kishkin.ru's avatar
wax@kishkin.ru committed
2596 2597
int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
				       byte* key2)
2598
{
monty@mysql.com's avatar
monty@mysql.com committed
2599
  Item_func_group_concat* grp_item= (Item_func_group_concat*)arg;
2600
  Item **field_item, **end;
monty@mysql.com's avatar
monty@mysql.com committed
2601
  char *record= (char*) grp_item->table->record[0];
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2602

monty@mysql.com's avatar
monty@mysql.com committed
2603
  for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field;
2604 2605
       field_item < end;
       field_item++)
2606
  {
monty@mysql.com's avatar
monty@mysql.com committed
2607 2608 2609 2610 2611 2612
    /*
      We have to use get_tmp_table_field() instead of
      real_item()->get_tmp_table_field() because we want the field in
      the temporary table, not the original field
    */
    Field *field= (*field_item)->get_tmp_table_field();
2613 2614
    if (field)
    {
2615
      int res;
monty@mysql.com's avatar
monty@mysql.com committed
2616
      uint offset= (uint) (field->ptr - record);
2617
      if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
2618
	return res;
2619
    }
2620
  }
2621 2622 2623
  return 0;
}

2624

2625
/*
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2626 2627
  function of sort for syntax:
  GROUP_CONCAT(expr,... ORDER BY col,... )
2628 2629
*/

wax@kishkin.ru's avatar
wax@kishkin.ru committed
2630
int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
2631
{
monty@mysql.com's avatar
monty@mysql.com committed
2632
  Item_func_group_concat* grp_item= (Item_func_group_concat*) arg;
2633
  ORDER **order_item, **end;
monty@mysql.com's avatar
monty@mysql.com committed
2634
  char *record= (char*) grp_item->table->record[0];
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2635

monty@mysql.com's avatar
monty@mysql.com committed
2636
  for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order;
2637 2638
       order_item < end;
       order_item++)
2639
  {
2640
    Item *item= *(*order_item)->item;
monty@mysql.com's avatar
monty@mysql.com committed
2641 2642 2643 2644 2645 2646
    /*
      We have to use get_tmp_table_field() instead of
      real_item()->get_tmp_table_field() because we want the field in
      the temporary table, not the original field
    */
    Field *field= item->get_tmp_table_field();
2647 2648
    if (field)
    {
monty@mysql.com's avatar
monty@mysql.com committed
2649 2650
      int res;
      uint offset= (uint) (field->ptr - record);
2651
      if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset)))
2652
        return (*order_item)->asc ? res : -res;
2653
    }
2654
  }
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2655
  /*
monty@mysql.com's avatar
monty@mysql.com committed
2656 2657 2658 2659
    We can't return 0 because in that case the tree class would remove this
    item as double value. This would cause problems for case-changes and
    if the the returned values are not the same we do the sort on.
  */
2660 2661 2662
  return 1;
}

2663

2664
/*
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2665 2666
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
2667 2668 2669 2670 2671

  BUG:
    This doesn't work in the case when the order by contains data that
    is not part of the field list because tree-insert will not notice
    the duplicated values when inserting things sorted by ORDER BY
2672
*/
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2673

wax@kishkin.ru's avatar
wax@kishkin.ru committed
2674 2675
int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
						 byte* key2)
2676 2677 2678 2679 2680 2681
{
  if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
    return 0;
  return(group_concat_key_cmp_with_order(arg,key1,key2));
}

2682

2683
/*
2684
  Append data from current leaf to item->result
2685
*/
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2686

wax@kishkin.ru's avatar
wax@kishkin.ru committed
2687
int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
2688
                  Item_func_group_concat *item)
2689 2690
{
  char buff[MAX_FIELD_WIDTH];
2691
  String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
monty@mysql.com's avatar
monty@mysql.com committed
2692 2693
  char *record= (char*) item->table->record[0];

ram@gw.mysql.r18.ru's avatar
a fix  
ram@gw.mysql.r18.ru committed
2694 2695 2696
  if (item->result.length())
    item->result.append(*item->separator);

2697 2698
  tmp.length(0);
  
2699
  for (uint i= 0; i < item->arg_count_field; i++)
2700
  {
2701
    Item *show_item= item->args[i];
2702 2703
    if (!show_item->const_item())
    {
monty@mysql.com's avatar
monty@mysql.com committed
2704 2705 2706 2707 2708 2709 2710 2711 2712
      /*
	We have to use get_tmp_table_field() instead of
	real_item()->get_tmp_table_field() because we want the field in
	the temporary table, not the original field
      */
      Field *field= show_item->get_tmp_table_field();
      String *res;
      char *save_ptr= field->ptr;
      uint offset= (uint) (save_ptr - record);
2713
      DBUG_ASSERT(offset < item->table->s->reclength);
monty@mysql.com's avatar
monty@mysql.com committed
2714 2715
      field->ptr= (char *) key + offset;
      res= field->val_str(&tmp,&tmp2);
2716
      item->result.append(*res);
monty@mysql.com's avatar
monty@mysql.com committed
2717
      field->ptr= save_ptr;
2718 2719 2720
    }
    else 
    {
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2721
      String *res= show_item->val_str(&tmp);
2722
      if (res)
2723
        item->result.append(*res);
2724 2725
    }
  }
2726 2727 2728

  /* stop if length of result more than group_concat_max_len */  
  if (item->result.length() > item->group_concat_max_len)
2729
  {
2730 2731 2732
    item->count_cut_values++;
    item->result.length(item->group_concat_max_len);
    item->warning_for_row= TRUE;
2733 2734 2735 2736 2737
    return 1;
  }
  return 0;
}

2738

2739
/*
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2740 2741 2742 2743 2744
  Constructor of Item_func_group_concat
  is_distinct - distinct
  is_select - list of expression for show values
  is_order - list of sort columns 
  is_separator - string value of separator
2745
*/
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2746

2747
Item_func_group_concat::Item_func_group_concat(bool is_distinct,
2748 2749 2750
					       List<Item> *is_select,
					       SQL_LIST *is_order,
					       String *is_separator)
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2751
  :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
2752
   key_length(0), tree_mode(0), distinct(is_distinct), warning_for_row(0),
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2753
   separator(is_separator), tree(&tree_base), table(0),
2754
   order(0), tables_list(0),
ram@gw.mysql.r18.ru's avatar
a fix  
ram@gw.mysql.r18.ru committed
2755
   arg_count_order(0), arg_count_field(0),
2756
   count_cut_values(0)
2757
{
2758 2759 2760
  Item *item_select;
  Item **arg_ptr;

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2761 2762
  original= 0;
  quick_group= 0;
2763
  mark_as_sum_func();
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2764
  order= 0;
2765
  group_concat_max_len= current_thd->variables.group_concat_max_len;
2766
    
2767
  arg_count_field= is_select->elements;
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2768
  arg_count_order= is_order ? is_order->elements : 0;
2769
  arg_count= arg_count_field + arg_count_order;
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2770 2771 2772
  
  /*
    We need to allocate:
2773 2774
    args - arg_count_field+arg_count_order
           (for possible order items in temporare tables)
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2775 2776
    order - arg_count_order
  */
monty@mysql.com's avatar
monty@mysql.com committed
2777
  if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
2778
				 sizeof(ORDER*)*arg_count_order)))
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2779
    return;
2780

2781 2782
  order= (ORDER**)(args + arg_count);

2783
  /* fill args items of show and sort */
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2784
  List_iterator_fast<Item> li(*is_select);
2785

2786 2787
  for (arg_ptr=args ; (item_select= li++) ; arg_ptr++)
    *arg_ptr= item_select;
2788 2789

  if (arg_count_order) 
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2790
  {
2791
    ORDER **order_ptr= order;
2792
    for (ORDER *order_item= (ORDER*) is_order->first;
2793 2794
	 order_item != NULL;
	 order_item= order_item->next)
2795
    {
2796 2797 2798
      (*order_ptr++)= order_item;
      *arg_ptr= *order_item->item;
      order_item->item= arg_ptr++;
2799 2800 2801
    }
  }
}
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828
  

Item_func_group_concat::Item_func_group_concat(THD *thd,
					       Item_func_group_concat *item)
  :Item_sum(thd, item),item_thd(thd),
  tmp_table_param(item->tmp_table_param),
  max_elements_in_tree(item->max_elements_in_tree),
  warning(item->warning),
  key_length(item->key_length), 
  tree_mode(item->tree_mode),
  distinct(item->distinct),
  warning_for_row(item->warning_for_row),
  separator(item->separator),
  tree(item->tree),
  table(item->table),
  order(item->order),
  tables_list(item->tables_list),
  group_concat_max_len(item->group_concat_max_len),
  arg_count_order(item->arg_count_order),
  arg_count_field(item->arg_count_field),
  field_list_offset(item->field_list_offset),
  count_cut_values(item->count_cut_values),
  original(item)
{
  quick_group= item->quick_group;
}

2829

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2830

hf@deer.(none)'s avatar
hf@deer.(none) committed
2831 2832
void Item_func_group_concat::cleanup()
{
2833
  DBUG_ENTER("Item_func_group_concat::cleanup");
2834
  Item_sum::cleanup();
2835

hf@deer.(none)'s avatar
hf@deer.(none) committed
2836 2837 2838 2839 2840 2841 2842 2843
  /*
    Free table and tree if they belong to this item (if item have not pointer
    to original item from which was made copy => it own its objects )
  */
  if (!original)
  {
    THD *thd= current_thd;
    if (table)
2844
    {
hf@deer.(none)'s avatar
hf@deer.(none) committed
2845
      free_tmp_table(thd, table);
2846 2847
      table= 0;
    }
hf@deer.(none)'s avatar
hf@deer.(none) committed
2848
    delete tmp_table_param;
2849
    tmp_table_param= 0;
hf@deer.(none)'s avatar
hf@deer.(none) committed
2850
    if (tree_mode)
2851 2852
    {
      tree_mode= 0;
hf@deer.(none)'s avatar
hf@deer.(none) committed
2853
      delete_tree(tree); 
2854
    }
2855 2856 2857 2858 2859 2860 2861
    if (warning)
    {
      char warn_buff[MYSQL_ERRMSG_SIZE];
      sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
      warning->set_msg(thd, warn_buff);
      warning= 0;
    }
hf@deer.(none)'s avatar
hf@deer.(none) committed
2862
  }
2863
  DBUG_VOID_RETURN;
hf@deer.(none)'s avatar
hf@deer.(none) committed
2864 2865
}

2866

2867 2868 2869 2870 2871
Item_func_group_concat::~Item_func_group_concat()
{
}


2872 2873
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
2874
  return new (thd->mem_root) Item_func_group_concat(thd, this);
2875 2876 2877
}


2878
void Item_func_group_concat::clear()
2879 2880 2881
{
  result.length(0);
  result.copy();
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2882
  null_value= TRUE;
monty@mysql.com's avatar
monty@mysql.com committed
2883
  warning_for_row= FALSE;
2884 2885 2886 2887 2888 2889 2890 2891 2892 2893
  if (table)
  {
    table->file->extra(HA_EXTRA_NO_CACHE);
    table->file->delete_all_rows();
    table->file->extra(HA_EXTRA_WRITE_CACHE);
  }
  if (tree_mode)
    reset_tree(tree);
}

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2894

2895 2896
bool Item_func_group_concat::add()
{
wax@kishkin.ru's avatar
BUG  
wax@kishkin.ru committed
2897 2898
  if (always_null)
    return 0;
2899 2900 2901
  copy_fields(tmp_table_param);
  copy_funcs(tmp_table_param->items_to_copy);

2902
  for (uint i= 0; i < arg_count_field; i++)
2903
  {
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2904
    Item *show_item= args[i];
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2905
    if (!show_item->const_item())
2906
    {
monty@mysql.com's avatar
monty@mysql.com committed
2907 2908 2909 2910
      /*
	Here we use real_item as we want the original field data that should
	be written to table->record[0]
      */
wax@kishkin.ru's avatar
BUG  
wax@kishkin.ru committed
2911
      Field *f= show_item->real_item()->get_tmp_table_field();
monty@mysql.com's avatar
monty@mysql.com committed
2912 2913
      if (f->is_null())
	return 0;				// Skip row if it contains null
2914 2915
    }
  }
monty@mysql.com's avatar
monty@mysql.com committed
2916

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2917
  null_value= FALSE;
2918 2919

  TREE_ELEMENT *el= 0;                          // Only for safety
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2920
  if (tree_mode)
2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931
    el= tree_insert(tree, table->record[0], 0, tree->custom_arg);
  /*
    If the row is not a duplicate (el->count == 1)
    we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
    instead of doing tree traverse later.
  */
  if (result.length() <= group_concat_max_len && 
      !warning_for_row &&
      (!tree_mode || (el->count == 1 && distinct && !arg_count_order)))
    dump_leaf_key(table->record[0], 1, this);

2932 2933 2934
  return 0;
}

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2935

2936 2937 2938 2939 2940 2941
void Item_func_group_concat::reset_field()
{
  if (tree_mode)
    reset_tree(tree);
}

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2942

2943 2944 2945
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
monty@mysql.com's avatar
monty@mysql.com committed
2946
  uint i;			/* for loop variable */ 
2947
  DBUG_ASSERT(fixed == 0);
2948

2949 2950
  if (!thd->allow_sum_func)
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2951 2952
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
2953
    return TRUE;
2954 2955
  }
  
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2956 2957
  thd->allow_sum_func= 0;
  maybe_null= 0;
2958
  item_thd= thd;
2959

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2960
  /*
2961
    Fix fields for select list and ORDER clause
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2962
  */
2963

wax@kishkin.ru's avatar
wax@kishkin.ru committed
2964
  for (i=0 ; i < arg_count ; i++)  
2965
  {
2966
    if ((!args[i]->fixed &&
2967 2968
         args[i]->fix_fields(thd, tables, args + i)) ||
        args[i]->check_cols(1))
2969
      return TRUE;
wax@kishkin.ru's avatar
wax@kishkin.ru committed
2970
    if (i < arg_count_field)
monty@mysql.com's avatar
monty@mysql.com committed
2971
      maybe_null|= args[i]->maybe_null;
2972
  }
2973

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2974 2975
  result_field= 0;
  null_value= 1;
2976
  max_length= group_concat_max_len;
2977
  thd->allow_sum_func= 1;
2978
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
2979
    return TRUE;
2980 2981
  /* We'll convert all blobs to varchar fields in the temporary table */
  tmp_table_param->convert_blob_length= group_concat_max_len;
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2982
  tables_list= tables;
2983
  fixed= 1;
2984
  return FALSE;
2985 2986
}

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2987

2988 2989 2990
bool Item_func_group_concat::setup(THD *thd)
{
  List<Item> list;
pem@mysql.com's avatar
pem@mysql.com committed
2991
  SELECT_LEX *select_lex= thd->lex->current_select;
monty@mysql.com's avatar
monty@mysql.com committed
2992
  uint const_fields;
2993 2994
  qsort_cmp2 compare_key;
  DBUG_ENTER("Item_func_group_concat::setup");
2995 2996

  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
2997
    DBUG_RETURN(1);
2998

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
2999
  /*
konstantin@oak.local's avatar
konstantin@oak.local committed
3000
    push all not constant fields to list and create temp table
3001
  */
3002
  const_fields= 0;
wax@kishkin.ru's avatar
BUG  
wax@kishkin.ru committed
3003
  always_null= 0;
3004
  for (uint i= 0; i < arg_count_field; i++)
3005
  {
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3006
    Item *item= args[i];
3007
    if (list.push_back(item))
3008
      DBUG_RETURN(1);
3009 3010
    if (item->const_item())
    {
3011
      const_fields++;
3012 3013
      (void) item->val_int();
      if (item->null_value)
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3014
	always_null= 1;
3015 3016
    }
  }
wax@kishkin.ru's avatar
BUG  
wax@kishkin.ru committed
3017
  if (always_null)
3018
    DBUG_RETURN(0);
3019

3020
  List<Item> all_fields(list);
3021
  if (arg_count_order)
3022 3023 3024 3025 3026
  {
    bool hidden_group_fields;
    setup_group(thd, args, tables_list, list, all_fields, *order,
                &hidden_group_fields);
  }
3027

3028
  count_field_types(tmp_table_param,all_fields,0);
3029 3030
  if (table)
  {
3031 3032 3033 3034
    /*
      We come here when we are getting the result from a temporary table,
      not the original tables used in the query
    */
3035 3036 3037
    free_tmp_table(thd, table);
    tmp_table_param->cleanup();
  }
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3038
  /*
3039
    We have to create a temporary table to get descriptions of fields 
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3040
    (types, sizes and so on).
3041 3042 3043

    Note that in the table, we first have the ORDER BY fields, then the
    field list.
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3044 3045 3046

    We need to set set_sum_field in true for storing value of blob in buffer 
    of a record instead of a pointer of one. 
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3047
  */
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3048
  if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 
monty@mysql.com's avatar
monty@mysql.com committed
3049 3050
			       (ORDER*) 0, 0, TRUE,
                               select_lex->options | thd->options,
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3051
			       HA_POS_ERROR,(char *) "")))
3052
    DBUG_RETURN(1);
3053
  table->file->extra(HA_EXTRA_NO_ROWS);
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3054
  table->no_rows= 1;
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3055

3056
  key_length= table->s->reclength;
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3057

3058
  /* Offset to first result field in table */
3059
  field_list_offset= table->s->fields - (list.elements - const_fields);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
3060 3061 3062

  if (tree_mode)
    delete_tree(tree);
3063 3064

  /* choose function of sort */  
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3065
  tree_mode= distinct || arg_count_order; 
3066 3067 3068 3069 3070
  if (tree_mode)
  {
    if (arg_count_order)
    {
      if (distinct)
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3071
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order;
3072
      else
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3073
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_order;
3074 3075 3076
    }
    else
    {
3077
      compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
3078
    }
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3079
    /*
3080 3081
      Create a tree of sort. Tree is used for a sort and a remove double 
      values (according with syntax of the function). If function doesn't
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3082 3083
      contain DISTINCT and ORDER BY clauses, we don't create this tree.
    */
3084
    init_tree(tree, min(thd->variables.max_heap_table_size,
3085
			thd->variables.sortbuff_size/16), 0,
wax@kishkin.ru's avatar
wax@kishkin.ru committed
3086
              key_length, compare_key, 0, NULL, (void*) this);
3087 3088
    max_elements_in_tree= (key_length ? 
			   thd->variables.max_heap_table_size/key_length : 1);
3089 3090
  };

wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3091 3092 3093 3094
  /*
    Copy table and tree_mode if they belong to this item (if item have not 
    pointer to original item from which was made copy => it own its objects)
  */
3095 3096 3097 3098 3099
  if (original)
  {
    original->table= table;
    original->tree_mode= tree_mode;
  }
3100
  DBUG_RETURN(0);
3101 3102
}

3103

3104 3105 3106 3107 3108 3109
/* This is used by rollup to create a separate usable copy of the function */

void Item_func_group_concat::make_unique()
{
  table=0;
  original= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
3110
  tree_mode= 0; // to prevent delete_tree call on uninitialized tree
3111 3112 3113 3114
  tree= &tree_base;
}


3115 3116
String* Item_func_group_concat::val_str(String* str)
{
3117
  DBUG_ASSERT(fixed == 1);
wax@kishkin.ru's avatar
SCRUM  
wax@kishkin.ru committed
3118 3119
  if (null_value)
    return 0;
3120
  if (count_cut_values && !warning)
3121
    warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
3122 3123
                          ER_CUT_VALUE_GROUP_CONCAT,
                          ER(ER_CUT_VALUE_GROUP_CONCAT));
3124 3125
  if (result.length())
    return &result;
3126 3127 3128 3129 3130 3131 3132
  if (tree_mode)
  {
    tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
              left_root_right);
  }
  return &result;
}
3133

3134

3135 3136
void Item_func_group_concat::print(String *str)
{
3137
  str->append("group_concat(", 13);
3138
  if (distinct)
3139
    str->append("distinct ", 9);
3140
  for (uint i= 0; i < arg_count_field; i++)
3141 3142 3143 3144 3145 3146 3147
  {
    if (i)
      str->append(',');
    args[i]->print(str);
  }
  if (arg_count_order)
  {
3148
    str->append(" order by ", 10);
3149 3150 3151 3152 3153 3154 3155
    for (uint i= 0 ; i < arg_count_order ; i++)
    {
      if (i)
	str->append(',');
      (*order[i]->item)->print(str);
    }
  }
3156
  str->append(" separator \'", 12);
3157
  str->append(*separator);
3158
  str->append("\')", 2);
3159
}