item_sum.cc 48.1 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2003 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown 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.
unknown's avatar
unknown committed
7

unknown's avatar
unknown 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.
unknown's avatar
unknown committed
12

unknown's avatar
unknown 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"
unknown's avatar
unknown committed
25

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

    while ((item=li++))
    {
      args[i++]= item;
    }
  }
40
  mark_as_sum_func();
unknown's avatar
unknown committed
41 42 43
  list.empty();					// Fields are used
}

unknown's avatar
unknown committed
44 45 46 47 48

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

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


62
void Item_sum::mark_as_sum_func()
63
{
unknown's avatar
unknown committed
64
  current_thd->lex->current_select->with_sum_func= 1;
unknown's avatar
unknown committed
65
  with_sum_func= 1;
66
}
unknown's avatar
unknown committed
67

68

unknown's avatar
unknown committed
69 70 71 72
void Item_sum::make_field(Send_field *tmp_field)
{
  if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
  {
73 74 75 76
    ((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;
77 78
    if (maybe_null)
      tmp_field->flags&= ~NOT_NULL_FLAG;
unknown's avatar
unknown committed
79
  }
80 81
  else
    init_make_field(tmp_field, field_type());
unknown's avatar
unknown committed
82 83
}

84

unknown's avatar
unknown committed
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
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);
}

106
Item *Item_sum::get_tmp_table_item(THD *thd)
107
{
108
  Item_sum* sum_item= (Item_sum *) copy_or_same(thd);
109 110
  if (sum_item && sum_item->result_field)	   // If not a const sum func
  {
111
    Field *result_field_tmp= sum_item->result_field;
112 113 114 115 116 117
    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)
118
	  ((Item_field*) arg)->field= result_field_tmp++;
119
	else
120
	  sum_item->args[i]= new Item_field(result_field_tmp++);
121 122 123 124 125
      }
    }
  }
  return sum_item;
}
unknown's avatar
unknown committed
126

127 128 129 130 131 132 133 134 135 136 137 138 139 140
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);
}

141

unknown's avatar
unknown committed
142 143 144
String *
Item_sum_num::val_str(String *str)
{
145
  DBUG_ASSERT(fixed == 1);
146
  double nr= val_real();
unknown's avatar
unknown committed
147 148
  if (null_value)
    return 0;
unknown's avatar
unknown committed
149
  str->set(nr,decimals, &my_charset_bin);
unknown's avatar
unknown committed
150 151 152 153 154 155 156
  return str;
}


String *
Item_sum_int::val_str(String *str)
{
157
  DBUG_ASSERT(fixed == 1);
158
  longlong nr= val_int();
unknown's avatar
unknown committed
159 160
  if (null_value)
    return 0;
161
  if (unsigned_flag)
unknown's avatar
unknown committed
162
    str->set((ulonglong) nr, &my_charset_bin);
163
  else
unknown's avatar
unknown committed
164
    str->set(nr, &my_charset_bin);
unknown's avatar
unknown committed
165 166 167 168 169
  return str;
}


bool
unknown's avatar
unknown committed
170
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
171
{
172
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
173

unknown's avatar
unknown committed
174 175
  if (!thd->allow_sum_func)
  {
unknown's avatar
unknown committed
176 177
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
unknown's avatar
unknown committed
178
    return TRUE;
unknown's avatar
unknown committed
179 180 181 182 183 184
  }
  thd->allow_sum_func=0;			// No included group funcs
  decimals=0;
  maybe_null=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
185
    if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
unknown's avatar
unknown committed
186
      return TRUE;
unknown's avatar
unknown committed
187 188 189 190 191 192 193 194 195
    if (decimals < args[i]->decimals)
      decimals=args[i]->decimals;
    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
196
  fixed= 1;
unknown's avatar
unknown committed
197
  return FALSE;
unknown's avatar
unknown committed
198 199 200 201
}


bool
unknown's avatar
unknown committed
202
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
203
{
204
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
205

206
  Item *item= args[0];
unknown's avatar
unknown committed
207 208
  if (!thd->allow_sum_func)
  {
unknown's avatar
unknown committed
209 210
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
unknown's avatar
unknown committed
211
    return TRUE;
unknown's avatar
unknown committed
212 213
  }
  thd->allow_sum_func=0;			// No included group funcs
214 215

  // 'item' can be changed during fix_fields
216
  if (!item->fixed &&
217 218
      item->fix_fields(thd, tables, args) ||
      (item= args[0])->check_cols(1))
unknown's avatar
unknown committed
219
    return TRUE;
220 221

  hybrid_type= item->result_type();
unknown's avatar
unknown committed
222
  if (hybrid_type == INT_RESULT)
223
  {
224
    max_length=20;
225
  }
unknown's avatar
unknown committed
226
  else if (hybrid_type == REAL_RESULT)
227
  {
unknown's avatar
unknown committed
228
    max_length=float_length(decimals);
229
  }else
230
  {
unknown's avatar
unknown committed
231
    max_length=item->max_length;
232
  }
unknown's avatar
unknown committed
233
  decimals=item->decimals;
234 235
  /* MIN/MAX can return NULL for empty set indepedent of the used column */
  maybe_null= 1;
236
  unsigned_flag=item->unsigned_flag;
237
  collation.set(item->collation);
unknown's avatar
unknown committed
238 239 240 241
  result_field=0;
  null_value=1;
  fix_length_and_dec();
  thd->allow_sum_func=1;			// Allow group functions
242 243 244 245
  if (item->type() == Item::FIELD_ITEM)
    hybrid_field_type= ((Item_field*) item)->field->type();
  else
    hybrid_field_type= Item::field_type();
246
  fixed= 1;
unknown's avatar
unknown committed
247
  return FALSE;
unknown's avatar
unknown committed
248 249 250 251 252 253 254
}


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

255
Item *Item_sum_sum::copy_or_same(THD* thd)
unknown's avatar
unknown committed
256
{
unknown's avatar
unknown committed
257
  return new (thd->mem_root) Item_sum_sum(thd, this);
unknown's avatar
unknown committed
258 259
}

260

261
void Item_sum_sum::clear()
262 263 264 265 266
{
  null_value=1; sum=0.0;
}


unknown's avatar
unknown committed
267 268
bool Item_sum_sum::add()
{
269
  sum+= args[0]->val_real();
unknown's avatar
unknown committed
270 271
  if (!args[0]->null_value)
    null_value= 0;
unknown's avatar
unknown committed
272 273 274
  return 0;
}

275

276
double Item_sum_sum::val_real()
unknown's avatar
unknown committed
277
{
278
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
279 280 281 282
  return sum;
}


283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
/* Item_sum_sum_distinct */

Item_sum_sum_distinct::Item_sum_sum_distinct(Item *item)
  :Item_sum_num(item), sum(0.0), tree(0)
{
  /*
    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,
unknown's avatar
unknown committed
299
                                             Item_sum_sum_distinct *original)
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
  :Item_sum_num(thd, original), sum(0.0), tree(0)
{
  quick_group= 0;
}


Item_sum_sum_distinct::~Item_sum_sum_distinct()
{
  delete tree;
}
  

Item *
Item_sum_sum_distinct::copy_or_same(THD *thd)
{
unknown's avatar
unknown committed
315
  return new (thd->mem_root) Item_sum_sum_distinct(thd, this);
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
}

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

bool Item_sum_sum_distinct::setup(THD *thd)
{
  SELECT_LEX *select_lex= thd->lex->current_select;
  /* what does it mean??? */
  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
    return 1;

  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
  */
  static uint key_length= sizeof(double);
  tree= new Unique(simple_raw_key_cmp, &key_length, key_length,
                   thd->variables.max_heap_table_size);
  return tree == 0;
}

void Item_sum_sum_distinct::clear()
{
  DBUG_ASSERT(tree);                            /* we always have a tree */
  null_value= 1; 
  tree->reset();
}

bool Item_sum_sum_distinct::add()
{
361 362
  /* args[0]->val_real() may reset args[0]->null_value */
  double val= args[0]->val_real();
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
  if (!args[0]->null_value)
  {
    DBUG_ASSERT(tree);
    null_value= 0;
    if (val)
      return tree->unique_add(&val);
  }
  return 0;
}

C_MODE_START

static int sum_sum_distinct(void *element, element_count num_of_dups,
                     void *item_sum_sum_distinct)
{ 
  ((Item_sum_sum_distinct *)
   (item_sum_sum_distinct))->add(* (double *) element);
  return 0;
}

C_MODE_END

385
double Item_sum_sum_distinct::val_real()
386 387 388 389 390 391 392 393 394 395 396 397 398
{
  /*
    We don't have a tree only if 'setup()' hasn't been called;
    this is the case of sql_select.cc:return_zero_rows.
  */
  sum= 0.0;
  if (tree) 
    tree->walk(sum_sum_distinct, (void *) this);
  return sum;
}

/* end of Item_sum_sum_distinct */

399
Item *Item_sum_count::copy_or_same(THD* thd)
unknown's avatar
unknown committed
400
{
unknown's avatar
unknown committed
401
  return new (thd->mem_root) Item_sum_count(thd, this);
unknown's avatar
unknown committed
402 403
}

404

405
void Item_sum_count::clear()
406
{
407
  count= 0;
408 409 410
}


unknown's avatar
unknown committed
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
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()
{
426
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
427 428 429
  return (longlong) count;
}

430 431 432 433 434 435 436 437 438 439

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


unknown's avatar
unknown committed
440
/*
441
  Avgerage
unknown's avatar
unknown committed
442 443
*/

444
Item *Item_sum_avg::copy_or_same(THD* thd)
unknown's avatar
unknown committed
445
{
unknown's avatar
unknown committed
446
  return new (thd->mem_root) Item_sum_avg(thd, this);
unknown's avatar
unknown committed
447 448
}

449

450
void Item_sum_avg::clear()
451 452 453 454 455
{
  sum=0.0; count=0;
}


unknown's avatar
unknown committed
456 457
bool Item_sum_avg::add()
{
458
  double nr= args[0]->val_real();
unknown's avatar
unknown committed
459 460 461 462 463 464 465 466
  if (!args[0]->null_value)
  {
    sum+=nr;
    count++;
  }
  return 0;
}

467
double Item_sum_avg::val_real()
unknown's avatar
unknown committed
468
{
469
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
470 471 472 473 474 475 476 477 478 479 480
  if (!count)
  {
    null_value=1;
    return 0.0;
  }
  null_value=0;
  return sum/ulonglong2double(count);
}


/*
481
  Standard deviation
unknown's avatar
unknown committed
482 483
*/

484
double Item_sum_std::val_real()
unknown's avatar
unknown committed
485
{
486
  DBUG_ASSERT(fixed == 1);
487
  double tmp= Item_sum_variance::val_real();
unknown's avatar
unknown committed
488
  return tmp <= 0.0 ? 0.0 : sqrt(tmp);
unknown's avatar
unknown committed
489 490
}

491 492
Item *Item_sum_std::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
493
  return new (thd->mem_root) Item_sum_std(thd, this);
494 495 496
}


unknown's avatar
unknown committed
497
/*
498
  Variance
unknown's avatar
unknown committed
499 500
*/

501 502
Item *Item_sum_variance::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
503
  return new (thd->mem_root) Item_sum_variance(thd, this);
504 505 506
}


507
void Item_sum_variance::clear()
unknown's avatar
unknown committed
508 509 510 511 512 513
{
  sum=sum_sqr=0.0; 
  count=0; 
}

bool Item_sum_variance::add()
unknown's avatar
unknown committed
514
{
515
  double nr= args[0]->val_real();
unknown's avatar
unknown committed
516 517 518 519 520 521 522 523 524
  if (!args[0]->null_value)
  {
    sum+=nr;
    sum_sqr+=nr*nr;
    count++;
  }
  return 0;
}

525
double Item_sum_variance::val_real()
unknown's avatar
unknown committed
526
{
527
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
528 529 530 531 532 533 534 535 536
  if (!count)
  {
    null_value=1;
    return 0.0;
  }
  null_value=0;
  /* Avoid problems when the precision isn't good enough */
  double tmp=ulonglong2double(count);
  double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
unknown's avatar
unknown committed
537
  return tmp2 <= 0.0 ? 0.0 : tmp2;
unknown's avatar
unknown committed
538 539
}

unknown's avatar
unknown committed
540
void Item_sum_variance::reset_field()
unknown's avatar
unknown committed
541
{
542
  double nr= args[0]->val_real();
unknown's avatar
unknown committed
543 544 545 546 547 548 549 550 551 552 553 554 555 556
  char *res=result_field->ptr;

  if (args[0]->null_value)
    bzero(res,sizeof(double)*2+sizeof(longlong));
  else
  {
    float8store(res,nr);
    nr*=nr;
    float8store(res+sizeof(double),nr);
    longlong tmp=1;
    int8store(res+sizeof(double)*2,tmp);
  }
}

unknown's avatar
unknown committed
557
void Item_sum_variance::update_field()
unknown's avatar
unknown committed
558 559 560 561 562
{
  double nr,old_nr,old_sqr;
  longlong field_count;
  char *res=result_field->ptr;

unknown's avatar
unknown committed
563 564 565
  float8get(old_nr, res);
  float8get(old_sqr, res+sizeof(double));
  field_count=sint8korr(res+sizeof(double)*2);
unknown's avatar
unknown committed
566

567
  nr= args[0]->val_real();
unknown's avatar
unknown committed
568 569 570 571 572 573 574 575 576 577 578 579 580
  if (!args[0]->null_value)
  {
    old_nr+=nr;
    old_sqr+=nr*nr;
    field_count++;
  }
  float8store(res,old_nr);
  float8store(res+sizeof(double),old_sqr);
  int8store(res+sizeof(double)*2,field_count);
}

/* min & max */

581 582 583 584 585 586 587 588
void Item_sum_hybrid::clear()
{
  sum= 0.0;
  sum_int= 0;
  value.length(0);
  null_value= 1;
}

589
double Item_sum_hybrid::val_real()
unknown's avatar
unknown committed
590
{
591
  DBUG_ASSERT(fixed == 1);
592
  int err;
unknown's avatar
unknown committed
593 594
  if (null_value)
    return 0.0;
595 596
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
597
    String *res;  res=val_str(&str_value);
598
    return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
599
			     (char**) 0, &err) : 0.0);
600 601 602 603 604 605
  case INT_RESULT:
    if (unsigned_flag)
      return ulonglong2double(sum_int);
    return (double) sum_int;
  case REAL_RESULT:
    return sum;
606
  case ROW_RESULT:
unknown's avatar
unknown committed
607
  default:
unknown's avatar
unknown committed
608 609 610
    // This case should never be choosen
    DBUG_ASSERT(0);
    return 0;
unknown's avatar
unknown committed
611
  }
612 613 614 615 616
  return 0;					// Keep compiler happy
}

longlong Item_sum_hybrid::val_int()
{
617
  DBUG_ASSERT(fixed == 1);
618 619 620 621
  if (null_value)
    return 0;
  if (hybrid_type == INT_RESULT)
    return sum_int;
622
  return (longlong) Item_sum_hybrid::val_real();
unknown's avatar
unknown committed
623 624 625 626 627 628
}


String *
Item_sum_hybrid::val_str(String *str)
{
629
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
630 631
  if (null_value)
    return 0;
632 633
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
634
    return &value;
635
  case REAL_RESULT:
unknown's avatar
unknown committed
636
    str->set(sum,decimals, &my_charset_bin);
637 638 639
    break;
  case INT_RESULT:
    if (unsigned_flag)
unknown's avatar
unknown committed
640
      str->set((ulonglong) sum_int, &my_charset_bin);
641
    else
unknown's avatar
unknown committed
642
      str->set((longlong) sum_int, &my_charset_bin);
643
    break;
644
  case ROW_RESULT:
unknown's avatar
unknown committed
645
  default:
unknown's avatar
unknown committed
646 647 648
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
649 650
  }
  return str;					// Keep compiler happy
unknown's avatar
unknown committed
651 652
}

653

654 655 656 657 658
void Item_sum_hybrid::cleanup()
{
  DBUG_ENTER("Item_sum_hybrid::cleanup");
  Item_sum::cleanup();
  used_table_cache= ~(table_map) 0;
unknown's avatar
unknown committed
659

660
  /*
unknown's avatar
unknown committed
661
    by default it is TRUE to avoid TRUE reporting by
662 663 664
    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.
unknown's avatar
unknown committed
665
    If some results found it will be left unchanged.
666 667
  */
  was_values= TRUE;
668 669 670
  DBUG_VOID_RETURN;
}

671 672 673 674 675 676
void Item_sum_hybrid::no_rows_in_result()
{
  Item_sum::no_rows_in_result();
  was_values= FALSE;
}

677

678 679
Item *Item_sum_min::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
680
  return new (thd->mem_root) Item_sum_min(thd, this);
681 682 683
}


unknown's avatar
unknown committed
684 685
bool Item_sum_min::add()
{
686 687
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
688 689 690
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
691
	(null_value || sortcmp(&value,result,collation.collation) > 0))
unknown's avatar
unknown committed
692 693 694 695 696
    {
      value.copy(*result);
      null_value=0;
    }
  }
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
  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;
  case REAL_RESULT:
unknown's avatar
unknown committed
712
  {
713
    double nr= args[0]->val_real();
714
    if (!args[0]->null_value && (null_value || nr < sum))
unknown's avatar
unknown committed
715 716 717 718 719
    {
      sum=nr;
      null_value=0;
    }
  }
720
  break;
721
  case ROW_RESULT:
unknown's avatar
unknown committed
722
  default:
unknown's avatar
unknown committed
723 724 725
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
726 727 728 729 730
  }
  return 0;
}


731 732
Item *Item_sum_max::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
733
  return new (thd->mem_root) Item_sum_max(thd, this);
734 735 736
}


737 738 739 740
bool Item_sum_max::add()
{
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
741 742 743
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
744
	(null_value || sortcmp(&value,result,collation.collation) < 0))
unknown's avatar
unknown committed
745 746 747 748 749
    {
      value.copy(*result);
      null_value=0;
    }
  }
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
  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;
  case REAL_RESULT:
  {
766
    double nr= args[0]->val_real();
767 768 769 770 771 772 773
    if (!args[0]->null_value && (null_value || nr > sum))
    {
      sum=nr;
      null_value=0;
    }
  }
  break;
774
  case ROW_RESULT:
unknown's avatar
unknown committed
775
  default:
unknown's avatar
unknown committed
776 777 778
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
779
  }
unknown's avatar
unknown committed
780 781 782 783 784 785 786 787
  return 0;
}


/* bit_or and bit_and */

longlong Item_sum_bit::val_int()
{
788
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
789 790 791
  return (longlong) bits;
}

792

793
void Item_sum_bit::clear()
794
{
795
  bits= reset_bits;
796 797 798
}

Item *Item_sum_or::copy_or_same(THD* thd)
unknown's avatar
unknown committed
799
{
unknown's avatar
unknown committed
800
  return new (thd->mem_root) Item_sum_or(thd, this);
unknown's avatar
unknown committed
801 802
}

803

unknown's avatar
unknown committed
804 805 806 807 808 809 810 811
bool Item_sum_or::add()
{
  ulonglong value= (ulonglong) args[0]->val_int();
  if (!args[0]->null_value)
    bits|=value;
  return 0;
}

812 813
Item *Item_sum_xor::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
814
  return new (thd->mem_root) Item_sum_xor(thd, this);
815 816 817 818 819 820 821 822 823 824 825
}


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

826 827
Item *Item_sum_and::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
828
  return new (thd->mem_root) Item_sum_and(thd, this);
829 830 831
}


unknown's avatar
unknown committed
832 833 834 835 836 837 838 839 840 841 842 843 844 845
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()
{
846
  double nr= args[0]->val_real();
unknown's avatar
unknown committed
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
  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()
{
  if (hybrid_type == STRING_RESULT)
  {
    char buff[MAX_FIELD_WIDTH];
868
    String tmp(buff,sizeof(buff),result_field->charset()),*res;
unknown's avatar
unknown committed
869 870 871 872 873 874 875 876 877 878

    res=args[0]->val_str(&tmp);
    if (args[0]->null_value)
    {
      result_field->set_null();
      result_field->reset();
    }
    else
    {
      result_field->set_notnull();
879
      result_field->store(res->ptr(),res->length(),tmp.charset());
unknown's avatar
unknown committed
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899
    }
  }
  else if (hybrid_type == INT_RESULT)
  {
    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);
  }
  else						// REAL_RESULT
  {
900
    double nr= args[0]->val_real();
unknown's avatar
unknown committed
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918

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


void Item_sum_sum::reset_field()
{
919
  double nr= args[0]->val_real();			// Nulls also return 0
unknown's avatar
unknown committed
920
  float8store(result_field->ptr,nr);
unknown's avatar
unknown committed
921 922 923 924
  if (args[0]->null_value)
    result_field->set_null();
  else
    result_field->set_notnull();
unknown's avatar
unknown committed
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
}


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()
{
947
  double nr= args[0]->val_real();
unknown's avatar
unknown committed
948 949 950 951 952 953 954 955 956 957 958 959 960 961
  char *res=result_field->ptr;

  if (args[0]->null_value)
    bzero(res,sizeof(double)+sizeof(longlong));
  else
  {
    float8store(res,nr);
    res+=sizeof(double);
    longlong tmp=1;
    int8store(res,tmp);
  }
}

void Item_sum_bit::reset_field()
unknown's avatar
unknown committed
962
{
963 964
  reset();
  int8store(result_field->ptr, bits);
unknown's avatar
unknown committed
965 966 967
}

void Item_sum_bit::update_field()
unknown's avatar
unknown committed
968 969
{
  char *res=result_field->ptr;
unknown's avatar
unknown committed
970 971 972
  bits= uint8korr(res);
  add();
  int8store(res, bits);
unknown's avatar
unknown committed
973 974 975 976 977 978
}

/*
** calc next value and merge it with field_value
*/

unknown's avatar
unknown committed
979
void Item_sum_sum::update_field()
unknown's avatar
unknown committed
980 981 982 983
{
  double old_nr,nr;
  char *res=result_field->ptr;

unknown's avatar
unknown committed
984
  float8get(old_nr,res);
985
  nr= args[0]->val_real();
unknown's avatar
unknown committed
986
  if (!args[0]->null_value)
unknown's avatar
unknown committed
987
  {
unknown's avatar
unknown committed
988
    old_nr+=nr;
unknown's avatar
unknown committed
989 990
    result_field->set_notnull();
  }
unknown's avatar
unknown committed
991 992 993 994
  float8store(res,old_nr);
}


unknown's avatar
unknown committed
995
void Item_sum_count::update_field()
unknown's avatar
unknown committed
996 997 998 999
{
  longlong nr;
  char *res=result_field->ptr;

unknown's avatar
unknown committed
1000
  nr=sint8korr(res);
unknown's avatar
unknown committed
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
  if (!args[0]->maybe_null)
    nr++;
  else
  {
    (void) args[0]->val_int();
    if (!args[0]->null_value)
      nr++;
  }
  int8store(res,nr);
}


unknown's avatar
unknown committed
1013
void Item_sum_avg::update_field()
unknown's avatar
unknown committed
1014 1015 1016 1017 1018
{
  double nr,old_nr;
  longlong field_count;
  char *res=result_field->ptr;

unknown's avatar
unknown committed
1019 1020
  float8get(old_nr,res);
  field_count=sint8korr(res+sizeof(double));
unknown's avatar
unknown committed
1021

1022
  nr= args[0]->val_real();
unknown's avatar
unknown committed
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
  if (!args[0]->null_value)
  {
    old_nr+=nr;
    field_count++;
  }
  float8store(res,old_nr);
  res+=sizeof(double);
  int8store(res,field_count);
}

unknown's avatar
unknown committed
1033
void Item_sum_hybrid::update_field()
unknown's avatar
unknown committed
1034 1035
{
  if (hybrid_type == STRING_RESULT)
unknown's avatar
unknown committed
1036
    min_max_update_str_field();
unknown's avatar
unknown committed
1037
  else if (hybrid_type == INT_RESULT)
unknown's avatar
unknown committed
1038
    min_max_update_int_field();
unknown's avatar
unknown committed
1039
  else
unknown's avatar
unknown committed
1040
    min_max_update_real_field();
unknown's avatar
unknown committed
1041 1042 1043 1044
}


void
unknown's avatar
unknown committed
1045
Item_sum_hybrid::min_max_update_str_field()
unknown's avatar
unknown committed
1046 1047 1048
{
  String *res_str=args[0]->val_str(&value);

unknown's avatar
unknown committed
1049
  if (!args[0]->null_value)
unknown's avatar
unknown committed
1050 1051
  {
    res_str->strip_sp();
1052
    result_field->val_str(&tmp_value);
unknown's avatar
unknown committed
1053 1054

    if (result_field->is_null() ||
1055
	(cmp_sign * sortcmp(res_str,&tmp_value,collation.collation)) < 0)
1056
      result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
unknown's avatar
unknown committed
1057 1058 1059 1060 1061 1062
    result_field->set_notnull();
  }
}


void
unknown's avatar
unknown committed
1063
Item_sum_hybrid::min_max_update_real_field()
unknown's avatar
unknown committed
1064 1065 1066 1067
{
  double nr,old_nr;

  old_nr=result_field->val_real();
1068
  nr= args[0]->val_real();
unknown's avatar
unknown committed
1069 1070
  if (!args[0]->null_value)
  {
unknown's avatar
unknown committed
1071
    if (result_field->is_null(0) ||
unknown's avatar
unknown committed
1072 1073 1074 1075
	(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
      old_nr=nr;
    result_field->set_notnull();
  }
unknown's avatar
unknown committed
1076
  else if (result_field->is_null(0))
unknown's avatar
unknown committed
1077 1078 1079 1080 1081 1082
    result_field->set_null();
  result_field->store(old_nr);
}


void
unknown's avatar
unknown committed
1083
Item_sum_hybrid::min_max_update_int_field()
unknown's avatar
unknown committed
1084 1085 1086 1087 1088 1089 1090
{
  longlong nr,old_nr;

  old_nr=result_field->val_int();
  nr=args[0]->val_int();
  if (!args[0]->null_value)
  {
unknown's avatar
unknown committed
1091
    if (result_field->is_null(0))
unknown's avatar
unknown committed
1092
      old_nr=nr;
1093 1094 1095 1096 1097 1098
    else
    {
      bool res=(unsigned_flag ?
		(ulonglong) old_nr > (ulonglong) nr :
		old_nr > nr);
      /* (cmp_sign > 0 && res) || (!(cmp_sign > 0) && !res) */
unknown's avatar
unknown committed
1099
      if ((cmp_sign > 0) ^ (!res))
1100 1101
	old_nr=nr;
    }
unknown's avatar
unknown committed
1102 1103
    result_field->set_notnull();
  }
unknown's avatar
unknown committed
1104
  else if (result_field->is_null(0))
unknown's avatar
unknown committed
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
    result_field->set_null();
  result_field->store(old_nr);
}


Item_avg_field::Item_avg_field(Item_sum_avg *item)
{
  name=item->name;
  decimals=item->decimals;
  max_length=item->max_length;
  field=item->result_field;
  maybe_null=1;
}

unknown's avatar
unknown committed
1119

1120
double Item_avg_field::val_real()
unknown's avatar
unknown committed
1121
{
1122
  // fix_fields() never calls for this Item
unknown's avatar
unknown committed
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
  double nr;
  longlong count;
  float8get(nr,field->ptr);
  char *res=(field->ptr+sizeof(double));
  count=sint8korr(res);

  if (!count)
  {
    null_value=1;
    return 0.0;
  }
  null_value=0;
  return nr/(double) count;
}

String *Item_avg_field::val_str(String *str)
{
1140
  // fix_fields() never calls for this Item
1141
  double nr= Item_avg_field::val_real();
unknown's avatar
unknown committed
1142 1143
  if (null_value)
    return 0;
unknown's avatar
unknown committed
1144
  str->set(nr,decimals, &my_charset_bin);
unknown's avatar
unknown committed
1145 1146 1147 1148
  return str;
}

Item_std_field::Item_std_field(Item_sum_std *item)
unknown's avatar
unknown committed
1149 1150 1151 1152
  : Item_variance_field(item)
{
}

1153
double Item_std_field::val_real()
unknown's avatar
unknown committed
1154
{
1155
  // fix_fields() never calls for this Item
1156
  double tmp= Item_variance_field::val_real();
unknown's avatar
unknown committed
1157 1158 1159 1160
  return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}

Item_variance_field::Item_variance_field(Item_sum_variance *item)
unknown's avatar
unknown committed
1161 1162 1163 1164 1165 1166 1167 1168
{
  name=item->name;
  decimals=item->decimals;
  max_length=item->max_length;
  field=item->result_field;
  maybe_null=1;
}

1169
double Item_variance_field::val_real()
unknown's avatar
unknown committed
1170
{
1171
  // fix_fields() never calls for this Item
unknown's avatar
unknown committed
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
  double sum,sum_sqr;
  longlong count;
  float8get(sum,field->ptr);
  float8get(sum_sqr,(field->ptr+sizeof(double)));
  count=sint8korr(field->ptr+sizeof(double)*2);

  if (!count)
  {
    null_value=1;
    return 0.0;
  }
  null_value=0;
  double tmp= (double) count;
  double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
unknown's avatar
unknown committed
1186
  return tmp2 <= 0.0 ? 0.0 : tmp2;
unknown's avatar
unknown committed
1187 1188
}

unknown's avatar
unknown committed
1189
String *Item_variance_field::val_str(String *str)
unknown's avatar
unknown committed
1190
{
1191
  // fix_fields() never calls for this Item
1192
  double nr= val_real();
unknown's avatar
unknown committed
1193 1194
  if (null_value)
    return 0;
unknown's avatar
unknown committed
1195
  str->set(nr,decimals, &my_charset_bin);
unknown's avatar
unknown committed
1196 1197 1198 1199 1200 1201 1202 1203 1204
  return str;
}

/****************************************************************************
** COUNT(DISTINCT ...)
****************************************************************************/

#include "sql_select.h"

1205
int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
1206
{
1207 1208 1209
  Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
  CHARSET_INFO *cs=item->key_charset;
  uint len=item->key_length;
unknown's avatar
Fix:  
unknown committed
1210 1211
  return cs->coll->strnncollsp(cs, 
			       (const uchar*) key1, len, 
1212
			       (const uchar*) key2, len, 0);
1213 1214
}

unknown's avatar
unknown committed
1215 1216 1217 1218 1219 1220 1221
/*
  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
*/

1222 1223 1224
int composite_key_cmp(void* arg, byte* key1, byte* key2)
{
  Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
unknown's avatar
unknown committed
1225 1226 1227 1228 1229 1230 1231
  Field **field    = item->table->field;
  Field **field_end= field + item->table->fields;
  uint32 *lengths=item->field_lengths;
  for (; field < field_end; ++field)
  {
    Field* f = *field;
    int len = *lengths++;
1232
    int res = f->cmp(key1, key2);
unknown's avatar
unknown committed
1233 1234 1235 1236 1237
    if (res)
      return res;
    key1 += len;
    key2 += len;
  }
1238 1239 1240
  return 0;
}

unknown's avatar
unknown committed
1241 1242 1243 1244
/*
  helper function for walking the tree when we dump it to MyISAM -
  tree_walk will call it for each leaf
*/
1245

1246 1247 1248
int dump_leaf(byte* key, uint32 count __attribute__((unused)),
		     Item_sum_count_distinct* item)
{
unknown's avatar
unknown committed
1249
  byte* buf = item->table->record[0];
1250
  int error;
unknown's avatar
unknown committed
1251 1252
  /*
    The first item->rec_offset bytes are taken care of with
unknown's avatar
unknown committed
1253
    restore_record(table,default_values) in setup()
unknown's avatar
unknown committed
1254
  */
1255
  memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
1256 1257
  if ((error = item->table->file->write_row(buf)))
  {
unknown's avatar
unknown committed
1258 1259 1260
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
      return 1;
1261 1262 1263
  }
  return 0;
}
1264

unknown's avatar
unknown committed
1265

unknown's avatar
unknown committed
1266
void Item_sum_count_distinct::cleanup()
unknown's avatar
unknown committed
1267
{
unknown's avatar
unknown committed
1268
  DBUG_ENTER("Item_sum_count_distinct::cleanup");
unknown's avatar
unknown committed
1269
  Item_sum_int::cleanup();
unknown's avatar
unknown committed
1270 1271 1272 1273
  /*
    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 )
  */
1274 1275 1276
  if (!original)
  {
    if (table)
unknown's avatar
unknown committed
1277
    {
1278
      free_tmp_table(current_thd, table);
unknown's avatar
unknown committed
1279 1280
      table= 0;
    }
1281
    delete tmp_table_param;
unknown's avatar
unknown committed
1282
    tmp_table_param= 0;
1283
    if (use_tree)
unknown's avatar
unknown committed
1284
    {
1285
      delete_tree(tree);
unknown's avatar
unknown committed
1286 1287
      use_tree= 0;
    }
1288
  }
unknown's avatar
unknown committed
1289
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1290 1291
}

unknown's avatar
unknown committed
1292

1293 1294 1295 1296 1297 1298
/* 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;
unknown's avatar
unknown committed
1299
  use_tree= 0; // to prevent delete_tree call on uninitialized tree
1300 1301 1302 1303
  tree= &tree_base;
}


unknown's avatar
unknown committed
1304 1305 1306
bool Item_sum_count_distinct::setup(THD *thd)
{
  List<Item> list;
unknown's avatar
unknown committed
1307
  SELECT_LEX *select_lex= thd->lex->current_select;
1308 1309 1310
  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
    return 1;
    
1311 1312 1313
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
    return 1;

unknown's avatar
unknown committed
1314 1315
  /* Create a table with an unique key over all parameters */
  for (uint i=0; i < arg_count ; i++)
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328
  {
    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;
unknown's avatar
unknown committed
1329
  count_field_types(tmp_table_param,list,0);
unknown's avatar
unknown committed
1330 1331 1332 1333 1334
  if (table)
  {
    free_tmp_table(thd, table);
    tmp_table_param->cleanup();
  }
1335
  if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
unknown's avatar
unknown committed
1336
				0,
1337
				select_lex->options | thd->options,
1338
				HA_POS_ERROR, (char*)"")))
unknown's avatar
unknown committed
1339 1340
    return 1;
  table->file->extra(HA_EXTRA_NO_ROWS);		// Don't update rows
1341
  table->no_rows=1;
1342

unknown's avatar
unknown committed
1343

unknown's avatar
unknown committed
1344 1345 1346 1347 1348
  // no blobs, otherwise it would be MyISAM
  if (table->db_type == DB_TYPE_HEAP)
  {
    qsort_cmp2 compare_key;
    void* cmp_arg;
unknown's avatar
unknown committed
1349

unknown's avatar
unknown committed
1350
    // to make things easier for dump_leaf if we ever have to dump to MyISAM
unknown's avatar
unknown committed
1351
    restore_record(table,default_values);
unknown's avatar
unknown committed
1352

unknown's avatar
unknown committed
1353 1354 1355 1356 1357 1358 1359 1360 1361
    if (table->fields == 1)
    {
      /*
	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];
1362 1363 1364
      switch (field->type()) {
      case MYSQL_TYPE_STRING:
      case MYSQL_TYPE_VAR_STRING:
1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
	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;
	}
unknown's avatar
unknown committed
1379 1380 1381 1382 1383 1384 1385
	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;
1386
	cmp_arg = (void*) &key_length;
unknown's avatar
unknown committed
1387 1388
	break;
      }
1389 1390 1391
      key_charset = field->charset();
      key_length  = field->pack_length();
      rec_offset  = 1;
1392
    }
unknown's avatar
unknown committed
1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
    else // too bad, cannot cheat - there is more than one field
    {
      bool all_binary = 1;
      Field** field, **field_end;
      field_end = (field = table->field) + table->fields;
      uint32 *lengths;
      if (!(field_lengths= 
	    (uint32*) thd->alloc(sizeof(uint32) * table->fields)))
	return 1;

1403
      for (key_length = 0, lengths=field_lengths; field < field_end; ++field)
unknown's avatar
unknown committed
1404 1405
      {
	uint32 length= (*field)->pack_length();
1406
	key_length += length;
unknown's avatar
unknown committed
1407 1408 1409 1410
	*lengths++ = length;
	if (!(*field)->binary())
	  all_binary = 0;			// Can't break loop here
      }
1411
      rec_offset = table->reclength - key_length;
unknown's avatar
unknown committed
1412 1413 1414
      if (all_binary)
      {
	compare_key = (qsort_cmp2)simple_raw_key_cmp;
1415
	cmp_arg = (void*) &key_length;
unknown's avatar
unknown committed
1416 1417 1418 1419
      }
      else
      {
	compare_key = (qsort_cmp2) composite_key_cmp ;
1420
	cmp_arg = (void*) this;
unknown's avatar
unknown committed
1421 1422 1423
      }
    }

unknown's avatar
unknown committed
1424 1425
    if (use_tree)
      delete_tree(tree);
1426 1427
    init_tree(tree, min(thd->variables.max_heap_table_size,
			thd->variables.sortbuff_size/16), 0,
1428
	      key_length, compare_key, 0, NULL, cmp_arg);
unknown's avatar
unknown committed
1429 1430 1431
    use_tree = 1;

    /*
1432
      The only time key_length could be 0 is if someone does
unknown's avatar
unknown committed
1433 1434 1435 1436
      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
    */
1437 1438
    max_elements_in_tree = ((key_length) ? 
			    thd->variables.max_heap_table_size/key_length : 1);
1439 1440 1441 1442 1443 1444

  }
  if (original)
  {
    original->table= table;
    original->use_tree= use_tree;
unknown's avatar
unknown committed
1445
  }
unknown's avatar
unknown committed
1446 1447 1448
  return 0;
}

unknown's avatar
unknown committed
1449

1450 1451
int Item_sum_count_distinct::tree_to_myisam()
{
unknown's avatar
unknown committed
1452
  if (create_myisam_from_heap(current_thd, table, tmp_table_param,
unknown's avatar
unknown committed
1453
			      HA_ERR_RECORD_FILE_FULL, 1) ||
1454
      tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
unknown's avatar
unknown committed
1455
		left_root_right))
1456
    return 1;
1457
  delete_tree(tree);
1458 1459 1460
  use_tree = 0;
  return 0;
}
unknown's avatar
unknown committed
1461

1462 1463 1464

Item *Item_sum_count_distinct::copy_or_same(THD* thd) 
{
unknown's avatar
unknown committed
1465
  return new (thd->mem_root) Item_sum_count_distinct(thd, this);
1466 1467 1468
}


1469
void Item_sum_count_distinct::clear()
unknown's avatar
unknown committed
1470
{
unknown's avatar
merge  
unknown committed
1471
  if (use_tree)
1472
    reset_tree(tree);
unknown's avatar
merge  
unknown committed
1473
  else if (table)
1474 1475 1476 1477 1478
  {
    table->file->extra(HA_EXTRA_NO_CACHE);
    table->file->delete_all_rows();
    table->file->extra(HA_EXTRA_WRITE_CACHE);
  }
unknown's avatar
unknown committed
1479 1480 1481 1482 1483
}

bool Item_sum_count_distinct::add()
{
  int error;
1484 1485
  if (always_null)
    return 0;
unknown's avatar
unknown committed
1486
  copy_fields(tmp_table_param);
unknown's avatar
unknown committed
1487
  copy_funcs(tmp_table_param->items_to_copy);
unknown's avatar
unknown committed
1488

1489 1490 1491 1492
  for (Field **field=table->field ; *field ; field++)
    if ((*field)->is_real_null(0))
      return 0;					// Don't count NULL

unknown's avatar
unknown committed
1493 1494 1495 1496 1497 1498
  if (use_tree)
  {
    /*
      If the tree got too big, convert to MyISAM, otherwise insert into the
      tree.
    */
1499
    if (tree->elements_in_tree > max_elements_in_tree)
1500
    {
1501
      if (tree_to_myisam())
1502 1503
	return 1;
    }
1504 1505
    else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
			  tree->custom_arg))
unknown's avatar
unknown committed
1506 1507
      return 1;
  }
1508
  else if ((error=table->file->write_row(table->record[0])))
unknown's avatar
unknown committed
1509 1510 1511 1512
  {
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
    {
unknown's avatar
unknown committed
1513 1514
      if (create_myisam_from_heap(current_thd, table, tmp_table_param, error,
				  1))
unknown's avatar
unknown committed
1515 1516 1517 1518 1519 1520
	return 1;				// Not a table_is_full error
    }
  }
  return 0;
}

unknown's avatar
unknown committed
1521

unknown's avatar
unknown committed
1522 1523
longlong Item_sum_count_distinct::val_int()
{
1524
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1525 1526
  if (!table)					// Empty query
    return LL(0);
unknown's avatar
unknown committed
1527
  if (use_tree)
1528
    return tree->elements_in_tree;
unknown's avatar
unknown committed
1529 1530 1531 1532
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  return table->file->records;
}

1533 1534 1535

void Item_sum_count_distinct::print(String *str)
{
1536
  str->append("count(distinct ", 15);
1537 1538 1539 1540
  args[0]->print(str);
  str->append(')');
}

unknown's avatar
unknown committed
1541 1542 1543 1544 1545 1546 1547 1548 1549
/****************************************************************************
** 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

1550
void Item_udf_sum::clear()
unknown's avatar
unknown committed
1551
{
1552
  DBUG_ENTER("Item_udf_sum::clear");
1553
  udf.clear();
1554
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1555 1556 1557 1558
}

bool Item_udf_sum::add()
{
1559
  DBUG_ENTER("Item_udf_sum::add");
unknown's avatar
unknown committed
1560 1561 1562 1563
  udf.add(&null_value);
  DBUG_RETURN(0);
}

1564 1565
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
1566
  return new (thd->mem_root) Item_sum_udf_float(thd, this);
1567 1568
}

1569
double Item_sum_udf_float::val_real()
unknown's avatar
unknown committed
1570
{
1571
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1572 1573 1574 1575 1576 1577 1578 1579
  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));
}

String *Item_sum_udf_float::val_str(String *str)
{
1580
  DBUG_ASSERT(fixed == 1);
1581
  double nr= val_real();
unknown's avatar
unknown committed
1582 1583
  if (null_value)
    return 0;					/* purecov: inspected */
unknown's avatar
unknown committed
1584
  str->set(nr,decimals, &my_charset_bin);
unknown's avatar
unknown committed
1585 1586 1587 1588
  return str;
}


1589 1590
Item *Item_sum_udf_int::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
1591
  return new (thd->mem_root) Item_sum_udf_int(thd, this);
1592 1593 1594
}


unknown's avatar
unknown committed
1595 1596
longlong Item_sum_udf_int::val_int()
{
1597
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1598 1599 1600 1601 1602 1603
  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));
}

1604

unknown's avatar
unknown committed
1605 1606
String *Item_sum_udf_int::val_str(String *str)
{
1607
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1608 1609 1610
  longlong nr=val_int();
  if (null_value)
    return 0;
unknown's avatar
unknown committed
1611
  str->set(nr, &my_charset_bin);
unknown's avatar
unknown committed
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
  return str;
}

/* 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;
}

1626 1627 1628

Item *Item_sum_udf_str::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
1629
  return new (thd->mem_root) Item_sum_udf_str(thd, this);
1630 1631 1632
}


unknown's avatar
unknown committed
1633 1634
String *Item_sum_udf_str::val_str(String *str)
{
1635
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1636 1637 1638 1639 1640 1641 1642
  DBUG_ENTER("Item_sum_udf_str::str");
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  DBUG_RETURN(res);
}

#endif /* HAVE_DLOPEN */
1643 1644 1645 1646


/*****************************************************************************
 GROUP_CONCAT function
unknown's avatar
unknown committed
1647 1648 1649 1650 1651

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

1652
 concat of values from "group by" operation
unknown's avatar
unknown committed
1653 1654 1655 1656 1657

 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
1658 1659 1660
*****************************************************************************/

/*
unknown's avatar
SCRUM  
unknown committed
1661 1662
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,...)
1663 1664
*/

unknown's avatar
unknown committed
1665 1666
int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
				       byte* key2)
1667
{
unknown's avatar
unknown committed
1668
  Item_func_group_concat* grp_item= (Item_func_group_concat*)arg;
unknown's avatar
unknown committed
1669
  Item **field_item, **end;
unknown's avatar
unknown committed
1670
  char *record= (char*) grp_item->table->record[0];
unknown's avatar
unknown committed
1671

unknown's avatar
unknown committed
1672
  for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field;
unknown's avatar
unknown committed
1673 1674
       field_item < end;
       field_item++)
1675
  {
unknown's avatar
unknown committed
1676 1677 1678 1679 1680 1681
    /*
      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();
1682 1683
    if (field)
    {
unknown's avatar
unknown committed
1684
      int res;
unknown's avatar
unknown committed
1685
      uint offset= (uint) (field->ptr - record);
1686
      if ((res= field->cmp(key1 + offset, key2 + offset)))
unknown's avatar
unknown committed
1687
	return res;
1688
    }
unknown's avatar
unknown committed
1689
  }
1690 1691 1692
  return 0;
}

1693

1694
/*
unknown's avatar
SCRUM  
unknown committed
1695 1696
  function of sort for syntax:
  GROUP_CONCAT(expr,... ORDER BY col,... )
1697 1698
*/

unknown's avatar
unknown committed
1699
int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
1700
{
unknown's avatar
unknown committed
1701
  Item_func_group_concat* grp_item= (Item_func_group_concat*) arg;
unknown's avatar
unknown committed
1702
  ORDER **order_item, **end;
unknown's avatar
unknown committed
1703
  char *record= (char*) grp_item->table->record[0];
unknown's avatar
unknown committed
1704

unknown's avatar
unknown committed
1705
  for (order_item= grp_item->order, end=order_item+ grp_item->arg_count_order;
unknown's avatar
unknown committed
1706 1707
       order_item < end;
       order_item++)
1708
  {
unknown's avatar
unknown committed
1709
    Item *item= *(*order_item)->item;
unknown's avatar
unknown committed
1710 1711 1712 1713 1714 1715
    /*
      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();
1716 1717
    if (field)
    {
unknown's avatar
unknown committed
1718 1719
      int res;
      uint offset= (uint) (field->ptr - record);
1720
      if ((res= field->cmp(key1 + offset, key2 + offset)))
unknown's avatar
unknown committed
1721
        return (*order_item)->asc ? res : -res;
1722
    }
unknown's avatar
unknown committed
1723
  }
unknown's avatar
SCRUM  
unknown committed
1724
  /*
unknown's avatar
unknown committed
1725 1726 1727 1728
    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.
  */
1729 1730 1731
  return 1;
}

1732

1733
/*
unknown's avatar
SCRUM  
unknown committed
1734 1735
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
unknown's avatar
unknown committed
1736 1737 1738 1739 1740

  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
1741
*/
unknown's avatar
SCRUM  
unknown committed
1742

unknown's avatar
unknown committed
1743 1744
int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
						 byte* key2)
1745 1746 1747 1748 1749 1750
{
  if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
    return 0;
  return(group_concat_key_cmp_with_order(arg,key1,key2));
}

1751

1752
/*
unknown's avatar
unknown committed
1753
  Append data from current leaf to item->result
1754
*/
unknown's avatar
SCRUM  
unknown committed
1755

unknown's avatar
unknown committed
1756
int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
unknown's avatar
unknown committed
1757
                  Item_func_group_concat *item)
1758 1759
{
  char buff[MAX_FIELD_WIDTH];
1760
  String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2;
unknown's avatar
unknown committed
1761 1762
  char *record= (char*) item->table->record[0];

unknown's avatar
a fix  
unknown committed
1763 1764 1765
  if (item->result.length())
    item->result.append(*item->separator);

1766 1767
  tmp.length(0);
  
unknown's avatar
unknown committed
1768
  for (uint i= 0; i < item->arg_count_field; i++)
1769
  {
unknown's avatar
unknown committed
1770
    Item *show_item= item->args[i];
1771 1772
    if (!show_item->const_item())
    {
unknown's avatar
unknown committed
1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784
      /*
	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);
      DBUG_ASSERT(offset < item->table->reclength);
      field->ptr= (char *) key + offset;
      res= field->val_str(&tmp,&tmp2);
unknown's avatar
unknown committed
1785
      item->result.append(*res);
unknown's avatar
unknown committed
1786
      field->ptr= save_ptr;
1787 1788 1789
    }
    else 
    {
unknown's avatar
SCRUM  
unknown committed
1790
      String *res= show_item->val_str(&tmp);
1791
      if (res)
unknown's avatar
unknown committed
1792
        item->result.append(*res);
1793 1794
    }
  }
unknown's avatar
unknown committed
1795 1796 1797

  /* stop if length of result more than group_concat_max_len */  
  if (item->result.length() > item->group_concat_max_len)
1798
  {
unknown's avatar
unknown committed
1799 1800 1801
    item->count_cut_values++;
    item->result.length(item->group_concat_max_len);
    item->warning_for_row= TRUE;
1802 1803 1804 1805 1806
    return 1;
  }
  return 0;
}

1807

1808
/*
unknown's avatar
SCRUM  
unknown committed
1809 1810 1811 1812 1813
  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
1814
*/
unknown's avatar
SCRUM  
unknown committed
1815

unknown's avatar
unknown committed
1816
Item_func_group_concat::Item_func_group_concat(bool is_distinct,
1817 1818 1819
					       List<Item> *is_select,
					       SQL_LIST *is_order,
					       String *is_separator)
unknown's avatar
unknown committed
1820
  :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
1821
   key_length(0), tree_mode(0), distinct(is_distinct), warning_for_row(0),
unknown's avatar
unknown committed
1822
   separator(is_separator), tree(&tree_base), table(0),
1823
   order(0), tables_list(0),
unknown's avatar
a fix  
unknown committed
1824
   arg_count_order(0), arg_count_field(0),
unknown's avatar
unknown committed
1825
   count_cut_values(0)
1826
{
unknown's avatar
unknown committed
1827 1828 1829
  Item *item_select;
  Item **arg_ptr;

unknown's avatar
SCRUM  
unknown committed
1830 1831
  original= 0;
  quick_group= 0;
1832
  mark_as_sum_func();
unknown's avatar
SCRUM  
unknown committed
1833
  order= 0;
unknown's avatar
unknown committed
1834
  group_concat_max_len= current_thd->variables.group_concat_max_len;
1835
    
unknown's avatar
unknown committed
1836
  arg_count_field= is_select->elements;
unknown's avatar
SCRUM  
unknown committed
1837
  arg_count_order= is_order ? is_order->elements : 0;
unknown's avatar
unknown committed
1838
  arg_count= arg_count_field + arg_count_order;
unknown's avatar
SCRUM  
unknown committed
1839 1840 1841
  
  /*
    We need to allocate:
unknown's avatar
unknown committed
1842 1843
    args - arg_count_field+arg_count_order
           (for possible order items in temporare tables)
unknown's avatar
SCRUM  
unknown committed
1844 1845
    order - arg_count_order
  */
unknown's avatar
unknown committed
1846
  if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
unknown's avatar
unknown committed
1847
				 sizeof(ORDER*)*arg_count_order)))
unknown's avatar
unknown committed
1848
    return;
unknown's avatar
unknown committed
1849

unknown's avatar
unknown committed
1850 1851
  order= (ORDER**)(args + arg_count);

unknown's avatar
unknown committed
1852
  /* fill args items of show and sort */
unknown's avatar
SCRUM  
unknown committed
1853
  List_iterator_fast<Item> li(*is_select);
1854

unknown's avatar
unknown committed
1855 1856
  for (arg_ptr=args ; (item_select= li++) ; arg_ptr++)
    *arg_ptr= item_select;
unknown's avatar
unknown committed
1857 1858

  if (arg_count_order) 
unknown's avatar
SCRUM  
unknown committed
1859
  {
unknown's avatar
unknown committed
1860
    ORDER **order_ptr= order;
unknown's avatar
unknown committed
1861
    for (ORDER *order_item= (ORDER*) is_order->first;
unknown's avatar
unknown committed
1862 1863
	 order_item != NULL;
	 order_item= order_item->next)
1864
    {
unknown's avatar
unknown committed
1865 1866 1867
      (*order_ptr++)= order_item;
      *arg_ptr= *order_item->item;
      order_item->item= arg_ptr++;
1868 1869 1870
    }
  }
}
unknown's avatar
unknown committed
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897
  

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;
}

1898

unknown's avatar
SCRUM  
unknown committed
1899

unknown's avatar
unknown committed
1900 1901
void Item_func_group_concat::cleanup()
{
unknown's avatar
unknown committed
1902
  DBUG_ENTER("Item_func_group_concat::cleanup");
1903
  Item_sum::cleanup();
unknown's avatar
unknown committed
1904

unknown's avatar
unknown committed
1905 1906 1907 1908 1909 1910 1911 1912
  /*
    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)
unknown's avatar
unknown committed
1913
    {
unknown's avatar
unknown committed
1914
      free_tmp_table(thd, table);
unknown's avatar
unknown committed
1915 1916
      table= 0;
    }
unknown's avatar
unknown committed
1917
    delete tmp_table_param;
unknown's avatar
unknown committed
1918
    tmp_table_param= 0;
unknown's avatar
unknown committed
1919
    if (tree_mode)
unknown's avatar
unknown committed
1920 1921
    {
      tree_mode= 0;
unknown's avatar
unknown committed
1922
      delete_tree(tree); 
unknown's avatar
unknown committed
1923
    }
1924 1925 1926 1927 1928 1929 1930
    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;
    }
unknown's avatar
unknown committed
1931
  }
unknown's avatar
unknown committed
1932
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1933 1934
}

unknown's avatar
unknown committed
1935

1936 1937 1938 1939 1940
Item_func_group_concat::~Item_func_group_concat()
{
}


1941 1942
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
unknown's avatar
unknown committed
1943
  return new (thd->mem_root) Item_func_group_concat(thd, this);
1944 1945 1946
}


1947
void Item_func_group_concat::clear()
1948 1949 1950
{
  result.length(0);
  result.copy();
unknown's avatar
SCRUM  
unknown committed
1951
  null_value= TRUE;
unknown's avatar
unknown committed
1952
  warning_for_row= FALSE;
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962
  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);
}

unknown's avatar
SCRUM  
unknown committed
1963

1964 1965
bool Item_func_group_concat::add()
{
unknown's avatar
BUG  
unknown committed
1966 1967
  if (always_null)
    return 0;
1968 1969 1970
  copy_fields(tmp_table_param);
  copy_funcs(tmp_table_param->items_to_copy);

unknown's avatar
unknown committed
1971
  for (uint i= 0; i < arg_count_field; i++)
1972
  {
unknown's avatar
unknown committed
1973
    Item *show_item= args[i];
unknown's avatar
SCRUM  
unknown committed
1974
    if (!show_item->const_item())
1975
    {
unknown's avatar
unknown committed
1976 1977 1978 1979
      /*
	Here we use real_item as we want the original field data that should
	be written to table->record[0]
      */
unknown's avatar
BUG  
unknown committed
1980
      Field *f= show_item->real_item()->get_tmp_table_field();
unknown's avatar
unknown committed
1981 1982
      if (f->is_null())
	return 0;				// Skip row if it contains null
1983 1984
    }
  }
unknown's avatar
unknown committed
1985

unknown's avatar
SCRUM  
unknown committed
1986
  null_value= FALSE;
1987 1988

  TREE_ELEMENT *el= 0;                          // Only for safety
unknown's avatar
SCRUM  
unknown committed
1989
  if (tree_mode)
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000
    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);

2001 2002 2003
  return 0;
}

unknown's avatar
SCRUM  
unknown committed
2004

2005 2006 2007 2008 2009 2010
void Item_func_group_concat::reset_field()
{
  if (tree_mode)
    reset_tree(tree);
}

unknown's avatar
SCRUM  
unknown committed
2011

2012 2013 2014
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
unknown's avatar
unknown committed
2015
  uint i;			/* for loop variable */ 
2016
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
2017

2018 2019
  if (!thd->allow_sum_func)
  {
unknown's avatar
unknown committed
2020 2021
    my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
               MYF(0));
unknown's avatar
unknown committed
2022
    return TRUE;
2023 2024
  }
  
unknown's avatar
SCRUM  
unknown committed
2025 2026
  thd->allow_sum_func= 0;
  maybe_null= 0;
unknown's avatar
unknown committed
2027
  item_thd= thd;
unknown's avatar
unknown committed
2028

unknown's avatar
SCRUM  
unknown committed
2029
  /*
unknown's avatar
unknown committed
2030
    Fix fields for select list and ORDER clause
unknown's avatar
SCRUM  
unknown committed
2031
  */
unknown's avatar
unknown committed
2032

unknown's avatar
unknown committed
2033
  for (i=0 ; i < arg_count ; i++)  
2034
  {
unknown's avatar
unknown committed
2035 2036 2037
    if ((!args[i]->fixed && 
         args[i]->fix_fields(thd, tables, args + i)) ||
        args[i]->check_cols(1))
unknown's avatar
unknown committed
2038
      return TRUE;
unknown's avatar
unknown committed
2039
    if (i < arg_count_field)
unknown's avatar
unknown committed
2040
      maybe_null|= args[i]->maybe_null;
2041
  }
unknown's avatar
unknown committed
2042

unknown's avatar
SCRUM  
unknown committed
2043 2044
  result_field= 0;
  null_value= 1;
2045
  max_length= group_concat_max_len;
unknown's avatar
unknown committed
2046
  thd->allow_sum_func= 1;
2047
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
unknown's avatar
unknown committed
2048
    return TRUE;
2049 2050
  /* We'll convert all blobs to varchar fields in the temporary table */
  tmp_table_param->convert_blob_length= group_concat_max_len;
unknown's avatar
SCRUM  
unknown committed
2051
  tables_list= tables;
2052
  fixed= 1;
unknown's avatar
unknown committed
2053
  return FALSE;
2054 2055
}

unknown's avatar
SCRUM  
unknown committed
2056

2057 2058 2059
bool Item_func_group_concat::setup(THD *thd)
{
  List<Item> list;
unknown's avatar
unknown committed
2060
  SELECT_LEX *select_lex= thd->lex->current_select;
unknown's avatar
unknown committed
2061
  uint const_fields;
unknown's avatar
unknown committed
2062 2063
  qsort_cmp2 compare_key;
  DBUG_ENTER("Item_func_group_concat::setup");
2064 2065

  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
2066
    DBUG_RETURN(1);
unknown's avatar
unknown committed
2067

unknown's avatar
SCRUM  
unknown committed
2068
  /*
unknown's avatar
unknown committed
2069
    push all not constant fields to list and create temp table
unknown's avatar
unknown committed
2070
  */
unknown's avatar
unknown committed
2071
  const_fields= 0;
unknown's avatar
BUG  
unknown committed
2072
  always_null= 0;
unknown's avatar
unknown committed
2073
  for (uint i= 0; i < arg_count_field; i++)
2074
  {
unknown's avatar
SCRUM  
unknown committed
2075
    Item *item= args[i];
2076
    if (list.push_back(item))
2077
      DBUG_RETURN(1);
2078 2079
    if (item->const_item())
    {
unknown's avatar
unknown committed
2080
      const_fields++;
2081 2082
      (void) item->val_int();
      if (item->null_value)
unknown's avatar
SCRUM  
unknown committed
2083
	always_null= 1;
2084 2085
    }
  }
unknown's avatar
BUG  
unknown committed
2086
  if (always_null)
2087
    DBUG_RETURN(0);
unknown's avatar
unknown committed
2088

2089
  List<Item> all_fields(list);
unknown's avatar
unknown committed
2090
  if (arg_count_order)
2091 2092 2093 2094 2095
  {
    bool hidden_group_fields;
    setup_group(thd, args, tables_list, list, all_fields, *order,
                &hidden_group_fields);
  }
unknown's avatar
unknown committed
2096

2097
  count_field_types(tmp_table_param,all_fields,0);
2098 2099
  if (table)
  {
unknown's avatar
unknown committed
2100 2101 2102 2103
    /*
      We come here when we are getting the result from a temporary table,
      not the original tables used in the query
    */
2104 2105 2106
    free_tmp_table(thd, table);
    tmp_table_param->cleanup();
  }
unknown's avatar
SCRUM  
unknown committed
2107
  /*
unknown's avatar
unknown committed
2108
    We have to create a temporary table to get descriptions of fields 
unknown's avatar
SCRUM  
unknown committed
2109
    (types, sizes and so on).
unknown's avatar
unknown committed
2110 2111 2112

    Note that in the table, we first have the ORDER BY fields, then the
    field list.
unknown's avatar
unknown committed
2113 2114 2115

    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. 
unknown's avatar
SCRUM  
unknown committed
2116
  */
unknown's avatar
unknown committed
2117
  if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 
unknown's avatar
unknown committed
2118 2119
			       (ORDER*) 0, 0, TRUE,
                               select_lex->options | thd->options,
unknown's avatar
unknown committed
2120
			       HA_POS_ERROR,(char *) "")))
2121
    DBUG_RETURN(1);
2122
  table->file->extra(HA_EXTRA_NO_ROWS);
unknown's avatar
SCRUM  
unknown committed
2123
  table->no_rows= 1;
unknown's avatar
unknown committed
2124

unknown's avatar
unknown committed
2125
  key_length= table->reclength;
unknown's avatar
unknown committed
2126

unknown's avatar
unknown committed
2127 2128
  /* Offset to first result field in table */
  field_list_offset= table->fields - (list.elements - const_fields);
unknown's avatar
unknown committed
2129 2130 2131

  if (tree_mode)
    delete_tree(tree);
unknown's avatar
unknown committed
2132 2133

  /* choose function of sort */  
unknown's avatar
unknown committed
2134
  tree_mode= distinct || arg_count_order; 
2135 2136 2137 2138 2139
  if (tree_mode)
  {
    if (arg_count_order)
    {
      if (distinct)
unknown's avatar
SCRUM  
unknown committed
2140
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order;
2141
      else
unknown's avatar
SCRUM  
unknown committed
2142
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_order;
2143 2144 2145
    }
    else
    {
2146
      compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
2147
    }
unknown's avatar
SCRUM  
unknown committed
2148
    /*
unknown's avatar
unknown committed
2149 2150
      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
unknown's avatar
SCRUM  
unknown committed
2151 2152
      contain DISTINCT and ORDER BY clauses, we don't create this tree.
    */
2153
    init_tree(tree, min(thd->variables.max_heap_table_size,
unknown's avatar
unknown committed
2154
			thd->variables.sortbuff_size/16), 0,
unknown's avatar
unknown committed
2155
              key_length, compare_key, 0, NULL, (void*) this);
unknown's avatar
unknown committed
2156 2157
    max_elements_in_tree= (key_length ? 
			   thd->variables.max_heap_table_size/key_length : 1);
2158 2159
  };

unknown's avatar
SCRUM  
unknown committed
2160 2161 2162 2163
  /*
    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)
  */
2164 2165 2166 2167 2168
  if (original)
  {
    original->table= table;
    original->tree_mode= tree_mode;
  }
2169
  DBUG_RETURN(0);
2170 2171
}

unknown's avatar
unknown committed
2172

2173 2174 2175 2176 2177 2178
/* 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;
unknown's avatar
unknown committed
2179
  tree_mode= 0; // to prevent delete_tree call on uninitialized tree
2180 2181 2182 2183
  tree= &tree_base;
}


2184 2185
String* Item_func_group_concat::val_str(String* str)
{
2186
  DBUG_ASSERT(fixed == 1);
unknown's avatar
SCRUM  
unknown committed
2187 2188
  if (null_value)
    return 0;
2189
  if (count_cut_values && !warning)
2190
    warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
2191 2192
                          ER_CUT_VALUE_GROUP_CONCAT,
                          ER(ER_CUT_VALUE_GROUP_CONCAT));
2193 2194
  if (result.length())
    return &result;
2195 2196 2197 2198 2199 2200 2201
  if (tree_mode)
  {
    tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
              left_root_right);
  }
  return &result;
}
2202

unknown's avatar
unknown committed
2203

2204 2205
void Item_func_group_concat::print(String *str)
{
2206
  str->append("group_concat(", 13);
2207
  if (distinct)
2208
    str->append("distinct ", 9);
unknown's avatar
unknown committed
2209
  for (uint i= 0; i < arg_count_field; i++)
2210 2211 2212 2213 2214 2215 2216
  {
    if (i)
      str->append(',');
    args[i]->print(str);
  }
  if (arg_count_order)
  {
2217
    str->append(" order by ", 10);
2218 2219 2220 2221 2222 2223 2224
    for (uint i= 0 ; i < arg_count_order ; i++)
    {
      if (i)
	str->append(',');
      (*order[i]->item)->print(str);
    }
  }
2225
  str->append(" separator \'", 12);
2226
  str->append(*separator);
2227
  str->append("\')", 2);
2228
}