item_func.cc 153 KB
Newer Older
1
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2 3 4

   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
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6 7 8 9 10 11 12 13 14 15 16

   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.

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


unknown's avatar
unknown committed
17 18 19 20 21 22
/**
  @file

  @brief
  This file defines all numerical functions
*/
unknown's avatar
unknown committed
23

24
#ifdef USE_PRAGMA_IMPLEMENTATION
unknown's avatar
unknown committed
25 26 27 28
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
unknown's avatar
unknown committed
29
#include "slave.h"				// for wait_for_master_pos
30
#include "rpl_mi.h"
unknown's avatar
unknown committed
31 32 33 34
#include <m_ctype.h>
#include <hash.h>
#include <time.h>
#include <ft_global.h>
35
#include <my_bit.h>
unknown's avatar
unknown committed
36

37 38 39
#include "sp_head.h"
#include "sp_rcontext.h"
#include "sp.h"
unknown's avatar
unknown committed
40

unknown's avatar
unknown committed
41 42 43 44
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
#endif

45 46 47 48 49 50 51 52 53 54
bool check_reserved_words(LEX_STRING *name)
{
  if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
      !my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
      !my_strcasecmp(system_charset_info, name->str, "SESSION"))
    return TRUE;
  return FALSE;
}


unknown's avatar
unknown committed
55 56 57 58
/**
  @return
    TRUE if item is a constant
*/
unknown's avatar
unknown committed
59 60 61 62 63 64 65

bool
eval_const_cond(COND *cond)
{
  return ((Item_func*) cond)->val_int() ? TRUE : FALSE;
}

unknown's avatar
unknown committed
66

67
void Item_func::set_arguments(List<Item> &list)
unknown's avatar
unknown committed
68
{
69
  allowed_arg_cols= 1;
unknown's avatar
unknown committed
70
  arg_count=list.elements;
unknown's avatar
unknown committed
71 72
  args= tmp_arg;                                // If 2 arguments
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
unknown's avatar
unknown committed
73
  {
unknown's avatar
unknown committed
74
    List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
75
    Item *item;
unknown's avatar
unknown committed
76
    Item **save_args= args;
unknown's avatar
unknown committed
77 78 79

    while ((item=li++))
    {
unknown's avatar
unknown committed
80
      *(save_args++)= item;
unknown's avatar
unknown committed
81 82 83 84 85 86
      with_sum_func|=item->with_sum_func;
    }
  }
  list.empty();					// Fields are used
}

87 88 89 90 91 92
Item_func::Item_func(List<Item> &list)
  :allowed_arg_cols(1)
{
  set_arguments(list);
}

93
Item_func::Item_func(THD *thd, Item_func *item)
94
  :Item_result_field(thd, item),
95 96 97 98 99
   allowed_arg_cols(item->allowed_arg_cols),
   arg_count(item->arg_count),
   used_tables_cache(item->used_tables_cache),
   not_null_tables_cache(item->not_null_tables_cache),
   const_item_cache(item->const_item_cache)
100 101 102 103 104 105 106 107 108 109
{
  if (arg_count)
  {
    if (arg_count <=2)
      args= tmp_arg;
    else
    {
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
	return;
    }
110
    memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
111 112 113
  }
}

unknown's avatar
unknown committed
114 115

/*
116
  Resolve references to table column for a function and its argument
unknown's avatar
unknown committed
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131

  SYNOPSIS:
  fix_fields()
  thd		Thread object
  ref		Pointer to where this object is used.  This reference
		is used if we want to replace this object with another
		one (for example in the summary functions).

  DESCRIPTION
    Call fix_fields() for all arguments to the function.  The main intention
    is to allow all Item_field() objects to setup pointers to the table fields.

    Sets as a side effect the following class variables:
      maybe_null	Set if any argument may return NULL
      with_sum_func	Set if any of the arguments contains a sum function
unknown's avatar
unknown committed
132
      used_tables_cache Set to union of the tables used by arguments
unknown's avatar
unknown committed
133 134 135

      str_value.charset If this is a string function, set this to the
			character set for the first argument.
136
			If any argument is binary, this is set to binary
unknown's avatar
unknown committed
137 138 139 140 141 142 143

   If for any item any of the defaults are wrong, then this can
   be fixed in the fix_length_and_dec() function that is called
   after this one or by writing a specialized fix_fields() for the
   item.

  RETURN VALUES
unknown's avatar
unknown committed
144 145
  FALSE	ok
  TRUE	Got error.  Stored with my_error().
unknown's avatar
unknown committed
146 147
*/

unknown's avatar
unknown committed
148
bool
149
Item_func::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
150
{
151
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
152
  Item **arg,**arg_end;
153
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
154
  uchar buff[STACK_BUFF_ALLOC];			// Max argument in function
155
#endif
156

157
  used_tables_cache= not_null_tables_cache= 0;
unknown's avatar
unknown committed
158 159
  const_item_cache=1;

160
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
unknown's avatar
unknown committed
161
    return TRUE;				// Fatal error if flag is set!
unknown's avatar
unknown committed
162 163 164 165
  if (arg_count)
  {						// Print purify happy
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
    {
unknown's avatar
unknown committed
166
      Item *item;
unknown's avatar
merge  
unknown committed
167 168 169 170
      /*
	We can't yet set item to *arg as fix_fields may change *arg
	We shouldn't call fix_fields() twice, so check 'fixed' field first
      */
171
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
unknown's avatar
unknown committed
172
	return TRUE;				/* purecov: inspected */
unknown's avatar
unknown committed
173
      item= *arg;
174 175 176 177 178 179 180 181 182 183 184 185 186 187

      if (allowed_arg_cols)
      {
        if (item->check_cols(allowed_arg_cols))
          return 1;
      }
      else
      {
        /*  we have to fetch allowed_arg_cols from first argument */
        DBUG_ASSERT(arg == args); // it is first argument
        allowed_arg_cols= item->cols();
        DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
      }

unknown's avatar
unknown committed
188
      if (item->maybe_null)
unknown's avatar
unknown committed
189
	maybe_null=1;
190

unknown's avatar
unknown committed
191
      with_sum_func= with_sum_func || item->with_sum_func;
192 193 194
      used_tables_cache|=     item->used_tables();
      not_null_tables_cache|= item->not_null_tables();
      const_item_cache&=      item->const_item();
195
      with_subselect|=        item->with_subselect;
unknown's avatar
unknown committed
196 197 198
    }
  }
  fix_length_and_dec();
199
  if (thd->is_error()) // An error inside fix_length_and_dec occured
unknown's avatar
unknown committed
200
    return TRUE;
201
  fixed= 1;
unknown's avatar
unknown committed
202
  return FALSE;
unknown's avatar
unknown committed
203 204
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
void
Item_func::quick_fix_field()
{
  Item **arg,**arg_end;
  if (arg_count)
  {
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
    {
      if (!(*arg)->fixed)
        (*arg)->quick_fix_field();
    }
  }
  fixed= 1;
}

220 221

bool Item_func::walk(Item_processor processor, bool walk_subquery,
222
                     uchar *argument)
unknown's avatar
unknown committed
223 224 225 226 227 228
{
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
229
      if ((*arg)->walk(processor, walk_subquery, argument))
unknown's avatar
unknown committed
230 231 232 233 234
	return 1;
    }
  }
  return (this->*processor)(argument);
}
235

236 237
void Item_func::traverse_cond(Cond_traverser traverser,
                              void *argument, traverse_order order)
238 239 240 241
{
  if (arg_count)
  {
    Item **arg,**arg_end;
242 243 244

    switch (order) {
    case(PREFIX):
unknown's avatar
unknown committed
245
      (*traverser)(this, argument);
246 247 248 249 250 251 252 253 254 255
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
      {
	(*arg)->traverse_cond(traverser, argument, order);
      }
      break;
    case (POSTFIX):
      for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
      {
	(*arg)->traverse_cond(traverser, argument, order);
      }
unknown's avatar
unknown committed
256
      (*traverser)(this, argument);
257 258
    }
  }
259 260
  else
    (*traverser)(this, argument);
261 262
}

unknown's avatar
unknown committed
263

unknown's avatar
unknown committed
264 265 266
/**
  Transform an Item_func object with a transformer callback function.

267 268 269
    The function recursively applies the transform method to each
    argument of the Item_func node.
    If the call of the method for an argument item returns a new item
unknown's avatar
unknown committed
270
    the old item is substituted for a new one.
271
    After this the transformer is applied to the root node
unknown's avatar
unknown committed
272
    of the Item_func object. 
unknown's avatar
unknown committed
273 274 275 276 277 278
  @param transformer   the transformer callback function to be applied to
                       the nodes of the tree of the object
  @param argument      parameter to be passed to the transformer

  @return
    Item returned as the result of transformation of the root node
unknown's avatar
unknown committed
279 280
*/

281
Item *Item_func::transform(Item_transformer transformer, uchar *argument)
282
{
283 284
  DBUG_ASSERT(!current_thd->is_stmt_prepare());

285 286 287 288 289
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
unknown's avatar
unknown committed
290
      Item *new_item= (*arg)->transform(transformer, argument);
291 292
      if (!new_item)
	return 0;
293 294 295 296 297 298 299

      /*
        THD::change_item_tree() should be called only if the tree was
        really transformed, i.e. when a new item has been created.
        Otherwise we'll be allocating a lot of unnecessary memory for
        change records at each execution.
      */
unknown's avatar
unknown committed
300 301
      if (*arg != new_item)
        current_thd->change_item_tree(arg, new_item);
302 303
    }
  }
unknown's avatar
unknown committed
304
  return (this->*transformer)(argument);
305 306 307
}


unknown's avatar
unknown committed
308 309 310 311
/**
  Compile Item_func object with a processor and a transformer
  callback functions.

312 313 314 315 316 317 318 319
    First the function applies the analyzer to the root node of
    the Item_func object. Then if the analizer succeeeds (returns TRUE)
    the function recursively applies the compile method to each argument
    of the Item_func node.
    If the call of the method for an argument item returns a new item
    the old item is substituted for a new one.
    After this the transformer is applied to the root node
    of the Item_func object. 
unknown's avatar
unknown committed
320 321 322 323 324 325 326 327 328 329

  @param analyzer      the analyzer callback function to be applied to the
                       nodes of the tree of the object
  @param[in,out] arg_p parameter to be passed to the processor
  @param transformer   the transformer callback function to be applied to the
                       nodes of the tree of the object
  @param arg_t         parameter to be passed to the transformer

  @return
    Item returned as the result of transformation of the root node
330 331
*/

332 333
Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
                         Item_transformer transformer, uchar *arg_t)
334 335 336 337 338 339 340 341 342 343 344 345
{
  if (!(this->*analyzer)(arg_p))
    return 0;
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
      /* 
        The same parameter value of arg_p must be passed
        to analyze any argument of the condition formula.
      */   
346
      uchar *arg_v= *arg_p;
347 348 349 350 351 352 353 354
      Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
      if (new_item && *arg != new_item)
        current_thd->change_item_tree(arg, new_item);
    }
  }
  return (this->*transformer)(arg_t);
}

unknown's avatar
unknown committed
355 356 357
/**
  See comments in Item_cmp_func::split_sum_func()
*/
358

359 360
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
                               List<Item> &fields)
unknown's avatar
unknown committed
361
{
362 363
  Item **arg, **arg_end;
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
unknown's avatar
unknown committed
364
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
unknown's avatar
unknown committed
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
}


void Item_func::update_used_tables()
{
  used_tables_cache=0;
  const_item_cache=1;
  for (uint i=0 ; i < arg_count ; i++)
  {
    args[i]->update_used_tables();
    used_tables_cache|=args[i]->used_tables();
    const_item_cache&=args[i]->const_item();
  }
}


table_map Item_func::used_tables() const
{
  return used_tables_cache;
}

386 387 388 389 390 391 392

table_map Item_func::not_null_tables() const
{
  return not_null_tables_cache;
}


393
void Item_func::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
394 395 396
{
  str->append(func_name());
  str->append('(');
397
  print_args(str, 0, query_type);
398 399 400 401
  str->append(')');
}


402
void Item_func::print_args(String *str, uint from, enum_query_type query_type)
403
{
unknown's avatar
unknown committed
404
  for (uint i=from ; i < arg_count ; i++)
unknown's avatar
unknown committed
405
  {
unknown's avatar
unknown committed
406
    if (i != from)
unknown's avatar
unknown committed
407
      str->append(',');
408
    args[i]->print(str, query_type);
unknown's avatar
unknown committed
409 410 411 412
  }
}


413
void Item_func::print_op(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
414 415 416 417
{
  str->append('(');
  for (uint i=0 ; i < arg_count-1 ; i++)
  {
418
    args[i]->print(str, query_type);
unknown's avatar
unknown committed
419 420 421 422
    str->append(' ');
    str->append(func_name());
    str->append(' ');
  }
423
  args[arg_count-1]->print(str, query_type);
unknown's avatar
unknown committed
424 425 426
  str->append(')');
}

unknown's avatar
unknown committed
427

428
bool Item_func::eq(const Item *item, bool binary_cmp) const
unknown's avatar
unknown committed
429 430 431 432 433 434 435
{
  /* Assume we don't have rtti */
  if (this == item)
    return 1;
  if (item->type() != FUNC_ITEM)
    return 0;
  Item_func *item_func=(Item_func*) item;
436 437 438 439 440 441 442
  Item_func::Functype func_type;
  if ((func_type= functype()) != item_func->functype() ||
      arg_count != item_func->arg_count ||
      (func_type != Item_func::FUNC_SP &&
       func_name() != item_func->func_name()) ||
      (func_type == Item_func::FUNC_SP &&
       my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
unknown's avatar
unknown committed
443 444
    return 0;
  for (uint i=0; i < arg_count ; i++)
445
    if (!args[i]->eq(item_func->args[i], binary_cmp))
unknown's avatar
unknown committed
446 447 448 449
      return 0;
  return 1;
}

450

unknown's avatar
unknown committed
451
Field *Item_func::tmp_table_field(TABLE *table)
452
{
Staale Smedseng's avatar
Staale Smedseng committed
453
  Field *field= NULL;
454

unknown's avatar
unknown committed
455
  switch (result_type()) {
456
  case INT_RESULT:
457
    if (max_length > MY_INT32_NUM_DECIMAL_DIGITS)
unknown's avatar
unknown committed
458
      field= new Field_longlong(max_length, maybe_null, name, unsigned_flag);
459
    else
unknown's avatar
unknown committed
460
      field= new Field_long(max_length, maybe_null, name, unsigned_flag);
461 462
    break;
  case REAL_RESULT:
unknown's avatar
unknown committed
463
    field= new Field_double(max_length, maybe_null, name, decimals);
464 465
    break;
  case STRING_RESULT:
unknown's avatar
unknown committed
466
    return make_string_field(table);
unknown's avatar
unknown committed
467
  case DECIMAL_RESULT:
468
    field= Field_new_decimal::create_from_item(this);
unknown's avatar
unknown committed
469
    break;
470
  case ROW_RESULT:
unknown's avatar
unknown committed
471
  default:
unknown's avatar
unknown committed
472
    // This case should never be chosen
unknown's avatar
unknown committed
473
    DBUG_ASSERT(0);
unknown's avatar
unknown committed
474
    field= 0;
unknown's avatar
unknown committed
475
    break;
476
  }
unknown's avatar
unknown committed
477 478 479
  if (field)
    field->init(table);
  return field;
480 481
}

unknown's avatar
unknown committed
482

483
bool Item_func::is_expensive_processor(uchar *arg)
484
{
485
  return is_expensive();
486 487 488
}


unknown's avatar
unknown committed
489 490 491 492 493 494 495
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed);
  int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
  return decimal_value;
}

496

unknown's avatar
unknown committed
497 498
String *Item_real_func::val_str(String *str)
{
499
  DBUG_ASSERT(fixed == 1);
500
  double nr= val_real();
unknown's avatar
unknown committed
501 502
  if (null_value)
    return 0; /* purecov: inspected */
503
  str->set_real(nr,decimals, &my_charset_bin);
unknown's avatar
unknown committed
504 505 506 507
  return str;
}


508 509 510 511 512 513 514 515 516 517 518
my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed);
  double nr= val_real();
  if (null_value)
    return 0; /* purecov: inspected */
  double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
  return decimal_value;
}


unknown's avatar
unknown committed
519
void Item_func::fix_num_length_and_dec()
unknown's avatar
unknown committed
520
{
521
  uint fl_length= 0;
unknown's avatar
unknown committed
522
  decimals=0;
unknown's avatar
unknown committed
523
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
524 525
  {
    set_if_bigger(decimals,args[i]->decimals);
526 527
    set_if_bigger(fl_length, args[i]->max_length);
  }
unknown's avatar
unknown committed
528
  max_length=float_length(decimals);
529 530 531 532
  if (fl_length > max_length)
  {
    decimals= NOT_FIXED_DEC;
    max_length= float_length(NOT_FIXED_DEC);
unknown's avatar
unknown committed
533
  }
unknown's avatar
unknown committed
534 535 536 537 538 539 540
}


void Item_func_numhybrid::fix_num_length_and_dec()
{}


unknown's avatar
unknown committed
541
/**
unknown's avatar
unknown committed
542
  Set max_length/decimals of function if function is fixed point and
unknown's avatar
unknown committed
543
  result length/precision depends on argument ones.
unknown's avatar
unknown committed
544 545 546 547
*/

void Item_func::count_decimal_length()
{
unknown's avatar
unknown committed
548
  int max_int_part= 0;
unknown's avatar
unknown committed
549
  decimals= 0;
unknown's avatar
unknown committed
550
  unsigned_flag= 1;
unknown's avatar
unknown committed
551
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
552
  {
unknown's avatar
unknown committed
553
    set_if_bigger(decimals, args[i]->decimals);
unknown's avatar
unknown committed
554 555
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
    set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
unknown's avatar
unknown committed
556
  }
unknown's avatar
unknown committed
557
  int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
558 559
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
560 561 562
}


unknown's avatar
unknown committed
563 564
/**
  Set max_length of if it is maximum length of its arguments.
unknown's avatar
unknown committed
565 566 567
*/

void Item_func::count_only_length()
unknown's avatar
unknown committed
568
{
unknown's avatar
unknown committed
569
  max_length= 0;
unknown's avatar
unknown committed
570
  unsigned_flag= 0;
unknown's avatar
unknown committed
571
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
572
  {
unknown's avatar
unknown committed
573
    set_if_bigger(max_length, args[i]->max_length);
unknown's avatar
unknown committed
574 575
    set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
  }
unknown's avatar
unknown committed
576 577
}

unknown's avatar
unknown committed
578

unknown's avatar
unknown committed
579
/**
unknown's avatar
unknown committed
580
  Set max_length/decimals of function if function is floating point and
unknown's avatar
unknown committed
581
  result length/precision depends on argument ones.
unknown's avatar
unknown committed
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
*/

void Item_func::count_real_length()
{
  uint32 length= 0;
  decimals= 0;
  max_length= 0;
  for (uint i=0 ; i < arg_count ; i++)
  {
    if (decimals != NOT_FIXED_DEC)
    {
      set_if_bigger(decimals, args[i]->decimals);
      set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
    }
    set_if_bigger(max_length, args[i]->max_length);
  }
  if (decimals != NOT_FIXED_DEC)
  {
    max_length= length;
    length+= decimals;
    if (length < max_length)  // If previous operation gave overflow
      max_length= UINT_MAX32;
    else
      max_length= length;
  }
}



unknown's avatar
unknown committed
611 612 613 614 615 616 617 618 619 620
void Item_func::signal_divide_by_null()
{
  THD *thd= current_thd;
  if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO,
                 ER(ER_DIVISION_BY_ZERO));
  null_value= 1;
}


621
Item *Item_func::get_tmp_table_item(THD *thd)
622
{
623
  if (!with_sum_func && !const_item())
624
    return new Item_field(result_field);
625
  return copy_or_same(thd);
626 627
}

628 629 630 631 632 633 634 635
double Item_int_func::val_real()
{
  DBUG_ASSERT(fixed == 1);

  return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int();
}


unknown's avatar
unknown committed
636 637
String *Item_int_func::val_str(String *str)
{
638
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
639 640 641
  longlong nr=val_int();
  if (null_value)
    return 0;
642
  str->set_int(nr, unsigned_flag, &my_charset_bin);
unknown's avatar
unknown committed
643 644 645
  return str;
}

unknown's avatar
unknown committed
646

647 648 649 650 651 652 653 654 655 656 657
void Item_func_connection_id::fix_length_and_dec()
{
  Item_int_func::fix_length_and_dec();
  max_length= 10;
}


bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
{
  if (Item_int_func::fix_fields(thd, ref))
    return TRUE;
658
  thd->thread_specific_used= TRUE;
659
  value= thd->variables.pseudo_thread_id;
660 661 662 663
  return FALSE;
}


unknown's avatar
unknown committed
664
/**
665 666
  Check arguments here to determine result's type for a numeric
  function of two arguments.
667
*/
unknown's avatar
unknown committed
668 669 670

void Item_num_op::find_num_type(void)
{
unknown's avatar
unknown committed
671 672 673 674 675 676 677 678
  DBUG_ENTER("Item_num_op::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
  DBUG_ASSERT(arg_count == 2);
  Item_result r0= args[0]->result_type();
  Item_result r1= args[1]->result_type();

  if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
      r0 == STRING_RESULT || r1 ==STRING_RESULT)
679
  {
unknown's avatar
unknown committed
680 681 682 683 684 685 686 687 688
    count_real_length();
    max_length= float_length(decimals);
    hybrid_type= REAL_RESULT;
  }
  else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
  {
    hybrid_type= DECIMAL_RESULT;
    result_precision();
  }
689
  else
690
  {
691
    DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
unknown's avatar
unknown committed
692
    decimals= 0;
unknown's avatar
unknown committed
693
    hybrid_type=INT_RESULT;
unknown's avatar
unknown committed
694
    result_precision();
695
  }
unknown's avatar
unknown committed
696 697 698 699 700 701
  DBUG_PRINT("info", ("Type: %s",
             (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
              hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
              hybrid_type == INT_RESULT ? "INT_RESULT" :
              "--ILLEGAL!!!--")));
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
702 703
}

unknown's avatar
unknown committed
704

unknown's avatar
unknown committed
705
/**
706 707 708
  Set result type for a numeric function of one argument
  (can be also used by a numeric function of many arguments, if the result
  type depends only on the first argument)
unknown's avatar
unknown committed
709
*/
710

unknown's avatar
unknown committed
711 712 713 714
void Item_func_num1::find_num_type()
{
  DBUG_ENTER("Item_func_num1::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
715
  switch (hybrid_type= args[0]->result_type()) {
unknown's avatar
unknown committed
716
  case INT_RESULT:
717
    unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
718 719 720 721 722 723 724 725 726 727
    break;
  case STRING_RESULT:
  case REAL_RESULT:
    hybrid_type= REAL_RESULT;
    max_length= float_length(decimals);
    break;
  case DECIMAL_RESULT:
    break;
  default:
    DBUG_ASSERT(0);
728
  }
unknown's avatar
unknown committed
729 730 731 732 733 734
  DBUG_PRINT("info", ("Type: %s",
                      (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
                       hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
                       hybrid_type == INT_RESULT ? "INT_RESULT" :
                       "--ILLEGAL!!!--")));
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
735 736
}

unknown's avatar
unknown committed
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752

void Item_func_num1::fix_num_length_and_dec()
{
  decimals= args[0]->decimals;
  max_length= args[0]->max_length;
}


void Item_func_numhybrid::fix_length_and_dec()
{
  fix_num_length_and_dec();
  find_num_type();
}


String *Item_func_numhybrid::val_str(String *str)
unknown's avatar
unknown committed
753
{
754
  DBUG_ASSERT(fixed == 1);
755
  switch (hybrid_type) {
unknown's avatar
unknown committed
756 757 758 759
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
760
      return 0;                                 // null is set
unknown's avatar
unknown committed
761 762 763 764 765 766 767
    my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
    my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
    break;
  }
  case INT_RESULT:
  {
    longlong nr= int_op();
unknown's avatar
unknown committed
768 769
    if (null_value)
      return 0; /* purecov: inspected */
770
    str->set_int(nr, unsigned_flag, &my_charset_bin);
unknown's avatar
unknown committed
771
    break;
unknown's avatar
unknown committed
772
  }
unknown's avatar
unknown committed
773
  case REAL_RESULT:
unknown's avatar
unknown committed
774
  {
775
    double nr= real_op();
unknown's avatar
unknown committed
776 777
    if (null_value)
      return 0; /* purecov: inspected */
778
    str->set_real(nr,decimals,&my_charset_bin);
unknown's avatar
unknown committed
779 780
    break;
  }
unknown's avatar
unknown committed
781 782
  case STRING_RESULT:
    return str_op(&str_value);
unknown's avatar
unknown committed
783 784
  default:
    DBUG_ASSERT(0);
unknown's avatar
unknown committed
785 786 787 788 789
  }
  return str;
}


unknown's avatar
unknown committed
790 791 792
double Item_func_numhybrid::val_real()
{
  DBUG_ASSERT(fixed == 1);
793
  switch (hybrid_type) {
unknown's avatar
unknown committed
794 795 796 797
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    double result;
798 799
    if (!(val= decimal_op(&decimal_value)))
      return 0.0;                               // null is set
unknown's avatar
unknown committed
800 801 802 803
    my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
    return result;
  }
  case INT_RESULT:
804 805 806 807
  {
    longlong result= int_op();
    return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
  }
unknown's avatar
unknown committed
808 809
  case REAL_RESULT:
    return real_op();
unknown's avatar
unknown committed
810 811 812 813 814 815 816 817
  case STRING_RESULT:
  {
    char *end_not_used;
    int err_not_used;
    String *res= str_op(&str_value);
    return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
			     &end_not_used, &err_not_used) : 0.0);
  }
unknown's avatar
unknown committed
818 819 820 821 822 823 824 825 826 827
  default:
    DBUG_ASSERT(0);
  }
  return 0.0;
}


longlong Item_func_numhybrid::val_int()
{
  DBUG_ASSERT(fixed == 1);
828
  switch (hybrid_type) {
unknown's avatar
unknown committed
829 830 831 832
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
833
      return 0;                                 // null is set
unknown's avatar
unknown committed
834 835 836 837 838 839 840
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
    return result;
  }
  case INT_RESULT:
    return int_op();
  case REAL_RESULT:
841
    return (longlong) rint(real_op());
unknown's avatar
unknown committed
842 843 844
  case STRING_RESULT:
  {
    int err_not_used;
unknown's avatar
unknown committed
845 846 847 848
    String *res;
    if (!(res= str_op(&str_value)))
      return 0;

849
    char *end= (char*) res->ptr() + res->length();
unknown's avatar
unknown committed
850
    CHARSET_INFO *cs= str_value.charset();
unknown's avatar
unknown committed
851
    return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
unknown's avatar
unknown committed
852
  }
unknown's avatar
unknown committed
853 854 855 856 857 858 859 860 861 862 863
  default:
    DBUG_ASSERT(0);
  }
  return 0;
}


my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
{
  my_decimal *val= decimal_value;
  DBUG_ASSERT(fixed == 1);
864
  switch (hybrid_type) {
unknown's avatar
unknown committed
865 866 867 868 869 870 871 872 873 874 875
  case DECIMAL_RESULT:
    val= decimal_op(decimal_value);
    break;
  case INT_RESULT:
  {
    longlong result= int_op();
    int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
    break;
  }
  case REAL_RESULT:
  {
876
    double result= (double)real_op();
unknown's avatar
unknown committed
877 878 879 880
    double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
    break;
  }
  case STRING_RESULT:
unknown's avatar
unknown committed
881
  {
unknown's avatar
unknown committed
882 883 884 885
    String *res;
    if (!(res= str_op(&str_value)))
      return NULL;

unknown's avatar
unknown committed
886 887 888 889
    str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
                   res->length(), res->charset(), decimal_value);
    break;
  }  
unknown's avatar
unknown committed
890 891 892 893 894 895 896 897
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  return val;
}


898
void Item_func_signed::print(String *str, enum_query_type query_type)
899
{
900
  str->append(STRING_WITH_LEN("cast("));
901
  args[0]->print(str, query_type);
902
  str->append(STRING_WITH_LEN(" as signed)"));
903 904 905 906

}


907 908
longlong Item_func_signed::val_int_from_str(int *error)
{
unknown's avatar
unknown committed
909 910
  char buff[MAX_FIELD_WIDTH], *end, *start;
  uint32 length;
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
  String tmp(buff,sizeof(buff), &my_charset_bin), *res;
  longlong value;

  /*
    For a string result, we must first get the string and then convert it
    to a longlong
  */

  if (!(res= args[0]->val_str(&tmp)))
  {
    null_value= 1;
    *error= 0;
    return 0;
  }
  null_value= 0;
unknown's avatar
unknown committed
926 927 928 929 930 931 932 933 934 935
  start= (char *)res->ptr();
  length= res->length();

  end= start + length;
  value= my_strtoll10(start, &end, error);
  if (*error > 0 || end != start+ length)
  {
    char err_buff[128];
    String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info);
    err_tmp.copy(start, length, system_charset_info);
936 937 938
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                        ER_TRUNCATED_WRONG_VALUE,
                        ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
unknown's avatar
unknown committed
939 940
                        err_tmp.c_ptr());
  }
941 942 943 944 945 946 947 948 949
  return value;
}


longlong Item_func_signed::val_int()
{
  longlong value;
  int error;

950 951
  if (args[0]->cast_to_int_type() != STRING_RESULT ||
      args[0]->result_as_longlong())
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
  {
    value= args[0]->val_int();
    null_value= args[0]->null_value; 
    return value;
  }

  value= val_int_from_str(&error);
  if (value < 0 && error == 0)
  {
    push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
                 "Cast to signed converted positive out-of-range integer to "
                 "it's negative complement");
  }
  return value;
}


969
void Item_func_unsigned::print(String *str, enum_query_type query_type)
970
{
971
  str->append(STRING_WITH_LEN("cast("));
972
  args[0]->print(str, query_type);
973
  str->append(STRING_WITH_LEN(" as unsigned)"));
974 975 976 977

}


978 979 980 981 982
longlong Item_func_unsigned::val_int()
{
  longlong value;
  int error;

983 984 985 986 987
  if (args[0]->cast_to_int_type() == DECIMAL_RESULT)
  {
    my_decimal tmp, *dec= args[0]->val_decimal(&tmp);
    if (!(null_value= args[0]->null_value))
      my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
988 989
    else
      value= 0;
990 991
    return value;
  }
992 993
  else if (args[0]->cast_to_int_type() != STRING_RESULT ||
           args[0]->result_as_longlong())
994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
  {
    value= args[0]->val_int();
    null_value= args[0]->null_value; 
    return value;
  }

  value= val_int_from_str(&error);
  if (error < 0)
    push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
                 "Cast to unsigned converted negative integer to it's "
                 "positive complement");
  return value;
}


unknown's avatar
unknown committed
1009 1010 1011
String *Item_decimal_typecast::val_str(String *str)
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1012 1013
  if (null_value)
    return NULL;
unknown's avatar
unknown committed
1014
  my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str);
unknown's avatar
unknown committed
1015 1016 1017 1018 1019 1020 1021 1022
  return str;
}


double Item_decimal_typecast::val_real()
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
  double res;
1023 1024
  if (null_value)
    return 0.0;
unknown's avatar
unknown committed
1025 1026 1027 1028 1029 1030 1031 1032 1033
  my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
  return res;
}


longlong Item_decimal_typecast::val_int()
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
  longlong res;
1034 1035
  if (null_value)
    return 0;
unknown's avatar
unknown committed
1036 1037 1038 1039 1040 1041 1042 1043
  my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
  return res;
}


my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
{
  my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
1044
  bool sign;
unknown's avatar
unknown committed
1045 1046
  uint precision;

1047 1048
  if ((null_value= args[0]->null_value))
    return NULL;
unknown's avatar
unknown committed
1049
  my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
1050 1051 1052 1053 1054 1055 1056 1057 1058
  sign= dec->sign();
  if (unsigned_flag)
  {
    if (sign)
    {
      my_decimal_set_zero(dec);
      goto err;
    }
  }
unknown's avatar
unknown committed
1059 1060 1061
  precision= my_decimal_length_to_precision(max_length,
                                            decimals, unsigned_flag);
  if (precision - decimals < (uint) my_decimal_intg(dec))
1062
  {
unknown's avatar
unknown committed
1063
    max_my_decimal(dec, precision, decimals);
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
    dec->sign(sign);
    goto err;
  }
  return dec;

err:
  push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
                      ER_WARN_DATA_OUT_OF_RANGE,
                      ER(ER_WARN_DATA_OUT_OF_RANGE),
                      name, 1);
unknown's avatar
unknown committed
1074 1075 1076 1077
  return dec;
}


1078
void Item_decimal_typecast::print(String *str, enum_query_type query_type)
1079
{
1080 1081 1082 1083 1084
  char len_buf[20*3 + 1];
  char *end;

  uint precision= my_decimal_length_to_precision(max_length, decimals,
                                                 unsigned_flag);
1085
  str->append(STRING_WITH_LEN("cast("));
1086
  args[0]->print(str, query_type);
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
  str->append(STRING_WITH_LEN(" as decimal("));

  end=int10_to_str(precision, len_buf,10);
  str->append(len_buf, (uint32) (end - len_buf));

  str->append(',');

  end=int10_to_str(decimals, len_buf,10);
  str->append(len_buf, (uint32) (end - len_buf));

  str->append(')');
  str->append(')');
1099 1100 1101
}


unknown's avatar
unknown committed
1102
double Item_func_plus::real_op()
unknown's avatar
unknown committed
1103
{
1104
  double value= args[0]->val_real() + args[1]->val_real();
unknown's avatar
unknown committed
1105 1106
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
1107
  return fix_result(value);
unknown's avatar
unknown committed
1108 1109
}

unknown's avatar
unknown committed
1110 1111

longlong Item_func_plus::int_op()
unknown's avatar
unknown committed
1112
{
unknown's avatar
unknown committed
1113 1114 1115 1116 1117 1118 1119
  longlong value=args[0]->val_int()+args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
}


unknown's avatar
unknown committed
1120 1121
/**
  Calculate plus of two decimals.
1122

unknown's avatar
unknown committed
1123
  @param decimal_value	Buffer that can be used to store result
1124

unknown's avatar
unknown committed
1125 1126 1127 1128
  @retval
    0  Value was NULL;  In this case null_value is set
  @retval
    \# Value of operation as a decimal
1129 1130
*/

unknown's avatar
unknown committed
1131 1132
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
{
1133 1134 1135
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1136 1137
  if ((null_value= args[0]->null_value))
    return 0;
1138
  val2= args[1]->val_decimal(&value2);
1139
  if (!(null_value= (args[1]->null_value ||
1140 1141
                     (my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
                                     val2) > 3))))
1142 1143
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1144 1145
}

unknown's avatar
unknown committed
1146
/**
unknown's avatar
unknown committed
1147 1148 1149 1150 1151
  Set precision of results for additive operations (+ and -)
*/
void Item_func_additive_op::result_precision()
{
  decimals= max(args[0]->decimals, args[1]->decimals);
1152 1153
  int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
  int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
1154
  int precision= max(arg1_int, arg2_int) + 1 + decimals;
unknown's avatar
unknown committed
1155 1156 1157 1158 1159 1160

  /* Integer operations keep unsigned_flag if one of arguments is unsigned */
  if (result_type() == INT_RESULT)
    unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
  else
    unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
1161 1162
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1163 1164
}

1165

unknown's avatar
unknown committed
1166
/**
1167 1168 1169 1170 1171 1172 1173 1174
  The following function is here to allow the user to force
  subtraction of UNSIGNED BIGINT to return negative values.
*/

void Item_func_minus::fix_length_and_dec()
{
  Item_num_op::fix_length_and_dec();
  if (unsigned_flag &&
1175
      (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
1176 1177 1178 1179
    unsigned_flag=0;
}


unknown's avatar
unknown committed
1180
double Item_func_minus::real_op()
unknown's avatar
unknown committed
1181
{
1182
  double value= args[0]->val_real() - args[1]->val_real();
unknown's avatar
unknown committed
1183 1184
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
1185
  return fix_result(value);
unknown's avatar
unknown committed
1186 1187
}

unknown's avatar
unknown committed
1188 1189

longlong Item_func_minus::int_op()
unknown's avatar
unknown committed
1190
{
unknown's avatar
unknown committed
1191 1192 1193 1194
  longlong value=args[0]->val_int() - args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
unknown's avatar
unknown committed
1195 1196
}

1197

unknown's avatar
unknown committed
1198 1199 1200
/**
  See Item_func_plus::decimal_op for comments.
*/
1201

unknown's avatar
unknown committed
1202 1203
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
{
1204 1205 1206 1207
  my_decimal value1, *val1;
  my_decimal value2, *val2= 

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1208 1209
  if ((null_value= args[0]->null_value))
    return 0;
1210
  val2= args[1]->val_decimal(&value2);
1211
  if (!(null_value= (args[1]->null_value ||
1212 1213
                     (my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
                                     val2) > 3))))
1214 1215
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1216 1217
}

1218

unknown's avatar
unknown committed
1219
double Item_func_mul::real_op()
unknown's avatar
unknown committed
1220
{
1221
  DBUG_ASSERT(fixed == 1);
1222
  double value= args[0]->val_real() * args[1]->val_real();
unknown's avatar
unknown committed
1223
  if ((null_value=args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1224
    return 0.0;
1225
  return fix_result(value);
unknown's avatar
unknown committed
1226 1227
}

unknown's avatar
unknown committed
1228 1229

longlong Item_func_mul::int_op()
unknown's avatar
unknown committed
1230
{
1231
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1232 1233 1234 1235
  longlong value=args[0]->val_int()*args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
unknown's avatar
unknown committed
1236 1237 1238
}


unknown's avatar
unknown committed
1239
/** See Item_func_plus::decimal_op for comments. */
1240

unknown's avatar
unknown committed
1241 1242
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
{
1243 1244 1245
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1246 1247
  if ((null_value= args[0]->null_value))
    return 0;
1248
  val2= args[1]->val_decimal(&value2);
1249
  if (!(null_value= (args[1]->null_value ||
1250 1251
                     (my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
                                    val2) > 3))))
1252 1253
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1254 1255 1256
}


unknown's avatar
unknown committed
1257 1258
void Item_func_mul::result_precision()
{
unknown's avatar
unknown committed
1259 1260 1261 1262 1263 1264
  /* Integer operations keep unsigned_flag if one of arguments is unsigned */
  if (result_type() == INT_RESULT)
    unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
  else
    unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
  decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
1265 1266
  uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
  uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
1267 1268
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1269 1270 1271 1272
}


double Item_func_div::real_op()
unknown's avatar
unknown committed
1273
{
1274
  DBUG_ASSERT(fixed == 1);
1275 1276
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
unknown's avatar
unknown committed
1277 1278 1279 1280 1281
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0.0;
  if (val2 == 0.0)
  {
    signal_divide_by_null();
unknown's avatar
unknown committed
1282
    return 0.0;
unknown's avatar
unknown committed
1283
  }
1284
  return fix_result(value/val2);
unknown's avatar
unknown committed
1285 1286
}

unknown's avatar
unknown committed
1287

unknown's avatar
unknown committed
1288
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1289
{
1290 1291
  my_decimal value1, *val1;
  my_decimal value2, *val2;
unknown's avatar
unknown committed
1292
  int err;
1293 1294

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1295 1296
  if ((null_value= args[0]->null_value))
    return 0;
1297
  val2= args[1]->val_decimal(&value2);
unknown's avatar
unknown committed
1298 1299
  if ((null_value= args[1]->null_value))
    return 0;
unknown's avatar
unknown committed
1300 1301 1302 1303 1304 1305
  if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
                           val1, val2, prec_increment)) > 3)
  {
    if (err == E_DEC_DIV_ZERO)
      signal_divide_by_null();
    null_value= 1;
unknown's avatar
unknown committed
1306
    return 0;
1307
  }
unknown's avatar
unknown committed
1308
  return decimal_value;
unknown's avatar
unknown committed
1309 1310 1311 1312 1313
}


void Item_func_div::result_precision()
{
1314 1315 1316 1317
  uint precision=min(args[0]->decimal_precision() + 
                     args[1]->decimals + prec_increment,
                     DECIMAL_MAX_PRECISION);

unknown's avatar
unknown committed
1318 1319 1320 1321 1322 1323
  /* Integer operations keep unsigned_flag if one of arguments is unsigned */
  if (result_type() == INT_RESULT)
    unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
  else
    unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
  decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
1324 1325
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1326 1327
}

unknown's avatar
unknown committed
1328

unknown's avatar
unknown committed
1329 1330
void Item_func_div::fix_length_and_dec()
{
unknown's avatar
unknown committed
1331
  DBUG_ENTER("Item_func_div::fix_length_and_dec");
unknown's avatar
unknown committed
1332
  prec_increment= current_thd->variables.div_precincrement;
1333
  Item_num_op::fix_length_and_dec();
1334
  switch(hybrid_type) {
unknown's avatar
unknown committed
1335 1336
  case REAL_RESULT:
  {
unknown's avatar
unknown committed
1337
    decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
unknown's avatar
unknown committed
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
    set_if_smaller(decimals, NOT_FIXED_DEC);
    max_length=args[0]->max_length - args[0]->decimals + decimals;
    uint tmp=float_length(decimals);
    set_if_smaller(max_length,tmp);
    break;
  }
  case INT_RESULT:
    hybrid_type= DECIMAL_RESULT;
    DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
    result_precision();
    break;
  case DECIMAL_RESULT:
    result_precision();
    break;
  default:
    DBUG_ASSERT(0);
  }
  maybe_null= 1; // devision by zero
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1357 1358
}

1359 1360 1361 1362

/* Integer division */
longlong Item_func_int_div::val_int()
{
1363
  DBUG_ASSERT(fixed == 1);
1364 1365
  longlong value=args[0]->val_int();
  longlong val2=args[1]->val_int();
1366
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
1367 1368 1369 1370
    return 0;
  if (val2 == 0)
  {
    signal_divide_by_null();
1371
    return 0;
unknown's avatar
unknown committed
1372
  }
1373 1374 1375 1376 1377 1378 1379

  if (unsigned_flag)
    return  ((ulonglong) value / (ulonglong) val2);
  else if (value == LONGLONG_MIN && val2 == -1)
    return LONGLONG_MIN;
  else
    return value / val2;
1380 1381 1382 1383 1384
}


void Item_func_int_div::fix_length_and_dec()
{
1385 1386 1387 1388 1389
  Item_result argtype= args[0]->result_type();
  /* use precision ony for the data type it is applicable for and valid */
  max_length=args[0]->max_length -
    (argtype == DECIMAL_RESULT || argtype == INT_RESULT ?
     args[0]->decimals : 0);
1390
  maybe_null=1;
unknown's avatar
unknown committed
1391
  unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
1392 1393 1394
}


unknown's avatar
unknown committed
1395 1396 1397 1398 1399
longlong Item_func_mod::int_op()
{
  DBUG_ASSERT(fixed == 1);
  longlong value=  args[0]->val_int();
  longlong val2= args[1]->val_int();
1400 1401
  longlong result;

unknown's avatar
unknown committed
1402 1403 1404 1405 1406 1407 1408
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0; /* purecov: inspected */
  if (val2 == 0)
  {
    signal_divide_by_null();
    return 0;
  }
1409 1410

  if (args[0]->unsigned_flag)
1411 1412
    result= args[1]->unsigned_flag ? 
      ((ulonglong) value) % ((ulonglong) val2) : ((ulonglong) value) % val2;
1413 1414 1415
  else result= args[1]->unsigned_flag ?
         value % ((ulonglong) val2) :
         (val2 == -1) ? 0 : value % val2;
1416

1417
  return result;
unknown's avatar
unknown committed
1418 1419 1420
}

double Item_func_mod::real_op()
unknown's avatar
unknown committed
1421
{
1422
  DBUG_ASSERT(fixed == 1);
1423 1424
  double value= args[0]->val_real();
  double val2=  args[1]->val_real();
unknown's avatar
unknown committed
1425
  if ((null_value= args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1426
    return 0.0; /* purecov: inspected */
unknown's avatar
unknown committed
1427 1428 1429 1430 1431
  if (val2 == 0.0)
  {
    signal_divide_by_null();
    return 0.0;
  }
unknown's avatar
unknown committed
1432 1433 1434
  return fmod(value,val2);
}

unknown's avatar
unknown committed
1435 1436

my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1437
{
1438 1439 1440 1441
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1442 1443
  if ((null_value= args[0]->null_value))
    return 0;
1444
  val2= args[1]->val_decimal(&value2);
unknown's avatar
unknown committed
1445 1446 1447
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1448
                         val1, val2)) {
unknown's avatar
unknown committed
1449 1450 1451 1452
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
unknown's avatar
unknown committed
1453
    signal_divide_by_null();
unknown's avatar
unknown committed
1454
  default:
1455
    null_value= 1;
unknown's avatar
unknown committed
1456 1457
    return 0;
  }
unknown's avatar
unknown committed
1458 1459
}

unknown's avatar
unknown committed
1460 1461

void Item_func_mod::result_precision()
unknown's avatar
unknown committed
1462
{
unknown's avatar
unknown committed
1463 1464
  decimals= max(args[0]->decimals, args[1]->decimals);
  max_length= max(args[0]->max_length, args[1]->max_length);
unknown's avatar
unknown committed
1465 1466 1467 1468 1469
}


void Item_func_mod::fix_length_and_dec()
{
1470
  Item_num_op::fix_length_and_dec();
1471
  maybe_null= 1;
1472
  unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
1473 1474 1475
}


unknown's avatar
unknown committed
1476
double Item_func_neg::real_op()
unknown's avatar
unknown committed
1477
{
1478
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1479
  null_value= args[0]->null_value;
unknown's avatar
unknown committed
1480 1481 1482
  return -value;
}

unknown's avatar
unknown committed
1483

unknown's avatar
unknown committed
1484
longlong Item_func_neg::int_op()
unknown's avatar
unknown committed
1485
{
unknown's avatar
unknown committed
1486 1487
  longlong value= args[0]->val_int();
  null_value= args[0]->null_value;
unknown's avatar
unknown committed
1488 1489 1490
  return -value;
}

unknown's avatar
unknown committed
1491

unknown's avatar
unknown committed
1492
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1493
{
unknown's avatar
unknown committed
1494 1495 1496 1497 1498
  my_decimal val, *value= args[0]->val_decimal(&val);
  if (!(null_value= args[0]->null_value))
  {
    my_decimal2decimal(value, decimal_value);
    my_decimal_neg(decimal_value);
1499
    return decimal_value;
unknown's avatar
unknown committed
1500
  }
1501
  return 0;
unknown's avatar
unknown committed
1502 1503
}

1504

unknown's avatar
unknown committed
1505
void Item_func_neg::fix_num_length_and_dec()
unknown's avatar
unknown committed
1506
{
unknown's avatar
unknown committed
1507 1508 1509
  decimals= args[0]->decimals;
  /* 1 add because sign can appear */
  max_length= args[0]->max_length + 1;
unknown's avatar
unknown committed
1510 1511
}

unknown's avatar
unknown committed
1512

1513
void Item_func_neg::fix_length_and_dec()
unknown's avatar
unknown committed
1514
{
1515
  DBUG_ENTER("Item_func_neg::fix_length_and_dec");
unknown's avatar
unknown committed
1516
  Item_func_num1::fix_length_and_dec();
1517 1518 1519 1520

  /*
    If this is in integer context keep the context as integer if possible
    (This is how multiplication and other integer functions works)
1521 1522
    Use val() to get value as arg_type doesn't mean that item is
    Item_int or Item_real due to existence of Item_param.
1523
  */
unknown's avatar
unknown committed
1524
  if (hybrid_type == INT_RESULT && args[0]->const_item())
unknown's avatar
unknown committed
1525
  {
unknown's avatar
unknown committed
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
    longlong val= args[0]->val_int();
    if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
        ((ulonglong) val != (ulonglong) LONGLONG_MIN ||
          args[0]->type() != INT_ITEM))        
    {
      /*
        Ensure that result is converted to DECIMAL, as longlong can't hold
        the negated number
      */
      hybrid_type= DECIMAL_RESULT;
      DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
    }
unknown's avatar
unknown committed
1538
  }
unknown's avatar
unknown committed
1539
  unsigned_flag= 0;
unknown's avatar
unknown committed
1540
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1541 1542
}

unknown's avatar
unknown committed
1543

unknown's avatar
unknown committed
1544
double Item_func_abs::real_op()
unknown's avatar
unknown committed
1545
{
1546
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1547
  null_value= args[0]->null_value;
unknown's avatar
unknown committed
1548 1549 1550
  return fabs(value);
}

unknown's avatar
unknown committed
1551

unknown's avatar
unknown committed
1552
longlong Item_func_abs::int_op()
unknown's avatar
unknown committed
1553
{
unknown's avatar
unknown committed
1554
  longlong value= args[0]->val_int();
1555 1556 1557
  if ((null_value= args[0]->null_value))
    return 0;
  return (value >= 0) || unsigned_flag ? value : -value;
unknown's avatar
unknown committed
1558 1559
}

unknown's avatar
unknown committed
1560

unknown's avatar
unknown committed
1561
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1562
{
unknown's avatar
unknown committed
1563 1564
  my_decimal val, *value= args[0]->val_decimal(&val);
  if (!(null_value= args[0]->null_value))
unknown's avatar
unknown committed
1565
  {
unknown's avatar
unknown committed
1566 1567 1568
    my_decimal2decimal(value, decimal_value);
    if (decimal_value->sign())
      my_decimal_neg(decimal_value);
1569
    return decimal_value;
unknown's avatar
unknown committed
1570
  }
1571
  return 0;
unknown's avatar
unknown committed
1572 1573 1574 1575 1576 1577
}


void Item_func_abs::fix_length_and_dec()
{
  Item_func_num1::fix_length_and_dec();
1578
  unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
1579 1580
}

unknown's avatar
unknown committed
1581

unknown's avatar
unknown committed
1582
/** Gateway to natural LOG function. */
1583
double Item_func_ln::val_real()
1584
{
1585
  DBUG_ASSERT(fixed == 1);
1586
  double value= args[0]->val_real();
1587
  if ((null_value= args[0]->null_value))
1588
    return 0.0;
1589
  if (value <= 0.0)
1590 1591
  {
    signal_divide_by_null();
1592
    return 0.0;
1593
  }
1594 1595 1596
  return log(value);
}

unknown's avatar
unknown committed
1597 1598 1599 1600 1601
/** 
  Extended but so slower LOG function.

  We have to check if all values are > zero and first one is not one
  as these are the cases then result is not a number.
1602
*/ 
1603
double Item_func_log::val_real()
unknown's avatar
unknown committed
1604
{
1605
  DBUG_ASSERT(fixed == 1);
1606
  double value= args[0]->val_real();
1607
  if ((null_value= args[0]->null_value))
1608
    return 0.0;
1609
  if (value <= 0.0)
1610 1611 1612 1613
  {
    signal_divide_by_null();
    return 0.0;
  }
1614 1615
  if (arg_count == 2)
  {
1616
    double value2= args[1]->val_real();
1617
    if ((null_value= args[1]->null_value))
1618
      return 0.0;
1619
    if (value2 <= 0.0 || value == 1.0)
1620 1621 1622 1623
    {
      signal_divide_by_null();
      return 0.0;
    }
1624 1625
    return log(value2) / log(value);
  }
unknown's avatar
unknown committed
1626 1627 1628
  return log(value);
}

1629
double Item_func_log2::val_real()
1630
{
1631
  DBUG_ASSERT(fixed == 1);
1632
  double value= args[0]->val_real();
1633 1634

  if ((null_value=args[0]->null_value))
1635
    return 0.0;
1636
  if (value <= 0.0)
1637 1638 1639 1640
  {
    signal_divide_by_null();
    return 0.0;
  }
1641
  return log(value) / M_LN2;
1642 1643
}

1644
double Item_func_log10::val_real()
unknown's avatar
unknown committed
1645
{
1646
  DBUG_ASSERT(fixed == 1);
1647
  double value= args[0]->val_real();
1648
  if ((null_value= args[0]->null_value))
1649
    return 0.0;
1650
  if (value <= 0.0)
1651 1652 1653 1654
  {
    signal_divide_by_null();
    return 0.0;
  }
unknown's avatar
unknown committed
1655 1656 1657
  return log10(value);
}

1658
double Item_func_exp::val_real()
unknown's avatar
unknown committed
1659
{
1660
  DBUG_ASSERT(fixed == 1);
1661
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1662 1663
  if ((null_value=args[0]->null_value))
    return 0.0; /* purecov: inspected */
1664
  return fix_result(exp(value));
unknown's avatar
unknown committed
1665 1666
}

1667
double Item_func_sqrt::val_real()
unknown's avatar
unknown committed
1668
{
1669
  DBUG_ASSERT(fixed == 1);
1670
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1671 1672 1673 1674 1675
  if ((null_value=(args[0]->null_value || value < 0)))
    return 0.0; /* purecov: inspected */
  return sqrt(value);
}

1676
double Item_func_pow::val_real()
unknown's avatar
unknown committed
1677
{
1678
  DBUG_ASSERT(fixed == 1);
1679 1680
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
unknown's avatar
unknown committed
1681 1682
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
    return 0.0; /* purecov: inspected */
1683
  return fix_result(pow(value,val2));
unknown's avatar
unknown committed
1684 1685 1686 1687
}

// Trigonometric functions

1688
double Item_func_acos::val_real()
unknown's avatar
unknown committed
1689
{
1690
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1691
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1692
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
1693 1694
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
1695
  return acos(value);
unknown's avatar
unknown committed
1696 1697
}

1698
double Item_func_asin::val_real()
unknown's avatar
unknown committed
1699
{
1700
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1701
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1702
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
1703 1704
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
1705
  return asin(value);
unknown's avatar
unknown committed
1706 1707
}

1708
double Item_func_atan::val_real()
unknown's avatar
unknown committed
1709
{
1710
  DBUG_ASSERT(fixed == 1);
1711
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1712 1713 1714 1715
  if ((null_value=args[0]->null_value))
    return 0.0;
  if (arg_count == 2)
  {
1716
    double val2= args[1]->val_real();
unknown's avatar
unknown committed
1717 1718 1719 1720
    if ((null_value=args[1]->null_value))
      return 0.0;
    return fix_result(atan2(value,val2));
  }
1721
  return atan(value);
unknown's avatar
unknown committed
1722 1723
}

1724
double Item_func_cos::val_real()
unknown's avatar
unknown committed
1725
{
1726
  DBUG_ASSERT(fixed == 1);
1727
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1728 1729
  if ((null_value=args[0]->null_value))
    return 0.0;
1730
  return cos(value);
unknown's avatar
unknown committed
1731 1732
}

1733
double Item_func_sin::val_real()
unknown's avatar
unknown committed
1734
{
1735
  DBUG_ASSERT(fixed == 1);
1736
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1737 1738
  if ((null_value=args[0]->null_value))
    return 0.0;
1739
  return sin(value);
unknown's avatar
unknown committed
1740 1741
}

1742
double Item_func_tan::val_real()
unknown's avatar
unknown committed
1743
{
1744
  DBUG_ASSERT(fixed == 1);
1745
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(tan(value));
}


// Shift-functions, same as << and >> in C/C++


longlong Item_func_shift_left::val_int()
{
1757
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771
  uint shift;
  ulonglong res= ((ulonglong) args[0]->val_int() <<
		  (shift=(uint) args[1]->val_int()));
  if (args[0]->null_value || args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
}

longlong Item_func_shift_right::val_int()
{
1772
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
  uint shift;
  ulonglong res= (ulonglong) args[0]->val_int() >>
    (shift=(uint) args[1]->val_int());
  if (args[0]->null_value || args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
}


longlong Item_func_bit_neg::val_int()
{
1788
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
  ulonglong res= (ulonglong) args[0]->val_int();
  if ((null_value=args[0]->null_value))
    return 0;
  return ~res;
}


// Conversion functions

void Item_func_integer::fix_length_and_dec()
{
  max_length=args[0]->max_length - args[0]->decimals+1;
  uint tmp=float_length(decimals);
  set_if_smaller(max_length,tmp);
  decimals=0;
}

unknown's avatar
unknown committed
1806
void Item_func_int_val::fix_num_length_and_dec()
unknown's avatar
unknown committed
1807
{
unknown's avatar
unknown committed
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859
  max_length= args[0]->max_length - (args[0]->decimals ?
                                     args[0]->decimals + 1 :
                                     0) + 2;
  uint tmp= float_length(decimals);
  set_if_smaller(max_length,tmp);
  decimals= 0;
}


void Item_func_int_val::find_num_type()
{
  DBUG_ENTER("Item_func_int_val::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
  switch(hybrid_type= args[0]->result_type())
  {
  case STRING_RESULT:
  case REAL_RESULT:
    hybrid_type= REAL_RESULT;
    max_length= float_length(decimals);
    break;
  case INT_RESULT:
  case DECIMAL_RESULT:
    /*
      -2 because in most high position can't be used any digit for longlong
      and one position for increasing value during operation
    */
    if ((args[0]->max_length - args[0]->decimals) >=
        (DECIMAL_LONGLONG_DIGITS - 2))
    {
      hybrid_type= DECIMAL_RESULT;
    }
    else
    {
      unsigned_flag= args[0]->unsigned_flag;
      hybrid_type= INT_RESULT;
    }
    break;
  default:
    DBUG_ASSERT(0);
  }
  DBUG_PRINT("info", ("Type: %s",
                      (hybrid_type == REAL_RESULT ? "REAL_RESULT" :
                       hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
                       hybrid_type == INT_RESULT ? "INT_RESULT" :
                       "--ILLEGAL!!!--")));

  DBUG_VOID_RETURN;
}


longlong Item_func_ceiling::int_op()
{
1860 1861 1862 1863 1864 1865 1866 1867 1868
  longlong result;
  switch (args[0]->result_type()) {
  case INT_RESULT:
    result= args[0]->val_int();
    null_value= args[0]->null_value;
    break;
  case DECIMAL_RESULT:
  {
    my_decimal dec_buf, *dec;
1869
    if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
1870 1871 1872 1873 1874 1875
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
    else
      result= 0;
    break;
  }
  default:
1876
    result= (longlong)Item_func_ceiling::real_op();
1877 1878
  };
  return result;
unknown's avatar
unknown committed
1879 1880
}

unknown's avatar
unknown committed
1881 1882

double Item_func_ceiling::real_op()
unknown's avatar
unknown committed
1883
{
unknown's avatar
unknown committed
1884 1885 1886 1887
  /*
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
    bug)
  */
1888
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
1889 1890 1891 1892 1893 1894
  null_value= args[0]->null_value;
  return ceil(value);
}


my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1895
{
unknown's avatar
unknown committed
1896
  my_decimal val, *value= args[0]->val_decimal(&val);
1897 1898 1899 1900 1901
  if (!(null_value= (args[0]->null_value ||
                     my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
                                        decimal_value) > 1)))
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1902 1903 1904 1905 1906
}


longlong Item_func_floor::int_op()
{
1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925
  longlong result;
  switch (args[0]->result_type()) {
  case INT_RESULT:
    result= args[0]->val_int();
    null_value= args[0]->null_value;
    break;
  case DECIMAL_RESULT:
  {
    my_decimal dec_buf, *dec;
    if ((dec= Item_func_floor::decimal_op(&dec_buf)))
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
    else
      result= 0;
    break;
  }
  default:
    result= (longlong)Item_func_floor::real_op();
  };
  return result;
unknown's avatar
unknown committed
1926 1927
}

unknown's avatar
unknown committed
1928 1929

double Item_func_floor::real_op()
unknown's avatar
unknown committed
1930
{
unknown's avatar
unknown committed
1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943
  /*
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
    bug)
  */
  volatile double value= args[0]->val_real();
  null_value= args[0]->null_value;
  return floor(value);
}


my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
{
  my_decimal val, *value= args[0]->val_decimal(&val);
1944 1945 1946 1947 1948
  if (!(null_value= (args[0]->null_value ||
                     my_decimal_floor(E_DEC_FATAL_ERROR, value,
                                      decimal_value) > 1)))
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1949 1950 1951
}


unknown's avatar
unknown committed
1952
void Item_func_round::fix_length_and_dec()
unknown's avatar
unknown committed
1953
{
1954 1955 1956 1957
  int      decimals_to_set;
  longlong val1;
  bool     val1_unsigned;
  
unknown's avatar
unknown committed
1958 1959
  unsigned_flag= args[0]->unsigned_flag;
  if (!args[1]->const_item())
unknown's avatar
unknown committed
1960
  {
unknown's avatar
unknown committed
1961
    decimals= args[0]->decimals;
1962
    max_length= float_length(decimals);
1963 1964 1965 1966 1967 1968 1969
    if (args[0]->result_type() == DECIMAL_RESULT)
    {
      max_length++;
      hybrid_type= DECIMAL_RESULT;
    }
    else
      hybrid_type= REAL_RESULT;
unknown's avatar
unknown committed
1970 1971
    return;
  }
1972 1973 1974 1975 1976 1977 1978 1979

  val1= args[1]->val_int();
  val1_unsigned= args[1]->unsigned_flag;
  if (val1 < 0)
    decimals_to_set= val1_unsigned ? INT_MAX : 0;
  else
    decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;

unknown's avatar
unknown committed
1980 1981 1982
  if (args[0]->decimals == NOT_FIXED_DEC)
  {
    decimals= min(decimals_to_set, NOT_FIXED_DEC);
1983
    max_length= float_length(decimals);
unknown's avatar
unknown committed
1984 1985 1986 1987
    hybrid_type= REAL_RESULT;
    return;
  }
  
unknown's avatar
unknown committed
1988
  switch (args[0]->result_type()) {
unknown's avatar
unknown committed
1989 1990 1991 1992 1993 1994 1995
  case REAL_RESULT:
  case STRING_RESULT:
    hybrid_type= REAL_RESULT;
    decimals= min(decimals_to_set, NOT_FIXED_DEC);
    max_length= float_length(decimals);
    break;
  case INT_RESULT:
1996
    if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
unknown's avatar
unknown committed
1997
    {
1998
      int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
unknown's avatar
unknown committed
1999
      max_length= args[0]->max_length + length_can_increase;
unknown's avatar
unknown committed
2000 2001 2002 2003 2004
      /* Here we can keep INT_RESULT */
      hybrid_type= INT_RESULT;
      decimals= 0;
      break;
    }
unknown's avatar
unknown committed
2005
    /* fall through */
unknown's avatar
unknown committed
2006 2007 2008
  case DECIMAL_RESULT:
  {
    hybrid_type= DECIMAL_RESULT;
2009
    decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
unknown's avatar
unknown committed
2010 2011
    int decimals_delta= args[0]->decimals - decimals_to_set;
    int precision= args[0]->decimal_precision();
2012 2013 2014
    int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;

    precision-= decimals_delta - length_increase;
2015
    decimals= min(decimals_to_set, DECIMAL_MAX_SCALE);
2016 2017 2018
    max_length= my_decimal_precision_to_length_no_truncation(precision,
                                                             decimals,
                                                             unsigned_flag);
unknown's avatar
unknown committed
2019 2020 2021 2022
    break;
  }
  default:
    DBUG_ASSERT(0); /* This result type isn't handled */
unknown's avatar
unknown committed
2023 2024 2025
  }
}

2026 2027
double my_double_round(double value, longlong dec, bool dec_unsigned,
                       bool truncate)
unknown's avatar
unknown committed
2028
{
2029
  double tmp;
2030 2031
  bool dec_negative= (dec < 0) && !dec_unsigned;
  ulonglong abs_dec= dec_negative ? -dec : dec;
2032 2033 2034 2035 2036
  /*
    tmp2 is here to avoid return the value with 80 bit precision
    This will fix that the test round(0.1,1) = round(0.1,1) is true
  */
  volatile double tmp2;
unknown's avatar
unknown committed
2037

2038 2039
  tmp=(abs_dec < array_elements(log_10) ?
       log_10[abs_dec] : pow(10.0,(double) abs_dec));
unknown's avatar
unknown committed
2040

2041
  if (dec_negative && my_isinf(tmp))
2042
    tmp2= 0;
2043
  else if (!dec_negative && my_isinf(value * tmp))
2044 2045
    tmp2= value;
  else if (truncate)
unknown's avatar
unknown committed
2046 2047
  {
    if (value >= 0)
2048
      tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
unknown's avatar
unknown committed
2049
    else
2050
      tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
unknown's avatar
unknown committed
2051
  }
2052 2053 2054
  else
    tmp2=dec < 0 ? rint(value/tmp)*tmp : rint(value*tmp)/tmp;
  return tmp2;
unknown's avatar
unknown committed
2055 2056 2057
}


2058 2059 2060 2061 2062
double Item_func_round::real_op()
{
  double value= args[0]->val_real();

  if (!(null_value= args[0]->null_value || args[1]->null_value))
2063 2064
    return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
                           truncate);
2065 2066 2067 2068

  return 0.0;
}

2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
/*
  Rounds a given value to a power of 10 specified as the 'to' argument,
  avoiding overflows when the value is close to the ulonglong range boundary.
*/

static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to)
{
  ulonglong tmp= value / to * to;
  return (value - tmp < (to >> 1)) ? tmp : tmp + to;
}

2080

unknown's avatar
unknown committed
2081 2082 2083
longlong Item_func_round::int_op()
{
  longlong value= args[0]->val_int();
2084
  longlong dec= args[1]->val_int();
unknown's avatar
unknown committed
2085
  decimals= 0;
2086
  ulonglong abs_dec;
unknown's avatar
unknown committed
2087 2088
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0;
2089
  if ((dec >= 0) || args[1]->unsigned_flag)
unknown's avatar
unknown committed
2090 2091 2092
    return value; // integer have not digits after point

  abs_dec= -dec;
unknown's avatar
unknown committed
2093 2094 2095 2096 2097 2098 2099
  longlong tmp;
  
  if(abs_dec >= array_elements(log_10_int))
    return 0;
  
  tmp= log_10_int[abs_dec];
  
unknown's avatar
unknown committed
2100
  if (truncate)
2101 2102
    value= (unsigned_flag) ?
      ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp;
unknown's avatar
unknown committed
2103
  else
2104 2105
    value= (unsigned_flag || value >= 0) ?
      my_unsigned_round((ulonglong) value, tmp) :
2106
      -(longlong) my_unsigned_round((ulonglong) -value, tmp);
unknown's avatar
unknown committed
2107
  return value;
unknown's avatar
unknown committed
2108 2109 2110 2111 2112 2113
}


my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
{
  my_decimal val, *value= args[0]->val_decimal(&val);
2114
  longlong dec= args[1]->val_int();
2115
  if (dec >= 0 || args[1]->unsigned_flag)
2116
    dec= min((ulonglong) dec, decimals);
2117 2118 2119
  else if (dec < INT_MIN)
    dec= INT_MIN;
    
2120
  if (!(null_value= (args[0]->null_value || args[1]->null_value ||
2121
                     my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
2122 2123 2124
                                      truncate, decimal_value) > 1))) 
  {
    decimal_value->frac= decimals;
2125
    return decimal_value;
2126
  }
2127
  return 0;
unknown's avatar
unknown committed
2128 2129 2130
}


2131 2132 2133 2134 2135 2136 2137
void Item_func_rand::seed_random(Item *arg)
{
  /*
    TODO: do not do reinit 'rand' for every execute of PS/SP if
    args[0] is a constant.
  */
  uint32 tmp= (uint32) arg->val_int();
2138
  my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L),
2139 2140 2141 2142
             (uint32) (tmp*0x10000001L));
}


2143
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
unknown's avatar
unknown committed
2144
{
2145
  if (Item_real_func::fix_fields(thd, ref))
2146
    return TRUE;
2147
  used_tables_cache|= RAND_TABLE_BIT;
unknown's avatar
unknown committed
2148 2149
  if (arg_count)
  {					// Only use argument once in query
2150
    /*
unknown's avatar
unknown committed
2151
      Allocate rand structure once: we must use thd->stmt_arena
2152 2153
      to create rand in proper mem_root if it's a prepared statement or
      stored procedure.
2154 2155 2156

      No need to send a Rand log event if seed was given eg: RAND(seed),
      as it will be replicated in the query as such.
2157
    */
2158
    if (!rand && !(rand= (struct my_rnd_struct*)
unknown's avatar
unknown committed
2159
                   thd->stmt_arena->alloc(sizeof(*rand))))
2160
      return TRUE;
unknown's avatar
unknown committed
2161
  }
2162
  else
unknown's avatar
unknown committed
2163
  {
2164 2165 2166 2167 2168
    /*
      Save the seed only the first time RAND() is used in the query
      Once events are forwarded rather than recreated,
      the following can be skipped if inside the slave thread
    */
2169 2170 2171 2172 2173 2174
    if (!thd->rand_used)
    {
      thd->rand_used= 1;
      thd->rand_saved_seed1= thd->rand.seed1;
      thd->rand_saved_seed2= thd->rand.seed2;
    }
2175
    rand= &thd->rand;
unknown's avatar
unknown committed
2176
  }
2177
  return FALSE;
2178 2179
}

unknown's avatar
unknown committed
2180 2181 2182 2183 2184 2185
void Item_func_rand::update_used_tables()
{
  Item_real_func::update_used_tables();
  used_tables_cache|= RAND_TABLE_BIT;
}

2186

2187
double Item_func_rand::val_real()
2188
{
2189
  DBUG_ASSERT(fixed == 1);
2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
  if (arg_count)
  {
    if (!args[0]->const_item())
      seed_random(args[0]);
    else if (first_eval)
    {
      /*
        Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
        is a field item of "constant" table. Thus, we have to evaluate
        seed_random() for constant arg there but not at the fix_fields method.
      */
      first_eval= FALSE;
      seed_random(args[0]);
    }
  }
2205
  return my_rnd(rand);
unknown's avatar
unknown committed
2206 2207 2208 2209
}

longlong Item_func_sign::val_int()
{
2210
  DBUG_ASSERT(fixed == 1);
2211
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2212 2213 2214 2215 2216
  null_value=args[0]->null_value;
  return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}


2217
double Item_func_units::val_real()
unknown's avatar
unknown committed
2218
{
2219
  DBUG_ASSERT(fixed == 1);
2220
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2221 2222 2223 2224 2225 2226 2227 2228
  if ((null_value=args[0]->null_value))
    return 0;
  return value*mul+add;
}


void Item_func_min_max::fix_length_and_dec()
{
unknown's avatar
unknown committed
2229
  int max_int_part=0;
2230
  bool datetime_found= FALSE;
unknown's avatar
unknown committed
2231 2232
  decimals=0;
  max_length=0;
unknown's avatar
unknown committed
2233
  maybe_null=0;
unknown's avatar
unknown committed
2234
  cmp_type=args[0]->result_type();
2235

unknown's avatar
unknown committed
2236 2237
  for (uint i=0 ; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2238 2239
    set_if_bigger(max_length, args[i]->max_length);
    set_if_bigger(decimals, args[i]->decimals);
unknown's avatar
unknown committed
2240
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
unknown's avatar
unknown committed
2241 2242
    if (args[i]->maybe_null)
      maybe_null=1;
unknown's avatar
unknown committed
2243
    cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
2244 2245 2246 2247 2248 2249
    if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
    {
      datetime_found= TRUE;
      if (!datetime_item || args[i]->field_type() == MYSQL_TYPE_DATETIME)
        datetime_item= args[i];
    }
unknown's avatar
unknown committed
2250
  }
unknown's avatar
unknown committed
2251
  if (cmp_type == STRING_RESULT)
2252
  {
2253
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1);
2254 2255 2256 2257 2258 2259
    if (datetime_found)
    {
      thd= current_thd;
      compare_as_dates= TRUE;
    }
  }
unknown's avatar
unknown committed
2260
  else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
2261 2262 2263
    max_length= my_decimal_precision_to_length_no_truncation(max_int_part +
                                                             decimals, decimals,
                                                             unsigned_flag);
2264 2265
  else if (cmp_type == REAL_RESULT)
    max_length= float_length(decimals);
2266
  cached_field_type= agg_field_type(args, arg_count);
unknown's avatar
unknown committed
2267 2268 2269
}


2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283
/*
  Compare item arguments in the DATETIME context.

  SYNOPSIS
    cmp_datetimes()
    value [out]   found least/greatest DATE/DATETIME value

  DESCRIPTION
    Compare item arguments as DATETIME values and return the index of the
    least/greatest argument in the arguments array.
    The correct integer DATE/DATETIME value of the found argument is
    stored to the value pointer, if latter is provided.

  RETURN
2284
   0	If one of arguments is NULL or there was a execution error
2285 2286 2287 2288 2289
   #	index of the least/greatest argument
*/

uint Item_func_min_max::cmp_datetimes(ulonglong *value)
{
2290
  longlong UNINIT_VAR(min_max);
2291 2292 2293 2294 2295 2296
  uint min_max_idx= 0;

  for (uint i=0; i < arg_count ; i++)
  {
    Item **arg= args + i;
    bool is_null;
2297
    longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
2298 2299 2300 2301 2302 2303 2304 2305

    /* Check if we need to stop (because of error or KILL)  and stop the loop */
    if (thd->is_error())
    {
      null_value= 1;
      return 0;
    }

2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323
    if ((null_value= args[i]->null_value))
      return 0;
    if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
    {
      min_max= res;
      min_max_idx= i;
    }
  }
  if (value)
  {
    *value= min_max;
    if (datetime_item->field_type() == MYSQL_TYPE_DATE)
      *value/= 1000000L;
  }
  return min_max_idx;
}


unknown's avatar
unknown committed
2324 2325
String *Item_func_min_max::val_str(String *str)
{
2326
  DBUG_ASSERT(fixed == 1);
2327 2328 2329 2330 2331 2332 2333
  if (compare_as_dates)
  {
    String *str_res;
    uint min_max_idx= cmp_datetimes(NULL);
    if (null_value)
      return 0;
    str_res= args[min_max_idx]->val_str(str);
2334 2335 2336 2337 2338 2339
    if (args[min_max_idx]->null_value)
    {
      // check if the call to val_str() above returns a NULL value
      null_value= 1;
      return NULL;
    }
2340 2341 2342
    str_res->set_charset(collation.collation);
    return str_res;
  }
unknown's avatar
unknown committed
2343 2344 2345 2346 2347 2348
  switch (cmp_type) {
  case INT_RESULT:
  {
    longlong nr=val_int();
    if (null_value)
      return 0;
2349
    str->set_int(nr, unsigned_flag, &my_charset_bin);
unknown's avatar
unknown committed
2350 2351
    return str;
  }
unknown's avatar
unknown committed
2352 2353 2354 2355 2356 2357 2358 2359
  case DECIMAL_RESULT:
  {
    my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
    if (null_value)
      return 0;
    my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
    return str;
  }
unknown's avatar
unknown committed
2360 2361
  case REAL_RESULT:
  {
2362
    double nr= val_real();
unknown's avatar
unknown committed
2363 2364
    if (null_value)
      return 0; /* purecov: inspected */
2365
    str->set_real(nr,decimals,&my_charset_bin);
unknown's avatar
unknown committed
2366 2367 2368 2369
    return str;
  }
  case STRING_RESULT:
  {
2370
    String *UNINIT_VAR(res);
unknown's avatar
unknown committed
2371 2372
    for (uint i=0; i < arg_count ; i++)
    {
unknown's avatar
unknown committed
2373
      if (i == 0)
unknown's avatar
unknown committed
2374 2375 2376 2377 2378 2379 2380
	res=args[i]->val_str(str);
      else
      {
	String *res2;
	res2= args[i]->val_str(res == str ? &tmp_value : str);
	if (res2)
	{
2381
	  int cmp= sortcmp(res,res2,collation.collation);
unknown's avatar
unknown committed
2382 2383 2384 2385
	  if ((cmp_sign < 0 ? cmp : -cmp) < 0)
	    res=res2;
	}
      }
unknown's avatar
unknown committed
2386
      if ((null_value= args[i]->null_value))
2387
        return 0;
unknown's avatar
unknown committed
2388
    }
2389
    res->set_charset(collation.collation);
unknown's avatar
unknown committed
2390 2391
    return res;
  }
2392
  case ROW_RESULT:
unknown's avatar
unknown committed
2393
  default:
unknown's avatar
unknown committed
2394
    // This case should never be chosen
unknown's avatar
unknown committed
2395 2396
    DBUG_ASSERT(0);
    return 0;
unknown's avatar
unknown committed
2397 2398 2399 2400 2401
  }
  return 0;					// Keep compiler happy
}


2402
double Item_func_min_max::val_real()
unknown's avatar
unknown committed
2403
{
2404
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2405
  double value=0.0;
2406 2407
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2408
    ulonglong result= 0;
2409 2410 2411
    (void)cmp_datetimes(&result);
    return (double)result;
  }
unknown's avatar
unknown committed
2412 2413
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2414
    if (i == 0)
2415
      value= args[i]->val_real();
unknown's avatar
unknown committed
2416 2417
    else
    {
2418
      double tmp= args[i]->val_real();
unknown's avatar
unknown committed
2419 2420 2421
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
    }
unknown's avatar
unknown committed
2422 2423
    if ((null_value= args[i]->null_value))
      break;
unknown's avatar
unknown committed
2424 2425 2426 2427 2428 2429 2430
  }
  return value;
}


longlong Item_func_min_max::val_int()
{
2431
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2432
  longlong value=0;
2433 2434
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2435
    ulonglong result= 0;
2436 2437 2438
    (void)cmp_datetimes(&result);
    return (longlong)result;
  }
unknown's avatar
unknown committed
2439 2440
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2441
    if (i == 0)
2442
      value=args[i]->val_int();
unknown's avatar
unknown committed
2443 2444
    else
    {
2445 2446 2447
      longlong tmp=args[i]->val_int();
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
unknown's avatar
unknown committed
2448
    }
2449 2450
    if ((null_value= args[i]->null_value))
      break;
unknown's avatar
unknown committed
2451 2452 2453 2454
  }
  return value;
}

unknown's avatar
unknown committed
2455 2456 2457 2458

my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
{
  DBUG_ASSERT(fixed == 1);
2459
  my_decimal tmp_buf, *tmp, *UNINIT_VAR(res);
2460

2461 2462
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2463
    ulonglong value= 0;
2464 2465 2466 2467
    (void)cmp_datetimes(&value);
    ulonglong2decimal(value, dec);
    return dec;
  }
unknown's avatar
unknown committed
2468 2469
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2470
    if (i == 0)
unknown's avatar
unknown committed
2471 2472 2473
      res= args[i]->val_decimal(dec);
    else
    {
2474 2475
      tmp= args[i]->val_decimal(&tmp_buf);      // Zero if NULL
      if (tmp && (my_decimal_cmp(tmp, res) * cmp_sign) < 0)
unknown's avatar
unknown committed
2476 2477 2478
      {
        if (tmp == &tmp_buf)
        {
2479
          /* Move value out of tmp_buf as this will be reused on next loop */
unknown's avatar
unknown committed
2480 2481 2482 2483 2484 2485 2486
          my_decimal2decimal(tmp, dec);
          res= dec;
        }
        else
          res= tmp;
      }
    }
unknown's avatar
unknown committed
2487
    if ((null_value= args[i]->null_value))
2488 2489
    {
      res= 0;
unknown's avatar
unknown committed
2490
      break;
2491
    }
unknown's avatar
unknown committed
2492 2493 2494 2495 2496
  }
  return res;
}


unknown's avatar
unknown committed
2497 2498
longlong Item_func_length::val_int()
{
2499
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
  return (longlong) res->length();
}

unknown's avatar
unknown committed
2510

unknown's avatar
unknown committed
2511 2512
longlong Item_func_char_length::val_int()
{
2513
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2514 2515 2516 2517 2518 2519 2520
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2521
  return (longlong) res->numchars();
unknown's avatar
unknown committed
2522 2523
}

unknown's avatar
unknown committed
2524

unknown's avatar
unknown committed
2525 2526
longlong Item_func_coercibility::val_int()
{
2527
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2528
  null_value= 0;
2529
  return (longlong) args[0]->collation.derivation;
unknown's avatar
unknown committed
2530
}
unknown's avatar
unknown committed
2531

unknown's avatar
unknown committed
2532

2533 2534
void Item_func_locate::fix_length_and_dec()
{
2535
  max_length= MY_INT32_NUM_DECIMAL_DIGITS;
2536
  agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
2537 2538
}

unknown's avatar
unknown committed
2539

unknown's avatar
unknown committed
2540 2541
longlong Item_func_locate::val_int()
{
2542
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2543 2544 2545 2546 2547 2548 2549 2550
  String *a=args[0]->val_str(&value1);
  String *b=args[1]->val_str(&value2);
  if (!a || !b)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2551 2552 2553
  /* must be longlong to avoid truncation */
  longlong start=  0; 
  longlong start0= 0;
2554
  my_match_t match;
2555

unknown's avatar
unknown committed
2556 2557
  if (arg_count == 3)
  {
2558 2559 2560 2561 2562 2563
    start0= start= args[2]->val_int() - 1;

    if ((start < 0) || (start > a->length()))
      return 0;

    /* start is now sufficiently valid to pass to charpos function */
2564
    start= a->charpos((int) start);
2565 2566

    if (start + b->length() > a->length())
unknown's avatar
unknown committed
2567 2568
      return 0;
  }
2569

unknown's avatar
unknown committed
2570
  if (!b->length())				// Found empty string at start
2571
    return start + 1;
2572
  
2573
  if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
2574 2575
                                            a->ptr()+start,
                                            (uint) (a->length()-start),
2576 2577 2578
                                            b->ptr(), b->length(),
                                            &match, 1))
    return 0;
2579
  return (longlong) match.mb_len + start0 + 1;
unknown's avatar
unknown committed
2580 2581 2582
}


2583
void Item_func_locate::print(String *str, enum_query_type query_type)
2584
{
2585
  str->append(STRING_WITH_LEN("locate("));
2586
  args[1]->print(str, query_type);
2587
  str->append(',');
2588
  args[0]->print(str, query_type);
2589 2590 2591
  if (arg_count == 3)
  {
    str->append(',');
2592
    args[2]->print(str, query_type);
2593 2594 2595 2596 2597
  }
  str->append(')');
}


unknown's avatar
unknown committed
2598 2599
longlong Item_func_field::val_int()
{
2600
  DBUG_ASSERT(fixed == 1);
2601

2602 2603 2604
  if (cmp_type == STRING_RESULT)
  {
    String *field;
2605 2606
    if (!(field= args[0]->val_str(&value)))
      return 0;
2607
    for (uint i=1 ; i < arg_count ; i++)
2608 2609
    {
      String *tmp_value=args[i]->val_str(&tmp);
unknown's avatar
Fix:  
unknown committed
2610
      if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
2611
        return (longlong) (i);
2612 2613 2614 2615
    }
  }
  else if (cmp_type == INT_RESULT)
  {
2616
    longlong val= args[0]->val_int();
unknown's avatar
unknown committed
2617 2618
    if (args[0]->null_value)
      return 0;
2619
    for (uint i=1; i < arg_count ; i++)
2620
    {
2621
      if (val == args[i]->val_int() && !args[i]->null_value)
2622
        return (longlong) (i);
2623 2624
    }
  }
unknown's avatar
unknown committed
2625 2626 2627 2628
  else if (cmp_type == DECIMAL_RESULT)
  {
    my_decimal dec_arg_buf, *dec_arg,
               dec_buf, *dec= args[0]->val_decimal(&dec_buf);
unknown's avatar
unknown committed
2629 2630
    if (args[0]->null_value)
      return 0;
unknown's avatar
unknown committed
2631 2632 2633
    for (uint i=1; i < arg_count; i++)
    {
      dec_arg= args[i]->val_decimal(&dec_arg_buf);
unknown's avatar
unknown committed
2634
      if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
unknown's avatar
unknown committed
2635 2636 2637
        return (longlong) (i);
    }
  }
2638
  else
unknown's avatar
unknown committed
2639
  {
2640
    double val= args[0]->val_real();
unknown's avatar
unknown committed
2641 2642
    if (args[0]->null_value)
      return 0;
2643
    for (uint i=1; i < arg_count ; i++)
2644
    {
unknown's avatar
unknown committed
2645
      if (val == args[i]->val_real() && !args[i]->null_value)
2646
        return (longlong) (i);
2647
    }
unknown's avatar
unknown committed
2648 2649 2650 2651
  }
  return 0;
}

unknown's avatar
unknown committed
2652

2653 2654 2655
void Item_func_field::fix_length_and_dec()
{
  maybe_null=0; max_length=3;
2656 2657
  cmp_type= args[0]->result_type();
  for (uint i=1; i < arg_count ; i++)
2658 2659
    cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
  if (cmp_type == STRING_RESULT)
2660
    agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1);
2661
}
unknown's avatar
unknown committed
2662

2663

unknown's avatar
unknown committed
2664 2665
longlong Item_func_ascii::val_int()
{
2666
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  return (longlong) (res->length() ? (uchar) (*res)[0] : (uchar) 0);
}

longlong Item_func_ord::val_int()
{
2679
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2680 2681 2682 2683 2684 2685 2686 2687 2688
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  if (!res->length()) return 0;
#ifdef USE_MB
2689
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
2690 2691
  {
    register const char *str=res->ptr();
2692
    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
unknown's avatar
unknown committed
2693 2694
    if (!l)
      return (longlong)((uchar) *str);
unknown's avatar
unknown committed
2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
    while (l--)
      n=(n<<8)|(uint32)((uchar) *str++);
    return (longlong) n;
  }
#endif
  return (longlong) ((uchar) (*res)[0]);
}

	/* Search after a string in a string of strings separated by ',' */
	/* Returns number of found type >= 1 or 0 if not found */
	/* This optimizes searching in enums to bit testing! */

void Item_func_find_in_set::fix_length_and_dec()
{
  decimals=0;
  max_length=3;					// 1-999
  if (args[0]->const_item() && args[1]->type() == FIELD_ITEM)
  {
    Field *field= ((Item_field*) args[1])->field;
2714
    if (field->real_type() == MYSQL_TYPE_SET)
unknown's avatar
unknown committed
2715 2716 2717 2718
    {
      String *find=args[0]->val_str(&value);
      if (find)
      {
2719 2720
	enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
			      find->length(), 0);
unknown's avatar
unknown committed
2721 2722 2723 2724 2725 2726
	enum_bit=0;
	if (enum_value)
	  enum_bit=LL(1) << (enum_value-1);
      }
    }
  }
2727
  agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1);
unknown's avatar
unknown committed
2728 2729 2730 2731 2732 2733
}

static const char separator=',';

longlong Item_func_find_in_set::val_int()
{
2734
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754
  if (enum_value)
  {
    ulonglong tmp=(ulonglong) args[1]->val_int();
    if (!(null_value=args[1]->null_value || args[0]->null_value))
    {
      if (tmp & enum_bit)
	return enum_value;
    }
    return 0L;
  }

  String *find=args[0]->val_str(&value);
  String *buffer=args[1]->val_str(&value2);
  if (!find || !buffer)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;

2755
  if ((int) (buffer->length() - find->length()) >= 0)
unknown's avatar
unknown committed
2756
  {
2757
    my_wc_t wc= 0;
2758 2759 2760 2761 2762 2763 2764 2765
    CHARSET_INFO *cs= cmp_collation.collation;
    const char *str_begin= buffer->ptr();
    const char *str_end= buffer->ptr();
    const char *real_end= str_end+buffer->length();
    const uchar *find_str= (const uchar *) find->ptr();
    uint find_str_len= find->length();
    int position= 0;
    while (1)
unknown's avatar
unknown committed
2766
    {
2767 2768 2769
      int symbol_len;
      if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end, 
                                       (uchar*) real_end)) > 0)
unknown's avatar
unknown committed
2770
      {
2771 2772
        const char *substr_end= str_end + symbol_len;
        bool is_last_item= (substr_end == real_end);
2773 2774
        bool is_separator= (wc == (my_wc_t) separator);
        if (is_separator || is_last_item)
2775 2776
        {
          position++;
2777
          if (is_last_item && !is_separator)
2778 2779
            str_end= substr_end;
          if (!my_strnncoll(cs, (const uchar *) str_begin,
2780
                            (uint) (str_end - str_begin),
2781 2782 2783 2784 2785 2786
                            find_str, find_str_len))
            return (longlong) position;
          else
            str_begin= substr_end;
        }
        str_end= substr_end;
unknown's avatar
unknown committed
2787
      }
unknown's avatar
unknown committed
2788 2789
      else if (str_end - str_begin == 0 &&
               find_str_len == 0 &&
2790 2791 2792
               wc == (my_wc_t) separator)
        return (longlong) ++position;
      else
unknown's avatar
unknown committed
2793
        return LL(0);
2794
    }
unknown's avatar
unknown committed
2795 2796 2797 2798 2799 2800
  }
  return 0;
}

longlong Item_func_bit_count::val_int()
{
2801
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2802
  ulonglong value= (ulonglong) args[0]->val_int();
2803
  if ((null_value= args[0]->null_value))
unknown's avatar
unknown committed
2804
    return 0; /* purecov: inspected */
unknown's avatar
unknown committed
2805
  return (longlong) my_count_bits(value);
unknown's avatar
unknown committed
2806 2807 2808 2809 2810 2811
}


/****************************************************************************
** Functions to handle dynamic loadable functions
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
2812
** Rewritten by monty.
unknown's avatar
unknown committed
2813 2814 2815 2816
****************************************************************************/

#ifdef HAVE_DLOPEN

2817
void udf_handler::cleanup()
unknown's avatar
unknown committed
2818
{
2819
  if (!not_original)
unknown's avatar
unknown committed
2820
  {
2821
    if (initialized)
unknown's avatar
unknown committed
2822
    {
2823 2824
      if (u_d->func_deinit != NULL)
      {
2825
        Udf_func_deinit deinit= u_d->func_deinit;
2826 2827 2828
        (*deinit)(&initid);
      }
      free_udf(u_d);
2829
      initialized= FALSE;
unknown's avatar
unknown committed
2830
    }
2831 2832
    if (buffers)				// Because of bug in ecc
      delete [] buffers;
2833
    buffers= 0;
unknown's avatar
unknown committed
2834 2835 2836 2837 2838
  }
}


bool
2839
udf_handler::fix_fields(THD *thd, Item_result_field *func,
unknown's avatar
unknown committed
2840 2841
			uint arg_count, Item **arguments)
{
2842
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
2843
  uchar buff[STACK_BUFF_ALLOC];			// Max argument in function
2844
#endif
unknown's avatar
unknown committed
2845 2846
  DBUG_ENTER("Item_udf_func::fix_fields");

2847
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
unknown's avatar
unknown committed
2848
    DBUG_RETURN(TRUE);				// Fatal error flag is set!
unknown's avatar
unknown committed
2849

2850
  udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
unknown's avatar
unknown committed
2851 2852 2853

  if (!tmp_udf)
  {
2854
    my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
unknown's avatar
unknown committed
2855
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2856 2857 2858 2859 2860
  }
  u_d=tmp_udf;
  args=arguments;

  /* Fix all arguments */
2861
  func->maybe_null=0;
unknown's avatar
unknown committed
2862 2863 2864 2865 2866 2867 2868 2869 2870 2871
  used_tables_cache=0;
  const_item_cache=1;

  if ((f_args.arg_count=arg_count))
  {
    if (!(f_args.arg_type= (Item_result*)
	  sql_alloc(f_args.arg_count*sizeof(Item_result))))

    {
      free_udf(u_d);
unknown's avatar
unknown committed
2872
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2873 2874 2875 2876 2877 2878 2879
    }
    uint i;
    Item **arg,**arg_end;
    for (i=0, arg=arguments, arg_end=arguments+arg_count;
	 arg != arg_end ;
	 arg++,i++)
    {
unknown's avatar
unknown committed
2880
      if (!(*arg)->fixed &&
2881
          (*arg)->fix_fields(thd, arg))
unknown's avatar
unknown committed
2882
	DBUG_RETURN(1);
2883
      // we can't assign 'item' before, because fix_fields() can change arg
unknown's avatar
unknown committed
2884
      Item *item= *arg;
2885
      if (item->check_cols(1))
unknown's avatar
unknown committed
2886
	DBUG_RETURN(TRUE);
2887 2888 2889 2890 2891 2892 2893 2894 2895
      /*
	TODO: We should think about this. It is not always
	right way just to set an UDF result to return my_charset_bin
	if one argument has binary sorting order.
	The result collation should be calculated according to arguments
	derivations in some cases and should not in other cases.
	Moreover, some arguments can represent a numeric input
	which doesn't effect the result character set and collation.
	There is no a general rule for UDF. Everything depends on
unknown's avatar
unknown committed
2896
        the particular user defined function.
2897
      */
2898 2899
      if (item->collation.collation->state & MY_CS_BINSORT)
	func->collation.set(&my_charset_bin);
unknown's avatar
unknown committed
2900
      if (item->maybe_null)
unknown's avatar
unknown committed
2901
	func->maybe_null=1;
unknown's avatar
unknown committed
2902 2903 2904 2905
      func->with_sum_func= func->with_sum_func || item->with_sum_func;
      used_tables_cache|=item->used_tables();
      const_item_cache&=item->const_item();
      f_args.arg_type[i]=item->result_type();
unknown's avatar
unknown committed
2906
    }
unknown's avatar
unknown committed
2907
    //TODO: why all following memory is not allocated with 1 call of sql_alloc?
unknown's avatar
unknown committed
2908 2909
    if (!(buffers=new String[arg_count]) ||
	!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
2910 2911 2912 2913 2914 2915 2916
	!(f_args.lengths= (ulong*) sql_alloc(arg_count * sizeof(long))) ||
	!(f_args.maybe_null= (char*) sql_alloc(arg_count * sizeof(char))) ||
	!(num_buffer= (char*) sql_alloc(arg_count *
					ALIGN_SIZE(sizeof(double)))) ||
	!(f_args.attributes= (char**) sql_alloc(arg_count * sizeof(char *))) ||
	!(f_args.attribute_lengths= (ulong*) sql_alloc(arg_count *
						       sizeof(long))))
unknown's avatar
unknown committed
2917 2918
    {
      free_udf(u_d);
unknown's avatar
unknown committed
2919
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930
    }
  }
  func->fix_length_and_dec();
  initid.max_length=func->max_length;
  initid.maybe_null=func->maybe_null;
  initid.const_item=const_item_cache;
  initid.decimals=func->decimals;
  initid.ptr=0;

  if (u_d->func_init)
  {
2931
    char init_msg_buff[MYSQL_ERRMSG_SIZE];
unknown's avatar
unknown committed
2932 2933 2934
    char *to=num_buffer;
    for (uint i=0; i < arg_count; i++)
    {
2935 2936 2937 2938 2939 2940
      /*
       For a constant argument i, args->args[i] points to the argument value. 
       For non-constant, args->args[i] is NULL.
      */
      f_args.args[i]= NULL;         /* Non-const unless updated below. */

2941 2942 2943 2944
      f_args.lengths[i]= arguments[i]->max_length;
      f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
      f_args.attributes[i]= arguments[i]->name;
      f_args.attribute_lengths[i]= arguments[i]->name_length;
unknown's avatar
unknown committed
2945

2946
      if (arguments[i]->const_item())
unknown's avatar
unknown committed
2947
      {
2948 2949 2950 2951 2952 2953
        switch (arguments[i]->result_type()) 
        {
        case STRING_RESULT:
        case DECIMAL_RESULT:
        {
          String *res= arguments[i]->val_str(&buffers[i]);
2954 2955
          if (arguments[i]->null_value)
            continue;
2956 2957
          f_args.args[i]= (char*) res->c_ptr();
          f_args.lengths[i]= res->length();
2958 2959 2960 2961
          break;
        }
        case INT_RESULT:
          *((longlong*) to)= arguments[i]->val_int();
2962 2963
          if (arguments[i]->null_value)
            continue;
2964 2965 2966 2967 2968
          f_args.args[i]= to;
          to+= ALIGN_SIZE(sizeof(longlong));
          break;
        case REAL_RESULT:
          *((double*) to)= arguments[i]->val_real();
2969 2970
          if (arguments[i]->null_value)
            continue;
2971 2972 2973 2974 2975 2976 2977 2978 2979
          f_args.args[i]= to;
          to+= ALIGN_SIZE(sizeof(double));
          break;
        case ROW_RESULT:
        default:
          // This case should never be chosen
          DBUG_ASSERT(0);
          break;
        }
unknown's avatar
unknown committed
2980 2981
      }
    }
2982
    Udf_func_init init= u_d->func_init;
2983
    if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
unknown's avatar
unknown committed
2984
    {
2985
      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
2986
               u_d->name.str, init_msg_buff);
unknown's avatar
unknown committed
2987
      free_udf(u_d);
unknown's avatar
unknown committed
2988
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2989 2990 2991 2992
    }
    func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
    func->maybe_null=initid.maybe_null;
    const_item_cache=initid.const_item;
2993 2994 2995 2996 2997 2998
    /* 
      Keep used_tables_cache in sync with const_item_cache.
      See the comment in Item_udf_func::update_used tables.
    */  
    if (!const_item_cache && !used_tables_cache)
      used_tables_cache= RAND_TABLE_BIT;
2999
    func->decimals=min(initid.decimals,NOT_FIXED_DEC);
unknown's avatar
unknown committed
3000 3001 3002 3003
  }
  initialized=1;
  if (error)
  {
3004 3005
    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
             u_d->name.str, ER(ER_UNKNOWN_ERROR));
unknown's avatar
unknown committed
3006
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3007
  }
unknown's avatar
unknown committed
3008
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022
}


bool udf_handler::get_arguments()
{
  if (error)
    return 1;					// Got an error earlier
  char *to= num_buffer;
  uint str_count=0;
  for (uint i=0; i < f_args.arg_count; i++)
  {
    f_args.args[i]=0;
    switch (f_args.arg_type[i]) {
    case STRING_RESULT:
unknown's avatar
unknown committed
3023
    case DECIMAL_RESULT:
unknown's avatar
unknown committed
3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041
      {
	String *res=args[i]->val_str(&buffers[str_count++]);
	if (!(args[i]->null_value))
	{
	  f_args.args[i]=    (char*) res->ptr();
	  f_args.lengths[i]= res->length();
	  break;
	}
      }
    case INT_RESULT:
      *((longlong*) to) = args[i]->val_int();
      if (!args[i]->null_value)
      {
	f_args.args[i]=to;
	to+= ALIGN_SIZE(sizeof(longlong));
      }
      break;
    case REAL_RESULT:
3042
      *((double*) to)= args[i]->val_real();
unknown's avatar
unknown committed
3043 3044 3045 3046 3047 3048
      if (!args[i]->null_value)
      {
	f_args.args[i]=to;
	to+= ALIGN_SIZE(sizeof(double));
      }
      break;
3049
    case ROW_RESULT:
unknown's avatar
unknown committed
3050
    default:
unknown's avatar
unknown committed
3051
      // This case should never be chosen
unknown's avatar
unknown committed
3052
      DBUG_ASSERT(0);
3053
      break;
unknown's avatar
unknown committed
3054 3055 3056 3057 3058
    }
  }
  return 0;
}

unknown's avatar
unknown committed
3059 3060 3061 3062
/**
  @return
    (String*)NULL in case of NULL values
*/
unknown's avatar
unknown committed
3063 3064
String *udf_handler::val_str(String *str,String *save_str)
{
3065
  uchar is_null_tmp=0;
unknown's avatar
unknown committed
3066
  ulong res_length;
3067
  DBUG_ENTER("udf_handler::val_str");
unknown's avatar
unknown committed
3068 3069

  if (get_arguments())
3070
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3071 3072 3073 3074 3075 3076 3077 3078 3079
  char * (*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
    (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
    u_d->func;

  if ((res_length=str->alloced_length()) < MAX_FIELD_WIDTH)
  {						// This happens VERY seldom
    if (str->alloc(MAX_FIELD_WIDTH))
    {
      error=1;
3080
      DBUG_RETURN(0);
unknown's avatar
unknown committed
3081 3082
    }
  }
3083 3084
  char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
		 &is_null_tmp, &error);
3085
  DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
3086
  if (is_null_tmp || !res || error)		// The !res is for safety
unknown's avatar
unknown committed
3087
  {
3088 3089
    DBUG_PRINT("info", ("Null or error"));
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3090 3091 3092 3093
  }
  if (res == str->ptr())
  {
    str->length(res_length);
3094 3095
    DBUG_PRINT("exit", ("str: %s", str->ptr()));
    DBUG_RETURN(str);
unknown's avatar
unknown committed
3096
  }
3097
  save_str->set(res, res_length, str->charset());
3098 3099
  DBUG_PRINT("exit", ("save_str: %s", save_str->ptr()));
  DBUG_RETURN(save_str);
unknown's avatar
unknown committed
3100 3101 3102
}


3103 3104 3105 3106
/*
  For the moment, UDF functions are returning DECIMAL values as strings
*/

unknown's avatar
unknown committed
3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126
my_decimal *udf_handler::val_decimal(my_bool *null_value, my_decimal *dec_buf)
{
  char buf[DECIMAL_MAX_STR_LENGTH+1], *end;
  ulong res_length= DECIMAL_MAX_STR_LENGTH;

  if (get_arguments())
  {
    *null_value=1;
    return 0;
  }
  char *(*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
    (char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
    u_d->func;

  char *res= func(&initid, &f_args, buf, &res_length, &is_null, &error);
  if (is_null || error)
  {
    *null_value= 1;
    return 0;
  }
3127 3128
  end= res+ res_length;
  str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
unknown's avatar
unknown committed
3129 3130 3131
  return dec_buf;
}

unknown's avatar
unknown committed
3132

3133 3134 3135 3136 3137 3138
void Item_udf_func::cleanup()
{
  udf.cleanup();
  Item_func::cleanup();
}

unknown's avatar
unknown committed
3139

3140
void Item_udf_func::print(String *str, enum_query_type query_type)
3141 3142 3143 3144 3145 3146 3147
{
  str->append(func_name());
  str->append('(');
  for (uint i=0 ; i < arg_count ; i++)
  {
    if (i != 0)
      str->append(',');
3148
    args[i]->print_item_w_name(str, query_type);
3149 3150 3151 3152 3153
  }
  str->append(')');
}


3154
double Item_func_udf_float::val_real()
unknown's avatar
unknown committed
3155
{
3156
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3157 3158 3159 3160 3161 3162 3163 3164 3165
  DBUG_ENTER("Item_func_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_func_udf_float::val_str(String *str)
{
3166
  DBUG_ASSERT(fixed == 1);
3167
  double nr= val_real();
unknown's avatar
unknown committed
3168 3169
  if (null_value)
    return 0;					/* purecov: inspected */
3170
  str->set_real(nr,decimals,&my_charset_bin);
unknown's avatar
unknown committed
3171 3172 3173 3174 3175 3176
  return str;
}


longlong Item_func_udf_int::val_int()
{
3177
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3178 3179 3180 3181 3182 3183 3184
  DBUG_ENTER("Item_func_udf_int::val_int");
  DBUG_RETURN(udf.val_int(&null_value));
}


String *Item_func_udf_int::val_str(String *str)
{
3185
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3186 3187 3188
  longlong nr=val_int();
  if (null_value)
    return 0;
3189
  str->set_int(nr, unsigned_flag, &my_charset_bin);
unknown's avatar
unknown committed
3190 3191 3192
  return str;
}

unknown's avatar
unknown committed
3193 3194 3195 3196

longlong Item_func_udf_decimal::val_int()
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3197
  longlong result;
unknown's avatar
unknown committed
3198 3199 3200 3201 3202 3203 3204 3205 3206 3207
  if (null_value)
    return 0;
  my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
  return result;
}


double Item_func_udf_decimal::val_real()
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3208
  double result;
unknown's avatar
unknown committed
3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245
  if (null_value)
    return 0.0;
  my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
  return result;
}


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

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


String *Item_func_udf_decimal::val_str(String *str)
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
  if (null_value)
    return 0;
  if (str->length() < DECIMAL_MAX_STR_LENGTH)
    str->length(DECIMAL_MAX_STR_LENGTH);
  my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
  my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str);
  return str;
}


void Item_func_udf_decimal::fix_length_and_dec()
{
  fix_num_length_and_dec();
}


unknown's avatar
unknown committed
3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258
/* Default max_length is max argument length */

void Item_func_udf_str::fix_length_and_dec()
{
  DBUG_ENTER("Item_func_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;
}

String *Item_func_udf_str::val_str(String *str)
{
3259
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3260 3261 3262 3263 3264
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  return res;
}

3265

unknown's avatar
unknown committed
3266 3267 3268 3269 3270
/**
  @note
  This has to come last in the udf_handler methods, or C for AIX
  version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.)
*/
3271 3272 3273

udf_handler::~udf_handler()
{
3274 3275
  /* Everything should be properly cleaned up by this moment. */
  DBUG_ASSERT(not_original || !(initialized || buffers));
3276 3277
}

unknown's avatar
unknown committed
3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288
#else
bool udf_handler::get_arguments() { return 0; }
#endif /* HAVE_DLOPEN */

/*
** User level locks
*/

pthread_mutex_t LOCK_user_locks;
static HASH hash_user_locks;

3289
class User_level_lock
unknown's avatar
unknown committed
3290
{
3291 3292
  uchar *key;
  size_t key_length;
unknown's avatar
unknown committed
3293 3294 3295 3296 3297

public:
  int count;
  bool locked;
  pthread_cond_t cond;
unknown's avatar
unknown committed
3298 3299
  my_thread_id thread_id;
  void set_thread(THD *thd) { thread_id= thd->thread_id; }
unknown's avatar
unknown committed
3300

3301
  User_level_lock(const uchar *key_arg,uint length, ulong id) 
unknown's avatar
SCRUM  
unknown committed
3302
    :key_length(length),count(1),locked(1), thread_id(id)
unknown's avatar
unknown committed
3303
  {
3304
    key= (uchar*) my_memdup(key_arg,length,MYF(0));
unknown's avatar
unknown committed
3305 3306 3307
    pthread_cond_init(&cond,NULL);
    if (key)
    {
3308
      if (my_hash_insert(&hash_user_locks,(uchar*) this))
unknown's avatar
unknown committed
3309
      {
3310
	my_free(key,MYF(0));
unknown's avatar
unknown committed
3311 3312 3313 3314
	key=0;
      }
    }
  }
3315
  ~User_level_lock()
unknown's avatar
unknown committed
3316 3317 3318
  {
    if (key)
    {
3319 3320
      hash_delete(&hash_user_locks,(uchar*) this);
      my_free(key, MYF(0));
unknown's avatar
unknown committed
3321 3322 3323 3324
    }
    pthread_cond_destroy(&cond);
  }
  inline bool initialized() { return key != 0; }
3325
  friend void item_user_lock_release(User_level_lock *ull);
3326 3327
  friend uchar *ull_get_key(const User_level_lock *ull, size_t *length,
                            my_bool not_used);
unknown's avatar
unknown committed
3328 3329
};

3330 3331
uchar *ull_get_key(const User_level_lock *ull, size_t *length,
                   my_bool not_used __attribute__((unused)))
unknown's avatar
unknown committed
3332
{
3333 3334
  *length= ull->key_length;
  return ull->key;
unknown's avatar
unknown committed
3335 3336
}

3337 3338 3339

static bool item_user_lock_inited= 0;

unknown's avatar
unknown committed
3340 3341
void item_user_lock_init(void)
{
3342
  pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
unknown's avatar
unknown committed
3343 3344
  hash_init(&hash_user_locks,system_charset_info,
	    16,0,0,(hash_get_key) ull_get_key,NULL,0);
3345
  item_user_lock_inited= 1;
unknown's avatar
unknown committed
3346 3347 3348 3349
}

void item_user_lock_free(void)
{
3350 3351 3352 3353 3354 3355
  if (item_user_lock_inited)
  {
    item_user_lock_inited= 0;
    hash_free(&hash_user_locks);
    pthread_mutex_destroy(&LOCK_user_locks);
  }
unknown's avatar
unknown committed
3356 3357
}

3358
void item_user_lock_release(User_level_lock *ull)
unknown's avatar
unknown committed
3359 3360
{
  ull->locked=0;
3361
  ull->thread_id= 0;
unknown's avatar
unknown committed
3362 3363 3364 3365 3366 3367
  if (--ull->count)
    pthread_cond_signal(&ull->cond);
  else
    delete ull;
}

unknown's avatar
unknown committed
3368 3369 3370 3371
/**
  Wait until we are at or past the given position in the master binlog
  on the slave.
*/
unknown's avatar
unknown committed
3372 3373 3374

longlong Item_master_pos_wait::val_int()
{
3375
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3376 3377
  THD* thd = current_thd;
  String *log_name = args[0]->val_str(&value);
3378
  int event_count= 0;
unknown's avatar
unknown committed
3379

unknown's avatar
unknown committed
3380 3381 3382 3383 3384 3385
  null_value=0;
  if (thd->slave_thread || !log_name || !log_name->length())
  {
    null_value = 1;
    return 0;
  }
3386
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
3387
  longlong pos = (ulong)args[1]->val_int();
3388 3389
  longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
  if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
unknown's avatar
unknown committed
3390 3391 3392 3393
  {
    null_value = 1;
    event_count=0;
  }
3394
#endif
unknown's avatar
unknown committed
3395 3396 3397
  return event_count;
}

3398

unknown's avatar
unknown committed
3399 3400 3401 3402 3403 3404 3405 3406 3407
/**
  Get a user level lock.  If the thread has an old lock this is first released.

  @retval
    1    : Got lock
  @retval
    0    : Timeout
  @retval
    NULL : Error
unknown's avatar
unknown committed
3408 3409 3410 3411
*/

longlong Item_func_get_lock::val_int()
{
3412
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3413 3414 3415 3416
  String *res=args[0]->val_str(&value);
  longlong timeout=args[1]->val_int();
  struct timespec abstime;
  THD *thd=current_thd;
3417
  User_level_lock *ull;
unknown's avatar
unknown committed
3418
  int error;
3419
  DBUG_ENTER("Item_func_get_lock::val_int");
unknown's avatar
unknown committed
3420

3421 3422 3423 3424 3425 3426 3427 3428
  /*
    In slave thread no need to get locks, everything is serialized. Anyway
    there is no way to make GET_LOCK() work on slave like it did on master
    (i.e. make it return exactly the same value) because we don't have the
    same other concurrent threads environment. No matter what we return here,
    it's not guaranteed to be same as on master.
  */
  if (thd->slave_thread)
3429
    DBUG_RETURN(1);
3430

unknown's avatar
unknown committed
3431 3432 3433 3434 3435 3436
  pthread_mutex_lock(&LOCK_user_locks);

  if (!res || !res->length())
  {
    pthread_mutex_unlock(&LOCK_user_locks);
    null_value=1;
3437
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3438
  }
3439 3440
  DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
                      (long) thd->real_id));
unknown's avatar
unknown committed
3441 3442 3443 3444 3445 3446 3447 3448
  null_value=0;

  if (thd->ull)
  {
    item_user_lock_release(thd->ull);
    thd->ull=0;
  }

3449
  if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
3450 3451
                                              (uchar*) res->ptr(),
                                              (size_t) res->length()))))
unknown's avatar
unknown committed
3452
  {
3453 3454
    ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
                             thd->thread_id);
unknown's avatar
unknown committed
3455 3456 3457 3458 3459
    if (!ull || !ull->initialized())
    {
      delete ull;
      pthread_mutex_unlock(&LOCK_user_locks);
      null_value=1;				// Probably out of memory
3460
      DBUG_RETURN(0);
unknown's avatar
unknown committed
3461
    }
3462
    ull->set_thread(thd);
unknown's avatar
unknown committed
3463 3464
    thd->ull=ull;
    pthread_mutex_unlock(&LOCK_user_locks);
3465 3466
    DBUG_PRINT("info", ("made new lock"));
    DBUG_RETURN(1);				// Got new lock
unknown's avatar
unknown committed
3467 3468
  }
  ull->count++;
3469
  DBUG_PRINT("info", ("ull->count=%d", ull->count));
unknown's avatar
unknown committed
3470

3471 3472 3473 3474
  /*
    Structure is now initialized.  Try to get the lock.
    Set up control struct to allow others to abort locks.
  */
3475
  thd_proc_info(thd, "User lock");
unknown's avatar
unknown committed
3476 3477 3478
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

3479
  set_timespec(abstime,timeout);
unknown's avatar
unknown committed
3480 3481 3482
  error= 0;
  while (ull->locked && !thd->killed)
  {
3483
    DBUG_PRINT("info", ("waiting on lock"));
unknown's avatar
unknown committed
3484 3485
    error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime);
    if (error == ETIMEDOUT || error == ETIME)
3486 3487
    {
      DBUG_PRINT("info", ("lock wait timeout"));
unknown's avatar
unknown committed
3488
      break;
3489
    }
unknown's avatar
unknown committed
3490 3491 3492
    error= 0;
  }

unknown's avatar
unknown committed
3493 3494 3495
  if (ull->locked)
  {
    if (!--ull->count)
unknown's avatar
unknown committed
3496 3497
    {
      DBUG_ASSERT(0);
unknown's avatar
unknown committed
3498
      delete ull;				// Should never happen
unknown's avatar
unknown committed
3499 3500
    }
    if (!error)                                 // Killed (thd->killed != 0)
unknown's avatar
unknown committed
3501 3502 3503 3504 3505
    {
      error=1;
      null_value=1;				// Return NULL
    }
  }
unknown's avatar
unknown committed
3506
  else                                          // We got the lock
unknown's avatar
unknown committed
3507 3508
  {
    ull->locked=1;
3509
    ull->set_thread(thd);
3510
    ull->thread_id= thd->thread_id;
unknown's avatar
unknown committed
3511 3512
    thd->ull=ull;
    error=0;
3513
    DBUG_PRINT("info", ("got the lock"));
unknown's avatar
unknown committed
3514 3515 3516 3517
  }
  pthread_mutex_unlock(&LOCK_user_locks);

  pthread_mutex_lock(&thd->mysys_var->mutex);
3518
  thd_proc_info(thd, 0);
unknown's avatar
unknown committed
3519 3520 3521 3522
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
  pthread_mutex_unlock(&thd->mysys_var->mutex);

3523
  DBUG_RETURN(!error ? 1 : 0);
unknown's avatar
unknown committed
3524 3525 3526
}


unknown's avatar
unknown committed
3527
/**
3528
  Release a user level lock.
unknown's avatar
unknown committed
3529 3530 3531 3532
  @return
    - 1 if lock released
    - 0 if lock wasn't held
    - (SQL) NULL if no such lock
unknown's avatar
unknown committed
3533 3534 3535 3536
*/

longlong Item_func_release_lock::val_int()
{
3537
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3538
  String *res=args[0]->val_str(&value);
3539
  User_level_lock *ull;
unknown's avatar
unknown committed
3540
  longlong result;
3541 3542
  THD *thd=current_thd;
  DBUG_ENTER("Item_func_release_lock::val_int");
unknown's avatar
unknown committed
3543 3544 3545
  if (!res || !res->length())
  {
    null_value=1;
3546
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3547
  }
3548
  DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
unknown's avatar
unknown committed
3549 3550 3551 3552
  null_value=0;

  result=0;
  pthread_mutex_lock(&LOCK_user_locks);
3553
  if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
3554 3555
                                             (const uchar*) res->ptr(),
                                             (size_t) res->length()))))
unknown's avatar
unknown committed
3556 3557 3558 3559 3560
  {
    null_value=1;
  }
  else
  {
unknown's avatar
unknown committed
3561
    DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu", 
3562
                        (int) ull->locked,
unknown's avatar
unknown committed
3563 3564
                        (long)ull->thread_id,
                        (long)thd->thread_id));
unknown's avatar
unknown committed
3565
    if (ull->locked && current_thd->thread_id == ull->thread_id)
unknown's avatar
unknown committed
3566
    {
3567
      DBUG_PRINT("info", ("release lock"));
unknown's avatar
unknown committed
3568 3569
      result=1;					// Release is ok
      item_user_lock_release(ull);
3570
      thd->ull=0;
unknown's avatar
unknown committed
3571 3572 3573
    }
  }
  pthread_mutex_unlock(&LOCK_user_locks);
3574
  DBUG_RETURN(result);
unknown's avatar
unknown committed
3575 3576 3577
}


3578
longlong Item_func_last_insert_id::val_int()
unknown's avatar
unknown committed
3579
{
unknown's avatar
unknown committed
3580
  THD *thd= current_thd;
3581
  DBUG_ASSERT(fixed == 1);
3582 3583
  if (arg_count)
  {
unknown's avatar
unknown committed
3584 3585
    longlong value= args[0]->val_int();
    null_value= args[0]->null_value;
3586 3587 3588 3589 3590 3591 3592 3593 3594 3595
    /*
      LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
      documented in the manual. We don't want to touch
      first_successful_insert_id_in_cur_stmt because it would make
      LAST_INSERT_ID(X) take precedence over an generated auto_increment
      value for this row.
    */
    thd->arg_of_last_insert_id_function= TRUE;
    thd->first_successful_insert_id_in_prev_stmt= value;
    return value;
3596
  }
3597
  return thd->read_first_successful_insert_id_in_prev_stmt();
unknown's avatar
unknown committed
3598 3599
}

3600 3601 3602 3603 3604 3605 3606 3607

bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref)
{
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
  return Item_int_func::fix_fields(thd, ref);
}


unknown's avatar
unknown committed
3608 3609 3610 3611
/* This function is just used to test speed of different functions */

longlong Item_func_benchmark::val_int()
{
3612
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3613
  char buff[MAX_FIELD_WIDTH];
unknown's avatar
unknown committed
3614
  String tmp(buff,sizeof(buff), &my_charset_bin);
unknown's avatar
unknown committed
3615
  my_decimal tmp_decimal;
unknown's avatar
unknown committed
3616
  THD *thd=current_thd;
3617
  ulonglong loop_count;
unknown's avatar
unknown committed
3618

3619
  loop_count= (ulonglong) args[0]->val_int();
3620

3621 3622
  if (args[0]->null_value ||
      (!args[0]->unsigned_flag && (((longlong) loop_count) < 0)))
3623
  {
3624 3625 3626 3627 3628 3629 3630 3631 3632
    if (!args[0]->null_value)
    {
      char buff[22];
      llstr(((longlong) loop_count), buff);
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
                          ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
                          "count", buff, "benchmark");
    }

3633 3634 3635 3636 3637
    null_value= 1;
    return 0;
  }

  null_value=0;
3638
  for (ulonglong loop=0 ; loop < loop_count && !thd->killed; loop++)
unknown's avatar
unknown committed
3639
  {
3640
    switch (args[1]->result_type()) {
unknown's avatar
unknown committed
3641
    case REAL_RESULT:
3642
      (void) args[1]->val_real();
unknown's avatar
unknown committed
3643 3644
      break;
    case INT_RESULT:
3645
      (void) args[1]->val_int();
unknown's avatar
unknown committed
3646 3647
      break;
    case STRING_RESULT:
3648
      (void) args[1]->val_str(&tmp);
unknown's avatar
unknown committed
3649
      break;
unknown's avatar
unknown committed
3650 3651 3652
    case DECIMAL_RESULT:
      (void) args[1]->val_decimal(&tmp_decimal);
      break;
3653
    case ROW_RESULT:
unknown's avatar
unknown committed
3654
    default:
unknown's avatar
unknown committed
3655
      // This case should never be chosen
unknown's avatar
unknown committed
3656 3657
      DBUG_ASSERT(0);
      return 0;
unknown's avatar
unknown committed
3658 3659 3660 3661 3662
    }
  }
  return 0;
}

3663

3664
void Item_func_benchmark::print(String *str, enum_query_type query_type)
3665
{
3666
  str->append(STRING_WITH_LEN("benchmark("));
3667
  args[0]->print(str, query_type);
3668
  str->append(',');
3669
  args[1]->print(str, query_type);
3670 3671 3672
  str->append(')');
}

unknown's avatar
unknown committed
3673

unknown's avatar
unknown committed
3674
/** This function is just used to create tests with time gaps. */
3675 3676 3677

longlong Item_func_sleep::val_int()
{
3678 3679 3680
  THD *thd= current_thd;
  struct timespec abstime;
  pthread_cond_t cond;
3681
  int error;
3682

3683
  DBUG_ASSERT(fixed == 1);
3684

3685
  double time= args[0]->val_real();
3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697
  /*
    On 64-bit OSX pthread_cond_timedwait() waits forever
    if passed abstime time has already been exceeded by 
    the system time.
    When given a very short timeout (< 10 mcs) just return 
    immediately.
    We assume that the lines between this test and the call 
    to pthread_cond_timedwait() will be executed in less than 0.00001 sec.
  */
  if (time < 0.00001)
    return 0;
    
3698 3699 3700 3701 3702
  set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000)));

  pthread_cond_init(&cond, NULL);
  pthread_mutex_lock(&LOCK_user_locks);

3703
  thd_proc_info(thd, "User sleep");
3704 3705 3706
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &cond;

unknown's avatar
unknown committed
3707 3708 3709 3710 3711 3712 3713 3714
  error= 0;
  while (!thd->killed)
  {
    error= pthread_cond_timedwait(&cond, &LOCK_user_locks, &abstime);
    if (error == ETIMEDOUT || error == ETIME)
      break;
    error= 0;
  }
3715
  thd_proc_info(thd, 0);
3716
  pthread_mutex_unlock(&LOCK_user_locks);
3717 3718 3719 3720 3721 3722 3723
  pthread_mutex_lock(&thd->mysys_var->mutex);
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
  pthread_mutex_unlock(&thd->mysys_var->mutex);

  pthread_cond_destroy(&cond);

unknown's avatar
unknown committed
3724
  return test(!error); 		// Return 1 killed
3725 3726 3727
}


unknown's avatar
unknown committed
3728 3729 3730 3731 3732 3733 3734
#define extra_size sizeof(double)

static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
				    bool create_if_not_exists)
{
  user_var_entry *entry;

3735
  if (!(entry = (user_var_entry*) hash_search(hash, (uchar*) name.str,
unknown's avatar
unknown committed
3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748
					      name.length)) &&
      create_if_not_exists)
  {
    uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
    if (!hash_inited(hash))
      return 0;
    if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
      return 0;
    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
      extra_size;
    entry->name.length=name.length;
    entry->value=0;
    entry->length=0;
3749
    entry->update_query_id=0;
3750
    entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
3751
    entry->unsigned_flag= 0;
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761
    /*
      If we are here, we were called from a SET or a query which sets a
      variable. Imagine it is this:
      INSERT INTO t SELECT @a:=10, @a:=@a+1.
      Then when we have a Item_func_get_user_var (because of the @a+1) so we
      think we have to write the value of @a to the binlog. But before that,
      we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
      the variable as "already logged" (line below) so that it won't be logged
      by Item_func_get_user_var (because that's not necessary).
    */
unknown's avatar
unknown committed
3762
    entry->used_query_id=current_thd->query_id;
unknown's avatar
unknown committed
3763 3764
    entry->type=STRING_RESULT;
    memcpy(entry->name.str, name.str, name.length+1);
3765
    if (my_hash_insert(hash,(uchar*) entry))
unknown's avatar
unknown committed
3766 3767 3768 3769 3770 3771 3772 3773
    {
      my_free((char*) entry,MYF(0));
      return 0;
    }
  }
  return entry;
}

3774

3775 3776 3777 3778 3779 3780 3781
void Item_func_set_user_var::cleanup()
{
  Item_func::cleanup();
  entry= NULL;
}


3782 3783
bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
{
3784
  if (entry && thd->thread_id == entry_thread_id)
3785
    goto end; // update entry->update_query_id for PS
3786
  if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
3787 3788
  {
    entry_thread_id= 0;
3789
    return TRUE;
3790 3791
  }
  entry_thread_id= thd->thread_id;
3792 3793 3794 3795 3796
  /* 
     Remember the last query which updated it, this way a query can later know
     if this variable is a constant item in the query (it is if update_query_id
     is different from query_id).
  */
3797
end:
3798 3799 3800 3801 3802
  entry->update_query_id= thd->query_id;
  return FALSE;
}


3803
/*
3804 3805
  When a user variable is updated (in a SET command or a query like
  SELECT @a:= ).
3806
*/
3807

3808
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
3809
{
3810
  DBUG_ASSERT(fixed == 0);
3811
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
3812
  if (Item_func::fix_fields(thd, ref) || set_entry(thd, TRUE))
unknown's avatar
unknown committed
3813
    return TRUE;
3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828
  /*
    As it is wrong and confusing to associate any 
    character set with NULL, @a should be latin2
    after this query sequence:

      SET @a=_latin2'string';
      SET @a=NULL;

    I.e. the second query should not change the charset
    to the current default value, but should keep the 
    original value assigned during the first query.
    In order to do it, we don't copy charset
    from the argument if the argument is NULL
    and the variable has previously been initialized.
  */
3829 3830
  null_item= (args[0]->type() == NULL_ITEM);
  if (!entry->collation.collation || !null_item)
3831 3832
    entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
3833
  cached_result_type= args[0]->result_type();
unknown's avatar
unknown committed
3834
  return FALSE;
unknown's avatar
unknown committed
3835 3836 3837 3838 3839 3840 3841 3842 3843
}


void
Item_func_set_user_var::fix_length_and_dec()
{
  maybe_null=args[0]->maybe_null;
  max_length=args[0]->max_length;
  decimals=args[0]->decimals;
3844
  collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
unknown's avatar
unknown committed
3845 3846
}

3847

unknown's avatar
unknown committed
3848 3849 3850 3851 3852 3853 3854 3855 3856 3857
/*
  Mark field in read_map

  NOTES
    This is used by filesort to register used fields in a a temporary
    column read set or to register used fields in a view
*/

bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
{
3858 3859 3860 3861 3862 3863
  if (result_field)
  {
    TABLE *table= (TABLE *) arg;
    if (result_field->table == table || !table)
      bitmap_set_bit(result_field->table->read_set, result_field->field_index);
  }
unknown's avatar
unknown committed
3864 3865 3866 3867
  return 0;
}


unknown's avatar
unknown committed
3868
/**
unknown's avatar
unknown committed
3869 3870
  Set value to user variable.

unknown's avatar
unknown committed
3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883
  @param entry          pointer to structure representing variable
  @param set_null       should we set NULL value ?
  @param ptr            pointer to buffer with new value
  @param length         length of new value
  @param type           type of new value
  @param cs             charset info for new value
  @param dv             derivation for new value
  @param unsigned_arg   indiates if a value of type INT_RESULT is unsigned

  @retval
    false   success
  @retval
    true    failure
unknown's avatar
unknown committed
3884 3885 3886 3887
*/

static bool
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
3888 3889
            Item_result type, CHARSET_INFO *cs, Derivation dv,
            bool unsigned_arg)
unknown's avatar
unknown committed
3890
{
unknown's avatar
unknown committed
3891
  if (set_null)
unknown's avatar
unknown committed
3892 3893 3894 3895
  {
    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
    if (entry->value && entry->value != pos)
      my_free(entry->value,MYF(0));
3896 3897
    entry->value= 0;
    entry->length= 0;
unknown's avatar
unknown committed
3898 3899 3900
  }
  else
  {
3901 3902
    if (type == STRING_RESULT)
      length++;					// Store strings with end \0
unknown's avatar
unknown committed
3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921
    if (length <= extra_size)
    {
      /* Save value in value struct */
      char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
      if (entry->value != pos)
      {
	if (entry->value)
	  my_free(entry->value,MYF(0));
	entry->value=pos;
      }
    }
    else
    {
      /* Allocate variable */
      if (entry->length != length)
      {
	char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
	if (entry->value == pos)
	  entry->value=0;
3922 3923 3924
        entry->value= (char*) my_realloc(entry->value, length,
                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME));
        if (!entry->value)
unknown's avatar
unknown committed
3925
	  return 1;
unknown's avatar
unknown committed
3926 3927
      }
    }
3928 3929 3930 3931 3932
    if (type == STRING_RESULT)
    {
      length--;					// Fix length change above
      entry->value[length]= 0;			// Store end \0
    }
unknown's avatar
unknown committed
3933
    memcpy(entry->value,ptr,length);
unknown's avatar
unknown committed
3934 3935
    if (type == DECIMAL_RESULT)
      ((my_decimal*)entry->value)->fix_buffer_pointer();
unknown's avatar
unknown committed
3936
    entry->length= length;
3937
    entry->collation.set(cs, dv);
unknown's avatar
unknown committed
3938
    entry->unsigned_flag= unsigned_arg;
unknown's avatar
unknown committed
3939
  }
3940
  entry->type=type;
3941
  return 0;
unknown's avatar
unknown committed
3942
}
unknown's avatar
unknown committed
3943

unknown's avatar
unknown committed
3944 3945

bool
3946 3947
Item_func_set_user_var::update_hash(void *ptr, uint length,
                                    Item_result res_type,
3948 3949
                                    CHARSET_INFO *cs, Derivation dv,
                                    bool unsigned_arg)
unknown's avatar
unknown committed
3950
{
3951 3952 3953 3954 3955
  /*
    If we set a variable explicitely to NULL then keep the old
    result type of the variable
  */
  if ((null_value= args[0]->null_value) && null_item)
3956
    res_type= entry->type;                      // Don't change type of item
unknown's avatar
unknown committed
3957
  if (::update_hash(entry, (null_value= args[0]->null_value),
3958
                    ptr, length, res_type, cs, dv, unsigned_arg))
unknown's avatar
unknown committed
3959 3960 3961 3962 3963 3964
  {
    current_thd->fatal_error();     // Probably end of memory
    null_value= 1;
    return 1;
  }
  return 0;
unknown's avatar
unknown committed
3965 3966 3967
}


unknown's avatar
unknown committed
3968
/** Get the value of a variable as a double. */
3969

unknown's avatar
unknown committed
3970
double user_var_entry::val_real(my_bool *null_value)
unknown's avatar
unknown committed
3971
{
3972 3973 3974 3975 3976 3977 3978 3979
  if ((*null_value= (value == 0)))
    return 0.0;

  switch (type) {
  case REAL_RESULT:
    return *(double*) value;
  case INT_RESULT:
    return (double) *(longlong*) value;
unknown's avatar
unknown committed
3980 3981 3982 3983 3984 3985
  case DECIMAL_RESULT:
  {
    double result;
    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
    return result;
  }
3986
  case STRING_RESULT:
unknown's avatar
unknown committed
3987
    return my_atof(value);                      // This is null terminated
3988
  case ROW_RESULT:
3989 3990
  case IMPOSSIBLE_RESULT:
    DBUG_ASSERT(0);				// Impossible
3991
    break;
unknown's avatar
unknown committed
3992
  }
3993
  return 0.0;					// Impossible
unknown's avatar
unknown committed
3994 3995 3996
}


unknown's avatar
unknown committed
3997
/** Get the value of a variable as an integer. */
3998

3999
longlong user_var_entry::val_int(my_bool *null_value) const
unknown's avatar
unknown committed
4000
{
4001 4002 4003 4004 4005 4006 4007 4008
  if ((*null_value= (value == 0)))
    return LL(0);

  switch (type) {
  case REAL_RESULT:
    return (longlong) *(double*) value;
  case INT_RESULT:
    return *(longlong*) value;
unknown's avatar
unknown committed
4009 4010 4011
  case DECIMAL_RESULT:
  {
    longlong result;
4012
    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
unknown's avatar
unknown committed
4013 4014
    return result;
  }
unknown's avatar
unknown committed
4015
  case STRING_RESULT:
unknown's avatar
unknown committed
4016 4017 4018 4019
  {
    int error;
    return my_strtoll10(value, (char**) 0, &error);// String is null terminated
  }
4020
  case ROW_RESULT:
4021 4022
  case IMPOSSIBLE_RESULT:
    DBUG_ASSERT(0);				// Impossible
4023
    break;
unknown's avatar
unknown committed
4024
  }
4025 4026 4027 4028
  return LL(0);					// Impossible
}


unknown's avatar
unknown committed
4029
/** Get the value of a variable as a string. */
4030 4031 4032 4033 4034 4035 4036 4037 4038

String *user_var_entry::val_str(my_bool *null_value, String *str,
				uint decimals)
{
  if ((*null_value= (value == 0)))
    return (String*) 0;

  switch (type) {
  case REAL_RESULT:
4039
    str->set_real(*(double*) value, decimals, &my_charset_bin);
4040 4041
    break;
  case INT_RESULT:
4042 4043 4044 4045
    if (!unsigned_flag)
      str->set(*(longlong*) value, &my_charset_bin);
    else
      str->set(*(ulonglong*) value, &my_charset_bin);
4046
    break;
unknown's avatar
unknown committed
4047 4048 4049
  case DECIMAL_RESULT:
    my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
    break;
4050
  case STRING_RESULT:
unknown's avatar
unknown committed
4051
    if (str->copy(value, length, collation.collation))
4052
      str= 0;					// EOM error
4053
    break;
4054
  case ROW_RESULT:
4055 4056
  case IMPOSSIBLE_RESULT:
    DBUG_ASSERT(0);				// Impossible
4057
    break;
unknown's avatar
unknown committed
4058
  }
4059
  return(str);
unknown's avatar
unknown committed
4060 4061
}

unknown's avatar
unknown committed
4062
/** Get the value of a variable as a decimal. */
unknown's avatar
unknown committed
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082

my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
{
  if ((*null_value= (value == 0)))
    return 0;

  switch (type) {
  case REAL_RESULT:
    double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
    break;
  case INT_RESULT:
    int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
    break;
  case DECIMAL_RESULT:
    val= (my_decimal *)value;
    break;
  case STRING_RESULT:
    str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
    break;
  case ROW_RESULT:
4083 4084
  case IMPOSSIBLE_RESULT:
    DBUG_ASSERT(0);				// Impossible
unknown's avatar
unknown committed
4085 4086 4087 4088 4089
    break;
  }
  return(val);
}

unknown's avatar
unknown committed
4090 4091 4092
/**
  This functions is invoked on SET \@variable or
  \@variable:= expression.
4093

unknown's avatar
unknown committed
4094
  Evaluate (and check expression), store results.
4095

unknown's avatar
unknown committed
4096
  @note
unknown's avatar
unknown committed
4097
    For now it always return OK. All problem with value evaluating
4098
    will be caught by thd->is_error() check in sql_set_variables().
4099

unknown's avatar
unknown committed
4100
  @retval
unknown's avatar
unknown committed
4101
    FALSE OK.
4102 4103 4104
*/

bool
4105
Item_func_set_user_var::check(bool use_result_field)
4106 4107
{
  DBUG_ENTER("Item_func_set_user_var::check");
unknown's avatar
unknown committed
4108 4109
  if (use_result_field && !result_field)
    use_result_field= FALSE;
4110 4111 4112 4113

  switch (cached_result_type) {
  case REAL_RESULT:
  {
4114 4115
    save_result.vreal= use_result_field ? result_field->val_real() :
                        args[0]->val_real();
4116 4117 4118 4119
    break;
  }
  case INT_RESULT:
  {
4120 4121 4122 4123
    save_result.vint= use_result_field ? result_field->val_int() :
                       args[0]->val_int();
    unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
                    args[0]->unsigned_flag;
4124 4125 4126 4127
    break;
  }
  case STRING_RESULT:
  {
4128 4129
    save_result.vstr= use_result_field ? result_field->val_str(&value) :
                       args[0]->val_str(&value);
4130 4131
    break;
  }
unknown's avatar
unknown committed
4132 4133
  case DECIMAL_RESULT:
  {
4134 4135 4136
    save_result.vdec= use_result_field ?
                       result_field->val_decimal(&decimal_buff) :
                       args[0]->val_decimal(&decimal_buff);
unknown's avatar
unknown committed
4137 4138
    break;
  }
4139 4140
  case ROW_RESULT:
  default:
unknown's avatar
unknown committed
4141
    // This case should never be chosen
4142 4143 4144
    DBUG_ASSERT(0);
    break;
  }
unknown's avatar
unknown committed
4145
  DBUG_RETURN(FALSE);
4146 4147
}

4148

4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183
/**
  @brief Evaluate and store item's result.
  This function is invoked on "SELECT ... INTO @var ...".
  
  @param    item    An item to get value from.
*/

void Item_func_set_user_var::save_item_result(Item *item)
{
  DBUG_ENTER("Item_func_set_user_var::save_item_result");

  switch (cached_result_type) {
  case REAL_RESULT:
    save_result.vreal= item->val_result();
    break;
  case INT_RESULT:
    save_result.vint= item->val_int_result();
    unsigned_flag= item->unsigned_flag;
    break;
  case STRING_RESULT:
    save_result.vstr= item->str_result(&value);
    break;
  case DECIMAL_RESULT:
    save_result.vdec= item->val_decimal_result(&decimal_buff);
    break;
  case ROW_RESULT:
  default:
    // Should never happen
    DBUG_ASSERT(0);
    break;
  }
  DBUG_VOID_RETURN;
}


unknown's avatar
unknown committed
4184 4185 4186
/**
  This functions is invoked on
  SET \@variable or \@variable:= expression.
4187

unknown's avatar
unknown committed
4188
  @note
4189 4190 4191
    We have to store the expression as such in the variable, independent of
    the value method used by the user

unknown's avatar
unknown committed
4192
  @retval
unknown's avatar
unknown committed
4193
    0	OK
unknown's avatar
unknown committed
4194
  @retval
4195 4196 4197 4198
    1	EOM Error

*/

unknown's avatar
unknown committed
4199 4200 4201
bool
Item_func_set_user_var::update()
{
Georgi Kodinov's avatar
Georgi Kodinov committed
4202
  bool res= 0;
4203 4204
  DBUG_ENTER("Item_func_set_user_var::update");

unknown's avatar
unknown committed
4205 4206
  switch (cached_result_type) {
  case REAL_RESULT:
unknown's avatar
unknown committed
4207
  {
4208
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
unknown's avatar
unknown committed
4209
		     REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4210
    break;
unknown's avatar
unknown committed
4211
  }
unknown's avatar
unknown committed
4212
  case INT_RESULT:
4213
  {
4214
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
4215
                     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT,
4216
                     unsigned_flag);
unknown's avatar
unknown committed
4217
    break;
unknown's avatar
unknown committed
4218
  }
unknown's avatar
unknown committed
4219
  case STRING_RESULT:
unknown's avatar
unknown committed
4220
  {
4221
    if (!save_result.vstr)					// Null value
unknown's avatar
unknown committed
4222
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
unknown's avatar
unknown committed
4223
		       DERIVATION_IMPLICIT, 0);
4224
    else
4225 4226 4227
      res= update_hash((void*) save_result.vstr->ptr(),
		       save_result.vstr->length(), STRING_RESULT,
		       save_result.vstr->charset(),
unknown's avatar
unknown committed
4228
		       DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4229 4230
    break;
  }
unknown's avatar
unknown committed
4231 4232 4233 4234
  case DECIMAL_RESULT:
  {
    if (!save_result.vdec)					// Null value
      res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
unknown's avatar
unknown committed
4235
                       DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4236 4237 4238
    else
      res= update_hash((void*) save_result.vdec,
                       sizeof(my_decimal), DECIMAL_RESULT,
unknown's avatar
unknown committed
4239
                       &my_charset_bin, DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4240 4241
    break;
  }
4242
  case ROW_RESULT:
unknown's avatar
unknown committed
4243
  default:
unknown's avatar
unknown committed
4244
    // This case should never be chosen
unknown's avatar
unknown committed
4245 4246 4247
    DBUG_ASSERT(0);
    break;
  }
4248
  DBUG_RETURN(res);
unknown's avatar
unknown committed
4249 4250 4251
}


4252
double Item_func_set_user_var::val_real()
unknown's avatar
unknown committed
4253
{
4254
  DBUG_ASSERT(fixed == 1);
4255
  check(0);
4256
  update();					// Store expression
unknown's avatar
unknown committed
4257
  return entry->val_real(&null_value);
unknown's avatar
unknown committed
4258 4259
}

4260
longlong Item_func_set_user_var::val_int()
unknown's avatar
unknown committed
4261
{
4262
  DBUG_ASSERT(fixed == 1);
4263
  check(0);
4264 4265
  update();					// Store expression
  return entry->val_int(&null_value);
unknown's avatar
unknown committed
4266 4267
}

4268
String *Item_func_set_user_var::val_str(String *str)
unknown's avatar
unknown committed
4269
{
4270
  DBUG_ASSERT(fixed == 1);
4271
  check(0);
4272 4273
  update();					// Store expression
  return entry->val_str(&null_value, str, decimals);
unknown's avatar
unknown committed
4274 4275 4276
}


unknown's avatar
unknown committed
4277 4278 4279
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
{
  DBUG_ASSERT(fixed == 1);
4280
  check(0);
unknown's avatar
unknown committed
4281 4282 4283 4284 4285
  update();					// Store expression
  return entry->val_decimal(&null_value, val);
}


unknown's avatar
unknown committed
4286
double Item_func_set_user_var::val_result()
4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return entry->val_real(&null_value);
}

longlong Item_func_set_user_var::val_int_result()
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return entry->val_int(&null_value);
}

Georgi Kodinov's avatar
Georgi Kodinov committed
4302 4303 4304 4305 4306 4307 4308 4309
bool Item_func_set_user_var::val_bool_result()
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return entry->val_int(&null_value) != 0;
}

unknown's avatar
unknown committed
4310
String *Item_func_set_user_var::str_result(String *str)
4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return entry->val_str(&null_value, str, decimals);
}


my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return entry->val_decimal(&null_value, val);
unknown's avatar
unknown committed
4325 4326 4327
}


4328 4329 4330 4331 4332 4333 4334 4335 4336
bool Item_func_set_user_var::is_null_result()
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return is_null();
}


4337
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
4338
{
4339
  str->append(STRING_WITH_LEN("(@"));
4340
  str->append(name.str, name.length);
4341
  str->append(STRING_WITH_LEN(":="));
4342
  args[0]->print(str, query_type);
unknown's avatar
unknown committed
4343 4344 4345 4346
  str->append(')');
}


4347 4348
void Item_func_set_user_var::print_as_stmt(String *str,
                                           enum_query_type query_type)
4349
{
4350
  str->append(STRING_WITH_LEN("set @"));
4351
  str->append(name.str, name.length);
4352
  str->append(STRING_WITH_LEN(":="));
4353
  args[0]->print(str, query_type);
4354 4355 4356
  str->append(')');
}

4357 4358 4359 4360 4361 4362 4363 4364 4365 4366
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
{
  if (result_field)
  {
    check(1);
    update();
    return protocol->store(result_field);
  }
  return Item::send(protocol, str_arg);
}
4367

unknown's avatar
unknown committed
4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379
void Item_func_set_user_var::make_field(Send_field *tmp_field)
{
  if (result_field)
  {
    result_field->make_field(tmp_field);
    DBUG_ASSERT(tmp_field->table_name != 0);
    if (Item::name)
      tmp_field->col_name=Item::name;               // Use user supplied name
  }
  else
    Item::make_field(tmp_field);
}
4380

4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419

/*
  Save the value of a user variable into a field

  SYNOPSIS
    save_in_field()
      field           target field to save the value to
      no_conversion   flag indicating whether conversions are allowed

  DESCRIPTION
    Save the function value into a field and update the user variable
    accordingly. If a result field is defined and the target field doesn't
    coincide with it then the value from the result field will be used as
    the new value of the user variable.

    The reason to have this method rather than simply using the result
    field in the val_xxx() methods is that the value from the result field
    not always can be used when the result field is defined.
    Let's consider the following cases:
    1) when filling a tmp table the result field is defined but the value of it
    is undefined because it has to be produced yet. Thus we can't use it.
    2) on execution of an INSERT ... SELECT statement the save_in_field()
    function will be called to fill the data in the new record. If the SELECT
    part uses a tmp table then the result field is defined and should be
    used in order to get the correct result.

    The difference between the SET_USER_VAR function and regular functions
    like CONCAT is that the Item_func objects for the regular functions are
    replaced by Item_field objects after the values of these functions have
    been stored in a tmp table. Yet an object of the Item_field class cannot
    be used to update a user variable.
    Due to this we have to handle the result field in a special way here and
    in the Item_func_set_user_var::send() function.

  RETURN VALUES
    FALSE       Ok
    TRUE        Error
*/

4420 4421
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
                                          bool can_use_result_field)
4422
{
4423 4424
  bool use_result_field= (!can_use_result_field ? 0 :
                          (result_field && result_field != field));
4425 4426 4427 4428 4429 4430 4431
  int error;

  /* Update the value of the user variable */
  check(use_result_field);
  update();

  if (result_type() == STRING_RESULT ||
4432 4433
      (result_type() == REAL_RESULT &&
       field->result_type() == STRING_RESULT))
4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463
  {
    String *result;
    CHARSET_INFO *cs= collation.collation;
    char buff[MAX_FIELD_WIDTH];		// Alloc buffer for small columns
    str_value.set_quick(buff, sizeof(buff), cs);
    result= entry->val_str(&null_value, &str_value, decimals);

    if (null_value)
    {
      str_value.set_quick(0, 0, cs);
      return set_field_to_null_with_conversions(field, no_conversions);
    }

    /* NOTE: If null_value == FALSE, "result" must be not NULL.  */

    field->set_notnull();
    error=field->store(result->ptr(),result->length(),cs);
    str_value.set_quick(0, 0, cs);
  }
  else if (result_type() == REAL_RESULT)
  {
    double nr= entry->val_real(&null_value);
    if (null_value)
      return set_field_to_null(field);
    field->set_notnull();
    error=field->store(nr);
  }
  else if (result_type() == DECIMAL_RESULT)
  {
    my_decimal decimal_value;
4464
    my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
4465 4466 4467
    if (null_value)
      return set_field_to_null(field);
    field->set_notnull();
4468
    error=field->store_decimal(val);
4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481
  }
  else
  {
    longlong nr= entry->val_int(&null_value);
    if (null_value)
      return set_field_to_null_with_conversions(field, no_conversions);
    field->set_notnull();
    error=field->store(nr, unsigned_flag);
  }
  return error;
}


unknown's avatar
unknown committed
4482 4483 4484
String *
Item_func_get_user_var::val_str(String *str)
{
4485
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
4486
  DBUG_ENTER("Item_func_get_user_var::val_str");
4487
  if (!var_entry)
4488
    DBUG_RETURN((String*) 0);			// No such variable
4489
  DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
unknown's avatar
unknown committed
4490 4491 4492
}


4493
double Item_func_get_user_var::val_real()
unknown's avatar
unknown committed
4494
{
4495
  DBUG_ASSERT(fixed == 1);
4496 4497
  if (!var_entry)
    return 0.0;					// No such variable
unknown's avatar
unknown committed
4498 4499 4500 4501 4502 4503 4504 4505 4506 4507
  return (var_entry->val_real(&null_value));
}


my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
{
  DBUG_ASSERT(fixed == 1);
  if (!var_entry)
    return 0;
  return var_entry->val_decimal(&null_value, dec);
unknown's avatar
unknown committed
4508 4509 4510 4511 4512
}


longlong Item_func_get_user_var::val_int()
{
4513
  DBUG_ASSERT(fixed == 1);
4514 4515 4516
  if (!var_entry)
    return LL(0);				// No such variable
  return (var_entry->val_int(&null_value));
unknown's avatar
unknown committed
4517 4518 4519
}


unknown's avatar
unknown committed
4520
/**
4521 4522 4523
  Get variable by name and, if necessary, put the record of variable 
  use into the binary log.

4524 4525 4526 4527
  When a user variable is invoked from an update query (INSERT, UPDATE etc),
  stores this variable and its value in thd->user_var_events, so that it can be
  written to the binlog (will be written just before the query is written, see
  log.cc).
4528

unknown's avatar
unknown committed
4529 4530 4531 4532 4533 4534
  @param      thd        Current thread
  @param      name       Variable name
  @param[out] out_entry  variable structure or NULL. The pointer is set
                         regardless of whether function succeeded or not.

  @retval
4535
    0  OK
unknown's avatar
unknown committed
4536
  @retval
unknown's avatar
unknown committed
4537
    1  Failed to put appropriate record into binary log
4538

4539 4540
*/

4541 4542
int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
                        LEX_STRING &name, user_var_entry **out_entry)
unknown's avatar
unknown committed
4543
{
4544
  BINLOG_USER_VAR_EVENT *user_var_event;
4545 4546
  user_var_entry *var_entry;
  var_entry= get_variable(&thd->user_vars, name, 0);
4547

4548 4549
  /*
    Any reference to user-defined variable which is done from stored
4550 4551 4552
    function or trigger affects their execution and the execution of the
    calling statement. We must log all such variables even if they are 
    not involved in table-updating statements.
4553 4554 4555
  */
  if (!(opt_bin_log && 
       (is_update_query(sql_command) || thd->in_sub_stmt)))
4556 4557 4558 4559
  {
    *out_entry= var_entry;
    return 0;
  }
4560 4561

  if (!var_entry)
unknown's avatar
unknown committed
4562
  {
4563
    /*
4564 4565 4566 4567
      If the variable does not exist, it's NULL, but we want to create it so
      that it gets into the binlog (if it didn't, the slave could be
      influenced by a variable of the same name previously set by another
      thread).
unknown's avatar
unknown committed
4568 4569
      We create it like if it had been explicitly set with SET before.
      The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
4570 4571 4572
      sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
      in dispatch_command()). Instead of building a one-element list to pass to
      sql_set_variables(), we could instead manually call check() and update();
4573 4574
      this would save memory and time; but calling sql_set_variables() makes
      one unique place to maintain (sql_set_variables()). 
4575 4576 4577

      Manipulation with lex is necessary since free_underlaid_joins
      is going to release memory belonging to the main query.
4578 4579 4580
    */

    List<set_var_base> tmp_var_list;
4581 4582
    LEX *sav_lex= thd->lex, lex_tmp;
    thd->lex= &lex_tmp;
4583
    lex_start(thd);
4584 4585
    tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
                                                                       new Item_null())));
4586 4587
    /* Create the variable */
    if (sql_set_variables(thd, &tmp_var_list))
4588 4589
    {
      thd->lex= sav_lex;
4590
      goto err;
4591 4592
    }
    thd->lex= sav_lex;
4593 4594 4595
    if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
      goto err;
  }
4596 4597
  else if (var_entry->used_query_id == thd->query_id ||
           mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
4598 4599 4600 4601 4602 4603 4604 4605 4606
  {
    /* 
       If this variable was already stored in user_var_events by this query
       (because it's used in more than one place in the query), don't store
       it.
    */
    *out_entry= var_entry;
    return 0;
  }
4607 4608 4609 4610

  uint size;
  /*
    First we need to store value of var_entry, when the next situation
unknown's avatar
unknown committed
4611
    appears:
4612 4613
    > set @a:=1;
    > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
4614
    We have to write to binlog value @a= 1.
4615

4616 4617 4618 4619
    We allocate the user_var_event on user_var_events_alloc pool, not on
    the this-statement-execution pool because in SPs user_var_event objects 
    may need to be valid after current [SP] statement execution pool is
    destroyed.
4620
  */
4621 4622 4623
  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
  if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
        alloc_root(thd->user_var_events_alloc, size)))
4624
    goto err;
4625

4626 4627 4628 4629 4630 4631 4632 4633 4634 4635
  user_var_event->value= (char*) user_var_event +
    ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
  user_var_event->user_var_event= var_entry;
  user_var_event->type= var_entry->type;
  user_var_event->charset_number= var_entry->collation.collation->number;
  if (!var_entry->value)
  {
    /* NULL value*/
    user_var_event->length= 0;
    user_var_event->value= 0;
unknown's avatar
unknown committed
4636
  }
4637 4638 4639 4640 4641 4642 4643 4644
  else
  {
    user_var_event->length= var_entry->length;
    memcpy(user_var_event->value, var_entry->value,
           var_entry->length);
  }
  /* Mark that this variable has been used by this query */
  var_entry->used_query_id= thd->query_id;
4645
  if (insert_dynamic(&thd->user_var_events, (uchar*) &user_var_event))
4646
    goto err;
4647

4648 4649
  *out_entry= var_entry;
  return 0;
4650

unknown's avatar
unknown committed
4651
err:
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662
  *out_entry= var_entry;
  return 1;
}

void Item_func_get_user_var::fix_length_and_dec()
{
  THD *thd=current_thd;
  int error;
  maybe_null=1;
  decimals=NOT_FIXED_DEC;
  max_length=MAX_BLOB_WIDTH;
4663

4664
  error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
4665

4666 4667 4668 4669 4670
  /*
    If the variable didn't exist it has been created as a STRING-type.
    'var_entry' is NULL only if there occured an error during the call to
    get_var_with_binlog.
  */
4671
  if (var_entry)
4672
  {
4673 4674 4675 4676
    m_cached_result_type= var_entry->type;
    unsigned_flag= var_entry->unsigned_flag;
    max_length= var_entry->length;

4677
    collation.set(var_entry->collation);
4678
    switch(m_cached_result_type) {
4679 4680
    case REAL_RESULT:
      max_length= DBL_DIG + 8;
unknown's avatar
unknown committed
4681
      break;
4682 4683
    case INT_RESULT:
      max_length= MAX_BIGINT_WIDTH;
unknown's avatar
unknown committed
4684
      decimals=0;
4685 4686
      break;
    case STRING_RESULT:
4687
      max_length= MAX_BLOB_WIDTH - 1;
4688
      break;
unknown's avatar
unknown committed
4689
    case DECIMAL_RESULT:
unknown's avatar
unknown committed
4690 4691
      max_length= DECIMAL_MAX_STR_LENGTH;
      decimals= DECIMAL_MAX_SCALE;
unknown's avatar
unknown committed
4692
      break;
unknown's avatar
unknown committed
4693
    case ROW_RESULT:                            // Keep compiler happy
unknown's avatar
unknown committed
4694 4695
    default:
      DBUG_ASSERT(0);
unknown's avatar
unknown committed
4696
      break;
4697 4698
    }
  }
4699
  else
4700 4701
  {
    collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
4702
    null_value= 1;
4703 4704
    m_cached_result_type= STRING_RESULT;
    max_length= MAX_BLOB_WIDTH;
4705
  }
4706

4707 4708
  if (error)
    thd->fatal_error();
4709

unknown's avatar
unknown committed
4710
  return;
unknown's avatar
unknown committed
4711 4712 4713
}


4714
bool Item_func_get_user_var::const_item() const
4715
{
4716
  return (!var_entry || current_thd->query_id != var_entry->update_query_id);
4717
}
unknown's avatar
unknown committed
4718 4719 4720 4721


enum Item_result Item_func_get_user_var::result_type() const
{
4722
  return m_cached_result_type;
unknown's avatar
unknown committed
4723 4724
}

unknown's avatar
unknown committed
4725

4726
void Item_func_get_user_var::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
4727
{
4728
  str->append(STRING_WITH_LEN("(@"));
unknown's avatar
unknown committed
4729 4730 4731 4732
  str->append(name.str,name.length);
  str->append(')');
}

4733

4734
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
unknown's avatar
unknown committed
4735 4736 4737 4738 4739 4740
{
  /* Assume we don't have rtti */
  if (this == item)
    return 1;					// Same item is same.
  /* Check if other type is also a get_user_var() object */
  if (item->type() != FUNC_ITEM ||
4741
      ((Item_func*) item)->functype() != functype())
unknown's avatar
unknown committed
4742 4743 4744 4745 4746 4747 4748
    return 0;
  Item_func_get_user_var *other=(Item_func_get_user_var*) item;
  return (name.length == other->name.length &&
	  !memcmp(name.str, other->name.str, name.length));
}


4749
bool Item_func_get_user_var::set_value(THD *thd,
4750
                                       sp_rcontext * /*ctx*/, Item **it)
4751
{
4752
  Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
4753 4754 4755 4756
  /*
    Item_func_set_user_var is not fixed after construction, call
    fix_fields().
  */
4757
  return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
4758 4759 4760
}


4761
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
4762 4763
{
  DBUG_ASSERT(fixed == 0);
4764
  DBUG_ASSERT(thd->lex->exchange);
4765
  if (Item::fix_fields(thd, ref) ||
unknown's avatar
unknown committed
4766 4767 4768 4769 4770 4771 4772 4773
      !(entry= get_variable(&thd->user_vars, name, 1)))
    return TRUE;
  entry->type= STRING_RESULT;
  /*
    Let us set the same collation which is used for loading
    of fields in LOAD DATA INFILE.
    (Since Item_user_var_as_out_param is used only there).
  */
4774 4775 4776
  entry->collation.set(thd->lex->exchange->cs ? 
                       thd->lex->exchange->cs :
                       thd->variables.collation_database);
unknown's avatar
unknown committed
4777 4778 4779 4780 4781 4782 4783 4784
  entry->update_query_id= thd->query_id;
  return FALSE;
}


void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
  if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
4785
                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
unknown's avatar
unknown committed
4786 4787 4788 4789 4790 4791 4792 4793
    current_thd->fatal_error();			// Probably end of memory
}


void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                           CHARSET_INFO* cs)
{
  if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
4794
                    DERIVATION_IMPLICIT, 0 /* unsigned_arg */))
unknown's avatar
unknown committed
4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826
    current_thd->fatal_error();			// Probably end of memory
}


double Item_user_var_as_out_param::val_real()
{
  DBUG_ASSERT(0);
  return 0.0;
}


longlong Item_user_var_as_out_param::val_int()
{
  DBUG_ASSERT(0);
  return 0;
}


String* Item_user_var_as_out_param::val_str(String *str)
{
  DBUG_ASSERT(0);
  return 0;
}


my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
{
  DBUG_ASSERT(0);
  return 0;
}


4827
void Item_user_var_as_out_param::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
4828 4829 4830 4831 4832 4833
{
  str->append('@');
  str->append(name.str,name.length);
}


4834 4835 4836 4837
Item_func_get_system_var::
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
                       LEX_STRING *component_arg, const char *name_arg,
                       size_t name_len_arg)
Georgi Kodinov's avatar
Georgi Kodinov committed
4838 4839
  :var(var_arg), var_type(var_type_arg), orig_var_type(var_type_arg),
  component(*component_arg), cache_present(0)
4840 4841
{
  /* set_name() will allocate the name */
4842
  set_name(name_arg, (uint) name_len_arg, system_charset_info);
4843 4844 4845
}


4846
bool Item_func_get_system_var::is_written_to_binlog()
4847
{
4848 4849 4850 4851
  return var->is_written_to_binlog(var_type);
}


4852 4853 4854 4855 4856 4857 4858 4859 4860 4861
void Item_func_get_system_var::update_null_value()
{
  THD *thd= current_thd;
  int save_no_errors= thd->no_errors;
  thd->no_errors= TRUE;
  Item::update_null_value();
  thd->no_errors= save_no_errors;
}


4862 4863
void Item_func_get_system_var::fix_length_and_dec()
{
4864
  char *cptr;
4865
  maybe_null= TRUE;
4866
  max_length= 0;
4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895

  if (var->check_type(var_type))
  {
    if (var_type != OPT_DEFAULT)
    {
      my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
               var->name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
      return;
    }
    /* As there was no local variable, return the global value */
    var_type= OPT_GLOBAL;
  }

  switch (var->show_type())
  {
    case SHOW_LONG:
    case SHOW_INT:
    case SHOW_HA_ROWS:
      unsigned_flag= TRUE;
      max_length= MY_INT64_NUM_DECIMAL_DIGITS;
      decimals=0;
      break;
    case SHOW_LONGLONG:
      unsigned_flag= FALSE;
      max_length= MY_INT64_NUM_DECIMAL_DIGITS;
      decimals=0;
      break;
    case SHOW_CHAR:
    case SHOW_CHAR_PTR:
4896 4897 4898 4899 4900 4901 4902
      pthread_mutex_lock(&LOCK_global_system_variables);
      cptr= var->show_type() == SHOW_CHAR_PTR ? 
        *(char**) var->value_ptr(current_thd, var_type, &component) :
        (char*) var->value_ptr(current_thd, var_type, &component);
      if (cptr)
        max_length= strlen(cptr) * system_charset_info->mbmaxlen;
      pthread_mutex_unlock(&LOCK_global_system_variables);
4903 4904 4905
      collation.set(system_charset_info, DERIVATION_SYSCONST);
      decimals=NOT_FIXED_DEC;
      break;
4906
    case SHOW_BOOL:
4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921
    case SHOW_MY_BOOL:
      unsigned_flag= FALSE;
      max_length= 1;
      decimals=0;
      break;
    case SHOW_DOUBLE:
      unsigned_flag= FALSE;
      decimals= 6;
      max_length= DBL_DIG + 6;
      break;
    default:
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
      break;
  }
}
4922

4923

4924 4925 4926
void Item_func_get_system_var::print(String *str, enum_query_type query_type)
{
  str->append(name, name_length);
4927 4928 4929
}


4930
enum Item_result Item_func_get_system_var::result_type() const
4931
{
4932 4933
  switch (var->show_type())
  {
4934
    case SHOW_BOOL:
4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956
    case SHOW_MY_BOOL:
    case SHOW_INT:
    case SHOW_LONG:
    case SHOW_LONGLONG:
    case SHOW_HA_ROWS:
      return INT_RESULT;
    case SHOW_CHAR: 
    case SHOW_CHAR_PTR: 
      return STRING_RESULT;
    case SHOW_DOUBLE:
      return REAL_RESULT;
    default:
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
      return STRING_RESULT;                   // keep the compiler happy
  }
}


enum_field_types Item_func_get_system_var::field_type() const
{
  switch (var->show_type())
  {
4957
    case SHOW_BOOL:
4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975
    case SHOW_MY_BOOL:
    case SHOW_INT:
    case SHOW_LONG:
    case SHOW_LONGLONG:
    case SHOW_HA_ROWS:
      return MYSQL_TYPE_LONGLONG;
    case SHOW_CHAR: 
    case SHOW_CHAR_PTR: 
      return MYSQL_TYPE_VARCHAR;
    case SHOW_DOUBLE:
      return MYSQL_TYPE_DOUBLE;
    default:
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
      return MYSQL_TYPE_VARCHAR;              // keep the compiler happy
  }
}


4976 4977 4978 4979
/*
  Uses var, var_type, component, cache_present, used_query_id, thd,
  cached_llval, null_value, cached_null_value
*/
4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997
#define get_sys_var_safe(type) \
do { \
  type value; \
  pthread_mutex_lock(&LOCK_global_system_variables); \
  value= *(type*) var->value_ptr(thd, var_type, &component); \
  pthread_mutex_unlock(&LOCK_global_system_variables); \
  cache_present |= GET_SYS_VAR_CACHE_LONG; \
  used_query_id= thd->query_id; \
  cached_llval= null_value ? 0 : (longlong) value; \
  cached_null_value= null_value; \
  return cached_llval; \
} while (0)


longlong Item_func_get_system_var::val_int()
{
  THD *thd= current_thd;

Georgi Kodinov's avatar
Georgi Kodinov committed
4998
  if (cache_present && thd->query_id == used_query_id)
4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032
  {
    if (cache_present & GET_SYS_VAR_CACHE_LONG)
    {
      null_value= cached_null_value;
      return cached_llval;
    } 
    else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
    {
      null_value= cached_null_value;
      cached_llval= (longlong) cached_dval;
      cache_present|= GET_SYS_VAR_CACHE_LONG;
      return cached_llval;
    }
    else if (cache_present & GET_SYS_VAR_CACHE_STRING)
    {
      null_value= cached_null_value;
      if (!null_value)
        cached_llval= longlong_from_string_with_check (cached_strval.charset(),
                                                       cached_strval.c_ptr(),
                                                       cached_strval.c_ptr() +
                                                       cached_strval.length());
      else
        cached_llval= 0;
      cache_present|= GET_SYS_VAR_CACHE_LONG;
      return cached_llval;
    }
  }

  switch (var->show_type())
  {
    case SHOW_INT:      get_sys_var_safe (uint);
    case SHOW_LONG:     get_sys_var_safe (ulong);
    case SHOW_LONGLONG: get_sys_var_safe (longlong);
    case SHOW_HA_ROWS:  get_sys_var_safe (ha_rows);
5033
    case SHOW_BOOL:     get_sys_var_safe (bool);
5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074
    case SHOW_MY_BOOL:  get_sys_var_safe (my_bool);
    case SHOW_DOUBLE:
      {
        double dval= val_real();

        used_query_id= thd->query_id;
        cached_llval= (longlong) dval;
        cache_present|= GET_SYS_VAR_CACHE_LONG;
        return cached_llval;
      }
    case SHOW_CHAR:
    case SHOW_CHAR_PTR:
      {
        String *str_val= val_str(NULL);

        if (str_val && str_val->length())
          cached_llval= longlong_from_string_with_check (system_charset_info,
                                                          str_val->c_ptr(), 
                                                          str_val->c_ptr() + 
                                                          str_val->length());
        else
        {
          null_value= TRUE;
          cached_llval= 0;
        }

        cache_present|= GET_SYS_VAR_CACHE_LONG;
        return cached_llval;
      }

    default:            
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); 
      return 0;                               // keep the compiler happy
  }
}


String* Item_func_get_system_var::val_str(String* str)
{
  THD *thd= current_thd;

Georgi Kodinov's avatar
Georgi Kodinov committed
5075
  if (cache_present && thd->query_id == used_query_id)
5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130
  {
    if (cache_present & GET_SYS_VAR_CACHE_STRING)
    {
      null_value= cached_null_value;
      return null_value ? NULL : &cached_strval;
    }
    else if (cache_present & GET_SYS_VAR_CACHE_LONG)
    {
      null_value= cached_null_value;
      if (!null_value)
        cached_strval.set (cached_llval, collation.collation);
      cache_present|= GET_SYS_VAR_CACHE_STRING;
      return null_value ? NULL : &cached_strval;
    }
    else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
    {
      null_value= cached_null_value;
      if (!null_value)
        cached_strval.set_real (cached_dval, decimals, collation.collation);
      cache_present|= GET_SYS_VAR_CACHE_STRING;
      return null_value ? NULL : &cached_strval;
    }
  }

  str= &cached_strval;
  switch (var->show_type())
  {
    case SHOW_CHAR:
    case SHOW_CHAR_PTR:
    {
      pthread_mutex_lock(&LOCK_global_system_variables);
      char *cptr= var->show_type() == SHOW_CHAR_PTR ? 
        *(char**) var->value_ptr(thd, var_type, &component) :
        (char*) var->value_ptr(thd, var_type, &component);
      if (cptr)
      {
        if (str->copy(cptr, strlen(cptr), collation.collation))
        {
          null_value= TRUE;
          str= NULL;
        }
      }
      else
      {
        null_value= TRUE;
        str= NULL;
      }
      pthread_mutex_unlock(&LOCK_global_system_variables);
      break;
    }

    case SHOW_INT:
    case SHOW_LONG:
    case SHOW_LONGLONG:
    case SHOW_HA_ROWS:
5131
    case SHOW_BOOL:
5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155
    case SHOW_MY_BOOL:
      str->set (val_int(), collation.collation);
      break;
    case SHOW_DOUBLE:
      str->set_real (val_real(), decimals, collation.collation);
      break;

    default:
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
      str= NULL;
      break;
  }

  cache_present|= GET_SYS_VAR_CACHE_STRING;
  used_query_id= thd->query_id;
  cached_null_value= null_value;
  return str;
}


double Item_func_get_system_var::val_real()
{
  THD *thd= current_thd;

Georgi Kodinov's avatar
Georgi Kodinov committed
5156
  if (cache_present && thd->query_id == used_query_id)
5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223
  {
    if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
    {
      null_value= cached_null_value;
      return cached_dval;
    }
    else if (cache_present & GET_SYS_VAR_CACHE_LONG)
    {
      null_value= cached_null_value;
      cached_dval= (double)cached_llval;
      cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
      return cached_dval;
    }
    else if (cache_present & GET_SYS_VAR_CACHE_STRING)
    {
      null_value= cached_null_value;
      if (!null_value)
        cached_dval= double_from_string_with_check (cached_strval.charset(),
                                                    cached_strval.c_ptr(),
                                                    cached_strval.c_ptr() +
                                                    cached_strval.length());
      else
        cached_dval= 0;
      cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
      return cached_dval;
    }
  }

  switch (var->show_type())
  {
    case SHOW_DOUBLE:
      pthread_mutex_lock(&LOCK_global_system_variables);
      cached_dval= *(double*) var->value_ptr(thd, var_type, &component);
      pthread_mutex_unlock(&LOCK_global_system_variables);
      used_query_id= thd->query_id;
      cached_null_value= null_value;
      if (null_value)
        cached_dval= 0;
      cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
      return cached_dval;
    case SHOW_CHAR:
    case SHOW_CHAR_PTR:
      {
        char *cptr;

        pthread_mutex_lock(&LOCK_global_system_variables);
        cptr= var->show_type() == SHOW_CHAR ? 
          (char*) var->value_ptr(thd, var_type, &component) :
          *(char**) var->value_ptr(thd, var_type, &component);
        if (cptr)
          cached_dval= double_from_string_with_check (system_charset_info, 
                                                cptr, cptr + strlen (cptr));
        else
        {
          null_value= TRUE;
          cached_dval= 0;
        }
        pthread_mutex_unlock(&LOCK_global_system_variables);
        used_query_id= thd->query_id;
        cached_null_value= null_value;
        cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
        return cached_dval;
      }
    case SHOW_INT:
    case SHOW_LONG:
    case SHOW_LONGLONG:
    case SHOW_HA_ROWS:
5224
    case SHOW_BOOL:
5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248
    case SHOW_MY_BOOL:
        cached_dval= (double) val_int();
        cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
        used_query_id= thd->query_id;
        cached_null_value= null_value;
        return cached_dval;
    default:
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name);
      return 0;
  }
}


bool Item_func_get_system_var::eq(const Item *item, bool binary_cmp) const
{
  /* Assume we don't have rtti */
  if (this == item)
    return 1;					// Same item is same.
  /* Check if other type is also a get_user_var() object */
  if (item->type() != FUNC_ITEM ||
      ((Item_func*) item)->functype() != functype())
    return 0;
  Item_func_get_system_var *other=(Item_func_get_system_var*) item;
  return (var == other->var && var_type == other->var_type);
5249 5250 5251
}


Georgi Kodinov's avatar
Georgi Kodinov committed
5252 5253 5254
void Item_func_get_system_var::cleanup()
{
  Item_func::cleanup();
Georgi Kodinov's avatar
Georgi Kodinov committed
5255
  cache_present= 0;
Georgi Kodinov's avatar
Georgi Kodinov committed
5256 5257 5258 5259 5260
  var_type= orig_var_type;
  cached_strval.free();
}


unknown's avatar
unknown committed
5261 5262
longlong Item_func_inet_aton::val_int()
{
5263
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
5264 5265 5266 5267 5268
  uint byte_result = 0;
  ulonglong result = 0;			// We are ready for 64 bit addresses
  const char *p,* end;
  char c = '.'; // we mark c to indicate invalid IP in case length is 0
  char buff[36];
5269
  int dot_count= 0;
unknown's avatar
unknown committed
5270

unknown's avatar
unknown committed
5271
  String *s,tmp(buff,sizeof(buff),&my_charset_bin);
unknown's avatar
unknown committed
5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287
  if (!(s = args[0]->val_str(&tmp)))		// If null value
    goto err;
  null_value=0;

  end= (p = s->ptr()) + s->length();
  while (p < end)
  {
    c = *p++;
    int digit = (int) (c - '0');		// Assume ascii
    if (digit >= 0 && digit <= 9)
    {
      if ((byte_result = byte_result * 10 + digit) > 255)
	goto err;				// Wrong address
    }
    else if (c == '.')
    {
5288
      dot_count++;
unknown's avatar
unknown committed
5289 5290 5291 5292 5293 5294 5295
      result= (result << 8) + (ulonglong) byte_result;
      byte_result = 0;
    }
    else
      goto err;					// Invalid character
  }
  if (c != '.')					// IP number can't end on '.'
5296
  {
5297 5298 5299 5300 5301 5302
    /*
      Handle short-forms addresses according to standard. Examples:
      127		-> 0.0.0.127
      127.1		-> 127.0.0.1
      127.2.1		-> 127.2.0.1
    */
unknown's avatar
unknown committed
5303
    switch (dot_count) {
5304 5305
    case 1: result<<= 8; /* Fall through */
    case 2: result<<= 8; /* Fall through */
5306
    }
unknown's avatar
unknown committed
5307
    return (result << 8) + (ulonglong) byte_result;
5308
  }
unknown's avatar
unknown committed
5309 5310 5311 5312 5313 5314

err:
  null_value=1;
  return 0;
}

unknown's avatar
unknown committed
5315

5316
void Item_func_match::init_search(bool no_order)
5317
{
unknown's avatar
unknown committed
5318
  DBUG_ENTER("Item_func_match::init_search");
5319 5320

  /* Check if init_search() has been called before */
5321
  if (ft_handler)
5322 5323 5324 5325 5326 5327 5328 5329 5330
  {
    /*
      We should reset ft_handler as it is cleaned up
      on destruction of FT_SELECT object
      (necessary in case of re-execution of subquery).
      TODO: FT_SELECT should not clean up ft_handler.
    */
    if (join_key)
      table->file->ft_handler= ft_handler;
unknown's avatar
unknown committed
5331
    DBUG_VOID_RETURN;
5332
  }
5333

5334
  if (key == NO_SUCH_KEY)
5335 5336
  {
    List<Item> fields;
5337
    fields.push_back(new Item_string(" ",1, cmp_collation.collation));
5338 5339
    for (uint i=1; i < arg_count; i++)
      fields.push_back(args[i]);
5340
    concat_ws=new Item_func_concat_ws(fields);
unknown's avatar
unknown committed
5341 5342 5343
    /*
      Above function used only to get value and do not need fix_fields for it:
      Item_string - basic constant
unknown's avatar
unknown committed
5344 5345
      fields - fix_fields() was already called for this arguments
      Item_func_concat_ws - do not need fix_fields() to produce value
unknown's avatar
unknown committed
5346
    */
5347
    concat_ws->quick_fix_field();
5348
  }
5349

5350 5351
  if (master)
  {
5352 5353
    join_key=master->join_key=join_key|master->join_key;
    master->init_search(no_order);
5354 5355
    ft_handler=master->ft_handler;
    join_key=master->join_key;
unknown's avatar
unknown committed
5356
    DBUG_VOID_RETURN;
5357 5358
  }

unknown's avatar
unknown committed
5359
  String *ft_tmp= 0;
5360

5361
  // MATCH ... AGAINST (NULL) is meaningless, but possible
5362
  if (!(ft_tmp=key_item()->val_str(&value)))
5363
  {
5364 5365
    ft_tmp= &value;
    value.set("",0,cmp_collation.collation);
5366 5367
  }

5368 5369
  if (ft_tmp->charset() != cmp_collation.collation)
  {
5370
    uint dummy_errors;
5371
    search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
5372
                      cmp_collation.collation, &dummy_errors);
5373
    ft_tmp= &search_value;
5374 5375
  }

5376 5377
  if (join_key && !no_order)
    flags|=FT_SORTED;
5378
  ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
5379 5380 5381

  if (join_key)
    table->file->ft_handler=ft_handler;
unknown's avatar
unknown committed
5382 5383

  DBUG_VOID_RETURN;
5384 5385
}

unknown's avatar
unknown committed
5386

5387
bool Item_func_match::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
5388
{
5389
  DBUG_ASSERT(fixed == 0);
5390
  Item *UNINIT_VAR(item);                        // Safe as arg_count is > 1
unknown's avatar
unknown committed
5391

5392 5393 5394
  maybe_null=1;
  join_key=0;

5395 5396 5397 5398 5399
  /*
    const_item is assumed in quite a bit of places, so it would be difficult
    to remove;  If it would ever to be removed, this should include
    modifications to find_best and auto_close as complement to auto_init code
    above.
5400
   */
5401
  if (Item_func::fix_fields(thd, ref) ||
5402
      !args[0]->const_during_execution())
5403 5404
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
unknown's avatar
unknown committed
5405
    return TRUE;
5406
  }
unknown's avatar
unknown committed
5407

5408 5409
  const_item_cache=0;
  for (uint i=1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
5410
  {
5411
    item=args[i];
unknown's avatar
unknown committed
5412
    if (item->type() == Item::REF_ITEM)
5413 5414
      args[i]= item= *((Item_ref *)item)->ref;
    if (item->type() != Item::FIELD_ITEM)
5415 5416 5417 5418
    {
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
      return TRUE;
    }
unknown's avatar
unknown committed
5419
  }
5420 5421
  /*
    Check that all columns come from the same table.
5422
    We've already checked that columns in MATCH are fields so
5423 5424 5425
    PARAM_TABLE_BIT can only appear from AGAINST argument.
  */
  if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
5426
    key=NO_SUCH_KEY;
5427

5428
  if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
5429 5430
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
unknown's avatar
unknown committed
5431
    return TRUE;
5432
  }
5433
  table=((Item_field *)item)->field->table;
5434
  if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
5435
  {
unknown's avatar
unknown committed
5436
    my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
unknown's avatar
unknown committed
5437
    return 1;
5438
  }
5439
  table->fulltext_searched=1;
5440 5441
  return agg_arg_collations_for_comparison(cmp_collation,
                                           args+1, arg_count-1, 0);
unknown's avatar
unknown committed
5442
}
5443

unknown's avatar
unknown committed
5444 5445 5446
bool Item_func_match::fix_index()
{
  Item_field *item;
5447
  uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
5448
  uint max_cnt=0, mkeys=0, i;
5449

5450
  if (key == NO_SUCH_KEY)
5451
    return 0;
5452 5453 5454
  
  if (!table) 
    goto err;
unknown's avatar
unknown committed
5455

5456
  for (keynr=0 ; keynr < table->s->keys ; keynr++)
unknown's avatar
unknown committed
5457
  {
5458
    if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
5459 5460 5461
        (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr) :
                           table->s->keys_in_use.is_set(keynr)))

unknown's avatar
unknown committed
5462
    {
5463
      ft_to_key[fts]=keynr;
unknown's avatar
unknown committed
5464 5465 5466 5467 5468 5469
      ft_cnt[fts]=0;
      fts++;
    }
  }

  if (!fts)
5470
    goto err;
unknown's avatar
unknown committed
5471

5472
  for (i=1; i < arg_count; i++)
unknown's avatar
unknown committed
5473
  {
5474
    item=(Item_field*)args[i];
5475
    for (keynr=0 ; keynr < fts ; keynr++)
unknown's avatar
unknown committed
5476
    {
5477
      KEY *ft_key=&table->key_info[ft_to_key[keynr]];
unknown's avatar
unknown committed
5478 5479 5480 5481 5482
      uint key_parts=ft_key->key_parts;

      for (uint part=0 ; part < key_parts ; part++)
      {
	if (item->field->eq(ft_key->key_part[part].field))
5483
	  ft_cnt[keynr]++;
unknown's avatar
unknown committed
5484 5485 5486 5487
      }
    }
  }

5488
  for (keynr=0 ; keynr < fts ; keynr++)
unknown's avatar
unknown committed
5489
  {
5490
    if (ft_cnt[keynr] > max_cnt)
unknown's avatar
unknown committed
5491
    {
5492
      mkeys=0;
5493 5494
      max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
5495 5496
      continue;
    }
5497
    if (max_cnt && ft_cnt[keynr] == max_cnt)
5498 5499
    {
      mkeys++;
5500 5501
      ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
5502
      continue;
unknown's avatar
unknown committed
5503 5504 5505
    }
  }

5506
  for (keynr=0 ; keynr <= mkeys ; keynr++)
unknown's avatar
unknown committed
5507
  {
5508 5509
    // partial keys doesn't work
    if (max_cnt < arg_count-1 ||
5510
        max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
5511
      continue;
unknown's avatar
unknown committed
5512

5513
    key=ft_to_key[keynr];
5514

5515 5516 5517
    return 0;
  }

5518
err:
5519
  if (flags & FT_BOOL)
5520
  {
5521
    key=NO_SUCH_KEY;
5522 5523
    return 0;
  }
unknown's avatar
unknown committed
5524 5525
  my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
             ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
5526
  return 1;
5527 5528
}

5529

5530
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
5531
{
unknown's avatar
unknown committed
5532 5533
  if (item->type() != FUNC_ITEM ||
      ((Item_func*)item)->functype() != FT_FUNC ||
5534
      flags != ((Item_func_match*)item)->flags)
5535 5536 5537 5538 5539
    return 0;

  Item_func_match *ifm=(Item_func_match*) item;

  if (key == ifm->key && table == ifm->table &&
5540
      key_item()->eq(ifm->key_item(), binary_cmp))
5541
    return 1;
unknown's avatar
unknown committed
5542 5543 5544 5545

  return 0;
}

5546

5547
double Item_func_match::val_real()
unknown's avatar
unknown committed
5548
{
5549
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
5550
  DBUG_ENTER("Item_func_match::val");
unknown's avatar
unknown committed
5551
  if (ft_handler == NULL)
unknown's avatar
unknown committed
5552
    DBUG_RETURN(-1.0);
unknown's avatar
unknown committed
5553

5554
  if (key != NO_SUCH_KEY && table->null_row) /* NULL row from an outer join */
unknown's avatar
unknown committed
5555
    DBUG_RETURN(0.0);
unknown's avatar
unknown committed
5556

unknown's avatar
unknown committed
5557 5558 5559
  if (join_key)
  {
    if (table->file->ft_handler)
unknown's avatar
unknown committed
5560
      DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
unknown's avatar
unknown committed
5561 5562 5563
    join_key=0;
  }

5564
  if (key == NO_SUCH_KEY)
unknown's avatar
unknown committed
5565
  {
5566 5567
    String *a= concat_ws->val_str(&value);
    if ((null_value= (a == 0)) || !a->length())
unknown's avatar
unknown committed
5568 5569
      DBUG_RETURN(0);
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
5570
				      (uchar *)a->ptr(), a->length()));
unknown's avatar
unknown committed
5571
  }
unknown's avatar
unknown committed
5572 5573
  DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
                                                 table->record[0], 0));
unknown's avatar
unknown committed
5574 5575
}

5576
void Item_func_match::print(String *str, enum_query_type query_type)
5577
{
5578
  str->append(STRING_WITH_LEN("(match "));
5579
  print_args(str, 1, query_type);
5580
  str->append(STRING_WITH_LEN(" against ("));
5581
  args[0]->print(str, query_type);
unknown's avatar
unknown committed
5582
  if (flags & FT_BOOL)
5583
    str->append(STRING_WITH_LEN(" in boolean mode"));
unknown's avatar
unknown committed
5584
  else if (flags & FT_EXPAND)
5585 5586
    str->append(STRING_WITH_LEN(" with query expansion"));
  str->append(STRING_WITH_LEN("))"));
5587
}
unknown's avatar
unknown committed
5588

unknown's avatar
unknown committed
5589 5590
longlong Item_func_bit_xor::val_int()
{
5591
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
5592 5593
  ulonglong arg1= (ulonglong) args[0]->val_int();
  ulonglong arg2= (ulonglong) args[1]->val_int();
5594
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
5595 5596 5597 5598
    return 0;
  return (longlong) (arg1 ^ arg2);
}

5599

5600 5601 5602 5603
/***************************************************************************
  System variables
****************************************************************************/

unknown's avatar
unknown committed
5604 5605
/**
  Return value of an system variable base[.name] as a constant item.
5606

unknown's avatar
unknown committed
5607 5608 5609 5610
  @param thd			Thread handler
  @param var_type		global / session
  @param name		        Name of base or system variable
  @param component		Component.
5611

unknown's avatar
unknown committed
5612
  @note
5613 5614
    If component.str = 0 then the variable name is in 'name'

unknown's avatar
unknown committed
5615 5616 5617
  @return
    - 0  : error
    - #  : constant item
5618
*/
5619

5620 5621 5622

Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
		     LEX_STRING component)
5623
{
5624 5625 5626
  sys_var *var;
  LEX_STRING *base_name, *component_name;

5627 5628 5629 5630 5631 5632 5633 5634 5635 5636
  if (component.str)
  {
    base_name= &component;
    component_name= &name;
  }
  else
  {
    base_name= &name;
    component_name= &component;			// Empty string
  }
unknown's avatar
unknown committed
5637

unknown's avatar
unknown committed
5638
  if (!(var= find_sys_var(thd, base_name->str, base_name->length)))
unknown's avatar
unknown committed
5639
    return 0;
5640 5641 5642 5643
  if (component.str)
  {
    if (!var->is_struct())
    {
5644
      my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
5645 5646 5647
      return 0;
    }
  }
unknown's avatar
unknown committed
5648
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
5649

5650 5651
  set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);

5652
  return new Item_func_get_system_var(var, var_type, component_name,
5653
                                      NULL, 0);
5654 5655 5656
}


unknown's avatar
unknown committed
5657
/**
unknown's avatar
unknown committed
5658
  Check a user level lock.
5659

unknown's avatar
unknown committed
5660
  Sets null_value=TRUE on error.
5661

unknown's avatar
unknown committed
5662
  @retval
5663
    1		Available
unknown's avatar
unknown committed
5664 5665
  @retval
    0		Already taken, or error
unknown's avatar
unknown committed
5666 5667
*/

5668
longlong Item_func_is_free_lock::val_int()
unknown's avatar
unknown committed
5669
{
5670
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
5671
  String *res=args[0]->val_str(&value);
5672
  User_level_lock *ull;
unknown's avatar
unknown committed
5673 5674

  null_value=0;
5675
  if (!res || !res->length())
unknown's avatar
unknown committed
5676 5677 5678 5679 5680 5681
  {
    null_value=1;
    return 0;
  }
  
  pthread_mutex_lock(&LOCK_user_locks);
5682 5683
  ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
                                       (size_t) res->length());
unknown's avatar
unknown committed
5684 5685 5686 5687 5688
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 1;
  return 0;
}
unknown's avatar
unknown committed
5689

unknown's avatar
SCRUM  
unknown committed
5690 5691
longlong Item_func_is_used_lock::val_int()
{
5692
  DBUG_ASSERT(fixed == 1);
unknown's avatar
SCRUM  
unknown committed
5693
  String *res=args[0]->val_str(&value);
5694
  User_level_lock *ull;
unknown's avatar
SCRUM  
unknown committed
5695 5696 5697 5698 5699 5700

  null_value=1;
  if (!res || !res->length())
    return 0;
  
  pthread_mutex_lock(&LOCK_user_locks);
5701 5702
  ull= (User_level_lock *) hash_search(&hash_user_locks, (uchar*) res->ptr(),
                                       (size_t) res->length());
unknown's avatar
SCRUM  
unknown committed
5703 5704 5705 5706 5707 5708 5709 5710
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 0;

  null_value=0;
  return ull->thread_id;
}

5711

5712 5713 5714 5715 5716 5717 5718 5719 5720
longlong Item_func_row_count::val_int()
{
  DBUG_ASSERT(fixed == 1);
  THD *thd= current_thd;

  return thd->row_count_func;
}


5721 5722


5723
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
5724
  :Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
5725
{
unknown's avatar
unknown committed
5726
  maybe_null= 1;
5727
  m_name->init_qname(current_thd);
unknown's avatar
unknown committed
5728 5729
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
  dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
5730 5731
}

unknown's avatar
unknown committed
5732

5733 5734
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
                           sp_name *name, List<Item> &list)
5735
  :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
5736
{
unknown's avatar
unknown committed
5737
  maybe_null= 1;
5738
  m_name->init_qname(current_thd);
unknown's avatar
unknown committed
5739 5740
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
  dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
5741 5742
}

unknown's avatar
unknown committed
5743

5744 5745 5746
void
Item_func_sp::cleanup()
{
5747
  if (sp_result_field)
5748
  {
5749 5750
    delete sp_result_field;
    sp_result_field= NULL;
5751
  }
5752
  m_sp= NULL;
5753
  dummy_table->alias= NULL;
5754 5755
  Item_func::cleanup();
}
unknown's avatar
unknown committed
5756

5757 5758 5759
const char *
Item_func_sp::func_name() const
{
5760
  THD *thd= current_thd;
unknown's avatar
unknown committed
5761
  /* Calculate length to avoid reallocation of string for sure */
5762
  uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
5763 5764
              m_name->m_name.length)*2 + //characters*quoting
             2 +                         // ` and `
5765 5766
             (m_name->m_explicit_name ?
              3 : 0) +                   // '`', '`' and '.' for the db
5767 5768
             1 +                         // end of string
             ALIGN_SIZE(1));             // to avoid String reallocation
unknown's avatar
unknown committed
5769
  String qname((char *)alloc_root(thd->mem_root, len), len,
5770
               system_charset_info);
5771

5772
  qname.length(0);
5773 5774 5775 5776 5777
  if (m_name->m_explicit_name)
  {
    append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
    qname.append('.');
  }
5778 5779
  append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
  return qname.ptr();
5780 5781
}

5782

5783 5784 5785 5786 5787 5788 5789 5790
int my_missing_function_error(const LEX_STRING &token, const char *func_name)
{
  if (token.length && is_lex_native_function (&token))
    return my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
  else
    return my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
}

5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808

/**
  @brief Initialize the result field by creating a temporary dummy table
    and assign it to a newly created field object. Meta data used to
    create the field is fetched from the sp_head belonging to the stored
    proceedure found in the stored procedure functon cache.
  
  @note This function should be called from fix_fields to init the result
    field. It is some what related to Item_field.

  @see Item_field

  @param thd A pointer to the session and thread context.

  @return Function return error status.
  @retval TRUE is returned on an error
  @retval FALSE is returned on success.
*/
5809

5810 5811
bool
Item_func_sp::init_result_field(THD *thd)
unknown's avatar
unknown committed
5812
{
unknown's avatar
unknown committed
5813
  LEX_STRING empty_name= { C_STRING_WITH_LEN("") };
5814
  TABLE_SHARE *share;
5815
  DBUG_ENTER("Item_func_sp::init_result_field");
unknown's avatar
unknown committed
5816

5817 5818
  DBUG_ASSERT(m_sp == NULL);
  DBUG_ASSERT(sp_result_field == NULL);
unknown's avatar
unknown committed
5819

5820 5821
  if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
                               &thd->sp_func_cache, TRUE)))
unknown's avatar
unknown committed
5822
  {
5823
    my_missing_function_error (m_name->m_name, m_name->m_qname.str);
5824 5825
    context->process_error(thd);
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
5826
  }
5827 5828 5829 5830 5831 5832

  /*
     A Field need to be attached to a Table.
     Below we "create" a dummy table by initializing 
     the needed pointers.
   */
unknown's avatar
unknown committed
5833 5834 5835
  
  share= dummy_table->s;
  dummy_table->alias = "";
5836 5837 5838 5839 5840 5841
  dummy_table->maybe_null = maybe_null;
  dummy_table->in_use= thd;
  dummy_table->copy_blobs= TRUE;
  share->table_cache_key = empty_name;
  share->table_name = empty_name;

5842 5843
  if (!(sp_result_field= m_sp->create_result_field(max_length, name,
                                                   dummy_table)))
unknown's avatar
unknown committed
5844
  {
5845
   DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
5846
  }
5847 5848
  
  if (sp_result_field->pack_length() > sizeof(result_buf))
unknown's avatar
unknown committed
5849
  {
5850 5851 5852 5853
    void *tmp;
    if (!(tmp= sql_alloc(sp_result_field->pack_length())))
      DBUG_RETURN(TRUE);
    sp_result_field->move_field((uchar*) tmp);
unknown's avatar
unknown committed
5854
  }
5855 5856
  else
    sp_result_field->move_field(result_buf);
5857 5858 5859 5860
  
  sp_result_field->null_ptr= (uchar *) &null_value;
  sp_result_field->null_bit= 1;
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
5861 5862
}

5863

5864 5865
/**
  @brief Initialize local members with values from the Field interface.
unknown's avatar
unknown committed
5866

5867 5868
  @note called from Item::fix_fields.
*/
5869

5870 5871 5872
void Item_func_sp::fix_length_and_dec()
{
  DBUG_ENTER("Item_func_sp::fix_length_and_dec");
unknown's avatar
unknown committed
5873

5874 5875 5876 5877 5878 5879 5880 5881 5882 5883
  DBUG_ASSERT(sp_result_field);
  decimals= sp_result_field->decimals();
  max_length= sp_result_field->field_length;
  collation.set(sp_result_field->charset());
  maybe_null= 1;
  unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG);

  DBUG_VOID_RETURN;
}

5884

5885 5886 5887 5888 5889 5890
/**
  @brief Execute function & store value in field.

  @return Function returns error status.
  @retval FALSE on success.
  @retval TRUE if an error occurred.
unknown's avatar
unknown committed
5891 5892
*/

5893
bool
5894
Item_func_sp::execute()
5895
{
5896
  THD *thd= current_thd;
5897
  
5898 5899
  /* Execute function and store the return value in the field. */

5900
  if (execute_impl(thd))
5901 5902 5903
  {
    null_value= 1;
    context->process_error(thd);
5904 5905
    if (thd->killed)
      thd->send_kill_message();
5906 5907 5908 5909 5910
    return TRUE;
  }

  /* Check that the field (the value) is not NULL. */

5911
  null_value= sp_result_field->is_null();
5912 5913

  return null_value;
5914 5915 5916
}


5917 5918 5919 5920 5921 5922 5923 5924 5925 5926
/**
   @brief Execute function and store the return value in the field.

   @note This function was intended to be the concrete implementation of
    the interface function execute. This was never realized.

   @return The error state.
   @retval FALSE on success
   @retval TRUE if an error occurred.
*/
5927
bool
5928
Item_func_sp::execute_impl(THD *thd)
5929
{
5930
  bool err_status= TRUE;
5931
  Sub_statement_state statement_state;
5932 5933 5934
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  Security_context *save_security_ctx= thd->security_ctx;
#endif
5935 5936 5937
  enum enum_sp_data_access access=
    (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
     SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
5938

5939 5940
  DBUG_ENTER("Item_func_sp::execute_impl");

5941 5942 5943 5944 5945 5946 5947
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  if (context->security_ctx)
  {
    /* Set view definer security context */
    thd->security_ctx= context->security_ctx;
  }
#endif
5948
  if (sp_check_access(thd))
5949
    goto error;
5950

5951 5952 5953 5954
  /*
    Throw an error if a non-deterministic function is called while
    statement-based replication (SBR) is active.
  */
5955

5956
  if (!m_sp->m_chistics->detistic && !trust_function_creators &&
5957
      (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
5958 5959 5960
      (mysql_bin_log.is_open() &&
       thd->variables.binlog_format == BINLOG_FORMAT_STMT))
  {
5961
    my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
5962 5963 5964
    goto error;
  }

5965 5966 5967 5968 5969
  /*
    Disable the binlogging if this is not a SELECT statement. If this is a
    SELECT, leave binlogging on, so execute_function() code writes the
    function call into binlog.
  */
5970
  thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
5971
  err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field); 
5972
  thd->restore_sub_statement_state(&statement_state);
unknown's avatar
unknown committed
5973

5974
error:
5975
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
5976
  thd->security_ctx= save_security_ctx;
5977
#endif
5978

5979
  DBUG_RETURN(err_status);
5980 5981
}

5982

unknown's avatar
unknown committed
5983 5984 5985 5986
void
Item_func_sp::make_field(Send_field *tmp_field)
{
  DBUG_ENTER("Item_func_sp::make_field");
5987 5988
  DBUG_ASSERT(sp_result_field);
  sp_result_field->make_field(tmp_field);
5989 5990
  if (name)
    tmp_field->col_name= name;
unknown's avatar
unknown committed
5991 5992 5993 5994
  DBUG_VOID_RETURN;
}


5995 5996
enum enum_field_types
Item_func_sp::field_type() const
5997
{
5998
  DBUG_ENTER("Item_func_sp::field_type");
5999 6000
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field->type());
6001 6002
}

6003 6004
Item_result
Item_func_sp::result_type() const
6005
{
6006
  DBUG_ENTER("Item_func_sp::result_type");
6007
  DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
6008 6009
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field->result_type());
6010 6011
}

6012 6013 6014
longlong Item_func_found_rows::val_int()
{
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
6015
  return current_thd->found_rows();
6016
}
unknown's avatar
unknown committed
6017

unknown's avatar
unknown committed
6018

unknown's avatar
unknown committed
6019 6020 6021 6022 6023
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
  DBUG_ENTER("Item_func_sp::tmp_table_field");

6024 6025
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field);
unknown's avatar
unknown committed
6026
}
6027

unknown's avatar
unknown committed
6028

6029 6030
/**
  @brief Checks if requested access to function can be granted to user.
6031 6032
    If function isn't found yet, it searches function first.
    If function can't be found or user don't have requested access
unknown's avatar
unknown committed
6033
    error is raised.
6034 6035 6036 6037 6038 6039 6040

  @param thd thread handler

  @return Indication if the access was granted or not.
  @retval FALSE Access is granted.
  @retval TRUE Requested access can't be granted or function doesn't exists.
    
6041
*/
unknown's avatar
unknown committed
6042

6043
bool
6044
Item_func_sp::sp_check_access(THD *thd)
6045
{
6046 6047
  DBUG_ENTER("Item_func_sp::sp_check_access");
  DBUG_ASSERT(m_sp);
unknown's avatar
unknown committed
6048
#ifndef NO_EMBEDDED_ACCESS_CHECKS
6049
  if (check_routine_access(thd, EXECUTE_ACL,
unknown's avatar
unknown committed
6050
			   m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
6051
    DBUG_RETURN(TRUE);
6052
#endif
unknown's avatar
unknown committed
6053

6054
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
6055
}
6056

6057

6058 6059 6060 6061
bool
Item_func_sp::fix_fields(THD *thd, Item **ref)
{
  bool res;
6062
  DBUG_ENTER("Item_func_sp::fix_fields");
6063
  DBUG_ASSERT(fixed == 0);
6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074
 
  /*
    We must call init_result_field before Item_func::fix_fields() 
    to make m_sp and result_field members available to fix_length_and_dec(),
    which is called from Item_func::fix_fields().
  */
  res= init_result_field(thd);

  if (res)
    DBUG_RETURN(res);

6075
  res= Item_func::fix_fields(thd, ref);
6076 6077 6078 6079 6080

  if (res)
    DBUG_RETURN(res);

  if (thd->lex->view_prepare_mode)
unknown's avatar
unknown committed
6081
  {
6082 6083
    /*
      Here we check privileges of the stored routine only during view
6084 6085 6086 6087 6088 6089 6090
      creation, in order to validate the view.  A runtime check is
      perfomed in Item_func_sp::execute(), and this method is not
      called during context analysis.  Notice, that during view
      creation we do not infer into stored routine bodies and do not
      check privileges of its statements, which would probably be a
      good idea especially if the view has SQL SECURITY DEFINER and
      the used stored procedure has SQL SECURITY DEFINER.
6091
    */
6092
    res= sp_check_access(thd);
6093
#ifndef NO_EMBEDDED_ACCESS_CHECKS
6094 6095 6096
    /*
      Try to set and restore the security context to see whether it's valid
    */
6097
    Security_context *save_secutiry_ctx;
6098 6099
    res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
    if (!res)
6100
      m_sp->m_security_ctx.restore_security_context(thd, save_secutiry_ctx);
6101
    
6102
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
unknown's avatar
unknown committed
6103
  }
6104

unknown's avatar
unknown committed
6105
  if (!m_sp->m_chistics->detistic)
6106 6107 6108 6109 6110
  {
    used_tables_cache |= RAND_TABLE_BIT;
    const_item_cache= FALSE;
  }

6111
  DBUG_RETURN(res);
6112
}
6113 6114


unknown's avatar
unknown committed
6115 6116 6117
void Item_func_sp::update_used_tables()
{
  Item_func::update_used_tables();
6118

unknown's avatar
unknown committed
6119
  if (!m_sp->m_chistics->detistic)
6120 6121 6122 6123
  {
    used_tables_cache |= RAND_TABLE_BIT;
    const_item_cache= FALSE;
  }
unknown's avatar
unknown committed
6124
}
6125 6126


6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148
/*
  uuid_short handling.

  The short uuid is defined as a longlong that contains the following bytes:

  Bytes  Comment
  1      Server_id & 255
  4      Startup time of server in seconds
  3      Incrementor

  This means that an uuid is guaranteed to be unique
  even in a replication environment if the following holds:

  - The last byte of the server id is unique
  - If you between two shutdown of the server don't get more than
    an average of 2^24 = 16M calls to uuid_short() per second.
*/

ulonglong uuid_value;

void uuid_short_init()
{
6149 6150
  uuid_value= ((((ulonglong) server_id) << 56) + 
               (((ulonglong) server_start_time) << 24));
6151 6152 6153 6154 6155 6156
}


longlong Item_func_uuid_short::val_int()
{
  ulonglong val;
6157
  pthread_mutex_lock(&LOCK_short_uuid_generator);
6158
  val= uuid_value++;
6159
  pthread_mutex_unlock(&LOCK_short_uuid_generator);
6160 6161
  return (longlong) val;
}