item_func.cc 111 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 20 21 22 23 24

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

#ifdef __GNUC__
#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;
164
  Item_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
    /*
      We do not check conv->fixed, because Item_func_conv_charset which can
      be return by safe_charset_converter can't be fixed at creation, also
      it do not need tables (second argument) for name resolving
    */
bar@mysql.com's avatar
bar@mysql.com committed
200
    *arg= conv;
201
    conv->fix_fields(thd, 0, arg);
bar@mysql.com's avatar
bar@mysql.com committed
202
  }
203
  if (arena)
bar@mysql.com's avatar
bar@mysql.com committed
204 205 206 207 208 209
    thd->restore_backup_item_arena(arena, &backup);
  return res;
}



210
void Item_func::set_arguments(List<Item> &list)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
211
{
212
  allowed_arg_cols= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
213 214 215 216
  arg_count=list.elements;
  if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
  {
    uint i=0;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
217
    List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
218 219 220 221 222 223 224 225 226 227 228
    Item *item;

    while ((item=li++))
    {
      args[i++]= item;
      with_sum_func|=item->with_sum_func;
    }
  }
  list.empty();					// Fields are used
}

229 230 231 232 233 234
Item_func::Item_func(List<Item> &list)
  :allowed_arg_cols(1)
{
  set_arguments(list);
}

235
Item_func::Item_func(THD *thd, Item_func *item)
236
  :Item_result_field(thd, item),
237 238 239 240 241
   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)
242 243 244 245 246 247 248 249 250 251
{
  if (arg_count)
  {
    if (arg_count <=2)
      args= tmp_arg;
    else
    {
      if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
	return;
    }
252
    memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
253 254 255
  }
}

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

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

  SYNOPSIS:
  fix_fields()
  thd		Thread object
  tables	List of all open tables involved in the query
  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
275
      used_tables_cache Set to union of the tables used by arguments
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
276 277 278

      str_value.charset If this is a string function, set this to the
			character set for the first argument.
279
			If any argument is binary, this is set to binary
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
280 281 282 283 284 285 286

   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
287 288
  FALSE	ok
  TRUE	Got error.  Stored with my_error().
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
289 290
*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
291
bool
292
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
293
{
294
  DBUG_ASSERT(fixed == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
295
  Item **arg,**arg_end;
296
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
297
  char buff[STACK_BUFF_ALLOC];			// Max argument in function
298
#endif
299

300
  used_tables_cache= not_null_tables_cache= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
301 302
  const_item_cache=1;

303
  if (check_stack_overrun(thd, buff))
304
    return TRUE;				// Fatal error if flag is set!
bk@work.mysql.com's avatar
bk@work.mysql.com committed
305 306 307 308
  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
309
      Item *item;
bell@sanja.is.com.ua's avatar
merge  
bell@sanja.is.com.ua committed
310 311 312 313
      /*
	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
      */
314
      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)))
315
	return TRUE;				/* purecov: inspected */
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
316
      item= *arg;
317 318 319 320 321 322 323 324 325 326 327 328 329 330

      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
      }

331
      if (item->maybe_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
332
	maybe_null=1;
333

334
      with_sum_func= with_sum_func || item->with_sum_func;
335 336 337
      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
338 339 340
    }
  }
  fix_length_and_dec();
341 342
  if (thd->net.report_error) // An error inside fix_length_and_dec occured
    return TRUE;
343
  fixed= 1;
344
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
345 346
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
347 348 349 350 351 352 353 354 355 356 357 358 359
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);
}
360

361 362
void Item_func::traverse_cond(Cond_traverser traverser,
                              void *argument, traverse_order order)
363 364 365 366
{
  if (arg_count)
  {
    Item **arg,**arg_end;
367 368 369

    switch (order) {
    case(PREFIX):
mskold@mysql.com's avatar
mskold@mysql.com committed
370
      (*traverser)(this, argument);
371 372 373 374 375 376 377 378 379 380
      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
381
      (*traverser)(this, argument);
382 383 384 385
    }
  }
}

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

387

igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/*
  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)
410 411 412 413 414 415
{
  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
416
      Item *new_item= (*arg)->transform(transformer, argument);
417 418
      if (!new_item)
	return 0;
monty@mysql.com's avatar
monty@mysql.com committed
419 420
      if (*arg != new_item)
        current_thd->change_item_tree(arg, new_item);
421 422
    }
  }
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
423
  return (this->*transformer)(argument);
424 425 426
}


427 428
/* See comments in Item_cmp_func::split_sum_func() */

429 430
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
431
{
432 433
  Item **arg, **arg_end;
  for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
434
    (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
}


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

456 457 458 459 460 461 462

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


bk@work.mysql.com's avatar
bk@work.mysql.com committed
463 464 465 466
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
467
  print_args(str, 0);
468 469 470 471
  str->append(')');
}


bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
472
void Item_func::print_args(String *str, uint from)
473
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
474
  for (uint i=from ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
475
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
476
    if (i != from)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
      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
497

498
bool Item_func::eq(const Item *item, bool binary_cmp) const
bk@work.mysql.com's avatar
bk@work.mysql.com committed
499 500 501 502 503 504 505 506 507 508 509
{
  /* 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++)
510
    if (!args[i]->eq(item_func->args[i], binary_cmp))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
511 512 513 514
      return 0;
  return 1;
}

515

516 517 518 519 520
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
  Field *res;
  LINT_INIT(res);

521
  switch (result_type()) {
522 523 524 525 526 527 528 529 530 531 532 533
  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:
534
    res= make_string_field(t_arg);
535
    break;
536 537 538 539
  case DECIMAL_RESULT:
    res= new Field_new_decimal(max_length + (decimals?1:0), maybe_null,
                               name, t_arg, decimals);
    break;
540
  case ROW_RESULT:
541
  default:
542
    // This case should never be chosen
543 544
    DBUG_ASSERT(0);
    break;
545 546 547 548
  }
  return res;
}

549 550 551 552 553 554 555
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;
}

556

bk@work.mysql.com's avatar
bk@work.mysql.com committed
557 558
String *Item_real_func::val_str(String *str)
{
559
  DBUG_ASSERT(fixed == 1);
560
  double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
561 562
  if (null_value)
    return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
563
  str->set(nr,decimals, &my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
564 565 566 567
  return str;
}


568
void Item_func::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
569
{
570 571
  decimals= 0;
  for (uint i=0 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
572
  {
573
    set_if_bigger(decimals, args[i]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
574
  }
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
  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()
{
  uint32 length= 0;
  decimals= 0;
  for (uint i=0 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
596
  {
597 598
    set_if_bigger(decimals, args[i]->decimals);
    set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
599
  }
600 601 602 603 604 605
  max_length= length;
  length+= decimals;
  if (length < max_length)  // If previous operation gave overflow
    max_length= UINT_MAX32;
  else
    max_length= length;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
606 607 608
}


609 610 611 612 613 614 615 616
/*
  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
617
{
618
  max_length= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
619
  for (uint i=0 ; i < arg_count ; i++)
620
    set_if_bigger(max_length, args[i]->max_length);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
621 622
}

623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658

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



659 660 661 662 663 664 665 666 667 668
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;
}


669
Item *Item_func::get_tmp_table_item(THD *thd)
670 671 672
{
  if (!with_sum_func && !const_item())
    return new Item_field(result_field);
673
  return copy_or_same(thd);
674 675
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
676 677
String *Item_int_func::val_str(String *str)
{
678
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
679 680 681
  longlong nr=val_int();
  if (null_value)
    return 0;
682
  if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
683
    str->set(nr,&my_charset_bin);
684
  else
monty@mysql.com's avatar
monty@mysql.com committed
685
    str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
686 687 688
  return str;
}

689

690
/*
691 692 693 694 695
  Check arguments here to determine result's type for function with two
  arguments.

  SYNOPSIS
    Item_num_op::find_num_type()
696
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
697 698 699

void Item_num_op::find_num_type(void)
{
700 701 702 703 704 705 706 707
  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)
708
  {
709 710 711 712 713 714 715 716 717 718
    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();
  }
  else if (r0 == INT_RESULT && r1 == INT_RESULT)
719
  {
720
    decimals= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
721
    hybrid_type=INT_RESULT;
722
    unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
723
    result_precision();
724
  }
725 726 727 728 729 730
  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
731 732
}

733 734 735 736 737 738 739

/*
  Set result type of function if it (type) is depends only on first argument

  SYNOPSIS
    Item_func_num1::find_num_type()
*/
740

741 742 743 744
void Item_func_num1::find_num_type()
{
  DBUG_ENTER("Item_func_num1::find_num_type");
  DBUG_PRINT("info", ("name %s", func_name()));
745
  switch (hybrid_type= args[0]->result_type()) {
746
  case INT_RESULT:
747
    unsigned_flag= args[0]->unsigned_flag;
748 749 750 751 752 753 754 755 756 757
    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);
758
  }
759 760 761 762 763 764
  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
765 766
}

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

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
783
{
784
  DBUG_ASSERT(fixed == 1);
785
  switch (hybrid_type) {
786 787 788 789
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
790
      return 0;                                 // null is set
791 792 793 794 795 796 797
    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
798 799
    if (null_value)
      return 0; /* purecov: inspected */
800
    if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
801
      str->set(nr,&my_charset_bin);
802
    else
monty@mysql.com's avatar
monty@mysql.com committed
803
      str->set((ulonglong) nr,&my_charset_bin);
804
    break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
805
  }
806
  case REAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
807
  {
808
    double nr= real_op();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
809 810
    if (null_value)
      return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
811
    str->set(nr,decimals,&my_charset_bin);
812 813 814 815
    break;
  }
  default:
    DBUG_ASSERT(0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
816 817 818 819 820
  }
  return str;
}


821 822 823
double Item_func_numhybrid::val_real()
{
  DBUG_ASSERT(fixed == 1);
824
  switch (hybrid_type) {
825 826 827 828
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    double result;
829 830
    if (!(val= decimal_op(&decimal_value)))
      return 0.0;                               // null is set
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
    my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
    return result;
  }
  case INT_RESULT:
    return (double)int_op();
  case REAL_RESULT:
    return real_op();
  default:
    DBUG_ASSERT(0);
  }
  return 0.0;
}


longlong Item_func_numhybrid::val_int()
{
  DBUG_ASSERT(fixed == 1);
848
  switch (hybrid_type) {
849 850 851 852
  case DECIMAL_RESULT:
  {
    my_decimal decimal_value, *val;
    if (!(val= decimal_op(&decimal_value)))
853
      return 0;                                 // null is set
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
    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();
  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);
873
  switch (hybrid_type) {
874 875 876 877 878 879 880 881 882 883 884
  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:
  {
885
    double result= (double)int_op();
886 887 888 889 890 891 892 893 894 895 896 897
    double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
    break;
  }
  case STRING_RESULT:
  case ROW_RESULT:
  default:
    DBUG_ASSERT(0);
  }
  return val;
}


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

}


void Item_func_unsigned::print(String *str)
{
909
  str->append("cast(", 5);
910
  args[0]->print(str);
911
  str->append(" as unsigned)", 13);
912 913 914 915

}


916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
String *Item_decimal_typecast::val_str(String *str)
{
  my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
  my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, &tmp_buf);
  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;
  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;
  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);
  my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
  return dec;
}


double Item_func_plus::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
952
{
953
  double value= args[0]->val_real() + args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
954 955 956 957 958
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
  return value;
}

959 960

longlong Item_func_plus::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
961
{
962 963 964 965 966 967 968
  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;
}


969 970 971 972 973 974 975 976 977 978 979 980
/*
  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
*/

981 982
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
{
983 984 985
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
986 987
  if ((null_value= args[0]->null_value))
    return 0;
988 989 990 991
  val2= args[1]->val_decimal(&value2);
  if ((null_value= (args[1]->null_value ||
                    my_decimal_add(E_DEC_FATAL_ERROR, decimal_value, val1,
                                   val2) > 1)))
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
    return 0;
  return decimal_value;
}

/*
  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);
  max_length= (max(args[0]->max_length - args[0]->decimals,
                   args[1]->max_length - args[1]->decimals) +
               decimals + 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1008 1009
}

1010 1011 1012 1013 1014 1015 1016 1017 1018 1019

/*
  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 &&
1020
      (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
1021 1022 1023 1024
    unsigned_flag=0;
}


1025
double Item_func_minus::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1026
{
1027
  double value= args[0]->val_real() - args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1028 1029 1030 1031 1032
  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
  return value;
}

1033 1034

longlong Item_func_minus::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1035
{
1036 1037 1038 1039
  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
1040 1041
}

1042

1043 1044
/* See Item_func_plus::decimal_op for comments */

1045 1046
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
{
1047 1048 1049 1050
  my_decimal value1, *val1;
  my_decimal value2, *val2= 

  val1= args[0]->val_decimal(&value1);
1051 1052
  if ((null_value= args[0]->null_value))
    return 0;
1053 1054 1055 1056
  val2= args[1]->val_decimal(&value2);
  if ((null_value= (args[1]->null_value ||
                    my_decimal_sub(E_DEC_FATAL_ERROR, decimal_value, val1,
                                   val2) > 1)))
1057 1058
    return 0;
  return decimal_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1059 1060
}

1061

1062
double Item_func_mul::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1063
{
1064
  DBUG_ASSERT(fixed == 1);
1065
  double value= args[0]->val_real() * args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1066
  if ((null_value=args[0]->null_value || args[1]->null_value))
1067
    return 0.0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1068 1069 1070
  return value;
}

1071 1072

longlong Item_func_mul::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1073
{
1074
  DBUG_ASSERT(fixed == 1);
1075 1076 1077 1078
  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
1079 1080 1081
}


1082 1083
/* See Item_func_plus::decimal_op for comments */

1084 1085
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
{
1086 1087 1088
  my_decimal value1, *val1;
  my_decimal value2, *val2;
  val1= args[0]->val_decimal(&value1);
1089 1090
  if ((null_value= args[0]->null_value))
    return 0;
1091 1092 1093 1094
  val2= args[1]->val_decimal(&value2);
  if ((null_value= (args[1]->null_value ||
                    my_decimal_mul(E_DEC_FATAL_ERROR, decimal_value, val1,
                                   val2) > 1)))
1095 1096
    return 0;
  return decimal_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1097 1098 1099
}


1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
void Item_func_mul::result_precision()
{
  decimals= args[0]->decimals + args[1]->decimals;
  max_length= ((args[0]->max_length - args[0]->decimals) +
               (args[1]->max_length - args[1]->decimals) +
               decimals);
}


double Item_func_div::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1110
{
1111
  DBUG_ASSERT(fixed == 1);
1112 1113
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
1114 1115 1116 1117 1118
  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
1119
    return 0.0;
1120
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1121 1122 1123
  return value/val2;
}

1124

1125
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1126
{
1127 1128 1129 1130
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
1131 1132
  if ((null_value= args[0]->null_value))
    return 0;
1133
  val2= args[1]->val_decimal(&value2);
1134 1135 1136
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1137
                         val1, val2, DECIMAL_DIV_SCALE_INCREASE)) {
1138 1139 1140 1141 1142 1143
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
    signal_divide_by_null();
  default:
1144
    null_value= 1;                              // Safety
1145
    return 0;
1146
  }
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
}


void Item_func_div::result_precision()
{
  decimals= (args[0]->decimals + args[0]->decimals +
             DECIMAL_DIV_SCALE_INCREASE);
  max_length= ((args[0]->max_length - args[0]->decimals) +
               (args[1]->max_length - args[1]->decimals) +
               decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1157 1158
}

1159

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1160 1161
void Item_func_div::fix_length_and_dec()
{
1162 1163
  DBUG_ENTER("Item_func_div::fix_length_and_dec");
  Item_num_op::fix_length_and_dec();
1164
  switch(hybrid_type) {
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
  case REAL_RESULT:
  {
    decimals=max(args[0]->decimals,args[1]->decimals)+2;
    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
1187 1188
}

1189 1190 1191 1192

/* Integer division */
longlong Item_func_int_div::val_int()
{
1193
  DBUG_ASSERT(fixed == 1);
1194 1195
  longlong value=args[0]->val_int();
  longlong val2=args[1]->val_int();
1196
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
1197 1198 1199 1200
    return 0;
  if (val2 == 0)
  {
    signal_divide_by_null();
1201
    return 0;
1202
  }
1203 1204 1205
  return (unsigned_flag ?
	  (ulonglong) value / (ulonglong) val2 :
	  value / val2);
1206 1207 1208 1209 1210 1211 1212
}


void Item_func_int_div::fix_length_and_dec()
{
  max_length=args[0]->max_length - args[0]->decimals;
  maybe_null=1;
1213
  unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
1214 1215 1216
}


1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
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
1233
{
1234
  DBUG_ASSERT(fixed == 1);
1235 1236
  double value= args[0]->val_real();
  double val2=  args[1]->val_real();
1237
  if ((null_value= args[0]->null_value || args[1]->null_value))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1238
    return 0.0; /* purecov: inspected */
1239 1240 1241 1242 1243
  if (val2 == 0.0)
  {
    signal_divide_by_null();
    return 0.0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1244 1245 1246
  return fmod(value,val2);
}

1247 1248

my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1249
{
1250 1251 1252 1253
  my_decimal value1, *val1;
  my_decimal value2, *val2;

  val1= args[0]->val_decimal(&value1);
1254 1255
  if ((null_value= args[0]->null_value))
    return 0;
1256
  val2= args[1]->val_decimal(&value2);
1257 1258 1259
  if ((null_value= args[1]->null_value))
    return 0;
  switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
1260
                         val1, val2)) {
1261 1262 1263 1264
  case E_DEC_TRUNCATED:
  case E_DEC_OK:
    return decimal_value;
  case E_DEC_DIV_ZERO:
1265
    signal_divide_by_null();
1266
  default:
1267
    null_value= 1;
1268 1269
    return 0;
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1270 1271
}

1272 1273

void Item_func_mod::result_precision()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1274
{
1275 1276
  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
1277 1278 1279
}


1280
double Item_func_neg::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1281
{
1282
  double value= args[0]->val_real();
1283
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1284 1285 1286
  return -value;
}

1287

1288
longlong Item_func_neg::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1289
{
1290 1291
  longlong value= args[0]->val_int();
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1292 1293 1294
  return -value;
}

1295

1296
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1297
{
1298 1299 1300 1301 1302 1303 1304 1305 1306
  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);
  }
  return decimal_value;
}

1307

1308
void Item_func_neg::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1309
{
1310 1311 1312 1313
  decimals= args[0]->decimals;
  /* 1 add because sign can appear */
  max_length= args[0]->max_length + 1;
  unsigned_flag= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1314 1315
}

1316

1317
void Item_func_neg::fix_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1318
{
1319
  DBUG_ENTER("Item_func_neg::fix_length_and_dec");
1320
  Item_func_num1::fix_length_and_dec();
1321 1322 1323 1324 1325

  /*
    If this is in integer context keep the context as integer if possible
    (This is how multiplication and other integer functions works)
  */
1326 1327 1328 1329
  if (hybrid_type == INT_RESULT &&
      args[0]->type() == INT_ITEM &&
      ((ulonglong) ((Item_uint*) args[0])->value >=
       (ulonglong) LONGLONG_MIN))
1330 1331
  {
    /*
1332 1333
      Ensure that result is converted to DECIMAL, as longlong can't hold
      the negated number
1334
    */
1335 1336
    hybrid_type= DECIMAL_RESULT;
    DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
1337
  }
1338
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1339 1340
}

1341

1342
double Item_func_abs::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1343
{
1344
  double value= args[0]->val_real();
1345
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1346 1347 1348
  return fabs(value);
}

1349

1350
longlong Item_func_abs::int_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1351
{
1352 1353
  longlong value= args[0]->val_int();
  null_value= args[0]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1354 1355 1356
  return value >= 0 ? value : -value;
}

1357

1358
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1359
{
1360 1361
  my_decimal val, *value= args[0]->val_decimal(&val);
  if (!(null_value= args[0]->null_value))
1362
  {
1363 1364 1365
    my_decimal2decimal(value, decimal_value);
    if (decimal_value->sign())
      my_decimal_neg(decimal_value);
1366
  }
1367 1368 1369 1370 1371 1372 1373 1374 1375
  return decimal_value;
}


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
1376 1377
}

1378

1379
/* Gateway to natural LOG function */
1380
double Item_func_ln::val_real()
1381
{
1382
  DBUG_ASSERT(fixed == 1);
1383
  double value= args[0]->val_real();
1384 1385 1386 1387 1388 1389 1390 1391 1392 1393
  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.
*/ 
1394
double Item_func_log::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1395
{
1396
  DBUG_ASSERT(fixed == 1);
1397
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1398
  if ((null_value=(args[0]->null_value || value <= 0.0)))
1399 1400 1401
    return 0.0;
  if (arg_count == 2)
  {
1402
    double value2= args[1]->val_real();
1403 1404 1405 1406
    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
1407 1408 1409
  return log(value);
}

1410
double Item_func_log2::val_real()
1411
{
1412
  DBUG_ASSERT(fixed == 1);
1413
  double value= args[0]->val_real();
1414 1415
  if ((null_value=(args[0]->null_value || value <= 0.0)))
    return 0.0;
1416
  return log(value) / M_LN2;
1417 1418
}

1419
double Item_func_log10::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1420
{
1421
  DBUG_ASSERT(fixed == 1);
1422
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1423 1424 1425 1426 1427
  if ((null_value=(args[0]->null_value || value <= 0.0)))
    return 0.0; /* purecov: inspected */
  return log10(value);
}

1428
double Item_func_exp::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1429
{
1430
  DBUG_ASSERT(fixed == 1);
1431
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1432 1433 1434 1435 1436
  if ((null_value=args[0]->null_value))
    return 0.0; /* purecov: inspected */
  return exp(value);
}

1437
double Item_func_sqrt::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1438
{
1439
  DBUG_ASSERT(fixed == 1);
1440
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1441 1442 1443 1444 1445
  if ((null_value=(args[0]->null_value || value < 0)))
    return 0.0; /* purecov: inspected */
  return sqrt(value);
}

1446
double Item_func_pow::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1447
{
1448
  DBUG_ASSERT(fixed == 1);
1449 1450
  double value= args[0]->val_real();
  double val2= args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1451 1452 1453 1454 1455 1456 1457
  if ((null_value=(args[0]->null_value || args[1]->null_value)))
    return 0.0; /* purecov: inspected */
  return pow(value,val2);
}

// Trigonometric functions

1458
double Item_func_acos::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1459
{
1460
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
1461
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1462
  volatile double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1463 1464 1465 1466 1467
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
  return fix_result(acos(value));
}

1468
double Item_func_asin::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1469
{
1470
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
1471
  // the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
1472
  volatile double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1473 1474 1475 1476 1477
  if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
    return 0.0;
  return fix_result(asin(value));
}

1478
double Item_func_atan::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1479
{
1480
  DBUG_ASSERT(fixed == 1);
1481
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1482 1483 1484 1485
  if ((null_value=args[0]->null_value))
    return 0.0;
  if (arg_count == 2)
  {
1486
    double val2= args[1]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1487 1488 1489 1490 1491 1492 1493
    if ((null_value=args[1]->null_value))
      return 0.0;
    return fix_result(atan2(value,val2));
  }
  return fix_result(atan(value));
}

1494
double Item_func_cos::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1495
{
1496
  DBUG_ASSERT(fixed == 1);
1497
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1498 1499 1500 1501 1502
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(cos(value));
}

1503
double Item_func_sin::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1504
{
1505
  DBUG_ASSERT(fixed == 1);
1506
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1507 1508 1509 1510 1511
  if ((null_value=args[0]->null_value))
    return 0.0;
  return fix_result(sin(value));
}

1512
double Item_func_tan::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1513
{
1514
  DBUG_ASSERT(fixed == 1);
1515
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526
  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()
{
1527
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
  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()
{
1542
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
  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()
{
1558
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
  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;
}

1576
void Item_func_int_val::fix_num_length_and_dec()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1577
{
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
  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()
{
1630 1631 1632 1633 1634 1635 1636 1637 1638
  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;
1639
    if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
1640 1641 1642 1643 1644 1645
      my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
    else
      result= 0;
    break;
  }
  default:
1646
    result= (longlong)Item_func_ceiling::real_op();
1647 1648
  };
  return result;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1649 1650
}

1651 1652

double Item_func_ceiling::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1653
{
1654 1655 1656 1657
  /*
    the volatile's for BUG #3051 to calm optimizer down (because of gcc's
    bug)
  */
1658
  volatile double value= args[0]->val_real();
1659 1660 1661 1662 1663 1664
  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
1665
{
1666
  my_decimal val, *value= args[0]->val_decimal(&val);
1667 1668 1669
  if ((null_value= (args[0]->null_value ||
                    my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
                                       decimal_value) > 1)))
1670 1671 1672 1673 1674 1675 1676
    return 0;
  return decimal_value;
}


longlong Item_func_floor::int_op()
{
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695
  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
1696 1697
}

1698 1699

double Item_func_floor::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1700
{
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
  /*
    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);
1714 1715 1716
  if ((null_value= (args[0]->null_value ||
                    my_decimal_floor(E_DEC_FATAL_ERROR, value,
                                     decimal_value) > 1)))
1717 1718 1719 1720 1721 1722 1723 1724 1725
    return 0;
  return decimal_value;
}


void Item_func_round::fix_num_length_and_dec()
{
  max_length= args[0]->max_length;
  decimals= NOT_FIXED_DEC;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1726 1727 1728 1729 1730 1731
  if (args[1]->const_item())
  {
    int tmp=(int) args[1]->val_int();
    if (tmp < 0)
      decimals=0;
    else
1732
      decimals=min(tmp, NOT_FIXED_DEC);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1733 1734 1735
  }
}

1736
double Item_func_round::real_op()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1737
{
1738
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1739
  int dec=(int) args[1]->val_int();
1740 1741
  if (dec > 0)
    decimals= dec; // to get correct output
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1742
  uint abs_dec=abs(dec);
1743 1744 1745 1746 1747 1748
  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;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1749 1750 1751

  if ((null_value=args[0]->null_value || args[1]->null_value))
    return 0.0;
1752 1753
  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
1754 1755

  if (truncate)
1756 1757
  {
    if (value >= 0)
1758
      tmp2= dec < 0 ? floor(value/tmp)*tmp : floor(value*tmp)/tmp;
1759
    else
1760
      tmp2= dec < 0 ? ceil(value/tmp)*tmp : ceil(value*tmp)/tmp;
1761
  }
1762 1763 1764
  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
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
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)
1793
      tmp2= floor(ulonglong2double(value)/tmp)*tmp;
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
    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)
    decimals= dec; // to get correct output
1811 1812 1813
  if ((null_value= (args[0]->null_value || args[1]->null_value ||
                    my_decimal_round(E_DEC_FATAL_ERROR, value, dec, truncate,
                                     decimal_value) > 1)))
1814 1815 1816 1817 1818
    return 0;
  return decimal_value;
}


1819 1820
bool Item_func_rand::fix_fields(THD *thd, struct st_table_list *tables,
                                Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1821
{
1822 1823
  if (Item_real_func::fix_fields(thd, tables, ref))
    return TRUE;
1824
  used_tables_cache|= RAND_TABLE_BIT;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1825 1826
  if (arg_count)
  {					// Only use argument once in query
1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848
    /*
      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
1849
  }
1850
  else
nick@mysql.com's avatar
nick@mysql.com committed
1851
  {
1852 1853 1854
    /*
      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
1855

1856 1857 1858 1859
      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
1860 1861 1862
    thd->rand_used=1;
    thd->rand_saved_seed1=thd->rand.seed1;
    thd->rand_saved_seed2=thd->rand.seed2;
1863
    rand= &thd->rand;
nick@mysql.com's avatar
nick@mysql.com committed
1864
  }
1865
  return FALSE;
1866 1867
}

1868 1869 1870 1871 1872 1873
void Item_func_rand::update_used_tables()
{
  Item_real_func::update_used_tables();
  used_tables_cache|= RAND_TABLE_BIT;
}

1874

1875
double Item_func_rand::val_real()
1876
{
1877
  DBUG_ASSERT(fixed == 1);
1878
  return my_rnd(rand);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1879 1880 1881 1882
}

longlong Item_func_sign::val_int()
{
1883
  DBUG_ASSERT(fixed == 1);
1884
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1885 1886 1887 1888 1889
  null_value=args[0]->null_value;
  return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}


1890
double Item_func_units::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1891
{
1892
  DBUG_ASSERT(fixed == 1);
1893
  double value= args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905
  if ((null_value=args[0]->null_value))
    return 0;
  return value*mul+add;
}


void Item_func_min_max::fix_length_and_dec()
{
  decimals=0;
  max_length=0;
  maybe_null=1;
  cmp_type=args[0]->result_type();
1906

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1907 1908
  for (uint i=0 ; i < arg_count ; i++)
  {
1909 1910
    set_if_bigger(max_length, args[i]->max_length);
    set_if_bigger(decimals, args[i]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1911 1912 1913 1914
    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
1915
  if (cmp_type == STRING_RESULT)
bar@mysql.com's avatar
bar@mysql.com committed
1916
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1917 1918 1919 1920 1921
}


String *Item_func_min_max::val_str(String *str)
{
1922
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1923 1924 1925 1926 1927 1928
  switch (cmp_type) {
  case INT_RESULT:
  {
    longlong nr=val_int();
    if (null_value)
      return 0;
1929
    if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
1930
      str->set(nr,&my_charset_bin);
1931
    else
monty@mysql.com's avatar
monty@mysql.com committed
1932
      str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1933 1934
    return str;
  }
1935 1936 1937 1938 1939 1940 1941 1942
  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
1943 1944
  case REAL_RESULT:
  {
1945
    double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1946 1947
    if (null_value)
      return 0; /* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
1948
    str->set(nr,decimals,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968
    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)
	{
1969
	  int cmp= sortcmp(res,res2,collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1970 1971 1972 1973 1974
	  if ((cmp_sign < 0 ? cmp : -cmp) < 0)
	    res=res2;
	}
      }
    }
1975 1976
    if (res)					// If !NULL
      res->set_charset(collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1977 1978
    return res;
  }
1979
  case ROW_RESULT:
1980
  default:
1981
    // This case should never be chosen
1982 1983
    DBUG_ASSERT(0);
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1984 1985 1986 1987 1988
  }
  return 0;					// Keep compiler happy
}


1989
double Item_func_min_max::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1990
{
1991
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1992 1993 1994 1995 1996 1997
  double value=0.0;
  null_value=1;
  for (uint i=0; i < arg_count ; i++)
  {
    if (null_value)
    {
1998
      value= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1999 2000 2001 2002
      null_value=args[i]->null_value;
    }
    else
    {
2003
      double tmp= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
      if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
	value=tmp;
    }
  }
  return value;
}


longlong Item_func_min_max::val_int()
{
2014
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033
  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;
}

2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067

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
2068 2069
longlong Item_func_length::val_int()
{
2070
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
  return (longlong) res->length();
}

2081

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2082 2083
longlong Item_func_char_length::val_int()
{
2084
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2085 2086 2087 2088 2089 2090 2091
  String *res=args[0]->val_str(&value);
  if (!res)
  {
    null_value=1;
    return 0; /* purecov: inspected */
  }
  null_value=0;
2092
  return (longlong) res->numchars();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2093 2094
}

2095

bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2096 2097
longlong Item_func_coercibility::val_int()
{
2098
  DBUG_ASSERT(fixed == 1);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2099
  null_value= 0;
2100
  return (longlong) args[0]->collation.derivation;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
2101
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2102

2103

2104 2105 2106
void Item_func_locate::fix_length_and_dec()
{
  maybe_null=0; max_length=11;
bar@mysql.com's avatar
bar@mysql.com committed
2107
  agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV);
2108 2109
}

2110

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2111 2112
longlong Item_func_locate::val_int()
{
2113
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2114 2115 2116 2117 2118 2119 2120 2121
  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;
2122 2123
  uint start=0;
  uint start0=0;
2124
  my_match_t match;
2125

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2126 2127
  if (arg_count == 3)
  {
2128 2129 2130
    start0= start =(uint) args[2]->val_int()-1;
    start=a->charpos(start);
    
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2131 2132 2133
    if (start > a->length() || start+b->length() > a->length())
      return 0;
  }
2134

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2135 2136
  if (!b->length())				// Found empty string at start
    return (longlong) (start+1);
2137
  
2138
  if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
2139
                                            a->ptr()+start, a->length()-start,
2140 2141 2142 2143
                                            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
2144 2145 2146
}


2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161
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
2162 2163
longlong Item_func_field::val_int()
{
2164
  DBUG_ASSERT(fixed == 1);
2165 2166 2167
  if (cmp_type == STRING_RESULT)
  {
    String *field;
2168
    if (!(field=args[0]->val_str(&value)))
2169
      return 0;					// -1 if null ?
2170
    for (uint i=1 ; i < arg_count ; i++)
2171 2172
    {
      String *tmp_value=args[i]->val_str(&tmp);
bar@bar.mysql.r18.ru's avatar
Fix:  
bar@bar.mysql.r18.ru committed
2173
      if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
2174
        return (longlong) (i);
2175 2176 2177 2178
    }
  }
  else if (cmp_type == INT_RESULT)
  {
2179
    longlong val= args[0]->val_int();
2180 2181
    if (args[0]->is_null())
      return 0;
2182
    for (uint i=1; i < arg_count ; i++)
2183
    {
2184
      if (val == args[i]->val_int() && ! args[i]->is_null())
2185
 	return (longlong) (i);
2186 2187
    }
  }
2188 2189 2190 2191 2192 2193 2194 2195 2196
  else if (cmp_type == DECIMAL_RESULT)
  {
    my_decimal dec_arg_buf, *dec_arg,
               dec_buf, *dec= args[0]->val_decimal(&dec_buf);
    if (args[0]->is_null())
      return 0;
    for (uint i=1; i < arg_count; i++)
    {
      dec_arg= args[i]->val_decimal(&dec_arg_buf);
2197
      if (!args[i]->is_null() && !my_decimal_cmp(dec_arg, dec))
2198 2199 2200
        return (longlong) (i);
    }
  }
2201
  else
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2202
  {
2203
    double val= args[0]->val_real();
2204 2205
    if (args[0]->is_null())
      return 0;
2206
    for (uint i=1; i < arg_count ; i++)
2207
    {
2208
      if (val == args[i]->val_real() && ! args[i]->is_null())
2209
 	return (longlong) (i);
2210
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2211 2212 2213 2214
  }
  return 0;
}

2215

2216 2217 2218
void Item_func_field::fix_length_and_dec()
{
  maybe_null=0; max_length=3;
2219 2220
  cmp_type= args[0]->result_type();
  for (uint i=1; i < arg_count ; i++)
2221 2222
    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
2223
    agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV);
2224
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2225

2226

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2227 2228
longlong Item_func_ascii::val_int()
{
2229
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
  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()
{
2242
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2243 2244 2245 2246 2247 2248 2249 2250 2251
  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
2252
  if (use_mb(res->charset()))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2253 2254
  {
    register const char *str=res->ptr();
2255
    register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2256 2257
    if (!l)
      return (longlong)((uchar) *str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281
    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)
      {
2282 2283
	enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
			      find->length(), 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2284 2285 2286 2287 2288 2289
	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
2290
  agg_arg_collations_for_comparison(cmp_collation, args, 2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2291 2292 2293 2294 2295 2296
}

static const char separator=',';

longlong Item_func_find_in_set::val_int()
{
2297
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320
  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)
  {
2321 2322 2323 2324 2325 2326 2327 2328 2329
    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
2330
    {
2331 2332 2333
      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
2334
      {
2335 2336
        const char *substr_end= str_end + symbol_len;
        bool is_last_item= (substr_end == real_end);
2337 2338
        bool is_separator= (wc == (my_wc_t) separator);
        if (is_separator || is_last_item)
2339 2340
        {
          position++;
2341
          if (is_last_item && !is_separator)
2342 2343 2344 2345 2346 2347 2348 2349 2350
            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
2351
      }
2352 2353 2354 2355 2356 2357 2358
      else if (str_end - str_begin == 0 && 
               find_str_len == 0 && 
               wc == (my_wc_t) separator)
        return (longlong) ++position;
      else
        return (longlong) 0;
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2359 2360 2361 2362 2363 2364
  }
  return 0;
}

longlong Item_func_bit_count::val_int()
{
2365
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2366 2367 2368 2369 2370 2371
  ulonglong value= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
2372
  return (longlong) my_count_bits(value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2373 2374 2375 2376 2377 2378
}


/****************************************************************************
** Functions to handle dynamic loadable functions
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
2379
** Rewritten by monty.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2380 2381 2382 2383 2384
****************************************************************************/

#ifdef HAVE_DLOPEN

bool
2385
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2386 2387
			uint arg_count, Item **arguments)
{
2388
#ifndef EMBEDDED_LIBRARY			// Avoid compiler warning
2389
  char buff[STACK_BUFF_ALLOC];			// Max argument in function
2390
#endif
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2391 2392
  DBUG_ENTER("Item_udf_func::fix_fields");

2393
  if (check_stack_overrun(thd, buff))
2394
    DBUG_RETURN(TRUE);				// Fatal error flag is set!
2395

2396
  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
2397 2398 2399

  if (!tmp_udf)
  {
2400
    my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
2401
    DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2402 2403 2404 2405 2406
  }
  u_d=tmp_udf;
  args=arguments;

  /* Fix all arguments */
2407
  func->maybe_null=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417
  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);
2418
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2419 2420 2421 2422 2423 2424 2425
    }
    uint i;
    Item **arg,**arg_end;
    for (i=0, arg=arguments, arg_end=arguments+arg_count;
	 arg != arg_end ;
	 arg++,i++)
    {
2426
      if (!(*arg)->fixed &&
2427
          (*arg)->fix_fields(thd, tables, arg))
2428
	DBUG_RETURN(1);
2429
      // we can't assign 'item' before, because fix_fields() can change arg
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
2430
      Item *item= *arg;
2431
      if (item->check_cols(1))
2432
	DBUG_RETURN(TRUE);
2433 2434 2435 2436 2437 2438 2439 2440 2441
      /*
	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
2442
        the particular user defined function.
2443
      */
2444 2445
      if (item->collation.collation->state & MY_CS_BINSORT)
	func->collation.set(&my_charset_bin);
2446
      if (item->maybe_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2447
	func->maybe_null=1;
2448 2449 2450 2451
      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
2452
    }
2453
    //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
2454 2455
    if (!(buffers=new String[arg_count]) ||
	!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
2456 2457 2458 2459 2460 2461 2462
	!(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
2463 2464
    {
      free_udf(u_d);
2465
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480
    }
  }
  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;
2481 2482 2483 2484
      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
2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503

      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:
2504
	*((double*) to)= arguments[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
	if (!arguments[i]->null_value)
	{
	  f_args.args[i]=to;
	  to+= ALIGN_SIZE(sizeof(double));
	}
	break;
      default:					// Skip these
	break;
      }
    }
2515
    thd->net.last_error[0]=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2516 2517 2518 2519 2520
    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)))
    {
2521 2522
      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
2523
      free_udf(u_d);
2524
      DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2525 2526 2527 2528
    }
    func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
    func->maybe_null=initid.maybe_null;
    const_item_cache=initid.const_item;
2529
    func->decimals=min(initid.decimals,NOT_FIXED_DEC);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2530 2531 2532 2533
  }
  initialized=1;
  if (error)
  {
2534 2535
    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
             u_d->name.str, ER(ER_UNKNOWN_ERROR));
2536
    DBUG_RETURN(TRUE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2537
  }
2538
  DBUG_RETURN(FALSE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552
}


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:
2553
    case DECIMAL_RESULT:
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571
      {
	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:
2572
      *((double*) to)= args[i]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2573 2574 2575 2576 2577 2578
      if (!args[i]->null_value)
      {
	f_args.args[i]=to;
	to+= ALIGN_SIZE(sizeof(double));
      }
      break;
2579
    case ROW_RESULT:
2580
    default:
2581
      // This case should never be chosen
2582
      DBUG_ASSERT(0);
2583
      break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2584 2585 2586 2587 2588 2589 2590 2591 2592
    }
  }
  return 0;
}

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

String *udf_handler::val_str(String *str,String *save_str)
{
2593
  uchar is_null_tmp=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609
  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;
    }
  }
2610 2611 2612
  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
2613 2614 2615 2616 2617 2618 2619 2620
  {
    return 0;
  }
  if (res == str->ptr())
  {
    str->length(res_length);
    return str;
  }
2621
  save_str->set(res, res_length, str->charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2622 2623 2624 2625
  return save_str;
}


2626 2627 2628 2629
/*
  For the moment, UDF functions are returning DECIMAL values as strings
*/

2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649
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;
  }
2650 2651
  end= res+ res_length;
  str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
2652 2653 2654
  return dec_buf;
}

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

2656
double Item_func_udf_float::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2657
{
2658
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2659 2660 2661 2662 2663 2664 2665 2666 2667
  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)
{
2668
  DBUG_ASSERT(fixed == 1);
2669
  double nr= val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2670 2671
  if (null_value)
    return 0;					/* purecov: inspected */
monty@mysql.com's avatar
monty@mysql.com committed
2672
  str->set(nr,decimals,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2673 2674 2675 2676 2677 2678
  return str;
}


longlong Item_func_udf_int::val_int()
{
2679
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2680 2681 2682 2683 2684 2685 2686 2687 2688 2689
  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)
{
2690
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2691 2692 2693
  longlong nr=val_int();
  if (null_value)
    return 0;
2694
  if (!unsigned_flag)
monty@mysql.com's avatar
monty@mysql.com committed
2695
    str->set(nr,&my_charset_bin);
2696
  else
monty@mysql.com's avatar
monty@mysql.com committed
2697
    str->set((ulonglong) nr,&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2698 2699 2700
  return str;
}

2701 2702 2703 2704

longlong Item_func_udf_decimal::val_int()
{
  my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
2705
  longlong result;
2706 2707 2708 2709 2710 2711 2712 2713 2714 2715
  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);
2716
  double result;
2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753
  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
2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766
/* 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)
{
2767
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2768 2769 2770 2771 2772
  String *res=udf.val_str(str,&str_value);
  null_value = !res;
  return res;
}

2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797

/*
   This has to come last in the udf_handler methods, or the compiler for IBM
   AIX fails to compile with debugging enabled. (Yes, really.)
 */

udf_handler::~udf_handler()
{
  if (!not_original)
  {
    if (initialized)
    {
      if (u_d->func_deinit != NULL)
      {
        void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
        u_d->func_deinit;
        (*deinit)(&initid);
      }
      free_udf(u_d);
    }
    if (buffers)				// Because of bug in ecc
      delete [] buffers;
  }
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808
#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;

2809
class User_level_lock
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2810 2811 2812 2813 2814 2815 2816 2817 2818
{
  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
2819
  ulong thread_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2820

2821
  User_level_lock(const char *key_arg,uint length, ulong id) 
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
2822
    :key_length(length),count(1),locked(1), thread_id(id)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2823 2824 2825 2826 2827
  {
    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
2828
      if (my_hash_insert(&hash_user_locks,(byte*) this))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2829 2830 2831 2832 2833 2834
      {
	my_free((gptr) key,MYF(0));
	key=0;
      }
    }
  }
2835
  ~User_level_lock()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2836 2837 2838 2839 2840 2841 2842 2843 2844
  {
    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; }
2845 2846 2847
  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
2848 2849
};

2850
char *ull_get_key(const User_level_lock *ull, uint *length,
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2851 2852 2853 2854 2855 2856
		  my_bool not_used __attribute__((unused)))
{
  *length=(uint) ull->key_length;
  return (char*) ull->key;
}

2857 2858 2859

static bool item_user_lock_inited= 0;

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2860 2861
void item_user_lock_init(void)
{
2862
  pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW);
2863 2864
  hash_init(&hash_user_locks,system_charset_info,
	    16,0,0,(hash_get_key) ull_get_key,NULL,0);
2865
  item_user_lock_inited= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2866 2867 2868 2869
}

void item_user_lock_free(void)
{
2870 2871 2872 2873 2874 2875
  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
2876 2877
}

2878
void item_user_lock_release(User_level_lock *ull)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2879 2880 2881 2882 2883 2884 2885 2886
{
  ull->locked=0;
  if (--ull->count)
    pthread_cond_signal(&ull->cond);
  else
    delete ull;
}

2887 2888 2889 2890 2891 2892 2893
/*
   Wait until we are at or past the given position in the master binlog
   on the slave
 */

longlong Item_master_pos_wait::val_int()
{
2894
  DBUG_ASSERT(fixed == 1);
2895 2896
  THD* thd = current_thd;
  String *log_name = args[0]->val_str(&value);
2897
  int event_count= 0;
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2898

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
2899 2900 2901 2902 2903 2904
  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
2905
  longlong pos = (ulong)args[1]->val_int();
2906
  longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
hf@deer.mysql.r18.ru's avatar
SCRUM  
hf@deer.mysql.r18.ru committed
2907
#ifdef HAVE_REPLICATION
2908
  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
2909 2910 2911 2912
  {
    null_value = 1;
    event_count=0;
  }
2913
#endif
2914 2915 2916
  return event_count;
}

2917 2918 2919 2920
#ifdef EXTRA_DEBUG
void debug_sync_point(const char* lock_name, uint lock_timeout)
{
  THD* thd=current_thd;
2921
  User_level_lock* ull;
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932
  struct timespec abstime;
  int lock_name_len,error=0;
  lock_name_len=strlen(lock_name);
  pthread_mutex_lock(&LOCK_user_locks);

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

2933 2934 2935 2936 2937
  /*
    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
2938
  */
2939
  if (!(ull= ((User_level_lock*) hash_search(&hash_user_locks, lock_name,
2940 2941 2942 2943 2944 2945 2946
				 lock_name_len))))
  {
    pthread_mutex_unlock(&LOCK_user_locks);
    return;
  }
  ull->count++;

2947 2948 2949 2950
  /*
    Structure is now initialized.  Try to get the lock.
    Set up control struct to allow others to abort locks
  */
2951 2952 2953 2954
  thd->proc_info="User lock";
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

2955
  set_timespec(abstime,lock_timeout);
2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
  while (!thd->killed &&
	 (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
	 != ETIME && error != ETIMEDOUT && ull->locked) ;
  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
2987 2988 2989 2990 2991 2992 2993 2994 2995
/*
  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()
{
2996
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2997 2998 2999 3000
  String *res=args[0]->val_str(&value);
  longlong timeout=args[1]->val_int();
  struct timespec abstime;
  THD *thd=current_thd;
3001
  User_level_lock *ull;
3002
  int error=0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3003

3004 3005 3006 3007 3008 3009 3010 3011 3012 3013
  /*
    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
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029
  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;
  }

3030 3031 3032
  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
3033
  {
3034
    ull=new User_level_lock(res->ptr(),res->length(), thd->thread_id);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048
    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++;

3049 3050 3051 3052
  /*
    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
3053 3054 3055 3056
  thd->proc_info="User lock";
  thd->mysys_var->current_mutex= &LOCK_user_locks;
  thd->mysys_var->current_cond=  &ull->cond;

3057
  set_timespec(abstime,timeout);
3058 3059
  while (!thd->killed &&
	 (error=pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime))
3060
	 != ETIME && error != ETIMEDOUT && error != EINVAL && ull->locked) ;
3061 3062
  if (thd->killed)
    error=EINTR;				// Return NULL
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092
  if (ull->locked)
  {
    if (!--ull->count)
      delete ull;				// Should never happen
    if (error != ETIME && error != ETIMEDOUT)
    {
      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;
}


/*
3093 3094 3095 3096 3097
  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
3098 3099 3100 3101
*/

longlong Item_func_release_lock::val_int()
{
3102
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3103
  String *res=args[0]->val_str(&value);
3104
  User_level_lock *ull;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3105 3106 3107 3108 3109 3110 3111 3112 3113 3114
  longlong result;
  if (!res || !res->length())
  {
    null_value=1;
    return 0;
  }
  null_value=0;

  result=0;
  pthread_mutex_lock(&LOCK_user_locks);
3115 3116 3117
  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
3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
  {
    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;
}


3135
longlong Item_func_last_insert_id::val_int()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3136
{
3137
  THD *thd= current_thd;
3138
  DBUG_ASSERT(fixed == 1);
3139 3140
  if (arg_count)
  {
3141 3142 3143 3144
    longlong value= args[0]->val_int();
    thd->insert_id(value);
    null_value= args[0]->null_value;
    return value;                       // Avoid side effect of insert_id()
3145
  }
3146 3147
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
  return thd->insert_id();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3148 3149 3150 3151 3152 3153
}

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

longlong Item_func_benchmark::val_int()
{
3154
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3155
  char buff[MAX_FIELD_WIDTH];
3156
  String tmp(buff,sizeof(buff), &my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3157 3158 3159 3160 3161 3162
  THD *thd=current_thd;

  for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++)
  {
    switch (args[0]->result_type()) {
    case REAL_RESULT:
3163
      (void) args[0]->val_real();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3164 3165 3166 3167 3168 3169 3170
      break;
    case INT_RESULT:
      (void) args[0]->val_int();
      break;
    case STRING_RESULT:
      (void) args[0]->val_str(&tmp);
      break;
3171
    case ROW_RESULT:
3172
    default:
3173
      // This case should never be chosen
3174 3175
      DBUG_ASSERT(0);
      return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3176 3177 3178 3179 3180
    }
  }
  return 0;
}

3181

3182 3183 3184 3185
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
3186 3187 3188
  // my_charset_bin is good enough for numbers
  String st(buffer, sizeof(buffer), &my_charset_bin);
  st.set((ulonglong)loop_count, &my_charset_bin);
3189 3190 3191 3192 3193 3194
  str->append(st);
  str->append(',');
  args[0]->print(str);
  str->append(')');
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215
#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;
3216
    entry->update_query_id=0;
3217
    entry->collation.set(NULL, DERIVATION_IMPLICIT);
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227
    /*
      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).
    */
3228
    entry->used_query_id=current_thd->query_id;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3229 3230
    entry->type=STRING_RESULT;
    memcpy(entry->name.str, name.str, name.length+1);
hf@deer.(none)'s avatar
SCRUM  
hf@deer.(none) committed
3231
    if (my_hash_insert(hash,(byte*) entry))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3232 3233 3234 3235 3236 3237 3238 3239
    {
      my_free((char*) entry,MYF(0));
      return 0;
    }
  }
  return entry;
}

3240
/*
3241 3242
  When a user variable is updated (in a SET command or a query like
  SELECT @a:= ).
3243
*/
3244

3245 3246
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
					Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3247
{
3248
  DBUG_ASSERT(fixed == 0);
3249
  /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
3250
  if (Item_func::fix_fields(thd, tables, ref) ||
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3251
      !(entry= get_variable(&thd->user_vars, name, 1)))
3252
    return TRUE;
3253 3254 3255 3256 3257
  /* 
     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).
  */
3258
  entry->update_query_id= thd->query_id;
3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274
  /*
    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.
  */
  if (!entry->collation.collation || !args[0]->null_value)
3275 3276
    entry->collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
  collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
3277
  cached_result_type= args[0]->result_type();
3278
  return FALSE;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3279 3280 3281 3282 3283 3284 3285 3286 3287
}


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;
3288
  collation.set(args[0]->collation.collation, DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3289 3290
}

3291

3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311
/*
  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
3312
{
3313
  if (set_null)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3314 3315 3316 3317 3318 3319 3320 3321 3322
  {
    char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
    if (entry->value && entry->value != pos)
      my_free(entry->value,MYF(0));
    entry->value=0;
    entry->length=0;
  }
  else
  {
3323 3324
    if (type == STRING_RESULT)
      length++;					// Store strings with end \0
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345
    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))))
3346
	  return 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3347 3348
      }
    }
3349 3350 3351 3352 3353
    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
3354
    memcpy(entry->value,ptr,length);
3355 3356
    if (type == DECIMAL_RESULT)
      ((my_decimal*)entry->value)->fix_buffer_pointer();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3357 3358
    entry->length= length;
    entry->type=type;
3359
    entry->collation.set(cs, dv);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3360
  }
3361
  return 0;
3362
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3363

3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376

bool
Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type,
                                    CHARSET_INFO *cs, Derivation dv)
{
  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
3377 3378 3379
}


3380 3381
/* Get the value of a variable as a double */

3382
double user_var_entry::val_real(my_bool *null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3383
{
3384 3385 3386 3387 3388 3389 3390 3391
  if ((*null_value= (value == 0)))
    return 0.0;

  switch (type) {
  case REAL_RESULT:
    return *(double*) value;
  case INT_RESULT:
    return (double) *(longlong*) value;
3392 3393 3394 3395 3396 3397
  case DECIMAL_RESULT:
  {
    double result;
    my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
    return result;
  }
3398
  case STRING_RESULT:
serg@serg.mylan's avatar
serg@serg.mylan committed
3399
    return my_atof(value);                      // This is null terminated
3400 3401 3402
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3403
  }
3404
  return 0.0;					// Impossible
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3405 3406 3407
}


3408 3409 3410
/* 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
3411
{
3412 3413 3414 3415 3416 3417 3418 3419
  if ((*null_value= (value == 0)))
    return LL(0);

  switch (type) {
  case REAL_RESULT:
    return (longlong) *(double*) value;
  case INT_RESULT:
    return *(longlong*) value;
3420 3421 3422 3423 3424 3425
  case DECIMAL_RESULT:
  {
    longlong result;
    my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 1, &result);
    return result;
  }
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3426
  case STRING_RESULT:
monty@mysql.com's avatar
monty@mysql.com committed
3427 3428 3429 3430
  {
    int error;
    return my_strtoll10(value, (char**) 0, &error);// String is null terminated
  }
3431 3432 3433
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3434
  }
3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448
  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
3449
    str->set(*(double*) value, decimals, &my_charset_bin);
3450 3451
    break;
  case INT_RESULT:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3452
    str->set(*(longlong*) value, &my_charset_bin);
3453
    break;
3454 3455 3456
  case DECIMAL_RESULT:
    my_decimal2string(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, 0, 0, str);
    break;
3457
  case STRING_RESULT:
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3458
    if (str->copy(value, length, collation.collation))
3459
      str= 0;					// EOM error
3460 3461 3462
  case ROW_RESULT:
    DBUG_ASSERT(1);				// Impossible
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3463
  }
3464
  return(str);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3465 3466
}

3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493
/* 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);
}

3494 3495
/*
  This functions is invoked on SET @variable or @variable:= expression.
3496
  Evaluate (and check expression), store results.
3497 3498 3499 3500 3501

  SYNOPSYS
    Item_func_set_user_var::check()

  NOTES
3502 3503
    For now it always return OK. All problem with value evaluating
    will be caught by thd->net.report_error check in sql_set_variables().
3504 3505

  RETURN
3506
    FALSE OK.
3507 3508 3509 3510 3511 3512 3513 3514 3515 3516
*/

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

  switch (cached_result_type) {
  case REAL_RESULT:
  {
3517
    save_result.vreal= args[0]->val_real();
3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529
    break;
  }
  case INT_RESULT:
  {
    save_result.vint= args[0]->val_int();
    break;
  }
  case STRING_RESULT:
  {
    save_result.vstr= args[0]->val_str(&value);
    break;
  }
3530 3531 3532 3533 3534
  case DECIMAL_RESULT:
  {
    save_result.vdec= args[0]->val_decimal(&decimal_buff);
    break;
  }
3535 3536
  case ROW_RESULT:
  default:
3537
    // This case should never be chosen
3538 3539 3540
    DBUG_ASSERT(0);
    break;
  }
3541
  DBUG_RETURN(FALSE);
3542 3543
}

3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555

/*
  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
3556
    0	OK
3557 3558 3559 3560
    1	EOM Error

*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3561 3562 3563
bool
Item_func_set_user_var::update()
{
3564 3565 3566 3567
  bool res;
  DBUG_ENTER("Item_func_set_user_var::update");
  LINT_INIT(res);

bk@work.mysql.com's avatar
bk@work.mysql.com committed
3568 3569
  switch (cached_result_type) {
  case REAL_RESULT:
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3570
  {
3571 3572
    res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
		     REAL_RESULT, &my_charset_bin, DERIVATION_NONE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3573
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3574
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3575
  case INT_RESULT:
3576
  {
3577 3578
    res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
		     INT_RESULT, &my_charset_bin, DERIVATION_NONE);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3579
    break;
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3580
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3581
  case STRING_RESULT:
3582
  {
3583
    if (!save_result.vstr)					// Null value
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
3584 3585
      res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
		       DERIVATION_NONE);
3586
    else
3587 3588 3589
      res= update_hash((void*) save_result.vstr->ptr(),
		       save_result.vstr->length(), STRING_RESULT,
		       save_result.vstr->charset(),
3590
		       DERIVATION_IMPLICIT);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3591 3592
    break;
  }
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603
  case DECIMAL_RESULT:
  {
    if (!save_result.vdec)					// Null value
      res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
                       DERIVATION_NONE);
    else
      res= update_hash((void*) save_result.vdec,
                       sizeof(my_decimal), DECIMAL_RESULT,
                       &my_charset_bin, DERIVATION_NONE);
    break;
  }
3604
  case ROW_RESULT:
3605
  default:
3606
    // This case should never be chosen
3607 3608 3609
    DBUG_ASSERT(0);
    break;
  }
3610
  DBUG_RETURN(res);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3611 3612 3613
}


3614
double Item_func_set_user_var::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3615
{
3616
  DBUG_ASSERT(fixed == 1);
3617
  check();
3618
  update();					// Store expression
3619
  return entry->val_real(&null_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3620 3621
}

3622
longlong Item_func_set_user_var::val_int()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3623
{
3624
  DBUG_ASSERT(fixed == 1);
3625
  check();
3626 3627
  update();					// Store expression
  return entry->val_int(&null_value);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3628 3629
}

3630
String *Item_func_set_user_var::val_str(String *str)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3631
{
3632
  DBUG_ASSERT(fixed == 1);
3633
  check();
3634 3635
  update();					// Store expression
  return entry->val_str(&null_value, str, decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3636 3637 3638
}


3639 3640 3641 3642 3643 3644 3645 3646 3647
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);
}


3648 3649
void Item_func_set_user_var::print(String *str)
{
3650 3651 3652
  str->append("(@", 2);
  str->append(name.str, name.length);
  str->append(":=", 2);
3653 3654 3655 3656 3657
  args[0]->print(str);
  str->append(')');
}


3658 3659 3660 3661 3662 3663 3664 3665 3666 3667
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
3668 3669 3670
String *
Item_func_get_user_var::val_str(String *str)
{
3671
  DBUG_ASSERT(fixed == 1);
vva@eagle.mysql.r18.ru's avatar
vva@eagle.mysql.r18.ru committed
3672
  DBUG_ENTER("Item_func_get_user_var::val_str");
3673
  if (!var_entry)
3674
    DBUG_RETURN((String*) 0);			// No such variable
3675
  DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3676 3677 3678
}


3679
double Item_func_get_user_var::val_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3680
{
3681
  DBUG_ASSERT(fixed == 1);
3682 3683
  if (!var_entry)
    return 0.0;					// No such variable
3684 3685 3686 3687 3688 3689 3690 3691 3692 3693
  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
3694 3695 3696 3697 3698
}


longlong Item_func_get_user_var::val_int()
{
3699
  DBUG_ASSERT(fixed == 1);
3700 3701 3702
  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
3703 3704 3705
}


3706
/*
3707 3708 3709 3710 3711 3712 3713 3714 3715 3716
  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.

3717 3718 3719 3720
  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).
3721 3722 3723
  
  RETURN
    0  OK 
3724
    1  Failed to put appropriate record into binary log
3725
    
3726 3727
*/

3728 3729
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
3730
{
3731
  BINLOG_USER_VAR_EVENT *user_var_event;
3732 3733
  user_var_entry *var_entry;
  var_entry= get_variable(&thd->user_vars, name, 0);
3734
  
pem@mysql.com's avatar
pem@mysql.com committed
3735
  if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
3736 3737 3738 3739
  {
    *out_entry= var_entry;
    return 0;
  }
3740 3741

  if (!var_entry)
3742
  {
3743
    /*
3744 3745 3746 3747
      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).
3748 3749
      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;'.
3750 3751 3752
      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();
3753 3754
      this would save memory and time; but calling sql_set_variables() makes
      one unique place to maintain (sql_set_variables()). 
3755 3756 3757 3758 3759
    */

    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())));
3760 3761
    /* Create the variable */
    if (sql_set_variables(thd, &tmp_var_list))
3762 3763 3764 3765 3766
      goto err;
    if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
      goto err;
  }
  else if (var_entry->used_query_id == thd->query_id)
3767 3768 3769 3770 3771 3772 3773 3774 3775
  {
    /* 
       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;
  }
3776 3777 3778 3779

  uint size;
  /*
    First we need to store value of var_entry, when the next situation
3780
    appears:
3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798
    > 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;
3799
  }
3800 3801 3802 3803 3804 3805 3806 3807 3808 3809
  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;
3810 3811 3812
  
  *out_entry= var_entry;
  return 0;
3813

3814
err:
3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826
  *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;
3827

3828
  error= get_var_with_binlog(thd, name, &var_entry);
3829 3830

  if (var_entry)
3831
  {
3832
    collation.set(var_entry->collation);
3833 3834 3835 3836 3837 3838 3839 3840 3841
    switch (var_entry->type) {
    case REAL_RESULT:
      max_length= DBL_DIG + 8;
    case INT_RESULT:
      max_length= MAX_BIGINT_WIDTH;
      break;
    case STRING_RESULT:
      max_length= MAX_BLOB_WIDTH;
      break;
3842 3843 3844 3845
    case DECIMAL_RESULT:
      max_length= DECIMAL_MAX_LENGTH;
      decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
      break;
monty@mysql.com's avatar
monty@mysql.com committed
3846
    case ROW_RESULT:                            // Keep compiler happy
3847 3848
    default:
      DBUG_ASSERT(0);
monty@mysql.com's avatar
monty@mysql.com committed
3849
      break;
3850 3851
    }
  }
3852 3853 3854
  else
    null_value= 1;

3855 3856
  if (error)
    thd->fatal_error();
3857

3858
  return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3859 3860 3861
}


3862
bool Item_func_get_user_var::const_item() const
3863
{
3864
  return (!var_entry || current_thd->query_id != var_entry->update_query_id);
3865
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877


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

3878 3879 3880

void Item_func_get_user_var::print(String *str)
{
3881
  str->append("(@", 2);
3882 3883 3884 3885
  str->append(name.str,name.length);
  str->append(')');
}

3886

3887
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901
{
  /* Assume we don't have rtti */
  if (this == item)
    return 1;					// Same item is same.
  /* Check if other type is also a get_user_var() object */
  if (item->type() != FUNC_ITEM ||
      ((Item_func*) item)->func_name() != func_name())
    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));
}


3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972
bool Item_user_var_as_out_param::fix_fields(THD *thd, TABLE_LIST *tables,
                                            Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  if (Item::fix_fields(thd, tables, ref) ||
      !(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);
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
3973 3974
longlong Item_func_inet_aton::val_int()
{
3975
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3976 3977 3978 3979 3980
  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];
3981
  int dot_count= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3982

3983
  String *s,tmp(buff,sizeof(buff),&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999
  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 == '.')
    {
4000
      dot_count++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4001 4002 4003 4004 4005 4006 4007
      result= (result << 8) + (ulonglong) byte_result;
      byte_result = 0;
    }
    else
      goto err;					// Invalid character
  }
  if (c != '.')					// IP number can't end on '.'
4008
  {
4009 4010 4011 4012 4013 4014
    /*
      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
    */
4015
    switch (dot_count) {
4016 4017
    case 1: result<<= 8; /* Fall through */
    case 2: result<<= 8; /* Fall through */
4018
    }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4019
    return (result << 8) + (ulonglong) byte_result;
4020
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4021 4022 4023 4024 4025 4026

err:
  null_value=1;
  return 0;
}

4027

4028
void Item_func_match::init_search(bool no_order)
4029
{
4030
  DBUG_ENTER("Item_func_match::init_search");
4031 4032

  /* Check if init_search() has been called before */
4033
  if (ft_handler)
4034
    DBUG_VOID_RETURN;
4035

4036
  if (key == NO_SUCH_KEY)
4037 4038
  {
    List<Item> fields;
4039
    fields.push_back(new Item_string(" ",1, cmp_collation.collation));
4040 4041
    for (uint i=1; i < arg_count; i++)
      fields.push_back(args[i]);
4042
    concat=new Item_func_concat_ws(fields);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4043 4044 4045
    /*
      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
4046 4047
      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
4048 4049
    */
    concat->quick_fix_field();
4050
  }
4051

4052 4053
  if (master)
  {
4054 4055
    join_key=master->join_key=join_key|master->join_key;
    master->init_search(no_order);
4056 4057
    ft_handler=master->ft_handler;
    join_key=master->join_key;
4058
    DBUG_VOID_RETURN;
4059 4060
  }

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

4063
  // MATCH ... AGAINST (NULL) is meaningless, but possible
4064
  if (!(ft_tmp=key_item()->val_str(&value)))
4065
  {
4066 4067
    ft_tmp= &value;
    value.set("",0,cmp_collation.collation);
4068 4069
  }

4070 4071
  if (ft_tmp->charset() != cmp_collation.collation)
  {
4072
    uint dummy_errors;
4073
    search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
4074
                      cmp_collation.collation, &dummy_errors);
4075
    ft_tmp= &search_value;
4076 4077
  }

4078 4079
  if (join_key && !no_order)
    flags|=FT_SORTED;
4080
  ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
4081 4082 4083

  if (join_key)
    table->file->ft_handler=ft_handler;
4084 4085

  DBUG_VOID_RETURN;
4086 4087
}

4088

4089
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4090
{
4091
  DBUG_ASSERT(fixed == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4092
  Item *item;
4093
  LINT_INIT(item);				// Safe as arg_count is > 1
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4094

4095 4096 4097
  maybe_null=1;
  join_key=0;

4098 4099 4100 4101 4102
  /*
    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.
4103
   */
4104 4105
  if (Item_func::fix_fields(thd, tlist, ref) ||
      !args[0]->const_during_execution())
4106 4107
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
4108
    return TRUE;
4109
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4110

4111 4112
  const_item_cache=0;
  for (uint i=1 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4113
  {
4114
    item=args[i];
serg@serg.mysql.com's avatar
serg@serg.mysql.com committed
4115
    if (item->type() == Item::REF_ITEM)
4116 4117
      args[i]= item= *((Item_ref *)item)->ref;
    if (item->type() != Item::FIELD_ITEM)
4118
      key=NO_SUCH_KEY;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4119
  }
4120 4121
  /*
    Check that all columns come from the same table.
4122
    We've already checked that columns in MATCH are fields so
4123 4124 4125
    PARAM_TABLE_BIT can only appear from AGAINST argument.
  */
  if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
4126
    key=NO_SUCH_KEY;
4127

4128
  if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
4129 4130
  {
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
4131
    return TRUE;
4132
  }
4133 4134 4135
  table=((Item_field *)item)->field->table;
  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
4136
}
4137

bk@work.mysql.com's avatar
bk@work.mysql.com committed
4138 4139 4140
bool Item_func_match::fix_index()
{
  Item_field *item;
4141
  uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
4142
  uint max_cnt=0, mkeys=0, i;
4143

4144
  if (key == NO_SUCH_KEY)
4145
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4146

4147
  for (keynr=0 ; keynr < table->s->keys ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4148
  {
4149
    if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
4150
        (table->keys_in_use_for_query.is_set(keynr)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4151
    {
4152
      ft_to_key[fts]=keynr;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4153 4154 4155 4156 4157 4158
      ft_cnt[fts]=0;
      fts++;
    }
  }

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

4161
  for (i=1; i < arg_count; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4162
  {
4163
    item=(Item_field*)args[i];
4164
    for (keynr=0 ; keynr < fts ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4165
    {
4166
      KEY *ft_key=&table->key_info[ft_to_key[keynr]];
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4167 4168 4169 4170 4171
      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))
4172
	  ft_cnt[keynr]++;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4173 4174 4175 4176
      }
    }
  }

4177
  for (keynr=0 ; keynr < fts ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4178
  {
4179
    if (ft_cnt[keynr] > max_cnt)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4180
    {
4181
      mkeys=0;
4182 4183
      max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
4184 4185
      continue;
    }
4186
    if (max_cnt && ft_cnt[keynr] == max_cnt)
4187 4188
    {
      mkeys++;
4189 4190
      ft_cnt[mkeys]=ft_cnt[keynr];
      ft_to_key[mkeys]=ft_to_key[keynr];
4191
      continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4192 4193 4194
    }
  }

4195
  for (keynr=0 ; keynr <= mkeys ; keynr++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4196
  {
4197 4198
    // partial keys doesn't work
    if (max_cnt < arg_count-1 ||
4199
        max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
4200
      continue;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4201

4202
    key=ft_to_key[keynr];
4203

4204 4205 4206
    return 0;
  }

4207
err:
4208
  if (flags & FT_BOOL)
4209
  {
4210
    key=NO_SUCH_KEY;
4211 4212
    return 0;
  }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4213 4214
  my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
             ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
4215
  return 1;
4216 4217
}

4218

4219
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
4220
{
4221 4222
  if (item->type() != FUNC_ITEM || ((Item_func*)item)->functype() != FT_FUNC ||
      flags != ((Item_func_match*)item)->flags)
4223 4224 4225 4226 4227
    return 0;

  Item_func_match *ifm=(Item_func_match*) item;

  if (key == ifm->key && table == ifm->table &&
4228
      key_item()->eq(ifm->key_item(), binary_cmp))
4229
    return 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
4230 4231 4232 4233

  return 0;
}

4234

4235
double Item_func_match::val_real()
4236
{
4237
  DBUG_ASSERT(fixed == 1);
4238
  DBUG_ENTER("Item_func_match::val");
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
4239
  if (ft_handler == NULL)
4240
    DBUG_RETURN(-1.0);
4241

4242 4243 4244
  if (table->null_row) /* NULL row from an outer join */
    return 0.0;

4245 4246 4247
  if (join_key)
  {
    if (table->file->ft_handler)
4248
      DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
4249 4250 4251
    join_key=0;
  }

4252
  if (key == NO_SUCH_KEY)
4253
  {
4254 4255
    String *a= concat->val_str(&value);
    if ((null_value= (a == 0)))
4256 4257 4258
      DBUG_RETURN(0);
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
				      (byte *)a->ptr(), a->length()));
4259 4260
  }
  else
4261 4262
    DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
                                                   table->record[0], 0));
4263 4264
}

4265 4266
void Item_func_match::print(String *str)
{
4267
  str->append("(match ", 7);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4268
  print_args(str, 1);
4269
  str->append(" against (", 10);
4270
  args[0]->print(str);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4271
  if (flags & FT_BOOL)
4272
    str->append(" in boolean mode", 16);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
4273 4274
  else if (flags & FT_EXPAND)
    str->append(" with query expansion", 21);
4275
  str->append("))", 2);
4276
}
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
4277

4278 4279
longlong Item_func_bit_xor::val_int()
{
4280
  DBUG_ASSERT(fixed == 1);
4281 4282
  ulonglong arg1= (ulonglong) args[0]->val_int();
  ulonglong arg2= (ulonglong) args[1]->val_int();
4283
  if ((null_value= (args[0]->null_value || args[1]->null_value)))
4284 4285 4286 4287
    return 0;
  return (longlong) (arg1 ^ arg2);
}

4288

4289 4290 4291 4292
/***************************************************************************
  System variables
****************************************************************************/

4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313
/*
  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
*/
  

Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
		     LEX_STRING component)
4314
{
4315 4316
  if (component.str == 0 &&
      !my_strcasecmp(system_charset_info, name.str, "VERSION"))
4317 4318 4319
    return new Item_string("@@VERSION", server_version,
			   (uint) strlen(server_version),
			   system_charset_info);
4320 4321 4322

  Item *item;
  sys_var *var;
4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335
  char buff[MAX_SYS_VAR_LENGTH*2+4+8], *pos;
  LEX_STRING *base_name, *component_name;

  if (component.str)
  {
    base_name= &component;
    component_name= &name;
  }
  else
  {
    base_name= &name;
    component_name= &component;			// Empty string
  }
4336

4337
  if (!(var= find_sys_var(base_name->str, base_name->length)))
4338
    return 0;
4339 4340 4341 4342
  if (component.str)
  {
    if (!var->is_struct())
    {
4343
      my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
4344 4345 4346 4347
      return 0;
    }
  }
  if (!(item=var->item(thd, var_type, component_name)))
4348
    return 0;					// Impossible
pem@mysql.com's avatar
pem@mysql.com committed
4349
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
4350 4351
  buff[0]='@';
  buff[1]='@';
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
4352 4353 4354 4355 4356
  pos=buff+2;
  if (var_type == OPT_SESSION)
    pos=strmov(pos,"session.");
  else if (var_type == OPT_GLOBAL)
    pos=strmov(pos,"global.");
4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369
  
  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;

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
4370
  // set_name() will allocate the name
4371
  item->set_name(buff,(uint) (pos-buff), system_charset_info);
4372
  return item;
4373
}
4374

4375

4376 4377
Item *get_system_var(THD *thd, enum_var_type var_type, const char *var_name,
		     uint length, const char *item_name)
4378 4379 4380
{
  Item *item;
  sys_var *var;
4381 4382 4383
  LEX_STRING null_lex_string;

  null_lex_string.str= 0;
4384 4385 4386

  var= find_sys_var(var_name, length);
  DBUG_ASSERT(var != 0);
4387
  if (!(item=var->item(thd, var_type, &null_lex_string)))
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
4388
    return 0;						// Impossible
pem@mysql.com's avatar
pem@mysql.com committed
4389
  thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
4390
  item->set_name(item_name, 0, system_charset_info);	// Will use original name
4391 4392 4393 4394
  return item;
}


4395 4396
/*
  Check a user level lock.
4397 4398 4399 4400 4401 4402 4403 4404

  SYNOPSIS:
    val_int()

  RETURN VALUES
    1		Available
    0		Already taken
    NULL	Error
4405 4406
*/

4407
longlong Item_func_is_free_lock::val_int()
4408
{
4409
  DBUG_ASSERT(fixed == 1);
4410
  String *res=args[0]->val_str(&value);
4411
  User_level_lock *ull;
4412 4413

  null_value=0;
4414
  if (!res || !res->length())
4415 4416 4417 4418 4419 4420
  {
    null_value=1;
    return 0;
  }
  
  pthread_mutex_lock(&LOCK_user_locks);
4421
  ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
4422 4423 4424 4425 4426 4427
			  res->length());
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 1;
  return 0;
}
4428

hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4429 4430
longlong Item_func_is_used_lock::val_int()
{
4431
  DBUG_ASSERT(fixed == 1);
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4432
  String *res=args[0]->val_str(&value);
4433
  User_level_lock *ull;
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4434 4435 4436 4437 4438 4439

  null_value=1;
  if (!res || !res->length())
    return 0;
  
  pthread_mutex_lock(&LOCK_user_locks);
4440
  ull= (User_level_lock *) hash_search(&hash_user_locks, (byte*) res->ptr(),
hf@genie.(none)'s avatar
SCRUM  
hf@genie.(none) committed
4441 4442 4443 4444 4445 4446 4447 4448 4449
			  res->length());
  pthread_mutex_unlock(&LOCK_user_locks);
  if (!ull || !ull->locked)
    return 0;

  null_value=0;
  return ull->thread_id;
}

4450

4451 4452 4453 4454 4455 4456 4457 4458 4459
longlong Item_func_row_count::val_int()
{
  DBUG_ASSERT(fixed == 1);
  THD *thd= current_thd;

  return thd->row_count_func;
}


4460 4461 4462
Item_func_sp::Item_func_sp(sp_name *name)
  :Item_func(), m_name(name), m_sp(NULL)
{
4463
  maybe_null= 1;
4464
  m_name->init_qname(current_thd);
monty@mysql.com's avatar
monty@mysql.com committed
4465
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
4466 4467
}

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

4469 4470 4471
Item_func_sp::Item_func_sp(sp_name *name, List<Item> &list)
  :Item_func(list), m_name(name), m_sp(NULL)
{
4472
  maybe_null= 1;
4473
  m_name->init_qname(current_thd);
monty@mysql.com's avatar
monty@mysql.com committed
4474
  dummy_table= (TABLE*) sql_calloc(sizeof(TABLE));
4475 4476
}

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

4478 4479 4480
const char *
Item_func_sp::func_name() const
{
4481
  THD *thd= current_thd;
4482
  /* Calculate length to avoid reallocation of string for sure */
4483 4484 4485 4486
  uint len= ((m_name->m_db.length +
              m_name->m_name.length)*2 + //characters*quoting
             2 +                         // ` and `
             1 +                         // .
4487 4488
             1 +                         // end of string
             ALIGN_SIZE(1));             // to avoid String reallocation
monty@mysql.com's avatar
monty@mysql.com committed
4489
  String qname((char *)alloc_root(thd->mem_root, len), len,
4490
               system_charset_info);
4491

4492 4493 4494 4495 4496
  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();
4497 4498
}

4499

4500 4501 4502 4503 4504 4505 4506
Field *
Item_func_sp::sp_result_field(void) const
{
  Field *field= 0;
  THD *thd= current_thd;
  DBUG_ENTER("Item_func_sp::sp_result_field");
  if (m_sp)
4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521
  {
    if (dummy_table->s == NULL)
    {
      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;
      share->table_name = empty_name;
    }
    field= m_sp->make_field(max_length, name, dummy_table);
  }
4522 4523 4524 4525
  DBUG_RETURN(field);
}


4526 4527 4528 4529 4530
int
Item_func_sp::execute(Item **itp)
{
  DBUG_ENTER("Item_func_sp::execute");
  THD *thd= current_thd;
4531
  int res;
4532 4533 4534
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  st_sp_security_context save_ctx;
#endif
4535

4536
  if (! m_sp)
4537
    m_sp= sp_find_function(thd, m_name, TRUE); // cache only
4538
  if (! m_sp)
4539
  {
4540
    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
4541
    DBUG_RETURN(-1);
4542
  }
4543

4544 4545 4546 4547 4548
#ifndef EMBEDDED_LIBRARY
  my_bool nsok= thd->net.no_send_ok;
  thd->net.no_send_ok= TRUE;
#endif

4549
#ifndef NO_EMBEDDED_ACCESS_CHECKS
4550 4551 4552
  if (check_procedure_access(thd, EXECUTE_ACL, 
			     m_sp->m_db.str, m_sp->m_name.str, 0))
      DBUG_RETURN(-1);
4553
  sp_change_security_context(thd, m_sp, &save_ctx);
4554 4555 4556 4557 4558 4559 4560
  if (save_ctx.changed && 
      check_procedure_access(thd, EXECUTE_ACL, 
			     m_sp->m_db.str, m_sp->m_name.str, 0))
  {
    sp_restore_security_context(thd, m_sp, &save_ctx);
    DBUG_RETURN(-1);
  }
4561
#endif
4562 4563 4564

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

4565
#ifndef NO_EMBEDDED_ACCESS_CHECKS
4566
  sp_restore_security_context(thd, m_sp, &save_ctx);
4567
#endif
4568

4569 4570 4571
#ifndef EMBEDDED_LIBRARY
  thd->net.no_send_ok= nsok;
#endif
4572
  DBUG_RETURN(res);
4573 4574
}

4575

4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594
void
Item_func_sp::make_field(Send_field *tmp_field)
{
  Field *field;
  DBUG_ENTER("Item_func_sp::make_field");
  if (! m_sp)
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
  if ((field= sp_result_field()))
  {
    field->make_field(tmp_field);
    delete field;
    DBUG_VOID_RETURN;
  }
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
  init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);  
  DBUG_VOID_RETURN;
}


4595 4596
enum enum_field_types
Item_func_sp::field_type() const
4597
{
4598
  Field *field= 0;
4599
  DBUG_ENTER("Item_func_sp::field_type");
4600

4601
  if (! m_sp)
4602
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
4603
  if ((field= sp_result_field()))
4604
  {
4605 4606 4607
    enum_field_types result= field->type();
    delete field;
    DBUG_RETURN(result);
4608
  }
4609
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
4610
  DBUG_RETURN(MYSQL_TYPE_VARCHAR);
4611 4612
}

4613

4614 4615
Item_result
Item_func_sp::result_type() const
4616
{
4617
  Field *field= 0;
4618 4619
  DBUG_ENTER("Item_func_sp::result_type");
  DBUG_PRINT("info", ("m_sp = %p", m_sp));
4620

4621
  if (! m_sp)
4622
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
4623
  if ((field= sp_result_field()))
4624
  {
4625 4626 4627
    Item_result result= field->result_type();
    delete field;
    DBUG_RETURN(result);
4628
  }
4629
  my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
4630
  DBUG_RETURN(STRING_RESULT);
4631 4632 4633 4634 4635 4636 4637
}

void
Item_func_sp::fix_length_and_dec()
{
  DBUG_ENTER("Item_func_sp::fix_length_and_dec");

4638
  if (! m_sp)
4639
    m_sp= sp_find_function(current_thd, m_name, TRUE); // cache only
4640 4641
  if (! m_sp)
  {
4642
    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
4643 4644
  }
  else
4645
  {
4646
    switch (result_type()) {
4647 4648
    case STRING_RESULT:
      maybe_null= 1;
4649
      max_length= MAX_BLOB_WIDTH;
4650 4651 4652 4653 4654 4655 4656 4657 4658
      break;
    case REAL_RESULT:
      decimals= NOT_FIXED_DEC;
      max_length= float_length(decimals);
      break;
    case INT_RESULT:
      decimals= 0;
      max_length= 21;
      break;
4659 4660 4661 4662
    case DECIMAL_RESULT:
      // TODO: where to find real precision and scale?
      decimals= min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1);
      max_length= DECIMAL_MAX_LENGTH;
4663 4664
    case ROW_RESULT:
    default:
4665
      // This case should never be chosen
4666 4667
      DBUG_ASSERT(0);
      break;
4668 4669 4670 4671
    }
  }
  DBUG_VOID_RETURN;
}
monty@mysql.com's avatar
monty@mysql.com committed
4672 4673


4674 4675 4676 4677 4678 4679 4680
longlong Item_func_found_rows::val_int()
{
  DBUG_ASSERT(fixed == 1);
  THD *thd= current_thd;

  return thd->found_rows();
}
4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695

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