item_func.cc 120 KB
Newer Older
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
1
/* Copyright (C) 2000-2003 MySQL AB
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* This file defines all numerical functions */

20
#ifdef USE_PRAGMA_IMPLEMENTATION
bk@work.mysql.com's avatar
bk@work.mysql.com committed
21 22 23 24
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
25
#include "slave.h"				// for wait_for_master_pos
bk@work.mysql.com's avatar
bk@work.mysql.com committed
26 27 28 29 30
#include <m_ctype.h>
#include <hash.h>
#include <time.h>
#include <ft_global.h>

31 32 33
#include "sp_head.h"
#include "sp_rcontext.h"
#include "sp.h"
34

35 36 37 38 39 40 41 42 43 44
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;
}


45 46
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
			      const char *fname)
47
{
48 49 50 51
  my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
           c1.collation->name, c1.derivation_name(),
           c2.collation->name, c2.derivation_name(),
           fname);
52 53
}

54
static void my_coll_agg_error(DTCollation &c1,
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
55 56 57 58
			       DTCollation &c2,
			       DTCollation &c3,
			       const char *fname)
{
59 60 61 62 63
  my_error(ER_CANT_AGGREGATE_3COLLATIONS, MYF(0),
           c1.collation->name, c1.derivation_name(),
           c2.collation->name, c2.derivation_name(),
           c3.collation->name, c3.derivation_name(),
           fname);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
64 65
}

66 67

static void my_coll_agg_error(Item** args, uint count, const char *fname)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
68
{
69
  if (count == 2)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
70
    my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
71
  else if (count == 3)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
72 73 74 75 76
    my_coll_agg_error(args[0]->collation,
		      args[1]->collation,
		      args[2]->collation,
		      fname);
  else
77
    my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), fname);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
78 79
}

80

81
bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
82
                                   uint flags)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
83 84
{
  uint i;
85
  c.set(av[0]->collation);
86
  for (i= 1; i < count; i++)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
87
  {
88
    if (c.aggregate(av[i]->collation, flags))
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
89
    {
90
      my_coll_agg_error(av, count, func_name());
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
91 92 93
      return TRUE;
    }
  }
bar@mysql.com's avatar
bar@mysql.com committed
94 95 96 97 98 99
  if ((flags & MY_COLL_DISALLOW_NONE) &&
      c.derivation == DERIVATION_NONE)
  {
    my_coll_agg_error(av, count, func_name());
    return TRUE;
  }
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
100 101 102
  return FALSE;
}

103

104
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
105
						  Item **av, uint count,
106
                                                  uint flags)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
107
{
bar@mysql.com's avatar
bar@mysql.com committed
108
  return (agg_arg_collations(c, av, count, flags | MY_COLL_DISALLOW_NONE));
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
109 110 111
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
112 113 114 115 116 117 118 119
/* return TRUE if item is a constant */

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

120

bar@mysql.com's avatar
bar@mysql.com committed
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

/* 
  Collect arguments' character sets together.
  We allow to apply automatic character set conversion in some cases.
  The conditions when conversion is possible are:
  - arguments A and B have different charsets
  - A wins according to coercibility rules
    (i.e. a column is stronger than a string constant,
     an explicit COLLATE clause is stronger than a column)
  - character set of A is either superset for character set of B,
    or B is a string constant which can be converted into the
    character set of A without data loss.
    
  If all of the above is true, then it's possible to convert
  B into the character set of A, and then compare according
  to the collation of A.
  
  For functions with more than two arguments:

    collect(A,B,C) ::= collect(collect(A,B),C)
*/

bool Item_func::agg_arg_charsets(DTCollation &coll,
                                 Item **args, uint nargs, uint flags)
{
  Item **arg, **last, *safe_args[2];
  if (agg_arg_collations(coll, args, nargs, flags))
    return TRUE;

  /*
    For better error reporting: save the first and the second argument.
    We need this only if the the number of args is 3 or 2:
    - for a longer argument list, "Illegal mix of collations"
      doesn't display each argument's characteristics.
    - if nargs is 1, then this error cannot happen.
  */
  if (nargs >=2 && nargs <= 3)
  {
    safe_args[0]= args[0];
    safe_args[1]= args[1];
  }

  THD *thd= current_thd;
serg@serg.mylan's avatar
serg@serg.mylan committed
164
  Query_arena *arena, backup;
bar@mysql.com's avatar
bar@mysql.com committed
165 166 167 168 169
  bool res= FALSE;
  /*
    In case we're in statement prepare, create conversion item
    in its memory: it will be reused on each execute.
  */
170
  arena= thd->change_arena_if_needed(&backup);
bar@mysql.com's avatar
bar@mysql.com committed
171 172 173 174

  for (arg= args, last= args + nargs; arg < last; arg++)
  {
    Item* conv;
175
    uint32 dummy_offset;
bar@mysql.com's avatar
bar@mysql.com committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
    if (!String::needs_conversion(0, coll.collation,
                                  (*arg)->collation.collation,
                                  &dummy_offset))
      continue;

    if (!(conv= (*arg)->safe_charset_converter(coll.collation)))
    {
      if (nargs >=2 && nargs <= 3)
      {
        /* restore the original arguments for better error message */
        args[0]= safe_args[0];
        args[1]= safe_args[1];
      }
      my_coll_agg_error(args, nargs, func_name());
      res= TRUE;
      break; // we cannot return here, we need to restore "arena".
    }
monty@mysql.com's avatar
monty@mysql.com committed
193 194
    if ((*arg)->type() == FIELD_ITEM)
      ((Item_field *)(*arg))->no_const_subst= 1;
195 196 197 198 199 200 201 202 203 204 205 206 207 208
    /*
      If in statement prepare, then we create a converter for two
      constant items, do it once and then reuse it.
      If we're in execution of a prepared statement, arena is NULL,
      and the conv was created in runtime memory. This can be
      the case only if the argument is a parameter marker ('?'),
      because for all true constants the charset converter has already
      been created in prepare. In this case register the change for
      rollback.
    */
    if (arena)
      *arg= conv;
    else
      thd->change_item_tree(arg, conv);
209 210
    /*
      We do not check conv->fixed, because Item_func_conv_charset which can
211
      be return by safe_charset_converter can't be fixed at creation
212
    */
213
    conv->fix_fields(thd, arg);
bar@mysql.com's avatar
bar@mysql.com committed
214
  }
215
  if (arena)
bar@mysql.com's avatar
bar@mysql.com committed
216 217 218 219 220 221
    thd->restore_backup_item_arena(arena, &backup);
  return res;
}



222
void Item_func::set_arguments(List<Item> &list)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
223
{
224
  allowed_arg_cols= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
225
  arg_count=list.elements;
monty@mysql.com's avatar
monty@mysql.com committed
226 227
  args= tmp_arg;                                // If 2 arguments
  if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
228
  {
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
229
    List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
230
    Item *item;
monty@mysql.com's avatar
monty@mysql.com committed
231
    Item **save_args= args;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
232 233 234

    while ((item=li++))
    {
monty@mysql.com's avatar
monty@mysql.com committed
235
      *(save_args++)= item;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
236 237 238 239 240 241
      with_sum_func|=item->with_sum_func;
    }
  }
  list.empty();					// Fields are used
}

242 243 244 245 246 247
Item_func::Item_func(List<Item> &list)
  :allowed_arg_cols(1)
{
  set_arguments(list);
}

248
Item_func::Item_func(THD *thd, Item_func *item)
249
  :Item_result_field(thd, item),
250 251 252 253 254
   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)
255 256 257 258 259 260 261 262 263 264
{
  if (arg_count)
  {
    if (arg_count <=2)
      args= tmp_arg;
    else
    {
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
	return;
    }
265
    memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
266 267 268
  }
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

/*
  Resolve references to table column for a function and it's argument

  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
konstantin@mysql.com's avatar
konstantin@mysql.com committed
287
      used_tables_cache Set to union of the tables used by arguments
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
288 289 290

      str_value.charset If this is a string function, set this to the
			character set for the first argument.
291
			If any argument is binary, this is set to binary
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
292 293 294 295 296 297 298

   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
299 300
  FALSE	ok
  TRUE	Got error.  Stored with my_error().
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
301 302
*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
303
bool
304
Item_func::fix_fields(THD *thd, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
305
{
306
  DBUG_ASSERT(fixed == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
307
  Item **arg,**arg_end;
308 309 310
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
  char buff[STACK_BUFF_ALLOC];			// Max argument in function
#endif
311

312
  used_tables_cache= not_null_tables_cache= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
313 314
  const_item_cache=1;

315
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
316
    return TRUE;				// Fatal error if flag is set!
bk@work.mysql.com's avatar
bk@work.mysql.com committed
317 318 319 320
  if (arg_count)
  {						// Print purify happy
    for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
    {
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
321
      Item *item;
bell@sanja.is.com.ua's avatar
merge  
bell@sanja.is.com.ua committed
322 323 324 325
      /*
	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
      */
326
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
327
	return TRUE;				/* purecov: inspected */
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
328
      item= *arg;
329 330 331 332 333 334 335 336 337 338 339 340 341 342

      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
      }

343
      if (item->maybe_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
344
	maybe_null=1;
345

346
      with_sum_func= with_sum_func || item->with_sum_func;
347 348 349
      used_tables_cache|=     item->used_tables();
      not_null_tables_cache|= item->not_null_tables();
      const_item_cache&=      item->const_item();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
350 351 352
    }
  }
  fix_length_and_dec();
353 354
  if (thd->net.report_error) // An error inside fix_length_and_dec occured
    return TRUE;
355
  fixed= 1;
356
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
357 358
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
359 360 361 362 363 364 365 366 367 368 369 370 371
bool Item_func::walk (Item_processor processor, byte *argument)
{
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
      if ((*arg)->walk(processor, argument))
	return 1;
    }
  }
  return (this->*processor)(argument);
}
372

373 374
void Item_func::traverse_cond(Cond_traverser traverser,
                              void *argument, traverse_order order)
375 376 377 378
{
  if (arg_count)
  {
    Item **arg,**arg_end;
379 380 381

    switch (order) {
    case(PREFIX):
mskold@mysql.com's avatar
mskold@mysql.com committed
382
      (*traverser)(this, argument);
383 384 385 386 387 388 389 390 391 392
      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);
      }
mskold@mysql.com's avatar
mskold@mysql.com committed
393
      (*traverser)(this, argument);
394 395 396 397
    }
  }
}

igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
398

399

igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
/*
  Transform an Item_func object with a transformer callback function
   
  SYNOPSIS
    transform()
    transformer   the transformer callback function to be applied to the nodes
                  of the tree of the object
    argument      parameter to be passed to the transformer
  
  DESCRIPTION
    The function recursively applies the transform method with the
    same transformer to each argument the function.
    If the call of the method for a member item returns a new item
    the old item is substituted for a new one.
    After this the transform method is applied to the root node
    of the Item_func object. 
     
  RETURN VALUES
    Item returned as the result of transformation of the root node 
*/

Item *Item_func::transform(Item_transformer transformer, byte *argument)
422 423 424 425 426 427
{
  if (arg_count)
  {
    Item **arg,**arg_end;
    for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
    {
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
428
      Item *new_item= (*arg)->transform(transformer, argument);
429 430
      if (!new_item)
	return 0;
monty@mysql.com's avatar
monty@mysql.com committed
431 432
      if (*arg != new_item)
        current_thd->change_item_tree(arg, new_item);
433 434
    }
  }
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
435
  return (this->*transformer)(argument);
436 437 438
}


439 440
/* See comments in Item_cmp_func::split_sum_func() */

441 442
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
                               List<Item> &fields)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
443
{
444 445
  Item **arg, **arg_end;
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
446
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
}


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

468 469 470 471 472 473 474

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


bk@work.mysql.com's avatar
bk@work.mysql.com committed
475 476 477 478
void Item_func::print(String *str)
{
  str->append(func_name());
  str->append('(');
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
479
  print_args(str, 0);
480 481 482 483
  str->append(')');
}


bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
484
void Item_func::print_args(String *str, uint from)
485
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
486
  for (uint i=from ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
487
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
488
    if (i != from)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
      str->append(',');
    args[i]->print(str);
  }
}


void Item_func::print_op(String *str)
{
  str->append('(');
  for (uint i=0 ; i < arg_count-1 ; i++)
  {
    args[i]->print(str);
    str->append(' ');
    str->append(func_name());
    str->append(' ');
  }
  args[arg_count-1]->print(str);
  str->append(')');
}

monty@mysql.com's avatar
monty@mysql.com committed
509

510
bool Item_func::eq(const Item *item, bool binary_cmp) const
bk@work.mysql.com's avatar
bk@work.mysql.com committed
511 512 513 514 515 516 517 518 519 520 521
{
  /* 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;
  if (arg_count != item_func->arg_count ||
      func_name() != item_func->func_name())
    return 0;
  for (uint i=0; i < arg_count ; i++)
522
    if (!args[i]->eq(item_func->args[i], binary_cmp))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
523 524 525 526
      return 0;
  return 1;
}

527

528 529 530 531 532
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
  Field *res;
  LINT_INIT(res);

533
  switch (result_type()) {
534 535 536 537 538 539 540 541 542 543 544 545
  case INT_RESULT:
    if (max_length > 11)
      res= new Field_longlong(max_length, maybe_null, name, t_arg,
			      unsigned_flag);
    else
      res= new Field_long(max_length, maybe_null, name, t_arg,
			  unsigned_flag);
    break;
  case REAL_RESULT:
    res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
    break;
  case STRING_RESULT:
546
    res= make_string_field(t_arg);
547
    break;
548
  case DECIMAL_RESULT:
549 550 551 552
    res= new Field_new_decimal(my_decimal_precision_to_length(decimal_precision(),
                                                              decimals,
                                                              unsigned_flag),
                               maybe_null, name, t_arg, decimals, unsigned_flag);
553
    break;
554
  case ROW_RESULT:
555
  default:
556
    // This case should never be chosen
557 558
    DBUG_ASSERT(0);
    break;
559 560 561 562
  }
  return res;
}

563 564 565 566 567 568 569
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
{
  DBUG_ASSERT(fixed);
  int2my_decimal(E_DEC_FATAL_ERROR, val_int(), unsigned_flag, decimal_value);
  return decimal_value;
}

570

bk@work.mysql.com's avatar
bk@work.mysql.com committed
571 572
String *Item_real_func::val_str(String *str)
{
573
  DBUG_ASSERT(fixed == 1);
574
  double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
575 576
  if (null_value)
    return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
577
  str->set(nr,decimals, &my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
578 579 580 581
  return str;
}


582 583 584 585 586 587 588 589 590 591 592
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;
}


593
void Item_func::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
594
{
595 596
  decimals= 0;
  for (uint i=0 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
597
  {
598
    set_if_bigger(decimals, args[i]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
599
  }
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
  max_length= float_length(decimals);
}


void Item_func_numhybrid::fix_num_length_and_dec()
{}


/*
  Set max_length/decimals of function if function is fixed point and
  result length/precision depends on argument ones

  SYNOPSIS
    Item_func::count_decimal_length()
*/

void Item_func::count_decimal_length()
{
618
  int max_int_part= 0;
619
  decimals= 0;
620
  unsigned_flag= 1;
621
  for (uint i=0 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
622
  {
623
    set_if_bigger(decimals, args[i]->decimals);
624 625
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
    set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
626
  }
627 628 629
  int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
  max_length= my_decimal_precision_to_length(precision, decimals,
                                             unsigned_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
630 631 632
}


633 634 635 636 637 638 639 640
/*
  Set max_length of if it is maximum length of its arguments

  SYNOPSIS
    Item_func::count_only_length()
*/

void Item_func::count_only_length()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
641
{
642
  max_length= 0;
643
  unsigned_flag= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
644
  for (uint i=0 ; i < arg_count ; i++)
645
  {
646
    set_if_bigger(max_length, args[i]->max_length);
647 648
    set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
649 650
}

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686

/*
  Set max_length/decimals of function if function is floating point and
  result length/precision depends on argument ones

  SYNOPSIS
    Item_func::count_real_length()
*/

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



687 688 689 690 691 692 693 694 695 696
void Item_func::signal_divide_by_null()
{
  THD *thd= current_thd;
  if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DIVISION_BY_ZERO,
                 ER(ER_DIVISION_BY_ZERO));
  null_value= 1;
}


697
Item *Item_func::get_tmp_table_item(THD *thd)
698 699 700
{
  if (!with_sum_func && !const_item())
    return new Item_field(result_field);
701
  return copy_or_same(thd);
702 703
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
704 705
String *Item_int_func::val_str(String *str)
{
706
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
707 708 709
  longlong nr=val_int();
  if (null_value)
    return 0;
710
  if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
711
    str->set(nr,&my_charset_bin);
712
  else
monty@mysql.com's avatar
monty@mysql.com committed
713
    str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
714 715 716
  return str;
}

717

718
/*
719 720
  Check arguments here to determine result's type for a numeric
  function of two arguments.
721 722 723

  SYNOPSIS
    Item_num_op::find_num_type()
724
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
725 726 727

void Item_num_op::find_num_type(void)
{
728 729 730 731 732 733 734 735
  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)
736
  {
737 738 739 740 741 742 743 744 745
    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();
  }
746
  else
747
  {
748
    DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
749
    decimals= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
750
    hybrid_type=INT_RESULT;
751
    result_precision();
752
  }
753 754 755 756 757 758
  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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
759 760
}

761 762

/*
763 764 765
  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)
766 767 768 769

  SYNOPSIS
    Item_func_num1::find_num_type()
*/
770

771 772 773 774
void Item_func_num1::find_num_type()
{
  DBUG_ENTER("Item_func_num1::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
775
  switch (hybrid_type= args[0]->result_type()) {
776
  case INT_RESULT:
777
    unsigned_flag= args[0]->unsigned_flag;
778 779 780 781 782 783 784 785 786 787
    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);
788
  }
789 790 791 792 793 794
  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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
795 796
}

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812

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)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
813
{
814
  DBUG_ASSERT(fixed == 1);
815
  switch (hybrid_type) {
816 817 818 819
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
820
      return 0;                                 // null is set
821 822 823 824 825 826 827
    my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
    my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
    break;
  }
  case INT_RESULT:
  {
    longlong nr= int_op();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
828 829
    if (null_value)
      return 0; /* purecov: inspected */
830
    if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
831
      str->set(nr,&my_charset_bin);
832
    else
monty@mysql.com's avatar
monty@mysql.com committed
833
      str->set((ulonglong) nr,&my_charset_bin);
834
    break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
835
  }
836
  case REAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
837
  {
838
    double nr= real_op();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
839 840
    if (null_value)
      return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
841
    str->set(nr,decimals,&my_charset_bin);
842 843
    break;
  }
844 845
  case STRING_RESULT:
    return str_op(&str_value);
846 847
  default:
    DBUG_ASSERT(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
848 849 850 851 852
  }
  return str;
}


853 854 855
double Item_func_numhybrid::val_real()
{
  DBUG_ASSERT(fixed == 1);
856
  switch (hybrid_type) {
857 858 859 860
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    double result;
861 862
    if (!(val= decimal_op(&decimal_value)))
      return 0.0;                               // null is set
863 864 865 866 867 868 869
    my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
    return result;
  }
  case INT_RESULT:
    return (double)int_op();
  case REAL_RESULT:
    return real_op();
870 871 872 873 874 875 876 877
  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);
  }
878 879 880 881 882 883 884 885 886 887
  default:
    DBUG_ASSERT(0);
  }
  return 0.0;
}


longlong Item_func_numhybrid::val_int()
{
  DBUG_ASSERT(fixed == 1);
888
  switch (hybrid_type) {
889 890 891 892
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
893
      return 0;                                 // null is set
894 895 896 897 898 899 900 901
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
    return result;
  }
  case INT_RESULT:
    return int_op();
  case REAL_RESULT:
    return (longlong)real_op();
902 903 904 905
  case STRING_RESULT:
  {
    int err_not_used;
    String *res= str_op(&str_value);
906
    char *end= (char*) res->ptr() + res->length();
907
    CHARSET_INFO *cs= str_value.charset();
908
    return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end,
909 910
                                           &err_not_used) : 0);
  }
911 912 913 914 915 916 917 918 919 920 921
  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);
922
  switch (hybrid_type) {
923 924 925 926 927 928 929 930 931 932 933
  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:
  {
934
    double result= (double)int_op();
935 936 937 938
    double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
    break;
  }
  case STRING_RESULT:
939 940 941 942 943 944
  {
    String *res= str_op(&str_value);
    str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
                   res->length(), res->charset(), decimal_value);
    break;
  }  
945 946 947 948 949 950 951 952
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  return val;
}


953 954
void Item_func_signed::print(String *str)
{
955
  str->append("cast(", 5);
956
  args[0]->print(str);
957
  str->append(" as signed)", 11);
958 959 960 961

}


962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
longlong Item_func_signed::val_int_from_str(int *error)
{
  char buff[MAX_FIELD_WIDTH], *end;
  String tmp(buff,sizeof(buff), &my_charset_bin), *res;
  longlong value;

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

  if (!(res= args[0]->val_str(&tmp)))
  {
    null_value= 1;
    *error= 0;
    return 0;
  }
  null_value= 0;
  end= (char*) res->ptr()+ res->length();
  value= my_strtoll10(res->ptr(), &end, error);
  if (*error > 0 || end != res->ptr()+ res->length())
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                        ER_TRUNCATED_WRONG_VALUE,
                        ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
                        res->c_ptr());
  return value;
}


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

  if (args[0]->cast_to_int_type() != STRING_RESULT)
  {
    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;
}


1014 1015
void Item_func_unsigned::print(String *str)
{
1016
  str->append("cast(", 5);
1017
  args[0]->print(str);
1018
  str->append(" as unsigned)", 13);
1019 1020 1021 1022

}


1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
longlong Item_func_unsigned::val_int()
{
  longlong value;
  int error;

  if (args[0]->cast_to_int_type() != STRING_RESULT)
  {
    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;
}


1044 1045 1046
String *Item_decimal_typecast::val_str(String *str)
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
1047 1048
  if (null_value)
    return NULL;
1049 1050 1051 1052 1053 1054 1055 1056 1057
  my_decimal2string(E_DEC_FATAL_ERROR, &tmp_buf, 0, 0, 0, str);
  return str;
}


double Item_decimal_typecast::val_real()
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
  double res;
1058 1059
  if (null_value)
    return 0.0;
1060 1061 1062 1063 1064 1065 1066 1067 1068
  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;
1069 1070
  if (null_value)
    return 0;
1071 1072 1073 1074 1075 1076 1077 1078
  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);
1079 1080
  if ((null_value= args[0]->null_value))
    return NULL;
1081 1082 1083 1084 1085
  my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
  return dec;
}


1086 1087 1088 1089 1090 1091 1092 1093
void Item_decimal_typecast::print(String *str)
{
  str->append("cast(", 5);
  args[0]->print(str);
  str->append(" as decimal)", 12);
}


1094
double Item_func_plus::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1095
{
1096
  double value= args[0]->val_real() + args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1097 1098 1099 1100 1101
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
  return value;
}

1102 1103

longlong Item_func_plus::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1104
{
1105 1106 1107 1108 1109 1110 1111
  longlong value=args[0]->val_int()+args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
}


1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
/*
  Calculate plus of two decimail's

  SYNOPSIS
    decimal_op()
    decimal_value	Buffer that can be used to store result

  RETURN
   0	Value was NULL;  In this case null_value is set
   #	Value of operation as a decimal
*/

1124 1125
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
{
1126 1127 1128
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
1129 1130
  if ((null_value= args[0]->null_value))
    return 0;
1131
  val2= args[1]->val_decimal(&value2);
1132 1133 1134 1135 1136
  if (!(null_value= (args[1]->null_value ||
                     my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
                                    val2) > 1)))
    return decimal_value;
  return 0;
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
}

/*
  Set precision of results for additive operations (+ and -)

  SYNOPSIS
    Item_func_additive_op::result_precision()
*/
void Item_func_additive_op::result_precision()
{
  decimals= max(args[0]->decimals, args[1]->decimals);
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
  int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals,
                        args[1]->decimal_precision() - args[1]->decimals);
  int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION);

  /* 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;
  max_length= my_decimal_precision_to_length(precision, decimals,
                                             unsigned_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1159 1160
}

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170

/*
  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 &&
1171
      (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
1172 1173 1174 1175
    unsigned_flag=0;
}


1176
double Item_func_minus::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1177
{
1178
  double value= args[0]->val_real() - args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1179 1180 1181 1182 1183
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
  return value;
}

1184 1185

longlong Item_func_minus::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1186
{
1187 1188 1189 1190
  longlong value=args[0]->val_int() - args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1191 1192
}

1193

1194 1195
/* See Item_func_plus::decimal_op for comments */

1196 1197
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
{
1198 1199 1200 1201
  my_decimal value1, *val1;
  my_decimal value2, *val2= 

  val1= args[0]->val_decimal(&value1);
1202 1203
  if ((null_value= args[0]->null_value))
    return 0;
1204
  val2= args[1]->val_decimal(&value2);
1205 1206 1207 1208 1209
  if (!(null_value= (args[1]->null_value ||
                     my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
                                    val2) > 1)))
    return decimal_value;
  return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1210 1211
}

1212

1213
double Item_func_mul::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1214
{
1215
  DBUG_ASSERT(fixed == 1);
1216
  double value= args[0]->val_real() * args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1217
  if ((null_value=args[0]->null_value || args[1]->null_value))
1218
    return 0.0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1219 1220 1221
  return value;
}

1222 1223

longlong Item_func_mul::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1224
{
1225
  DBUG_ASSERT(fixed == 1);
1226 1227 1228 1229
  longlong value=args[0]->val_int()*args[1]->val_int();
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0;
  return value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1230 1231 1232
}


1233 1234
/* See Item_func_plus::decimal_op for comments */

1235 1236
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
{
1237 1238 1239
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
1240 1241
  if ((null_value= args[0]->null_value))
    return 0;
1242
  val2= args[1]->val_decimal(&value2);
1243 1244 1245 1246 1247
  if (!(null_value= (args[1]->null_value ||
                     my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
                                    val2) > 1)))
    return decimal_value;
  return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1248 1249 1250
}


1251 1252
void Item_func_mul::result_precision()
{
1253 1254 1255 1256 1257 1258 1259 1260 1261
  /* 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);
  int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(),
                     DECIMAL_MAX_PRECISION);
  max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag);
1262 1263 1264 1265
}


double Item_func_div::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1266
{
1267
  DBUG_ASSERT(fixed == 1);
1268 1269
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
1270 1271 1272 1273 1274
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0.0;
  if (val2 == 0.0)
  {
    signal_divide_by_null();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1275
    return 0.0;
1276
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1277 1278 1279
  return value/val2;
}

1280

1281
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1282
{
1283 1284 1285 1286
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
1287 1288
  if ((null_value= args[0]->null_value))
    return 0;
1289
  val2= args[1]->val_decimal(&value2);
1290 1291 1292
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1293
                         val1, val2, prec_increment)) {
1294 1295 1296 1297 1298 1299
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
    signal_divide_by_null();
  default:
1300
    null_value= 1;                              // Safety
1301
    return 0;
1302
  }
1303 1304 1305 1306 1307
}


void Item_func_div::result_precision()
{
1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
  uint precision=min(args[0]->decimal_precision() + prec_increment,
                     DECIMAL_MAX_PRECISION);
  /* 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);
  max_length= my_decimal_precision_to_length(precision, decimals,
                                             unsigned_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1318 1319
}

1320

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1321 1322
void Item_func_div::fix_length_and_dec()
{
1323
  DBUG_ENTER("Item_func_div::fix_length_and_dec");
1324
  prec_increment= current_thd->variables.div_precincrement;
1325
  Item_num_op::fix_length_and_dec();
1326
  switch(hybrid_type) {
1327 1328
  case REAL_RESULT:
  {
1329
    decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
    set_if_smaller(decimals, NOT_FIXED_DEC);
    max_length=args[0]->max_length - args[0]->decimals + decimals;
    uint tmp=float_length(decimals);
    set_if_smaller(max_length,tmp);
    break;
  }
  case INT_RESULT:
    hybrid_type= DECIMAL_RESULT;
    DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
    result_precision();
    break;
  case DECIMAL_RESULT:
    result_precision();
    break;
  default:
    DBUG_ASSERT(0);
  }
  maybe_null= 1; // devision by zero
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1349 1350
}

1351 1352 1353 1354

/* Integer division */
longlong Item_func_int_div::val_int()
{
1355
  DBUG_ASSERT(fixed == 1);
1356 1357
  longlong value=args[0]->val_int();
  longlong val2=args[1]->val_int();
1358
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
1359 1360 1361 1362
    return 0;
  if (val2 == 0)
  {
    signal_divide_by_null();
1363
    return 0;
1364
  }
1365 1366 1367
  return (unsigned_flag ?
	  (ulonglong) value / (ulonglong) val2 :
	  value / val2);
1368 1369 1370 1371 1372 1373 1374
}


void Item_func_int_div::fix_length_and_dec()
{
  max_length=args[0]->max_length - args[0]->decimals;
  maybe_null=1;
1375
  unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
1376 1377 1378
}


1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
longlong Item_func_mod::int_op()
{
  DBUG_ASSERT(fixed == 1);
  longlong value=  args[0]->val_int();
  longlong val2= args[1]->val_int();
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0; /* purecov: inspected */
  if (val2 == 0)
  {
    signal_divide_by_null();
    return 0;
  }
  return value % val2;
}

double Item_func_mod::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1395
{
1396
  DBUG_ASSERT(fixed == 1);
1397 1398
  double value= args[0]->val_real();
  double val2=  args[1]->val_real();
1399
  if ((null_value= args[0]->null_value || args[1]->null_value))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1400
    return 0.0; /* purecov: inspected */
1401 1402 1403 1404 1405
  if (val2 == 0.0)
  {
    signal_divide_by_null();
    return 0.0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1406 1407 1408
  return fmod(value,val2);
}

1409 1410

my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1411
{
1412 1413 1414 1415
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
1416 1417
  if ((null_value= args[0]->null_value))
    return 0;
1418
  val2= args[1]->val_decimal(&value2);
1419 1420 1421
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1422
                         val1, val2)) {
1423 1424 1425 1426
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
1427
    signal_divide_by_null();
1428
  default:
1429
    null_value= 1;
1430 1431
    return 0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1432 1433
}

1434 1435

void Item_func_mod::result_precision()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1436
{
1437 1438
  decimals= max(args[0]->decimals, args[1]->decimals);
  max_length= max(args[0]->max_length, args[1]->max_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1439 1440 1441
}


1442
double Item_func_neg::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1443
{
1444
  double value= args[0]->val_real();
1445
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1446 1447 1448
  return -value;
}

1449

1450
longlong Item_func_neg::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1451
{
1452 1453
  longlong value= args[0]->val_int();
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1454 1455 1456
  return -value;
}

1457

1458
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1459
{
1460 1461 1462 1463 1464
  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);
1465
    return decimal_value;
1466
  }
1467
  return 0;
1468 1469
}

1470

1471
void Item_func_neg::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1472
{
1473 1474 1475
  decimals= args[0]->decimals;
  /* 1 add because sign can appear */
  max_length= args[0]->max_length + 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1476 1477
}

1478

1479
void Item_func_neg::fix_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1480
{
1481
  DBUG_ENTER("Item_func_neg::fix_length_and_dec");
1482
  Item_func_num1::fix_length_and_dec();
1483 1484 1485 1486

  /*
    If this is in integer context keep the context as integer if possible
    (This is how multiplication and other integer functions works)
1487 1488
    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.
1489
  */
1490 1491
  if (hybrid_type == INT_RESULT &&
      args[0]->type() == INT_ITEM &&
1492
      ((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN))
1493 1494
  {
    /*
1495 1496
      Ensure that result is converted to DECIMAL, as longlong can't hold
      the negated number
1497
    */
1498 1499
    hybrid_type= DECIMAL_RESULT;
    DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
1500
  }
1501
  unsigned_flag= 0;
1502
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1503 1504
}

1505

1506
double Item_func_abs::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1507
{
1508
  double value= args[0]->val_real();
1509
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1510 1511 1512
  return fabs(value);
}

1513

1514
longlong Item_func_abs::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1515
{
1516 1517
  longlong value= args[0]->val_int();
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1518 1519 1520
  return value >= 0 ? value : -value;
}

1521

1522
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1523
{
1524 1525
  my_decimal val, *value= args[0]->val_decimal(&val);
  if (!(null_value= args[0]->null_value))
1526
  {
1527 1528 1529
    my_decimal2decimal(value, decimal_value);
    if (decimal_value->sign())
      my_decimal_neg(decimal_value);
1530
    return decimal_value;
1531
  }
1532
  return 0;
1533 1534 1535 1536 1537 1538 1539 1540
}


void Item_func_abs::fix_length_and_dec()
{
  Item_func_num1::fix_length_and_dec();
  if (hybrid_type == INT_RESULT)
    unsigned_flag= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1541 1542
}

1543

1544
/* Gateway to natural LOG function */
1545
double Item_func_ln::val_real()
1546
{
1547
  DBUG_ASSERT(fixed == 1);
1548
  double value= args[0]->val_real();
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558
  if ((null_value=(args[0]->null_value || value <= 0.0)))
    return 0.0;
  return log(value);
}

/* 
 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.
*/ 
1559
double Item_func_log::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1560
{
1561
  DBUG_ASSERT(fixed == 1);
1562
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1563
  if ((null_value=(args[0]->null_value || value <= 0.0)))
1564 1565 1566
    return 0.0;
  if (arg_count == 2)
  {
1567
    double value2= args[1]->val_real();
1568 1569 1570 1571
    if ((null_value=(args[1]->null_value || value2 <= 0.0 || value == 1.0)))
      return 0.0;
    return log(value2) / log(value);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1572 1573 1574
  return log(value);
}

1575
double Item_func_log2::val_real()
1576
{
1577
  DBUG_ASSERT(fixed == 1);
1578
  double value= args[0]->val_real();
1579 1580
  if ((null_value=(args[0]->null_value || value <= 0.0)))
    return 0.0;
1581
  return log(value) / M_LN2;
1582 1583
}

1584
double Item_func_log10::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1585
{
1586
  DBUG_ASSERT(fixed == 1);
1587
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1588 1589 1590 1591 1592
  if ((null_value=(args[0]->null_value || value <= 0.0)))
    return 0.0; /* purecov: inspected */
  return log10(value);
}

1593
double Item_func_exp::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1594
{
1595
  DBUG_ASSERT(fixed == 1);
1596
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1597 1598 1599 1600 1601
  if ((null_value=args[0]->null_value))
    return 0.0; /* purecov: inspected */
  return exp(value);
}

1602
double Item_func_sqrt::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1603
{
1604
  DBUG_ASSERT(fixed == 1);
1605
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1606 1607 1608 1609 1610
  if ((null_value=(args[0]->null_value || value < 0)))
    return 0.0; /* purecov: inspected */
  return sqrt(value);
}

1611
double Item_func_pow::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1612
{
1613
  DBUG_ASSERT(fixed == 1);
1614 1615
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1616 1617 1618 1619 1620 1621 1622
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
    return 0.0; /* purecov: inspected */
  return pow(value,val2);
}

// Trigonometric functions

1623
double Item_func_acos::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1624
{
1625
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
1626
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1627
  volatile double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1628 1629 1630 1631 1632
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
  return fix_result(acos(value));
}

1633
double Item_func_asin::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1634
{
1635
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
1636
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1637
  volatile double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1638 1639 1640 1641 1642
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
  return fix_result(asin(value));
}

1643
double Item_func_atan::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1644
{
1645
  DBUG_ASSERT(fixed == 1);
1646
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1647 1648 1649 1650
  if ((null_value=args[0]->null_value))
    return 0.0;
  if (arg_count == 2)
  {
1651
    double val2= args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1652 1653 1654 1655 1656 1657 1658
    if ((null_value=args[1]->null_value))
      return 0.0;
    return fix_result(atan2(value,val2));
  }
  return fix_result(atan(value));
}

1659
double Item_func_cos::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1660
{
1661
  DBUG_ASSERT(fixed == 1);
1662
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1663 1664 1665 1666 1667
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(cos(value));
}

1668
double Item_func_sin::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1669
{
1670
  DBUG_ASSERT(fixed == 1);
1671
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1672 1673 1674 1675 1676
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(sin(value));
}

1677
double Item_func_tan::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1678
{
1679
  DBUG_ASSERT(fixed == 1);
1680
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(tan(value));
}


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


longlong Item_func_shift_left::val_int()
{
1692
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
  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()
{
1707
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722
  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()
{
1723
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
  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;
}

1741
void Item_func_int_val::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1742
{
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
  max_length= args[0]->max_length - (args[0]->decimals ?
                                     args[0]->decimals + 1 :
                                     0) + 2;
  uint tmp= float_length(decimals);
  set_if_smaller(max_length,tmp);
  decimals= 0;
}


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

  DBUG_VOID_RETURN;
}


longlong Item_func_ceiling::int_op()
{
1795 1796 1797 1798 1799 1800 1801 1802 1803
  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;
1804
    if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
1805 1806 1807 1808 1809 1810
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
    else
      result= 0;
    break;
  }
  default:
1811
    result= (longlong)Item_func_ceiling::real_op();
1812 1813
  };
  return result;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1814 1815
}

1816 1817

double Item_func_ceiling::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1818
{
1819 1820 1821 1822
  /*
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
    bug)
  */
1823
  volatile double value= args[0]->val_real();
1824 1825 1826 1827 1828 1829
  null_value= args[0]->null_value;
  return ceil(value);
}


my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1830
{
1831
  my_decimal val, *value= args[0]->val_decimal(&val);
1832 1833 1834 1835 1836
  if (!(null_value= (args[0]->null_value ||
                     my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
                                        decimal_value) > 1)))
    return decimal_value;
  return 0;
1837 1838 1839 1840 1841
}


longlong Item_func_floor::int_op()
{
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860
  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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1861 1862
}

1863 1864

double Item_func_floor::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1865
{
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
  /*
    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);
1879 1880 1881 1882 1883
  if (!(null_value= (args[0]->null_value ||
                     my_decimal_floor(E_DEC_FATAL_ERROR, value,
                                      decimal_value) > 1)))
    return decimal_value;
  return 0;
1884 1885 1886
}


1887
void Item_func_round::fix_length_and_dec()
1888
{
1889 1890
  unsigned_flag= args[0]->unsigned_flag;
  if (!args[1]->const_item())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1891
  {
1892 1893 1894 1895 1896 1897
    max_length= args[0]->max_length;
    decimals= args[0]->decimals;
    hybrid_type= REAL_RESULT;
    return;
  }
  
1898
  int decimals_to_set= max((int)args[1]->val_int(), 0);
1899 1900 1901 1902 1903 1904 1905 1906
  if (args[0]->decimals == NOT_FIXED_DEC)
  {
    max_length= args[0]->max_length;
    decimals= min(decimals_to_set, NOT_FIXED_DEC);
    hybrid_type= REAL_RESULT;
    return;
  }
  
1907
  switch (args[0]->result_type()) {
1908 1909 1910 1911 1912 1913 1914
  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:
1915
    if (!decimals_to_set &&
1916
        (truncate || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)))
1917
    {
1918 1919
      int length_can_increase= test(!truncate && (args[1]->val_int() < 0));
      max_length= args[0]->max_length + length_can_increase;
1920 1921 1922 1923 1924
      /* Here we can keep INT_RESULT */
      hybrid_type= INT_RESULT;
      decimals= 0;
      break;
    }
1925
    /* fall through */
1926 1927 1928 1929 1930
  case DECIMAL_RESULT:
  {
    hybrid_type= DECIMAL_RESULT;
    int decimals_delta= args[0]->decimals - decimals_to_set;
    int precision= args[0]->decimal_precision();
1931 1932 1933 1934
    int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;

    precision-= decimals_delta - length_increase;
    decimals= decimals_to_set;
1935
    max_length= my_decimal_precision_to_length(precision, decimals,
1936
                                               unsigned_flag);
1937 1938 1939 1940
    break;
  }
  default:
    DBUG_ASSERT(0); /* This result type isn't handled */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1941 1942 1943
  }
}

1944
double my_double_round(double value, int dec, bool truncate)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1945
{
1946
  double tmp;
1947
  uint abs_dec= abs(dec);
1948 1949 1950 1951 1952
  /*
    tmp2 is here to avoid return the value with 80 bit precision
    This will fix that the test round(0.1,1) = round(0.1,1) is true
  */
  volatile double tmp2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1953

1954 1955
  tmp=(abs_dec < array_elements(log_10) ?
       log_10[abs_dec] : pow(10.0,(double) abs_dec));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1956 1957

  if (truncate)
1958 1959
  {
    if (value >= 0)
1960
      tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
1961
    else
1962
      tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
1963
  }
1964 1965 1966
  else
    tmp2=dec < 0 ? rint(value/tmp)*tmp : rint(value*tmp)/tmp;
  return tmp2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1967 1968 1969
}


1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
double Item_func_round::real_op()
{
  double value= args[0]->val_real();
  int dec= (int) args[1]->val_int();

  if (!(null_value= args[0]->null_value || args[1]->null_value))
    return my_double_round(value, dec, truncate);

  return 0.0;
}


1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
longlong Item_func_round::int_op()
{
  longlong value= args[0]->val_int();
  int dec=(int) args[1]->val_int();
  decimals= 0;
  uint abs_dec;
  if ((null_value= args[0]->null_value || args[1]->null_value))
    return 0;
  if (dec >= 0)
    return value; // integer have not digits after point

  abs_dec= -dec;
  double tmp;
  /*
    tmp2 is here to avoid return the value with 80 bit precision
    This will fix that the test round(0.1,1) = round(0.1,1) is true
  */
  volatile double tmp2;

  tmp= (abs_dec < array_elements(log_10) ?
        log_10[abs_dec] : pow(10.0, (double) abs_dec));

  if (truncate)
  {
    if (unsigned_flag)
2007
      tmp2= floor(ulonglong2double(value)/tmp)*tmp;
2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
    else if (value >= 0)
      tmp2= floor(((double)value)/tmp)*tmp;
    else
      tmp2= ceil(((double)value)/tmp)*tmp;
  }
  else
    tmp2= rint(((double)value)/tmp)*tmp;
  return (longlong)tmp2;
}


my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
{
  my_decimal val, *value= args[0]->val_decimal(&val);
  int dec=(int) args[1]->val_int();
  if (dec > 0)
2024 2025 2026
  {
    decimals= min(dec, DECIMAL_MAX_SCALE); // to get correct output
  }
2027 2028 2029 2030 2031
  if (!(null_value= (args[0]->null_value || args[1]->null_value ||
                     my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate,
                                      decimal_value) > 1)))
    return decimal_value;
  return 0;
2032 2033 2034
}


2035
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2036
{
2037
  if (Item_real_func::fix_fields(thd, ref))
2038
    return TRUE;
2039
  used_tables_cache|= RAND_TABLE_BIT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2040 2041
  if (arg_count)
  {					// Only use argument once in query
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
    /*
      Allocate rand structure once: we must use thd->current_arena
      to create rand in proper mem_root if it's a prepared statement or
      stored procedure.
    */
    if (!rand && !(rand= (struct rand_struct*)
                   thd->current_arena->alloc(sizeof(*rand))))
      return TRUE;
    /*
      PARAM_ITEM is returned if we're in statement prepare and consequently
      no placeholder value is set yet.
    */
    if (args[0]->type() != PARAM_ITEM)
    {
      /*
        TODO: do not do reinit 'rand' for every execute of PS/SP if
        args[0] is a constant.
      */
      uint32 tmp= (uint32) args[0]->val_int();
      randominit(rand, (uint32) (tmp*0x10001L+55555555L),
                 (uint32) (tmp*0x10000001L));
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2064
  }
2065
  else
nick@mysql.com's avatar
nick@mysql.com committed
2066
  {
2067 2068 2069
    /*
      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.
nick@mysql.com's avatar
nick@mysql.com committed
2070

2071 2072 2073 2074
      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
    */
nick@mysql.com's avatar
nick@mysql.com committed
2075 2076 2077
    thd->rand_used=1;
    thd->rand_saved_seed1=thd->rand.seed1;
    thd->rand_saved_seed2=thd->rand.seed2;
2078
    rand= &thd->rand;
nick@mysql.com's avatar
nick@mysql.com committed
2079
  }
2080
  return FALSE;
2081 2082
}

2083 2084 2085 2086 2087 2088
void Item_func_rand::update_used_tables()
{
  Item_real_func::update_used_tables();
  used_tables_cache|= RAND_TABLE_BIT;
}

2089

2090
double Item_func_rand::val_real()
2091
{
2092
  DBUG_ASSERT(fixed == 1);
2093
  return my_rnd(rand);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2094 2095 2096 2097
}

longlong Item_func_sign::val_int()
{
2098
  DBUG_ASSERT(fixed == 1);
2099
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2100 2101 2102 2103 2104
  null_value=args[0]->null_value;
  return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}


2105
double Item_func_units::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2106
{
2107
  DBUG_ASSERT(fixed == 1);
2108
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2109 2110 2111 2112 2113 2114 2115 2116
  if ((null_value=args[0]->null_value))
    return 0;
  return value*mul+add;
}


void Item_func_min_max::fix_length_and_dec()
{
2117
  int max_int_part=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2118 2119 2120 2121
  decimals=0;
  max_length=0;
  maybe_null=1;
  cmp_type=args[0]->result_type();
2122

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2123 2124
  for (uint i=0 ; i < arg_count ; i++)
  {
2125 2126
    set_if_bigger(max_length, args[i]->max_length);
    set_if_bigger(decimals, args[i]->decimals);
2127
    set_if_bigger(max_int_part, args[i]->decimal_int_part());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2128 2129 2130 2131
    if (!args[i]->maybe_null)
      maybe_null=0;
    cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
  }
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2132
  if (cmp_type == STRING_RESULT)
bar@mysql.com's avatar
bar@mysql.com committed
2133
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
2134 2135 2136
  else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
    max_length= my_decimal_precision_to_length(max_int_part+decimals, decimals,
                                            unsigned_flag);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2137 2138 2139 2140 2141
}


String *Item_func_min_max::val_str(String *str)
{
2142
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2143 2144 2145 2146 2147 2148
  switch (cmp_type) {
  case INT_RESULT:
  {
    longlong nr=val_int();
    if (null_value)
      return 0;
2149
    if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
2150
      str->set(nr,&my_charset_bin);
2151
    else
monty@mysql.com's avatar
monty@mysql.com committed
2152
      str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2153 2154
    return str;
  }
2155 2156 2157 2158 2159 2160 2161 2162
  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;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2163 2164
  case REAL_RESULT:
  {
2165
    double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2166 2167
    if (null_value)
      return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
2168
    str->set(nr,decimals,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
    return str;
  }
  case STRING_RESULT:
  {
    String *res;
    LINT_INIT(res);
    null_value=1;
    for (uint i=0; i < arg_count ; i++)
    {
      if (null_value)
      {
	res=args[i]->val_str(str);
	null_value=args[i]->null_value;
      }
      else
      {
	String *res2;
	res2= args[i]->val_str(res == str ? &tmp_value : str);
	if (res2)
	{
2189
	  int cmp= sortcmp(res,res2,collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2190 2191 2192 2193 2194
	  if ((cmp_sign < 0 ? cmp : -cmp) < 0)
	    res=res2;
	}
      }
    }
2195 2196
    if (res)					// If !NULL
      res->set_charset(collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2197 2198
    return res;
  }
2199
  case ROW_RESULT:
2200
  default:
2201
    // This case should never be chosen
2202 2203
    DBUG_ASSERT(0);
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2204 2205 2206 2207 2208
  }
  return 0;					// Keep compiler happy
}


2209
double Item_func_min_max::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2210
{
2211
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2212 2213 2214 2215 2216 2217
  double value=0.0;
  null_value=1;
  for (uint i=0; i < arg_count ; i++)
  {
    if (null_value)
    {
2218
      value= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2219 2220 2221 2222
      null_value=args[i]->null_value;
    }
    else
    {
2223
      double tmp= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
    }
  }
  return value;
}


longlong Item_func_min_max::val_int()
{
2234
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253
  longlong value=0;
  null_value=1;
  for (uint i=0; i < arg_count ; i++)
  {
    if (null_value)
    {
      value=args[i]->val_int();
      null_value=args[i]->null_value;
    }
    else
    {
      longlong tmp=args[i]->val_int();
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
    }
  }
  return value;
}

2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287

my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
{
  DBUG_ASSERT(fixed == 1);
  my_decimal tmp_buf, *tmp, *res= NULL;
  null_value=1;
  for (uint i=0; i < arg_count ; i++)
  {
    if (null_value)
    {
      res= args[i]->val_decimal(dec);
      null_value= args[i]->null_value;
    }
    else
    {
      tmp= args[i]->val_decimal(&tmp_buf);
      if (args[i]->null_value)
        continue;
      if ((my_decimal_cmp(tmp, res) * cmp_sign) < 0)
      {
        if (tmp == &tmp_buf)
        {
          my_decimal2decimal(tmp, dec);
          res= dec;
        }
        else
          res= tmp;
      }
    }
  }
  return res;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2288 2289
longlong Item_func_length::val_int()
{
2290
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
  return (longlong) res->length();
}

2301

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2302 2303
longlong Item_func_char_length::val_int()
{
2304
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2305 2306 2307 2308 2309 2310 2311
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2312
  return (longlong) res->numchars();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2313 2314
}

2315

bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2316 2317
longlong Item_func_coercibility::val_int()
{
2318
  DBUG_ASSERT(fixed == 1);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2319
  null_value= 0;
2320
  return (longlong) args[0]->collation.derivation;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2321
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2322

2323

2324 2325 2326
void Item_func_locate::fix_length_and_dec()
{
  maybe_null=0; max_length=11;
bar@mysql.com's avatar
bar@mysql.com committed
2327
  agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV);
2328 2329
}

2330

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2331 2332
longlong Item_func_locate::val_int()
{
2333
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2334 2335 2336 2337 2338 2339 2340 2341
  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;
2342 2343
  uint start=0;
  uint start0=0;
2344
  my_match_t match;
2345

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2346 2347
  if (arg_count == 3)
  {
2348 2349 2350
    start0= start =(uint) args[2]->val_int()-1;
    start=a->charpos(start);
    
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2351 2352 2353
    if (start > a->length() || start+b->length() > a->length())
      return 0;
  }
2354

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2355 2356
  if (!b->length())				// Found empty string at start
    return (longlong) (start+1);
2357
  
2358
  if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
2359
                                            a->ptr()+start, a->length()-start,
2360 2361 2362 2363
                                            b->ptr(), b->length(),
                                            &match, 1))
    return 0;
  return (longlong) match.mblen + start0 + 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2364 2365 2366
}


2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381
void Item_func_locate::print(String *str)
{
  str->append("locate(", 7);
  args[1]->print(str);
  str->append(',');
  args[0]->print(str);
  if (arg_count == 3)
  {
    str->append(',');
    args[2]->print(str);
  }
  str->append(')');
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2382 2383
longlong Item_func_field::val_int()
{
2384
  DBUG_ASSERT(fixed == 1);
2385

2386 2387 2388
  if (cmp_type == STRING_RESULT)
  {
    String *field;
2389 2390
    if (!(field= args[0]->val_str(&value)))
      return 0;
2391
    for (uint i=1 ; i < arg_count ; i++)
2392 2393
    {
      String *tmp_value=args[i]->val_str(&tmp);
bar@bar.mysql.r18.ru's avatar
Fix:  
bar@bar.mysql.r18.ru committed
2394
      if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
2395
        return (longlong) (i);
2396 2397 2398 2399
    }
  }
  else if (cmp_type == INT_RESULT)
  {
2400
    longlong val= args[0]->val_int();
serg@serg.mylan's avatar
serg@serg.mylan committed
2401 2402
    if (args[0]->null_value)
      return 0;
2403
    for (uint i=1; i < arg_count ; i++)
2404
    {
2405
      if (val == args[i]->val_int() && !args[i]->null_value)
2406
        return (longlong) (i);
2407 2408
    }
  }
2409 2410 2411 2412
  else if (cmp_type == DECIMAL_RESULT)
  {
    my_decimal dec_arg_buf, *dec_arg,
               dec_buf, *dec= args[0]->val_decimal(&dec_buf);
serg@serg.mylan's avatar
serg@serg.mylan committed
2413 2414
    if (args[0]->null_value)
      return 0;
2415 2416 2417
    for (uint i=1; i < arg_count; i++)
    {
      dec_arg= args[i]->val_decimal(&dec_arg_buf);
monty@mysql.com's avatar
monty@mysql.com committed
2418
      if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
2419 2420 2421
        return (longlong) (i);
    }
  }
2422
  else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2423
  {
2424
    double val= args[0]->val_real();
serg@serg.mylan's avatar
serg@serg.mylan committed
2425 2426
    if (args[0]->null_value)
      return 0;
2427
    for (uint i=1; i < arg_count ; i++)
2428
    {
monty@mysql.com's avatar
monty@mysql.com committed
2429
      if (val == args[i]->val_real() && !args[i]->null_value)
2430
        return (longlong) (i);
2431
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2432 2433 2434 2435
  }
  return 0;
}

2436

2437 2438 2439
void Item_func_field::fix_length_and_dec()
{
  maybe_null=0; max_length=3;
2440 2441
  cmp_type= args[0]->result_type();
  for (uint i=1; i < arg_count ; i++)
2442 2443
    cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
  if (cmp_type == STRING_RESULT)
bar@mysql.com's avatar
bar@mysql.com committed
2444
    agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV);
2445
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2446

2447

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2448 2449
longlong Item_func_ascii::val_int()
{
2450
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462
  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()
{
2463
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2464 2465 2466 2467 2468 2469 2470 2471 2472
  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
2473
  if (use_mb(res->charset()))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2474 2475
  {
    register const char *str=res->ptr();
2476
    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2477 2478
    if (!l)
      return (longlong)((uchar) *str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502
    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;
    if (field->real_type() == FIELD_TYPE_SET)
    {
      String *find=args[0]->val_str(&value);
      if (find)
      {
2503 2504
	enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
			      find->length(), 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2505 2506 2507 2508 2509 2510
	enum_bit=0;
	if (enum_value)
	  enum_bit=LL(1) << (enum_value-1);
      }
    }
  }
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2511
  agg_arg_collations_for_comparison(cmp_collation, args, 2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2512 2513 2514 2515 2516 2517
}

static const char separator=',';

longlong Item_func_find_in_set::val_int()
{
2518
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541
  if (enum_value)
  {
    ulonglong tmp=(ulonglong) args[1]->val_int();
    if (!(null_value=args[1]->null_value || args[0]->null_value))
    {
      if (tmp & enum_bit)
	return enum_value;
    }
    return 0L;
  }

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

  int diff;
  if ((diff=buffer->length() - find->length()) >= 0)
  {
2542 2543 2544 2545 2546 2547 2548 2549 2550
    my_wc_t wc;
    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)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2551
    {
2552 2553 2554
      int symbol_len;
      if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end, 
                                       (uchar*) real_end)) > 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2555
      {
2556 2557
        const char *substr_end= str_end + symbol_len;
        bool is_last_item= (substr_end == real_end);
2558 2559
        bool is_separator= (wc == (my_wc_t) separator);
        if (is_separator || is_last_item)
2560 2561
        {
          position++;
2562
          if (is_last_item && !is_separator)
2563 2564 2565 2566 2567 2568 2569 2570 2571
            str_end= substr_end;
          if (!my_strnncoll(cs, (const uchar *) str_begin,
                            str_end - str_begin,
                            find_str, find_str_len))
            return (longlong) position;
          else
            str_begin= substr_end;
        }
        str_end= substr_end;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2572
      }
serg@serg.mylan's avatar
serg@serg.mylan committed
2573 2574
      else if (str_end - str_begin == 0 &&
               find_str_len == 0 &&
2575 2576 2577
               wc == (my_wc_t) separator)
        return (longlong) ++position;
      else
serg@serg.mylan's avatar
serg@serg.mylan committed
2578
        return LL(0);
2579
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2580 2581 2582 2583 2584 2585
  }
  return 0;
}

longlong Item_func_bit_count::val_int()
{
2586
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2587 2588 2589 2590 2591 2592
  ulonglong value= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
2593
  return (longlong) my_count_bits(value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2594 2595 2596 2597 2598 2599
}


/****************************************************************************
** Functions to handle dynamic loadable functions
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
2600
** Rewritten by monty.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2601 2602 2603 2604
****************************************************************************/

#ifdef HAVE_DLOPEN

2605
void udf_handler::cleanup()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2606
{
2607
  if (!not_original)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2608
  {
2609
    if (initialized)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2610
    {
2611 2612 2613 2614 2615 2616 2617
      if (u_d->func_deinit != NULL)
      {
        void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
        u_d->func_deinit;
        (*deinit)(&initid);
      }
      free_udf(u_d);
2618
      initialized= FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2619
    }
2620 2621
    if (buffers)				// Because of bug in ecc
      delete [] buffers;
2622
    buffers= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2623 2624 2625 2626 2627
  }
}


bool
2628
udf_handler::fix_fields(THD *thd, Item_result_field *func,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2629 2630
			uint arg_count, Item **arguments)
{
2631 2632 2633
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
  char buff[STACK_BUFF_ALLOC];			// Max argument in function
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2634 2635
  DBUG_ENTER("Item_udf_func::fix_fields");

2636
  if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
2637
    DBUG_RETURN(TRUE);				// Fatal error flag is set!
2638

2639
  udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2640 2641 2642

  if (!tmp_udf)
  {
2643
    my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
2644
    DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2645 2646 2647 2648 2649
  }
  u_d=tmp_udf;
  args=arguments;

  /* Fix all arguments */
2650
  func->maybe_null=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2651 2652 2653 2654 2655 2656 2657 2658 2659 2660
  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);
2661
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2662 2663 2664 2665 2666 2667 2668
    }
    uint i;
    Item **arg,**arg_end;
    for (i=0, arg=arguments, arg_end=arguments+arg_count;
	 arg != arg_end ;
	 arg++,i++)
    {
2669
      if (!(*arg)->fixed &&
2670
          (*arg)->fix_fields(thd, arg))
2671
	DBUG_RETURN(1);
2672
      // we can't assign 'item' before, because fix_fields() can change arg
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2673
      Item *item= *arg;
2674
      if (item->check_cols(1))
2675
	DBUG_RETURN(TRUE);
2676 2677 2678 2679 2680 2681 2682 2683 2684
      /*
	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
2685
        the particular user defined function.
2686
      */
2687 2688
      if (item->collation.collation->state & MY_CS_BINSORT)
	func->collation.set(&my_charset_bin);
2689
      if (item->maybe_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2690
	func->maybe_null=1;
2691 2692 2693 2694
      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();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2695
    }
2696
    //TODO: why all following memory is not allocated with 1 call of sql_alloc?
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2697 2698
    if (!(buffers=new String[arg_count]) ||
	!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
2699 2700 2701 2702 2703 2704 2705
	!(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))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2706 2707
    {
      free_udf(u_d);
2708
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723
    }
  }
  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)
  {
    char *to=num_buffer;
    for (uint i=0; i < arg_count; i++)
    {
      f_args.args[i]=0;
2724 2725 2726 2727
      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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746

      switch(arguments[i]->type()) {
      case Item::STRING_ITEM:			// Constant string !
      {
	String *res=arguments[i]->val_str((String *) 0);
	if (arguments[i]->null_value)
	  continue;
	f_args.args[i]=    (char*) res->ptr();
	break;
      }
      case Item::INT_ITEM:
	*((longlong*) to) = arguments[i]->val_int();
	if (!arguments[i]->null_value)
	{
	  f_args.args[i]=to;
	  to+= ALIGN_SIZE(sizeof(longlong));
	}
	break;
      case Item::REAL_ITEM:
2747
	*((double*) to)= arguments[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
	if (!arguments[i]->null_value)
	{
	  f_args.args[i]=to;
	  to+= ALIGN_SIZE(sizeof(double));
	}
	break;
      default:					// Skip these
	break;
      }
    }
2758
    thd->net.last_error[0]=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2759 2760 2761 2762 2763
    my_bool (*init)(UDF_INIT *, UDF_ARGS *, char *)=
      (my_bool (*)(UDF_INIT *, UDF_ARGS *,  char *))
      u_d->func_init;
    if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
    {
2764 2765
      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
               u_d->name.str, thd->net.last_error);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2766
      free_udf(u_d);
2767
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2768 2769 2770 2771
    }
    func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
    func->maybe_null=initid.maybe_null;
    const_item_cache=initid.const_item;
2772
    func->decimals=min(initid.decimals,NOT_FIXED_DEC);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2773 2774 2775 2776
  }
  initialized=1;
  if (error)
  {
2777 2778
    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
             u_d->name.str, ER(ER_UNKNOWN_ERROR));
2779
    DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2780
  }
2781
  DBUG_RETURN(FALSE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795
}


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:
2796
    case DECIMAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814
      {
	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:
2815
      *((double*) to)= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2816 2817 2818 2819 2820 2821
      if (!args[i]->null_value)
      {
	f_args.args[i]=to;
	to+= ALIGN_SIZE(sizeof(double));
      }
      break;
2822
    case ROW_RESULT:
2823
    default:
2824
      // This case should never be chosen
2825
      DBUG_ASSERT(0);
2826
      break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2827 2828 2829 2830 2831 2832 2833 2834 2835
    }
  }
  return 0;
}

/* This returns (String*) 0 in case of NULL values */

String *udf_handler::val_str(String *str,String *save_str)
{
2836
  uchar is_null_tmp=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852
  ulong res_length;

  if (get_arguments())
    return 0;
  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;
      return 0;
    }
  }
2853 2854 2855
  char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
		 &is_null_tmp, &error);
  if (is_null_tmp || !res || error)		// The !res is for safety
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2856 2857 2858 2859 2860 2861 2862 2863
  {
    return 0;
  }
  if (res == str->ptr())
  {
    str->length(res_length);
    return str;
  }
2864
  save_str->set(res, res_length, str->charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2865 2866 2867 2868
  return save_str;
}


2869 2870 2871 2872
/*
  For the moment, UDF functions are returning DECIMAL values as strings
*/

2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892
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;
  }
2893 2894
  end= res+ res_length;
  str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
2895 2896 2897
  return dec_buf;
}

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

2899 2900 2901 2902 2903 2904
void Item_udf_func::cleanup()
{
  udf.cleanup();
  Item_func::cleanup();
}

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

2906
double Item_func_udf_float::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2907
{
2908
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2909 2910 2911 2912 2913 2914 2915 2916 2917
  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)
{
2918
  DBUG_ASSERT(fixed == 1);
2919
  double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2920 2921
  if (null_value)
    return 0;					/* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
2922
  str->set(nr,decimals,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2923 2924 2925 2926 2927 2928
  return str;
}


longlong Item_func_udf_int::val_int()
{
2929
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2930 2931 2932 2933 2934 2935 2936 2937 2938 2939
  DBUG_ENTER("Item_func_udf_int::val_int");
  DBUG_PRINT("info",("result_type: %d  arg_count: %d",
		     args[0]->result_type(), arg_count));

  DBUG_RETURN(udf.val_int(&null_value));
}


String *Item_func_udf_int::val_str(String *str)
{
2940
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2941 2942 2943
  longlong nr=val_int();
  if (null_value)
    return 0;
2944
  if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
2945
    str->set(nr,&my_charset_bin);
2946
  else
monty@mysql.com's avatar
monty@mysql.com committed
2947
    str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2948 2949 2950
  return str;
}

2951 2952 2953 2954

longlong Item_func_udf_decimal::val_int()
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
2955
  longlong result;
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965
  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);
2966
  double result;
2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
  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();
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016
/* 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)
{
3017
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3018 3019 3020 3021 3022
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  return res;
}

3023 3024

/*
3025 3026
   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.)
3027 3028 3029 3030
 */

udf_handler::~udf_handler()
{
3031 3032
  /* Everything should be properly cleaned up by this moment. */
  DBUG_ASSERT(not_original || !(initialized || buffers));
3033 3034
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045
#else
bool udf_handler::get_arguments() { return 0; }
#endif /* HAVE_DLOPEN */

/*
** User level locks
*/

pthread_mutex_t LOCK_user_locks;
static HASH hash_user_locks;

3046
class User_level_lock
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3047 3048 3049 3050 3051 3052 3053 3054 3055
{
  char *key;
  uint key_length;

public:
  int count;
  bool locked;
  pthread_cond_t cond;
  pthread_t thread;
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
3056
  ulong thread_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3057

3058
  User_level_lock(const char *key_arg,uint length, ulong id) 
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
3059
    :key_length(length),count(1),locked(1), thread_id(id)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3060 3061 3062 3063 3064
  {
    key=(char*) my_memdup((byte*) key_arg,length,MYF(0));
    pthread_cond_init(&cond,NULL);
    if (key)
    {
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
3065
      if (my_hash_insert(&hash_user_locks,(byte*) this))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3066 3067 3068 3069 3070 3071
      {
	my_free((gptr) key,MYF(0));
	key=0;
      }
    }
  }
3072
  ~User_level_lock()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3073 3074 3075 3076 3077 3078 3079 3080 3081
  {
    if (key)
    {
      hash_delete(&hash_user_locks,(byte*) this);
      my_free((gptr) key,MYF(0));
    }
    pthread_cond_destroy(&cond);
  }
  inline bool initialized() { return key != 0; }
3082 3083 3084
  friend void item_user_lock_release(User_level_lock *ull);
  friend char *ull_get_key(const User_level_lock *ull, uint *length,
                           my_bool not_used);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3085 3086
};

3087
char *ull_get_key(const User_level_lock *ull, uint *length,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3088 3089 3090 3091 3092 3093
		  my_bool not_used __attribute__((unused)))
{
  *length=(uint) ull->key_length;
  return (char*) ull->key;
}

3094 3095 3096

static bool item_user_lock_inited= 0;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3097 3098
void item_user_lock_init(void)
{
3099
  pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
3100 3101
  hash_init(&hash_user_locks,system_charset_info,
	    16,0,0,(hash_get_key) ull_get_key,NULL,0);
3102
  item_user_lock_inited= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3103 3104 3105 3106
}

void item_user_lock_free(void)
{
3107 3108 3109 3110 3111 3112
  if (item_user_lock_inited)
  {
    item_user_lock_inited= 0;
    hash_free(&hash_user_locks);
    pthread_mutex_destroy(&LOCK_user_locks);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3113 3114
}

3115
void item_user_lock_release(User_level_lock *ull)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3116 3117 3118 3119 3120 3121 3122 3123
{
  ull->locked=0;
  if (--ull->count)
    pthread_cond_signal(&ull->cond);
  else
    delete ull;
}

3124 3125 3126 3127 3128 3129 3130
/*
   Wait until we are at or past the given position in the master binlog
   on the slave
 */

longlong Item_master_pos_wait::val_int()
{
3131
  DBUG_ASSERT(fixed == 1);
3132 3133
  THD* thd = current_thd;
  String *log_name = args[0]->val_str(&value);
3134
  int event_count= 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
3135

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
3136 3137 3138 3139 3140 3141
  null_value=0;
  if (thd->slave_thread || !log_name || !log_name->length())
  {
    null_value = 1;
    return 0;
  }
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
3142
  longlong pos = (ulong)args[1]->val_int();
3143
  longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
3144
#ifdef HAVE_REPLICATION
3145
  if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
3146 3147 3148 3149
  {
    null_value = 1;
    event_count=0;
  }
3150
#endif
3151 3152 3153
  return event_count;
}

3154 3155 3156 3157
#ifdef EXTRA_DEBUG
void debug_sync_point(const char* lock_name, uint lock_timeout)
{
  THD* thd=current_thd;
3158
  User_level_lock* ull;
3159
  struct timespec abstime;
3160
  int lock_name_len;
3161 3162 3163 3164 3165 3166 3167 3168 3169
  lock_name_len=strlen(lock_name);
  pthread_mutex_lock(&LOCK_user_locks);

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

3170 3171 3172 3173 3174
  /*
    If the lock has not been aquired by some client, we do not want to
    create an entry for it, since we immediately release the lock. In
    this case, we will not be waiting, but rather, just waste CPU and
    memory on the whole deal
3175
  */
3176
  if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, lock_name,
3177 3178 3179 3180 3181 3182 3183
				 lock_name_len))))
  {
    pthread_mutex_unlock(&LOCK_user_locks);
    return;
  }
  ull->count++;

3184 3185 3186 3187
  /*
    Structure is now initialized.  Try to get the lock.
    Set up control struct to allow others to abort locks
  */
3188 3189 3190 3191
  thd->proc_info="User lock";
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

3192
  set_timespec(abstime,lock_timeout);
3193
  while (!thd->killed &&
3194 3195
         pthread_cond_timedwait(&ull->cond, &LOCK_user_locks,
                                &abstime) != ETIMEDOUT && ull->locked) ;
3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223
  if (ull->locked)
  {
    if (!--ull->count)
      delete ull;				// Should never happen
  }
  else
  {
    ull->locked=1;
    ull->thread=thd->real_id;
    thd->ull=ull;
  }
  pthread_mutex_unlock(&LOCK_user_locks);
  pthread_mutex_lock(&thd->mysys_var->mutex);
  thd->proc_info=0;
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
  pthread_mutex_unlock(&thd->mysys_var->mutex);
  pthread_mutex_lock(&LOCK_user_locks);
  if (thd->ull)
  {
    item_user_lock_release(thd->ull);
    thd->ull=0;
  }
  pthread_mutex_unlock(&LOCK_user_locks);
}

#endif

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3224 3225 3226 3227 3228 3229 3230 3231 3232
/*
  Get a user level lock. If the thread has an old lock this is first released.
  Returns 1:  Got lock
  Returns 0:  Timeout
  Returns NULL: Error
*/

longlong Item_func_get_lock::val_int()
{
3233
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3234 3235 3236 3237
  String *res=args[0]->val_str(&value);
  longlong timeout=args[1]->val_int();
  struct timespec abstime;
  THD *thd=current_thd;
3238
  User_level_lock *ull;
3239
  int error=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3240

3241 3242 3243 3244 3245 3246 3247 3248 3249 3250
  /*
    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)
    return 1;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266
  pthread_mutex_lock(&LOCK_user_locks);

  if (!res || !res->length())
  {
    pthread_mutex_unlock(&LOCK_user_locks);
    null_value=1;
    return 0;
  }
  null_value=0;

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

3267 3268 3269
  if (!(ull= ((User_level_lock *) hash_search(&hash_user_locks,
                                              (byte*) res->ptr(),
                                              res->length()))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3270
  {
3271
    ull=new User_level_lock(res->ptr(),res->length(), thd->thread_id);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
    if (!ull || !ull->initialized())
    {
      delete ull;
      pthread_mutex_unlock(&LOCK_user_locks);
      null_value=1;				// Probably out of memory
      return 0;
    }
    ull->thread=thd->real_id;
    thd->ull=ull;
    pthread_mutex_unlock(&LOCK_user_locks);
    return 1;					// Got new lock
  }
  ull->count++;

3286 3287 3288 3289
  /*
    Structure is now initialized.  Try to get the lock.
    Set up control struct to allow others to abort locks.
  */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3290 3291 3292 3293
  thd->proc_info="User lock";
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

3294
  set_timespec(abstime,timeout);
3295 3296
  while (!thd->killed &&
	 (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
3297
         != ETIMEDOUT && error != EINVAL && ull->locked) ;
3298 3299
  if (thd->killed)
    error=EINTR;				// Return NULL
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3300 3301 3302 3303
  if (ull->locked)
  {
    if (!--ull->count)
      delete ull;				// Should never happen
3304
    if (error != ETIMEDOUT)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329
    {
      error=1;
      null_value=1;				// Return NULL
    }
  }
  else
  {
    ull->locked=1;
    ull->thread=thd->real_id;
    thd->ull=ull;
    error=0;
  }
  pthread_mutex_unlock(&LOCK_user_locks);

  pthread_mutex_lock(&thd->mysys_var->mutex);
  thd->proc_info=0;
  thd->mysys_var->current_mutex= 0;
  thd->mysys_var->current_cond=  0;
  pthread_mutex_unlock(&thd->mysys_var->mutex);

  return !error ? 1 : 0;
}


/*
3330 3331 3332 3333 3334
  Release a user level lock.
  Return:
    1 if lock released
    0 if lock wasn't held
    (SQL) NULL if no such lock
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3335 3336 3337 3338
*/

longlong Item_func_release_lock::val_int()
{
3339
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3340
  String *res=args[0]->val_str(&value);
3341
  User_level_lock *ull;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3342 3343 3344 3345 3346 3347 3348 3349 3350 3351
  longlong result;
  if (!res || !res->length())
  {
    null_value=1;
    return 0;
  }
  null_value=0;

  result=0;
  pthread_mutex_lock(&LOCK_user_locks);
3352 3353 3354
  if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks,
                                             (const byte*) res->ptr(),
                                             res->length()))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371
  {
    null_value=1;
  }
  else
  {
    if (ull->locked && pthread_equal(pthread_self(),ull->thread))
    {
      result=1;					// Release is ok
      item_user_lock_release(ull);
      current_thd->ull=0;
    }
  }
  pthread_mutex_unlock(&LOCK_user_locks);
  return result;
}


3372
longlong Item_func_last_insert_id::val_int()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3373
{
3374
  THD *thd= current_thd;
3375
  DBUG_ASSERT(fixed == 1);
3376 3377
  if (arg_count)
  {
3378 3379 3380 3381
    longlong value= args[0]->val_int();
    thd->insert_id(value);
    null_value= args[0]->null_value;
    return value;                       // Avoid side effect of insert_id()
3382
  }
3383 3384
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
  return thd->insert_id();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3385 3386 3387 3388 3389 3390
}

/* This function is just used to test speed of different functions */

longlong Item_func_benchmark::val_int()
{
3391
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3392
  char buff[MAX_FIELD_WIDTH];
3393
  String tmp(buff,sizeof(buff), &my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3394 3395 3396 3397 3398 3399
  THD *thd=current_thd;

  for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
  {
    switch (args[0]->result_type()) {
    case REAL_RESULT:
3400
      (void) args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3401 3402 3403 3404 3405 3406 3407
      break;
    case INT_RESULT:
      (void) args[0]->val_int();
      break;
    case STRING_RESULT:
      (void) args[0]->val_str(&tmp);
      break;
3408
    case ROW_RESULT:
3409
    default:
3410
      // This case should never be chosen
3411 3412
      DBUG_ASSERT(0);
      return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3413 3414 3415 3416 3417
    }
  }
  return 0;
}

3418

3419 3420 3421 3422
void Item_func_benchmark::print(String *str)
{
  str->append("benchmark(", 10);
  char buffer[20];
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
3423 3424 3425
  // my_charset_bin is good enough for numbers
  String st(buffer, sizeof(buffer), &my_charset_bin);
  st.set((ulonglong)loop_count, &my_charset_bin);
3426 3427 3428 3429 3430 3431
  str->append(st);
  str->append(',');
  args[0]->print(str);
  str->append(')');
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452
#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;

  if (!(entry = (user_var_entry*) hash_search(hash, (byte*) name.str,
					      name.length)) &&
      create_if_not_exists)
  {
    uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
    if (!hash_inited(hash))
      return 0;
    if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME))))
      return 0;
    entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
      extra_size;
    entry->name.length=name.length;
    entry->value=0;
    entry->length=0;
3453
    entry->update_query_id=0;
3454
    entry->collation.set(NULL, DERIVATION_IMPLICIT);
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464
    /*
      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).
    */
3465
    entry->used_query_id=current_thd->query_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3466 3467
    entry->type=STRING_RESULT;
    memcpy(entry->name.str, name.str, name.length+1);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
3468
    if (my_hash_insert(hash,(byte*) entry))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3469 3470 3471 3472 3473 3474 3475 3476
    {
      my_free((char*) entry,MYF(0));
      return 0;
    }
  }
  return entry;
}

3477
/*
3478 3479
  When a user variable is updated (in a SET command or a query like
  SELECT @a:= ).
3480
*/
3481

3482
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3483
{
3484
  DBUG_ASSERT(fixed == 0);
3485
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
3486
  if (Item_func::fix_fields(thd, ref) ||
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3487
      !(entry= get_variable(&thd->user_vars, name, 1)))
3488
    return TRUE;
3489 3490 3491 3492 3493
  /* 
     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).
  */
3494
  entry->update_query_id= thd->query_id;
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509
  /*
    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.
  */
3510 3511
  null_item= (args[0]->type() == NULL_ITEM);
  if (!entry->collation.collation || !null_item)
3512 3513
    entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
3514
  cached_result_type= args[0]->result_type();
3515
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3516 3517 3518 3519 3520 3521 3522 3523 3524
}


void
Item_func_set_user_var::fix_length_and_dec()
{
  maybe_null=args[0]->maybe_null;
  max_length=args[0]->max_length;
  decimals=args[0]->decimals;
3525
  collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3526 3527
}

3528

3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548
/*
  Set value to user variable.

  SYNOPSYS
    update_hash()
    entry    - pointer to structure representing variable
    set_null - should we set NULL value ?
    ptr      - pointer to buffer with new value
    length   - length of new value
    type     - type of new value
    cs       - charset info for new value
    dv       - derivation for new value

  RETURN VALUE
    False - success, True - failure
*/

static bool
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
            Item_result type, CHARSET_INFO *cs, Derivation dv)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3549
{
3550
  if (set_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3551 3552 3553 3554
  {
    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
    if (entry->value && entry->value != pos)
      my_free(entry->value,MYF(0));
3555 3556
    entry->value= 0;
    entry->length= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3557 3558 3559
  }
  else
  {
3560 3561
    if (type == STRING_RESULT)
      length++;					// Store strings with end \0
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582
    if (length <= extra_size)
    {
      /* Save value in value struct */
      char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
      if (entry->value != pos)
      {
	if (entry->value)
	  my_free(entry->value,MYF(0));
	entry->value=pos;
      }
    }
    else
    {
      /* Allocate variable */
      if (entry->length != length)
      {
	char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
	if (entry->value == pos)
	  entry->value=0;
	if (!(entry->value=(char*) my_realloc(entry->value, length,
					      MYF(MY_ALLOW_ZERO_PTR))))
3583
	  return 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3584 3585
      }
    }
3586 3587 3588 3589 3590
    if (type == STRING_RESULT)
    {
      length--;					// Fix length change above
      entry->value[length]= 0;			// Store end \0
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3591
    memcpy(entry->value,ptr,length);
3592 3593
    if (type == DECIMAL_RESULT)
      ((my_decimal*)entry->value)->fix_buffer_pointer();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3594
    entry->length= length;
3595
    entry->collation.set(cs, dv);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3596
  }
3597
  entry->type=type;
3598
  return 0;
3599
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3600

3601 3602 3603 3604 3605

bool
Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
                                    CHARSET_INFO *cs, Derivation dv)
{
3606 3607 3608 3609 3610 3611
  /*
    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)
    type= entry->type;                          // Don't change type of item
3612 3613 3614 3615 3616 3617 3618 3619
  if (::update_hash(entry, (null_value= args[0]->null_value),
                    ptr, length, type, cs, dv))
  {
    current_thd->fatal_error();     // Probably end of memory
    null_value= 1;
    return 1;
  }
  return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3620 3621 3622
}


3623 3624
/* Get the value of a variable as a double */

3625
double user_var_entry::val_real(my_bool *null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3626
{
3627 3628 3629 3630 3631 3632 3633 3634
  if ((*null_value= (value == 0)))
    return 0.0;

  switch (type) {
  case REAL_RESULT:
    return *(double*) value;
  case INT_RESULT:
    return (double) *(longlong*) value;
3635 3636 3637 3638 3639 3640
  case DECIMAL_RESULT:
  {
    double result;
    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
    return result;
  }
3641
  case STRING_RESULT:
serg@serg.mylan's avatar
serg@serg.mylan committed
3642
    return my_atof(value);                      // This is null terminated
3643 3644 3645
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3646
  }
3647
  return 0.0;					// Impossible
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3648 3649 3650
}


3651 3652 3653
/* Get the value of a variable as an integer */

longlong user_var_entry::val_int(my_bool *null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3654
{
3655 3656 3657 3658 3659 3660 3661 3662
  if ((*null_value= (value == 0)))
    return LL(0);

  switch (type) {
  case REAL_RESULT:
    return (longlong) *(double*) value;
  case INT_RESULT:
    return *(longlong*) value;
3663 3664 3665
  case DECIMAL_RESULT:
  {
    longlong result;
3666
    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
3667 3668
    return result;
  }
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3669
  case STRING_RESULT:
monty@mysql.com's avatar
monty@mysql.com committed
3670 3671 3672 3673
  {
    int error;
    return my_strtoll10(value, (char**) 0, &error);// String is null terminated
  }
3674 3675 3676
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3677
  }
3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691
  return LL(0);					// Impossible
}


/* Get the value of a variable as a string */

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:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3692
    str->set(*(double*) value, decimals, &my_charset_bin);
3693 3694
    break;
  case INT_RESULT:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3695
    str->set(*(longlong*) value, &my_charset_bin);
3696
    break;
3697 3698 3699
  case DECIMAL_RESULT:
    my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
    break;
3700
  case STRING_RESULT:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3701
    if (str->copy(value, length, collation.collation))
3702
      str= 0;					// EOM error
3703 3704 3705
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3706
  }
3707
  return(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3708 3709
}

3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736
/* Get the value of a variable as a decimal */

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

  switch (type) {
  case REAL_RESULT:
    double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
    break;
  case INT_RESULT:
    int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
    break;
  case DECIMAL_RESULT:
    val= (my_decimal *)value;
    break;
  case STRING_RESULT:
    str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
    break;
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
  }
  return(val);
}

3737 3738
/*
  This functions is invoked on SET @variable or @variable:= expression.
3739
  Evaluate (and check expression), store results.
3740 3741 3742 3743 3744

  SYNOPSYS
    Item_func_set_user_var::check()

  NOTES
3745 3746
    For now it always return OK. All problem with value evaluating
    will be caught by thd->net.report_error check in sql_set_variables().
3747 3748

  RETURN
3749
    FALSE OK.
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759
*/

bool
Item_func_set_user_var::check()
{
  DBUG_ENTER("Item_func_set_user_var::check");

  switch (cached_result_type) {
  case REAL_RESULT:
  {
3760
    save_result.vreal= args[0]->val_real();
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
    break;
  }
  case INT_RESULT:
  {
    save_result.vint= args[0]->val_int();
    break;
  }
  case STRING_RESULT:
  {
    save_result.vstr= args[0]->val_str(&value);
    break;
  }
3773 3774 3775 3776 3777
  case DECIMAL_RESULT:
  {
    save_result.vdec= args[0]->val_decimal(&decimal_buff);
    break;
  }
3778 3779
  case ROW_RESULT:
  default:
3780
    // This case should never be chosen
3781 3782 3783
    DBUG_ASSERT(0);
    break;
  }
3784
  DBUG_RETURN(FALSE);
3785 3786
}

3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798

/*
  This functions is invoked on SET @variable or @variable:= expression.

  SYNOPSIS
    Item_func_set_user_var::update()

  NOTES
    We have to store the expression as such in the variable, independent of
    the value method used by the user

  RETURN
3799
    0	OK
3800 3801 3802 3803
    1	EOM Error

*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3804 3805 3806
bool
Item_func_set_user_var::update()
{
3807 3808 3809 3810
  bool res;
  DBUG_ENTER("Item_func_set_user_var::update");
  LINT_INIT(res);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3811 3812
  switch (cached_result_type) {
  case REAL_RESULT:
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3813
  {
3814
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
3815
		     REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3816
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3817
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3818
  case INT_RESULT:
3819
  {
3820
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
3821
		     INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3822
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3823
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3824
  case STRING_RESULT:
3825
  {
3826
    if (!save_result.vstr)					// Null value
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3827
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
3828
		       DERIVATION_IMPLICIT);
3829
    else
3830 3831 3832
      res= update_hash((void*) save_result.vstr->ptr(),
		       save_result.vstr->length(), STRING_RESULT,
		       save_result.vstr->charset(),
3833
		       DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3834 3835
    break;
  }
3836 3837 3838 3839
  case DECIMAL_RESULT:
  {
    if (!save_result.vdec)					// Null value
      res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
3840
                       DERIVATION_IMPLICIT);
3841 3842 3843
    else
      res= update_hash((void*) save_result.vdec,
                       sizeof(my_decimal), DECIMAL_RESULT,
3844
                       &my_charset_bin, DERIVATION_IMPLICIT);
3845 3846
    break;
  }
3847
  case ROW_RESULT:
3848
  default:
3849
    // This case should never be chosen
3850 3851 3852
    DBUG_ASSERT(0);
    break;
  }
3853
  DBUG_RETURN(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3854 3855 3856
}


3857
double Item_func_set_user_var::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3858
{
3859
  DBUG_ASSERT(fixed == 1);
3860
  check();
3861
  update();					// Store expression
3862
  return entry->val_real(&null_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3863 3864
}

3865
longlong Item_func_set_user_var::val_int()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3866
{
3867
  DBUG_ASSERT(fixed == 1);
3868
  check();
3869 3870
  update();					// Store expression
  return entry->val_int(&null_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3871 3872
}

3873
String *Item_func_set_user_var::val_str(String *str)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3874
{
3875
  DBUG_ASSERT(fixed == 1);
3876
  check();
3877 3878
  update();					// Store expression
  return entry->val_str(&null_value, str, decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3879 3880 3881
}


3882 3883 3884 3885 3886 3887 3888 3889 3890
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
{
  DBUG_ASSERT(fixed == 1);
  check();
  update();					// Store expression
  return entry->val_decimal(&null_value, val);
}


3891 3892
void Item_func_set_user_var::print(String *str)
{
3893 3894 3895
  str->append("(@", 2);
  str->append(name.str, name.length);
  str->append(":=", 2);
3896 3897 3898 3899 3900
  args[0]->print(str);
  str->append(')');
}


3901 3902 3903 3904 3905 3906 3907 3908 3909 3910
void Item_func_set_user_var::print_as_stmt(String *str)
{
  str->append("set @", 5);
  str->append(name.str, name.length);
  str->append(":=", 2);
  args[0]->print(str);
  str->append(')');
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
3911 3912 3913
String *
Item_func_get_user_var::val_str(String *str)
{
3914
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3915
  DBUG_ENTER("Item_func_get_user_var::val_str");
3916
  if (!var_entry)
3917
    DBUG_RETURN((String*) 0);			// No such variable
3918
  DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3919 3920 3921
}


3922
double Item_func_get_user_var::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3923
{
3924
  DBUG_ASSERT(fixed == 1);
3925 3926
  if (!var_entry)
    return 0.0;					// No such variable
3927 3928 3929 3930 3931 3932 3933 3934 3935 3936
  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);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3937 3938 3939 3940 3941
}


longlong Item_func_get_user_var::val_int()
{
3942
  DBUG_ASSERT(fixed == 1);
3943 3944 3945
  if (!var_entry)
    return LL(0);				// No such variable
  return (var_entry->val_int(&null_value));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3946 3947 3948
}


3949
/*
3950 3951 3952 3953 3954 3955 3956 3957 3958 3959
  Get variable by name and, if necessary, put the record of variable 
  use into the binary log.
  
  SYNOPSIS
    get_var_with_binlog()
      thd        Current thread
      name       Variable name 
      out_entry  [out] variable structure or NULL. The pointer is set 
                 regardless of whether function succeeded or not.

3960 3961 3962 3963
  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).
3964 3965 3966
  
  RETURN
    0  OK 
3967
    1  Failed to put appropriate record into binary log
3968
    
3969 3970
*/

3971 3972
int get_var_with_binlog(THD *thd, LEX_STRING &name, 
                        user_var_entry **out_entry)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3973
{
3974
  BINLOG_USER_VAR_EVENT *user_var_event;
3975 3976
  user_var_entry *var_entry;
  var_entry= get_variable(&thd->user_vars, name, 0);
3977
  
pem@mysql.com's avatar
pem@mysql.com committed
3978
  if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
3979 3980 3981 3982
  {
    *out_entry= var_entry;
    return 0;
  }
3983 3984

  if (!var_entry)
3985
  {
3986
    /*
3987 3988 3989 3990
      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).
3991 3992
      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;'.
3993 3994 3995
      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();
3996 3997
      this would save memory and time; but calling sql_set_variables() makes
      one unique place to maintain (sql_set_variables()). 
3998 3999 4000 4001 4002
    */

    List<set_var_base> tmp_var_list;
    tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
                                                                       new Item_null())));
4003 4004
    /* Create the variable */
    if (sql_set_variables(thd, &tmp_var_list))
4005 4006 4007 4008 4009
      goto err;
    if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
      goto err;
  }
  else if (var_entry->used_query_id == thd->query_id)
4010 4011 4012 4013 4014 4015 4016 4017 4018
  {
    /* 
       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;
  }
4019 4020 4021 4022

  uint size;
  /*
    First we need to store value of var_entry, when the next situation
4023
    appears:
4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041
    > set @a:=1;
    > insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
    We have to write to binlog value @a= 1;
  */
  size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;      
  if (!(user_var_event= (BINLOG_USER_VAR_EVENT *) thd->alloc(size)))
    goto err;
  
  user_var_event->value= (char*) user_var_event +
    ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
  user_var_event->user_var_event= var_entry;
  user_var_event->type= var_entry->type;
  user_var_event->charset_number= var_entry->collation.collation->number;
  if (!var_entry->value)
  {
    /* NULL value*/
    user_var_event->length= 0;
    user_var_event->value= 0;
4042
  }
4043 4044 4045 4046 4047 4048 4049 4050 4051 4052
  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;
  if (insert_dynamic(&thd->user_var_events, (gptr) &user_var_event))
    goto err;
4053 4054 4055
  
  *out_entry= var_entry;
  return 0;
4056

4057
err:
4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069
  *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;
4070

4071
  error= get_var_with_binlog(thd, name, &var_entry);
4072 4073

  if (var_entry)
4074
  {
4075
    collation.set(var_entry->collation);
4076 4077 4078
    switch (var_entry->type) {
    case REAL_RESULT:
      max_length= DBL_DIG + 8;
4079
      break;
4080 4081
    case INT_RESULT:
      max_length= MAX_BIGINT_WIDTH;
4082
      decimals=0;
4083 4084 4085 4086
      break;
    case STRING_RESULT:
      max_length= MAX_BLOB_WIDTH;
      break;
4087
    case DECIMAL_RESULT:
4088 4089
      max_length= DECIMAL_MAX_STR_LENGTH;
      decimals= DECIMAL_MAX_SCALE;
4090
      break;
monty@mysql.com's avatar
monty@mysql.com committed
4091
    case ROW_RESULT:                            // Keep compiler happy
4092 4093
    default:
      DBUG_ASSERT(0);
monty@mysql.com's avatar
monty@mysql.com committed
4094
      break;
4095 4096
    }
  }
4097
  else
4098 4099
  {
    collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
4100
    null_value= 1;
4101
  }
4102

4103 4104
  if (error)
    thd->fatal_error();
4105

4106
  return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4107 4108 4109
}


4110
bool Item_func_get_user_var::const_item() const
4111
{
4112
  return (!var_entry || current_thd->query_id != var_entry->update_query_id);
4113
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125


enum Item_result Item_func_get_user_var::result_type() const
{
  user_var_entry *entry;
  if (!(entry = (user_var_entry*) hash_search(&current_thd->user_vars,
					      (byte*) name.str,
					      name.length)))
    return STRING_RESULT;
  return entry->type;
}

4126 4127 4128

void Item_func_get_user_var::print(String *str)
{
4129
  str->append("(@", 2);
4130 4131 4132 4133
  str->append(name.str,name.length);
  str->append(')');
}

4134

4135
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
4136 4137 4138 4139 4140 4141
{
  /* 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 ||
4142
      ((Item_func*) item)->functype() != functype())
4143 4144 4145 4146 4147 4148 4149
    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));
}


4150
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
4151 4152
{
  DBUG_ASSERT(fixed == 0);
4153
  if (Item::fix_fields(thd, ref) ||
4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219
      !(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).
  */
  entry->collation.set(thd->variables.collation_database);
  entry->update_query_id= thd->query_id;
  return FALSE;
}


void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
{
  if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
                    DERIVATION_IMPLICIT))
    current_thd->fatal_error();			// Probably end of memory
}


void Item_user_var_as_out_param::set_value(const char *str, uint length,
                                           CHARSET_INFO* cs)
{
  if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
                    DERIVATION_IMPLICIT))
    current_thd->fatal_error();			// Probably end of memory
}


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


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


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


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


void Item_user_var_as_out_param::print(String *str)
{
  str->append('@');
  str->append(name.str,name.length);
}


4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231
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)
  :var(var_arg), var_type(var_type_arg), component(*component_arg)
{
  /* set_name() will allocate the name */
  set_name(name_arg, name_len_arg, system_charset_info);
}


bool
4232
Item_func_get_system_var::fix_fields(THD *thd, Item **ref)
4233
{
4234
  Item *item;
4235
  DBUG_ENTER("Item_func_get_system_var::fix_fields");
4236

4237 4238 4239 4240 4241
  /*
    Evaluate the system variable and substitute the result (a basic constant)
    instead of this item. If the variable can not be evaluated,
    the error is reported in sys_var::item().
  */
4242
  if (!(item= var->item(thd, var_type, &component)))
4243 4244 4245 4246 4247 4248 4249 4250
    DBUG_RETURN(1);                             // Impossible
  item->set_name(name, 0, system_charset_info); // don't allocate a new name
  thd->change_item_tree(ref, item);

  DBUG_RETURN(0);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
4251 4252
longlong Item_func_inet_aton::val_int()
{
4253
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4254 4255 4256 4257 4258
  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];
4259
  int dot_count= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4260

4261
  String *s,tmp(buff,sizeof(buff),&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277
  if (!(s = args[0]->val_str(&tmp)))		// If null value
    goto err;
  null_value=0;

  end= (p = s->ptr()) + s->length();
  while (p < end)
  {
    c = *p++;
    int digit = (int) (c - '0');		// Assume ascii
    if (digit >= 0 && digit <= 9)
    {
      if ((byte_result = byte_result * 10 + digit) > 255)
	goto err;				// Wrong address
    }
    else if (c == '.')
    {
4278
      dot_count++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4279 4280 4281 4282 4283 4284 4285
      result= (result << 8) + (ulonglong) byte_result;
      byte_result = 0;
    }
    else
      goto err;					// Invalid character
  }
  if (c != '.')					// IP number can't end on '.'
4286
  {
4287 4288 4289 4290 4291 4292
    /*
      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
    */
4293
    switch (dot_count) {
4294 4295
    case 1: result<<= 8; /* Fall through */
    case 2: result<<= 8; /* Fall through */
4296
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4297
    return (result << 8) + (ulonglong) byte_result;
4298
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4299 4300 4301 4302 4303 4304

err:
  null_value=1;
  return 0;
}

4305

4306
void Item_func_match::init_search(bool no_order)
4307
{
4308
  DBUG_ENTER("Item_func_match::init_search");
4309 4310

  /* Check if init_search() has been called before */
4311
  if (ft_handler)
4312
    DBUG_VOID_RETURN;
4313

4314
  if (key == NO_SUCH_KEY)
4315 4316
  {
    List<Item> fields;
4317
    fields.push_back(new Item_string(" ",1, cmp_collation.collation));
4318 4319
    for (uint i=1; i < arg_count; i++)
      fields.push_back(args[i]);
4320
    concat=new Item_func_concat_ws(fields);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4321 4322 4323
    /*
      Above function used only to get value and do not need fix_fields for it:
      Item_string - basic constant
monty@mysql.com's avatar
monty@mysql.com committed
4324 4325
      fields - fix_fields() was already called for this arguments
      Item_func_concat_ws - do not need fix_fields() to produce value
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4326 4327
    */
    concat->quick_fix_field();
4328
  }
4329

4330 4331
  if (master)
  {
4332 4333
    join_key=master->join_key=join_key|master->join_key;
    master->init_search(no_order);
4334 4335
    ft_handler=master->ft_handler;
    join_key=master->join_key;
4336
    DBUG_VOID_RETURN;
4337 4338
  }

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
4339
  String *ft_tmp= 0;
4340

4341
  // MATCH ... AGAINST (NULL) is meaningless, but possible
4342
  if (!(ft_tmp=key_item()->val_str(&value)))
4343
  {
4344 4345
    ft_tmp= &value;
    value.set("",0,cmp_collation.collation);
4346 4347
  }

4348 4349
  if (ft_tmp->charset() != cmp_collation.collation)
  {
4350
    uint dummy_errors;
4351
    search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
4352
                      cmp_collation.collation, &dummy_errors);
4353
    ft_tmp= &search_value;
4354 4355
  }

4356 4357
  if (join_key && !no_order)
    flags|=FT_SORTED;
4358
  ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
4359 4360 4361

  if (join_key)
    table->file->ft_handler=ft_handler;
4362 4363

  DBUG_VOID_RETURN;
4364 4365
}

4366

4367
bool Item_func_match::fix_fields(THD *thd, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4368
{
4369
  DBUG_ASSERT(fixed == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4370
  Item *item;
4371
  LINT_INIT(item);				// Safe as arg_count is > 1
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4372

4373 4374 4375
  maybe_null=1;
  join_key=0;

4376 4377 4378 4379 4380
  /*
    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.
4381
   */
4382
  if (Item_func::fix_fields(thd, ref) ||
4383
      !args[0]->const_during_execution())
4384 4385
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
4386
    return TRUE;
4387
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4388

4389 4390
  const_item_cache=0;
  for (uint i=1 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4391
  {
4392
    item=args[i];
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
4393
    if (item->type() == Item::REF_ITEM)
4394 4395
      args[i]= item= *((Item_ref *)item)->ref;
    if (item->type() != Item::FIELD_ITEM)
4396
      key=NO_SUCH_KEY;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4397
  }
4398 4399
  /*
    Check that all columns come from the same table.
4400
    We've already checked that columns in MATCH are fields so
4401 4402 4403
    PARAM_TABLE_BIT can only appear from AGAINST argument.
  */
  if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
4404
    key=NO_SUCH_KEY;
4405

4406
  if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
4407 4408
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
4409
    return TRUE;
4410
  }
4411
  table=((Item_field *)item)->field->table;
monty@mysql.com's avatar
monty@mysql.com committed
4412
  if (!(table->file->table_flags() & HA_CAN_FULLTEXT))
4413
  {
monty@mysql.com's avatar
monty@mysql.com committed
4414
    my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4415
    return 1;
4416
  }
4417 4418
  table->fulltext_searched=1;
  return agg_arg_collations_for_comparison(cmp_collation, args+1, arg_count-1);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4419
}
4420

bk@work.mysql.com's avatar
bk@work.mysql.com committed
4421 4422 4423
bool Item_func_match::fix_index()
{
  Item_field *item;
4424
  uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
4425
  uint max_cnt=0, mkeys=0, i;
4426

4427
  if (key == NO_SUCH_KEY)
4428
    return 0;
4429 4430 4431
  
  if (!table) 
    goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4432

4433
  for (keynr=0 ; keynr < table->s->keys ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4434
  {
4435
    if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
4436
        (table->keys_in_use_for_query.is_set(keynr)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4437
    {
4438
      ft_to_key[fts]=keynr;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4439 4440 4441 4442 4443 4444
      ft_cnt[fts]=0;
      fts++;
    }
  }

  if (!fts)
4445
    goto err;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4446

4447
  for (i=1; i < arg_count; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4448
  {
4449
    item=(Item_field*)args[i];
4450
    for (keynr=0 ; keynr < fts ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4451
    {
4452
      KEY *ft_key=&table->key_info[ft_to_key[keynr]];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4453 4454 4455 4456 4457
      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))
4458
	  ft_cnt[keynr]++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4459 4460 4461 4462
      }
    }
  }

4463
  for (keynr=0 ; keynr < fts ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4464
  {
4465
    if (ft_cnt[keynr] > max_cnt)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4466
    {
4467
      mkeys=0;
4468 4469
      max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
4470 4471
      continue;
    }
4472
    if (max_cnt && ft_cnt[keynr] == max_cnt)
4473 4474
    {
      mkeys++;
4475 4476
      ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
4477
      continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4478 4479 4480
    }
  }

4481
  for (keynr=0 ; keynr <= mkeys ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4482
  {
4483 4484
    // partial keys doesn't work
    if (max_cnt < arg_count-1 ||
4485
        max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
4486
      continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4487

4488
    key=ft_to_key[keynr];
4489

4490 4491 4492
    return 0;
  }

4493
err:
4494
  if (flags & FT_BOOL)
4495
  {
4496
    key=NO_SUCH_KEY;
4497 4498
    return 0;
  }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4499 4500
  my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
             ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
4501
  return 1;
4502 4503
}

4504

4505
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
4506
{
4507 4508
  if (item->type() != FUNC_ITEM ||
      ((Item_func*)item)->functype() != FT_FUNC ||
4509
      flags != ((Item_func_match*)item)->flags)
4510 4511 4512 4513 4514
    return 0;

  Item_func_match *ifm=(Item_func_match*) item;

  if (key == ifm->key && table == ifm->table &&
4515
      key_item()->eq(ifm->key_item(), binary_cmp))
4516
    return 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4517 4518 4519 4520

  return 0;
}

4521

4522
double Item_func_match::val_real()
4523
{
4524
  DBUG_ASSERT(fixed == 1);
4525
  DBUG_ENTER("Item_func_match::val");
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
4526
  if (ft_handler == NULL)
4527
    DBUG_RETURN(-1.0);
4528

4529 4530 4531
  if (table->null_row) /* NULL row from an outer join */
    return 0.0;

4532 4533 4534
  if (join_key)
  {
    if (table->file->ft_handler)
4535
      DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
4536 4537 4538
    join_key=0;
  }

4539
  if (key == NO_SUCH_KEY)
4540
  {
4541 4542
    String *a= concat->val_str(&value);
    if ((null_value= (a == 0)))
4543 4544 4545
      DBUG_RETURN(0);
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
				      (byte *)a->ptr(), a->length()));
4546 4547
  }
  else
4548 4549
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
                                                   table->record[0], 0));
4550 4551
}

4552 4553
void Item_func_match::print(String *str)
{
4554
  str->append("(match ", 7);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4555
  print_args(str, 1);
4556
  str->append(" against (", 10);
4557
  args[0]->print(str);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4558
  if (flags & FT_BOOL)
4559
    str->append(" in boolean mode", 16);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4560 4561
  else if (flags & FT_EXPAND)
    str->append(" with query expansion", 21);
4562
  str->append("))", 2);
4563
}
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
4564

4565 4566
longlong Item_func_bit_xor::val_int()
{
4567
  DBUG_ASSERT(fixed == 1);
4568 4569
  ulonglong arg1= (ulonglong) args[0]->val_int();
  ulonglong arg2= (ulonglong) args[1]->val_int();
4570
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
4571 4572 4573 4574
    return 0;
  return (longlong) (arg1 ^ arg2);
}

4575

4576 4577 4578 4579
/***************************************************************************
  System variables
****************************************************************************/

4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596
/*
  Return value of an system variable base[.name] as a constant item

  SYNOPSIS
    get_system_var()
    thd			Thread handler
    var_type		global / session
    name		Name of base or system variable
    component		Component.

  NOTES
    If component.str = 0 then the variable name is in 'name'

  RETURN
    0	error
    #	constant item
*/
4597

4598 4599 4600

Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
		     LEX_STRING component)
4601
{
4602 4603 4604 4605
  sys_var *var;
  char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
  LEX_STRING *base_name, *component_name;

4606 4607
  if (component.str == 0 &&
      !my_strcasecmp(system_charset_info, name.str, "VERSION"))
4608 4609
    return new Item_string("@@VERSION", server_version,
			   (uint) strlen(server_version),
bar@mysql.com's avatar
bar@mysql.com committed
4610
			   system_charset_info, DERIVATION_SYSCONST);
4611

4612 4613 4614 4615 4616 4617 4618 4619 4620 4621
  if (component.str)
  {
    base_name= &component;
    component_name= &name;
  }
  else
  {
    base_name= &name;
    component_name= &component;			// Empty string
  }
4622

4623
  if (!(var= find_sys_var(base_name->str, base_name->length)))
4624
    return 0;
4625 4626 4627 4628
  if (component.str)
  {
    if (!var->is_struct())
    {
4629
      my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
4630 4631 4632
      return 0;
    }
  }
pem@mysql.com's avatar
pem@mysql.com committed
4633
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
4634

4635 4636
  buff[0]='@';
  buff[1]='@';
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
4637 4638 4639 4640 4641
  pos=buff+2;
  if (var_type == OPT_SESSION)
    pos=strmov(pos,"session.");
  else if (var_type == OPT_GLOBAL)
    pos=strmov(pos,"global.");
4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654
  
  set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
  set_if_smaller(base_name->length, MAX_SYS_VAR_LENGTH);

  if (component_name->str)
  {
    memcpy(pos, component_name->str, component_name->length);
    pos+= component_name->length;
    *pos++= '.';
  }
  memcpy(pos, base_name->str, base_name->length);
  pos+= base_name->length;

4655 4656
  return new Item_func_get_system_var(var, var_type, component_name,
                                      buff, pos - buff);
4657 4658 4659
}


4660 4661
/*
  Check a user level lock.
4662 4663 4664 4665 4666 4667 4668 4669

  SYNOPSIS:
    val_int()

  RETURN VALUES
    1		Available
    0		Already taken
    NULL	Error
4670 4671
*/

4672
longlong Item_func_is_free_lock::val_int()
4673
{
4674
  DBUG_ASSERT(fixed == 1);
4675
  String *res=args[0]->val_str(&value);
4676
  User_level_lock *ull;
4677 4678

  null_value=0;
4679
  if (!res || !res->length())
4680 4681 4682 4683 4684 4685
  {
    null_value=1;
    return 0;
  }
  
  pthread_mutex_lock(&LOCK_user_locks);
4686
  ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
4687 4688 4689 4690 4691 4692
			  res->length());
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 1;
  return 0;
}
4693

hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4694 4695
longlong Item_func_is_used_lock::val_int()
{
4696
  DBUG_ASSERT(fixed == 1);
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4697
  String *res=args[0]->val_str(&value);
4698
  User_level_lock *ull;
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4699 4700 4701 4702 4703 4704

  null_value=1;
  if (!res || !res->length())
    return 0;
  
  pthread_mutex_lock(&LOCK_user_locks);
4705
  ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4706 4707 4708 4709 4710 4711 4712 4713 4714
			  res->length());
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 0;

  null_value=0;
  return ull->thread_id;
}

4715

4716 4717 4718 4719 4720 4721 4722 4723 4724
longlong Item_func_row_count::val_int()
{
  DBUG_ASSERT(fixed == 1);
  THD *thd= current_thd;

  return thd->row_count_func;
}


4725 4726 4727
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
  :Item_func(), context(context_arg), m_name(name), m_sp(NULL),
   result_field(NULL)
4728
{
4729
  maybe_null= 1;
4730
  m_name->init_qname(current_thd);
monty@mysql.com's avatar
monty@mysql.com committed
4731
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
4732 4733
}

monty@mysql.com's avatar
monty@mysql.com committed
4734

4735 4736 4737 4738
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
                           sp_name *name, List<Item> &list)
  :Item_func(list), context(context_arg), m_name(name), m_sp(NULL),
   result_field(NULL)
4739
{
4740
  maybe_null= 1;
4741
  m_name->init_qname(current_thd);
monty@mysql.com's avatar
monty@mysql.com committed
4742
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
4743 4744
}

4745 4746 4747 4748 4749 4750 4751 4752
void
Item_func_sp::cleanup()
{
  if (result_field)
  {
    delete result_field;
    result_field= NULL;
  }
4753
  m_sp= NULL;
4754 4755
  Item_func::cleanup();
}
monty@mysql.com's avatar
monty@mysql.com committed
4756

4757 4758 4759
const char *
Item_func_sp::func_name() const
{
4760
  THD *thd= current_thd;
4761
  /* Calculate length to avoid reallocation of string for sure */
4762 4763 4764 4765
  uint len= ((m_name->m_db.length +
              m_name->m_name.length)*2 + //characters*quoting
             2 +                         // ` and `
             1 +                         // .
4766 4767
             1 +                         // end of string
             ALIGN_SIZE(1));             // to avoid String reallocation
monty@mysql.com's avatar
monty@mysql.com committed
4768
  String qname((char *)alloc_root(thd->mem_root, len), len,
4769
               system_charset_info);
4770

4771 4772 4773 4774 4775
  qname.length(0);
  append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
  qname.append('.');
  append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
  return qname.ptr();
4776 4777
}

4778

4779 4780 4781
Field *
Item_func_sp::sp_result_field(void) const
{
pem@mysql.comhem.se's avatar
pem@mysql.comhem.se committed
4782
  Field *field;
4783
  DBUG_ENTER("Item_func_sp::sp_result_field");
4784 4785

  if (!m_sp)
4786
  {
4787
    if (!(m_sp= sp_find_function(current_thd, m_name, TRUE)))
4788
    {
4789 4790
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
      DBUG_RETURN(0);
4791 4792
    }
  }
4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803
  if (!dummy_table->s)
  {
    char *empty_name= (char *) "";
    TABLE_SHARE *share;
    dummy_table->s= share= &dummy_table->share_not_to_be_used;      
    dummy_table->alias = empty_name;
    dummy_table->maybe_null = maybe_null;
    dummy_table->in_use= current_thd;
    share->table_cache_key = empty_name;
    share->table_name = empty_name;
  }
4804 4805
  field= m_sp->make_field(max_length, name, dummy_table);
  DBUG_RETURN(field);
4806 4807 4808
}


4809 4810 4811 4812 4813 4814 4815 4816
/*
  Execute function & store value in field

  RETURN
   0  value <> NULL
   1  value =  NULL  or error
*/

4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835
int
Item_func_sp::execute(Field **flp)
{
  Item *it;
  Field *f;
  if (execute(&it))
  {
    null_value= 1;
    return 1;
  }
  if (!(f= *flp))
  {
    *flp= f= sp_result_field();
    f->move_field((f->pack_length() > sizeof(result_buf)) ? 
                  sql_alloc(f->pack_length()) : result_buf);
    f->null_ptr= (uchar *)&null_value;
    f->null_bit= 1;
  }
  it->save_in_field(f, 1);
4836
  return null_value= f->is_null();
4837 4838 4839
}


4840 4841 4842 4843 4844
int
Item_func_sp::execute(Item **itp)
{
  DBUG_ENTER("Item_func_sp::execute");
  THD *thd= current_thd;
4845
  ulong old_client_capabilites;
4846
  int res= -1;
4847
  bool save_in_sub_stmt= thd->transaction.in_sub_stmt;
4848
  my_bool save_no_send_ok;
4849 4850 4851
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  st_sp_security_context save_ctx;
#endif
4852

4853
  if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
4854
  {
4855 4856
    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
    goto error;
4857
  }
4858

4859
  old_client_capabilites= thd->client_capabilities;
4860 4861
  thd->client_capabilities &= ~CLIENT_MULTI_RESULTS;

4862
#ifndef EMBEDDED_LIBRARY
4863
  save_no_send_ok= thd->net.no_send_ok;
4864 4865 4866
  thd->net.no_send_ok= TRUE;
#endif

4867
#ifndef NO_EMBEDDED_ACCESS_CHECKS
4868 4869
  if (check_routine_access(thd, EXECUTE_ACL, 
			   m_sp->m_db.str, m_sp->m_name.str, 0, 0))
4870
    goto error_check;
4871
  sp_change_security_context(thd, m_sp, &save_ctx);
4872
  if (save_ctx.changed && 
4873 4874
      check_routine_access(thd, EXECUTE_ACL, 
			   m_sp->m_db.str, m_sp->m_name.str, 0, 0))
4875
    goto error_check_ctx;
4876
#endif
4877 4878 4879 4880 4881 4882
  /*
    Like for SPs, we don't binlog the substatements. If the statement which
    called this function is an update statement, it will be binlogged; but if
    it's not (e.g. SELECT myfunc()) it won't be binlogged (documented known
    problem).
  */
4883

4884
  tmp_disable_binlog(thd); /* don't binlog the substatements */
4885
  thd->transaction.in_sub_stmt= TRUE;
4886 4887 4888

  res= m_sp->execute_function(thd, args, arg_count, itp);

4889
  thd->transaction.in_sub_stmt= save_in_sub_stmt;
4890 4891 4892 4893 4894 4895 4896 4897
  reenable_binlog(thd);
  if (res && mysql_bin_log.is_open() &&
      (m_sp->m_chistics->daccess == SP_CONTAINS_SQL ||
       m_sp->m_chistics->daccess == SP_MODIFIES_SQL_DATA))
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                 ER_FAILED_ROUTINE_BREAK_BINLOG,
		 ER(ER_FAILED_ROUTINE_BREAK_BINLOG));

4898
#ifndef NO_EMBEDDED_ACCESS_CHECKS
4899
error_check_ctx:
4900
  sp_restore_security_context(thd, m_sp, &save_ctx);
4901
#endif
4902

4903 4904 4905
  thd->client_capabilities|= old_client_capabilites &  CLIENT_MULTI_RESULTS;

error_check:
4906
#ifndef EMBEDDED_LIBRARY
4907
  thd->net.no_send_ok= save_no_send_ok;
4908
#endif
4909

4910
  thd->client_capabilities|= old_client_capabilites &  CLIENT_MULTI_RESULTS;
4911

4912
error:
4913
  DBUG_RETURN(res);
4914 4915
}

4916

4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932
void
Item_func_sp::make_field(Send_field *tmp_field)
{
  Field *field;
  DBUG_ENTER("Item_func_sp::make_field");
  if ((field= sp_result_field()))
  {
    field->make_field(tmp_field);
    delete field;
    DBUG_VOID_RETURN;
  }
  init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);  
  DBUG_VOID_RETURN;
}


4933 4934
enum enum_field_types
Item_func_sp::field_type() const
4935
{
4936
  Field *field;
4937
  DBUG_ENTER("Item_func_sp::field_type");
4938

4939 4940
  if (result_field)
    DBUG_RETURN(result_field->type());
4941
  if ((field= sp_result_field()))
4942
  {
4943 4944 4945
    enum_field_types result= field->type();
    delete field;
    DBUG_RETURN(result);
4946
  }
4947
  DBUG_RETURN(MYSQL_TYPE_VARCHAR);
4948 4949
}

4950

4951 4952
Item_result
Item_func_sp::result_type() const
4953
{
4954
  Field *field;
4955 4956
  DBUG_ENTER("Item_func_sp::result_type");
  DBUG_PRINT("info", ("m_sp = %p", m_sp));
4957

4958 4959
  if (result_field)
    DBUG_RETURN(result_field->result_type());
4960
  if ((field= sp_result_field()))
4961
  {
4962 4963 4964
    Item_result result= field->result_type();
    delete field;
    DBUG_RETURN(result);
4965
  }
4966
  DBUG_RETURN(STRING_RESULT);
4967 4968 4969 4970 4971
}

void
Item_func_sp::fix_length_and_dec()
{
4972
  Field *field;
4973 4974
  DBUG_ENTER("Item_func_sp::fix_length_and_dec");

4975 4976 4977
  if (result_field)
  {
    decimals= result_field->decimals();
4978
    max_length= result_field->field_length;
4979 4980 4981
    DBUG_VOID_RETURN;
  }

4982
  if (!(field= sp_result_field()))
4983 4984
  {
    context->process_error(current_thd);
4985
    DBUG_VOID_RETURN;
4986
  }
4987
  decimals= field->decimals();
monty@mishka.local's avatar
merge  
monty@mishka.local committed
4988 4989
  max_length= field->field_length;
  maybe_null= 1;
4990
  delete field;
4991 4992
  DBUG_VOID_RETURN;
}
monty@mysql.com's avatar
monty@mysql.com committed
4993 4994


4995 4996 4997
longlong Item_func_found_rows::val_int()
{
  DBUG_ASSERT(fixed == 1);
4998
  return current_thd->found_rows();
4999
}
5000

5001

5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015
Field *
Item_func_sp::tmp_table_field(TABLE *t_arg)
{
  Field *res= 0;
  DBUG_ENTER("Item_func_sp::tmp_table_field");

  if (m_sp)
    res= m_sp->make_field(max_length, (const char *)name, t_arg);
  
  if (!res) 
    res= Item_func::tmp_table_field(t_arg);

  DBUG_RETURN(res);
}