item_cmpfunc.cc 72.3 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
unknown's avatar
unknown committed
2

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

unknown's avatar
unknown committed
8 9 10 11
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
12

unknown's avatar
unknown committed
13 14 15 16 17 18 19
   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 compare functions */

20
#ifdef USE_PRAGMA_IMPLEMENTATION
unknown's avatar
unknown committed
21 22
#pragma implementation				// gcc: Class implementation
#endif
23 24

#include "mysql_priv.h"
unknown's avatar
unknown committed
25
#include <m_ctype.h>
26
#include "sql_select.h"
27

28 29
static bool convert_constant_item(THD *thd, Field *field, Item **item);

30 31 32 33 34 35 36 37 38 39 40 41
static Item_result item_store_type(Item_result a,Item_result b)
{
  if (a == STRING_RESULT || b == STRING_RESULT)
    return STRING_RESULT;
  else if (a == REAL_RESULT || b == REAL_RESULT)
    return REAL_RESULT;
  else
    return INT_RESULT;
}

static void agg_result_type(Item_result *type, Item **items, uint nitems)
{
42 43 44 45 46
  Item **item, **item_end;

  *type= STRING_RESULT;
  /* Skip beginning NULL items */
  for (item= items, item_end= item + nitems; item < item_end; item++)
47
  {
48 49 50 51 52 53
    if ((*item)->type() != Item::NULL_ITEM)
    {
      *type= (*item)->result_type();
      item++;
      break;
    }
54 55
  }
  /* Combine result types. Note: NULL items don't affect the result */
56
  for (; item < item_end; item++)
57
  {
58 59
    if ((*item)->type() != Item::NULL_ITEM)
      *type= item_store_type(type[0], (*item)->result_type());
60
  }
61 62
}

63 64 65 66 67 68

/*
  Aggregates result types from the array of items.

  SYNOPSIS:
    agg_cmp_type()
69
    thd          thread handle
70 71 72 73 74 75 76 77 78 79 80
    type   [out] the aggregated type
    items        array of items to aggregate the type from
    nitems       number of items in the array

  DESCRIPTION
    This function aggregates result types from the array of items. Found type
    supposed to be used later for comparison of values of these items.
    Aggregation itself is performed by the item_cmp_type() function.

  NOTES
    Aggregation rules:
81 82
    If there are DATE/TIME fields/functions in the list and no string
    fields/functions in the list then:
unknown's avatar
unknown committed
83
      The INT_RESULT type will be used for aggregation instead of original
84 85 86 87 88
      result type of any DATE/TIME field/function in the list
      All constant items in the list will be converted to a DATE/TIME using
      found field or result field of found function.

    Implementation notes:
unknown's avatar
unknown committed
89 90
      The code is equivalent to:
      1. Check the list for presence of a STRING field/function.
91 92 93 94
         Collect the is_const flag.
      2. Get a Field* object to use for type coercion
      3. Perform type conversion.
      1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME
unknown's avatar
unknown committed
95
      field/function and checks presence of a STRING field/function.
96
      The second loop works only if a DATE/TIME field/function is found.
unknown's avatar
unknown committed
97
      It checks presence of a STRING field/function in the rest of the list.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

  TODO
    1) The current implementation can produce false comparison results for
    expressions like:
      date_time_field BETWEEN string_field_with_dates AND string_constant
    if the string_constant will omit some of leading zeroes.
    In order to fully implement correct comparison of DATE/TIME the new
    DATETIME_RESULT result type should be introduced and agg_cmp_type()
    should return the DATE/TIME field used for the conversion. Later
    this field can be used by comparison functions like Item_func_between to
    convert string values to ints on the fly and thus return correct results.
    This modification will affect functions BETWEEN, IN and CASE.

    2) If in the list a DATE field/function and a DATETIME field/function
    are present in the list then the first found field/function will be
    used for conversion. This may lead to wrong results and probably should
    be fixed.
115
*/
116 117

static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
118 119
{
  uint i;
unknown's avatar
unknown committed
120 121 122
  Item::Type res= (Item::Type)0;
  /* Used only for date/time fields, max_length = 19 */
  char buff[20];
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
  uchar null_byte;
  Field *field= NULL;

  /* Search for date/time fields/functions */
  for (i= 0; i < nitems; i++)
  {
    if (!items[i]->result_as_longlong())
    {
      /* Do not convert anything if a string field/function is present */
      if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT)
      {
        i= nitems;
        break;
      }
      continue;
    }
    if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM)
    {
      field= ((Item_field *)items[i]->real_item())->field;
      break;
    }
    else if (res == Item::FUNC_ITEM)
    {
      field= items[i]->tmp_table_field_from_field_type(0);
      if (field)
        field->move_field(buff, &null_byte, 0);
      break;
    }
  }
  if (field)
  {
unknown's avatar
unknown committed
154
    /* Check the rest of the list for presence of a string field/function. */
155 156 157 158 159
    for (i++ ; i < nitems; i++)
    {
      if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT &&
          !items[i]->result_as_longlong())
      {
unknown's avatar
unknown committed
160 161
        if (res == Item::FUNC_ITEM)
          delete field;
162 163 164 165 166 167 168 169 170 171
        field= 0;
        break;
      }
    }
  }
  /*
    If the first item is a date/time function then its result should be
    compared as int
  */
  if (field)
172
    /* Suppose we are comparing dates */
173 174 175
    type[0]= INT_RESULT;
  else
    type[0]= items[0]->result_type();
176

177
  for (i= 0; i < nitems ; i++)
178
  {
179 180 181 182 183 184 185
    Item_result result= items[i]->result_type();
    if (field &&
         ((!items[i]->const_item() && items[i]->result_as_longlong()) ||
         (items[i]->const_item() && convert_constant_item(thd, field,
                                                          &items[i]))))
      result= INT_RESULT;
    type[0]= item_cmp_type(type[0], result);
186 187 188 189
  }

  if (res == Item::FUNC_ITEM && field)
    delete field;
190 191
}

unknown's avatar
unknown committed
192 193
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
                              const char *fname)
194
{
195
  my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
196 197 198 199 200
  	   c1.collation->name,c1.derivation_name(),
	   c2.collation->name,c2.derivation_name(),
	   fname);
}

unknown's avatar
unknown committed
201 202

Item_bool_func2* Eq_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
203 204 205
{
  return new Item_func_eq(a, b);
}
unknown's avatar
unknown committed
206 207 208


Item_bool_func2* Ne_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
209 210 211
{
  return new Item_func_ne(a, b);
}
unknown's avatar
unknown committed
212 213 214


Item_bool_func2* Gt_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
215 216 217
{
  return new Item_func_gt(a, b);
}
unknown's avatar
unknown committed
218 219 220


Item_bool_func2* Lt_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
221 222 223
{
  return new Item_func_lt(a, b);
}
unknown's avatar
unknown committed
224 225 226


Item_bool_func2* Ge_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
227 228 229
{
  return new Item_func_ge(a, b);
}
unknown's avatar
unknown committed
230 231 232


Item_bool_func2* Le_creator::create(Item *a, Item *b) const
unknown's avatar
unknown committed
233 234 235
{
  return new Item_func_le(a, b);
}
unknown's avatar
unknown committed
236

unknown's avatar
unknown committed
237
/*
238
  Test functions
239 240
  Most of these  returns 0LL if false and 1LL if true and
  NULL if some arg is NULL.
unknown's avatar
unknown committed
241 242 243 244
*/

longlong Item_func_not::val_int()
{
245
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
246 247
  double value=args[0]->val();
  null_value=args[0]->null_value;
248
  return ((!null_value && value == 0) ? 1 : 0);
unknown's avatar
unknown committed
249 250
}

251 252 253 254 255
/*
  special NOT for ALL subquery
*/

longlong Item_func_not_all::val_int()
256 257
{
  DBUG_ASSERT(fixed == 1);
258
  double value= args[0]->val();
259 260 261

  /*
    return TRUE if there was records in underlaying select in max/min
unknown's avatar
unknown committed
262
    optimisation (ALL subquery)
263 264 265 266
  */
  if (empty_underlying_subquery())
    return 1;

267
  null_value= args[0]->null_value;
268 269 270 271 272 273 274 275
  return ((!null_value && value == 0) ? 1 : 0);
}


bool Item_func_not_all::empty_underlying_subquery()
{
  return ((test_sum_item && !test_sum_item->any_value()) ||
          (test_sub_item && !test_sub_item->any_value()));
276 277
}

unknown's avatar
unknown committed
278 279 280 281 282 283 284 285
void Item_func_not_all::print(String *str)
{
  if (show)
    Item_func::print(str);
  else
    args[0]->print(str);
}

286 287

/*
unknown's avatar
unknown committed
288 289 290
  Special NOP (No OPeration) for ALL subquery it is like  Item_func_not_all
  (return TRUE if underlaying sudquery do not return rows) but if subquery
  returns some rows it return same value as argument (TRUE/FALSE).
291 292 293 294 295 296 297 298
*/

longlong Item_func_nop_all::val_int()
{
  DBUG_ASSERT(fixed == 1);
  double value= args[0]->val();

  /*
unknown's avatar
unknown committed
299 300
    return FALSE if there was records in underlaying select in max/min
    optimisation (SAME/ANY subquery)
301 302
  */
  if (empty_underlying_subquery())
unknown's avatar
unknown committed
303
    return 0;
304 305 306 307 308 309

  null_value= args[0]->null_value;
  return (null_value || value == 0) ? 0 : 1;
}


unknown's avatar
unknown committed
310 311 312 313 314
/*
  Convert a constant expression or string to an integer.
  This is done when comparing DATE's of different formats and
  also when comparing bigint to strings (in which case the string
  is converted once to a bigint).
unknown's avatar
unknown committed
315 316 317 318

  RESULT VALUES
  0	Can't convert item
  1	Item was replaced with an integer version of the item
unknown's avatar
unknown committed
319
*/
unknown's avatar
unknown committed
320

321
static bool convert_constant_item(THD *thd, Field *field, Item **item)
unknown's avatar
unknown committed
322
{
323
  if ((*item)->const_item())
unknown's avatar
unknown committed
324
  {
unknown's avatar
unknown committed
325
    if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
unknown's avatar
unknown committed
326
    {
327 328
      Item *tmp=new Item_int_with_ref(field->val_int(), *item);
      if (tmp)
329
        thd->change_item_tree(item, tmp);
330
      return 1;					// Item was replaced
unknown's avatar
unknown committed
331 332 333 334 335
    }
  }
  return 0;
}

unknown's avatar
unknown committed
336

337 338 339
void Item_bool_func2::fix_length_and_dec()
{
  max_length= 1;				     // Function returns 0 or 1
340
  THD *thd= current_thd;
341 342 343 344 345 346 347

  /*
    As some compare functions are generated after sql_yacc,
    we have to check for out of memory conditions here
  */
  if (!args[0] || !args[1])
    return;
348

349 350 351
  DTCollation coll;
  if (args[0]->result_type() == STRING_RESULT &&
      args[1]->result_type() == STRING_RESULT &&
unknown's avatar
unknown committed
352 353
      agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV))
    return;
354
  
unknown's avatar
unknown committed
355
  // Make a special case of compare with fields to get nicer DATE comparisons
unknown's avatar
unknown committed
356 357 358 359 360 361 362

  if (functype() == LIKE_FUNC)  // Disable conversion in case of LIKE function.
  {
    set_cmp_func();
    return;
  }
    
unknown's avatar
unknown committed
363 364 365
  if (args[0]->type() == FIELD_ITEM)
  {
    Field *field=((Item_field*) args[0])->field;
366
    if (field->can_be_compared_as_longlong())
unknown's avatar
unknown committed
367
    {
368
      if (convert_constant_item(thd, field,&args[1]))
unknown's avatar
unknown committed
369
      {
370
	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
unknown's avatar
unknown committed
371
			 INT_RESULT);		// Works for all types.
unknown's avatar
unknown committed
372 373 374 375 376 377 378
	return;
      }
    }
  }
  if (args[1]->type() == FIELD_ITEM)
  {
    Field *field=((Item_field*) args[1])->field;
379
    if (field->can_be_compared_as_longlong())
unknown's avatar
unknown committed
380
    {
381
      if (convert_constant_item(thd, field,&args[0]))
unknown's avatar
unknown committed
382
      {
383 384
	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
			 INT_RESULT); // Works for all types.
unknown's avatar
unknown committed
385 386 387 388
	return;
      }
    }
  }
389
  set_cmp_func();
unknown's avatar
unknown committed
390 391
}

392

393
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
unknown's avatar
unknown committed
394
{
395
  owner= item;
unknown's avatar
unknown committed
396 397
  func= comparator_matrix[type]
                         [test(owner->functype() == Item_func::EQUAL_FUNC)];
unknown's avatar
unknown committed
398
  if (type == ROW_RESULT)
unknown's avatar
unknown committed
399
  {
400 401
    uint n= (*a)->cols();
    if (n != (*b)->cols())
402
    {
unknown's avatar
unknown committed
403
      my_error(ER_OPERAND_COLUMNS, MYF(0), n);
404 405 406
      comparators= 0;
      return 1;
    }
407
    if (!(comparators= new Arg_comparator[n]))
unknown's avatar
unknown committed
408 409 410 411
      return 1;
    for (uint i=0; i < n; i++)
    {
      if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
unknown's avatar
unknown committed
412
      {
unknown's avatar
unknown committed
413
	my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->el(i)->cols());
unknown's avatar
unknown committed
414
	return 1;
unknown's avatar
unknown committed
415
      }
unknown's avatar
unknown committed
416 417
      comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
    }
418
  }
419 420 421 422 423 424
  else if (type == STRING_RESULT)
  {
    /*
      We must set cmp_charset here as we may be called from for an automatic
      generated item, like in natural join
    */
425 426
    if (cmp_collation.set((*a)->collation, (*b)->collation) || 
	cmp_collation.derivation == DERIVATION_NONE)
427 428 429 430
    {
      my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
      return 1;
    }
431
    if (cmp_collation.collation == &my_charset_bin)
unknown's avatar
unknown committed
432 433
    {
      /*
434
	We are using BLOB/BINARY/VARBINARY, change to compare byte by byte,
unknown's avatar
unknown committed
435 436 437 438 439 440 441
	without removing end space
      */
      if (func == &Arg_comparator::compare_string)
	func= &Arg_comparator::compare_binary_string;
      else if (func == &Arg_comparator::compare_e_string)
	func= &Arg_comparator::compare_e_binary_string;
    }
442
  }
443 444
  else if (type == INT_RESULT)
  {
445
    if (func == &Arg_comparator::compare_int_signed)
446 447 448 449 450 451 452
    {
      if ((*a)->unsigned_flag)
        func= ((*b)->unsigned_flag)? &Arg_comparator::compare_int_unsigned : 
                                     &Arg_comparator::compare_int_unsigned_signed;
      else if ((*b)->unsigned_flag)
        func= &Arg_comparator::compare_int_signed_unsigned;
    }
453 454 455 456 457
    else if (func== &Arg_comparator::compare_e_int)
    {
      if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
        func= &Arg_comparator::compare_e_int_diff_signedness;
    }
458
  }
459
  return 0;
unknown's avatar
unknown committed
460
}
unknown's avatar
unknown committed
461

unknown's avatar
unknown committed
462

463
int Arg_comparator::compare_string()
unknown's avatar
unknown committed
464 465
{
  String *res1,*res2;
466
  if ((res1= (*a)->val_str(&owner->tmp_value1)))
unknown's avatar
unknown committed
467
  {
468
    if ((res2= (*b)->val_str(&owner->tmp_value2)))
unknown's avatar
unknown committed
469
    {
unknown's avatar
unknown committed
470
      owner->null_value= 0;
471
      return sortcmp(res1,res2,cmp_collation.collation);
unknown's avatar
unknown committed
472 473
    }
  }
unknown's avatar
unknown committed
474
  owner->null_value= 1;
unknown's avatar
unknown committed
475 476 477
  return -1;
}

unknown's avatar
unknown committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510

/*
  Compare strings byte by byte. End spaces are also compared.

  RETURN
   < 0	*a < *b
   0	*b == *b
   > 0	*a > *b
*/

int Arg_comparator::compare_binary_string()
{
  String *res1,*res2;
  if ((res1= (*a)->val_str(&owner->tmp_value1)))
  {
    if ((res2= (*b)->val_str(&owner->tmp_value2)))
    {
      owner->null_value= 0;
      uint res1_length= res1->length();
      uint res2_length= res2->length();
      int cmp= memcmp(res1->ptr(), res2->ptr(), min(res1_length,res2_length));
      return cmp ? cmp : (int) (res1_length - res2_length);
    }
  }
  owner->null_value= 1;
  return -1;
}


/*
  Compare strings, but take into account that NULL == NULL
*/

unknown's avatar
unknown committed
511 512 513
int Arg_comparator::compare_e_string()
{
  String *res1,*res2;
514 515
  res1= (*a)->val_str(&owner->tmp_value1);
  res2= (*b)->val_str(&owner->tmp_value2);
unknown's avatar
unknown committed
516 517
  if (!res1 || !res2)
    return test(res1 == res2);
518
  return test(sortcmp(res1, res2, cmp_collation.collation) == 0);
unknown's avatar
unknown committed
519 520 521
}


unknown's avatar
unknown committed
522 523 524 525 526 527 528 529 530 531 532
int Arg_comparator::compare_e_binary_string()
{
  String *res1,*res2;
  res1= (*a)->val_str(&owner->tmp_value1);
  res2= (*b)->val_str(&owner->tmp_value2);
  if (!res1 || !res2)
    return test(res1 == res2);
  return test(stringcmp(res1, res2) == 0);
}


533
int Arg_comparator::compare_real()
unknown's avatar
unknown committed
534
{
535 536 537 538 539 540 541
  /*
    Fix yet another manifestation of Bug#2338. 'Volatile' will instruct
    gcc to flush double values out of 80-bit Intel FPU registers before
    performing the comparison.
  */
  volatile double val1, val2;
  val1= (*a)->val();
542
  if (!(*a)->null_value)
unknown's avatar
unknown committed
543
  {
544
    val2= (*b)->val();
545
    if (!(*b)->null_value)
unknown's avatar
unknown committed
546
    {
unknown's avatar
unknown committed
547
      owner->null_value= 0;
unknown's avatar
unknown committed
548 549 550 551 552
      if (val1 < val2)	return -1;
      if (val1 == val2) return 0;
      return 1;
    }
  }
unknown's avatar
unknown committed
553
  owner->null_value= 1;
unknown's avatar
unknown committed
554 555 556
  return -1;
}

unknown's avatar
unknown committed
557 558
int Arg_comparator::compare_e_real()
{
559 560 561 562
  double val1= (*a)->val();
  double val2= (*b)->val();
  if ((*a)->null_value || (*b)->null_value)
    return test((*a)->null_value && (*b)->null_value);
unknown's avatar
unknown committed
563 564
  return test(val1 == val2);
}
unknown's avatar
unknown committed
565

566
int Arg_comparator::compare_int_signed()
unknown's avatar
unknown committed
567
{
568 569
  longlong val1= (*a)->val_int();
  if (!(*a)->null_value)
unknown's avatar
unknown committed
570
  {
571 572
    longlong val2= (*b)->val_int();
    if (!(*b)->null_value)
unknown's avatar
unknown committed
573
    {
unknown's avatar
unknown committed
574
      owner->null_value= 0;
unknown's avatar
unknown committed
575 576 577 578 579
      if (val1 < val2)	return -1;
      if (val1 == val2)   return 0;
      return 1;
    }
  }
unknown's avatar
unknown committed
580
  owner->null_value= 1;
unknown's avatar
unknown committed
581 582 583
  return -1;
}

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 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 659

/*
  Compare values as BIGINT UNSIGNED.
*/

int Arg_comparator::compare_int_unsigned()
{
  ulonglong val1= (*a)->val_int();
  if (!(*a)->null_value)
  {
    ulonglong val2= (*b)->val_int();
    if (!(*b)->null_value)
    {
      owner->null_value= 0;
      if (val1 < val2)	return -1;
      if (val1 == val2)   return 0;
      return 1;
    }
  }
  owner->null_value= 1;
  return -1;
}


/*
  Compare signed (*a) with unsigned (*B)
*/

int Arg_comparator::compare_int_signed_unsigned()
{
  longlong sval1= (*a)->val_int();
  if (!(*a)->null_value)
  {
    ulonglong uval2= (ulonglong)(*b)->val_int();
    if (!(*b)->null_value)
    {
      owner->null_value= 0;
      if (sval1 < 0 || (ulonglong)sval1 < uval2)
        return -1;
      if ((ulonglong)sval1 == uval2)
        return 0;
      return 1;
    }
  }
  owner->null_value= 1;
  return -1;
}


/*
  Compare unsigned (*a) with signed (*B)
*/

int Arg_comparator::compare_int_unsigned_signed()
{
  ulonglong uval1= (ulonglong)(*a)->val_int();
  if (!(*a)->null_value)
  {
    longlong sval2= (*b)->val_int();
    if (!(*b)->null_value)
    {
      owner->null_value= 0;
      if (sval2 < 0)
        return 1;
      if (uval1 < (ulonglong)sval2)
        return -1;
      if (uval1 == (ulonglong)sval2)
        return 0;
      return 1;
    }
  }
  owner->null_value= 1;
  return -1;
}


unknown's avatar
unknown committed
660 661
int Arg_comparator::compare_e_int()
{
662 663 664 665
  longlong val1= (*a)->val_int();
  longlong val2= (*b)->val_int();
  if ((*a)->null_value || (*b)->null_value)
    return test((*a)->null_value && (*b)->null_value);
unknown's avatar
unknown committed
666 667 668
  return test(val1 == val2);
}

669 670 671 672 673 674 675 676 677 678 679
/*
  Compare unsigned *a with signed *b or signed *a with unsigned *b.
*/
int Arg_comparator::compare_e_int_diff_signedness()
{
  longlong val1= (*a)->val_int();
  longlong val2= (*b)->val_int();
  if ((*a)->null_value || (*b)->null_value)
    return test((*a)->null_value && (*b)->null_value);
  return (val1 >= 0) && test(val1 == val2);
}
unknown's avatar
unknown committed
680

681
int Arg_comparator::compare_row()
unknown's avatar
unknown committed
682 683
{
  int res= 0;
684 685
  (*a)->bring_value();
  (*b)->bring_value();
686
  uint n= (*a)->cols();
unknown's avatar
unknown committed
687
  for (uint i= 0; i<n; i++)
unknown's avatar
unknown committed
688
  {
689
    if ((res= comparators[i].compare()))
unknown's avatar
unknown committed
690 691 692 693 694 695
      return res;
    if (owner->null_value)
      return -1;
  }
  return res;
}
unknown's avatar
unknown committed
696

unknown's avatar
unknown committed
697 698
int Arg_comparator::compare_e_row()
{
699 700
  (*a)->bring_value();
  (*b)->bring_value();
701
  uint n= (*a)->cols();
unknown's avatar
unknown committed
702 703
  for (uint i= 0; i<n; i++)
  {
unknown's avatar
unknown committed
704
    if (!comparators[i].compare())
705
      return 0;
unknown's avatar
unknown committed
706 707 708 709
  }
  return 1;
}

710 711 712 713

bool Item_in_optimizer::fix_left(THD *thd,
				 struct st_table_list *tables,
				 Item **ref)
unknown's avatar
unknown committed
714
{
unknown's avatar
unknown committed
715 716
  if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
      !cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
717
    return 1;
718

719
  cache->setup(args[0]);
720 721 722 723
  /*
    If it is preparation PS only then we do not know values of parameters =>
    cant't get there values and do not need that values.
  */
724
  if (! thd->current_arena->is_stmt_prepare())
725
    cache->store(args[0]);
726
  if (cache->cols() == 1)
727
  {
unknown's avatar
unknown committed
728
    if ((used_tables_cache= args[0]->used_tables()))
unknown's avatar
unknown committed
729
      cache->set_used_tables(OUTER_REF_TABLE_BIT);
730 731 732
    else
      cache->set_used_tables(0);
  }
733 734 735 736
  else
  {
    uint n= cache->cols();
    for (uint i= 0; i < n; i++)
737 738
    {
      if (args[0]->el(i)->used_tables())
unknown's avatar
unknown committed
739
	((Item_cache *)cache->el(i))->set_used_tables(OUTER_REF_TABLE_BIT);
740 741 742
      else
	((Item_cache *)cache->el(i))->set_used_tables(0);
    }
unknown's avatar
unknown committed
743
    used_tables_cache= args[0]->used_tables();
744
  }
unknown's avatar
unknown committed
745 746 747
  not_null_tables_cache= args[0]->not_null_tables();
  with_sum_func= args[0]->with_sum_func;
  const_item_cache= args[0]->const_item();
748 749 750 751 752 753 754
  return 0;
}


bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
				   Item ** ref)
{
755
  DBUG_ASSERT(fixed == 0);
756
  if (fix_left(thd, tables, ref))
757 758 759 760
    return 1;
  if (args[0]->maybe_null)
    maybe_null=1;

761
  if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
unknown's avatar
unknown committed
762 763 764 765
    return 1;
  Item_in_subselect * sub= (Item_in_subselect *)args[1];
  if (args[0]->cols() != sub->engine->cols())
  {
unknown's avatar
unknown committed
766
    my_error(ER_OPERAND_COLUMNS, MYF(0), args[0]->cols());
767
    return 1;
unknown's avatar
unknown committed
768
  }
769 770 771 772
  if (args[1]->maybe_null)
    maybe_null=1;
  with_sum_func= with_sum_func || args[1]->with_sum_func;
  used_tables_cache|= args[1]->used_tables();
unknown's avatar
unknown committed
773
  not_null_tables_cache|= args[1]->not_null_tables();
774
  const_item_cache&= args[1]->const_item();
775
  fixed= 1;
776 777 778
  return 0;
}

779

780 781
longlong Item_in_optimizer::val_int()
{
782
  DBUG_ASSERT(fixed == 1);
783 784
  cache->store(args[0]);
  if (cache->null_value)
785
  {
786
    null_value= 1;
787 788
    return 0;
  }
789
  longlong tmp= args[1]->val_int_result();
unknown's avatar
unknown committed
790
  null_value= args[1]->null_value;
791 792 793
  return tmp;
}

794 795 796 797 798 799 800 801

void Item_in_optimizer::keep_top_level_cache()
{
  cache->keep_array();
  save_cache= 1;
}


unknown's avatar
unknown committed
802 803 804 805
void Item_in_optimizer::cleanup()
{
  DBUG_ENTER("Item_in_optimizer::cleanup");
  Item_bool_func::cleanup();
806 807
  if (!save_cache)
    cache= 0;
unknown's avatar
unknown committed
808 809 810
  DBUG_VOID_RETURN;
}

811

812
bool Item_in_optimizer::is_null()
813
{
814 815
  cache->store(args[0]);
  return (null_value= (cache->null_value || args[1]->is_null()));
816
}
unknown's avatar
unknown committed
817

818

unknown's avatar
unknown committed
819 820
longlong Item_func_eq::val_int()
{
821
  DBUG_ASSERT(fixed == 1);
822
  int value= cmp.compare();
unknown's avatar
unknown committed
823 824 825
  return value == 0 ? 1 : 0;
}

826

unknown's avatar
unknown committed
827 828
/* Same as Item_func_eq, but NULL = NULL */

unknown's avatar
unknown committed
829 830 831 832 833 834
void Item_func_equal::fix_length_and_dec()
{
  Item_bool_func2::fix_length_and_dec();
  maybe_null=null_value=0;
}

unknown's avatar
unknown committed
835 836
longlong Item_func_equal::val_int()
{
837
  DBUG_ASSERT(fixed == 1);
838
  return cmp.compare();
unknown's avatar
unknown committed
839 840 841 842
}

longlong Item_func_ne::val_int()
{
843
  DBUG_ASSERT(fixed == 1);
844
  int value= cmp.compare();
845
  return value != 0 && !null_value ? 1 : 0;
unknown's avatar
unknown committed
846 847 848 849 850
}


longlong Item_func_ge::val_int()
{
851
  DBUG_ASSERT(fixed == 1);
852
  int value= cmp.compare();
unknown's avatar
unknown committed
853 854 855 856 857 858
  return value >= 0 ? 1 : 0;
}


longlong Item_func_gt::val_int()
{
859
  DBUG_ASSERT(fixed == 1);
860
  int value= cmp.compare();
unknown's avatar
unknown committed
861 862 863 864 865
  return value > 0 ? 1 : 0;
}

longlong Item_func_le::val_int()
{
866
  DBUG_ASSERT(fixed == 1);
867
  int value= cmp.compare();
unknown's avatar
unknown committed
868 869 870 871 872 873
  return value <= 0 && !null_value ? 1 : 0;
}


longlong Item_func_lt::val_int()
{
874
  DBUG_ASSERT(fixed == 1);
875
  int value= cmp.compare();
unknown's avatar
unknown committed
876 877 878 879 880 881
  return value < 0 && !null_value ? 1 : 0;
}


longlong Item_func_strcmp::val_int()
{
882
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
883 884 885 886 887 888 889
  String *a=args[0]->val_str(&tmp_value1);
  String *b=args[1]->val_str(&tmp_value2);
  if (!a || !b)
  {
    null_value=1;
    return 0;
  }
890
  int value= sortcmp(a,b,cmp.cmp_collation.collation);
unknown's avatar
unknown committed
891 892 893 894 895 896 897
  null_value=0;
  return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}


void Item_func_interval::fix_length_and_dec()
{
898
  if (row->cols() > 8)
unknown's avatar
unknown committed
899
  {
900 901 902
    bool consts=1;

    for (uint i=1 ; consts && i < row->cols() ; i++)
unknown's avatar
unknown committed
903
    {
904
      consts&= row->el(i)->const_item();
unknown's avatar
unknown committed
905
    }
906 907 908

    if (consts &&
        (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
unknown's avatar
unknown committed
909
    {
910 911
      for (uint i=1 ; i < row->cols(); i++)
        intervals[i-1]=row->el(i)->val();
unknown's avatar
unknown committed
912 913
    }
  }
unknown's avatar
unknown committed
914 915
  maybe_null= 0;
  max_length= 2;
916
  used_tables_cache|= row->used_tables();
unknown's avatar
unknown committed
917
  not_null_tables_cache= row->not_null_tables();
918
  with_sum_func= with_sum_func || row->with_sum_func;
unknown's avatar
unknown committed
919
  const_item_cache&= row->const_item();
unknown's avatar
unknown committed
920 921
}

unknown's avatar
unknown committed
922

unknown's avatar
unknown committed
923 924 925
/*
  return -1 if null value,
	  0 if lower than lowest
926 927
	  1 - arg_count-1 if between args[n] and args[n+1]
	  arg_count if higher than biggest argument
unknown's avatar
unknown committed
928 929 930 931
*/

longlong Item_func_interval::val_int()
{
932
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
933 934 935
  double value= row->el(0)->val();
  uint i;

936 937
  if (row->el(0)->null_value)
    return -1;				// -1 if null
unknown's avatar
unknown committed
938 939 940
  if (intervals)
  {					// Use binary search to find interval
    uint start,end;
941
    start= 0;
unknown's avatar
unknown committed
942
    end=   row->cols()-2;
unknown's avatar
unknown committed
943 944
    while (start != end)
    {
unknown's avatar
unknown committed
945
      uint mid= (start + end + 1) / 2;
unknown's avatar
unknown committed
946
      if (intervals[mid] <= value)
unknown's avatar
unknown committed
947
	start= mid;
unknown's avatar
unknown committed
948
      else
unknown's avatar
unknown committed
949
	end= mid - 1;
unknown's avatar
unknown committed
950
    }
unknown's avatar
unknown committed
951
    return (value < intervals[start]) ? 0 : start + 1;
unknown's avatar
unknown committed
952
  }
953 954

  for (i=1 ; i < row->cols() ; i++)
unknown's avatar
unknown committed
955
  {
956 957
    if (row->el(i)->val() > value)
      return i-1;
unknown's avatar
unknown committed
958
  }
959
  return i-1;
unknown's avatar
unknown committed
960 961
}

unknown's avatar
unknown committed
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991

/*
  Perform context analysis of a BETWEEN item tree

  SYNOPSIS:
    fix_fields()
    thd     reference to the global context of the query thread
    tables  list of all open tables involved in the query
    ref     pointer to Item* variable where pointer to resulting "fixed"
            item is to be assigned

  DESCRIPTION
    This function performs context analysis (name resolution) and calculates
    various attributes of the item tree with Item_func_between as its root.
    The function saves in ref the pointer to the item or to a newly created
    item that is considered as a replacement for the original one.

  NOTES
    Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
    a predicate/function level. Then it's easy to show that:
      T0(e BETWEEN e1 AND e2)     = union(T1(e),T1(e1),T1(e2))
      T1(e BETWEEN e1 AND e2)     = union(T1(e),intersection(T1(e1),T1(e2)))
      T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))
      T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2)))

  RETURN
    0   ok
    1   got error
*/

unknown's avatar
unknown committed
992 993
bool Item_func_between::fix_fields(THD *thd, struct st_table_list *tables,
                                   Item **ref)
unknown's avatar
unknown committed
994 995 996 997 998 999 1000 1001 1002
{
  if (Item_func_opt_neg::fix_fields(thd, tables, ref))
    return 1;

  /* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
  if (pred_level && !negated)
    return 0;

  /* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
unknown's avatar
unknown committed
1003 1004 1005
  not_null_tables_cache= (args[0]->not_null_tables() |
                          (args[1]->not_null_tables() &
                           args[2]->not_null_tables()));
unknown's avatar
unknown committed
1006 1007 1008 1009 1010

  return 0;
}


unknown's avatar
unknown committed
1011 1012
void Item_func_between::fix_length_and_dec()
{
unknown's avatar
unknown committed
1013
   max_length= 1;
1014
   THD *thd= current_thd;
unknown's avatar
unknown committed
1015

1016 1017 1018 1019
  /*
    As some compare functions are generated after sql_yacc,
    we have to check for out of memory conditons here
  */
unknown's avatar
unknown committed
1020 1021
  if (!args[0] || !args[1] || !args[2])
    return;
1022 1023 1024
  agg_cmp_type(thd, &cmp_type, args, 3);
  if (cmp_type == STRING_RESULT)
      agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV);
unknown's avatar
unknown committed
1025 1026 1027 1028 1029
}


longlong Item_func_between::val_int()
{						// ANSI BETWEEN
1030
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1031 1032 1033 1034 1035 1036 1037 1038 1039
  if (cmp_type == STRING_RESULT)
  {
    String *value,*a,*b;
    value=args[0]->val_str(&value0);
    if ((null_value=args[0]->null_value))
      return 0;
    a=args[1]->val_str(&value1);
    b=args[2]->val_str(&value2);
    if (!args[1]->null_value && !args[2]->null_value)
unknown's avatar
unknown committed
1040 1041 1042
      return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
                          sortcmp(value,b,cmp_collation.collation) <= 0) !=
                         negated);
unknown's avatar
unknown committed
1043 1044 1045 1046
    if (args[1]->null_value && args[2]->null_value)
      null_value=1;
    else if (args[1]->null_value)
    {
unknown's avatar
unknown committed
1047 1048
      // Set to not null if false range.
      null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
unknown's avatar
unknown committed
1049 1050 1051
    }
    else
    {
unknown's avatar
unknown committed
1052 1053
      // Set to not null if false range.
      null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
unknown's avatar
unknown committed
1054 1055 1056 1057 1058 1059
    }
  }
  else if (cmp_type == INT_RESULT)
  {
    longlong value=args[0]->val_int(),a,b;
    if ((null_value=args[0]->null_value))
1060
      return 0;					/* purecov: inspected */
unknown's avatar
unknown committed
1061 1062 1063
    a=args[1]->val_int();
    b=args[2]->val_int();
    if (!args[1]->null_value && !args[2]->null_value)
unknown's avatar
unknown committed
1064
      return (longlong) ((value >= a && value <= b) != negated);
unknown's avatar
unknown committed
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
    if (args[1]->null_value && args[2]->null_value)
      null_value=1;
    else if (args[1]->null_value)
    {
      null_value= value <= b;			// not null if false range.
    }
    else
    {
      null_value= value >= a;
    }
  }
  else
  {
    double value=args[0]->val(),a,b;
    if ((null_value=args[0]->null_value))
1080
      return 0;					/* purecov: inspected */
unknown's avatar
unknown committed
1081 1082 1083
    a=args[1]->val();
    b=args[2]->val();
    if (!args[1]->null_value && !args[2]->null_value)
unknown's avatar
unknown committed
1084
      return (longlong) ((value >= a && value <= b) != negated);
unknown's avatar
unknown committed
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
    if (args[1]->null_value && args[2]->null_value)
      null_value=1;
    else if (args[1]->null_value)
    {
      null_value= value <= b;			// not null if false range.
    }
    else
    {
      null_value= value >= a;
    }
  }
unknown's avatar
unknown committed
1096
  return (longlong) (!null_value && negated);
unknown's avatar
unknown committed
1097 1098
}

1099 1100 1101 1102 1103

void Item_func_between::print(String *str)
{
  str->append('(');
  args[0]->print(str);
unknown's avatar
unknown committed
1104 1105
  if (negated)
    str->append(" not", 4);
1106
  str->append(" between ", 9);
1107
  args[1]->print(str);
1108
  str->append(" and ", 5);
1109 1110 1111 1112
  args[2]->print(str);
  str->append(')');
}

unknown's avatar
unknown committed
1113 1114 1115 1116 1117 1118
void
Item_func_ifnull::fix_length_and_dec()
{
  maybe_null=args[1]->maybe_null;
  max_length=max(args[0]->max_length,args[1]->max_length);
  decimals=max(args[0]->decimals,args[1]->decimals);
1119
  agg_result_type(&cached_result_type, args, 2);
unknown's avatar
unknown committed
1120
  if (cached_result_type == STRING_RESULT)
unknown's avatar
unknown committed
1121
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
1122 1123
  else if (cached_result_type != REAL_RESULT)
    decimals= 0;
1124 1125 1126 1127
  
  cached_field_type= args[0]->field_type();
  if (cached_field_type != args[1]->field_type())
    cached_field_type= Item_func::field_type();
unknown's avatar
unknown committed
1128 1129
}

1130 1131 1132
enum_field_types Item_func_ifnull::field_type() const 
{
  return cached_field_type;
unknown's avatar
unknown committed
1133 1134
}

1135 1136 1137 1138
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
{
  return tmp_table_field_from_field_type(table);
}
1139

unknown's avatar
unknown committed
1140 1141 1142
double
Item_func_ifnull::val()
{
1143
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
  double value=args[0]->val();
  if (!args[0]->null_value)
  {
    null_value=0;
    return value;
  }
  value=args[1]->val();
  if ((null_value=args[1]->null_value))
    return 0.0;
  return value;
}

longlong
Item_func_ifnull::val_int()
{
1159
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
  longlong value=args[0]->val_int();
  if (!args[0]->null_value)
  {
    null_value=0;
    return value;
  }
  value=args[1]->val_int();
  if ((null_value=args[1]->null_value))
    return 0;
  return value;
}

String *
Item_func_ifnull::val_str(String *str)
{
1175
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1176 1177 1178 1179
  String *res  =args[0]->val_str(str);
  if (!args[0]->null_value)
  {
    null_value=0;
1180
    res->set_charset(collation.collation);
unknown's avatar
unknown committed
1181 1182 1183 1184 1185
    return res;
  }
  res=args[1]->val_str(str);
  if ((null_value=args[1]->null_value))
    return 0;
1186
  res->set_charset(collation.collation);
unknown's avatar
unknown committed
1187 1188 1189
  return res;
}

1190

unknown's avatar
unknown committed
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
/*
  Perform context analysis of an IF item tree

  SYNOPSIS:
    fix_fields()
    thd     reference to the global context of the query thread
    tables  list of all open tables involved in the query
    ref     pointer to Item* variable where pointer to resulting "fixed"
            item is to be assigned

  DESCRIPTION
    This function performs context analysis (name resolution) and calculates
    various attributes of the item tree with Item_func_if as its root.
    The function saves in ref the pointer to the item or to a newly created
    item that is considered as a replacement for the original one.

  NOTES
    Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
    a predicate/function level. Then it's easy to show that:
      T0(IF(e,e1,e2)  = T1(IF(e,e1,e2))
      T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2))

  RETURN
    0   ok
    1   got error
*/

bool
Item_func_if::fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
  DBUG_ASSERT(fixed == 0);
  args[0]->top_level_item();

  if (Item_func::fix_fields(thd, tlist, ref))
    return 1;

unknown's avatar
unknown committed
1227 1228
  not_null_tables_cache= (args[1]->not_null_tables() &
                          args[2]->not_null_tables());
unknown's avatar
unknown committed
1229 1230 1231 1232 1233

  return 0;
}


unknown's avatar
unknown committed
1234 1235 1236 1237 1238
void
Item_func_if::fix_length_and_dec()
{
  maybe_null=args[1]->maybe_null || args[2]->maybe_null;
  max_length=max(args[1]->max_length,args[2]->max_length);
1239
  decimals=max(args[1]->decimals,args[2]->decimals);
unknown's avatar
unknown committed
1240 1241
  enum Item_result arg1_type=args[1]->result_type();
  enum Item_result arg2_type=args[2]->result_type();
unknown's avatar
unknown committed
1242 1243
  bool null1=args[1]->const_item() && args[1]->null_value;
  bool null2=args[2]->const_item() && args[2]->null_value;
1244 1245 1246 1247

  if (null1)
  {
    cached_result_type= arg2_type;
1248
    collation.set(args[2]->collation.collation);
1249 1250 1251
  }
  else if (null2)
  {
unknown's avatar
unknown committed
1252
    cached_result_type= arg1_type;
1253
    collation.set(args[1]->collation.collation);
1254
  }
unknown's avatar
unknown committed
1255
  else
1256
  {
1257 1258 1259
    agg_result_type(&cached_result_type, args+1, 2);
    if (cached_result_type == STRING_RESULT)
    {
unknown's avatar
unknown committed
1260
      if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV))
1261 1262
      return;
    }
1263
    else
1264
    {
1265
      collation.set(&my_charset_bin);	// Number
1266
    }
1267
  }
unknown's avatar
unknown committed
1268 1269 1270 1271 1272 1273
}


double
Item_func_if::val()
{
1274
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1275 1276 1277 1278 1279 1280 1281 1282 1283
  Item *arg= args[0]->val_int() ? args[1] : args[2];
  double value=arg->val();
  null_value=arg->null_value;
  return value;
}

longlong
Item_func_if::val_int()
{
1284
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1285 1286 1287 1288 1289 1290 1291 1292 1293
  Item *arg= args[0]->val_int() ? args[1] : args[2];
  longlong value=arg->val_int();
  null_value=arg->null_value;
  return value;
}

String *
Item_func_if::val_str(String *str)
{
1294
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1295 1296
  Item *arg= args[0]->val_int() ? args[1] : args[2];
  String *res=arg->val_str(str);
1297
  if (res)
1298
    res->set_charset(collation.collation);
unknown's avatar
unknown committed
1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
  null_value=arg->null_value;
  return res;
}


void
Item_func_nullif::fix_length_and_dec()
{
  Item_bool_func2::fix_length_and_dec();
  maybe_null=1;
  if (args[0])					// Only false if EOM
  {
    max_length=args[0]->max_length;
    decimals=args[0]->decimals;
1313
    agg_result_type(&cached_result_type, args, 2);
1314 1315 1316
    if (cached_result_type == STRING_RESULT &&
        agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV))
      return;
unknown's avatar
unknown committed
1317 1318 1319 1320
  }
}

/*
1321
  nullif () returns NULL if arguments are equal, else it returns the
unknown's avatar
unknown committed
1322 1323 1324 1325 1326 1327 1328 1329
  first argument.
  Note that we have to evaluate the first argument twice as the compare
  may have been done with a different type than return value
*/

double
Item_func_nullif::val()
{
1330
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1331
  double value;
unknown's avatar
unknown committed
1332
  if (!cmp.compare())
unknown's avatar
unknown committed
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344
  {
    null_value=1;
    return 0.0;
  }
  value=args[0]->val();
  null_value=args[0]->null_value;
  return value;
}

longlong
Item_func_nullif::val_int()
{
1345
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1346
  longlong value;
unknown's avatar
unknown committed
1347
  if (!cmp.compare())
unknown's avatar
unknown committed
1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359
  {
    null_value=1;
    return 0;
  }
  value=args[0]->val_int();
  null_value=args[0]->null_value;
  return value;
}

String *
Item_func_nullif::val_str(String *str)
{
1360
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1361
  String *res;
unknown's avatar
unknown committed
1362
  if (!cmp.compare())
unknown's avatar
unknown committed
1363 1364 1365 1366 1367 1368 1369 1370 1371
  {
    null_value=1;
    return 0;
  }
  res=args[0]->val_str(str);
  null_value=args[0]->null_value;
  return res;
}

1372 1373 1374 1375

bool
Item_func_nullif::is_null()
{
unknown's avatar
unknown committed
1376
  return (null_value= (!cmp.compare() ? 1 : args[0]->null_value)); 
1377 1378
}

unknown's avatar
unknown committed
1379
/*
1380 1381
  CASE expression 
  Return the matching ITEM or NULL if all compares (including else) failed
unknown's avatar
unknown committed
1382 1383 1384 1385 1386 1387 1388
*/

Item *Item_func_case::find_item(String *str)
{
  String *first_expr_str,*tmp;
  longlong first_expr_int;
  double   first_expr_real;
1389 1390
  char buff[MAX_FIELD_WIDTH];
  String buff_str(buff,sizeof(buff),default_charset());
unknown's avatar
unknown committed
1391
  
unknown's avatar
unknown committed
1392 1393 1394 1395 1396
  /* These will be initialized later */
  LINT_INIT(first_expr_str);
  LINT_INIT(first_expr_int);
  LINT_INIT(first_expr_real);

unknown's avatar
unknown committed
1397 1398 1399 1400 1401 1402
  if (first_expr_num != -1)
  {
    switch (cmp_type)
    {
      case STRING_RESULT:
      	// We can't use 'str' here as this may be overwritten
1403
	if (!(first_expr_str= args[first_expr_num]->val_str(&buff_str)))
unknown's avatar
unknown committed
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423
	  return else_expr_num != -1 ? args[else_expr_num] : 0;	// Impossible
        break;
      case INT_RESULT:
	first_expr_int= args[first_expr_num]->val_int();
	if (args[first_expr_num]->null_value)
	  return else_expr_num != -1 ? args[else_expr_num] : 0;
	break;
      case REAL_RESULT:
	first_expr_real= args[first_expr_num]->val();
	if (args[first_expr_num]->null_value)
	  return else_expr_num != -1 ? args[else_expr_num] : 0;
	break;
      case ROW_RESULT:
      default:
	// This case should never be choosen
	DBUG_ASSERT(0);
	break;
    }
  }

unknown's avatar
unknown committed
1424
  // Compare every WHEN argument with it and return the first match
1425
  for (uint i=0 ; i < ncases ; i+=2)
unknown's avatar
unknown committed
1426
  {
1427
    if (first_expr_num == -1)
unknown's avatar
unknown committed
1428
    {
unknown's avatar
unknown committed
1429
      // No expression between CASE and the first WHEN
unknown's avatar
unknown committed
1430 1431 1432 1433
      if (args[i]->val_int())
	return args[i+1];
      continue;
    }
unknown's avatar
unknown committed
1434
    switch (cmp_type) {
unknown's avatar
unknown committed
1435 1436
    case STRING_RESULT:
      if ((tmp=args[i]->val_str(str)))		// If not null
unknown's avatar
unknown committed
1437
	if (sortcmp(tmp,first_expr_str,cmp_collation.collation)==0)
unknown's avatar
unknown committed
1438 1439 1440 1441 1442 1443 1444 1445 1446
	  return args[i+1];
      break;
    case INT_RESULT:
      if (args[i]->val_int()==first_expr_int && !args[i]->null_value) 
        return args[i+1];
      break;
    case REAL_RESULT: 
      if (args[i]->val()==first_expr_real && !args[i]->null_value) 
        return args[i+1];
unknown's avatar
unknown committed
1447
      break;
1448
    case ROW_RESULT:
unknown's avatar
unknown committed
1449
    default:
unknown's avatar
unknown committed
1450 1451 1452
      // This case should never be choosen
      DBUG_ASSERT(0);
      break;
unknown's avatar
unknown committed
1453 1454 1455
    }
  }
  // No, WHEN clauses all missed, return ELSE expression
1456
  return else_expr_num != -1 ? args[else_expr_num] : 0;
unknown's avatar
unknown committed
1457 1458 1459 1460 1461 1462
}



String *Item_func_case::val_str(String *str)
{
1463
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1464 1465 1466 1467 1468 1469 1470 1471
  String *res;
  Item *item=find_item(str);

  if (!item)
  {
    null_value=1;
    return 0;
  }
unknown's avatar
unknown committed
1472
  null_value= 0;
unknown's avatar
unknown committed
1473
  if (!(res=item->val_str(str)))
unknown's avatar
unknown committed
1474
    null_value= 1;
unknown's avatar
unknown committed
1475 1476 1477 1478 1479 1480
  return res;
}


longlong Item_func_case::val_int()
{
1481
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1482
  char buff[MAX_FIELD_WIDTH];
1483
  String dummy_str(buff,sizeof(buff),default_charset());
unknown's avatar
unknown committed
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
  Item *item=find_item(&dummy_str);
  longlong res;

  if (!item)
  {
    null_value=1;
    return 0;
  }
  res=item->val_int();
  null_value=item->null_value;
  return res;
}

double Item_func_case::val()
{
1499
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1500
  char buff[MAX_FIELD_WIDTH];
1501
  String dummy_str(buff,sizeof(buff),default_charset());
unknown's avatar
unknown committed
1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
  Item *item=find_item(&dummy_str);
  double res;

  if (!item)
  {
    null_value=1;
    return 0;
  }
  res=item->val();
  null_value=item->null_value;
  return res;
}

void Item_func_case::fix_length_and_dec()
1516
{
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533
  Item **agg;
  uint nagg;
  
  if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
    return;
  
  // Aggregate all THEN and ELSE expression types
  // and collations when string result
  
  for (nagg= 0 ; nagg < ncases/2 ; nagg++)
    agg[nagg]= args[nagg*2+1];
  
  if (else_expr_num != -1)
    agg[nagg++]= args[else_expr_num];
  
  agg_result_type(&cached_result_type, agg, nagg);
  if ((cached_result_type == STRING_RESULT) &&
unknown's avatar
unknown committed
1534
      agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV))
1535 1536 1537
    return;
  
  
unknown's avatar
unknown committed
1538 1539 1540 1541
  /*
    Aggregate first expression and all THEN expression types
    and collations when string comparison
  */
1542
  if (first_expr_num != -1)
1543
  {
1544 1545
    agg[0]= args[first_expr_num];
    for (nagg= 0; nagg < ncases/2 ; nagg++)
unknown's avatar
unknown committed
1546
      agg[nagg+1]= args[nagg*2];
1547
    nagg++;
1548
    agg_cmp_type(current_thd, &cmp_type, agg, nagg);
1549
    if ((cmp_type == STRING_RESULT) &&
unknown's avatar
unknown committed
1550
        agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
1551
    return;
1552
  }
1553
  
unknown's avatar
unknown committed
1554
  if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
1555
    maybe_null=1;
1556
  
unknown's avatar
unknown committed
1557 1558
  max_length=0;
  decimals=0;
1559
  for (uint i=0 ; i < ncases ; i+=2)
unknown's avatar
unknown committed
1560 1561 1562 1563
  {
    set_if_bigger(max_length,args[i+1]->max_length);
    set_if_bigger(decimals,args[i+1]->decimals);
  }
1564
  if (else_expr_num != -1) 
unknown's avatar
unknown committed
1565
  {
1566 1567
    set_if_bigger(max_length,args[else_expr_num]->max_length);
    set_if_bigger(decimals,args[else_expr_num]->decimals);
unknown's avatar
unknown committed
1568 1569 1570
  }
}

unknown's avatar
unknown committed
1571

1572
/* TODO:  Fix this so that it prints the whole CASE expression */
unknown's avatar
unknown committed
1573 1574 1575

void Item_func_case::print(String *str)
{
1576
  str->append("(case ", 6);
1577 1578 1579 1580 1581 1582 1583
  if (first_expr_num != -1)
  {
    args[first_expr_num]->print(str);
    str->append(' ');
  }
  for (uint i=0 ; i < ncases ; i+=2)
  {
1584
    str->append("when ", 5);
1585
    args[i]->print(str);
1586
    str->append(" then ", 6);
1587 1588 1589 1590 1591
    args[i+1]->print(str);
    str->append(' ');
  }
  if (else_expr_num != -1)
  {
1592
    str->append("else ", 5);
1593 1594 1595
    args[else_expr_num]->print(str);
    str->append(' ');
  }
1596
  str->append("end)", 4);
unknown's avatar
unknown committed
1597 1598 1599
}

/*
1600
  Coalesce - return first not NULL argument.
unknown's avatar
unknown committed
1601 1602 1603 1604
*/

String *Item_func_coalesce::val_str(String *str)
{
1605
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1606 1607 1608
  null_value=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
unknown's avatar
unknown committed
1609 1610 1611
    String *res;
    if ((res=args[i]->val_str(str)))
      return res;
unknown's avatar
unknown committed
1612 1613 1614 1615 1616 1617 1618
  }
  null_value=1;
  return 0;
}

longlong Item_func_coalesce::val_int()
{
1619
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632
  null_value=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
    longlong res=args[i]->val_int();
    if (!args[i]->null_value)
      return res;
  }
  null_value=1;
  return 0;
}

double Item_func_coalesce::val()
{
1633
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
  null_value=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
    double res=args[i]->val();
    if (!args[i]->null_value)
      return res;
  }
  null_value=1;
  return 0;
}


void Item_func_coalesce::fix_length_and_dec()
{
unknown's avatar
unknown committed
1648 1649
  max_length= 0;
  decimals= 0;
1650
  agg_result_type(&cached_result_type, args, arg_count);
unknown's avatar
unknown committed
1651 1652 1653 1654 1655
  for (uint i=0 ; i < arg_count ; i++)
  {
    set_if_bigger(max_length,args[i]->max_length);
    set_if_bigger(decimals,args[i]->decimals);
  }
1656
  if (cached_result_type == STRING_RESULT)
unknown's avatar
unknown committed
1657
    agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV);
1658 1659
  else if (cached_result_type != REAL_RESULT)
    decimals= 0;
unknown's avatar
unknown committed
1660 1661 1662
}

/****************************************************************************
1663
 Classes and function for the IN operator
unknown's avatar
unknown committed
1664 1665
****************************************************************************/

1666
static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
unknown's avatar
unknown committed
1667 1668 1669 1670
{
  return *a < *b ? -1 : *a == *b ? 0 : 1;
}

1671
static int cmp_double(void *cmp_arg, double *a,double *b)
unknown's avatar
unknown committed
1672 1673 1674 1675
{
  return *a < *b ? -1 : *a == *b ? 0 : 1;
}

1676
static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
unknown's avatar
unknown committed
1677 1678 1679 1680
{
  return a->compare(b);
}

unknown's avatar
unknown committed
1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692
int in_vector::find(Item *item)
{
  byte *result=get_value(item);
  if (!result || !used_count)
    return 0;				// Null value

  uint start,end;
  start=0; end=used_count-1;
  while (start != end)
  {
    uint mid=(start+end+1)/2;
    int res;
1693
    if ((res=(*compare)(collation, base+mid*size, result)) == 0)
unknown's avatar
unknown committed
1694 1695 1696 1697 1698 1699
      return 1;
    if (res < 0)
      start=mid;
    else
      end=mid-1;
  }
1700
  return (int) ((*compare)(collation, base+start*size, result) == 0);
unknown's avatar
unknown committed
1701 1702
}

1703 1704
in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
  :in_vector(elements, sizeof(String), cmp_func, cs),
1705
   tmp(buff, sizeof(buff), &my_charset_bin)
unknown's avatar
unknown committed
1706 1707 1708 1709
{}

in_string::~in_string()
{
1710
  if (base)
1711
  {
unknown's avatar
unknown committed
1712
    // base was allocated with help of sql_alloc => following is OK
1713 1714
    for (uint i=0 ; i < count ; i++)
      ((String*) base)[i].free();
1715
  }
unknown's avatar
unknown committed
1716 1717 1718 1719 1720 1721 1722
}

void in_string::set(uint pos,Item *item)
{
  String *str=((String*) base)+pos;
  String *res=item->val_str(str);
  if (res && res != str)
1723 1724 1725
  {
    if (res->uses_buffer_owned_by(str))
      res->copy();
unknown's avatar
unknown committed
1726
    *str= *res;
1727
  }
1728
  if (!str->charset())
1729 1730
  {
    CHARSET_INFO *cs;
1731
    if (!(cs= item->collation.collation))
1732
      cs= &my_charset_bin;		// Should never happen for STR items
1733 1734
    str->set_charset(cs);
  }
unknown's avatar
unknown committed
1735 1736
}

1737

unknown's avatar
unknown committed
1738 1739 1740 1741 1742
byte *in_string::get_value(Item *item)
{
  return (byte*) item->val_str(&tmp);
}

unknown's avatar
unknown committed
1743 1744
in_row::in_row(uint elements, Item * item)
{
1745
  base= (char*) new cmp_item_row[count= elements];
unknown's avatar
unknown committed
1746
  size= sizeof(cmp_item_row);
1747
  compare= (qsort2_cmp) cmp_row;
unknown's avatar
unknown committed
1748
  tmp.store_value(item);
1749 1750 1751 1752 1753 1754
  /*
    We need to reset these as otherwise we will call sort() with
    uninitialized (even if not used) elements
  */
  used_count= elements;
  collation= 0;
1755 1756 1757 1758 1759
}

in_row::~in_row()
{
  if (base)
1760
    delete [] (cmp_item_row*) base;
unknown's avatar
unknown committed
1761 1762 1763 1764 1765
}

byte *in_row::get_value(Item *item)
{
  tmp.store_value(item);
unknown's avatar
unknown committed
1766 1767
  if (item->is_null())
    return 0;
unknown's avatar
unknown committed
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
  return (byte *)&tmp;
}

void in_row::set(uint pos, Item *item)
{
  DBUG_ENTER("in_row::set");
  DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item));
  ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item);
  DBUG_VOID_RETURN;
}
unknown's avatar
unknown committed
1778 1779

in_longlong::in_longlong(uint elements)
1780
  :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
unknown's avatar
unknown committed
1781 1782 1783 1784 1785 1786 1787 1788 1789
{}

void in_longlong::set(uint pos,Item *item)
{
  ((longlong*) base)[pos]=item->val_int();
}

byte *in_longlong::get_value(Item *item)
{
unknown's avatar
unknown committed
1790
  tmp= item->val_int();
unknown's avatar
unknown committed
1791
  if (item->null_value)
unknown's avatar
unknown committed
1792
    return 0;
unknown's avatar
unknown committed
1793 1794 1795 1796
  return (byte*) &tmp;
}

in_double::in_double(uint elements)
1797
  :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
unknown's avatar
unknown committed
1798 1799 1800 1801 1802 1803 1804 1805 1806
{}

void in_double::set(uint pos,Item *item)
{
  ((double*) base)[pos]=item->val();
}

byte *in_double::get_value(Item *item)
{
unknown's avatar
unknown committed
1807
  tmp= item->val();
unknown's avatar
unknown committed
1808
  if (item->null_value)
1809
    return 0;					/* purecov: inspected */
unknown's avatar
unknown committed
1810 1811 1812
  return (byte*) &tmp;
}

1813
cmp_item* cmp_item::get_comparator(Item *item)
1814 1815 1816
{
  switch (item->result_type()) {
  case STRING_RESULT:
1817
    return new cmp_item_sort_string(item->collation.collation);
1818 1819 1820 1821 1822 1823
  case INT_RESULT:
    return new cmp_item_int;
  case REAL_RESULT:
    return new cmp_item_real;
  case ROW_RESULT:
    return new cmp_item_row;
unknown's avatar
unknown committed
1824 1825 1826
  default:
    DBUG_ASSERT(0);
    break;
1827 1828 1829 1830
  }
  return 0; // to satisfy compiler :)
}

1831

unknown's avatar
unknown committed
1832 1833
cmp_item* cmp_item_sort_string::make_same()
{
1834
  return new cmp_item_sort_string_in_static(cmp_charset);
unknown's avatar
unknown committed
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
}

cmp_item* cmp_item_int::make_same()
{
  return new cmp_item_int();
}

cmp_item* cmp_item_real::make_same()
{
  return new cmp_item_real();
}

cmp_item* cmp_item_row::make_same()
{
  return new cmp_item_row();
}

1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868

cmp_item_row::~cmp_item_row()
{
  DBUG_ENTER("~cmp_item_row");
  DBUG_PRINT("enter",("this: %lx", this));
  if (comparators)
  {
    for (uint i= 0; i < n; i++)
    {
      if (comparators[i])
	delete comparators[i];
    }
  }
  DBUG_VOID_RETURN;
}


1869 1870
void cmp_item_row::store_value(Item *item)
{
1871
  DBUG_ENTER("cmp_item_row::store_value");
1872
  n= item->cols();
1873
  if (!comparators)
unknown's avatar
unknown committed
1874
    comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
1875
  if (comparators)
1876
  {
1877
    item->bring_value();
unknown's avatar
unknown committed
1878
    item->null_value= 0;
1879
    for (uint i=0; i < n; i++)
1880
    {
unknown's avatar
unknown committed
1881 1882 1883
      if (!comparators[i])
	if (!(comparators[i]= cmp_item::get_comparator(item->el(i))))
	  break;					// new failed
1884 1885 1886
      comparators[i]->store_value(item->el(i));
      item->null_value|= item->el(i)->null_value;
    }
1887
  }
1888
  DBUG_VOID_RETURN;
1889 1890
}

1891

unknown's avatar
unknown committed
1892 1893 1894 1895 1896
void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
{
  cmp_item_row *tmpl= (cmp_item_row*) t;
  if (tmpl->n != item->cols())
  {
unknown's avatar
unknown committed
1897
    my_error(ER_OPERAND_COLUMNS, MYF(0), tmpl->n);
unknown's avatar
unknown committed
1898 1899 1900 1901 1902
    return;
  }
  n= tmpl->n;
  if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
  {
1903
    item->bring_value();
unknown's avatar
unknown committed
1904 1905
    item->null_value= 0;
    for (uint i=0; i < n; i++)
1906 1907 1908 1909 1910 1911 1912
    {
      if (!(comparators[i]= tmpl->comparators[i]->make_same()))
	break;					// new failed
      comparators[i]->store_value_by_template(tmpl->comparators[i],
					      item->el(i));
      item->null_value|= item->el(i)->null_value;
    }
unknown's avatar
unknown committed
1913 1914 1915
  }
}

1916

1917 1918
int cmp_item_row::cmp(Item *arg)
{
unknown's avatar
unknown committed
1919 1920 1921
  arg->null_value= 0;
  if (arg->cols() != n)
  {
unknown's avatar
unknown committed
1922
    my_error(ER_OPERAND_COLUMNS, MYF(0), n);
unknown's avatar
unknown committed
1923 1924
    return 1;
  }
unknown's avatar
unknown committed
1925
  bool was_null= 0;
1926
  arg->bring_value();
unknown's avatar
unknown committed
1927
  for (uint i=0; i < n; i++)
1928
  {
unknown's avatar
unknown committed
1929
    if (comparators[i]->cmp(arg->el(i)))
unknown's avatar
unknown committed
1930
    {
unknown's avatar
unknown committed
1931 1932 1933
      if (!arg->el(i)->null_value)
	return 1;
      was_null= 1;
unknown's avatar
unknown committed
1934
    }
1935
  }
unknown's avatar
unknown committed
1936
  return (arg->null_value= was_null);
unknown's avatar
unknown committed
1937 1938
}

1939

unknown's avatar
unknown committed
1940 1941 1942
int cmp_item_row::compare(cmp_item *c)
{
  cmp_item_row *cmp= (cmp_item_row *) c;
unknown's avatar
unknown committed
1943
  for (uint i=0; i < n; i++)
1944 1945
  {
    int res;
unknown's avatar
unknown committed
1946
    if ((res= comparators[i]->compare(cmp->comparators[i])))
unknown's avatar
unknown committed
1947
      return res;
1948
  }
1949 1950
  return 0;
}
unknown's avatar
unknown committed
1951

1952

unknown's avatar
unknown committed
1953 1954 1955
bool Item_func_in::nulls_in_row()
{
  Item **arg,**arg_end;
1956
  for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++)
unknown's avatar
unknown committed
1957 1958 1959 1960 1961 1962 1963
  {
    if ((*arg)->null_inside())
      return 1;
  }
  return 0;
}

1964

unknown's avatar
unknown committed
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
/*
  Perform context analysis of an IN item tree

  SYNOPSIS:
    fix_fields()
    thd     reference to the global context of the query thread
    tables  list of all open tables involved in the query
    ref     pointer to Item* variable where pointer to resulting "fixed"
            item is to be assigned

  DESCRIPTION
    This function performs context analysis (name resolution) and calculates
    various attributes of the item tree with Item_func_in as its root.
    The function saves in ref the pointer to the item or to a newly created
    item that is considered as a replacement for the original one.

  NOTES
    Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on
    a predicate/function level. Then it's easy to show that:
      T0(e IN(e1,...,en))     = union(T1(e),intersection(T1(ei)))
      T1(e IN(e1,...,en))     = union(T1(e),intersection(T1(ei)))
      T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei)))
      T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei)))

  RETURN
    0   ok
    1   got error
*/

bool
Item_func_in::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
  Item **arg, **arg_end;

  if (Item_func_opt_neg::fix_fields(thd, tables, ref))
    return 1;

  /* not_null_tables_cache == union(T1(e),union(T1(ei))) */
  if (pred_level && negated)
    return 0;

  /* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
  not_null_tables_cache= ~(table_map) 0;
  for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++)
    not_null_tables_cache&= (*arg)->not_null_tables();
  not_null_tables_cache|= (*args)->not_null_tables();
  return 0;
}


2015
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
2016
{
2017
  return cs->coll->strnncollsp(cs,
unknown's avatar
unknown committed
2018 2019
                               (uchar *) x->ptr(),x->length(),
                               (uchar *) y->ptr(),y->length());
2020 2021
}

2022

unknown's avatar
unknown committed
2023 2024
void Item_func_in::fix_length_and_dec()
{
2025 2026
  Item **arg, **arg_end;
  uint const_itm= 1;
2027
  THD *thd= current_thd;
2028
  
2029
  agg_cmp_type(thd, &cmp_type, args, arg_count);
2030

unknown's avatar
unknown committed
2031 2032 2033 2034
  if (cmp_type == STRING_RESULT &&
      agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV))
    return;

2035 2036
  for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
    const_itm&= arg[0]->const_item();
2037

unknown's avatar
unknown committed
2038 2039 2040 2041
  /*
    Row item with NULLs inside can return NULL or FALSE => 
    they can't be processed as static
  */
2042
  if (const_itm && !nulls_in_row())
unknown's avatar
unknown committed
2043
  {
2044
    switch (cmp_type) {
unknown's avatar
unknown committed
2045
    case STRING_RESULT:
2046
      array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in, 
2047
			  cmp_collation.collation);
unknown's avatar
unknown committed
2048 2049
      break;
    case INT_RESULT:
2050
      array= new in_longlong(arg_count-1);
unknown's avatar
unknown committed
2051 2052
      break;
    case REAL_RESULT:
2053
      array= new in_double(arg_count-1);
unknown's avatar
unknown committed
2054
      break;
unknown's avatar
unknown committed
2055
    case ROW_RESULT:
2056
      array= new in_row(arg_count-1, args[0]);
unknown's avatar
unknown committed
2057
      break;
unknown's avatar
unknown committed
2058 2059 2060
    default:
      DBUG_ASSERT(0);
      return;
unknown's avatar
unknown committed
2061
    }
2062
    if (array && !(thd->is_fatal_error))		// If not EOM
unknown's avatar
unknown committed
2063
    {
unknown's avatar
unknown committed
2064
      uint j=0;
unknown's avatar
unknown committed
2065
      for (uint i=1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
2066 2067 2068 2069
      {
	array->set(j,args[i]);
	if (!args[i]->null_value)			// Skip NULL values
	  j++;
unknown's avatar
unknown committed
2070 2071
	else
	  have_null= 1;
unknown's avatar
unknown committed
2072 2073 2074
      }
      if ((array->used_count=j))
	array->sort();
unknown's avatar
unknown committed
2075 2076 2077 2078
    }
  }
  else
  {
2079
    in_item= cmp_item::get_comparator(args[0]);
2080
    if (cmp_type  == STRING_RESULT)
2081
      in_item->cmp_charset= cmp_collation.collation;
unknown's avatar
unknown committed
2082
  }
2083
  maybe_null= args[0]->maybe_null;
unknown's avatar
unknown committed
2084
  max_length= 1;
unknown's avatar
unknown committed
2085 2086 2087 2088 2089 2090
}


void Item_func_in::print(String *str)
{
  str->append('(');
2091
  args[0]->print(str);
unknown's avatar
unknown committed
2092 2093
  if (negated)
    str->append(" not", 4);
2094
  str->append(" in (", 5);
unknown's avatar
unknown committed
2095
  print_args(str, 1);
2096
  str->append("))", 2);
unknown's avatar
unknown committed
2097 2098 2099 2100 2101
}


longlong Item_func_in::val_int()
{
2102
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2103 2104
  if (array)
  {
2105 2106
    int tmp=array->find(args[0]);
    null_value=args[0]->null_value || (!tmp && have_null);
unknown's avatar
unknown committed
2107
    return (longlong) (!null_value && tmp != negated);
unknown's avatar
unknown committed
2108
  }
2109 2110
  in_item->store_value(args[0]);
  if ((null_value=args[0]->null_value))
unknown's avatar
unknown committed
2111
    return 0;
2112
  have_null= 0;
2113
  for (uint i=1 ; i < arg_count ; i++)
unknown's avatar
unknown committed
2114 2115
  {
    if (!in_item->cmp(args[i]) && !args[i]->null_value)
unknown's avatar
unknown committed
2116
      return (longlong) (!negated);
2117
    have_null|= args[i]->null_value;
unknown's avatar
unknown committed
2118
  }
2119
  null_value= have_null;
unknown's avatar
unknown committed
2120
  return (longlong) (!null_value && negated);
unknown's avatar
unknown committed
2121 2122 2123 2124 2125
}


longlong Item_func_bit_or::val_int()
{
2126
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145
  ulonglong arg1= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  ulonglong arg2= (ulonglong) args[1]->val_int();
  if (args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
  return (longlong) (arg1 | arg2);
}


longlong Item_func_bit_and::val_int()
{
2146
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162
  ulonglong arg1= (ulonglong) args[0]->val_int();
  if (args[0]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  ulonglong arg2= (ulonglong) args[1]->val_int();
  if (args[1]->null_value)
  {
    null_value=1; /* purecov: inspected */
    return 0; /* purecov: inspected */
  }
  null_value=0;
  return (longlong) (arg1 & arg2);
}

2163
Item_cond::Item_cond(THD *thd, Item_cond *item)
2164
  :Item_bool_func(thd, item),
2165 2166
   abort_on_null(item->abort_on_null),
   and_tables_cache(item->and_tables_cache)
2167 2168
{
  /*
unknown's avatar
unknown committed
2169
    item->list will be copied by copy_andor_arguments() call
2170 2171 2172
  */
}

unknown's avatar
unknown committed
2173

2174 2175 2176
void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
{
  List_iterator_fast<Item> li(item->list);
unknown's avatar
unknown committed
2177
  while (Item *it= li++)
2178 2179
    list.push_back(it->copy_andor_structure(thd));
}
unknown's avatar
unknown committed
2180

unknown's avatar
unknown committed
2181

unknown's avatar
unknown committed
2182
bool
unknown's avatar
unknown committed
2183
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
2184
{
2185
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
2186 2187
  List_iterator<Item> li(list);
  Item *item;
2188
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
2189
  char buff[sizeof(char*)];			// Max local vars in function
2190
#endif
2191 2192
  not_null_tables_cache= used_tables_cache= 0;
  const_item_cache= 0;
2193 2194 2195 2196 2197
  /*
    and_table_cache is the value that Item_cond_or() returns for
    not_null_tables()
  */
  and_tables_cache= ~(table_map) 0;
unknown's avatar
unknown committed
2198

unknown's avatar
unknown committed
2199
  if (check_stack_overrun(thd, buff))
2200
    return 1;					// Fatal error flag is set!
unknown's avatar
unknown committed
2201 2202
  while ((item=li++))
  {
2203
    table_map tmp_table_map;
unknown's avatar
unknown committed
2204 2205 2206 2207 2208 2209 2210
    while (item->type() == Item::COND_ITEM &&
	   ((Item_cond*) item)->functype() == functype())
    {						// Identical function
      li.replace(((Item_cond*) item)->list);
      ((Item_cond*) item)->list.empty();
      item= *li.ref();				// new current item
    }
2211 2212
    if (abort_on_null)
      item->top_level_item();
2213 2214

    // item can be substituted in fix_fields
2215
    if ((!item->fixed &&
2216 2217
	 item->fix_fields(thd, tables, li.ref())) ||
	(item= *li.ref())->check_cols(1))
unknown's avatar
unknown committed
2218
      return 1; /* purecov: inspected */
2219 2220 2221 2222 2223 2224
    used_tables_cache|=     item->used_tables();
    tmp_table_map=	    item->not_null_tables();
    not_null_tables_cache|= tmp_table_map;
    and_tables_cache&=      tmp_table_map;
    const_item_cache&=	    item->const_item();
    with_sum_func=	    with_sum_func || item->with_sum_func;
unknown's avatar
unknown committed
2225 2226
    if (item->maybe_null)
      maybe_null=1;
unknown's avatar
unknown committed
2227
  }
2228
  thd->lex->current_select->cond_count+= list.elements;
unknown's avatar
unknown committed
2229
  fix_length_and_dec();
2230
  fixed= 1;
unknown's avatar
unknown committed
2231 2232 2233
  return 0;
}

unknown's avatar
unknown committed
2234 2235 2236 2237 2238 2239 2240 2241 2242 2243
bool Item_cond::walk(Item_processor processor, byte *arg)
{
  List_iterator_fast<Item> li(list);
  Item *item;
  while ((item= li++))
    if (item->walk(processor, arg))
      return 1;
  return Item_func::walk(processor, arg);
}

2244 2245 2246 2247 2248

/*
  Move SUM items out from item tree and replace with reference

  SYNOPSIS
2249 2250 2251 2252
    split_sum_func()
    thd			Thread handler
    ref_pointer_array	Pointer to array of reference fields
    fields		All fields in select
2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263

  NOTES
   This function is run on all expression (SELECT list, WHERE, HAVING etc)
   that have or refer (HAVING) to a SUM expression.

   The split is done to get an unique item for each SUM function
   so that we can easily find and calculate them.
   (Calculation done by update_sum_func() and copy_sum_funcs() in
   sql_select.cc)
*/

2264 2265
void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
                               List<Item> &fields)
unknown's avatar
unknown committed
2266 2267 2268
{
  List_iterator<Item> li(list);
  Item *item;
2269 2270
  while ((item= li++))
    item->split_sum_func2(thd, ref_pointer_array, fields, li.ref());
unknown's avatar
unknown committed
2271 2272 2273 2274 2275 2276 2277 2278 2279
}


table_map
Item_cond::used_tables() const
{						// This caches used_tables
  return used_tables_cache;
}

2280

unknown's avatar
unknown committed
2281 2282
void Item_cond::update_used_tables()
{
unknown's avatar
unknown committed
2283
  List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
2284
  Item *item;
2285 2286 2287

  used_tables_cache=0;
  const_item_cache=1;
unknown's avatar
unknown committed
2288 2289 2290
  while ((item=li++))
  {
    item->update_used_tables();
2291 2292
    used_tables_cache|= item->used_tables();
    const_item_cache&=  item->const_item();
unknown's avatar
unknown committed
2293 2294 2295 2296 2297 2298 2299
  }
}


void Item_cond::print(String *str)
{
  str->append('(');
unknown's avatar
unknown committed
2300
  List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313
  Item *item;
  if ((item=li++))
    item->print(str);
  while ((item=li++))
  {
    str->append(' ');
    str->append(func_name());
    str->append(' ');
    item->print(str);
  }
  str->append(')');
}

2314

2315
void Item_cond::neg_arguments(THD *thd)
2316 2317 2318 2319 2320
{
  List_iterator<Item> li(list);
  Item *item;
  while ((item= li++))		/* Apply not transformation to the arguments */
  {
2321 2322 2323
    Item *new_item= item->neg_transformer(thd);
    if (!new_item)
    {
unknown's avatar
unknown committed
2324 2325
      if (!(new_item= new Item_func_not(item)))
	return;					// Fatal OEM error
2326 2327
    }
    VOID(li.replace(new_item));
2328 2329 2330 2331
  }
}


2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348
/*
  Evalution of AND(expr, expr, expr ...)

  NOTES:
    abort_if_null is set for AND expressions for which we don't care if the
    result is NULL or 0. This is set for:
    - WHERE clause
    - HAVING clause
    - IF(expression)

  RETURN VALUES
    1  If all expressions are true
    0  If all expressions are false or if we find a NULL expression and
       'abort_on_null' is set.
    NULL if all expression are either 1 or NULL
*/

unknown's avatar
unknown committed
2349 2350 2351

longlong Item_cond_and::val_int()
{
2352
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2353
  List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
2354
  Item *item;
2355
  null_value= 0;
unknown's avatar
unknown committed
2356 2357 2358 2359
  while ((item=li++))
  {
    if (item->val_int() == 0)
    {
2360 2361
      if (abort_on_null || !(null_value= item->null_value))
	return 0;				// return FALSE
unknown's avatar
unknown committed
2362 2363
    }
  }
2364
  return null_value ? 0 : 1;
unknown's avatar
unknown committed
2365 2366
}

2367

unknown's avatar
unknown committed
2368 2369
longlong Item_cond_or::val_int()
{
2370
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2371
  List_iterator_fast<Item> li(list);
unknown's avatar
unknown committed
2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
  Item *item;
  null_value=0;
  while ((item=li++))
  {
    if (item->val_int() != 0)
    {
      null_value=0;
      return 1;
    }
    if (item->null_value)
      null_value=1;
  }
  return 0;
}

2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
/*
  Create an AND expression from two expressions

  SYNOPSIS
   and_expressions()
   a		expression or NULL
   b    	expression.
   org_item	Don't modify a if a == *org_item
		If a == NULL, org_item is set to point at b,
		to ensure that future calls will not modify b.

  NOTES
    This will not modify item pointed to by org_item or b
    The idea is that one can call this in a loop and create and
    'and' over all items without modifying any of the original items.

  RETURN
    NULL	Error
    Item
*/

Item *and_expressions(Item *a, Item *b, Item **org_item)
{
  if (!a)
2411
    return (*org_item= (Item*) b);
2412 2413 2414
  if (a == *org_item)
  {
    Item_cond *res;
2415
    if ((res= new Item_cond_and(a, (Item*) b)))
2416
    {
2417
      res->used_tables_cache= a->used_tables() | b->used_tables();
2418 2419
      res->not_null_tables_cache= a->not_null_tables() | b->not_null_tables();
    }
2420 2421
    return res;
  }
2422
  if (((Item_cond_and*) a)->add((Item*) b))
2423 2424
    return 0;
  ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
2425
  ((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables();
2426 2427 2428 2429
  return a;
}


unknown's avatar
unknown committed
2430 2431
longlong Item_func_isnull::val_int()
{
2432
  DBUG_ASSERT(fixed == 1);
2433 2434 2435 2436 2437
  /*
    Handle optimization if the argument can't be null
    This has to be here because of the test in update_used_tables().
  */
  if (!used_tables_cache)
unknown's avatar
unknown committed
2438
    return cached_value;
unknown's avatar
unknown committed
2439
  return args[0]->is_null() ? 1: 0;
unknown's avatar
unknown committed
2440 2441
}

2442 2443
longlong Item_is_not_null_test::val_int()
{
2444
  DBUG_ASSERT(fixed == 1);
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
  DBUG_ENTER("Item_is_not_null_test::val_int");
  if (!used_tables_cache)
  {
    owner->was_null|= (!cached_value);
    DBUG_PRINT("info", ("cached :%d", cached_value));
    DBUG_RETURN(cached_value);
  }
  if (args[0]->is_null())
  {
    DBUG_PRINT("info", ("null"))
    owner->was_null|= 1;
    DBUG_RETURN(0);
  }
  else
    DBUG_RETURN(1);
}

/* Optimize case of not_null_column IS NULL */
void Item_is_not_null_test::update_used_tables()
{
  if (!args[0]->maybe_null)
  {
    used_tables_cache= 0;			/* is always true */
    cached_value= (longlong) 1;
  }
  else
  {
    args[0]->update_used_tables();
    if (!(used_tables_cache=args[0]->used_tables()))
    {
      /* Remember if the value is always NULL or never NULL */
      cached_value= (longlong) !args[0]->is_null();
    }
  }
}
2480

2481

unknown's avatar
unknown committed
2482 2483
longlong Item_func_isnotnull::val_int()
{
2484
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2485
  return args[0]->is_null() ? 0 : 1;
unknown's avatar
unknown committed
2486 2487 2488
}


2489 2490 2491 2492
void Item_func_isnotnull::print(String *str)
{
  str->append('(');
  args[0]->print(str);
2493
  str->append(" is not null)", 13);
2494 2495 2496
}


unknown's avatar
unknown committed
2497 2498
longlong Item_func_like::val_int()
{
2499
  DBUG_ASSERT(fixed == 1);
2500
  String* res = args[0]->val_str(&tmp_value1);
unknown's avatar
unknown committed
2501 2502 2503 2504 2505
  if (args[0]->null_value)
  {
    null_value=1;
    return 0;
  }
2506
  String* res2 = args[1]->val_str(&tmp_value2);
unknown's avatar
unknown committed
2507 2508 2509 2510 2511 2512
  if (args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
2513 2514
  if (canDoTurboBM)
    return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
2515
  return my_wildcmp(cmp.cmp_collation.collation,
2516 2517 2518
		    res->ptr(),res->ptr()+res->length(),
		    res2->ptr(),res2->ptr()+res2->length(),
		    escape,wild_one,wild_many) ? 0 : 1;
unknown's avatar
unknown committed
2519 2520 2521 2522 2523 2524 2525
}


/* We can optimize a where if first character isn't a wildcard */

Item_func::optimize_type Item_func_like::select_optimize() const
{
2526
  if (args[1]->const_item())
unknown's avatar
unknown committed
2527
  {
2528 2529 2530 2531 2532 2533
    String* res2= args[1]->val_str((String *)&tmp_value2);

    if (!res2)
      return OPTIMIZE_NONE;

    if (*res2->ptr() != wild_many)
unknown's avatar
unknown committed
2534
    {
2535
      if (args[0]->result_type() != STRING_RESULT || *res2->ptr() != wild_one)
unknown's avatar
unknown committed
2536 2537 2538 2539 2540 2541
	return OPTIMIZE_OP;
    }
  }
  return OPTIMIZE_NONE;
}

2542

unknown's avatar
unknown committed
2543
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
2544
{
2545
  DBUG_ASSERT(fixed == 0);
2546 2547
  if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
      escape_item->fix_fields(thd, tlist, &escape_item))
2548 2549
    return 1;

2550
  if (!escape_item->const_during_execution())
2551
  {
2552 2553 2554 2555 2556 2557 2558 2559
    my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
    return 1;
  }
  
  if (escape_item->const_item())
  {
    /* If we are on execution stage */
    String *escape_str= escape_item->val_str(&tmp_value1);
2560 2561
    if (escape_str)
    {
unknown's avatar
unknown committed
2562
      if (use_mb(cmp.cmp_collation.collation))
2563
      {
2564
        CHARSET_INFO *cs= escape_str->charset();
2565 2566 2567 2568 2569 2570 2571 2572 2573
        my_wc_t wc;
        int rc= cs->cset->mb_wc(cs, &wc,
                                (const uchar*) escape_str->ptr(),
                                (const uchar*) escape_str->ptr() +
                                               escape_str->length());
        escape= (int) (rc > 0 ? wc : '\\');
      }
      else
      {
unknown's avatar
unknown committed
2574 2575 2576 2577 2578
        /*
          In the case of 8bit character set, we pass native
          code instead of Unicode code as "escape" argument.
          Convert to "cs" if charset of escape differs.
        */
unknown's avatar
unknown committed
2579
        CHARSET_INFO *cs= cmp.cmp_collation.collation;
unknown's avatar
unknown committed
2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592
        uint32 unused;
        if (escape_str->needs_conversion(escape_str->length(),
                                         escape_str->charset(), cs, &unused))
        {
          char ch;
          uint errors;
          uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(),
                                          escape_str->length(),
                                          escape_str->charset(), &errors);
          escape= cnvlen ? ch : '\\';
        }
        else
          escape= *(escape_str->ptr());
2593 2594 2595 2596
      }
    }
    else
      escape= '\\';
2597
 
2598
    /*
2599 2600
      We could also do boyer-more for non-const items, but as we would have to
      recompute the tables for each row it's not worth it.
2601
    */
2602 2603
    if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
       !(specialflag & SPECIAL_NO_NEW_FUNC))
2604
    {
2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637
      String* res2 = args[1]->val_str(&tmp_value2);
      if (!res2)
        return 0;				// Null argument
      
      const size_t len   = res2->length();
      const char*  first = res2->ptr();
      const char*  last  = first + len - 1;
      /*
        len must be > 2 ('%pattern%')
        heuristic: only do TurboBM for pattern_len > 2
      */
      
      if (len > MIN_TURBOBM_PATTERN_LEN + 2 &&
          *first == wild_many &&
          *last  == wild_many)
      {
        const char* tmp = first + 1;
        for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
        canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation);
      }
      if (canDoTurboBM)
      {
        pattern     = first + 1;
        pattern_len = len - 2;
        DBUG_PRINT("info", ("Initializing pattern: '%s'", first));
        int *suff = (int*) thd->alloc(sizeof(int)*((pattern_len + 1)*2+
                                      alphabet_size));
        bmGs      = suff + pattern_len + 1;
        bmBc      = bmGs + pattern_len + 1;
        turboBM_compute_good_suffix_shifts(suff);
        turboBM_compute_bad_character_shifts();
        DBUG_PRINT("info",("done"));
      }
2638 2639 2640 2641 2642
    }
  }
  return 0;
}

2643 2644 2645 2646 2647 2648
void Item_func_like::cleanup()
{
  canDoTurboBM= FALSE;
  Item_bool_func2::cleanup();
}

unknown's avatar
unknown committed
2649 2650 2651
#ifdef USE_REGEX

bool
unknown's avatar
unknown committed
2652
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
unknown's avatar
unknown committed
2653
{
2654
  DBUG_ASSERT(fixed == 0);
unknown's avatar
unknown committed
2655 2656 2657 2658
  if ((!args[0]->fixed &&
       args[0]->fix_fields(thd, tables, args)) || args[0]->check_cols(1) ||
      (!args[1]->fixed && 
       args[1]->fix_fields(thd,tables, args + 1)) || args[1]->check_cols(1))
unknown's avatar
unknown committed
2659 2660
    return 1;					/* purecov: inspected */
  with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
unknown's avatar
unknown committed
2661 2662
  max_length= 1;
  decimals= 0;
2663

unknown's avatar
unknown committed
2664
  if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV))
2665
    return 1;
2666

unknown's avatar
unknown committed
2667
  used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
2668 2669
  not_null_tables_cache= (args[0]->not_null_tables() |
			  args[1]->not_null_tables());
unknown's avatar
unknown committed
2670 2671 2672 2673
  const_item_cache=args[0]->const_item() && args[1]->const_item();
  if (!regex_compiled && args[1]->const_item())
  {
    char buff[MAX_FIELD_WIDTH];
2674
    String tmp(buff,sizeof(buff),&my_charset_bin);
unknown's avatar
unknown committed
2675 2676 2677 2678 2679 2680 2681
    String *res=args[1]->val_str(&tmp);
    if (args[1]->null_value)
    {						// Will always return NULL
      maybe_null=1;
      return 0;
    }
    int error;
unknown's avatar
unknown committed
2682 2683 2684 2685 2686 2687
    if ((error= my_regcomp(&preg,res->c_ptr(),
                           ((cmp_collation.collation->state &
                             (MY_CS_BINSORT | MY_CS_CSSORT)) ?
                            REG_EXTENDED | REG_NOSUB :
                            REG_EXTENDED | REG_NOSUB | REG_ICASE),
                           cmp_collation.collation)))
unknown's avatar
unknown committed
2688
    {
unknown's avatar
unknown committed
2689
      (void) my_regerror(error,&preg,buff,sizeof(buff));
unknown's avatar
unknown committed
2690 2691 2692 2693 2694 2695 2696 2697
      my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff);
      return 1;
    }
    regex_compiled=regex_is_const=1;
    maybe_null=args[0]->maybe_null;
  }
  else
    maybe_null=1;
2698
  fixed= 1;
unknown's avatar
unknown committed
2699 2700 2701
  return 0;
}

2702

unknown's avatar
unknown committed
2703 2704
longlong Item_func_regex::val_int()
{
2705
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
2706
  char buff[MAX_FIELD_WIDTH];
2707
  String *res, tmp(buff,sizeof(buff),&my_charset_bin);
unknown's avatar
unknown committed
2708 2709 2710 2711 2712 2713 2714 2715 2716 2717

  res=args[0]->val_str(&tmp);
  if (args[0]->null_value)
  {
    null_value=1;
    return 0;
  }
  if (!regex_is_const)
  {
    char buff2[MAX_FIELD_WIDTH];
2718
    String *res2, tmp2(buff2,sizeof(buff2),&my_charset_bin);
unknown's avatar
unknown committed
2719 2720 2721 2722 2723 2724 2725

    res2= args[1]->val_str(&tmp2);
    if (args[1]->null_value)
    {
      null_value=1;
      return 0;
    }
unknown's avatar
unknown committed
2726
    if (!regex_compiled || stringcmp(res2,&prev_regexp))
unknown's avatar
unknown committed
2727 2728 2729 2730
    {
      prev_regexp.copy(*res2);
      if (regex_compiled)
      {
unknown's avatar
unknown committed
2731
	my_regfree(&preg);
unknown's avatar
unknown committed
2732 2733
	regex_compiled=0;
      }
unknown's avatar
unknown committed
2734 2735 2736 2737 2738 2739
      if (my_regcomp(&preg,res2->c_ptr(),
                     ((cmp_collation.collation->state &
                       (MY_CS_BINSORT | MY_CS_CSSORT)) ?
                      REG_EXTENDED | REG_NOSUB :
                      REG_EXTENDED | REG_NOSUB | REG_ICASE),
                     cmp_collation.collation))
unknown's avatar
unknown committed
2740 2741 2742 2743 2744 2745 2746 2747
      {
	null_value=1;
	return 0;
      }
      regex_compiled=1;
    }
  }
  null_value=0;
unknown's avatar
unknown committed
2748
  return my_regexec(&preg,res->c_ptr(),0,(my_regmatch_t*) 0,0) ? 0 : 1;
unknown's avatar
unknown committed
2749 2750 2751
}


2752
void Item_func_regex::cleanup()
unknown's avatar
unknown committed
2753
{
2754 2755
  DBUG_ENTER("Item_func_regex::cleanup");
  Item_bool_func::cleanup();
unknown's avatar
unknown committed
2756 2757
  if (regex_compiled)
  {
unknown's avatar
unknown committed
2758
    my_regfree(&preg);
unknown's avatar
unknown committed
2759 2760
    regex_compiled=0;
  }
2761
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2762 2763
}

2764

unknown's avatar
unknown committed
2765
#endif /* USE_REGEX */
2766 2767 2768


#ifdef LIKE_CMP_TOUPPER
unknown's avatar
unknown committed
2769
#define likeconv(cs,A) (uchar) (cs)->toupper(A)
2770
#else
unknown's avatar
unknown committed
2771
#define likeconv(cs,A) (uchar) (cs)->sort_order[(uchar) (A)]
2772 2773 2774 2775 2776 2777 2778 2779
#endif


/**********************************************************************
  turboBM_compute_suffixes()
  Precomputation dependent only on pattern_len.
**********************************************************************/

2780
void Item_func_like::turboBM_compute_suffixes(int *suff)
2781 2782 2783 2784
{
  const int   plm1 = pattern_len - 1;
  int            f = 0;
  int            g = plm1;
unknown's avatar
unknown committed
2785
  int *const splm1 = suff + plm1;
2786
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
2787 2788 2789

  *splm1 = pattern_len;

unknown's avatar
unknown committed
2790
  if (!cs->sort_order)
2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821
  {
    int i;
    for (i = pattern_len - 2; i >= 0; i--)
    {
      int tmp = *(splm1 + i - f);
      if (g < i && tmp < i - g)
	suff[i] = tmp;
      else
      {
	if (i < g)
	  g = i; // g = min(i, g)
	f = i;
	while (g >= 0 && pattern[g] == pattern[g + plm1 - f])
	  g--;
	suff[i] = f - g;
      }
    }
  }
  else
  {
    int i;
    for (i = pattern_len - 2; 0 <= i; --i)
    {
      int tmp = *(splm1 + i - f);
      if (g < i && tmp < i - g)
	suff[i] = tmp;
      else
      {
	if (i < g)
	  g = i; // g = min(i, g)
	f = i;
2822
	while (g >= 0 &&
unknown's avatar
unknown committed
2823
	       likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f]))
2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836
	  g--;
	suff[i] = f - g;
      }
    }
  }
}


/**********************************************************************
   turboBM_compute_good_suffix_shifts()
   Precomputation dependent only on pattern_len.
**********************************************************************/

2837
void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff)
2838 2839 2840
{
  turboBM_compute_suffixes(suff);

2841 2842
  int *end = bmGs + pattern_len;
  int *k;
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855
  for (k = bmGs; k < end; k++)
    *k = pattern_len;

  int tmp;
  int i;
  int j          = 0;
  const int plm1 = pattern_len - 1;
  for (i = plm1; i > -1; i--)
  {
    if (suff[i] == i + 1)
    {
      for (tmp = plm1 - i; j < tmp; j++)
      {
2856
	int *tmp2 = bmGs + j;
2857 2858 2859 2860 2861 2862
	if (*tmp2 == pattern_len)
	  *tmp2 = tmp;
      }
    }
  }

2863
  int *tmp2;
2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883
  for (tmp = plm1 - i; j < tmp; j++)
  {
    tmp2 = bmGs + j;
    if (*tmp2 == pattern_len)
      *tmp2 = tmp;
  }

  tmp2 = bmGs + plm1;
  for (i = 0; i <= pattern_len - 2; i++)
    *(tmp2 - suff[i]) = plm1 - i;
}


/**********************************************************************
   turboBM_compute_bad_character_shifts()
   Precomputation dependent on pattern_len.
**********************************************************************/

void Item_func_like::turboBM_compute_bad_character_shifts()
{
unknown's avatar
unknown committed
2884 2885 2886 2887
  int *i;
  int *end = bmBc + alphabet_size;
  int j;
  const int plm1 = pattern_len - 1;
2888
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
unknown's avatar
unknown committed
2889

2890 2891 2892
  for (i = bmBc; i < end; i++)
    *i = pattern_len;

unknown's avatar
unknown committed
2893
  if (!cs->sort_order)
unknown's avatar
unknown committed
2894
  {
2895
    for (j = 0; j < plm1; j++)
2896
      bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
unknown's avatar
unknown committed
2897
  }
2898
  else
unknown's avatar
unknown committed
2899
  {
2900
    for (j = 0; j < plm1; j++)
unknown's avatar
unknown committed
2901
      bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j;
unknown's avatar
unknown committed
2902
  }
2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
}


/**********************************************************************
  turboBM_matches()
  Search for pattern in text, returns true/false for match/no match
**********************************************************************/

bool Item_func_like::turboBM_matches(const char* text, int text_len) const
{
  register int bcShift;
  register int turboShift;
  int shift = pattern_len;
  int j     = 0;
  int u     = 0;
2918
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
2919

2920 2921
  const int plm1=  pattern_len - 1;
  const int tlmpl= text_len - pattern_len;
2922 2923

  /* Searching */
unknown's avatar
unknown committed
2924
  if (!cs->sort_order)
2925 2926 2927
  {
    while (j <= tlmpl)
    {
2928
      register int i= plm1;
2929 2930 2931 2932
      while (i >= 0 && pattern[i] == text[i + j])
      {
	i--;
	if (i == plm1 - shift)
2933
	  i-= u;
2934 2935
      }
      if (i < 0)
unknown's avatar
unknown committed
2936
	return 1;
2937 2938 2939

      register const int v = plm1 - i;
      turboShift = u - v;
2940
      bcShift    = bmBc[(uint) (uchar) text[i + j]] - plm1 + i;
2941 2942 2943 2944 2945 2946 2947 2948 2949 2950
      shift      = max(turboShift, bcShift);
      shift      = max(shift, bmGs[i]);
      if (shift == bmGs[i])
	u = min(pattern_len - shift, v);
      else
      {
	if (turboShift < bcShift)
	  shift = max(shift, u + 1);
	u = 0;
      }
2951
      j+= shift;
2952
    }
unknown's avatar
unknown committed
2953
    return 0;
2954 2955 2956 2957 2958 2959
  }
  else
  {
    while (j <= tlmpl)
    {
      register int i = plm1;
unknown's avatar
unknown committed
2960
      while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j]))
2961 2962 2963
      {
	i--;
	if (i == plm1 - shift)
2964
	  i-= u;
2965 2966
      }
      if (i < 0)
unknown's avatar
unknown committed
2967
	return 1;
2968 2969 2970

      register const int v = plm1 - i;
      turboShift = u - v;
unknown's avatar
unknown committed
2971
      bcShift    = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i;
2972 2973 2974 2975 2976 2977 2978 2979 2980 2981
      shift      = max(turboShift, bcShift);
      shift      = max(shift, bmGs[i]);
      if (shift == bmGs[i])
	u = min(pattern_len - shift, v);
      else
      {
	if (turboShift < bcShift)
	  shift = max(shift, u + 1);
	u = 0;
      }
2982
      j+= shift;
2983
    }
unknown's avatar
unknown committed
2984
    return 0;
2985 2986
  }
}
unknown's avatar
unknown committed
2987

2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008

/*
  Make a logical XOR of the arguments.

  SYNOPSIS
    val_int()

  DESCRIPTION
  If either operator is NULL, return NULL.

  NOTE
    As we don't do any index optimization on XOR this is not going to be
    very fast to use.

  TODO (low priority)
    Change this to be optimized as:
      A XOR B   ->  (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1)
    To be able to do this, we would however first have to extend the MySQL
    range optimizer to handle OR better.
*/

unknown's avatar
unknown committed
3009 3010
longlong Item_cond_xor::val_int()
{
3011
  DBUG_ASSERT(fixed == 1);
unknown's avatar
unknown committed
3012 3013 3014
  List_iterator<Item> li(list);
  Item *item;
  int result=0;	
3015
  null_value=0;
unknown's avatar
unknown committed
3016 3017
  while ((item=li++))
  {
3018 3019 3020 3021 3022 3023
    result^= (item->val_int() != 0);
    if (item->null_value)
    {
      null_value=1;
      return 0;
    }
unknown's avatar
unknown committed
3024
  }
3025
  return (longlong) result;
unknown's avatar
unknown committed
3026
}
3027 3028 3029 3030 3031 3032

/*
  Apply NOT transformation to the item and return a new one.

  SYNPOSIS
    neg_transformer()
3033
    thd		thread handler
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053

  DESCRIPTION
    Transform the item using next rules:
       a AND b AND ...    -> NOT(a) OR NOT(b) OR ...
       a OR b OR ...      -> NOT(a) AND NOT(b) AND ...
       NOT(a)             -> a
       a = b              -> a != b
       a != b             -> a = b
       a < b              -> a >= b
       a >= b             -> a < b
       a > b              -> a <= b
       a <= b             -> a > b
       IS NULL(a)         -> IS NOT NULL(a)
       IS NOT NULL(a)     -> IS NULL(a)

  RETURN
    New item or
    NULL if we cannot apply NOT transformation (see Item::neg_transformer()).
*/

3054
Item *Item_func_not::neg_transformer(THD *thd)	/* NOT(x)  ->  x */
3055
{
unknown's avatar
unknown committed
3056
  return args[0];
3057 3058
}

3059 3060

Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
3061
{
3062 3063
  Item *item= negated_item();
  return item;
3064 3065
}

3066 3067 3068

/* a IS NULL  ->  a IS NOT NULL */
Item *Item_func_isnull::neg_transformer(THD *thd)
3069
{
3070 3071
  Item *item= new Item_func_isnotnull(args[0]);
  return item;
3072 3073
}

3074 3075 3076

/* a IS NOT NULL  ->  a IS NULL */
Item *Item_func_isnotnull::neg_transformer(THD *thd)
3077
{
3078 3079
  Item *item= new Item_func_isnull(args[0]);
  return item;
3080 3081
}

3082 3083 3084

Item *Item_cond_and::neg_transformer(THD *thd)	/* NOT(a AND b AND ...)  -> */
					/* NOT a OR NOT b OR ... */
3085
{
3086 3087 3088
  neg_arguments(thd);
  Item *item= new Item_cond_or(list);
  return item;
3089 3090
}

3091 3092 3093

Item *Item_cond_or::neg_transformer(THD *thd)	/* NOT(a OR b OR ...)  -> */
					/* NOT a AND NOT b AND ... */
3094
{
3095 3096 3097
  neg_arguments(thd);
  Item *item= new Item_cond_and(list);
  return item;
3098 3099
}

3100 3101

Item *Item_func_eq::negated_item()		/* a = b  ->  a != b */
3102
{
3103
  return new Item_func_ne(args[0], args[1]);
3104 3105
}

3106 3107

Item *Item_func_ne::negated_item()		/* a != b  ->  a = b */
3108
{
3109
  return new Item_func_eq(args[0], args[1]);
3110 3111
}

3112 3113

Item *Item_func_lt::negated_item()		/* a < b  ->  a >= b */
3114
{
3115
  return new Item_func_ge(args[0], args[1]);
3116 3117
}

3118 3119

Item *Item_func_ge::negated_item()		/* a >= b  ->  a < b */
3120
{
3121
  return new Item_func_lt(args[0], args[1]);
3122 3123
}

3124 3125

Item *Item_func_gt::negated_item()		/* a > b  ->  a <= b */
3126
{
3127
  return new Item_func_le(args[0], args[1]);
3128 3129
}

3130 3131

Item *Item_func_le::negated_item()		/* a <= b  ->  a > b */
3132
{
3133
  return new Item_func_gt(args[0], args[1]);
3134 3135
}

3136 3137
// just fake method, should never be called
Item *Item_bool_rowready_func2::negated_item()
3138
{
3139 3140
  DBUG_ASSERT(0);
  return 0;
3141
}