item_sum.cc 40.9 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 27 28 29 30 31
Item_sum::Item_sum(List<Item> &list)
{
  arg_count=list.elements;
  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
}

44 45 46
// Constructor used in processing select with temporary tebles
Item_sum::Item_sum(THD *thd, Item_sum &item):
  Item_result_field(thd, item), quick_group(item.quick_group)
47 48 49 50 51 52 53
{
  arg_count= item.arg_count;
  if (arg_count <= 2)
    args=tmp_args;
  else
    if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
      return;
unknown's avatar
unknown committed
54
  for (uint i= 0; i < arg_count; i++)
55 56 57
    args[i]= item.args[i];
}

58
void Item_sum::mark_as_sum_func()
59
{
unknown's avatar
unknown committed
60 61
  current_thd->lex.current_select->with_sum_func= 1;
  with_sum_func= 1;
62
}
unknown's avatar
unknown committed
63

64

unknown's avatar
unknown committed
65 66 67 68
void Item_sum::make_field(Send_field *tmp_field)
{
  if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
  {
69 70 71 72
    ((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;
unknown's avatar
unknown committed
73
  }
74 75
  else
    init_make_field(tmp_field, field_type());
unknown's avatar
unknown committed
76 77
}

78

unknown's avatar
unknown committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
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);
}

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

String *
Item_sum_num::val_str(String *str)
{
  double nr=val();
  if (null_value)
    return 0;
127
  str->set(nr,decimals,default_charset());
unknown's avatar
unknown committed
128 129 130 131 132 133 134 135 136 137
  return str;
}


String *
Item_sum_int::val_str(String *str)
{
  longlong nr=val_int();
  if (null_value)
    return 0;
138
  str->set(nr,default_charset());
unknown's avatar
unknown committed
139 140 141 142 143
  return str;
}


bool
unknown's avatar
unknown committed
144
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
145 146 147 148 149 150 151 152 153 154 155
{
  if (!thd->allow_sum_func)
  {
    my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
    return 1;
  }
  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
156
    if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
unknown's avatar
unknown committed
157 158 159 160 161 162 163 164 165 166
      return 1;
    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
167
  fixed= 1;
unknown's avatar
unknown committed
168 169 170 171 172
  return 0;
}


bool
unknown's avatar
unknown committed
173
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
174 175 176 177 178 179 180 181
{
  Item *item=args[0];
  if (!thd->allow_sum_func)
  {
    my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
    return 1;
  }
  thd->allow_sum_func=0;			// No included group funcs
unknown's avatar
unknown committed
182
  if (item->fix_fields(thd, tables, args) || item->check_cols(1))
unknown's avatar
unknown committed
183 184 185
    return 1;
  hybrid_type=item->result_type();
  if (hybrid_type == INT_RESULT)
186 187
  {
    cmp_charset= &my_charset_bin;
188
    max_length=20;
189
  }
unknown's avatar
unknown committed
190
  else if (hybrid_type == REAL_RESULT)
191 192
  {
    cmp_charset= &my_charset_bin;
unknown's avatar
unknown committed
193
    max_length=float_length(decimals);
194
  }else
195
  {
196
    cmp_charset= item->charset();
unknown's avatar
unknown committed
197
    max_length=item->max_length;
198
  }
unknown's avatar
unknown committed
199 200
  decimals=item->decimals;
  maybe_null=item->maybe_null;
201
  unsigned_flag=item->unsigned_flag;
unknown's avatar
unknown committed
202
  set_charset(item->charset());
unknown's avatar
unknown committed
203 204 205 206
  result_field=0;
  null_value=1;
  fix_length_and_dec();
  thd->allow_sum_func=1;			// Allow group functions
207 208 209 210
  if (item->type() == Item::FIELD_ITEM)
    hybrid_field_type= ((Item_field*) item)->field->type();
  else
    hybrid_field_type= Item::field_type();
211
  fixed= 1;
unknown's avatar
unknown committed
212 213 214 215 216 217 218 219
  return 0;
}


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

220
Item *Item_sum_sum::copy_or_same(THD* thd)
unknown's avatar
unknown committed
221
{
222
  return new (&thd->mem_root) Item_sum_sum(thd, *this);
unknown's avatar
unknown committed
223 224
}

225 226 227 228 229 230 231 232

bool Item_sum_sum::reset()
{
  null_value=1; sum=0.0;
  return Item_sum_sum::add();
}


unknown's avatar
unknown committed
233 234 235
bool Item_sum_sum::add()
{
  sum+=args[0]->val();
unknown's avatar
unknown committed
236 237
  if (!args[0]->null_value)
    null_value= 0;
unknown's avatar
unknown committed
238 239 240
  return 0;
}

241

unknown's avatar
unknown committed
242 243 244 245 246 247
double Item_sum_sum::val()
{
  return sum;
}


248
Item *Item_sum_count::copy_or_same(THD* thd)
unknown's avatar
unknown committed
249
{
250
  return new (&thd->mem_root) Item_sum_count(thd, *this);
unknown's avatar
unknown committed
251 252
}

253 254 255 256 257 258 259 260

bool Item_sum_count::reset()
{
  count=0;
  return add();
}


unknown's avatar
unknown committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
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()
{
  return (longlong) count;
}

/*
280
  Avgerage
unknown's avatar
unknown committed
281 282
*/

283
Item *Item_sum_avg::copy_or_same(THD* thd)
unknown's avatar
unknown committed
284
{
285
  return new (&thd->mem_root) Item_sum_avg(thd, *this);
unknown's avatar
unknown committed
286 287
}

288 289 290 291 292 293 294 295

bool Item_sum_avg::reset()
{
  sum=0.0; count=0;
  return Item_sum_avg::add();
}


unknown's avatar
unknown committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
bool Item_sum_avg::add()
{
  double nr=args[0]->val();
  if (!args[0]->null_value)
  {
    sum+=nr;
    count++;
  }
  return 0;
}

double Item_sum_avg::val()
{
  if (!count)
  {
    null_value=1;
    return 0.0;
  }
  null_value=0;
  return sum/ulonglong2double(count);
}


/*
320
  Standard deviation
unknown's avatar
unknown committed
321 322
*/

unknown's avatar
unknown committed
323
double Item_sum_std::val()
unknown's avatar
unknown committed
324
{
unknown's avatar
unknown committed
325 326
  double tmp= Item_sum_variance::val();
  return tmp <= 0.0 ? 0.0 : sqrt(tmp);
unknown's avatar
unknown committed
327 328
}

329 330 331 332 333 334
Item *Item_sum_std::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_std(thd, *this);
}


unknown's avatar
unknown committed
335
/*
336
  Variance
unknown's avatar
unknown committed
337 338
*/

339 340 341 342 343 344 345
Item *Item_sum_variance::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_variance(thd, *this);
}


bool Item_sum_variance::reset()
unknown's avatar
unknown committed
346 347 348
{
  sum=sum_sqr=0.0; 
  count=0; 
349
  return Item_sum_variance::add();
unknown's avatar
unknown committed
350 351 352
}

bool Item_sum_variance::add()
unknown's avatar
unknown committed
353 354 355 356 357 358 359 360 361 362 363
{
  double nr=args[0]->val();
  if (!args[0]->null_value)
  {
    sum+=nr;
    sum_sqr+=nr*nr;
    count++;
  }
  return 0;
}

unknown's avatar
unknown committed
364
double Item_sum_variance::val()
unknown's avatar
unknown committed
365 366 367 368 369 370 371 372 373 374
{
  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
375
  return tmp2 <= 0.0 ? 0.0 : tmp2;
unknown's avatar
unknown committed
376 377
}

unknown's avatar
unknown committed
378
void Item_sum_variance::reset_field()
unknown's avatar
unknown committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
{
  double nr=args[0]->val();
  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
395
void Item_sum_variance::update_field(int offset)
unknown's avatar
unknown committed
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
{
  double nr,old_nr,old_sqr;
  longlong field_count;
  char *res=result_field->ptr;

  float8get(old_nr,res+offset);
  float8get(old_sqr,res+offset+sizeof(double));
  field_count=sint8korr(res+offset+sizeof(double)*2);

  nr=args[0]->val();
  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 */

double Item_sum_hybrid::val()
{
421
  int err;
unknown's avatar
unknown committed
422 423
  if (null_value)
    return 0.0;
424 425
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
426
    String *res;  res=val_str(&str_value);
427
    return (res ? my_strntod(res->charset(), (char*) res->ptr(),res->length(),
428
			     (char**) 0, &err) : 0.0);
429 430 431 432 433 434
  case INT_RESULT:
    if (unsigned_flag)
      return ulonglong2double(sum_int);
    return (double) sum_int;
  case REAL_RESULT:
    return sum;
435
  case ROW_RESULT:
unknown's avatar
unknown committed
436
  default:
unknown's avatar
unknown committed
437 438 439
    // This case should never be choosen
    DBUG_ASSERT(0);
    return 0;
unknown's avatar
unknown committed
440
  }
441 442 443 444 445 446 447 448 449 450
  return 0;					// Keep compiler happy
}

longlong Item_sum_hybrid::val_int()
{
  if (null_value)
    return 0;
  if (hybrid_type == INT_RESULT)
    return sum_int;
  return (longlong) Item_sum_hybrid::val();
unknown's avatar
unknown committed
451 452 453 454 455 456 457 458
}


String *
Item_sum_hybrid::val_str(String *str)
{
  if (null_value)
    return 0;
459 460
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
461
    return &value;
462
  case REAL_RESULT:
463
    str->set(sum,decimals,default_charset());
464 465 466
    break;
  case INT_RESULT:
    if (unsigned_flag)
467
      str->set((ulonglong) sum_int,default_charset());
468
    else
469
      str->set((longlong) sum_int,default_charset());
470
    break;
471
  case ROW_RESULT:
unknown's avatar
unknown committed
472
  default:
unknown's avatar
unknown committed
473 474 475
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
476 477
  }
  return str;					// Keep compiler happy
unknown's avatar
unknown committed
478 479
}

480 481 482 483 484 485 486

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


unknown's avatar
unknown committed
487 488
bool Item_sum_min::add()
{
489 490
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
491 492 493
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
494
	(null_value || sortcmp(&value,result,cmp_charset) > 0))
unknown's avatar
unknown committed
495 496 497 498 499
    {
      value.copy(*result);
      null_value=0;
    }
  }
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514
  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
515 516
  {
    double nr=args[0]->val();
517
    if (!args[0]->null_value && (null_value || nr < sum))
unknown's avatar
unknown committed
518 519 520 521 522
    {
      sum=nr;
      null_value=0;
    }
  }
523
  break;
524
  case ROW_RESULT:
unknown's avatar
unknown committed
525
  default:
unknown's avatar
unknown committed
526 527 528
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
529 530 531 532 533
  }
  return 0;
}


534 535 536 537 538 539
Item *Item_sum_max::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_max(thd, *this);
}


540 541 542 543
bool Item_sum_max::add()
{
  switch (hybrid_type) {
  case STRING_RESULT:
unknown's avatar
unknown committed
544 545 546
  {
    String *result=args[0]->val_str(&tmp_value);
    if (!args[0]->null_value &&
547
	(null_value || sortcmp(&value,result,cmp_charset) < 0))
unknown's avatar
unknown committed
548 549 550 551 552
    {
      value.copy(*result);
      null_value=0;
    }
  }
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
  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:
  {
    double nr=args[0]->val();
    if (!args[0]->null_value && (null_value || nr > sum))
    {
      sum=nr;
      null_value=0;
    }
  }
  break;
577
  case ROW_RESULT:
unknown's avatar
unknown committed
578
  default:
unknown's avatar
unknown committed
579 580 581
    // This case should never be choosen
    DBUG_ASSERT(0);
    break;
582
  }
unknown's avatar
unknown committed
583 584 585 586 587 588 589 590 591 592 593
  return 0;
}


/* bit_or and bit_and */

longlong Item_sum_bit::val_int()
{
  return (longlong) bits;
}

594 595 596 597 598 599 600 601

bool Item_sum_bit::reset()
{
  bits=reset_bits;
  return add();
}

Item *Item_sum_or::copy_or_same(THD* thd)
unknown's avatar
unknown committed
602
{
603
  return new (&thd->mem_root) Item_sum_or(thd, *this);
unknown's avatar
unknown committed
604 605
}

606

unknown's avatar
unknown committed
607 608 609 610 611 612 613 614
bool Item_sum_or::add()
{
  ulonglong value= (ulonglong) args[0]->val_int();
  if (!args[0]->null_value)
    bits|=value;
  return 0;
}

615 616 617 618 619 620
Item *Item_sum_and::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_and(thd, *this);
}


unknown's avatar
unknown committed
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
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()
{
  double nr=args[0]->val();
  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];
657
    String tmp(buff,sizeof(buff),result_field->charset()),*res;
unknown's avatar
unknown committed
658 659 660 661 662 663 664 665 666 667

    res=args[0]->val_str(&tmp);
    if (args[0]->null_value)
    {
      result_field->set_null();
      result_field->reset();
    }
    else
    {
      result_field->set_notnull();
668
      result_field->store(res->ptr(),res->length(),tmp.charset());
unknown's avatar
unknown committed
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    }
  }
  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
  {
    double nr=args[0]->val();

    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()
{
  double nr=args[0]->val();			// Nulls also return 0
  float8store(result_field->ptr,nr);
unknown's avatar
unknown committed
710 711 712 713
  if (args[0]->null_value)
    result_field->set_null();
  else
    result_field->set_notnull();
unknown's avatar
unknown committed
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
}


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()
{
  double nr=args[0]->val();
  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()
{
  char *res=result_field->ptr;
  ulonglong nr=(ulonglong) args[0]->val_int();
  int8store(res,nr);
}

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

void Item_sum_sum::update_field(int offset)
{
  double old_nr,nr;
  char *res=result_field->ptr;

  float8get(old_nr,res+offset);
  nr=args[0]->val();
  if (!args[0]->null_value)
unknown's avatar
unknown committed
769
  {
unknown's avatar
unknown committed
770
    old_nr+=nr;
unknown's avatar
unknown committed
771 772
    result_field->set_notnull();
  }
unknown's avatar
unknown committed
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
  float8store(res,old_nr);
}


void Item_sum_count::update_field(int offset)
{
  longlong nr;
  char *res=result_field->ptr;

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


void Item_sum_avg::update_field(int offset)
{
  double nr,old_nr;
  longlong field_count;
  char *res=result_field->ptr;

  float8get(old_nr,res+offset);
  field_count=sint8korr(res+offset+sizeof(double));

  nr=args[0]->val();
  if (!args[0]->null_value)
  {
    old_nr+=nr;
    field_count++;
  }
  float8store(res,old_nr);
  res+=sizeof(double);
  int8store(res,field_count);
}

void Item_sum_hybrid::update_field(int offset)
{
  if (hybrid_type == STRING_RESULT)
    min_max_update_str_field(offset);
  else if (hybrid_type == INT_RESULT)
    min_max_update_int_field(offset);
  else
    min_max_update_real_field(offset);
}


void
Item_sum_hybrid::min_max_update_str_field(int offset)
{
  String *res_str=args[0]->val_str(&value);

  if (args[0]->null_value)
    result_field->copy_from_tmp(offset);	// Use old value
  else
  {
    res_str->strip_sp();
    result_field->ptr+=offset;			// Get old max/min
    result_field->val_str(&tmp_value,&tmp_value);
    result_field->ptr-=offset;

    if (result_field->is_null() ||
841
	(cmp_sign * sortcmp(res_str,&tmp_value,cmp_charset)) < 0)
842
      result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
unknown's avatar
unknown committed
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884
    else
    {						// Use old value
      char *res=result_field->ptr;
      memcpy(res,res+offset,result_field->pack_length());
    }
    result_field->set_notnull();
  }
}


void
Item_sum_hybrid::min_max_update_real_field(int offset)
{
  double nr,old_nr;

  result_field->ptr+=offset;
  old_nr=result_field->val_real();
  nr=args[0]->val();
  if (!args[0]->null_value)
  {
    if (result_field->is_null(offset) ||
	(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
      old_nr=nr;
    result_field->set_notnull();
  }
  else if (result_field->is_null(offset))
    result_field->set_null();
  result_field->ptr-=offset;
  result_field->store(old_nr);
}


void
Item_sum_hybrid::min_max_update_int_field(int offset)
{
  longlong nr,old_nr;

  result_field->ptr+=offset;
  old_nr=result_field->val_int();
  nr=args[0]->val_int();
  if (!args[0]->null_value)
  {
885
    if (result_field->is_null(offset))
unknown's avatar
unknown committed
886
      old_nr=nr;
887 888 889 890 891 892
    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
893
      if ((cmp_sign > 0) ^ (!res))
894 895
	old_nr=nr;
    }
unknown's avatar
unknown committed
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
    result_field->set_notnull();
  }
  else if (result_field->is_null(offset))
    result_field->set_null();
  result_field->ptr-=offset;
  result_field->store(old_nr);
}


void Item_sum_or::update_field(int offset)
{
  ulonglong nr;
  char *res=result_field->ptr;

  nr=uint8korr(res+offset);
  nr|= (ulonglong) args[0]->val_int();
  int8store(res,nr);
}


void Item_sum_and::update_field(int offset)
{
  ulonglong nr;
  char *res=result_field->ptr;

  nr=uint8korr(res+offset);
  nr&= (ulonglong) args[0]->val_int();
  int8store(res,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;
}

double Item_avg_field::val()
{
  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)
{
  double nr=Item_avg_field::val();
  if (null_value)
    return 0;
958
  str->set(nr,decimals,default_charset());
unknown's avatar
unknown committed
959 960 961 962
  return str;
}

Item_std_field::Item_std_field(Item_sum_std *item)
unknown's avatar
unknown committed
963 964 965 966 967 968 969 970 971 972 973
  : Item_variance_field(item)
{
}

double Item_std_field::val()
{
  double tmp= Item_variance_field::val();
  return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}

Item_variance_field::Item_variance_field(Item_sum_variance *item)
unknown's avatar
unknown committed
974 975 976 977 978 979 980 981
{
  name=item->name;
  decimals=item->decimals;
  max_length=item->max_length;
  field=item->result_field;
  maybe_null=1;
}

unknown's avatar
unknown committed
982
double Item_variance_field::val()
unknown's avatar
unknown committed
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
{
  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
998
  return tmp2 <= 0.0 ? 0.0 : tmp2;
unknown's avatar
unknown committed
999 1000
}

unknown's avatar
unknown committed
1001
String *Item_variance_field::val_str(String *str)
unknown's avatar
unknown committed
1002 1003 1004 1005
{
  double nr=val();
  if (null_value)
    return 0;
1006
  str->set(nr,decimals,default_charset());
unknown's avatar
unknown committed
1007 1008 1009 1010 1011 1012 1013 1014 1015
  return str;
}

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

#include "sql_select.h"

1016
int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
1017
{
1018
  return memcmp(key1, key2, *(uint*) arg);
1019 1020
}

1021
int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
1022
{
1023 1024 1025 1026
  Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
  CHARSET_INFO *cs=item->key_charset;
  uint len=item->key_length;
  return my_strnncoll(cs, (const uchar*) key1, len, (const uchar*) key2, len);
1027 1028
}

unknown's avatar
unknown committed
1029 1030 1031 1032 1033 1034 1035
/*
  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
*/

1036 1037 1038
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
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
  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++;
    int res = f->key_cmp(key1, key2);
    if (res)
      return res;
    key1 += len;
    key2 += len;
  }
1052 1053 1054
  return 0;
}

unknown's avatar
unknown committed
1055 1056 1057 1058
/*
  helper function for walking the tree when we dump it to MyISAM -
  tree_walk will call it for each leaf
*/
1059

1060 1061 1062
int dump_leaf(byte* key, uint32 count __attribute__((unused)),
		     Item_sum_count_distinct* item)
{
unknown's avatar
unknown committed
1063
  byte* buf = item->table->record[0];
1064
  int error;
unknown's avatar
unknown committed
1065 1066
  /*
    The first item->rec_offset bytes are taken care of with
unknown's avatar
unknown committed
1067
    restore_record(table,default_values) in setup()
unknown's avatar
unknown committed
1068
  */
1069
  memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
1070 1071
  if ((error = item->table->file->write_row(buf)))
  {
unknown's avatar
unknown committed
1072 1073 1074
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
      return 1;
1075 1076 1077
  }
  return 0;
}
1078

unknown's avatar
unknown committed
1079

unknown's avatar
unknown committed
1080 1081
Item_sum_count_distinct::~Item_sum_count_distinct()
{
unknown's avatar
unknown committed
1082 1083 1084 1085
  /*
    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 )
  */
1086 1087 1088 1089 1090 1091 1092 1093
  if (!original)
  {
    if (table)
      free_tmp_table(current_thd, table);
    delete tmp_table_param;
    if (use_tree)
      delete_tree(tree);
  }
unknown's avatar
unknown committed
1094 1095
}

unknown's avatar
unknown committed
1096 1097
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
					 Item **ref)
unknown's avatar
unknown committed
1098
{
1099
  if (Item_sum_num::fix_fields(thd, tables, ref))
unknown's avatar
unknown committed
1100 1101 1102 1103
    return 1;
  return 0;
}

1104 1105 1106 1107 1108 1109 1110 1111 1112 1113
/* 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;
  tree= &tree_base;
}


unknown's avatar
unknown committed
1114 1115 1116
bool Item_sum_count_distinct::setup(THD *thd)
{
  List<Item> list;
1117
  SELECT_LEX *select_lex= thd->lex.current_select->select_lex();
1118 1119 1120
  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
    return 1;
    
1121 1122 1123
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
    return 1;

unknown's avatar
unknown committed
1124 1125
  /* Create a table with an unique key over all parameters */
  for (uint i=0; i < arg_count ; i++)
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
  {
    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
1139
  count_field_types(tmp_table_param,list,0);
unknown's avatar
unknown committed
1140 1141 1142 1143 1144
  if (table)
  {
    free_tmp_table(thd, table);
    tmp_table_param->cleanup();
  }
1145
  if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
unknown's avatar
unknown committed
1146
				0,
1147
				select_lex->options | thd->options,
unknown's avatar
unknown committed
1148
				HA_POS_ERROR)))
unknown's avatar
unknown committed
1149 1150
    return 1;
  table->file->extra(HA_EXTRA_NO_ROWS);		// Don't update rows
1151
  table->no_rows=1;
1152

unknown's avatar
unknown committed
1153

unknown's avatar
unknown committed
1154 1155 1156 1157 1158
  // 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
1159

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

unknown's avatar
unknown committed
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
    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];
      switch(field->type())
      {
      case FIELD_TYPE_STRING:
      case FIELD_TYPE_VAR_STRING:
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
	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
1190 1191 1192 1193 1194 1195 1196
	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;
1197
	cmp_arg = (void*) &key_length;
unknown's avatar
unknown committed
1198 1199
	break;
      }
1200 1201 1202
      key_charset = field->charset();
      key_length  = field->pack_length();
      rec_offset  = 1;
1203
    }
unknown's avatar
unknown committed
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    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;

1214
      for (key_length = 0, lengths=field_lengths; field < field_end; ++field)
unknown's avatar
unknown committed
1215 1216
      {
	uint32 length= (*field)->pack_length();
1217
	key_length += length;
unknown's avatar
unknown committed
1218 1219 1220 1221
	*lengths++ = length;
	if (!(*field)->binary())
	  all_binary = 0;			// Can't break loop here
      }
1222
      rec_offset = table->reclength - key_length;
unknown's avatar
unknown committed
1223 1224 1225
      if (all_binary)
      {
	compare_key = (qsort_cmp2)simple_raw_key_cmp;
1226
	cmp_arg = (void*) &key_length;
unknown's avatar
unknown committed
1227 1228 1229 1230
      }
      else
      {
	compare_key = (qsort_cmp2) composite_key_cmp ;
1231
	cmp_arg = (void*) this;
unknown's avatar
unknown committed
1232 1233 1234
      }
    }

1235 1236
    init_tree(tree, min(thd->variables.max_heap_table_size,
			thd->variables.sortbuff_size/16), 0,
1237
	      key_length, compare_key, 0, NULL, cmp_arg);
unknown's avatar
unknown committed
1238 1239 1240
    use_tree = 1;

    /*
1241
      The only time key_length could be 0 is if someone does
unknown's avatar
unknown committed
1242 1243 1244 1245
      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
    */
1246 1247
    max_elements_in_tree = ((key_length) ? 
			    thd->variables.max_heap_table_size/key_length : 1);
1248 1249 1250 1251 1252 1253

  }
  if (original)
  {
    original->table= table;
    original->use_tree= use_tree;
unknown's avatar
unknown committed
1254
  }
unknown's avatar
unknown committed
1255 1256 1257
  return 0;
}

unknown's avatar
unknown committed
1258

1259 1260
int Item_sum_count_distinct::tree_to_myisam()
{
unknown's avatar
unknown committed
1261
  if (create_myisam_from_heap(current_thd, table, tmp_table_param,
unknown's avatar
unknown committed
1262
			      HA_ERR_RECORD_FILE_FULL, 1) ||
1263
      tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
unknown's avatar
unknown committed
1264
		left_root_right))
1265
    return 1;
1266
  delete_tree(tree);
1267 1268 1269
  use_tree = 0;
  return 0;
}
unknown's avatar
unknown committed
1270

1271 1272 1273 1274 1275 1276 1277 1278

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


bool Item_sum_count_distinct::reset()
unknown's avatar
unknown committed
1279
{
unknown's avatar
merge  
unknown committed
1280
  if (use_tree)
1281
    reset_tree(tree);
unknown's avatar
merge  
unknown committed
1282
  else if (table)
1283 1284 1285 1286 1287
  {
    table->file->extra(HA_EXTRA_NO_CACHE);
    table->file->delete_all_rows();
    table->file->extra(HA_EXTRA_WRITE_CACHE);
  }
1288
  return add();
unknown's avatar
unknown committed
1289 1290 1291 1292 1293
}

bool Item_sum_count_distinct::add()
{
  int error;
1294 1295
  if (always_null)
    return 0;
unknown's avatar
unknown committed
1296
  copy_fields(tmp_table_param);
unknown's avatar
unknown committed
1297
  copy_funcs(tmp_table_param->items_to_copy);
unknown's avatar
unknown committed
1298

1299 1300 1301 1302
  for (Field **field=table->field ; *field ; field++)
    if ((*field)->is_real_null(0))
      return 0;					// Don't count NULL

unknown's avatar
unknown committed
1303 1304 1305 1306 1307 1308
  if (use_tree)
  {
    /*
      If the tree got too big, convert to MyISAM, otherwise insert into the
      tree.
    */
1309
    if (tree->elements_in_tree > max_elements_in_tree)
1310
    {
1311
      if (tree_to_myisam())
1312 1313
	return 1;
    }
1314 1315
    else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
			  tree->custom_arg))
unknown's avatar
unknown committed
1316 1317
      return 1;
  }
1318
  else if ((error=table->file->write_row(table->record[0])))
unknown's avatar
unknown committed
1319 1320 1321 1322
  {
    if (error != HA_ERR_FOUND_DUPP_KEY &&
	error != HA_ERR_FOUND_DUPP_UNIQUE)
    {
unknown's avatar
unknown committed
1323 1324
      if (create_myisam_from_heap(current_thd, table, tmp_table_param, error,
				  1))
unknown's avatar
unknown committed
1325 1326 1327 1328 1329 1330
	return 1;				// Not a table_is_full error
    }
  }
  return 0;
}

unknown's avatar
unknown committed
1331

unknown's avatar
unknown committed
1332 1333 1334 1335
longlong Item_sum_count_distinct::val_int()
{
  if (!table)					// Empty query
    return LL(0);
unknown's avatar
unknown committed
1336
  if (use_tree)
1337
    return tree->elements_in_tree;
unknown's avatar
unknown committed
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
  table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
  return table->file->records;
}

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

1351
bool Item_udf_sum::reset()
unknown's avatar
unknown committed
1352 1353 1354
{
  DBUG_ENTER("Item_udf_sum::reset");
  udf.reset(&null_value);
1355
  DBUG_RETURN(0);
unknown's avatar
unknown committed
1356 1357 1358 1359
}

bool Item_udf_sum::add()
{
1360
  DBUG_ENTER("Item_udf_sum::add");
unknown's avatar
unknown committed
1361 1362 1363 1364
  udf.add(&null_value);
  DBUG_RETURN(0);
}

1365 1366 1367 1368 1369
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_udf_float(thd, *this);
}

unknown's avatar
unknown committed
1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
double Item_sum_udf_float::val()
{
  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)
{
  double nr=val();
  if (null_value)
    return 0;					/* purecov: inspected */
  else
1384
    str->set(nr,decimals,default_charset());
unknown's avatar
unknown committed
1385 1386 1387 1388
  return str;
}


1389 1390 1391 1392 1393 1394
Item *Item_sum_udf_int::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_sum_udf_int(thd, *this);
}


unknown's avatar
unknown committed
1395 1396 1397 1398 1399 1400 1401 1402
longlong Item_sum_udf_int::val_int()
{
  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));
}

1403

unknown's avatar
unknown committed
1404 1405 1406 1407 1408 1409
String *Item_sum_udf_int::val_str(String *str)
{
  longlong nr=val_int();
  if (null_value)
    return 0;
  else
1410
    str->set(nr,default_charset());
unknown's avatar
unknown committed
1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
  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;
}

1425 1426 1427 1428 1429 1430 1431

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


unknown's avatar
unknown committed
1432 1433 1434 1435 1436 1437 1438 1439 1440
String *Item_sum_udf_str::val_str(String *str)
{
  DBUG_ENTER("Item_sum_udf_str::str");
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  DBUG_RETURN(res);
}

#endif /* HAVE_DLOPEN */
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451


/*****************************************************************************
 GROUP_CONCAT function
 Syntax:
 GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...] 
   [SEPARATOR str_const])
 concat of values from "group by" operation
*****************************************************************************/

/*
unknown's avatar
SCRUM  
unknown committed
1452 1453
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,...)
1454 1455
*/

unknown's avatar
unknown committed
1456 1457
int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
				       byte* key2)
1458
{
unknown's avatar
SCRUM  
unknown committed
1459
  Item_func_group_concat* item= (Item_func_group_concat*)arg;
unknown's avatar
unknown committed
1460

unknown's avatar
unknown committed
1461
  for (uint i= 0; i < item->arg_count_field; i++)
1462
  {
unknown's avatar
unknown committed
1463
    Item *field_item= item->args[i];
unknown's avatar
SCRUM  
unknown committed
1464
    Field *field= field_item->tmp_table_field();
1465 1466
    if (field)
    {
unknown's avatar
unknown committed
1467
      uint offset= field->abs_offset;
1468

unknown's avatar
SCRUM  
unknown committed
1469 1470
      int res= field->key_cmp(key1 + offset, key2 + offset);
      /*
1471
        if key1 and key2 is not equal than field->key_cmp return offset. This
unknown's avatar
unknown committed
1472
        function must return value 1 for this case.
unknown's avatar
SCRUM  
unknown committed
1473
      */
1474 1475 1476
      if (res)
        return 1;
    }
unknown's avatar
unknown committed
1477
  } 
1478 1479 1480
  return 0;
}

1481

1482
/*
unknown's avatar
SCRUM  
unknown committed
1483 1484
  function of sort for syntax:
  GROUP_CONCAT(expr,... ORDER BY col,... )
1485 1486
*/

unknown's avatar
unknown committed
1487
int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
1488
{
unknown's avatar
SCRUM  
unknown committed
1489
  Item_func_group_concat* item= (Item_func_group_concat*)arg;
unknown's avatar
unknown committed
1490

unknown's avatar
unknown committed
1491
  for (uint i=0; i < item->arg_count_order; i++)
1492
  {
unknown's avatar
SCRUM  
unknown committed
1493 1494 1495
    ORDER *order_item= item->order[i];
    Item *item= *order_item->item;
    Field *field= item->tmp_table_field();
1496 1497
    if (field)
    {
unknown's avatar
unknown committed
1498
      uint offset= field->abs_offset;
1499

unknown's avatar
SCRUM  
unknown committed
1500 1501
      bool dir= order_item->asc;
      int res= field->key_cmp(key1 + offset, key2 + offset);
1502 1503 1504
      if (res)
        return dir ? res : -res;
    }
unknown's avatar
unknown committed
1505
  } 
unknown's avatar
SCRUM  
unknown committed
1506
  /*
1507
    We can't return 0 because tree class remove this item as double value. 
unknown's avatar
SCRUM  
unknown committed
1508
  */   
1509 1510 1511
  return 1;
}

1512

1513
/*
unknown's avatar
SCRUM  
unknown committed
1514 1515
  function of sort for syntax:
  GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
1516
*/
unknown's avatar
SCRUM  
unknown committed
1517

unknown's avatar
unknown committed
1518 1519
int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
						 byte* key2)
1520 1521 1522 1523 1524 1525
{
  if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
    return 0;
  return(group_concat_key_cmp_with_order(arg,key1,key2));
}

1526

1527
/*
unknown's avatar
SCRUM  
unknown committed
1528 1529
  create result
  item is pointer to Item_func_group_concat
1530
*/
unknown's avatar
SCRUM  
unknown committed
1531

unknown's avatar
unknown committed
1532
int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
unknown's avatar
SCRUM  
unknown committed
1533
                  Item_func_group_concat *group_concat_item)
1534 1535 1536 1537
{
  char buff[MAX_FIELD_WIDTH];
  String tmp((char *)&buff,sizeof(buff),default_charset_info);
  String tmp2((char *)&buff,sizeof(buff),default_charset_info);
unknown's avatar
unknown committed
1538
  
1539 1540
  tmp.length(0);
  
unknown's avatar
unknown committed
1541
  for (uint i= 0; i < group_concat_item->arg_show_fields; i++)
1542
  {
unknown's avatar
unknown committed
1543
    Item *show_item= group_concat_item->args[i];
1544 1545
    if (!show_item->const_item())
    {
unknown's avatar
SCRUM  
unknown committed
1546 1547
      Field *f= show_item->tmp_table_field();
      char *sv= f->ptr;
unknown's avatar
unknown committed
1548
      f->ptr= (char *)key + f->abs_offset;
unknown's avatar
SCRUM  
unknown committed
1549 1550 1551
      String *res= f->val_str(&tmp,&tmp2);
      group_concat_item->result.append(*res);
      f->ptr= sv;
1552 1553 1554
    }
    else 
    {
unknown's avatar
SCRUM  
unknown committed
1555
      String *res= show_item->val_str(&tmp);
1556
      if (res)
unknown's avatar
SCRUM  
unknown committed
1557
        group_concat_item->result.append(*res);
1558 1559
    }
  }
unknown's avatar
SCRUM  
unknown committed
1560
  if (group_concat_item->tree_mode) // Last item of tree
1561
  {
unknown's avatar
SCRUM  
unknown committed
1562 1563 1564 1565
    group_concat_item->show_elements++;
    if (group_concat_item->show_elements < 
        group_concat_item->tree->elements_in_tree)
      group_concat_item->result.append(*group_concat_item->separator);
1566 1567 1568
  }
  else
  {
unknown's avatar
SCRUM  
unknown committed
1569
    group_concat_item->result.append(*group_concat_item->separator); 
1570
  }
unknown's avatar
SCRUM  
unknown committed
1571 1572 1573 1574 1575 1576 1577 1578 1579
  /*
    if length of result more than group_concat_max_len - stop !
  */  
  if (group_concat_item->result.length() > 
      group_concat_item->group_concat_max_len)
  {
    group_concat_item->count_cut_values++;
    group_concat_item->result.length(group_concat_item->group_concat_max_len);
    group_concat_item->warning_for_row= TRUE;
1580 1581 1582 1583 1584
    return 1;
  }
  return 0;
}

1585

1586
/*
unknown's avatar
SCRUM  
unknown committed
1587 1588 1589 1590 1591
  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
1592
*/
unknown's avatar
SCRUM  
unknown committed
1593

unknown's avatar
unknown committed
1594
Item_func_group_concat::Item_func_group_concat(bool is_distinct,
1595 1596 1597
					       List<Item> *is_select,
					       SQL_LIST *is_order,
					       String *is_separator)
unknown's avatar
unknown committed
1598 1599 1600 1601
  :Item_sum(), tmp_table_param(0), max_elements_in_tree(0), warning(0),
   warning_available(0), key_length(0), rec_offset(0),
   tree_mode(0), distinct(is_distinct), warning_for_row(0),
   separator(is_separator), tree(&tree_base), table(0),
1602
   order(0), tables_list(0),
unknown's avatar
unknown committed
1603 1604 1605
   show_elements(0), arg_count_order(0), arg_count_field(0),
   arg_show_fields(0), count_cut_values(0)
   
1606
{
unknown's avatar
SCRUM  
unknown committed
1607 1608
  original= 0;
  quick_group= 0;
1609
  mark_as_sum_func();
1610 1611
  item_thd= current_thd;
  SELECT_LEX *select_lex= item_thd->lex.current_select->select_lex();
unknown's avatar
SCRUM  
unknown committed
1612
  order= 0;
1613 1614
  group_concat_max_len= item_thd->variables.group_concat_max_len;

1615
    
unknown's avatar
SCRUM  
unknown committed
1616 1617 1618 1619 1620 1621 1622 1623 1624 1625
  arg_show_fields= arg_count_field= is_select->elements;
  arg_count_order= is_order ? is_order->elements : 0;
  arg_count= arg_count_field;
  
  /*
    We need to allocate:
    args - arg_count+arg_count_order (for possible order items in temporare 
           tables)
    order - arg_count_order
  */
unknown's avatar
unknown committed
1626
  args= (Item**) sql_alloc(sizeof(Item*)*(arg_count+arg_count_order)+
unknown's avatar
unknown committed
1627
			   sizeof(ORDER*)*arg_count_order);
unknown's avatar
SCRUM  
unknown committed
1628
  if (!args)
unknown's avatar
unknown committed
1629
    return;
unknown's avatar
unknown committed
1630 1631

  /* fill args items of show and sort */
unknown's avatar
SCRUM  
unknown committed
1632 1633 1634
  int i= 0;
  List_iterator_fast<Item> li(*is_select);
  Item *item_select;
1635

unknown's avatar
unknown committed
1636
  for ( ; (item_select= li++) ; i++)
unknown's avatar
unknown committed
1637
    args[i]= item_select;
unknown's avatar
unknown committed
1638 1639

  if (arg_count_order) 
unknown's avatar
SCRUM  
unknown committed
1640
  {
unknown's avatar
unknown committed
1641
    i= 0;
unknown's avatar
unknown committed
1642
    order= (ORDER**)(args + arg_count + arg_count_order);
unknown's avatar
unknown committed
1643
    for (ORDER *order_item= (ORDER*) is_order->first;
unknown's avatar
SCRUM  
unknown committed
1644 1645
                order_item != NULL;
                order_item= order_item->next)
1646
    {
unknown's avatar
unknown committed
1647
      order[i++]= order_item;
1648 1649 1650 1651
    }
  }
}

unknown's avatar
SCRUM  
unknown committed
1652

1653 1654
Item_func_group_concat::~Item_func_group_concat()
{
unknown's avatar
SCRUM  
unknown committed
1655 1656 1657 1658
  /*
    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 )
  */
1659 1660
  if (!original)
  {
1661
    THD *thd= current_thd;
1662 1663 1664 1665
    if (warning_available)
    {
      char warn_buff[MYSQL_ERRMSG_SIZE];
      sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
1666
      warning->set_msg(thd, warn_buff);
1667 1668
    }
    if (table)
1669
      free_tmp_table(thd, table);
unknown's avatar
unknown committed
1670
    delete tmp_table_param;
1671 1672 1673 1674 1675 1676
    if (tree_mode)
      delete_tree(tree); 
  }
}


1677 1678 1679 1680 1681 1682 1683
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
  return new (&thd->mem_root) Item_func_group_concat(thd, *this);
}


bool Item_func_group_concat::reset()
1684 1685 1686
{
  result.length(0);
  result.copy();
unknown's avatar
SCRUM  
unknown committed
1687 1688
  null_value= TRUE;
  warning_for_row= false;
1689 1690 1691 1692 1693 1694 1695 1696
  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);
1697
  return add();
1698 1699
}

unknown's avatar
SCRUM  
unknown committed
1700

1701 1702
bool Item_func_group_concat::add()
{
unknown's avatar
BUG  
unknown committed
1703 1704
  if (always_null)
    return 0;
1705 1706 1707
  copy_fields(tmp_table_param);
  copy_funcs(tmp_table_param->items_to_copy);

unknown's avatar
SCRUM  
unknown committed
1708
  bool record_is_null= TRUE;
unknown's avatar
unknown committed
1709
  for (uint i= 0; i < arg_show_fields; i++)
1710
  {
unknown's avatar
unknown committed
1711
    Item *show_item= args[i];
unknown's avatar
SCRUM  
unknown committed
1712
    if (!show_item->const_item())
1713
    {
unknown's avatar
SCRUM  
unknown committed
1714 1715
      Field *f= show_item->tmp_table_field();
      if (!f->is_null())
unknown's avatar
unknown committed
1716
      {
unknown's avatar
SCRUM  
unknown committed
1717
        record_is_null= FALSE;      
unknown's avatar
unknown committed
1718 1719
	break;
      }
1720 1721
    }
  }
unknown's avatar
SCRUM  
unknown committed
1722 1723 1724 1725 1726
  if (record_is_null)
    return 0;
  null_value= FALSE;
  if (tree_mode)
  {
unknown's avatar
unknown committed
1727
    if (!tree_insert(tree, table->record[0] + rec_offset, 0, tree->custom_arg))
unknown's avatar
SCRUM  
unknown committed
1728 1729
      return 1;
  }
1730 1731 1732
  else
  {
    if (result.length() <= group_concat_max_len && !warning_for_row)
unknown's avatar
unknown committed
1733
      dump_leaf_key(table->record[0] + rec_offset, 1,
1734 1735 1736 1737 1738
                    (Item_func_group_concat*)this);
  }
  return 0;
}

unknown's avatar
SCRUM  
unknown committed
1739

1740 1741 1742 1743 1744 1745
void Item_func_group_concat::reset_field()
{
  if (tree_mode)
    reset_tree(tree);
}

unknown's avatar
SCRUM  
unknown committed
1746

1747 1748 1749
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
unknown's avatar
unknown committed
1750
  uint i;			/* for loop variable */ 
1751

1752 1753 1754 1755 1756 1757
  if (!thd->allow_sum_func)
  {
    my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
    return 1;
  }
  
unknown's avatar
SCRUM  
unknown committed
1758 1759
  thd->allow_sum_func= 0;
  maybe_null= 0;
unknown's avatar
unknown committed
1760
  for (i= 0 ; i < arg_count ; i++)
1761
  {
unknown's avatar
unknown committed
1762
    if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
1763
      return 1;
unknown's avatar
unknown committed
1764
    maybe_null |= args[i]->maybe_null;
1765
  }
unknown's avatar
SCRUM  
unknown committed
1766 1767 1768 1769
  /*
    Fix fields for order clause in function:
    GROUP_CONCAT(expr,... ORDER BY col,... )
  */
1770
  for (i= 0 ; i < arg_count_order ; i++)
1771
  {
unknown's avatar
SCRUM  
unknown committed
1772
    ORDER *order_item= order[i];
1773 1774 1775 1776
    Item *item=*order_item->item;
    if (item->fix_fields(thd, tables, &item) || item->check_cols(1))
      return 1;
  }
unknown's avatar
SCRUM  
unknown committed
1777 1778
  result_field= 0;
  null_value= 1;
1779
  max_length= group_concat_max_len;
unknown's avatar
SCRUM  
unknown committed
1780
  thd->allow_sum_func= 1;			
1781 1782
  if (!(tmp_table_param= new TMP_TABLE_PARAM))
    return 1;
unknown's avatar
SCRUM  
unknown committed
1783
  tables_list= tables;
1784 1785 1786 1787
  fixed= 1;
  return 0;
}

unknown's avatar
SCRUM  
unknown committed
1788

1789 1790 1791
bool Item_func_group_concat::setup(THD *thd)
{
  List<Item> list;
1792
  SELECT_LEX *select_lex= thd->lex.current_select->select_lex();
1793 1794 1795

  if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
    return 1;
unknown's avatar
SCRUM  
unknown committed
1796 1797 1798
  /*
    all not constant fields are push to list and create temp table
  */ 
unknown's avatar
BUG  
unknown committed
1799
  always_null= 0;
unknown's avatar
SCRUM  
unknown committed
1800
  for (uint i= 0; i < arg_count; i++)
1801
  {
unknown's avatar
SCRUM  
unknown committed
1802
    Item *item= args[i];
1803 1804 1805 1806 1807 1808
    if (list.push_back(item))
      return 1;
    if (item->const_item())
    {
      (void) item->val_int();
      if (item->null_value)
unknown's avatar
SCRUM  
unknown committed
1809
	always_null= 1;
1810 1811
    }
  }
unknown's avatar
BUG  
unknown committed
1812 1813
  if (always_null)
    return 0;
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
        
  List<Item> all_fields(list);
  if (arg_count_order) 
  {
    bool hidden_group_fields;
    setup_group(thd, args, tables_list, list, all_fields, *order,
                &hidden_group_fields);
  }
  
  count_field_types(tmp_table_param,all_fields,0);
unknown's avatar
SCRUM  
unknown committed
1824 1825 1826 1827 1828 1829
  /*
    We have to create a temporary table for that we get descriptions of fields 
    (types, sizes and so on).
  */
  if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 0,
        0, 0, 0,select_lex->options | thd->options)))
1830 1831
    return 1;
  table->file->extra(HA_EXTRA_NO_ROWS);
unknown's avatar
SCRUM  
unknown committed
1832
  table->no_rows= 1;
unknown's avatar
unknown committed
1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846


  Field** field, **field_end;
  field_end = (field = table->field) + table->fields;
  uint offset = 0;
  for (key_length = 0; field < field_end; ++field)
  {
    uint32 length= (*field)->pack_length();
    (*field)->abs_offset= offset;
    offset+= length;
    key_length += length;
  } 
  rec_offset = table->reclength - key_length;

unknown's avatar
SCRUM  
unknown committed
1847 1848 1849
  /*
    choise function of sort
  */  
unknown's avatar
unknown committed
1850 1851
  tree_mode= distinct || arg_count_order; 
  qsort_cmp2 compare_key;
1852 1853 1854 1855 1856
  if (tree_mode)
  {
    if (arg_count_order)
    {
      if (distinct)
unknown's avatar
SCRUM  
unknown committed
1857
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order;
1858
      else
unknown's avatar
SCRUM  
unknown committed
1859
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_order;
1860 1861 1862 1863
    }
    else
    {
      if (distinct)
unknown's avatar
SCRUM  
unknown committed
1864
        compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
1865
      else 
unknown's avatar
SCRUM  
unknown committed
1866
       compare_key= NULL; 
1867
    }
unknown's avatar
SCRUM  
unknown committed
1868 1869 1870 1871 1872
    /*
      Create a tree of sort. Tree is used for a sort and a remove dubl 
      values (according with syntax of the function). If function does't
      contain DISTINCT and ORDER BY clauses, we don't create this tree.
    */
1873 1874
    init_tree(tree, min(thd->variables.max_heap_table_size,
              thd->variables.sortbuff_size/16), 0,
unknown's avatar
unknown committed
1875 1876 1877
              key_length, compare_key, 0, NULL, (void*) this);
    max_elements_in_tree= ((key_length) ? 
           thd->variables.max_heap_table_size/key_length : 1);
1878 1879
  };

unknown's avatar
SCRUM  
unknown committed
1880 1881 1882 1883
  /*
    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)
  */
1884 1885 1886 1887 1888 1889 1890 1891
  if (original)
  {
    original->table= table;
    original->tree_mode= tree_mode;
  }
  return 0;
}

1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
/* 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;
  tree= &tree_base;
}


1902 1903
String* Item_func_group_concat::val_str(String* str)
{
unknown's avatar
SCRUM  
unknown committed
1904 1905
  if (null_value)
    return 0;
1906 1907
  if (tree_mode)
  {
unknown's avatar
SCRUM  
unknown committed
1908
    show_elements= 0;
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
    tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
              left_root_right);
  }
  else
  {
    if (!warning_for_row)
      result.length(result.length()-separator->length());
  }
  if (count_cut_values && !warning_available)
  {
unknown's avatar
SCRUM  
unknown committed
1919 1920
    warning_available= TRUE;
    warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1921 1922 1923 1924
                           ER_CUT_VALUE_GROUP_CONCAT, NULL);
  }
  return &result;
}
unknown's avatar
unknown committed
1925 1926 1927