item_func.cc 167 KB
Newer Older
1
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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

   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
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
unknown's avatar
unknown committed
15

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

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

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

Mats Kindahl's avatar
Mats Kindahl committed
27
#include "my_global.h"                          /* NO_EMBEDDED_ACCESS_CHECKS */
28 29 30 31 32 33 34 35
#include "sql_priv.h"
/*
  It is necessary to include set_var.h instead of item.h because there
  are dependencies on include order for set_var.h and item.h. This
  will be resolved later.
*/
#include "sql_class.h"                          // set_var.h: THD
#include "set_var.h"
unknown's avatar
unknown committed
36
#include "slave.h"				// for wait_for_master_pos
37 38 39 40 41
#include "sql_show.h"                           // append_identifier
#include "strfunc.h"                            // find_type
#include "sql_parse.h"                          // is_update_query
#include "sql_acl.h"                            // EXECUTE_ACL
#include "mysqld.h"                             // LOCK_uuid_generator
42
#include "rpl_mi.h"
unknown's avatar
unknown committed
43 44 45 46
#include <m_ctype.h>
#include <hash.h>
#include <time.h>
#include <ft_global.h>
47
#include <my_bit.h>
unknown's avatar
unknown committed
48

49 50 51
#include "sp_head.h"
#include "sp_rcontext.h"
#include "sp.h"
52
#include "set_var.h"
53
#include "debug_sync.h"
54 55
#include <mysql/plugin.h>
#include <mysql/service_thd_wait.h>
unknown's avatar
unknown committed
56

unknown's avatar
unknown committed
57 58 59 60
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
#endif

61 62 63 64 65 66 67 68 69 70
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
71 72 73 74
/**
  @return
    TRUE if item is a constant
*/
unknown's avatar
unknown committed
75 76 77 78 79 80 81

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

unknown's avatar
unknown committed
82

83 84 85 86 87 88 89 90
/**
   Test if the sum of arguments overflows the ulonglong range.
*/
static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2)
{
  return ULONGLONG_MAX - arg1 < arg2;
}

91
void Item_func::set_arguments(List<Item> &list)
unknown's avatar
unknown committed
92
{
93
  allowed_arg_cols= 1;
unknown's avatar
unknown committed
94
  arg_count=list.elements;
unknown's avatar
unknown committed
95 96
  args= tmp_arg;                                // If 2 arguments
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
unknown's avatar
unknown committed
97
  {
unknown's avatar
unknown committed
98
    List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
99
    Item *item;
unknown's avatar
unknown committed
100
    Item **save_args= args;
unknown's avatar
unknown committed
101 102 103

    while ((item=li++))
    {
unknown's avatar
unknown committed
104
      *(save_args++)= item;
unknown's avatar
unknown committed
105 106 107 108 109 110
      with_sum_func|=item->with_sum_func;
    }
  }
  list.empty();					// Fields are used
}

111 112 113 114 115 116
Item_func::Item_func(List<Item> &list)
  :allowed_arg_cols(1)
{
  set_arguments(list);
}

117
Item_func::Item_func(THD *thd, Item_func *item)
118
  :Item_result_field(thd, item),
119 120 121 122 123
   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)
124 125 126 127 128 129 130 131 132 133
{
  if (arg_count)
  {
    if (arg_count <=2)
      args= tmp_arg;
    else
    {
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
	return;
    }
134
    memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
135 136 137
  }
}

unknown's avatar
unknown committed
138 139

/*
140
  Resolve references to table column for a function and its argument
unknown's avatar
unknown committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

  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
156
      used_tables_cache Set to union of the tables used by arguments
unknown's avatar
unknown committed
157 158 159

      str_value.charset If this is a string function, set this to the
			character set for the first argument.
160
			If any argument is binary, this is set to binary
unknown's avatar
unknown committed
161 162 163 164 165 166 167

   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
168 169
  FALSE	ok
  TRUE	Got error.  Stored with my_error().
unknown's avatar
unknown committed
170 171
*/

unknown's avatar
unknown committed
172
bool
173
Item_func::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
174
{
175
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
176
  Item **arg,**arg_end;
177
  uchar buff[STACK_BUFF_ALLOC];			// Max argument in function
178

179
  used_tables_cache= not_null_tables_cache= 0;
unknown's avatar
unknown committed
180 181
  const_item_cache=1;

182 183 184 185 186 187 188 189
  /*
    Use stack limit of STACK_MIN_SIZE * 2 since
    on some platforms a recursive call to fix_fields
    requires more than STACK_MIN_SIZE bytes (e.g. for
    MIPS, it takes about 22kB to make one recursive
    call to Item_func::fix_fields())
  */
  if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff))
unknown's avatar
unknown committed
190
    return TRUE;				// Fatal error if flag is set!
unknown's avatar
unknown committed
191 192 193 194
  if (arg_count)
  {						// Print purify happy
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
    {
unknown's avatar
unknown committed
195
      Item *item;
unknown's avatar
merge  
unknown committed
196 197 198 199
      /*
	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
      */
200
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
unknown's avatar
unknown committed
201
	return TRUE;				/* purecov: inspected */
unknown's avatar
unknown committed
202
      item= *arg;
203 204 205 206 207 208 209 210 211 212 213 214 215 216

      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
217
      if (item->maybe_null)
unknown's avatar
unknown committed
218
	maybe_null=1;
219

unknown's avatar
unknown committed
220
      with_sum_func= with_sum_func || item->with_sum_func;
221 222 223
      used_tables_cache|=     item->used_tables();
      not_null_tables_cache|= item->not_null_tables();
      const_item_cache&=      item->const_item();
224
      with_subselect|=        item->with_subselect;
unknown's avatar
unknown committed
225 226 227
    }
  }
  fix_length_and_dec();
228
  if (thd->is_error()) // An error inside fix_length_and_dec occured
unknown's avatar
unknown committed
229
    return TRUE;
230
  fixed= 1;
unknown's avatar
unknown committed
231
  return FALSE;
unknown's avatar
unknown committed
232 233
}

234 235

bool Item_func::walk(Item_processor processor, bool walk_subquery,
236
                     uchar *argument)
unknown's avatar
unknown committed
237 238 239 240 241 242
{
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
243
      if ((*arg)->walk(processor, walk_subquery, argument))
unknown's avatar
unknown committed
244 245 246 247 248
	return 1;
    }
  }
  return (this->*processor)(argument);
}
249

250 251
void Item_func::traverse_cond(Cond_traverser traverser,
                              void *argument, traverse_order order)
unknown's avatar
unknown committed
252 253 254 255
{
  if (arg_count)
  {
    Item **arg,**arg_end;
256 257 258

    switch (order) {
    case(PREFIX):
unknown's avatar
unknown committed
259
      (*traverser)(this, argument);
260 261 262 263 264 265 266 267 268 269
      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
270
      (*traverser)(this, argument);
unknown's avatar
unknown committed
271 272
    }
  }
273 274
  else
    (*traverser)(this, argument);
unknown's avatar
unknown committed
275 276
}

unknown's avatar
unknown committed
277

unknown's avatar
unknown committed
278 279 280
/**
  Transform an Item_func object with a transformer callback function.

281 282 283
    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
284
    the old item is substituted for a new one.
285
    After this the transformer is applied to the root node
unknown's avatar
unknown committed
286
    of the Item_func object. 
unknown's avatar
unknown committed
287 288 289 290 291 292
  @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
293 294
*/

295
Item *Item_func::transform(Item_transformer transformer, uchar *argument)
296
{
297
  DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
298

299 300 301 302 303
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
unknown's avatar
unknown committed
304
      Item *new_item= (*arg)->transform(transformer, argument);
305 306
      if (!new_item)
	return 0;
307 308 309 310 311 312 313

      /*
        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
314 315
      if (*arg != new_item)
        current_thd->change_item_tree(arg, new_item);
316 317
    }
  }
unknown's avatar
unknown committed
318
  return (this->*transformer)(argument);
319 320 321
}


unknown's avatar
unknown committed
322 323 324 325
/**
  Compile Item_func object with a processor and a transformer
  callback functions.

326 327 328 329 330 331 332 333
    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
334 335 336 337 338 339 340 341 342 343

  @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
344 345
*/

346 347
Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
                         Item_transformer transformer, uchar *arg_t)
348 349 350 351 352 353 354 355 356 357 358 359
{
  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.
      */   
360
      uchar *arg_v= *arg_p;
361 362 363 364 365 366 367 368
      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
369 370 371
/**
  See comments in Item_cmp_func::split_sum_func()
*/
372

373 374
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
                               List<Item> &fields)
unknown's avatar
unknown committed
375
{
unknown's avatar
unknown committed
376 377
  Item **arg, **arg_end;
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
unknown's avatar
unknown committed
378
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
unknown's avatar
unknown committed
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
}


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

400 401 402 403 404 405 406

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


407
void Item_func::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
408 409 410
{
  str->append(func_name());
  str->append('(');
411
  print_args(str, 0, query_type);
412 413 414 415
  str->append(')');
}


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


427
void Item_func::print_op(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
428 429 430 431
{
  str->append('(');
  for (uint i=0 ; i < arg_count-1 ; i++)
  {
432
    args[i]->print(str, query_type);
unknown's avatar
unknown committed
433 434 435 436
    str->append(' ');
    str->append(func_name());
    str->append(' ');
  }
437
  args[arg_count-1]->print(str, query_type);
unknown's avatar
unknown committed
438 439 440
  str->append(')');
}

unknown's avatar
unknown committed
441

442
bool Item_func::eq(const Item *item, bool binary_cmp) const
unknown's avatar
unknown committed
443 444 445 446 447 448 449
{
  /* 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;
450 451 452 453 454 455 456
  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
457 458
    return 0;
  for (uint i=0; i < arg_count ; i++)
459
    if (!args[i]->eq(item_func->args[i], binary_cmp))
unknown's avatar
unknown committed
460 461 462 463
      return 0;
  return 1;
}

464

unknown's avatar
unknown committed
465
Field *Item_func::tmp_table_field(TABLE *table)
466
{
Staale Smedseng's avatar
Staale Smedseng committed
467
  Field *field= NULL;
468

unknown's avatar
unknown committed
469
  switch (result_type()) {
470
  case INT_RESULT:
471 472 473
    if (max_char_length() > MY_INT32_NUM_DECIMAL_DIGITS)
      field= new Field_longlong(max_char_length(), maybe_null, name,
                                unsigned_flag);
474
    else
475 476
      field= new Field_long(max_char_length(), maybe_null, name,
                            unsigned_flag);
477 478
    break;
  case REAL_RESULT:
479
    field= new Field_double(max_char_length(), maybe_null, name, decimals);
480 481
    break;
  case STRING_RESULT:
unknown's avatar
unknown committed
482
    return make_string_field(table);
483
    break;
unknown's avatar
unknown committed
484
  case DECIMAL_RESULT:
485
    field= Field_new_decimal::create_from_item(this);
unknown's avatar
unknown committed
486
    break;
487
  case ROW_RESULT:
unknown's avatar
unknown committed
488
  default:
unknown's avatar
unknown committed
489
    // This case should never be chosen
unknown's avatar
unknown committed
490
    DBUG_ASSERT(0);
unknown's avatar
unknown committed
491
    field= 0;
unknown's avatar
unknown committed
492
    break;
493
  }
unknown's avatar
unknown committed
494 495 496
  if (field)
    field->init(table);
  return field;
497 498
}

unknown's avatar
unknown committed
499

500
bool Item_func::is_expensive_processor(uchar *arg)
501
{
502
  return is_expensive();
503 504 505
}


unknown's avatar
unknown committed
506 507 508
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed);
509 510 511 512
  longlong nr= val_int();
  if (null_value)
    return 0; /* purecov: inspected */
  int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
unknown's avatar
unknown committed
513 514 515
  return decimal_value;
}

516

unknown's avatar
unknown committed
517 518
String *Item_real_func::val_str(String *str)
{
519
  DBUG_ASSERT(fixed == 1);
520
  double nr= val_real();
unknown's avatar
unknown committed
521 522
  if (null_value)
    return 0; /* purecov: inspected */
523
  str->set_real(nr, decimals, collation.collation);
unknown's avatar
unknown committed
524 525 526 527
  return str;
}


528 529 530 531 532 533 534 535 536 537 538
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
539
void Item_func::fix_num_length_and_dec()
unknown's avatar
unknown committed
540
{
541
  uint fl_length= 0;
unknown's avatar
unknown committed
542
  decimals=0;
unknown's avatar
unknown committed
543
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
544 545
  {
    set_if_bigger(decimals,args[i]->decimals);
546 547
    set_if_bigger(fl_length, args[i]->max_length);
  }
unknown's avatar
unknown committed
548
  max_length=float_length(decimals);
549 550 551 552
  if (fl_length > max_length)
  {
    decimals= NOT_FIXED_DEC;
    max_length= float_length(NOT_FIXED_DEC);
unknown's avatar
unknown committed
553
  }
unknown's avatar
unknown committed
554 555 556 557 558 559 560
}


void Item_func_numhybrid::fix_num_length_and_dec()
{}


unknown's avatar
unknown committed
561
/**
unknown's avatar
unknown committed
562
  Set max_length/decimals of function if function is fixed point and
unknown's avatar
unknown committed
563
  result length/precision depends on argument ones.
unknown's avatar
unknown committed
564 565 566 567
*/

void Item_func::count_decimal_length()
{
unknown's avatar
unknown committed
568
  int max_int_part= 0;
unknown's avatar
unknown committed
569
  decimals= 0;
unknown's avatar
unknown committed
570
  unsigned_flag= 1;
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(decimals, args[i]->decimals);
unknown's avatar
unknown committed
574 575
    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
576
  }
unknown's avatar
unknown committed
577
  int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
578 579 580
  fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
                                                               decimals,
                                                               unsigned_flag));
unknown's avatar
unknown committed
581 582 583
}


unknown's avatar
unknown committed
584 585
/**
  Set max_length of if it is maximum length of its arguments.
unknown's avatar
unknown committed
586 587 588
*/

void Item_func::count_only_length()
unknown's avatar
unknown committed
589
{
590
  uint32 char_length= 0;
unknown's avatar
unknown committed
591
  unsigned_flag= 0;
unknown's avatar
unknown committed
592
  for (uint i=0 ; i < arg_count ; i++)
unknown's avatar
unknown committed
593
  {
594
    set_if_bigger(char_length, args[i]->max_char_length());
unknown's avatar
unknown committed
595 596
    set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
  }
597
  fix_char_length(char_length);
unknown's avatar
unknown committed
598 599
}

unknown's avatar
unknown committed
600

unknown's avatar
unknown committed
601
/**
unknown's avatar
unknown committed
602
  Set max_length/decimals of function if function is floating point and
unknown's avatar
unknown committed
603
  result length/precision depends on argument ones.
unknown's avatar
unknown committed
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
*/

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
633 634 635 636
void Item_func::signal_divide_by_null()
{
  THD *thd= current_thd;
  if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
Marc Alff's avatar
Marc Alff committed
637
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_DIVISION_BY_ZERO,
unknown's avatar
unknown committed
638 639 640 641 642
                 ER(ER_DIVISION_BY_ZERO));
  null_value= 1;
}


643
Item *Item_func::get_tmp_table_item(THD *thd)
644
{
645
  if (!with_sum_func && !const_item())
646
    return new Item_field(result_field);
647
  return copy_or_same(thd);
648 649
}

650 651 652 653 654 655 656 657
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
658 659
String *Item_int_func::val_str(String *str)
{
660
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
661 662 663
  longlong nr=val_int();
  if (null_value)
    return 0;
664
  str->set_int(nr, unsigned_flag, collation.collation);
unknown's avatar
unknown committed
665 666 667
  return str;
}

unknown's avatar
unknown committed
668

669 670 671 672 673 674 675 676 677 678 679
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;
680
  thd->thread_specific_used= TRUE;
681
  value= thd->variables.pseudo_thread_id;
682 683 684 685
  return FALSE;
}


unknown's avatar
unknown committed
686
/**
687 688
  Check arguments here to determine result's type for a numeric
  function of two arguments.
689
*/
unknown's avatar
unknown committed
690 691 692

void Item_num_op::find_num_type(void)
{
unknown's avatar
unknown committed
693 694 695 696 697 698 699 700
  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)
701
  {
unknown's avatar
unknown committed
702 703 704 705 706 707 708 709 710
    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();
  }
711
  else
712
  {
713
    DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
unknown's avatar
unknown committed
714
    decimals= 0;
unknown's avatar
unknown committed
715
    hybrid_type=INT_RESULT;
unknown's avatar
unknown committed
716
    result_precision();
717
  }
unknown's avatar
unknown committed
718 719 720 721 722 723
  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
724 725
}

unknown's avatar
unknown committed
726

unknown's avatar
unknown committed
727
/**
728 729 730
  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
731
*/
732

unknown's avatar
unknown committed
733 734 735 736
void Item_func_num1::find_num_type()
{
  DBUG_ENTER("Item_func_num1::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
737
  switch (hybrid_type= args[0]->result_type()) {
unknown's avatar
unknown committed
738
  case INT_RESULT:
739
    unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
740 741 742 743 744 745 746 747 748 749
    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);
750
  }
unknown's avatar
unknown committed
751 752 753 754 755 756
  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
757 758
}

unknown's avatar
unknown committed
759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774

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
775
{
776
  DBUG_ASSERT(fixed == 1);
777
  switch (hybrid_type) {
unknown's avatar
unknown committed
778 779 780 781
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
782
      return 0;                                 // null is set
unknown's avatar
unknown committed
783
    my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
784
    str->set_charset(collation.collation);
unknown's avatar
unknown committed
785 786 787 788 789 790
    my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
    break;
  }
  case INT_RESULT:
  {
    longlong nr= int_op();
unknown's avatar
unknown committed
791 792
    if (null_value)
      return 0; /* purecov: inspected */
793
    str->set_int(nr, unsigned_flag, collation.collation);
unknown's avatar
unknown committed
794
    break;
unknown's avatar
unknown committed
795
  }
unknown's avatar
unknown committed
796
  case REAL_RESULT:
unknown's avatar
unknown committed
797
  {
798
    double nr= real_op();
unknown's avatar
unknown committed
799 800
    if (null_value)
      return 0; /* purecov: inspected */
801
    str->set_real(nr, decimals, collation.collation);
unknown's avatar
unknown committed
802 803
    break;
  }
unknown's avatar
unknown committed
804 805
  case STRING_RESULT:
    return str_op(&str_value);
unknown's avatar
unknown committed
806 807
  default:
    DBUG_ASSERT(0);
unknown's avatar
unknown committed
808 809 810 811 812
  }
  return str;
}


unknown's avatar
unknown committed
813 814 815
double Item_func_numhybrid::val_real()
{
  DBUG_ASSERT(fixed == 1);
816
  switch (hybrid_type) {
unknown's avatar
unknown committed
817 818 819 820
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    double result;
821 822
    if (!(val= decimal_op(&decimal_value)))
      return 0.0;                               // null is set
unknown's avatar
unknown committed
823 824 825 826
    my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
    return result;
  }
  case INT_RESULT:
827 828 829 830
  {
    longlong result= int_op();
    return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
  }
unknown's avatar
unknown committed
831 832
  case REAL_RESULT:
    return real_op();
unknown's avatar
unknown committed
833 834 835 836 837 838 839 840
  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
841 842 843 844 845 846 847 848 849 850
  default:
    DBUG_ASSERT(0);
  }
  return 0.0;
}


longlong Item_func_numhybrid::val_int()
{
  DBUG_ASSERT(fixed == 1);
851
  switch (hybrid_type) {
unknown's avatar
unknown committed
852 853 854 855
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
856
      return 0;                                 // null is set
unknown's avatar
unknown committed
857 858 859 860 861 862 863
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
    return result;
  }
  case INT_RESULT:
    return int_op();
  case REAL_RESULT:
864
    return (longlong) rint(real_op());
unknown's avatar
unknown committed
865 866 867
  case STRING_RESULT:
  {
    int err_not_used;
unknown's avatar
unknown committed
868 869 870 871
    String *res;
    if (!(res= str_op(&str_value)))
      return 0;

872
    char *end= (char*) res->ptr() + res->length();
873
    CHARSET_INFO *cs= res->charset();
unknown's avatar
unknown committed
874
    return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
unknown's avatar
unknown committed
875
  }
unknown's avatar
unknown committed
876 877 878 879 880 881 882 883 884 885 886
  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);
887
  switch (hybrid_type) {
unknown's avatar
unknown committed
888 889 890 891 892 893 894 895 896 897 898
  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:
  {
899
    double result= (double)real_op();
unknown's avatar
unknown committed
900 901 902 903
    double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
    break;
  }
  case STRING_RESULT:
unknown's avatar
unknown committed
904
  {
unknown's avatar
unknown committed
905 906 907 908
    String *res;
    if (!(res= str_op(&str_value)))
      return NULL;

unknown's avatar
unknown committed
909 910 911 912
    str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
                   res->length(), res->charset(), decimal_value);
    break;
  }  
unknown's avatar
unknown committed
913 914 915 916 917 918 919 920
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  return val;
}


921
void Item_func_signed::print(String *str, enum_query_type query_type)
922
{
923
  str->append(STRING_WITH_LEN("cast("));
924
  args[0]->print(str, query_type);
925
  str->append(STRING_WITH_LEN(" as signed)"));
926 927 928 929

}


930 931
longlong Item_func_signed::val_int_from_str(int *error)
{
unknown's avatar
unknown committed
932 933
  char buff[MAX_FIELD_WIDTH], *end, *start;
  uint32 length;
934 935
  String tmp(buff,sizeof(buff), &my_charset_bin), *res;
  longlong value;
936
  CHARSET_INFO *cs;
937 938 939 940 941 942 943 944 945 946 947 948 949

  /*
    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
950 951
  start= (char *)res->ptr();
  length= res->length();
952
  cs= res->charset();
unknown's avatar
unknown committed
953 954

  end= start + length;
955
  value= cs->cset->strtoll10(cs, start, &end, error);
unknown's avatar
unknown committed
956 957 958 959 960
  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);
961 962 963
    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
964 965
                        err_tmp.c_ptr());
  }
966 967 968 969 970 971 972 973 974
  return value;
}


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

975 976
  if (args[0]->cast_to_int_type() != STRING_RESULT ||
      args[0]->result_as_longlong())
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
  {
    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;
}


994
void Item_func_unsigned::print(String *str, enum_query_type query_type)
995
{
996
  str->append(STRING_WITH_LEN("cast("));
997
  args[0]->print(str, query_type);
998
  str->append(STRING_WITH_LEN(" as unsigned)"));
999 1000 1001 1002

}


1003 1004 1005 1006 1007
longlong Item_func_unsigned::val_int()
{
  longlong value;
  int error;

1008 1009 1010 1011 1012
  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);
1013 1014
    else
      value= 0;
1015 1016
    return value;
  }
1017 1018
  else if (args[0]->cast_to_int_type() != STRING_RESULT ||
           args[0]->result_as_longlong())
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033
  {
    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
1034 1035 1036
String *Item_decimal_typecast::val_str(String *str)
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1037 1038
  if (null_value)
    return NULL;
unknown's avatar
unknown committed
1039
  my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str);
unknown's avatar
unknown committed
1040 1041 1042 1043 1044 1045 1046 1047
  return str;
}


double Item_decimal_typecast::val_real()
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
  double res;
1048 1049
  if (null_value)
    return 0.0;
unknown's avatar
unknown committed
1050 1051 1052 1053 1054 1055 1056 1057 1058
  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;
1059 1060
  if (null_value)
    return 0;
unknown's avatar
unknown committed
1061 1062 1063 1064 1065 1066 1067 1068
  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);
1069
  bool sign;
unknown's avatar
unknown committed
1070 1071
  uint precision;

1072 1073
  if ((null_value= args[0]->null_value))
    return NULL;
unknown's avatar
unknown committed
1074
  my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
1075 1076 1077 1078 1079 1080 1081 1082 1083
  sign= dec->sign();
  if (unsigned_flag)
  {
    if (sign)
    {
      my_decimal_set_zero(dec);
      goto err;
    }
  }
unknown's avatar
unknown committed
1084 1085 1086
  precision= my_decimal_length_to_precision(max_length,
                                            decimals, unsigned_flag);
  if (precision - decimals < (uint) my_decimal_intg(dec))
1087
  {
unknown's avatar
unknown committed
1088
    max_my_decimal(dec, precision, decimals);
1089 1090 1091 1092 1093 1094
    dec->sign(sign);
    goto err;
  }
  return dec;

err:
Marc Alff's avatar
Marc Alff committed
1095
  push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1096 1097
                      ER_WARN_DATA_OUT_OF_RANGE,
                      ER(ER_WARN_DATA_OUT_OF_RANGE),
1098
                      name, 1L);
unknown's avatar
unknown committed
1099 1100 1101 1102
  return dec;
}


1103
void Item_decimal_typecast::print(String *str, enum_query_type query_type)
1104
{
1105 1106 1107 1108 1109
  char len_buf[20*3 + 1];
  char *end;

  uint precision= my_decimal_length_to_precision(max_length, decimals,
                                                 unsigned_flag);
1110
  str->append(STRING_WITH_LEN("cast("));
1111
  args[0]->print(str, query_type);
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
  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(')');
1124 1125 1126
}


unknown's avatar
unknown committed
1127
double Item_func_plus::real_op()
unknown's avatar
unknown committed
1128
{
1129
  double value= args[0]->val_real() + args[1]->val_real();
unknown's avatar
unknown committed
1130 1131
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
1132
  return check_float_overflow(value);
unknown's avatar
unknown committed
1133 1134
}

unknown's avatar
unknown committed
1135 1136

longlong Item_func_plus::int_op()
unknown's avatar
unknown committed
1137
{
1138 1139 1140 1141 1142 1143
  longlong val0= args[0]->val_int();
  longlong val1= args[1]->val_int();
  longlong res= val0 + val1;
  bool     res_unsigned= FALSE;

  if ((null_value= args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1144
    return 0;
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193

  /*
    First check whether the result can be represented as a
    (bool unsigned_flag, longlong value) pair, then check if it is compatible
    with this Item's unsigned_flag by calling check_integer_overflow().
  */
  if (args[0]->unsigned_flag)
  {
    if (args[1]->unsigned_flag || val1 >= 0)
    {
      if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
        goto err;
      res_unsigned= TRUE;
    }
    else
    {
      /* val1 is negative */
      if ((ulonglong) val0 > (ulonglong) LONGLONG_MAX)
        res_unsigned= TRUE;
    }
  }
  else
  {
    if (args[1]->unsigned_flag)
    {
      if (val0 >= 0)
      {
        if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
          goto err;
        res_unsigned= TRUE;
      }
      else
      {
        if ((ulonglong) val1 > (ulonglong) LONGLONG_MAX)
          res_unsigned= TRUE;
      }
    }
    else
    {
      if (val0 >=0 && val1 >= 0)
        res_unsigned= TRUE;
      else if (val0 < 0 && val1 < 0 && res >= 0)
        goto err;
    }
  }
  return check_integer_overflow(res, res_unsigned);

err:
  return raise_integer_overflow();
unknown's avatar
unknown committed
1194 1195 1196
}


unknown's avatar
unknown committed
1197 1198
/**
  Calculate plus of two decimals.
1199

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

unknown's avatar
unknown committed
1202 1203 1204 1205
  @retval
    0  Value was NULL;  In this case null_value is set
  @retval
    \# Value of operation as a decimal
1206 1207
*/

unknown's avatar
unknown committed
1208 1209
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
{
1210 1211 1212
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1213 1214
  if ((null_value= args[0]->null_value))
    return 0;
1215
  val2= args[1]->val_decimal(&value2);
1216
  if (!(null_value= (args[1]->null_value ||
1217 1218 1219 1220
                     check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR &
                                                           ~E_DEC_OVERFLOW,
                                                           decimal_value,
                                                           val1, val2)) > 3)))
1221 1222
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1223 1224
}

unknown's avatar
unknown committed
1225
/**
unknown's avatar
unknown committed
1226 1227 1228 1229 1230
  Set precision of results for additive operations (+ and -)
*/
void Item_func_additive_op::result_precision()
{
  decimals= max(args[0]->decimals, args[1]->decimals);
1231 1232
  int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
  int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
1233
  int precision= max(arg1_int, arg2_int) + 1 + decimals;
unknown's avatar
unknown committed
1234 1235 1236 1237 1238 1239

  /* 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;
1240 1241
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1242 1243
}

1244

unknown's avatar
unknown committed
1245
/**
1246 1247 1248 1249 1250 1251 1252 1253
  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 &&
1254
      (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
1255 1256 1257 1258
    unsigned_flag=0;
}


unknown's avatar
unknown committed
1259
double Item_func_minus::real_op()
unknown's avatar
unknown committed
1260
{
1261
  double value= args[0]->val_real() - args[1]->val_real();
unknown's avatar
unknown committed
1262 1263
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
1264
  return check_float_overflow(value);
unknown's avatar
unknown committed
1265 1266
}

unknown's avatar
unknown committed
1267 1268

longlong Item_func_minus::int_op()
unknown's avatar
unknown committed
1269
{
1270 1271 1272 1273 1274 1275
  longlong val0= args[0]->val_int();
  longlong val1= args[1]->val_int();
  longlong res= val0 - val1;
  bool     res_unsigned= FALSE;

  if ((null_value= args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1276
    return 0;
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328

  /*
    First check whether the result can be represented as a
    (bool unsigned_flag, longlong value) pair, then check if it is compatible
    with this Item's unsigned_flag by calling check_integer_overflow().
  */
  if (args[0]->unsigned_flag)
  {
    if (args[1]->unsigned_flag)
    {
      if ((ulonglong) val0 < (ulonglong) val1)
      {
        if (res >= 0)
          goto err;
      }
      else
        res_unsigned= TRUE;
    }
    else
    {
      if (val1 >= 0)
      {
        if ((ulonglong) val0 > (ulonglong) val1)
          res_unsigned= TRUE;
      }
      else
      {
        if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) -val1))
          goto err;
        res_unsigned= TRUE;
      }
    }
  }
  else
  {
    if (args[1]->unsigned_flag)
    {
      if ((ulonglong) (val0 - LONGLONG_MIN) < (ulonglong) val1)
        goto err;
    }
    else
    {
      if (val0 > 0 && val1 < 0)
        res_unsigned= TRUE;
      else if (val0 < 0 && val1 > 0 && res >= 0)
        goto err;
    }
  }
  return check_integer_overflow(res, res_unsigned);

err:
  return raise_integer_overflow();
unknown's avatar
unknown committed
1329 1330
}

1331

unknown's avatar
unknown committed
1332 1333 1334
/**
  See Item_func_plus::decimal_op for comments.
*/
1335

unknown's avatar
unknown committed
1336 1337
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
{
1338 1339 1340 1341
  my_decimal value1, *val1;
  my_decimal value2, *val2= 

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1342 1343
  if ((null_value= args[0]->null_value))
    return 0;
1344
  val2= args[1]->val_decimal(&value2);
1345
  if (!(null_value= (args[1]->null_value ||
1346 1347 1348 1349
                     (check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR &
                                                            ~E_DEC_OVERFLOW,
                                                            decimal_value, val1,
                                                            val2)) > 3))))
1350 1351
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1352 1353
}

1354

unknown's avatar
unknown committed
1355
double Item_func_mul::real_op()
unknown's avatar
unknown committed
1356
{
1357
  DBUG_ASSERT(fixed == 1);
1358
  double value= args[0]->val_real() * args[1]->val_real();
unknown's avatar
unknown committed
1359
  if ((null_value=args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1360
    return 0.0;
1361
  return check_float_overflow(value);
unknown's avatar
unknown committed
1362 1363
}

unknown's avatar
unknown committed
1364 1365

longlong Item_func_mul::int_op()
unknown's avatar
unknown committed
1366
{
1367
  DBUG_ASSERT(fixed == 1);
1368 1369 1370 1371 1372 1373 1374 1375 1376
  longlong a= args[0]->val_int();
  longlong b= args[1]->val_int();
  longlong res;
  ulonglong res0, res1;
  ulong a0, a1, b0, b1;
  bool     res_unsigned= FALSE;
  bool     a_negative= FALSE, b_negative= FALSE;

  if ((null_value= args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1377
    return 0;
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440

  /*
    First check whether the result can be represented as a
    (bool unsigned_flag, longlong value) pair, then check if it is compatible
    with this Item's unsigned_flag by calling check_integer_overflow().

    Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then
    a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 +
            + (a1 * b0 + a0 * b1) * 2^32 + a0 * b0;
    We can determine if the above sum overflows the ulonglong range by
    sequentially checking the following conditions:
    1. If both a1 and b1 are non-zero.
    2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX.
    3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than
    ULONGLONG_MAX.

    Since we also have to take the unsigned_flag for a and b into account,
    it is easier to first work with absolute values and set the
    correct sign later.
  */
  if (!args[0]->unsigned_flag && a < 0)
  {
    a_negative= TRUE;
    a= -a;
  }
  if (!args[1]->unsigned_flag && b < 0)
  {
    b_negative= TRUE;
    b= -b;
  }

  a0= 0xFFFFFFFFUL & a;
  a1= ((ulonglong) a) >> 32;
  b0= 0xFFFFFFFFUL & b;
  b1= ((ulonglong) b) >> 32;

  if (a1 && b1)
    goto err;

  res1= (ulonglong) a1 * b0 + (ulonglong) a0 * b1;
  if (res1 > 0xFFFFFFFFUL)
    goto err;

  res1= res1 << 32;
  res0= (ulonglong) a0 * b0;

  if (test_if_sum_overflows_ull(res1, res0))
    goto err;
  res= res1 + res0;

  if (a_negative != b_negative)
  {
    if ((ulonglong) res > (ulonglong) LONGLONG_MIN + 1)
      goto err;
    res= -res;
  }
  else
    res_unsigned= TRUE;

  return check_integer_overflow(res, res_unsigned);

err:
  return raise_integer_overflow();
unknown's avatar
unknown committed
1441 1442 1443
}


unknown's avatar
unknown committed
1444
/** See Item_func_plus::decimal_op for comments. */
1445

unknown's avatar
unknown committed
1446 1447
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
{
1448 1449 1450
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1451 1452
  if ((null_value= args[0]->null_value))
    return 0;
1453
  val2= args[1]->val_decimal(&value2);
1454
  if (!(null_value= (args[1]->null_value ||
1455 1456 1457 1458
                     (check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR &
                                                            ~E_DEC_OVERFLOW,
                                                            decimal_value, val1,
                                                            val2)) > 3))))
1459 1460
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
1461 1462 1463
}


unknown's avatar
unknown committed
1464 1465
void Item_func_mul::result_precision()
{
unknown's avatar
unknown committed
1466 1467 1468 1469 1470 1471
  /* 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);
1472 1473
  uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
  uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
1474 1475
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1476 1477 1478 1479
}


double Item_func_div::real_op()
unknown's avatar
unknown committed
1480
{
1481
  DBUG_ASSERT(fixed == 1);
1482 1483
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
unknown's avatar
unknown committed
1484 1485 1486 1487 1488
  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
1489
    return 0.0;
unknown's avatar
unknown committed
1490
  }
1491
  return check_float_overflow(value/val2);
unknown's avatar
unknown committed
1492 1493
}

unknown's avatar
unknown committed
1494

unknown's avatar
unknown committed
1495
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1496
{
1497 1498
  my_decimal value1, *val1;
  my_decimal value2, *val2;
unknown's avatar
unknown committed
1499
  int err;
1500 1501

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1502 1503
  if ((null_value= args[0]->null_value))
    return 0;
1504
  val2= args[1]->val_decimal(&value2);
unknown's avatar
unknown committed
1505 1506
  if ((null_value= args[1]->null_value))
    return 0;
1507 1508 1509 1510 1511 1512
  if ((err= check_decimal_overflow(my_decimal_div(E_DEC_FATAL_ERROR &
                                                  ~E_DEC_OVERFLOW &
                                                  ~E_DEC_DIV_ZERO,
                                                  decimal_value,
                                                  val1, val2,
                                                  prec_increment))) > 3)
unknown's avatar
unknown committed
1513 1514 1515 1516
  {
    if (err == E_DEC_DIV_ZERO)
      signal_divide_by_null();
    null_value= 1;
unknown's avatar
unknown committed
1517
    return 0;
1518
  }
unknown's avatar
unknown committed
1519
  return decimal_value;
unknown's avatar
unknown committed
1520 1521 1522 1523 1524
}


void Item_func_div::result_precision()
{
1525 1526 1527 1528
  uint precision=min(args[0]->decimal_precision() + 
                     args[1]->decimals + prec_increment,
                     DECIMAL_MAX_PRECISION);

unknown's avatar
unknown committed
1529 1530 1531 1532 1533 1534
  /* 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);
1535 1536
  max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
                                                           unsigned_flag);
unknown's avatar
unknown committed
1537 1538
}

unknown's avatar
unknown committed
1539

unknown's avatar
unknown committed
1540 1541
void Item_func_div::fix_length_and_dec()
{
unknown's avatar
unknown committed
1542
  DBUG_ENTER("Item_func_div::fix_length_and_dec");
unknown's avatar
unknown committed
1543
  prec_increment= current_thd->variables.div_precincrement;
unknown's avatar
unknown committed
1544
  Item_num_op::fix_length_and_dec();
1545
  switch(hybrid_type) {
unknown's avatar
unknown committed
1546 1547
  case REAL_RESULT:
  {
unknown's avatar
unknown committed
1548
    decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
unknown's avatar
unknown committed
1549 1550
    set_if_smaller(decimals, NOT_FIXED_DEC);
    uint tmp=float_length(decimals);
1551 1552 1553 1554 1555 1556 1557
    if (decimals == NOT_FIXED_DEC)
      max_length= tmp;
    else
    {
      max_length=args[0]->max_length - args[0]->decimals + decimals;
      set_if_smaller(max_length,tmp);
    }
unknown's avatar
unknown committed
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572
    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
1573 1574
}

1575 1576 1577 1578

/* Integer division */
longlong Item_func_int_div::val_int()
{
1579
  DBUG_ASSERT(fixed == 1);
1580 1581 1582 1583 1584 1585 1586 1587

  /*
    Perform division using DECIMAL math if either of the operands has a
    non-integer type
  */
  if (args[0]->result_type() != INT_RESULT ||
      args[1]->result_type() != INT_RESULT)
  {
1588
    my_decimal tmp;
1589 1590
    my_decimal *val0p= args[0]->val_decimal(&tmp);
    if ((null_value= args[0]->null_value))
1591
      return 0;
1592 1593 1594 1595 1596 1597
    my_decimal val0= *val0p;

    my_decimal *val1p= args[1]->val_decimal(&tmp);
    if ((null_value= args[1]->null_value))
      return 0;
    my_decimal val1= *val1p;
1598

1599
    int err;
1600
    if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp,
1601
                             &val0, &val1, 0)) > 3)
1602 1603 1604 1605 1606 1607
    {
      if (err == E_DEC_DIV_ZERO)
        signal_divide_by_null();
      return 0;
    }

1608 1609 1610 1611 1612
    my_decimal truncated;
    const bool do_truncate= true;
    if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated))
      DBUG_ASSERT(false);

1613
    longlong res;
1614
    if (my_decimal2int(E_DEC_FATAL_ERROR, &truncated, unsigned_flag, &res) &
1615
        E_DEC_OVERFLOW)
1616
      raise_integer_overflow();
1617 1618 1619
    return res;
  }
  
1620 1621 1622 1623
  longlong val0=args[0]->val_int();
  longlong val1=args[1]->val_int();
  bool val0_negative, val1_negative, res_negative;
  ulonglong uval0, uval1, res;
1624
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
1625
    return 0;
1626
  if (val1 == 0)
unknown's avatar
unknown committed
1627 1628
  {
    signal_divide_by_null();
1629
    return 0;
unknown's avatar
unknown committed
1630
  }
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644

  val0_negative= !args[0]->unsigned_flag && val0 < 0;
  val1_negative= !args[1]->unsigned_flag && val1 < 0;
  res_negative= val0_negative != val1_negative;
  uval0= (ulonglong) (val0_negative ? -val0 : val0);
  uval1= (ulonglong) (val1_negative ? -val1 : val1);
  res= uval0 / uval1;
  if (res_negative)
  {
    if (res > (ulonglong) LONGLONG_MAX)
      return raise_integer_overflow();
    res= (ulonglong) (-(longlong) res);
  }
  return check_integer_overflow(res, !res_negative);
1645 1646 1647 1648 1649
}


void Item_func_int_div::fix_length_and_dec()
{
1650 1651 1652 1653 1654
  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);
1655
  maybe_null=1;
unknown's avatar
unknown committed
1656
  unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
1657 1658 1659
}


unknown's avatar
unknown committed
1660 1661 1662
longlong Item_func_mod::int_op()
{
  DBUG_ASSERT(fixed == 1);
1663 1664 1665 1666 1667
  longlong val0= args[0]->val_int();
  longlong val1= args[1]->val_int();
  bool val0_negative, val1_negative;
  ulonglong uval0, uval1;
  ulonglong res;
1668

unknown's avatar
unknown committed
1669 1670
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0; /* purecov: inspected */
1671
  if (val1 == 0)
unknown's avatar
unknown committed
1672 1673 1674 1675
  {
    signal_divide_by_null();
    return 0;
  }
1676

1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
  /*
    '%' is calculated by integer division internally. Since dividing
    LONGLONG_MIN by -1 generates SIGFPE, we calculate using unsigned values and
    then adjust the sign appropriately.
  */
  val0_negative= !args[0]->unsigned_flag && val0 < 0;
  val1_negative= !args[1]->unsigned_flag && val1 < 0;
  uval0= (ulonglong) (val0_negative ? -val0 : val0);
  uval1= (ulonglong) (val1_negative ? -val1 : val1);
  res= uval0 % uval1;
  return check_integer_overflow(val0_negative ? -(longlong) res : res,
                                !val0_negative);
unknown's avatar
unknown committed
1689 1690 1691
}

double Item_func_mod::real_op()
unknown's avatar
unknown committed
1692
{
1693
  DBUG_ASSERT(fixed == 1);
1694 1695
  double value= args[0]->val_real();
  double val2=  args[1]->val_real();
unknown's avatar
unknown committed
1696
  if ((null_value= args[0]->null_value || args[1]->null_value))
unknown's avatar
unknown committed
1697
    return 0.0; /* purecov: inspected */
unknown's avatar
unknown committed
1698 1699 1700 1701 1702
  if (val2 == 0.0)
  {
    signal_divide_by_null();
    return 0.0;
  }
unknown's avatar
unknown committed
1703 1704 1705
  return fmod(value,val2);
}

unknown's avatar
unknown committed
1706 1707

my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1708
{
1709 1710 1711 1712
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
unknown's avatar
unknown committed
1713 1714
  if ((null_value= args[0]->null_value))
    return 0;
1715
  val2= args[1]->val_decimal(&value2);
unknown's avatar
unknown committed
1716 1717 1718
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1719
                         val1, val2)) {
unknown's avatar
unknown committed
1720 1721 1722 1723
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
unknown's avatar
unknown committed
1724
    signal_divide_by_null();
unknown's avatar
unknown committed
1725
  default:
1726
    null_value= 1;
unknown's avatar
unknown committed
1727 1728
    return 0;
  }
unknown's avatar
unknown committed
1729 1730
}

unknown's avatar
unknown committed
1731 1732

void Item_func_mod::result_precision()
unknown's avatar
unknown committed
1733
{
unknown's avatar
unknown committed
1734 1735
  decimals= max(args[0]->decimals, args[1]->decimals);
  max_length= max(args[0]->max_length, args[1]->max_length);
unknown's avatar
unknown committed
1736 1737 1738 1739 1740
}


void Item_func_mod::fix_length_and_dec()
{
1741
  Item_num_op::fix_length_and_dec();
1742
  maybe_null= 1;
1743
  unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
1744 1745 1746
}


unknown's avatar
unknown committed
1747
double Item_func_neg::real_op()
unknown's avatar
unknown committed
1748
{
1749
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1750
  null_value= args[0]->null_value;
unknown's avatar
unknown committed
1751 1752 1753
  return -value;
}

unknown's avatar
unknown committed
1754

unknown's avatar
unknown committed
1755
longlong Item_func_neg::int_op()
unknown's avatar
unknown committed
1756
{
unknown's avatar
unknown committed
1757
  longlong value= args[0]->val_int();
1758 1759 1760 1761 1762 1763
  if ((null_value= args[0]->null_value))
    return 0;
  if (args[0]->unsigned_flag &&
      (ulonglong) value > (ulonglong) LONGLONG_MAX + 1)
    return raise_integer_overflow();
  return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
unknown's avatar
unknown committed
1764 1765
}

unknown's avatar
unknown committed
1766

unknown's avatar
unknown committed
1767
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1768
{
unknown's avatar
unknown committed
1769 1770 1771 1772 1773
  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);
1774
    return decimal_value;
unknown's avatar
unknown committed
1775
  }
1776
  return 0;
unknown's avatar
unknown committed
1777 1778
}

1779

unknown's avatar
unknown committed
1780
void Item_func_neg::fix_num_length_and_dec()
unknown's avatar
unknown committed
1781
{
unknown's avatar
unknown committed
1782 1783 1784
  decimals= args[0]->decimals;
  /* 1 add because sign can appear */
  max_length= args[0]->max_length + 1;
unknown's avatar
unknown committed
1785 1786
}

unknown's avatar
unknown committed
1787

1788
void Item_func_neg::fix_length_and_dec()
unknown's avatar
unknown committed
1789
{
1790
  DBUG_ENTER("Item_func_neg::fix_length_and_dec");
unknown's avatar
unknown committed
1791
  Item_func_num1::fix_length_and_dec();
1792 1793 1794 1795

  /*
    If this is in integer context keep the context as integer if possible
    (This is how multiplication and other integer functions works)
1796 1797
    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.
1798
  */
unknown's avatar
unknown committed
1799
  if (hybrid_type == INT_RESULT && args[0]->const_item())
unknown's avatar
unknown committed
1800
  {
unknown's avatar
unknown committed
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
    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
1813
  }
unknown's avatar
unknown committed
1814
  unsigned_flag= 0;
unknown's avatar
unknown committed
1815
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1816 1817
}

unknown's avatar
unknown committed
1818

unknown's avatar
unknown committed
1819
double Item_func_abs::real_op()
unknown's avatar
unknown committed
1820
{
1821
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1822
  null_value= args[0]->null_value;
unknown's avatar
unknown committed
1823 1824 1825
  return fabs(value);
}

unknown's avatar
unknown committed
1826

unknown's avatar
unknown committed
1827
longlong Item_func_abs::int_op()
unknown's avatar
unknown committed
1828
{
unknown's avatar
unknown committed
1829
  longlong value= args[0]->val_int();
1830 1831
  if ((null_value= args[0]->null_value))
    return 0;
1832 1833 1834 1835 1836 1837
  if (unsigned_flag)
    return value;
  /* -LONGLONG_MIN = LONGLONG_MAX + 1 => outside of signed longlong range */
  if (value == LONGLONG_MIN)
    return raise_integer_overflow();
  return (value >= 0) ? value : -value;
unknown's avatar
unknown committed
1838 1839
}

unknown's avatar
unknown committed
1840

unknown's avatar
unknown committed
1841
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
unknown's avatar
unknown committed
1842
{
unknown's avatar
unknown committed
1843 1844
  my_decimal val, *value= args[0]->val_decimal(&val);
  if (!(null_value= args[0]->null_value))
unknown's avatar
unknown committed
1845
  {
unknown's avatar
unknown committed
1846 1847 1848
    my_decimal2decimal(value, decimal_value);
    if (decimal_value->sign())
      my_decimal_neg(decimal_value);
1849
    return decimal_value;
unknown's avatar
unknown committed
1850
  }
1851
  return 0;
unknown's avatar
unknown committed
1852 1853 1854 1855 1856 1857
}


void Item_func_abs::fix_length_and_dec()
{
  Item_func_num1::fix_length_and_dec();
1858
  unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
1859 1860
}

unknown's avatar
unknown committed
1861

unknown's avatar
unknown committed
1862
/** Gateway to natural LOG function. */
1863
double Item_func_ln::val_real()
1864
{
1865
  DBUG_ASSERT(fixed == 1);
1866
  double value= args[0]->val_real();
1867
  if ((null_value= args[0]->null_value))
1868
    return 0.0;
1869
  if (value <= 0.0)
1870 1871
  {
    signal_divide_by_null();
1872
    return 0.0;
1873
  }
1874 1875 1876
  return log(value);
}

unknown's avatar
unknown committed
1877 1878 1879 1880 1881
/** 
  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.
1882
*/ 
1883
double Item_func_log::val_real()
unknown's avatar
unknown committed
1884
{
1885
  DBUG_ASSERT(fixed == 1);
1886
  double value= args[0]->val_real();
1887
  if ((null_value= args[0]->null_value))
1888
    return 0.0;
1889
  if (value <= 0.0)
1890 1891 1892 1893
  {
    signal_divide_by_null();
    return 0.0;
  }
1894 1895
  if (arg_count == 2)
  {
1896
    double value2= args[1]->val_real();
1897
    if ((null_value= args[1]->null_value))
1898
      return 0.0;
1899
    if (value2 <= 0.0 || value == 1.0)
1900 1901 1902 1903
    {
      signal_divide_by_null();
      return 0.0;
    }
1904 1905
    return log(value2) / log(value);
  }
unknown's avatar
unknown committed
1906 1907 1908
  return log(value);
}

1909
double Item_func_log2::val_real()
1910
{
1911
  DBUG_ASSERT(fixed == 1);
1912
  double value= args[0]->val_real();
1913 1914

  if ((null_value=args[0]->null_value))
1915
    return 0.0;
1916
  if (value <= 0.0)
1917 1918 1919 1920
  {
    signal_divide_by_null();
    return 0.0;
  }
1921
  return log(value) / M_LN2;
1922 1923
}

1924
double Item_func_log10::val_real()
unknown's avatar
unknown committed
1925
{
1926
  DBUG_ASSERT(fixed == 1);
1927
  double value= args[0]->val_real();
1928
  if ((null_value= args[0]->null_value))
1929
    return 0.0;
1930
  if (value <= 0.0)
1931 1932 1933 1934
  {
    signal_divide_by_null();
    return 0.0;
  }
unknown's avatar
unknown committed
1935 1936 1937
  return log10(value);
}

1938
double Item_func_exp::val_real()
unknown's avatar
unknown committed
1939
{
1940
  DBUG_ASSERT(fixed == 1);
1941
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1942 1943
  if ((null_value=args[0]->null_value))
    return 0.0; /* purecov: inspected */
1944
  return check_float_overflow(exp(value));
unknown's avatar
unknown committed
1945 1946
}

1947
double Item_func_sqrt::val_real()
unknown's avatar
unknown committed
1948
{
1949
  DBUG_ASSERT(fixed == 1);
1950
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1951 1952 1953 1954 1955
  if ((null_value=(args[0]->null_value || value < 0)))
    return 0.0; /* purecov: inspected */
  return sqrt(value);
}

1956
double Item_func_pow::val_real()
unknown's avatar
unknown committed
1957
{
1958
  DBUG_ASSERT(fixed == 1);
1959 1960
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
unknown's avatar
unknown committed
1961 1962
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
    return 0.0; /* purecov: inspected */
1963
  return check_float_overflow(pow(value,val2));
unknown's avatar
unknown committed
1964 1965 1966 1967
}

// Trigonometric functions

1968
double Item_func_acos::val_real()
unknown's avatar
unknown committed
1969
{
1970
  DBUG_ASSERT(fixed == 1);
1971 1972
  /* One can use this to defer SELECT processing. */
  DEBUG_SYNC(current_thd, "before_acos_function");
unknown's avatar
unknown committed
1973
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1974
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
1975 1976
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
1977
  return acos(value);
unknown's avatar
unknown committed
1978 1979
}

1980
double Item_func_asin::val_real()
unknown's avatar
unknown committed
1981
{
1982
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1983
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1984
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
1985 1986
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
1987
  return asin(value);
unknown's avatar
unknown committed
1988 1989
}

1990
double Item_func_atan::val_real()
unknown's avatar
unknown committed
1991
{
1992
  DBUG_ASSERT(fixed == 1);
1993
  double value= args[0]->val_real();
unknown's avatar
unknown committed
1994 1995 1996 1997
  if ((null_value=args[0]->null_value))
    return 0.0;
  if (arg_count == 2)
  {
1998
    double val2= args[1]->val_real();
unknown's avatar
unknown committed
1999 2000
    if ((null_value=args[1]->null_value))
      return 0.0;
2001
    return check_float_overflow(atan2(value,val2));
unknown's avatar
unknown committed
2002
  }
2003
  return atan(value);
unknown's avatar
unknown committed
2004 2005
}

2006
double Item_func_cos::val_real()
unknown's avatar
unknown committed
2007
{
2008
  DBUG_ASSERT(fixed == 1);
2009
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2010 2011
  if ((null_value=args[0]->null_value))
    return 0.0;
2012
  return cos(value);
unknown's avatar
unknown committed
2013 2014
}

2015
double Item_func_sin::val_real()
unknown's avatar
unknown committed
2016
{
2017
  DBUG_ASSERT(fixed == 1);
2018
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2019 2020
  if ((null_value=args[0]->null_value))
    return 0.0;
2021
  return sin(value);
unknown's avatar
unknown committed
2022 2023
}

2024
double Item_func_tan::val_real()
unknown's avatar
unknown committed
2025
{
2026
  DBUG_ASSERT(fixed == 1);
2027
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2028 2029
  if ((null_value=args[0]->null_value))
    return 0.0;
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040
  return check_float_overflow(tan(value));
}


double Item_func_cot::val_real()
{
  DBUG_ASSERT(fixed == 1);
  double value= args[0]->val_real();
  if ((null_value=args[0]->null_value))
    return 0.0;
  return check_float_overflow(1.0 / tan(value));
unknown's avatar
unknown committed
2041 2042 2043 2044 2045 2046 2047 2048
}


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


longlong Item_func_shift_left::val_int()
{
2049
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
  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()
{
2064
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
  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()
{
2080
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
  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
2098
void Item_func_int_val::fix_num_length_and_dec()
unknown's avatar
unknown committed
2099
{
2100 2101
  ulonglong tmp_max_length= (ulonglong ) args[0]->max_length - 
    (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
Sergey Glukhov's avatar
Sergey Glukhov committed
2102 2103
  max_length= tmp_max_length > (ulonglong) 4294967295U ?
    (uint32) 4294967295U : (uint32) tmp_max_length;
unknown's avatar
unknown committed
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152
  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()
{
2153 2154 2155 2156 2157 2158 2159 2160 2161
  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;
2162
    if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
2163 2164 2165 2166 2167 2168
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
    else
      result= 0;
    break;
  }
  default:
2169
    result= (longlong)Item_func_ceiling::real_op();
2170 2171
  };
  return result;
unknown's avatar
unknown committed
2172 2173
}

unknown's avatar
unknown committed
2174 2175

double Item_func_ceiling::real_op()
unknown's avatar
unknown committed
2176
{
unknown's avatar
unknown committed
2177 2178 2179 2180
  /*
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
    bug)
  */
2181
  volatile double value= args[0]->val_real();
unknown's avatar
unknown committed
2182 2183 2184 2185 2186 2187
  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
2188
{
unknown's avatar
unknown committed
2189
  my_decimal val, *value= args[0]->val_decimal(&val);
2190 2191 2192 2193 2194
  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
2195 2196 2197 2198 2199
}


longlong Item_func_floor::int_op()
{
2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
  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
2219 2220
}

unknown's avatar
unknown committed
2221 2222

double Item_func_floor::real_op()
unknown's avatar
unknown committed
2223
{
unknown's avatar
unknown committed
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
  /*
    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);
2237 2238 2239 2240 2241
  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
2242 2243 2244
}


unknown's avatar
unknown committed
2245
void Item_func_round::fix_length_and_dec()
unknown's avatar
unknown committed
2246
{
2247 2248 2249 2250
  int      decimals_to_set;
  longlong val1;
  bool     val1_unsigned;
  
unknown's avatar
unknown committed
2251 2252
  unsigned_flag= args[0]->unsigned_flag;
  if (!args[1]->const_item())
unknown's avatar
unknown committed
2253
  {
unknown's avatar
unknown committed
2254
    decimals= args[0]->decimals;
2255
    max_length= float_length(decimals);
2256 2257 2258 2259 2260 2261 2262
    if (args[0]->result_type() == DECIMAL_RESULT)
    {
      max_length++;
      hybrid_type= DECIMAL_RESULT;
    }
    else
      hybrid_type= REAL_RESULT;
unknown's avatar
unknown committed
2263 2264
    return;
  }
2265 2266

  val1= args[1]->val_int();
2267 2268 2269
  if ((null_value= args[1]->is_null()))
    return;

2270 2271 2272 2273 2274 2275
  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
2276 2277 2278
  if (args[0]->decimals == NOT_FIXED_DEC)
  {
    decimals= min(decimals_to_set, NOT_FIXED_DEC);
2279
    max_length= float_length(decimals);
unknown's avatar
unknown committed
2280 2281 2282 2283
    hybrid_type= REAL_RESULT;
    return;
  }
  
unknown's avatar
unknown committed
2284
  switch (args[0]->result_type()) {
unknown's avatar
unknown committed
2285 2286 2287 2288 2289 2290 2291
  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:
2292
    if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
unknown's avatar
unknown committed
2293
    {
2294
      int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
unknown's avatar
unknown committed
2295
      max_length= args[0]->max_length + length_can_increase;
unknown's avatar
unknown committed
2296 2297 2298 2299 2300
      /* Here we can keep INT_RESULT */
      hybrid_type= INT_RESULT;
      decimals= 0;
      break;
    }
unknown's avatar
unknown committed
2301
    /* fall through */
unknown's avatar
unknown committed
2302 2303 2304
  case DECIMAL_RESULT:
  {
    hybrid_type= DECIMAL_RESULT;
2305
    decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
unknown's avatar
unknown committed
2306 2307
    int decimals_delta= args[0]->decimals - decimals_to_set;
    int precision= args[0]->decimal_precision();
2308 2309 2310
    int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;

    precision-= decimals_delta - length_increase;
2311
    decimals= min(decimals_to_set, DECIMAL_MAX_SCALE);
2312 2313 2314
    max_length= my_decimal_precision_to_length_no_truncation(precision,
                                                             decimals,
                                                             unsigned_flag);
unknown's avatar
unknown committed
2315 2316 2317 2318
    break;
  }
  default:
    DBUG_ASSERT(0); /* This result type isn't handled */
unknown's avatar
unknown committed
2319 2320 2321
  }
}

2322 2323
double my_double_round(double value, longlong dec, bool dec_unsigned,
                       bool truncate)
unknown's avatar
unknown committed
2324
{
2325
  double tmp;
2326 2327
  bool dec_negative= (dec < 0) && !dec_unsigned;
  ulonglong abs_dec= dec_negative ? -dec : dec;
2328 2329 2330
  /*
    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
2331
    Tagging with volatile is no guarantee, it may still be optimized away...
2332 2333
  */
  volatile double tmp2;
unknown's avatar
unknown committed
2334

2335 2336
  tmp=(abs_dec < array_elements(log_10) ?
       log_10[abs_dec] : pow(10.0,(double) abs_dec));
unknown's avatar
unknown committed
2337

2338 2339 2340 2341
  // Pre-compute these, to avoid optimizing away e.g. 'floor(v/tmp) * tmp'.
  volatile double value_div_tmp= value / tmp;
  volatile double value_mul_tmp= value * tmp;

2342
  if (dec_negative && my_isinf(tmp))
2343 2344
    tmp2= 0.0;
  else if (!dec_negative && my_isinf(value_mul_tmp))
2345 2346
    tmp2= value;
  else if (truncate)
unknown's avatar
unknown committed
2347
  {
2348 2349
    if (value >= 0.0)
      tmp2= dec < 0 ? floor(value_div_tmp) * tmp : floor(value_mul_tmp) / tmp;
unknown's avatar
unknown committed
2350
    else
2351
      tmp2= dec < 0 ? ceil(value_div_tmp) * tmp : ceil(value_mul_tmp) / tmp;
unknown's avatar
unknown committed
2352
  }
2353
  else
2354 2355
    tmp2=dec < 0 ? rint(value_div_tmp) * tmp : rint(value_mul_tmp) / tmp;

2356
  return tmp2;
unknown's avatar
unknown committed
2357 2358 2359
}


2360 2361 2362 2363 2364
double Item_func_round::real_op()
{
  double value= args[0]->val_real();

  if (!(null_value= args[0]->null_value || args[1]->null_value))
2365 2366
    return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
                           truncate);
2367 2368 2369 2370

  return 0.0;
}

2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381
/*
  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;
}

2382

unknown's avatar
unknown committed
2383 2384 2385
longlong Item_func_round::int_op()
{
  longlong value= args[0]->val_int();
2386
  longlong dec= args[1]->val_int();
unknown's avatar
unknown committed
2387
  decimals= 0;
2388
  ulonglong abs_dec;
unknown's avatar
unknown committed
2389 2390
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0;
2391
  if ((dec >= 0) || args[1]->unsigned_flag)
unknown's avatar
unknown committed
2392 2393 2394
    return value; // integer have not digits after point

  abs_dec= -dec;
unknown's avatar
unknown committed
2395 2396 2397 2398 2399 2400 2401
  longlong tmp;
  
  if(abs_dec >= array_elements(log_10_int))
    return 0;
  
  tmp= log_10_int[abs_dec];
  
unknown's avatar
unknown committed
2402
  if (truncate)
2403 2404
    value= (unsigned_flag) ?
      ((ulonglong) value / tmp) * tmp : (value / tmp) * tmp;
unknown's avatar
unknown committed
2405
  else
2406 2407
    value= (unsigned_flag || value >= 0) ?
      my_unsigned_round((ulonglong) value, tmp) :
2408
      -(longlong) my_unsigned_round((ulonglong) -value, tmp);
unknown's avatar
unknown committed
2409
  return value;
unknown's avatar
unknown committed
2410 2411 2412 2413 2414 2415
}


my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
{
  my_decimal val, *value= args[0]->val_decimal(&val);
2416
  longlong dec= args[1]->val_int();
2417
  if (dec >= 0 || args[1]->unsigned_flag)
2418
    dec= min((ulonglong) dec, decimals);
2419 2420 2421
  else if (dec < INT_MIN)
    dec= INT_MIN;
    
2422
  if (!(null_value= (args[0]->null_value || args[1]->null_value ||
2423
                     my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
2424
                                      truncate, decimal_value) > 1))) 
2425 2426
    return decimal_value;
  return 0;
unknown's avatar
unknown committed
2427 2428 2429
}


2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441
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();
  randominit(rand, (uint32) (tmp*0x10001L+55555555L),
             (uint32) (tmp*0x10000001L));
}


2442
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
unknown's avatar
unknown committed
2443
{
2444
  if (Item_real_func::fix_fields(thd, ref))
2445
    return TRUE;
2446
  used_tables_cache|= RAND_TABLE_BIT;
unknown's avatar
unknown committed
2447 2448
  if (arg_count)
  {					// Only use argument once in query
2449
    /*
unknown's avatar
Rename:  
unknown committed
2450
      Allocate rand structure once: we must use thd->stmt_arena
2451 2452
      to create rand in proper mem_root if it's a prepared statement or
      stored procedure.
2453 2454 2455

      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.
2456 2457
    */
    if (!rand && !(rand= (struct rand_struct*)
unknown's avatar
Rename:  
unknown committed
2458
                   thd->stmt_arena->alloc(sizeof(*rand))))
2459
      return TRUE;
unknown's avatar
unknown committed
2460
  }
2461
  else
unknown's avatar
unknown committed
2462
  {
2463 2464 2465 2466 2467
    /*
      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
    */
2468 2469 2470 2471 2472 2473
    if (!thd->rand_used)
    {
      thd->rand_used= 1;
      thd->rand_saved_seed1= thd->rand.seed1;
      thd->rand_saved_seed2= thd->rand.seed2;
    }
2474
    rand= &thd->rand;
unknown's avatar
unknown committed
2475
  }
2476
  return FALSE;
2477 2478
}

unknown's avatar
unknown committed
2479 2480 2481 2482 2483 2484
void Item_func_rand::update_used_tables()
{
  Item_real_func::update_used_tables();
  used_tables_cache|= RAND_TABLE_BIT;
}

2485

2486
double Item_func_rand::val_real()
2487
{
2488
  DBUG_ASSERT(fixed == 1);
2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
  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]);
    }
  }
2504
  return my_rnd(rand);
unknown's avatar
unknown committed
2505 2506 2507 2508
}

longlong Item_func_sign::val_int()
{
2509
  DBUG_ASSERT(fixed == 1);
2510
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2511 2512 2513 2514 2515
  null_value=args[0]->null_value;
  return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}


2516
double Item_func_units::val_real()
unknown's avatar
unknown committed
2517
{
2518
  DBUG_ASSERT(fixed == 1);
2519
  double value= args[0]->val_real();
unknown's avatar
unknown committed
2520 2521
  if ((null_value=args[0]->null_value))
    return 0;
2522
  return check_float_overflow(value * mul + add);
unknown's avatar
unknown committed
2523 2524 2525 2526 2527
}


void Item_func_min_max::fix_length_and_dec()
{
unknown's avatar
unknown committed
2528
  int max_int_part=0;
2529
  bool datetime_found= FALSE;
unknown's avatar
unknown committed
2530 2531
  decimals=0;
  max_length=0;
unknown's avatar
unknown committed
2532
  maybe_null=0;
unknown's avatar
unknown committed
2533
  cmp_type=args[0]->result_type();
2534

unknown's avatar
unknown committed
2535 2536
  for (uint i=0 ; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2537 2538
    set_if_bigger(max_length, args[i]->max_length);
    set_if_bigger(decimals, args[i]->decimals);
unknown's avatar
unknown committed
2539
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
unknown's avatar
unknown committed
2540 2541
    if (args[i]->maybe_null)
      maybe_null=1;
unknown's avatar
unknown committed
2542
    cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
2543 2544 2545 2546 2547 2548
    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
2549
  }
unknown's avatar
unknown committed
2550
  if (cmp_type == STRING_RESULT)
2551
  {
2552 2553
    agg_arg_charsets_for_string_result_with_comparison(collation,
                                                       args, arg_count);
2554 2555 2556 2557 2558 2559
    if (datetime_found)
    {
      thd= current_thd;
      compare_as_dates= TRUE;
    }
  }
unknown's avatar
unknown committed
2560
  else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
2561 2562 2563 2564 2565 2566 2567
  {
    collation.set_numeric();
    fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
                                                                 decimals,
                                                                 decimals,
                                                                 unsigned_flag));
  }
2568
  else if (cmp_type == REAL_RESULT)
Georgi Kodinov's avatar
merge  
Georgi Kodinov committed
2569
    fix_char_length(float_length(decimals));
2570
  cached_field_type= agg_field_type(args, arg_count);
unknown's avatar
unknown committed
2571 2572 2573
}


2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
/*
  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
2588
   0	If one of arguments is NULL or there was a execution error
2589 2590 2591 2592 2593
   #	index of the least/greatest argument
*/

uint Item_func_min_max::cmp_datetimes(ulonglong *value)
{
2594
  longlong UNINIT_VAR(min_max);
2595 2596 2597 2598 2599 2600
  uint min_max_idx= 0;

  for (uint i=0; i < arg_count ; i++)
  {
    Item **arg= args + i;
    bool is_null;
2601
    longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
2602 2603 2604 2605 2606 2607 2608 2609

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

2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627
    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
2628 2629
String *Item_func_min_max::val_str(String *str)
{
2630
  DBUG_ASSERT(fixed == 1);
2631 2632 2633 2634 2635 2636 2637
  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);
2638 2639 2640 2641 2642 2643
    if (args[min_max_idx]->null_value)
    {
      // check if the call to val_str() above returns a NULL value
      null_value= 1;
      return NULL;
    }
2644 2645 2646
    str_res->set_charset(collation.collation);
    return str_res;
  }
unknown's avatar
unknown committed
2647 2648 2649 2650 2651 2652
  switch (cmp_type) {
  case INT_RESULT:
  {
    longlong nr=val_int();
    if (null_value)
      return 0;
2653
    str->set_int(nr, unsigned_flag, collation.collation);
unknown's avatar
unknown committed
2654 2655
    return str;
  }
unknown's avatar
unknown committed
2656 2657 2658 2659 2660 2661 2662 2663
  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
2664 2665
  case REAL_RESULT:
  {
2666
    double nr= val_real();
unknown's avatar
unknown committed
2667 2668
    if (null_value)
      return 0; /* purecov: inspected */
2669
    str->set_real(nr, decimals, collation.collation);
unknown's avatar
unknown committed
2670 2671 2672 2673
    return str;
  }
  case STRING_RESULT:
  {
2674
    String *UNINIT_VAR(res);
unknown's avatar
unknown committed
2675 2676
    for (uint i=0; i < arg_count ; i++)
    {
unknown's avatar
unknown committed
2677
      if (i == 0)
unknown's avatar
unknown committed
2678 2679 2680 2681 2682 2683 2684
	res=args[i]->val_str(str);
      else
      {
	String *res2;
	res2= args[i]->val_str(res == str ? &tmp_value : str);
	if (res2)
	{
2685
	  int cmp= sortcmp(res,res2,collation.collation);
unknown's avatar
unknown committed
2686 2687 2688 2689
	  if ((cmp_sign < 0 ? cmp : -cmp) < 0)
	    res=res2;
	}
      }
unknown's avatar
unknown committed
2690
      if ((null_value= args[i]->null_value))
2691
        return 0;
unknown's avatar
unknown committed
2692
    }
2693
    res->set_charset(collation.collation);
unknown's avatar
unknown committed
2694 2695
    return res;
  }
2696
  case ROW_RESULT:
unknown's avatar
unknown committed
2697
  default:
unknown's avatar
unknown committed
2698
    // This case should never be chosen
unknown's avatar
unknown committed
2699 2700
    DBUG_ASSERT(0);
    return 0;
unknown's avatar
unknown committed
2701 2702 2703 2704 2705
  }
  return 0;					// Keep compiler happy
}


2706
double Item_func_min_max::val_real()
unknown's avatar
unknown committed
2707
{
2708
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2709
  double value=0.0;
2710 2711
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2712
    ulonglong result= 0;
2713 2714 2715
    (void)cmp_datetimes(&result);
    return (double)result;
  }
unknown's avatar
unknown committed
2716 2717
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2718
    if (i == 0)
2719
      value= args[i]->val_real();
unknown's avatar
unknown committed
2720 2721
    else
    {
2722
      double tmp= args[i]->val_real();
unknown's avatar
unknown committed
2723 2724 2725
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
    }
unknown's avatar
unknown committed
2726 2727
    if ((null_value= args[i]->null_value))
      break;
unknown's avatar
unknown committed
2728 2729 2730 2731 2732 2733 2734
  }
  return value;
}


longlong Item_func_min_max::val_int()
{
2735
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2736
  longlong value=0;
2737 2738
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2739
    ulonglong result= 0;
2740 2741 2742
    (void)cmp_datetimes(&result);
    return (longlong)result;
  }
unknown's avatar
unknown committed
2743 2744
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2745
    if (i == 0)
2746
      value=args[i]->val_int();
unknown's avatar
unknown committed
2747 2748
    else
    {
2749 2750 2751
      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
2752
    }
2753 2754
    if ((null_value= args[i]->null_value))
      break;
unknown's avatar
unknown committed
2755 2756 2757 2758
  }
  return value;
}

unknown's avatar
unknown committed
2759 2760 2761 2762

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

2765 2766
  if (compare_as_dates)
  {
unknown's avatar
unknown committed
2767
    ulonglong value= 0;
2768 2769 2770 2771
    (void)cmp_datetimes(&value);
    ulonglong2decimal(value, dec);
    return dec;
  }
unknown's avatar
unknown committed
2772 2773
  for (uint i=0; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
2774
    if (i == 0)
unknown's avatar
unknown committed
2775 2776 2777
      res= args[i]->val_decimal(dec);
    else
    {
2778 2779
      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
2780 2781 2782
      {
        if (tmp == &tmp_buf)
        {
2783
          /* Move value out of tmp_buf as this will be reused on next loop */
unknown's avatar
unknown committed
2784 2785 2786 2787 2788 2789 2790
          my_decimal2decimal(tmp, dec);
          res= dec;
        }
        else
          res= tmp;
      }
    }
unknown's avatar
unknown committed
2791
    if ((null_value= args[i]->null_value))
2792 2793
    {
      res= 0;
unknown's avatar
unknown committed
2794
      break;
2795
    }
unknown's avatar
unknown committed
2796 2797 2798 2799 2800
  }
  return res;
}


unknown's avatar
unknown committed
2801 2802
longlong Item_func_length::val_int()
{
2803
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2804 2805 2806 2807 2808 2809 2810 2811 2812 2813
  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
2814

unknown's avatar
unknown committed
2815 2816
longlong Item_func_char_length::val_int()
{
2817
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2818 2819 2820 2821 2822 2823 2824
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2825
  return (longlong) res->numchars();
unknown's avatar
unknown committed
2826 2827
}

unknown's avatar
unknown committed
2828

unknown's avatar
unknown committed
2829 2830
longlong Item_func_coercibility::val_int()
{
2831
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2832
  null_value= 0;
2833
  return (longlong) args[0]->collation.derivation;
unknown's avatar
unknown committed
2834
}
unknown's avatar
unknown committed
2835

unknown's avatar
unknown committed
2836

2837 2838
void Item_func_locate::fix_length_and_dec()
{
2839
  max_length= MY_INT32_NUM_DECIMAL_DIGITS;
2840
  agg_arg_charsets_for_comparison(cmp_collation, args, 2);
2841 2842
}

unknown's avatar
unknown committed
2843

unknown's avatar
unknown committed
2844 2845
longlong Item_func_locate::val_int()
{
2846
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2847 2848 2849 2850 2851 2852 2853 2854
  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;
2855 2856 2857
  /* must be longlong to avoid truncation */
  longlong start=  0; 
  longlong start0= 0;
2858
  my_match_t match;
2859

unknown's avatar
unknown committed
2860 2861
  if (arg_count == 3)
  {
2862 2863 2864 2865 2866 2867
    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 */
2868
    start= a->charpos((int) start);
2869 2870

    if (start + b->length() > a->length())
unknown's avatar
unknown committed
2871 2872
      return 0;
  }
2873

unknown's avatar
unknown committed
2874
  if (!b->length())				// Found empty string at start
2875
    return start + 1;
2876
  
2877
  if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
2878 2879
                                            a->ptr()+start,
                                            (uint) (a->length()-start),
2880 2881 2882
                                            b->ptr(), b->length(),
                                            &match, 1))
    return 0;
2883
  return (longlong) match.mb_len + start0 + 1;
unknown's avatar
unknown committed
2884 2885 2886
}


2887
void Item_func_locate::print(String *str, enum_query_type query_type)
2888
{
2889
  str->append(STRING_WITH_LEN("locate("));
2890
  args[1]->print(str, query_type);
2891
  str->append(',');
2892
  args[0]->print(str, query_type);
2893 2894 2895
  if (arg_count == 3)
  {
    str->append(',');
2896
    args[2]->print(str, query_type);
2897 2898 2899 2900 2901
  }
  str->append(')');
}


unknown's avatar
unknown committed
2902 2903
longlong Item_func_field::val_int()
{
2904
  DBUG_ASSERT(fixed == 1);
2905

2906 2907 2908
  if (cmp_type == STRING_RESULT)
  {
    String *field;
2909 2910
    if (!(field= args[0]->val_str(&value)))
      return 0;
2911
    for (uint i=1 ; i < arg_count ; i++)
2912 2913
    {
      String *tmp_value=args[i]->val_str(&tmp);
unknown's avatar
Fix:  
unknown committed
2914
      if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
2915
        return (longlong) (i);
2916 2917 2918 2919
    }
  }
  else if (cmp_type == INT_RESULT)
  {
2920
    longlong val= args[0]->val_int();
unknown's avatar
cleanup  
unknown committed
2921 2922
    if (args[0]->null_value)
      return 0;
2923
    for (uint i=1; i < arg_count ; i++)
2924
    {
2925
      if (val == args[i]->val_int() && !args[i]->null_value)
2926
        return (longlong) (i);
2927 2928
    }
  }
unknown's avatar
unknown committed
2929 2930 2931 2932
  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
cleanup  
unknown committed
2933 2934
    if (args[0]->null_value)
      return 0;
unknown's avatar
unknown committed
2935 2936 2937
    for (uint i=1; i < arg_count; i++)
    {
      dec_arg= args[i]->val_decimal(&dec_arg_buf);
unknown's avatar
unknown committed
2938
      if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
unknown's avatar
unknown committed
2939 2940 2941
        return (longlong) (i);
    }
  }
2942
  else
unknown's avatar
unknown committed
2943
  {
2944
    double val= args[0]->val_real();
unknown's avatar
cleanup  
unknown committed
2945 2946
    if (args[0]->null_value)
      return 0;
2947
    for (uint i=1; i < arg_count ; i++)
2948
    {
unknown's avatar
unknown committed
2949
      if (val == args[i]->val_real() && !args[i]->null_value)
2950
        return (longlong) (i);
2951
    }
unknown's avatar
unknown committed
2952 2953 2954 2955
  }
  return 0;
}

unknown's avatar
unknown committed
2956

2957 2958 2959
void Item_func_field::fix_length_and_dec()
{
  maybe_null=0; max_length=3;
2960 2961
  cmp_type= args[0]->result_type();
  for (uint i=1; i < arg_count ; i++)
2962 2963
    cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
  if (cmp_type == STRING_RESULT)
2964
    agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
2965
}
unknown's avatar
unknown committed
2966

2967

unknown's avatar
unknown committed
2968 2969
longlong Item_func_ascii::val_int()
{
2970
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982
  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()
{
2983
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2984 2985 2986 2987 2988 2989 2990 2991 2992
  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
2993
  if (use_mb(res->charset()))
unknown's avatar
unknown committed
2994 2995
  {
    register const char *str=res->ptr();
2996
    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
unknown's avatar
unknown committed
2997 2998
    if (!l)
      return (longlong)((uchar) *str);
unknown's avatar
unknown committed
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017
    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;
3018
    if (field->real_type() == MYSQL_TYPE_SET)
unknown's avatar
unknown committed
3019 3020 3021 3022
    {
      String *find=args[0]->val_str(&value);
      if (find)
      {
3023 3024
        // find is not NULL pointer so args[0] is not a null-value
        DBUG_ASSERT(!args[0]->null_value);
3025 3026
	enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
			      find->length(), 0);
unknown's avatar
unknown committed
3027 3028 3029 3030 3031 3032
	enum_bit=0;
	if (enum_value)
	  enum_bit=LL(1) << (enum_value-1);
      }
    }
  }
3033
  agg_arg_charsets_for_comparison(cmp_collation, args, 2);
unknown's avatar
unknown committed
3034 3035 3036 3037 3038 3039
}

static const char separator=',';

longlong Item_func_find_in_set::val_int()
{
3040
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3041 3042
  if (enum_value)
  {
3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055
    // enum_value is set iff args[0]->const_item() in fix_length_and_dec().
    DBUG_ASSERT(args[0]->const_item());

    ulonglong tmp= (ulonglong) args[1]->val_int();
    null_value= args[1]->null_value;
    /* 
      No need to check args[0]->null_value since enum_value is set iff
      args[0] is a non-null const item. Note: no DBUG_ASSERT on
      args[0]->null_value here because args[0] may have been replaced
      by an Item_cache on which val_int() has not been called. See
      BUG#11766317
    */
    if (!null_value)
unknown's avatar
unknown committed
3056 3057
    {
      if (tmp & enum_bit)
3058
        return enum_value;
unknown's avatar
unknown committed
3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074
    }
    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;

  int diff;
  if ((diff=buffer->length() - find->length()) >= 0)
  {
3075
    my_wc_t wc= 0;
3076 3077 3078 3079 3080 3081 3082 3083
    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
3084
    {
3085 3086 3087
      int symbol_len;
      if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end, 
                                       (uchar*) real_end)) > 0)
unknown's avatar
unknown committed
3088
      {
3089 3090
        const char *substr_end= str_end + symbol_len;
        bool is_last_item= (substr_end == real_end);
3091 3092
        bool is_separator= (wc == (my_wc_t) separator);
        if (is_separator || is_last_item)
3093 3094
        {
          position++;
3095
          if (is_last_item && !is_separator)
3096 3097
            str_end= substr_end;
          if (!my_strnncoll(cs, (const uchar *) str_begin,
3098
                            (uint) (str_end - str_begin),
3099 3100 3101 3102 3103 3104
                            find_str, find_str_len))
            return (longlong) position;
          else
            str_begin= substr_end;
        }
        str_end= substr_end;
unknown's avatar
unknown committed
3105
      }
unknown's avatar
unknown committed
3106 3107
      else if (str_end - str_begin == 0 &&
               find_str_len == 0 &&
3108 3109 3110
               wc == (my_wc_t) separator)
        return (longlong) ++position;
      else
unknown's avatar
unknown committed
3111
        return LL(0);
3112
    }
unknown's avatar
unknown committed
3113 3114 3115 3116 3117 3118
  }
  return 0;
}

longlong Item_func_bit_count::val_int()
{
3119
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3120
  ulonglong value= (ulonglong) args[0]->val_int();
3121
  if ((null_value= args[0]->null_value))
unknown's avatar
unknown committed
3122
    return 0; /* purecov: inspected */
unknown's avatar
unknown committed
3123
  return (longlong) my_count_bits(value);
unknown's avatar
unknown committed
3124 3125 3126 3127 3128 3129
}


/****************************************************************************
** Functions to handle dynamic loadable functions
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
3130
** Rewritten by monty.
unknown's avatar
unknown committed
3131 3132 3133 3134
****************************************************************************/

#ifdef HAVE_DLOPEN

3135
void udf_handler::cleanup()
unknown's avatar
unknown committed
3136
{
3137
  if (!not_original)
unknown's avatar
unknown committed
3138
  {
3139
    if (initialized)
unknown's avatar
unknown committed
3140
    {
3141 3142
      if (u_d->func_deinit != NULL)
      {
3143
        Udf_func_deinit deinit= u_d->func_deinit;
3144 3145 3146
        (*deinit)(&initid);
      }
      free_udf(u_d);
3147
      initialized= FALSE;
unknown's avatar
unknown committed
3148
    }
3149 3150
    if (buffers)				// Because of bug in ecc
      delete [] buffers;
3151
    buffers= 0;
unknown's avatar
unknown committed
3152 3153 3154 3155 3156
  }
}


bool
3157
udf_handler::fix_fields(THD *thd, Item_result_field *func,
unknown's avatar
unknown committed
3158 3159
			uint arg_count, Item **arguments)
{
3160
  uchar buff[STACK_BUFF_ALLOC];			// Max argument in function
unknown's avatar
unknown committed
3161 3162
  DBUG_ENTER("Item_udf_func::fix_fields");

3163
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
unknown's avatar
unknown committed
3164
    DBUG_RETURN(TRUE);				// Fatal error flag is set!
unknown's avatar
unknown committed
3165

3166
  udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
unknown's avatar
unknown committed
3167 3168 3169

  if (!tmp_udf)
  {
3170
    my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str);
unknown's avatar
unknown committed
3171
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3172 3173 3174 3175 3176
  }
  u_d=tmp_udf;
  args=arguments;

  /* Fix all arguments */
3177
  func->maybe_null=0;
unknown's avatar
unknown committed
3178 3179 3180 3181 3182 3183 3184 3185 3186 3187
  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
3188
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3189 3190 3191 3192 3193 3194 3195
    }
    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
3196
      if (!(*arg)->fixed &&
3197
          (*arg)->fix_fields(thd, arg))
unknown's avatar
unknown committed
3198
	DBUG_RETURN(1);
3199
      // we can't assign 'item' before, because fix_fields() can change arg
unknown's avatar
unknown committed
3200
      Item *item= *arg;
3201
      if (item->check_cols(1))
unknown's avatar
unknown committed
3202
	DBUG_RETURN(TRUE);
3203 3204 3205 3206 3207 3208 3209 3210 3211
      /*
	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
3212
        the particular user defined function.
3213
      */
3214 3215
      if (item->collation.collation->state & MY_CS_BINSORT)
	func->collation.set(&my_charset_bin);
unknown's avatar
unknown committed
3216
      if (item->maybe_null)
unknown's avatar
unknown committed
3217
	func->maybe_null=1;
unknown's avatar
unknown committed
3218 3219 3220 3221
      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
3222
    }
unknown's avatar
unknown committed
3223
    //TODO: why all following memory is not allocated with 1 call of sql_alloc?
unknown's avatar
unknown committed
3224 3225
    if (!(buffers=new String[arg_count]) ||
	!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
3226 3227 3228 3229 3230 3231 3232
	!(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
3233 3234
    {
      free_udf(u_d);
unknown's avatar
unknown committed
3235
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246
    }
  }
  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)
  {
3247
    char init_msg_buff[MYSQL_ERRMSG_SIZE];
unknown's avatar
unknown committed
3248 3249 3250
    char *to=num_buffer;
    for (uint i=0; i < arg_count; i++)
    {
3251 3252 3253 3254 3255 3256
      /*
       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. */

3257 3258 3259 3260
      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
3261

3262
      if (arguments[i]->const_item())
unknown's avatar
unknown committed
3263
      {
3264 3265 3266 3267 3268 3269
        switch (arguments[i]->result_type()) 
        {
        case STRING_RESULT:
        case DECIMAL_RESULT:
        {
          String *res= arguments[i]->val_str(&buffers[i]);
3270 3271
          if (arguments[i]->null_value)
            continue;
3272
          f_args.args[i]= (char*) res->c_ptr_safe();
3273
          f_args.lengths[i]= res->length();
3274 3275 3276 3277
          break;
        }
        case INT_RESULT:
          *((longlong*) to)= arguments[i]->val_int();
3278 3279
          if (arguments[i]->null_value)
            continue;
3280 3281 3282 3283 3284
          f_args.args[i]= to;
          to+= ALIGN_SIZE(sizeof(longlong));
          break;
        case REAL_RESULT:
          *((double*) to)= arguments[i]->val_real();
3285 3286
          if (arguments[i]->null_value)
            continue;
3287 3288 3289 3290 3291 3292 3293 3294 3295
          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
3296 3297
      }
    }
3298
    Udf_func_init init= u_d->func_init;
3299
    if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
unknown's avatar
unknown committed
3300
    {
3301
      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
3302
               u_d->name.str, init_msg_buff);
unknown's avatar
unknown committed
3303
      free_udf(u_d);
unknown's avatar
unknown committed
3304
      DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3305 3306 3307 3308
    }
    func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
    func->maybe_null=initid.maybe_null;
    const_item_cache=initid.const_item;
3309 3310 3311 3312 3313 3314
    /* 
      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;
3315
    func->decimals=min(initid.decimals,NOT_FIXED_DEC);
unknown's avatar
unknown committed
3316 3317 3318 3319
  }
  initialized=1;
  if (error)
  {
3320 3321
    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
             u_d->name.str, ER(ER_UNKNOWN_ERROR));
unknown's avatar
unknown committed
3322
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
3323
  }
unknown's avatar
unknown committed
3324
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338
}


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
3339
    case DECIMAL_RESULT:
unknown's avatar
unknown committed
3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357
      {
	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:
3358
      *((double*) to)= args[i]->val_real();
unknown's avatar
unknown committed
3359 3360 3361 3362 3363 3364
      if (!args[i]->null_value)
      {
	f_args.args[i]=to;
	to+= ALIGN_SIZE(sizeof(double));
      }
      break;
3365
    case ROW_RESULT:
unknown's avatar
unknown committed
3366
    default:
unknown's avatar
unknown committed
3367
      // This case should never be chosen
unknown's avatar
unknown committed
3368
      DBUG_ASSERT(0);
3369
      break;
unknown's avatar
unknown committed
3370 3371 3372 3373 3374
    }
  }
  return 0;
}

unknown's avatar
unknown committed
3375 3376 3377 3378
/**
  @return
    (String*)NULL in case of NULL values
*/
unknown's avatar
unknown committed
3379 3380
String *udf_handler::val_str(String *str,String *save_str)
{
3381
  uchar is_null_tmp=0;
unknown's avatar
unknown committed
3382
  ulong res_length;
3383
  DBUG_ENTER("udf_handler::val_str");
unknown's avatar
unknown committed
3384 3385

  if (get_arguments())
3386
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3387 3388 3389 3390 3391 3392 3393 3394 3395
  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;
3396
      DBUG_RETURN(0);
unknown's avatar
unknown committed
3397 3398
    }
  }
3399 3400
  char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
		 &is_null_tmp, &error);
3401
  DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
3402
  if (is_null_tmp || !res || error)		// The !res is for safety
unknown's avatar
unknown committed
3403
  {
3404 3405
    DBUG_PRINT("info", ("Null or error"));
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3406 3407 3408 3409
  }
  if (res == str->ptr())
  {
    str->length(res_length);
3410
    DBUG_PRINT("exit", ("str: %*.s", (int) str->length(), str->ptr()));
3411
    DBUG_RETURN(str);
unknown's avatar
unknown committed
3412
  }
3413
  save_str->set(res, res_length, str->charset());
3414 3415
  DBUG_PRINT("exit", ("save_str: %s", save_str->ptr()));
  DBUG_RETURN(save_str);
unknown's avatar
unknown committed
3416 3417 3418
}


3419 3420 3421 3422
/*
  For the moment, UDF functions are returning DECIMAL values as strings
*/

unknown's avatar
unknown committed
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442
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;
  }
3443 3444
  end= res+ res_length;
  str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
unknown's avatar
unknown committed
3445 3446 3447
  return dec_buf;
}

unknown's avatar
unknown committed
3448

3449 3450 3451 3452 3453 3454
void Item_udf_func::cleanup()
{
  udf.cleanup();
  Item_func::cleanup();
}

unknown's avatar
unknown committed
3455

3456
void Item_udf_func::print(String *str, enum_query_type query_type)
3457 3458 3459 3460 3461 3462 3463
{
  str->append(func_name());
  str->append('(');
  for (uint i=0 ; i < arg_count ; i++)
  {
    if (i != 0)
      str->append(',');
3464
    args[i]->print_item_w_name(str, query_type);
3465 3466 3467 3468 3469
  }
  str->append(')');
}


3470
double Item_func_udf_float::val_real()
unknown's avatar
unknown committed
3471
{
3472
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3473 3474 3475 3476 3477 3478 3479 3480 3481
  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)
{
3482
  DBUG_ASSERT(fixed == 1);
3483
  double nr= val_real();
unknown's avatar
unknown committed
3484 3485
  if (null_value)
    return 0;					/* purecov: inspected */
3486
  str->set_real(nr,decimals,&my_charset_bin);
unknown's avatar
unknown committed
3487 3488 3489 3490 3491 3492
  return str;
}


longlong Item_func_udf_int::val_int()
{
3493
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3494 3495 3496 3497 3498 3499 3500
  DBUG_ENTER("Item_func_udf_int::val_int");
  DBUG_RETURN(udf.val_int(&null_value));
}


String *Item_func_udf_int::val_str(String *str)
{
3501
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3502 3503 3504
  longlong nr=val_int();
  if (null_value)
    return 0;
3505
  str->set_int(nr, unsigned_flag, &my_charset_bin);
unknown's avatar
unknown committed
3506 3507 3508
  return str;
}

unknown's avatar
unknown committed
3509 3510 3511 3512

longlong Item_func_udf_decimal::val_int()
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
3513
  longlong result;
unknown's avatar
unknown committed
3514 3515 3516 3517 3518 3519 3520 3521 3522 3523
  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);
3524
  double result;
unknown's avatar
unknown committed
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561
  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
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574
/* 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)
{
3575
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3576 3577 3578 3579 3580
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  return res;
}

3581

unknown's avatar
unknown committed
3582 3583 3584 3585 3586
/**
  @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.)
*/
3587 3588 3589

udf_handler::~udf_handler()
{
3590 3591
  /* Everything should be properly cleaned up by this moment. */
  DBUG_ASSERT(not_original || !(initialized || buffers));
3592 3593
}

unknown's avatar
unknown committed
3594 3595 3596 3597 3598 3599 3600 3601
#else
bool udf_handler::get_arguments() { return 0; }
#endif /* HAVE_DLOPEN */

/*
** User level locks
*/

Marc Alff's avatar
Marc Alff committed
3602
mysql_mutex_t LOCK_user_locks;
unknown's avatar
unknown committed
3603 3604
static HASH hash_user_locks;

3605
class User_level_lock
unknown's avatar
unknown committed
3606
{
3607 3608
  uchar *key;
  size_t key_length;
unknown's avatar
unknown committed
3609 3610 3611 3612

public:
  int count;
  bool locked;
Marc Alff's avatar
Marc Alff committed
3613
  mysql_cond_t cond;
unknown's avatar
unknown committed
3614 3615
  my_thread_id thread_id;
  void set_thread(THD *thd) { thread_id= thd->thread_id; }
unknown's avatar
unknown committed
3616

3617
  User_level_lock(const uchar *key_arg,uint length, ulong id) 
unknown's avatar
SCRUM  
unknown committed
3618
    :key_length(length),count(1),locked(1), thread_id(id)
unknown's avatar
unknown committed
3619
  {
3620
    key= (uchar*) my_memdup(key_arg,length,MYF(0));
Marc Alff's avatar
Marc Alff committed
3621
    mysql_cond_init(key_user_level_lock_cond, &cond, NULL);
unknown's avatar
unknown committed
3622 3623
    if (key)
    {
3624
      if (my_hash_insert(&hash_user_locks,(uchar*) this))
unknown's avatar
unknown committed
3625
      {
3626
	my_free(key);
unknown's avatar
unknown committed
3627 3628 3629 3630
	key=0;
      }
    }
  }
3631
  ~User_level_lock()
unknown's avatar
unknown committed
3632 3633 3634
  {
    if (key)
    {
Konstantin Osipov's avatar
Konstantin Osipov committed
3635
      my_hash_delete(&hash_user_locks,(uchar*) this);
3636
      my_free(key);
unknown's avatar
unknown committed
3637
    }
Marc Alff's avatar
Marc Alff committed
3638
    mysql_cond_destroy(&cond);
unknown's avatar
unknown committed
3639 3640
  }
  inline bool initialized() { return key != 0; }
3641
  friend void item_user_lock_release(User_level_lock *ull);
3642 3643
  friend uchar *ull_get_key(const User_level_lock *ull, size_t *length,
                            my_bool not_used);
unknown's avatar
unknown committed
3644 3645
};

3646 3647
uchar *ull_get_key(const User_level_lock *ull, size_t *length,
                   my_bool not_used __attribute__((unused)))
unknown's avatar
unknown committed
3648
{
3649 3650
  *length= ull->key_length;
  return ull->key;
unknown's avatar
unknown committed
3651 3652
}

Marc Alff's avatar
Marc Alff committed
3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_LOCK_user_locks;

static PSI_mutex_info all_user_mutexes[]=
{
  { &key_LOCK_user_locks, "LOCK_user_locks", PSI_FLAG_GLOBAL}
};

static void init_user_lock_psi_keys(void)
{
  const char* category= "sql";
  int count;

  if (PSI_server == NULL)
    return;

  count= array_elements(all_user_mutexes);
  PSI_server->register_mutex(category, all_user_mutexes, count);
}
#endif
3673 3674 3675

static bool item_user_lock_inited= 0;

unknown's avatar
unknown committed
3676 3677
void item_user_lock_init(void)
{
Marc Alff's avatar
Marc Alff committed
3678 3679 3680 3681 3682
#ifdef HAVE_PSI_INTERFACE
  init_user_lock_psi_keys();
#endif

  mysql_mutex_init(key_LOCK_user_locks, &LOCK_user_locks, MY_MUTEX_INIT_SLOW);
Konstantin Osipov's avatar
Konstantin Osipov committed
3683 3684
  my_hash_init(&hash_user_locks,system_charset_info,
	    16,0,0,(my_hash_get_key) ull_get_key,NULL,0);
3685
  item_user_lock_inited= 1;
unknown's avatar
unknown committed
3686 3687 3688 3689
}

void item_user_lock_free(void)
{
3690 3691 3692
  if (item_user_lock_inited)
  {
    item_user_lock_inited= 0;
Konstantin Osipov's avatar
Konstantin Osipov committed
3693
    my_hash_free(&hash_user_locks);
Marc Alff's avatar
Marc Alff committed
3694
    mysql_mutex_destroy(&LOCK_user_locks);
3695
  }
unknown's avatar
unknown committed
3696 3697
}

3698
void item_user_lock_release(User_level_lock *ull)
unknown's avatar
unknown committed
3699 3700
{
  ull->locked=0;
3701
  ull->thread_id= 0;
unknown's avatar
unknown committed
3702
  if (--ull->count)
Marc Alff's avatar
Marc Alff committed
3703
    mysql_cond_signal(&ull->cond);
unknown's avatar
unknown committed
3704 3705 3706 3707
  else
    delete ull;
}

unknown's avatar
unknown committed
3708 3709 3710 3711
/**
  Wait until we are at or past the given position in the master binlog
  on the slave.
*/
unknown's avatar
unknown committed
3712 3713 3714

longlong Item_master_pos_wait::val_int()
{
3715
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3716 3717
  THD* thd = current_thd;
  String *log_name = args[0]->val_str(&value);
3718
  int event_count= 0;
unknown's avatar
unknown committed
3719

unknown's avatar
unknown committed
3720 3721 3722 3723 3724 3725
  null_value=0;
  if (thd->slave_thread || !log_name || !log_name->length())
  {
    null_value = 1;
    return 0;
  }
3726
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
3727
  longlong pos = (ulong)args[1]->val_int();
3728 3729
  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
3730 3731 3732 3733
  {
    null_value = 1;
    event_count=0;
  }
3734
#endif
unknown's avatar
unknown committed
3735 3736 3737
  return event_count;
}

3738

3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782
/**
  Enables a session to wait on a condition until a timeout or a network
  disconnect occurs.

  @remark The connection is polled every m_interrupt_interval nanoseconds.
*/

class Interruptible_wait
{
  THD *m_thd;
  struct timespec m_abs_timeout;
  static const ulonglong m_interrupt_interval;

  public:
    Interruptible_wait(THD *thd)
    : m_thd(thd) {}

    ~Interruptible_wait() {}

  public:
    /**
      Set the absolute timeout.

      @param timeout The amount of time in nanoseconds to wait
    */
    void set_timeout(ulonglong timeout)
    {
      /*
        Calculate the absolute system time at the start so it can
        be controlled in slices. It relies on the fact that once
        the absolute time passes, the timed wait call will fail
        automatically with a timeout error.
      */
      set_timespec_nsec(m_abs_timeout, timeout);
    }

    /** The timed wait. */
    int wait(mysql_cond_t *, mysql_mutex_t *);
};


/** Time to wait before polling the connection status. */
const ulonglong Interruptible_wait::m_interrupt_interval= 5 * ULL(1000000000);

3783 3784

/**
3785
  Wait for a given condition to be signaled.
3786

3787 3788 3789 3790
  @param cond   The condition variable to wait on.
  @param mutex  The associated mutex.

  @remark The absolute timeout is preserved across calls.
3791

Marc Alff's avatar
Marc Alff committed
3792
  @retval return value from mysql_cond_timedwait
3793 3794
*/

3795
int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
3796 3797
{
  int error;
3798
  struct timespec timeout;
3799

3800
  while (1)
3801 3802
  {
    /* Wait for a fixed interval. */
3803
    set_timespec_nsec(timeout, m_interrupt_interval);
3804

3805 3806 3807 3808 3809
    /* But only if not past the absolute timeout. */
    if (cmp_timespec(timeout, m_abs_timeout) > 0)
      timeout= m_abs_timeout;

    error= mysql_cond_timedwait(cond, mutex, &timeout);
3810 3811 3812
    if (error == ETIMEDOUT || error == ETIME)
    {
      /* Return error if timed out or connection is broken. */
3813
      if (!cmp_timespec(timeout, m_abs_timeout) || !m_thd->is_connected())
3814 3815
        break;
    }
3816 3817 3818 3819
    /* Otherwise, propagate status to the caller. */
    else
      break;
  }
3820 3821 3822 3823

  return error;
}

3824

unknown's avatar
unknown committed
3825 3826 3827 3828 3829 3830 3831 3832 3833
/**
  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
3834 3835 3836 3837
*/

longlong Item_func_get_lock::val_int()
{
3838
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3839
  String *res=args[0]->val_str(&value);
3840
  ulonglong timeout= args[1]->val_int();
unknown's avatar
unknown committed
3841
  THD *thd=current_thd;
3842
  User_level_lock *ull;
unknown's avatar
unknown committed
3843
  int error;
3844
  Interruptible_wait timed_cond(thd);
3845
  DBUG_ENTER("Item_func_get_lock::val_int");
unknown's avatar
unknown committed
3846

3847 3848 3849 3850 3851 3852 3853 3854
  /*
    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)
3855
    DBUG_RETURN(1);
3856

Marc Alff's avatar
Marc Alff committed
3857
  mysql_mutex_lock(&LOCK_user_locks);
unknown's avatar
unknown committed
3858 3859 3860

  if (!res || !res->length())
  {
Marc Alff's avatar
Marc Alff committed
3861
    mysql_mutex_unlock(&LOCK_user_locks);
unknown's avatar
unknown committed
3862
    null_value=1;
3863
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3864
  }
3865 3866
  DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
                      (long) thd->real_id));
unknown's avatar
unknown committed
3867 3868 3869 3870 3871 3872 3873 3874
  null_value=0;

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

Konstantin Osipov's avatar
Konstantin Osipov committed
3875 3876 3877
  if (!(ull= ((User_level_lock *) my_hash_search(&hash_user_locks,
                                                 (uchar*) res->ptr(),
                                                 (size_t) res->length()))))
unknown's avatar
unknown committed
3878
  {
3879 3880
    ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
                             thd->thread_id);
unknown's avatar
unknown committed
3881 3882 3883
    if (!ull || !ull->initialized())
    {
      delete ull;
Marc Alff's avatar
Marc Alff committed
3884
      mysql_mutex_unlock(&LOCK_user_locks);
unknown's avatar
unknown committed
3885
      null_value=1;				// Probably out of memory
3886
      DBUG_RETURN(0);
unknown's avatar
unknown committed
3887
    }
3888
    ull->set_thread(thd);
unknown's avatar
unknown committed
3889
    thd->ull=ull;
Marc Alff's avatar
Marc Alff committed
3890
    mysql_mutex_unlock(&LOCK_user_locks);
3891 3892
    DBUG_PRINT("info", ("made new lock"));
    DBUG_RETURN(1);				// Got new lock
unknown's avatar
unknown committed
3893 3894
  }
  ull->count++;
3895
  DBUG_PRINT("info", ("ull->count=%d", ull->count));
unknown's avatar
unknown committed
3896

3897 3898 3899 3900
  /*
    Structure is now initialized.  Try to get the lock.
    Set up control struct to allow others to abort locks.
  */
3901
  thd_proc_info(thd, "User lock");
unknown's avatar
unknown committed
3902 3903 3904
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

3905 3906
  timed_cond.set_timeout(timeout * ULL(1000000000));

unknown's avatar
unknown committed
3907
  error= 0;
Mikael Ronstrom's avatar
Mikael Ronstrom committed
3908
  thd_wait_begin(thd, THD_WAIT_USER_LOCK);
unknown's avatar
unknown committed
3909 3910
  while (ull->locked && !thd->killed)
  {
3911
    DBUG_PRINT("info", ("waiting on lock"));
3912
    error= timed_cond.wait(&ull->cond, &LOCK_user_locks);
unknown's avatar
unknown committed
3913
    if (error == ETIMEDOUT || error == ETIME)
3914 3915
    {
      DBUG_PRINT("info", ("lock wait timeout"));
unknown's avatar
unknown committed
3916
      break;
3917
    }
unknown's avatar
unknown committed
3918 3919
    error= 0;
  }
Mikael Ronstrom's avatar
Mikael Ronstrom committed
3920
  thd_wait_end(thd);
unknown's avatar
unknown committed
3921

unknown's avatar
unknown committed
3922 3923 3924
  if (ull->locked)
  {
    if (!--ull->count)
unknown's avatar
unknown committed
3925 3926
    {
      DBUG_ASSERT(0);
unknown's avatar
unknown committed
3927
      delete ull;				// Should never happen
unknown's avatar
unknown committed
3928 3929
    }
    if (!error)                                 // Killed (thd->killed != 0)
unknown's avatar
unknown committed
3930 3931 3932 3933 3934
    {
      error=1;
      null_value=1;				// Return NULL
    }
  }
unknown's avatar
unknown committed
3935
  else                                          // We got the lock
unknown's avatar
unknown committed
3936 3937
  {
    ull->locked=1;
3938
    ull->set_thread(thd);
3939
    ull->thread_id= thd->thread_id;
unknown's avatar
unknown committed
3940 3941
    thd->ull=ull;
    error=0;
3942
    DBUG_PRINT("info", ("got the lock"));
unknown's avatar
unknown committed
3943
  }
Marc Alff's avatar
Marc Alff committed
3944
  mysql_mutex_unlock(&LOCK_user_locks);
unknown's avatar
unknown committed
3945

Marc Alff's avatar
Marc Alff committed
3946
  mysql_mutex_lock(&thd->mysys_var->mutex);
3947
  thd_proc_info(thd, 0);
unknown's avatar
unknown committed
3948 3949
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
Marc Alff's avatar
Marc Alff committed
3950
  mysql_mutex_unlock(&thd->mysys_var->mutex);
unknown's avatar
unknown committed
3951

3952
  DBUG_RETURN(!error ? 1 : 0);
unknown's avatar
unknown committed
3953 3954 3955
}


unknown's avatar
unknown committed
3956
/**
3957
  Release a user level lock.
unknown's avatar
unknown committed
3958 3959 3960 3961
  @return
    - 1 if lock released
    - 0 if lock wasn't held
    - (SQL) NULL if no such lock
unknown's avatar
unknown committed
3962 3963 3964 3965
*/

longlong Item_func_release_lock::val_int()
{
3966
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3967
  String *res=args[0]->val_str(&value);
3968
  User_level_lock *ull;
unknown's avatar
unknown committed
3969
  longlong result;
3970 3971
  THD *thd=current_thd;
  DBUG_ENTER("Item_func_release_lock::val_int");
unknown's avatar
unknown committed
3972 3973 3974
  if (!res || !res->length())
  {
    null_value=1;
3975
    DBUG_RETURN(0);
unknown's avatar
unknown committed
3976
  }
3977
  DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
unknown's avatar
unknown committed
3978 3979 3980
  null_value=0;

  result=0;
Marc Alff's avatar
Marc Alff committed
3981
  mysql_mutex_lock(&LOCK_user_locks);
Konstantin Osipov's avatar
Konstantin Osipov committed
3982 3983 3984
  if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks,
                                                (const uchar*) res->ptr(),
                                                (size_t) res->length()))))
unknown's avatar
unknown committed
3985 3986 3987 3988 3989
  {
    null_value=1;
  }
  else
  {
unknown's avatar
unknown committed
3990
    DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu", 
3991
                        (int) ull->locked,
unknown's avatar
unknown committed
3992 3993
                        (long)ull->thread_id,
                        (long)thd->thread_id));
unknown's avatar
unknown committed
3994
    if (ull->locked && current_thd->thread_id == ull->thread_id)
unknown's avatar
unknown committed
3995
    {
3996
      DBUG_PRINT("info", ("release lock"));
unknown's avatar
unknown committed
3997 3998
      result=1;					// Release is ok
      item_user_lock_release(ull);
3999
      thd->ull=0;
unknown's avatar
unknown committed
4000 4001
    }
  }
Marc Alff's avatar
Marc Alff committed
4002
  mysql_mutex_unlock(&LOCK_user_locks);
4003
  DBUG_RETURN(result);
unknown's avatar
unknown committed
4004 4005 4006
}


4007
longlong Item_func_last_insert_id::val_int()
unknown's avatar
unknown committed
4008
{
unknown's avatar
unknown committed
4009
  THD *thd= current_thd;
4010
  DBUG_ASSERT(fixed == 1);
4011 4012
  if (arg_count)
  {
unknown's avatar
unknown committed
4013 4014
    longlong value= args[0]->val_int();
    null_value= args[0]->null_value;
4015 4016 4017 4018 4019 4020 4021 4022 4023 4024
    /*
      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;
4025
  }
4026 4027
  return
    static_cast<longlong>(thd->read_first_successful_insert_id_in_prev_stmt());
unknown's avatar
unknown committed
4028 4029
}

4030 4031 4032 4033 4034 4035 4036 4037

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
4038 4039 4040 4041
/* This function is just used to test speed of different functions */

longlong Item_func_benchmark::val_int()
{
4042
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
4043
  char buff[MAX_FIELD_WIDTH];
unknown's avatar
unknown committed
4044
  String tmp(buff,sizeof(buff), &my_charset_bin);
unknown's avatar
unknown committed
4045
  my_decimal tmp_decimal;
unknown's avatar
unknown committed
4046
  THD *thd=current_thd;
4047
  ulonglong loop_count;
unknown's avatar
unknown committed
4048

4049
  loop_count= (ulonglong) args[0]->val_int();
4050

4051 4052
  if (args[0]->null_value ||
      (!args[0]->unsigned_flag && (((longlong) loop_count) < 0)))
4053
  {
4054 4055 4056 4057
    if (!args[0]->null_value)
    {
      char buff[22];
      llstr(((longlong) loop_count), buff);
Marc Alff's avatar
Marc Alff committed
4058
      push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
4059 4060 4061 4062
                          ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
                          "count", buff, "benchmark");
    }

4063 4064 4065 4066 4067
    null_value= 1;
    return 0;
  }

  null_value=0;
4068
  for (ulonglong loop=0 ; loop < loop_count && !thd->killed; loop++)
unknown's avatar
unknown committed
4069
  {
4070
    switch (args[1]->result_type()) {
unknown's avatar
unknown committed
4071
    case REAL_RESULT:
4072
      (void) args[1]->val_real();
unknown's avatar
unknown committed
4073 4074
      break;
    case INT_RESULT:
4075
      (void) args[1]->val_int();
unknown's avatar
unknown committed
4076 4077
      break;
    case STRING_RESULT:
4078
      (void) args[1]->val_str(&tmp);
unknown's avatar
unknown committed
4079
      break;
unknown's avatar
unknown committed
4080 4081 4082
    case DECIMAL_RESULT:
      (void) args[1]->val_decimal(&tmp_decimal);
      break;
4083
    case ROW_RESULT:
unknown's avatar
unknown committed
4084
    default:
unknown's avatar
unknown committed
4085
      // This case should never be chosen
unknown's avatar
unknown committed
4086 4087
      DBUG_ASSERT(0);
      return 0;
unknown's avatar
unknown committed
4088 4089 4090 4091 4092
    }
  }
  return 0;
}

4093

4094
void Item_func_benchmark::print(String *str, enum_query_type query_type)
4095
{
4096
  str->append(STRING_WITH_LEN("benchmark("));
4097
  args[0]->print(str, query_type);
4098
  str->append(',');
4099
  args[1]->print(str, query_type);
4100 4101 4102
  str->append(')');
}

unknown's avatar
unknown committed
4103

unknown's avatar
unknown committed
4104
/** This function is just used to create tests with time gaps. */
4105 4106 4107

longlong Item_func_sleep::val_int()
{
4108
  THD *thd= current_thd;
4109
  Interruptible_wait timed_cond(thd);
Marc Alff's avatar
Marc Alff committed
4110
  mysql_cond_t cond;
4111
  double timeout;
4112
  int error;
4113

4114
  DBUG_ASSERT(fixed == 1);
4115

4116
  timeout= args[0]->val_real();
4117
  /*
Marc Alff's avatar
Marc Alff committed
4118
    On 64-bit OSX mysql_cond_timedwait() waits forever
4119 4120 4121 4122 4123
    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 
Marc Alff's avatar
Marc Alff committed
4124
    to mysql_cond_timedwait() will be executed in less than 0.00001 sec.
4125
  */
4126
  if (timeout < 0.00001)
4127
    return 0;
4128

4129 4130
  timed_cond.set_timeout((ulonglong) (timeout * 1000000000.0));

Marc Alff's avatar
Marc Alff committed
4131 4132
  mysql_cond_init(key_item_func_sleep_cond, &cond, NULL);
  mysql_mutex_lock(&LOCK_user_locks);
4133

4134
  thd_proc_info(thd, "User sleep");
4135 4136 4137
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &cond;

unknown's avatar
unknown committed
4138
  error= 0;
Mikael Ronstrom's avatar
Mikael Ronstrom committed
4139
  thd_wait_begin(thd, THD_WAIT_SLEEP);
unknown's avatar
unknown committed
4140 4141
  while (!thd->killed)
  {
4142
    error= timed_cond.wait(&cond, &LOCK_user_locks);
unknown's avatar
unknown committed
4143 4144 4145 4146
    if (error == ETIMEDOUT || error == ETIME)
      break;
    error= 0;
  }
Mikael Ronstrom's avatar
Mikael Ronstrom committed
4147
  thd_wait_end(thd);
4148
  thd_proc_info(thd, 0);
Marc Alff's avatar
Marc Alff committed
4149 4150
  mysql_mutex_unlock(&LOCK_user_locks);
  mysql_mutex_lock(&thd->mysys_var->mutex);
4151 4152
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
Marc Alff's avatar
Marc Alff committed
4153
  mysql_mutex_unlock(&thd->mysys_var->mutex);
4154

Marc Alff's avatar
Marc Alff committed
4155
  mysql_cond_destroy(&cond);
4156

unknown's avatar
unknown committed
4157
  return test(!error); 		// Return 1 killed
4158 4159 4160
}


unknown's avatar
unknown committed
4161 4162 4163 4164 4165 4166 4167
#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;

Konstantin Osipov's avatar
Konstantin Osipov committed
4168 4169
  if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.str,
                                                 name.length)) &&
unknown's avatar
unknown committed
4170 4171 4172
      create_if_not_exists)
  {
    uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
Konstantin Osipov's avatar
Konstantin Osipov committed
4173
    if (!my_hash_inited(hash))
unknown's avatar
unknown committed
4174
      return 0;
4175
    if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
unknown's avatar
unknown committed
4176 4177 4178 4179 4180 4181
      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;
4182
    entry->update_query_id=0;
4183
    entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4184
    entry->unsigned_flag= 0;
4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
    /*
      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
4195
    entry->used_query_id=current_thd->query_id;
unknown's avatar
unknown committed
4196 4197
    entry->type=STRING_RESULT;
    memcpy(entry->name.str, name.str, name.length+1);
4198
    if (my_hash_insert(hash,(uchar*) entry))
unknown's avatar
unknown committed
4199
    {
4200
      my_free(entry);
unknown's avatar
unknown committed
4201 4202 4203 4204 4205 4206
      return 0;
    }
  }
  return entry;
}

4207

4208 4209 4210 4211 4212 4213 4214
void Item_func_set_user_var::cleanup()
{
  Item_func::cleanup();
  entry= NULL;
}


4215 4216
bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
{
4217
  if (entry && thd->thread_id == entry_thread_id)
4218
    goto end; // update entry->update_query_id for PS
4219
  if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
4220 4221
  {
    entry_thread_id= 0;
4222
    return TRUE;
4223 4224
  }
  entry_thread_id= thd->thread_id;
4225 4226 4227 4228 4229
  /* 
     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).
  */
4230
end:
4231 4232 4233 4234 4235
  entry->update_query_id= thd->query_id;
  return FALSE;
}


4236
/*
4237 4238
  When a user variable is updated (in a SET command or a query like
  SELECT @a:= ).
4239
*/
4240

4241
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
4242
{
4243
  DBUG_ASSERT(fixed == 0);
4244
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
4245
  if (Item_func::fix_fields(thd, ref) || set_entry(thd, TRUE))
unknown's avatar
unknown committed
4246
    return TRUE;
4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261
  /*
    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.
  */
4262 4263
  null_item= (args[0]->type() == NULL_ITEM);
  if (!entry->collation.collation || !null_item)
4264 4265 4266
    entry->collation.set(args[0]->collation.derivation == DERIVATION_NUMERIC ?
                         default_charset() : args[0]->collation.collation,
                         DERIVATION_IMPLICIT);
4267
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
4268
  cached_result_type= args[0]->result_type();
unknown's avatar
unknown committed
4269
  return FALSE;
unknown's avatar
unknown committed
4270 4271 4272 4273 4274 4275 4276 4277
}


void
Item_func_set_user_var::fix_length_and_dec()
{
  maybe_null=args[0]->maybe_null;
  decimals=args[0]->decimals;
4278 4279 4280 4281 4282 4283 4284 4285
  collation.set(DERIVATION_IMPLICIT);
  if (args[0]->collation.derivation == DERIVATION_NUMERIC)
    fix_length_and_charset(args[0]->max_char_length(), default_charset());
  else
  {
    fix_length_and_charset(args[0]->max_char_length(),
                           args[0]->collation.collation);
  }
4286
  unsigned_flag= args[0]->unsigned_flag;
unknown's avatar
unknown committed
4287 4288
}

4289

unknown's avatar
unknown committed
4290 4291 4292 4293 4294 4295 4296 4297 4298 4299
/*
  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)
{
4300 4301 4302 4303 4304 4305
  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
4306 4307 4308 4309
  return 0;
}


unknown's avatar
unknown committed
4310
/**
unknown's avatar
unknown committed
4311 4312
  Set value to user variable.

unknown's avatar
unknown committed
4313 4314 4315 4316 4317 4318 4319 4320 4321
  @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

4322 4323
  @note Sets error and fatal error if allocation fails.

unknown's avatar
unknown committed
4324 4325 4326 4327
  @retval
    false   success
  @retval
    true    failure
unknown's avatar
unknown committed
4328 4329 4330 4331
*/

static bool
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
4332 4333
            Item_result type, CHARSET_INFO *cs, Derivation dv,
            bool unsigned_arg)
unknown's avatar
unknown committed
4334
{
unknown's avatar
unknown committed
4335
  if (set_null)
unknown's avatar
unknown committed
4336 4337 4338
  {
    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
    if (entry->value && entry->value != pos)
4339
      my_free(entry->value);
4340 4341
    entry->value= 0;
    entry->length= 0;
unknown's avatar
unknown committed
4342 4343 4344
  }
  else
  {
4345 4346
    if (type == STRING_RESULT)
      length++;					// Store strings with end \0
unknown's avatar
unknown committed
4347 4348 4349 4350 4351 4352 4353
    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)
4354
	  my_free(entry->value);
unknown's avatar
unknown committed
4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365
	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;
4366
        entry->value= (char*) my_realloc(entry->value, length,
4367 4368
                                         MYF(MY_ALLOW_ZERO_PTR | MY_WME |
                                             ME_FATALERROR));
4369
        if (!entry->value)
unknown's avatar
unknown committed
4370
	  return 1;
unknown's avatar
unknown committed
4371 4372
      }
    }
4373 4374 4375 4376 4377
    if (type == STRING_RESULT)
    {
      length--;					// Fix length change above
      entry->value[length]= 0;			// Store end \0
    }
4378
    memmove(entry->value, ptr, length);
unknown's avatar
unknown committed
4379 4380
    if (type == DECIMAL_RESULT)
      ((my_decimal*)entry->value)->fix_buffer_pointer();
unknown's avatar
unknown committed
4381
    entry->length= length;
4382
    entry->collation.set(cs, dv);
unknown's avatar
unknown committed
4383
    entry->unsigned_flag= unsigned_arg;
unknown's avatar
unknown committed
4384
  }
4385
  entry->type=type;
4386
  return 0;
unknown's avatar
unknown committed
4387
}
unknown's avatar
unknown committed
4388

unknown's avatar
unknown committed
4389 4390

bool
4391 4392
Item_func_set_user_var::update_hash(void *ptr, uint length,
                                    Item_result res_type,
4393 4394
                                    CHARSET_INFO *cs, Derivation dv,
                                    bool unsigned_arg)
unknown's avatar
unknown committed
4395
{
4396 4397 4398 4399 4400
  /*
    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)
4401
    res_type= entry->type;                      // Don't change type of item
unknown's avatar
unknown committed
4402
  if (::update_hash(entry, (null_value= args[0]->null_value),
4403
                    ptr, length, res_type, cs, dv, unsigned_arg))
unknown's avatar
unknown committed
4404 4405 4406 4407 4408
  {
    null_value= 1;
    return 1;
  }
  return 0;
unknown's avatar
unknown committed
4409 4410 4411
}


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

unknown's avatar
unknown committed
4414
double user_var_entry::val_real(my_bool *null_value)
unknown's avatar
unknown committed
4415
{
4416 4417 4418 4419 4420 4421 4422 4423
  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
4424 4425 4426 4427 4428 4429
  case DECIMAL_RESULT:
  {
    double result;
    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
    return result;
  }
4430
  case STRING_RESULT:
unknown's avatar
unknown committed
4431
    return my_atof(value);                      // This is null terminated
4432 4433 4434
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
unknown's avatar
unknown committed
4435
  }
4436
  return 0.0;					// Impossible
unknown's avatar
unknown committed
4437 4438 4439
}


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

4442
longlong user_var_entry::val_int(my_bool *null_value) const
unknown's avatar
unknown committed
4443
{
4444 4445 4446 4447 4448 4449 4450 4451
  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
4452 4453 4454
  case DECIMAL_RESULT:
  {
    longlong result;
4455
    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
unknown's avatar
unknown committed
4456 4457
    return result;
  }
unknown's avatar
unknown committed
4458
  case STRING_RESULT:
unknown's avatar
unknown committed
4459 4460 4461 4462
  {
    int error;
    return my_strtoll10(value, (char**) 0, &error);// String is null terminated
  }
4463 4464 4465
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
unknown's avatar
unknown committed
4466
  }
4467 4468 4469 4470
  return LL(0);					// Impossible
}


unknown's avatar
unknown committed
4471
/** Get the value of a variable as a string. */
4472 4473 4474 4475 4476 4477 4478 4479 4480

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:
4481
    str->set_real(*(double*) value, decimals, collation.collation);
4482 4483
    break;
  case INT_RESULT:
4484
    if (!unsigned_flag)
4485
      str->set(*(longlong*) value, collation.collation);
4486
    else
4487
      str->set(*(ulonglong*) value, collation.collation);
4488
    break;
unknown's avatar
unknown committed
4489
  case DECIMAL_RESULT:
4490
    str_set_decimal((my_decimal *) value, str, collation.collation);
unknown's avatar
unknown committed
4491
    break;
4492
  case STRING_RESULT:
unknown's avatar
unknown committed
4493
    if (str->copy(value, length, collation.collation))
4494
      str= 0;					// EOM error
4495 4496 4497
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
unknown's avatar
unknown committed
4498
  }
4499
  return(str);
unknown's avatar
unknown committed
4500 4501
}

unknown's avatar
unknown committed
4502
/** Get the value of a variable as a decimal. */
unknown's avatar
unknown committed
4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516

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:
4517
    my_decimal2decimal((my_decimal *) value, val);
unknown's avatar
unknown committed
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528
    break;
  case STRING_RESULT:
    str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
    break;
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
  }
  return(val);
}

unknown's avatar
unknown committed
4529 4530 4531
/**
  This functions is invoked on SET \@variable or
  \@variable:= expression.
4532

unknown's avatar
unknown committed
4533
  Evaluate (and check expression), store results.
4534

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

unknown's avatar
unknown committed
4539
  @retval
unknown's avatar
unknown committed
4540
    FALSE OK.
4541 4542 4543
*/

bool
4544
Item_func_set_user_var::check(bool use_result_field)
4545 4546
{
  DBUG_ENTER("Item_func_set_user_var::check");
unknown's avatar
unknown committed
4547 4548
  if (use_result_field && !result_field)
    use_result_field= FALSE;
4549 4550 4551 4552

  switch (cached_result_type) {
  case REAL_RESULT:
  {
4553 4554
    save_result.vreal= use_result_field ? result_field->val_real() :
                        args[0]->val_real();
4555 4556 4557 4558
    break;
  }
  case INT_RESULT:
  {
4559 4560 4561 4562
    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;
4563 4564 4565 4566
    break;
  }
  case STRING_RESULT:
  {
4567 4568
    save_result.vstr= use_result_field ? result_field->val_str(&value) :
                       args[0]->val_str(&value);
4569 4570
    break;
  }
unknown's avatar
unknown committed
4571 4572
  case DECIMAL_RESULT:
  {
4573 4574 4575
    save_result.vdec= use_result_field ?
                       result_field->val_decimal(&decimal_buff) :
                       args[0]->val_decimal(&decimal_buff);
unknown's avatar
unknown committed
4576 4577
    break;
  }
4578 4579
  case ROW_RESULT:
  default:
unknown's avatar
unknown committed
4580
    // This case should never be chosen
4581 4582 4583
    DBUG_ASSERT(0);
    break;
  }
unknown's avatar
unknown committed
4584
  DBUG_RETURN(FALSE);
4585 4586
}

4587

4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622
/**
  @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
4623 4624 4625
/**
  This functions is invoked on
  SET \@variable or \@variable:= expression.
4626

unknown's avatar
unknown committed
4627
  @note
4628 4629 4630
    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
4631
  @retval
unknown's avatar
unknown committed
4632
    0	OK
unknown's avatar
unknown committed
4633
  @retval
4634 4635 4636 4637
    1	EOM Error

*/

unknown's avatar
unknown committed
4638 4639 4640
bool
Item_func_set_user_var::update()
{
Georgi Kodinov's avatar
Georgi Kodinov committed
4641
  bool res= 0;
4642 4643
  DBUG_ENTER("Item_func_set_user_var::update");

unknown's avatar
unknown committed
4644 4645
  switch (cached_result_type) {
  case REAL_RESULT:
unknown's avatar
unknown committed
4646
  {
4647
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
4648
		     REAL_RESULT, default_charset(), DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4649
    break;
unknown's avatar
unknown committed
4650
  }
unknown's avatar
unknown committed
4651
  case INT_RESULT:
4652
  {
4653
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
4654
                     INT_RESULT, default_charset(), DERIVATION_IMPLICIT,
4655
                     unsigned_flag);
unknown's avatar
unknown committed
4656
    break;
unknown's avatar
unknown committed
4657
  }
unknown's avatar
unknown committed
4658
  case STRING_RESULT:
unknown's avatar
unknown committed
4659
  {
4660
    if (!save_result.vstr)					// Null value
unknown's avatar
unknown committed
4661
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
unknown's avatar
unknown committed
4662
		       DERIVATION_IMPLICIT, 0);
4663
    else
4664 4665 4666
      res= update_hash((void*) save_result.vstr->ptr(),
		       save_result.vstr->length(), STRING_RESULT,
		       save_result.vstr->charset(),
unknown's avatar
unknown committed
4667
		       DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4668 4669
    break;
  }
unknown's avatar
unknown committed
4670 4671 4672 4673
  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
4674
                       DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4675 4676 4677
    else
      res= update_hash((void*) save_result.vdec,
                       sizeof(my_decimal), DECIMAL_RESULT,
4678
                       default_charset(), DERIVATION_IMPLICIT, 0);
unknown's avatar
unknown committed
4679 4680
    break;
  }
4681
  case ROW_RESULT:
unknown's avatar
unknown committed
4682
  default:
unknown's avatar
unknown committed
4683
    // This case should never be chosen
unknown's avatar
unknown committed
4684 4685 4686
    DBUG_ASSERT(0);
    break;
  }
4687
  DBUG_RETURN(res);
unknown's avatar
unknown committed
4688 4689 4690
}


4691
double Item_func_set_user_var::val_real()
unknown's avatar
unknown committed
4692
{
4693
  DBUG_ASSERT(fixed == 1);
4694
  check(0);
4695
  update();					// Store expression
unknown's avatar
unknown committed
4696
  return entry->val_real(&null_value);
unknown's avatar
unknown committed
4697 4698
}

4699
longlong Item_func_set_user_var::val_int()
unknown's avatar
unknown committed
4700
{
4701
  DBUG_ASSERT(fixed == 1);
4702
  check(0);
4703 4704
  update();					// Store expression
  return entry->val_int(&null_value);
unknown's avatar
unknown committed
4705 4706
}

4707
String *Item_func_set_user_var::val_str(String *str)
unknown's avatar
unknown committed
4708
{
4709
  DBUG_ASSERT(fixed == 1);
4710
  check(0);
4711 4712
  update();					// Store expression
  return entry->val_str(&null_value, str, decimals);
unknown's avatar
unknown committed
4713 4714 4715
}


unknown's avatar
unknown committed
4716 4717 4718
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
{
  DBUG_ASSERT(fixed == 1);
4719
  check(0);
unknown's avatar
unknown committed
4720 4721 4722 4723 4724
  update();					// Store expression
  return entry->val_decimal(&null_value, val);
}


unknown's avatar
unknown committed
4725
double Item_func_set_user_var::val_result()
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740
{
  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
merge  
Georgi Kodinov committed
4741 4742 4743 4744 4745 4746 4747 4748
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
4749
String *Item_func_set_user_var::str_result(String *str)
4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763
{
  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
4764 4765 4766
}


4767 4768 4769 4770 4771 4772 4773 4774 4775
bool Item_func_set_user_var::is_null_result()
{
  DBUG_ASSERT(fixed == 1);
  check(TRUE);
  update();					// Store expression
  return is_null();
}


4776
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
4777
{
4778
  str->append(STRING_WITH_LEN("(@"));
4779
  str->append(name.str, name.length);
4780
  str->append(STRING_WITH_LEN(":="));
4781
  args[0]->print(str, query_type);
unknown's avatar
unknown committed
4782 4783 4784 4785
  str->append(')');
}


4786 4787
void Item_func_set_user_var::print_as_stmt(String *str,
                                           enum_query_type query_type)
4788
{
4789
  str->append(STRING_WITH_LEN("set @"));
4790
  str->append(name.str, name.length);
4791
  str->append(STRING_WITH_LEN(":="));
4792
  args[0]->print(str, query_type);
4793 4794 4795
  str->append(')');
}

4796 4797 4798 4799 4800 4801 4802 4803 4804 4805
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);
}
4806

unknown's avatar
unknown committed
4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818
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);
}
4819

4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858

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

4859 4860
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
                                          bool can_use_result_field)
4861
{
4862 4863
  bool use_result_field= (!can_use_result_field ? 0 :
                          (result_field && result_field != field));
4864 4865 4866 4867 4868 4869 4870
  int error;

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

  if (result_type() == STRING_RESULT ||
4871 4872
      (result_type() == REAL_RESULT &&
      field->result_type() == STRING_RESULT))
4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902
  {
    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;
4903
    my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
4904 4905 4906
    if (null_value)
      return set_field_to_null(field);
    field->set_notnull();
4907
    error=field->store_decimal(val);
4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920
  }
  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
4921 4922 4923
String *
Item_func_get_user_var::val_str(String *str)
{
4924
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
4925
  DBUG_ENTER("Item_func_get_user_var::val_str");
4926
  if (!var_entry)
4927
    DBUG_RETURN((String*) 0);			// No such variable
4928
  DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
unknown's avatar
unknown committed
4929 4930 4931
}


4932
double Item_func_get_user_var::val_real()
unknown's avatar
unknown committed
4933
{
4934
  DBUG_ASSERT(fixed == 1);
4935 4936
  if (!var_entry)
    return 0.0;					// No such variable
unknown's avatar
unknown committed
4937 4938 4939 4940 4941 4942 4943 4944 4945 4946
  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
4947 4948 4949 4950 4951
}


longlong Item_func_get_user_var::val_int()
{
4952
  DBUG_ASSERT(fixed == 1);
4953 4954 4955
  if (!var_entry)
    return LL(0);				// No such variable
  return (var_entry->val_int(&null_value));
unknown's avatar
unknown committed
4956 4957 4958
}


unknown's avatar
unknown committed
4959
/**
4960 4961 4962
  Get variable by name and, if necessary, put the record of variable 
  use into the binary log.

4963 4964 4965 4966
  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).
4967

unknown's avatar
unknown committed
4968 4969 4970 4971 4972 4973
  @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
4974
    0  OK
unknown's avatar
unknown committed
4975
  @retval
unknown's avatar
unknown committed
4976
    1  Failed to put appropriate record into binary log
4977

4978 4979
*/

4980 4981 4982
static 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
4983
{
4984
  BINLOG_USER_VAR_EVENT *user_var_event;
4985 4986
  user_var_entry *var_entry;
  var_entry= get_variable(&thd->user_vars, name, 0);
4987

4988 4989
  /*
    Any reference to user-defined variable which is done from stored
4990 4991 4992
    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.
4993 4994 4995
  */
  if (!(opt_bin_log && 
       (is_update_query(sql_command) || thd->in_sub_stmt)))
4996 4997 4998 4999
  {
    *out_entry= var_entry;
    return 0;
  }
5000 5001

  if (!var_entry)
unknown's avatar
unknown committed
5002
  {
5003
    /*
5004 5005 5006 5007
      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
5008 5009
      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;'.
5010 5011 5012
      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();
5013 5014
      this would save memory and time; but calling sql_set_variables() makes
      one unique place to maintain (sql_set_variables()). 
5015 5016 5017

      Manipulation with lex is necessary since free_underlaid_joins
      is going to release memory belonging to the main query.
5018 5019 5020
    */

    List<set_var_base> tmp_var_list;
5021 5022
    LEX *sav_lex= thd->lex, lex_tmp;
    thd->lex= &lex_tmp;
5023
    lex_start(thd);
5024 5025
    tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
                                                                       new Item_null())));
5026 5027
    /* Create the variable */
    if (sql_set_variables(thd, &tmp_var_list))
5028 5029
    {
      thd->lex= sav_lex;
5030
      goto err;
5031 5032
    }
    thd->lex= sav_lex;
5033 5034 5035
    if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
      goto err;
  }
5036 5037
  else if (var_entry->used_query_id == thd->query_id ||
           mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
5038 5039 5040 5041 5042 5043 5044 5045 5046
  {
    /* 
       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;
  }
5047 5048 5049 5050

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

5056 5057 5058 5059
    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.
5060
  */
5061 5062 5063
  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)))
5064
    goto err;
5065

5066 5067 5068 5069 5070
  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;
5071
  user_var_event->unsigned_flag= var_entry->unsigned_flag;
5072 5073 5074 5075 5076
  if (!var_entry->value)
  {
    /* NULL value*/
    user_var_event->length= 0;
    user_var_event->value= 0;
unknown's avatar
unknown committed
5077
  }
5078 5079 5080 5081 5082 5083 5084 5085
  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;
5086
  if (insert_dynamic(&thd->user_var_events, (uchar*) &user_var_event))
5087
    goto err;
5088

5089 5090
  *out_entry= var_entry;
  return 0;
5091

unknown's avatar
unknown committed
5092
err:
5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103
  *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;
5104

5105
  error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
5106

5107 5108 5109 5110 5111
  /*
    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.
  */
5112
  if (!error && var_entry)
5113
  {
5114 5115 5116 5117
    m_cached_result_type= var_entry->type;
    unsigned_flag= var_entry->unsigned_flag;
    max_length= var_entry->length;

5118
    collation.set(var_entry->collation);
5119
    switch(m_cached_result_type) {
5120
    case REAL_RESULT:
5121
      fix_char_length(DBL_DIG + 8);
unknown's avatar
unknown committed
5122
      break;
5123
    case INT_RESULT:
5124
      fix_char_length(MAX_BIGINT_WIDTH);
unknown's avatar
unknown committed
5125
      decimals=0;
5126 5127
      break;
    case STRING_RESULT:
5128
      max_length= MAX_BLOB_WIDTH - 1;
5129
      break;
unknown's avatar
unknown committed
5130
    case DECIMAL_RESULT:
5131
      fix_char_length(DECIMAL_MAX_STR_LENGTH);
unknown's avatar
unknown committed
5132
      decimals= DECIMAL_MAX_SCALE;
unknown's avatar
unknown committed
5133
      break;
unknown's avatar
unknown committed
5134
    case ROW_RESULT:                            // Keep compiler happy
unknown's avatar
unknown committed
5135 5136
    default:
      DBUG_ASSERT(0);
unknown's avatar
unknown committed
5137
      break;
5138 5139
    }
  }
5140
  else
5141 5142
  {
    collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
5143
    null_value= 1;
5144 5145
    m_cached_result_type= STRING_RESULT;
    max_length= MAX_BLOB_WIDTH;
5146
  }
unknown's avatar
unknown committed
5147 5148 5149
}


5150
bool Item_func_get_user_var::const_item() const
5151
{
5152
  return (!var_entry || current_thd->query_id != var_entry->update_query_id);
5153
}
unknown's avatar
unknown committed
5154 5155 5156 5157


enum Item_result Item_func_get_user_var::result_type() const
{
5158
  return m_cached_result_type;
unknown's avatar
unknown committed
5159 5160
}

unknown's avatar
unknown committed
5161

5162
void Item_func_get_user_var::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
5163
{
5164
  str->append(STRING_WITH_LEN("(@"));
unknown's avatar
unknown committed
5165 5166 5167 5168
  str->append(name.str,name.length);
  str->append(')');
}

5169

5170
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
unknown's avatar
unknown committed
5171 5172 5173 5174 5175 5176
{
  /* 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 ||
5177
      ((Item_func*) item)->functype() != functype())
unknown's avatar
unknown committed
5178 5179 5180 5181 5182 5183 5184
    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));
}


5185
bool Item_func_get_user_var::set_value(THD *thd,
5186
                                       sp_rcontext * /*ctx*/, Item **it)
5187
{
5188
  Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it);
5189 5190 5191 5192
  /*
    Item_func_set_user_var is not fixed after construction, call
    fix_fields().
  */
5193
  return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
5194 5195 5196
}


5197
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
5198 5199
{
  DBUG_ASSERT(fixed == 0);
5200
  DBUG_ASSERT(thd->lex->exchange);
5201
  if (Item::fix_fields(thd, ref) ||
unknown's avatar
unknown committed
5202 5203 5204 5205 5206 5207 5208 5209
      !(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).
  */
5210 5211 5212
  entry->collation.set(thd->lex->exchange->cs ? 
                       thd->lex->exchange->cs :
                       thd->variables.collation_database);
unknown's avatar
unknown committed
5213 5214 5215 5216 5217 5218 5219
  entry->update_query_id= thd->query_id;
  return FALSE;
}


void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
5220 5221
  ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
unknown's avatar
unknown committed
5222 5223 5224 5225 5226 5227
}


void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                           CHARSET_INFO* cs)
{
5228 5229
  ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
                DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
unknown's avatar
unknown committed
5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260
}


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


5261
void Item_user_var_as_out_param::print(String *str, enum_query_type query_type)
unknown's avatar
unknown committed
5262 5263 5264 5265 5266 5267
{
  str->append('@');
  str->append(name.str,name.length);
}


5268 5269 5270 5271
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
5272 5273
  :var(var_arg), var_type(var_type_arg), orig_var_type(var_type_arg),
  component(*component_arg), cache_present(0)
5274 5275
{
  /* set_name() will allocate the name */
5276
  set_name(name_arg, (uint) name_len_arg, system_charset_info);
5277 5278 5279
}


5280
bool Item_func_get_system_var::is_written_to_binlog()
5281
{
5282 5283 5284 5285
  return var->is_written_to_binlog(var_type);
}


5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
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;
}


5296 5297
void Item_func_get_system_var::fix_length_and_dec()
{
5298
  char *cptr;
5299
  maybe_null= TRUE;
5300
  max_length= 0;
5301 5302 5303 5304 5305 5306

  if (var->check_type(var_type))
  {
    if (var_type != OPT_DEFAULT)
    {
      my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
5307
               var->name.str, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319
      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;
5320 5321
      collation.set_numeric();
      fix_char_length(MY_INT64_NUM_DECIMAL_DIGITS);
5322 5323 5324
      decimals=0;
      break;
    case SHOW_LONGLONG:
5325
      unsigned_flag= TRUE;
5326 5327
      collation.set_numeric();
      fix_char_length(MY_INT64_NUM_DECIMAL_DIGITS);
5328 5329 5330 5331
      decimals=0;
      break;
    case SHOW_CHAR:
    case SHOW_CHAR_PTR:
Marc Alff's avatar
Marc Alff committed
5332
      mysql_mutex_lock(&LOCK_global_system_variables);
5333 5334 5335
      cptr= var->show_type() == SHOW_CHAR ? 
        (char*) var->value_ptr(current_thd, var_type, &component) :
        *(char**) var->value_ptr(current_thd, var_type, &component);
5336
      if (cptr)
5337 5338 5339
        max_length= system_charset_info->cset->numchars(system_charset_info,
                                                        cptr,
                                                        cptr + strlen(cptr));
Marc Alff's avatar
Marc Alff committed
5340
      mysql_mutex_unlock(&LOCK_global_system_variables);
5341
      collation.set(system_charset_info, DERIVATION_SYSCONST);
5342
      max_length*= system_charset_info->mbmaxlen;
5343 5344
      decimals=NOT_FIXED_DEC;
      break;
5345 5346
    case SHOW_LEX_STRING:
      {
Marc Alff's avatar
Marc Alff committed
5347
        mysql_mutex_lock(&LOCK_global_system_variables);
5348 5349 5350 5351
        LEX_STRING *ls= ((LEX_STRING*)var->value_ptr(current_thd, var_type, &component));
        max_length= system_charset_info->cset->numchars(system_charset_info,
                                                        ls->str,
                                                        ls->str + ls->length);
Marc Alff's avatar
Marc Alff committed
5352
        mysql_mutex_unlock(&LOCK_global_system_variables);
5353 5354 5355 5356 5357
        collation.set(system_charset_info, DERIVATION_SYSCONST);
        max_length*= system_charset_info->mbmaxlen;
        decimals=NOT_FIXED_DEC;
      }
      break;
5358
    case SHOW_BOOL:
5359 5360
    case SHOW_MY_BOOL:
      unsigned_flag= FALSE;
5361 5362
      collation.set_numeric();
      fix_char_length(1);
5363 5364 5365 5366 5367
      decimals=0;
      break;
    case SHOW_DOUBLE:
      unsigned_flag= FALSE;
      decimals= 6;
5368 5369
      collation.set_numeric();
      fix_char_length(DBL_DIG + 6);
5370 5371
      break;
    default:
5372
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
5373 5374 5375
      break;
  }
}
5376

5377

5378 5379 5380
void Item_func_get_system_var::print(String *str, enum_query_type query_type)
{
  str->append(name, name_length);
5381 5382 5383
}


5384
enum Item_result Item_func_get_system_var::result_type() const
5385
{
5386 5387
  switch (var->show_type())
  {
5388
    case SHOW_BOOL:
5389 5390 5391 5392 5393 5394 5395 5396
    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: 
5397
    case SHOW_LEX_STRING:
5398 5399 5400 5401
      return STRING_RESULT;
    case SHOW_DOUBLE:
      return REAL_RESULT;
    default:
5402
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
5403 5404 5405 5406 5407 5408 5409 5410 5411
      return STRING_RESULT;                   // keep the compiler happy
  }
}


enum_field_types Item_func_get_system_var::field_type() const
{
  switch (var->show_type())
  {
5412
    case SHOW_BOOL:
5413 5414 5415 5416 5417 5418 5419 5420
    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: 
5421
    case SHOW_LEX_STRING:
5422 5423 5424 5425
      return MYSQL_TYPE_VARCHAR;
    case SHOW_DOUBLE:
      return MYSQL_TYPE_DOUBLE;
    default:
5426
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
5427 5428 5429 5430 5431
      return MYSQL_TYPE_VARCHAR;              // keep the compiler happy
  }
}


5432 5433 5434 5435
/*
  Uses var, var_type, component, cache_present, used_query_id, thd,
  cached_llval, null_value, cached_null_value
*/
5436 5437 5438
#define get_sys_var_safe(type) \
do { \
  type value; \
Marc Alff's avatar
Marc Alff committed
5439
  mysql_mutex_lock(&LOCK_global_system_variables); \
5440
  value= *(type*) var->value_ptr(thd, var_type, &component); \
Marc Alff's avatar
Marc Alff committed
5441
  mysql_mutex_unlock(&LOCK_global_system_variables); \
5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453
  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
5454
  if (cache_present && thd->query_id == used_query_id)
5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486
  {
    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);
5487
    case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
5488
    case SHOW_HA_ROWS:  get_sys_var_safe (ha_rows);
5489
    case SHOW_BOOL:     get_sys_var_safe (bool);
5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501
    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:
5502
    case SHOW_LEX_STRING:
5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521
      {
        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:            
5522
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); 
5523 5524 5525 5526 5527 5528 5529 5530 5531
      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
5532
  if (cache_present && thd->query_id == used_query_id)
5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561
  {
    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:
5562
    case SHOW_LEX_STRING:
5563
    {
Marc Alff's avatar
Marc Alff committed
5564
      mysql_mutex_lock(&LOCK_global_system_variables);
5565 5566 5567
      char *cptr= var->show_type() == SHOW_CHAR ? 
        (char*) var->value_ptr(thd, var_type, &component) :
        *(char**) var->value_ptr(thd, var_type, &component);
5568 5569
      if (cptr)
      {
5570 5571 5572 5573
        size_t len= var->show_type() == SHOW_LEX_STRING ?
          ((LEX_STRING*)(var->value_ptr(thd, var_type, &component)))->length :
          strlen(cptr);
        if (str->copy(cptr, len, collation.collation))
5574 5575 5576 5577 5578 5579 5580 5581 5582 5583
        {
          null_value= TRUE;
          str= NULL;
        }
      }
      else
      {
        null_value= TRUE;
        str= NULL;
      }
Marc Alff's avatar
Marc Alff committed
5584
      mysql_mutex_unlock(&LOCK_global_system_variables);
5585 5586 5587 5588 5589 5590 5591
      break;
    }

    case SHOW_INT:
    case SHOW_LONG:
    case SHOW_LONGLONG:
    case SHOW_HA_ROWS:
5592
    case SHOW_BOOL:
5593 5594 5595 5596 5597 5598 5599 5600
    case SHOW_MY_BOOL:
      str->set (val_int(), collation.collation);
      break;
    case SHOW_DOUBLE:
      str->set_real (val_real(), decimals, collation.collation);
      break;

    default:
5601
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616
      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
5617
  if (cache_present && thd->query_id == used_query_id)
5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648
  {
    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:
Marc Alff's avatar
Marc Alff committed
5649
      mysql_mutex_lock(&LOCK_global_system_variables);
5650
      cached_dval= *(double*) var->value_ptr(thd, var_type, &component);
Marc Alff's avatar
Marc Alff committed
5651
      mysql_mutex_unlock(&LOCK_global_system_variables);
5652 5653 5654 5655 5656 5657 5658
      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:
5659
    case SHOW_LEX_STRING:
5660 5661
    case SHOW_CHAR_PTR:
      {
Marc Alff's avatar
Marc Alff committed
5662
        mysql_mutex_lock(&LOCK_global_system_variables);
5663
        char *cptr= var->show_type() == SHOW_CHAR ? 
5664 5665 5666 5667 5668 5669 5670 5671 5672 5673
          (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;
        }
Marc Alff's avatar
Marc Alff committed
5674
        mysql_mutex_unlock(&LOCK_global_system_variables);
5675 5676 5677 5678 5679 5680 5681 5682 5683
        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:
5684
    case SHOW_BOOL:
5685 5686 5687 5688 5689 5690 5691
    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:
5692
      my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708
      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);
5709 5710 5711
}


Georgi Kodinov's avatar
Georgi Kodinov committed
5712 5713 5714
void Item_func_get_system_var::cleanup()
{
  Item_func::cleanup();
Georgi Kodinov's avatar
Georgi Kodinov committed
5715
  cache_present= 0;
Georgi Kodinov's avatar
Georgi Kodinov committed
5716 5717 5718 5719 5720
  var_type= orig_var_type;
  cached_strval.free();
}


unknown's avatar
unknown committed
5721 5722
longlong Item_func_inet_aton::val_int()
{
5723
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
5724 5725 5726 5727 5728
  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];
5729
  int dot_count= 0;
unknown's avatar
unknown committed
5730

5731 5732
  String *s, tmp(buff, sizeof(buff), &my_charset_latin1);
  if (!(s = args[0]->val_str_ascii(&tmp)))       // If null value
unknown's avatar
unknown committed
5733 5734 5735 5736 5737 5738 5739
    goto err;
  null_value=0;

  end= (p = s->ptr()) + s->length();
  while (p < end)
  {
    c = *p++;
5740
    int digit = (int) (c - '0');
unknown's avatar
unknown committed
5741 5742 5743 5744 5745 5746 5747
    if (digit >= 0 && digit <= 9)
    {
      if ((byte_result = byte_result * 10 + digit) > 255)
	goto err;				// Wrong address
    }
    else if (c == '.')
    {
5748
      dot_count++;
unknown's avatar
unknown committed
5749 5750 5751 5752 5753 5754 5755
      result= (result << 8) + (ulonglong) byte_result;
      byte_result = 0;
    }
    else
      goto err;					// Invalid character
  }
  if (c != '.')					// IP number can't end on '.'
5756
  {
5757 5758 5759 5760 5761 5762
    /*
      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
5763
    switch (dot_count) {
5764 5765
    case 1: result<<= 8; /* Fall through */
    case 2: result<<= 8; /* Fall through */
5766
    }
unknown's avatar
unknown committed
5767
    return (result << 8) + (ulonglong) byte_result;
5768
  }
unknown's avatar
unknown committed
5769 5770 5771 5772 5773 5774

err:
  null_value=1;
  return 0;
}

unknown's avatar
unknown committed
5775

unknown's avatar
unknown committed
5776
void Item_func_match::init_search(bool no_order)
5777
{
unknown's avatar
unknown committed
5778
  DBUG_ENTER("Item_func_match::init_search");
5779 5780

  /* Check if init_search() has been called before */
5781
  if (ft_handler)
5782 5783 5784 5785 5786 5787 5788 5789 5790
  {
    /*
      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
5791
    DBUG_VOID_RETURN;
5792
  }
5793

5794
  if (key == NO_SUCH_KEY)
5795 5796
  {
    List<Item> fields;
5797
    fields.push_back(new Item_string(" ",1, cmp_collation.collation));
5798 5799
    for (uint i=1; i < arg_count; i++)
      fields.push_back(args[i]);
5800
    concat_ws=new Item_func_concat_ws(fields);
unknown's avatar
unknown committed
5801 5802 5803
    /*
      Above function used only to get value and do not need fix_fields for it:
      Item_string - basic constant
unknown's avatar
unknown committed
5804 5805
      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
5806
    */
5807
    concat_ws->quick_fix_field();
5808
  }
5809

5810 5811
  if (master)
  {
unknown's avatar
unknown committed
5812 5813
    join_key=master->join_key=join_key|master->join_key;
    master->init_search(no_order);
5814 5815
    ft_handler=master->ft_handler;
    join_key=master->join_key;
unknown's avatar
unknown committed
5816
    DBUG_VOID_RETURN;
5817 5818
  }

unknown's avatar
unknown committed
5819
  String *ft_tmp= 0;
5820

5821
  // MATCH ... AGAINST (NULL) is meaningless, but possible
5822
  if (!(ft_tmp=key_item()->val_str(&value)))
5823
  {
5824 5825
    ft_tmp= &value;
    value.set("",0,cmp_collation.collation);
5826 5827
  }

5828 5829
  if (ft_tmp->charset() != cmp_collation.collation)
  {
unknown's avatar
unknown committed
5830
    uint dummy_errors;
5831
    search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
unknown's avatar
unknown committed
5832
                      cmp_collation.collation, &dummy_errors);
5833
    ft_tmp= &search_value;
5834 5835
  }

5836 5837
  if (join_key && !no_order)
    flags|=FT_SORTED;
5838
  ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
5839 5840 5841

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

  DBUG_VOID_RETURN;
5844 5845
}

unknown's avatar
unknown committed
5846

5847
bool Item_func_match::fix_fields(THD *thd, Item **ref)
unknown's avatar
unknown committed
5848
{
5849
  DBUG_ASSERT(fixed == 0);
5850
  Item *UNINIT_VAR(item);                        // Safe as arg_count is > 1
unknown's avatar
unknown committed
5851

5852 5853 5854
  maybe_null=1;
  join_key=0;

5855 5856 5857 5858 5859
  /*
    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.
5860
   */
5861
  if (Item_func::fix_fields(thd, ref) ||
5862
      !args[0]->const_during_execution())
5863 5864
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
unknown's avatar
unknown committed
5865
    return TRUE;
5866
  }
unknown's avatar
unknown committed
5867

5868 5869
  const_item_cache=0;
  for (uint i=1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
5870
  {
5871
    item=args[i];
unknown's avatar
unknown committed
5872
    if (item->type() == Item::REF_ITEM)
5873 5874
      args[i]= item= *((Item_ref *)item)->ref;
    if (item->type() != Item::FIELD_ITEM)
5875 5876 5877 5878
    {
      my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
      return TRUE;
    }
unknown's avatar
unknown committed
5879
  }
5880 5881
  /*
    Check that all columns come from the same table.
5882
    We've already checked that columns in MATCH are fields so
5883 5884 5885
    PARAM_TABLE_BIT can only appear from AGAINST argument.
  */
  if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
5886
    key=NO_SUCH_KEY;
5887

5888
  if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
5889 5890
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
unknown's avatar
unknown committed
5891
    return TRUE;
5892
  }
5893
  table=((Item_field *)item)->field->table;
5894
  if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
5895
  {
unknown's avatar
unknown committed
5896
    my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
unknown's avatar
unknown committed
5897
    return 1;
5898
  }
5899
  table->fulltext_searched=1;
5900 5901
  return agg_item_collations_for_comparison(cmp_collation, func_name(),
                                            args+1, arg_count-1, 0);
unknown's avatar
unknown committed
5902
}
5903

unknown's avatar
unknown committed
5904 5905 5906
bool Item_func_match::fix_index()
{
  Item_field *item;
5907
  uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
5908
  uint max_cnt=0, mkeys=0, i;
5909

5910
  if (key == NO_SUCH_KEY)
5911
    return 0;
5912 5913 5914
  
  if (!table) 
    goto err;
unknown's avatar
unknown committed
5915

5916
  for (keynr=0 ; keynr < table->s->keys ; keynr++)
unknown's avatar
unknown committed
5917
  {
5918
    if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
5919 5920 5921
        (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
5922
    {
5923
      ft_to_key[fts]=keynr;
unknown's avatar
unknown committed
5924 5925 5926 5927 5928 5929
      ft_cnt[fts]=0;
      fts++;
    }
  }

  if (!fts)
5930
    goto err;
unknown's avatar
unknown committed
5931

5932
  for (i=1; i < arg_count; i++)
unknown's avatar
unknown committed
5933
  {
5934
    item=(Item_field*)args[i];
5935
    for (keynr=0 ; keynr < fts ; keynr++)
unknown's avatar
unknown committed
5936
    {
5937
      KEY *ft_key=&table->key_info[ft_to_key[keynr]];
unknown's avatar
unknown committed
5938 5939 5940 5941 5942
      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))
5943
	  ft_cnt[keynr]++;
unknown's avatar
unknown committed
5944 5945 5946 5947
      }
    }
  }

5948
  for (keynr=0 ; keynr < fts ; keynr++)
unknown's avatar
unknown committed
5949
  {
5950
    if (ft_cnt[keynr] > max_cnt)
unknown's avatar
unknown committed
5951
    {
5952
      mkeys=0;
5953 5954
      max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
5955 5956
      continue;
    }
5957
    if (max_cnt && ft_cnt[keynr] == max_cnt)
5958 5959
    {
      mkeys++;
5960 5961
      ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
5962
      continue;
unknown's avatar
unknown committed
5963 5964 5965
    }
  }

5966
  for (keynr=0 ; keynr <= mkeys ; keynr++)
unknown's avatar
unknown committed
5967
  {
5968 5969
    // partial keys doesn't work
    if (max_cnt < arg_count-1 ||
5970
        max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
5971
      continue;
unknown's avatar
unknown committed
5972

5973
    key=ft_to_key[keynr];
5974

5975 5976 5977
    return 0;
  }

5978
err:
5979
  if (flags & FT_BOOL)
5980
  {
5981
    key=NO_SUCH_KEY;
5982 5983
    return 0;
  }
unknown's avatar
unknown committed
5984 5985
  my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
             ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
5986
  return 1;
5987 5988
}

5989

5990
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
5991
{
unknown's avatar
unknown committed
5992 5993
  if (item->type() != FUNC_ITEM ||
      ((Item_func*)item)->functype() != FT_FUNC ||
5994
      flags != ((Item_func_match*)item)->flags)
5995 5996 5997 5998 5999
    return 0;

  Item_func_match *ifm=(Item_func_match*) item;

  if (key == ifm->key && table == ifm->table &&
6000
      key_item()->eq(ifm->key_item(), binary_cmp))
6001
    return 1;
unknown's avatar
unknown committed
6002 6003 6004 6005

  return 0;
}

6006

6007
double Item_func_match::val_real()
unknown's avatar
unknown committed
6008
{
6009
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
6010
  DBUG_ENTER("Item_func_match::val");
unknown's avatar
unknown committed
6011
  if (ft_handler == NULL)
unknown's avatar
unknown committed
6012
    DBUG_RETURN(-1.0);
unknown's avatar
unknown committed
6013

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

unknown's avatar
unknown committed
6017 6018 6019
  if (join_key)
  {
    if (table->file->ft_handler)
unknown's avatar
unknown committed
6020
      DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
unknown's avatar
unknown committed
6021 6022 6023
    join_key=0;
  }

6024
  if (key == NO_SUCH_KEY)
unknown's avatar
unknown committed
6025
  {
6026 6027
    String *a= concat_ws->val_str(&value);
    if ((null_value= (a == 0)) || !a->length())
unknown's avatar
unknown committed
6028 6029
      DBUG_RETURN(0);
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
6030
				      (uchar *)a->ptr(), a->length()));
unknown's avatar
unknown committed
6031
  }
unknown's avatar
unknown committed
6032 6033
  DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
                                                 table->record[0], 0));
unknown's avatar
unknown committed
6034 6035
}

6036
void Item_func_match::print(String *str, enum_query_type query_type)
6037
{
6038
  str->append(STRING_WITH_LEN("(match "));
6039
  print_args(str, 1, query_type);
6040
  str->append(STRING_WITH_LEN(" against ("));
6041
  args[0]->print(str, query_type);
unknown's avatar
unknown committed
6042
  if (flags & FT_BOOL)
6043
    str->append(STRING_WITH_LEN(" in boolean mode"));
unknown's avatar
unknown committed
6044
  else if (flags & FT_EXPAND)
6045 6046
    str->append(STRING_WITH_LEN(" with query expansion"));
  str->append(STRING_WITH_LEN("))"));
6047
}
unknown's avatar
unknown committed
6048

unknown's avatar
unknown committed
6049 6050
longlong Item_func_bit_xor::val_int()
{
6051
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
6052 6053
  ulonglong arg1= (ulonglong) args[0]->val_int();
  ulonglong arg2= (ulonglong) args[1]->val_int();
6054
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
unknown's avatar
unknown committed
6055 6056 6057 6058
    return 0;
  return (longlong) (arg1 ^ arg2);
}

6059

6060 6061 6062 6063
/***************************************************************************
  System variables
****************************************************************************/

unknown's avatar
unknown committed
6064 6065
/**
  Return value of an system variable base[.name] as a constant item.
6066

unknown's avatar
unknown committed
6067 6068 6069 6070
  @param thd			Thread handler
  @param var_type		global / session
  @param name		        Name of base or system variable
  @param component		Component.
6071

unknown's avatar
unknown committed
6072
  @note
6073 6074
    If component.str = 0 then the variable name is in 'name'

unknown's avatar
unknown committed
6075 6076 6077
  @return
    - 0  : error
    - #  : constant item
6078
*/
6079

6080 6081 6082

Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
		     LEX_STRING component)
6083
{
6084 6085 6086
  sys_var *var;
  LEX_STRING *base_name, *component_name;

6087 6088 6089 6090 6091 6092 6093 6094 6095 6096
  if (component.str)
  {
    base_name= &component;
    component_name= &name;
  }
  else
  {
    base_name= &name;
    component_name= &component;			// Empty string
  }
unknown's avatar
unknown committed
6097

unknown's avatar
WL#2936  
unknown committed
6098
  if (!(var= find_sys_var(thd, base_name->str, base_name->length)))
unknown's avatar
unknown committed
6099
    return 0;
6100 6101 6102 6103
  if (component.str)
  {
    if (!var->is_struct())
    {
6104
      my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
6105 6106 6107
      return 0;
    }
  }
unknown's avatar
unknown committed
6108
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
6109

6110 6111
  set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);

6112
  return new Item_func_get_system_var(var, var_type, component_name,
6113
                                      NULL, 0);
6114 6115 6116
}


unknown's avatar
unknown committed
6117
/**
unknown's avatar
unknown committed
6118
  Check a user level lock.
6119

unknown's avatar
unknown committed
6120
  Sets null_value=TRUE on error.
6121

unknown's avatar
unknown committed
6122
  @retval
6123
    1		Available
unknown's avatar
unknown committed
6124 6125
  @retval
    0		Already taken, or error
unknown's avatar
unknown committed
6126 6127
*/

6128
longlong Item_func_is_free_lock::val_int()
unknown's avatar
unknown committed
6129
{
6130
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
6131
  String *res=args[0]->val_str(&value);
6132
  User_level_lock *ull;
unknown's avatar
unknown committed
6133 6134

  null_value=0;
6135
  if (!res || !res->length())
unknown's avatar
unknown committed
6136 6137 6138 6139 6140
  {
    null_value=1;
    return 0;
  }
  
Marc Alff's avatar
Marc Alff committed
6141
  mysql_mutex_lock(&LOCK_user_locks);
Konstantin Osipov's avatar
Konstantin Osipov committed
6142 6143
  ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
                                          (size_t) res->length());
Marc Alff's avatar
Marc Alff committed
6144
  mysql_mutex_unlock(&LOCK_user_locks);
unknown's avatar
unknown committed
6145 6146 6147 6148
  if (!ull || !ull->locked)
    return 1;
  return 0;
}
unknown's avatar
unknown committed
6149

unknown's avatar
SCRUM  
unknown committed
6150 6151
longlong Item_func_is_used_lock::val_int()
{
6152
  DBUG_ASSERT(fixed == 1);
unknown's avatar
SCRUM  
unknown committed
6153
  String *res=args[0]->val_str(&value);
6154
  User_level_lock *ull;
unknown's avatar
SCRUM  
unknown committed
6155 6156 6157 6158 6159

  null_value=1;
  if (!res || !res->length())
    return 0;
  
Marc Alff's avatar
Marc Alff committed
6160
  mysql_mutex_lock(&LOCK_user_locks);
Konstantin Osipov's avatar
Konstantin Osipov committed
6161 6162
  ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
                                          (size_t) res->length());
Marc Alff's avatar
Marc Alff committed
6163
  mysql_mutex_unlock(&LOCK_user_locks);
unknown's avatar
SCRUM  
unknown committed
6164 6165 6166 6167 6168 6169 6170
  if (!ull || !ull->locked)
    return 0;

  null_value=0;
  return ull->thread_id;
}

6171

6172 6173 6174 6175 6176
longlong Item_func_row_count::val_int()
{
  DBUG_ASSERT(fixed == 1);
  THD *thd= current_thd;

6177
  return thd->get_row_count_func();
6178 6179 6180
}


6181 6182


6183
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
6184
  :Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
6185
{
unknown's avatar
unknown committed
6186
  maybe_null= 1;
6187
  m_name->init_qname(current_thd);
unknown's avatar
unknown committed
6188 6189
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
  dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
6190 6191
}

unknown's avatar
unknown committed
6192

6193 6194
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
                           sp_name *name, List<Item> &list)
6195
  :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
6196
{
unknown's avatar
unknown committed
6197
  maybe_null= 1;
6198
  m_name->init_qname(current_thd);
unknown's avatar
unknown committed
6199 6200
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
  dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
6201 6202
}

unknown's avatar
unknown committed
6203

6204 6205 6206
void
Item_func_sp::cleanup()
{
6207
  if (sp_result_field)
6208
  {
6209 6210
    delete sp_result_field;
    sp_result_field= NULL;
6211
  }
6212
  m_sp= NULL;
6213
  dummy_table->alias= NULL;
6214 6215
  Item_func::cleanup();
}
unknown's avatar
unknown committed
6216

6217 6218 6219
const char *
Item_func_sp::func_name() const
{
6220
  THD *thd= current_thd;
unknown's avatar
unknown committed
6221
  /* Calculate length to avoid reallocation of string for sure */
6222
  uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
6223 6224
              m_name->m_name.length)*2 + //characters*quoting
             2 +                         // ` and `
6225 6226
             (m_name->m_explicit_name ?
              3 : 0) +                   // '`', '`' and '.' for the db
6227 6228
             1 +                         // end of string
             ALIGN_SIZE(1));             // to avoid String reallocation
unknown's avatar
unknown committed
6229
  String qname((char *)alloc_root(thd->mem_root, len), len,
6230
               system_charset_info);
6231

6232
  qname.length(0);
6233 6234 6235 6236 6237
  if (m_name->m_explicit_name)
  {
    append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
    qname.append('.');
  }
6238 6239
  append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
  return qname.ptr();
6240 6241
}

6242

Marc Alff's avatar
Marc Alff committed
6243
void my_missing_function_error(const LEX_STRING &token, const char *func_name)
6244 6245
{
  if (token.length && is_lex_native_function (&token))
Marc Alff's avatar
Marc Alff committed
6246
    my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
6247
  else
Marc Alff's avatar
Marc Alff committed
6248
    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
6249 6250
}

6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268

/**
  @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.
*/
6269

6270 6271
bool
Item_func_sp::init_result_field(THD *thd)
unknown's avatar
unknown committed
6272
{
unknown's avatar
unknown committed
6273
  LEX_STRING empty_name= { C_STRING_WITH_LEN("") };
6274
  TABLE_SHARE *share;
6275
  DBUG_ENTER("Item_func_sp::init_result_field");
unknown's avatar
unknown committed
6276

6277 6278
  DBUG_ASSERT(m_sp == NULL);
  DBUG_ASSERT(sp_result_field == NULL);
unknown's avatar
unknown committed
6279

6280 6281
  if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
                               &thd->sp_func_cache, TRUE)))
unknown's avatar
unknown committed
6282
  {
6283
    my_missing_function_error (m_name->m_name, m_name->m_qname.str);
6284 6285
    context->process_error(thd);
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
6286
  }
6287 6288 6289 6290 6291 6292

  /*
     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
6293 6294 6295
  
  share= dummy_table->s;
  dummy_table->alias = "";
6296 6297 6298 6299 6300 6301
  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;

6302 6303
  if (!(sp_result_field= m_sp->create_result_field(max_length, name,
                                                   dummy_table)))
unknown's avatar
unknown committed
6304
  {
6305
   DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
6306
  }
6307 6308
  
  if (sp_result_field->pack_length() > sizeof(result_buf))
unknown's avatar
unknown committed
6309
  {
6310 6311 6312 6313
    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
6314
  }
6315 6316
  else
    sp_result_field->move_field(result_buf);
6317 6318 6319 6320
  
  sp_result_field->null_ptr= (uchar *) &null_value;
  sp_result_field->null_bit= 1;
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
6321 6322
}

6323

6324 6325
/**
  @brief Initialize local members with values from the Field interface.
unknown's avatar
unknown committed
6326

6327 6328
  @note called from Item::fix_fields.
*/
6329

6330 6331 6332
void Item_func_sp::fix_length_and_dec()
{
  DBUG_ENTER("Item_func_sp::fix_length_and_dec");
unknown's avatar
unknown committed
6333

6334 6335 6336 6337 6338 6339 6340 6341 6342 6343
  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;
}

6344

6345 6346 6347 6348 6349 6350
/**
  @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
6351 6352
*/

6353
bool
6354
Item_func_sp::execute()
6355
{
6356
  THD *thd= current_thd;
6357
  
6358 6359
  /* Execute function and store the return value in the field. */

6360
  if (execute_impl(thd))
6361 6362 6363
  {
    null_value= 1;
    context->process_error(thd);
6364 6365
    if (thd->killed)
      thd->send_kill_message();
6366 6367 6368 6369 6370
    return TRUE;
  }

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

6371
  null_value= sp_result_field->is_null();
6372 6373

  return null_value;
6374 6375 6376
}


6377 6378 6379 6380 6381 6382 6383 6384 6385 6386
/**
   @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.
*/
6387
bool
6388
Item_func_sp::execute_impl(THD *thd)
6389
{
6390
  bool err_status= TRUE;
6391
  Sub_statement_state statement_state;
6392 6393 6394
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  Security_context *save_security_ctx= thd->security_ctx;
#endif
6395 6396 6397
  enum enum_sp_data_access access=
    (m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
     SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
6398

6399 6400
  DBUG_ENTER("Item_func_sp::execute_impl");

6401 6402 6403 6404 6405 6406 6407
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  if (context->security_ctx)
  {
    /* Set view definer security context */
    thd->security_ctx= context->security_ctx;
  }
#endif
6408
  if (sp_check_access(thd))
6409
    goto error;
6410

6411 6412 6413 6414
  /*
    Throw an error if a non-deterministic function is called while
    statement-based replication (SBR) is active.
  */
6415

6416
  if (!m_sp->m_chistics->detistic && !trust_function_creators &&
6417
      (access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
6418 6419 6420
      (mysql_bin_log.is_open() &&
       thd->variables.binlog_format == BINLOG_FORMAT_STMT))
  {
6421
    my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
6422 6423 6424
    goto error;
  }

6425 6426 6427 6428 6429
  /*
    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.
  */
6430
  thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
6431
  err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field); 
6432
  thd->restore_sub_statement_state(&statement_state);
unknown's avatar
unknown committed
6433

6434
error:
6435
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
6436
  thd->security_ctx= save_security_ctx;
6437
#endif
6438

6439
  DBUG_RETURN(err_status);
6440 6441
}

6442

unknown's avatar
unknown committed
6443 6444 6445 6446
void
Item_func_sp::make_field(Send_field *tmp_field)
{
  DBUG_ENTER("Item_func_sp::make_field");
6447 6448
  DBUG_ASSERT(sp_result_field);
  sp_result_field->make_field(tmp_field);
6449 6450
  if (name)
    tmp_field->col_name= name;
unknown's avatar
unknown committed
6451 6452 6453 6454
  DBUG_VOID_RETURN;
}


6455 6456
enum enum_field_types
Item_func_sp::field_type() const
6457
{
6458
  DBUG_ENTER("Item_func_sp::field_type");
6459 6460
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field->type());
6461 6462
}

6463 6464
Item_result
Item_func_sp::result_type() const
6465
{
6466
  DBUG_ENTER("Item_func_sp::result_type");
6467
  DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
6468 6469
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field->result_type());
6470 6471
}

6472 6473 6474
longlong Item_func_found_rows::val_int()
{
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
6475
  return current_thd->found_rows();
6476
}
unknown's avatar
unknown committed
6477

unknown's avatar
unknown committed
6478

unknown's avatar
unknown committed
6479 6480 6481 6482 6483
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
  DBUG_ENTER("Item_func_sp::tmp_table_field");

6484 6485
  DBUG_ASSERT(sp_result_field);
  DBUG_RETURN(sp_result_field);
unknown's avatar
unknown committed
6486
}
6487

unknown's avatar
unknown committed
6488

6489 6490
/**
  @brief Checks if requested access to function can be granted to user.
6491 6492
    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
6493
    error is raised.
6494 6495 6496 6497 6498 6499 6500

  @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.
    
6501
*/
unknown's avatar
unknown committed
6502

6503
bool
6504
Item_func_sp::sp_check_access(THD *thd)
6505
{
6506 6507
  DBUG_ENTER("Item_func_sp::sp_check_access");
  DBUG_ASSERT(m_sp);
unknown's avatar
unknown committed
6508
#ifndef NO_EMBEDDED_ACCESS_CHECKS
6509
  if (check_routine_access(thd, EXECUTE_ACL,
unknown's avatar
unknown committed
6510
			   m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
6511
    DBUG_RETURN(TRUE);
6512
#endif
unknown's avatar
unknown committed
6513

6514
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
6515
}
6516

6517

6518 6519 6520 6521
bool
Item_func_sp::fix_fields(THD *thd, Item **ref)
{
  bool res;
6522
  DBUG_ENTER("Item_func_sp::fix_fields");
6523
  DBUG_ASSERT(fixed == 0);
6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534
 
  /*
    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);

6535
  res= Item_func::fix_fields(thd, ref);
6536 6537 6538 6539

  if (res)
    DBUG_RETURN(res);

Sergey Glukhov's avatar
Sergey Glukhov committed
6540
  if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
unknown's avatar
unknown committed
6541
  {
6542 6543
    /*
      Here we check privileges of the stored routine only during view
6544 6545 6546 6547 6548 6549 6550
      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.
6551
    */
6552
    res= sp_check_access(thd);
6553
#ifndef NO_EMBEDDED_ACCESS_CHECKS
6554 6555 6556
    /*
      Try to set and restore the security context to see whether it's valid
    */
6557
    Security_context *save_secutiry_ctx;
6558 6559
    res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
    if (!res)
6560
      m_sp->m_security_ctx.restore_security_context(thd, save_secutiry_ctx);
6561
    
6562
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
unknown's avatar
unknown committed
6563
  }
6564

unknown's avatar
unknown committed
6565
  if (!m_sp->m_chistics->detistic)
6566 6567 6568 6569 6570
  {
    used_tables_cache |= RAND_TABLE_BIT;
    const_item_cache= FALSE;
  }

6571
  DBUG_RETURN(res);
6572
}
6573 6574


unknown's avatar
unknown committed
6575 6576 6577
void Item_func_sp::update_used_tables()
{
  Item_func::update_used_tables();
6578

unknown's avatar
unknown committed
6579
  if (!m_sp->m_chistics->detistic)
6580 6581 6582 6583
  {
    used_tables_cache |= RAND_TABLE_BIT;
    const_item_cache= FALSE;
  }
unknown's avatar
unknown committed
6584
}
6585 6586


6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608
/*
  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()
{
6609 6610
  uuid_value= ((((ulonglong) server_id) << 56) + 
               (((ulonglong) server_start_time) << 24));
6611 6612 6613 6614 6615 6616
}


longlong Item_func_uuid_short::val_int()
{
  ulonglong val;
Marc Alff's avatar
Marc Alff committed
6617
  mysql_mutex_lock(&LOCK_uuid_generator);
6618
  val= uuid_value++;
Marc Alff's avatar
Marc Alff committed
6619
  mysql_mutex_unlock(&LOCK_uuid_generator);
6620 6621
  return (longlong) val;
}