item_cmpfunc.cc 63.3 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2

bk@work.mysql.com's avatar
bk@work.mysql.com 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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
7

bk@work.mysql.com's avatar
bk@work.mysql.com 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.
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
12

bk@work.mysql.com's avatar
bk@work.mysql.com committed
13 14 15 16 17 18 19 20 21 22 23 24 25
   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 */

#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
#include <m_ctype.h>
26
#include "sql_select.h"
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
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)
{
  uint i;
  type[0]= items[0]->result_type();
  for (i=1 ; i < nitems ; i++)
    type[0]= item_store_type(type[0], items[i]->result_type());
}

static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
{
  uint i;
  type[0]= items[0]->result_type();
  for (i=1 ; i < nitems ; i++)
    type[0]= item_cmp_type(type[0], items[i]->result_type());
}

54 55
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
{
56
  my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
57 58 59 60 61
  	   c1.collation->name,c1.derivation_name(),
	   c2.collation->name,c2.derivation_name(),
	   fname);
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
62 63

Item_bool_func2* Eq_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
64 65 66
{
  return new Item_func_eq(a, b);
}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
67 68 69


Item_bool_func2* Ne_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
70 71 72
{
  return new Item_func_ne(a, b);
}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
73 74 75


Item_bool_func2* Gt_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
76 77 78
{
  return new Item_func_gt(a, b);
}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
79 80 81


Item_bool_func2* Lt_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
82 83 84
{
  return new Item_func_lt(a, b);
}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
85 86 87


Item_bool_func2* Ge_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
88 89 90
{
  return new Item_func_ge(a, b);
}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
91 92 93


Item_bool_func2* Le_creator::create(Item *a, Item *b) const
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
94 95 96
{
  return new Item_func_le(a, b);
}
97

bk@work.mysql.com's avatar
bk@work.mysql.com committed
98
/*
99
  Test functions
100 101
  Most of these  returns 0LL if false and 1LL if true and
  NULL if some arg is NULL.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
102 103 104 105
*/

longlong Item_func_not::val_int()
{
106
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
107 108
  double value=args[0]->val();
  null_value=args[0]->null_value;
109
  return ((!null_value && value == 0) ? 1 : 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
110 111
}

112 113 114 115 116
/*
  special NOT for ALL subquery
*/

longlong Item_func_not_all::val_int()
117 118
{
  DBUG_ASSERT(fixed == 1);
119
  double value= args[0]->val();
120 121 122

  /*
    return TRUE if there was records in underlaying select in max/min
123
    optimisation (ALL subquery)
124 125 126 127
  */
  if (empty_underlying_subquery())
    return 1;

128
  null_value= args[0]->null_value;
129 130 131 132 133 134 135 136
  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()));
137 138
}

139 140 141 142 143 144 145 146
void Item_func_not_all::print(String *str)
{
  if (show)
    Item_func::print(str);
  else
    args[0]->print(str);
}

147 148

/*
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
149 150 151
  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).
152 153 154 155 156 157 158 159
*/

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

  /*
160 161
    return FALSE if there was records in underlaying select in max/min
    optimisation (SAME/ANY subquery)
162 163
  */
  if (empty_underlying_subquery())
164
    return 0;
165 166 167 168 169 170

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


171 172 173 174 175
/*
  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).
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
176 177 178 179

  RESULT VALUES
  0	Can't convert item
  1	Item was replaced with an integer version of the item
180
*/
bk@work.mysql.com's avatar
bk@work.mysql.com committed
181

182
static bool convert_constant_item(THD *thd, Field *field, Item **item)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
183
{
184
  if ((*item)->const_item())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
185
  {
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
186
    if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
187
    {
188 189
      Item *tmp=new Item_int_with_ref(field->val_int(), *item);
      if (tmp)
190
        thd->change_item_tree(item, tmp);
191
      return 1;					// Item was replaced
bk@work.mysql.com's avatar
bk@work.mysql.com committed
192 193 194 195 196
    }
  }
  return 0;
}

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
197

198 199 200
void Item_bool_func2::fix_length_and_dec()
{
  max_length= 1;				     // Function returns 0 or 1
201
  THD *thd= current_thd;
202 203 204 205 206 207 208

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

210 211 212
  DTCollation coll;
  if (args[0]->result_type() == STRING_RESULT &&
      args[1]->result_type() == STRING_RESULT &&
bar@mysql.com's avatar
bar@mysql.com committed
213 214
      agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV))
    return;
215
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
216
  // Make a special case of compare with fields to get nicer DATE comparisons
217 218 219 220 221 222 223

  if (functype() == LIKE_FUNC)  // Disable conversion in case of LIKE function.
  {
    set_cmp_func();
    return;
  }
    
bk@work.mysql.com's avatar
bk@work.mysql.com committed
224 225 226
  if (args[0]->type() == FIELD_ITEM)
  {
    Field *field=((Item_field*) args[0])->field;
227
    if (field->can_be_compared_as_longlong())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
228
    {
229
      if (convert_constant_item(thd, field,&args[1]))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
230
      {
231
	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
232
			 INT_RESULT);		// Works for all types.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
233 234 235 236 237 238 239
	return;
      }
    }
  }
  if (args[1]->type() == FIELD_ITEM)
  {
    Field *field=((Item_field*) args[1])->field;
240
    if (field->can_be_compared_as_longlong())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
241
    {
242
      if (convert_constant_item(thd, field,&args[0]))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
243
      {
244 245
	cmp.set_cmp_func(this, tmp_arg, tmp_arg+1,
			 INT_RESULT); // Works for all types.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
246 247 248 249
	return;
      }
    }
  }
250
  set_cmp_func();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
251 252
}

253

254
int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
255
{
256
  owner= item;
serg@serg.mylan's avatar
serg@serg.mylan committed
257 258
  func= comparator_matrix[type]
                         [test(owner->functype() == Item_func::EQUAL_FUNC)];
259
  if (type == ROW_RESULT)
260
  {
261 262
    uint n= (*a)->cols();
    if (n != (*b)->cols())
263
    {
264
      my_error(ER_OPERAND_COLUMNS, MYF(0), n);
265 266 267
      comparators= 0;
      return 1;
    }
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
268 269 270 271 272
    if (!(comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n)))
      return 1;
    for (uint i=0; i < n; i++)
    {
      if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
273
      {
274
	my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->el(i)->cols());
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
275
	return 1;
276
      }
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
277 278
      comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
    }
279
  }
280 281 282 283 284 285
  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
    */
286 287
    if (cmp_collation.set((*a)->collation, (*b)->collation) || 
	cmp_collation.derivation == DERIVATION_NONE)
288 289 290 291
    {
      my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name());
      return 1;
    }
292
    if (cmp_collation.collation == &my_charset_bin)
monty@mysql.com's avatar
monty@mysql.com committed
293 294
    {
      /*
295
	We are using BLOB/BINARY/VARBINARY, change to compare byte by byte,
monty@mysql.com's avatar
monty@mysql.com committed
296 297 298 299 300 301 302
	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;
    }
303
  }
304 305
  else if (type == INT_RESULT)
  {
306
    if (func == &Arg_comparator::compare_int_signed)
307 308 309 310 311 312 313
    {
      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;
    }
314 315 316 317 318
    else if (func== &Arg_comparator::compare_e_int)
    {
      if ((*a)->unsigned_flag ^ (*b)->unsigned_flag)
        func= &Arg_comparator::compare_e_int_diff_signedness;
    }
319
  }
320
  return 0;
321
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
322

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
323

324
int Arg_comparator::compare_string()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
325 326
{
  String *res1,*res2;
327
  if ((res1= (*a)->val_str(&owner->tmp_value1)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
328
  {
329
    if ((res2= (*b)->val_str(&owner->tmp_value2)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
330
    {
331
      owner->null_value= 0;
332
      return sortcmp(res1,res2,cmp_collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
333 334
    }
  }
335
  owner->null_value= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
336 337 338
  return -1;
}

monty@mysql.com's avatar
monty@mysql.com committed
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

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

372 373 374
int Arg_comparator::compare_e_string()
{
  String *res1,*res2;
375 376
  res1= (*a)->val_str(&owner->tmp_value1);
  res2= (*b)->val_str(&owner->tmp_value2);
377 378
  if (!res1 || !res2)
    return test(res1 == res2);
379
  return test(sortcmp(res1, res2, cmp_collation.collation) == 0);
380 381 382
}


monty@mysql.com's avatar
monty@mysql.com committed
383 384 385 386 387 388 389 390 391 392 393
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);
}


394
int Arg_comparator::compare_real()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
395
{
396 397
  double val1= (*a)->val();
  if (!(*a)->null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
398
  {
399 400
    double val2= (*b)->val();
    if (!(*b)->null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
401
    {
402
      owner->null_value= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
403 404 405 406 407
      if (val1 < val2)	return -1;
      if (val1 == val2) return 0;
      return 1;
    }
  }
408
  owner->null_value= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
409 410 411
  return -1;
}

412 413
int Arg_comparator::compare_e_real()
{
414 415 416 417
  double val1= (*a)->val();
  double val2= (*b)->val();
  if ((*a)->null_value || (*b)->null_value)
    return test((*a)->null_value && (*b)->null_value);
418 419
  return test(val1 == val2);
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
420

421
int Arg_comparator::compare_int_signed()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
422
{
423 424
  longlong val1= (*a)->val_int();
  if (!(*a)->null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
425
  {
426 427
    longlong val2= (*b)->val_int();
    if (!(*b)->null_value)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
428
    {
429
      owner->null_value= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
430 431 432 433 434
      if (val1 < val2)	return -1;
      if (val1 == val2)   return 0;
      return 1;
    }
  }
435
  owner->null_value= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
436 437 438
  return -1;
}

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 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 511 512 513 514

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


515 516
int Arg_comparator::compare_e_int()
{
517 518 519 520
  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);
521 522 523
  return test(val1 == val2);
}

524 525 526 527 528 529 530 531 532 533 534
/*
  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);
}
535

536
int Arg_comparator::compare_row()
537 538
{
  int res= 0;
539 540
  (*a)->bring_value();
  (*b)->bring_value();
541
  uint n= (*a)->cols();
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
542
  for (uint i= 0; i<n; i++)
543
  {
544
    if ((res= comparators[i].compare()))
545 546 547 548 549 550
      return res;
    if (owner->null_value)
      return -1;
  }
  return res;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
551

552 553
int Arg_comparator::compare_e_row()
{
554 555
  (*a)->bring_value();
  (*b)->bring_value();
556
  uint n= (*a)->cols();
557 558
  for (uint i= 0; i<n; i++)
  {
559
    if (!comparators[i].compare())
560
      return 0;
561 562 563 564
  }
  return 1;
}

565 566 567 568

bool Item_in_optimizer::fix_left(THD *thd,
				 struct st_table_list *tables,
				 Item **ref)
569
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
570 571
  if (!args[0]->fixed && args[0]->fix_fields(thd, tables, args) ||
      !cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
572
    return 1;
573

574
  cache->setup(args[0]);
575 576 577 578
  /*
    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.
  */
579
  if (! thd->current_arena->is_stmt_prepare())
580
    cache->store(args[0]);
581
  if (cache->cols() == 1)
582
  {
583
    if ((used_tables_cache= args[0]->used_tables()))
584
      cache->set_used_tables(OUTER_REF_TABLE_BIT);
585 586 587
    else
      cache->set_used_tables(0);
  }
588 589 590 591
  else
  {
    uint n= cache->cols();
    for (uint i= 0; i < n; i++)
592 593
    {
      if (args[0]->el(i)->used_tables())
594
	((Item_cache *)cache->el(i))->set_used_tables(OUTER_REF_TABLE_BIT);
595 596 597
      else
	((Item_cache *)cache->el(i))->set_used_tables(0);
    }
598
    used_tables_cache= args[0]->used_tables();
599
  }
600 601 602
  not_null_tables_cache= args[0]->not_null_tables();
  with_sum_func= args[0]->with_sum_func;
  const_item_cache= args[0]->const_item();
603 604 605 606 607 608 609
  return 0;
}


bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
				   Item ** ref)
{
610
  DBUG_ASSERT(fixed == 0);
611
  if (fix_left(thd, tables, ref))
612 613 614 615
    return 1;
  if (args[0]->maybe_null)
    maybe_null=1;

616
  if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
617 618 619 620
    return 1;
  Item_in_subselect * sub= (Item_in_subselect *)args[1];
  if (args[0]->cols() != sub->engine->cols())
  {
621
    my_error(ER_OPERAND_COLUMNS, MYF(0), args[0]->cols());
622
    return 1;
623
  }
624 625 626 627
  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();
628
  not_null_tables_cache|= args[1]->not_null_tables();
629
  const_item_cache&= args[1]->const_item();
630
  fixed= 1;
631 632 633
  return 0;
}

634

635 636
longlong Item_in_optimizer::val_int()
{
637
  DBUG_ASSERT(fixed == 1);
638 639
  cache->store(args[0]);
  if (cache->null_value)
640 641 642 643 644
  {
    null_value= 1;
    return 0;
  }
  longlong tmp= args[1]->val_int_result();
645
  null_value= args[1]->null_value;
646 647 648
  return tmp;
}

649 650 651 652 653 654 655 656

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


657 658 659 660
void Item_in_optimizer::cleanup()
{
  DBUG_ENTER("Item_in_optimizer::cleanup");
  Item_bool_func::cleanup();
661 662
  if (!save_cache)
    cache= 0;
663 664 665
  DBUG_VOID_RETURN;
}

666

667
bool Item_in_optimizer::is_null()
668
{
669 670
  cache->store(args[0]);
  return (null_value= (cache->null_value || args[1]->is_null()));
671
}
672

673

bk@work.mysql.com's avatar
bk@work.mysql.com committed
674 675
longlong Item_func_eq::val_int()
{
676
  DBUG_ASSERT(fixed == 1);
677
  int value= cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
678 679 680
  return value == 0 ? 1 : 0;
}

681

bk@work.mysql.com's avatar
bk@work.mysql.com committed
682 683
/* Same as Item_func_eq, but NULL = NULL */

monty@donna.mysql.com's avatar
monty@donna.mysql.com committed
684 685 686 687 688 689
void Item_func_equal::fix_length_and_dec()
{
  Item_bool_func2::fix_length_and_dec();
  maybe_null=null_value=0;
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
690 691
longlong Item_func_equal::val_int()
{
692
  DBUG_ASSERT(fixed == 1);
693
  return cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
694 695 696 697
}

longlong Item_func_ne::val_int()
{
698
  DBUG_ASSERT(fixed == 1);
699
  int value= cmp.compare();
700
  return value != 0 && !null_value ? 1 : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
701 702 703 704 705
}


longlong Item_func_ge::val_int()
{
706
  DBUG_ASSERT(fixed == 1);
707
  int value= cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
708 709 710 711 712 713
  return value >= 0 ? 1 : 0;
}


longlong Item_func_gt::val_int()
{
714
  DBUG_ASSERT(fixed == 1);
715
  int value= cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
716 717 718 719 720
  return value > 0 ? 1 : 0;
}

longlong Item_func_le::val_int()
{
721
  DBUG_ASSERT(fixed == 1);
722
  int value= cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
723 724 725 726 727 728
  return value <= 0 && !null_value ? 1 : 0;
}


longlong Item_func_lt::val_int()
{
729
  DBUG_ASSERT(fixed == 1);
730
  int value= cmp.compare();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
731 732 733 734 735 736
  return value < 0 && !null_value ? 1 : 0;
}


longlong Item_func_strcmp::val_int()
{
737
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
738 739 740 741 742 743 744
  String *a=args[0]->val_str(&tmp_value1);
  String *b=args[1]->val_str(&tmp_value2);
  if (!a || !b)
  {
    null_value=1;
    return 0;
  }
745
  int value= sortcmp(a,b,cmp.cmp_collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
746 747 748 749 750 751 752
  null_value=0;
  return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1);
}


void Item_func_interval::fix_length_and_dec()
{
753
  if (row->cols() > 8)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
754
  {
755 756 757
    bool consts=1;

    for (uint i=1 ; consts && i < row->cols() ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
758
    {
759
      consts&= row->el(i)->const_item();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
760
    }
761 762 763

    if (consts &&
        (intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
764
    {
765 766
      for (uint i=1 ; i < row->cols(); i++)
        intervals[i-1]=row->el(i)->val();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
767 768
    }
  }
769 770
  maybe_null= 0;
  max_length= 2;
771
  used_tables_cache|= row->used_tables();
serg@serg.mylan's avatar
serg@serg.mylan committed
772
  not_null_tables_cache= row->not_null_tables();
773
  with_sum_func= with_sum_func || row->with_sum_func;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
774
  const_item_cache&= row->const_item();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
775 776
}

monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
777

bk@work.mysql.com's avatar
bk@work.mysql.com committed
778 779 780
/*
  return -1 if null value,
	  0 if lower than lowest
781 782
	  1 - arg_count-1 if between args[n] and args[n+1]
	  arg_count if higher than biggest argument
bk@work.mysql.com's avatar
bk@work.mysql.com committed
783 784 785 786
*/

longlong Item_func_interval::val_int()
{
787
  DBUG_ASSERT(fixed == 1);
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
788 789 790
  double value= row->el(0)->val();
  uint i;

791 792
  if (row->el(0)->null_value)
    return -1;				// -1 if null
bk@work.mysql.com's avatar
bk@work.mysql.com committed
793 794 795
  if (intervals)
  {					// Use binary search to find interval
    uint start,end;
796
    start= 0;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
797
    end=   row->cols()-2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
798 799
    while (start != end)
    {
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
800
      uint mid= (start + end + 1) / 2;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
801
      if (intervals[mid] <= value)
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
802
	start= mid;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
803
      else
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
804
	end= mid - 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
805
    }
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
806
    return (value < intervals[start]) ? 0 : start + 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
807
  }
808 809

  for (i=1 ; i < row->cols() ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
810
  {
811 812
    if (row->el(i)->val() > value)
      return i-1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
813
  }
814
  return i-1;
815 816
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
817 818
void Item_func_between::fix_length_and_dec()
{
819
   max_length= 1;
820
   THD *thd= current_thd;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
821

822 823 824 825
  /*
    As some compare functions are generated after sql_yacc,
    we have to check for out of memory conditons here
  */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
826 827
  if (!args[0] || !args[1] || !args[2])
    return;
828
  agg_cmp_type(&cmp_type, args, 3);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
829
  if (cmp_type == STRING_RESULT &&
bar@mysql.com's avatar
bar@mysql.com committed
830
      agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV))
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
831
    return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
832

serg@sergbook.mysql.com's avatar
serg@sergbook.mysql.com committed
833 834 835 836 837
  /*
    Make a special case of compare with date/time and longlong fields.
    They are compared as integers, so for const item this time-consuming
    conversion can be done only once, not for every single comparison
  */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
838 839 840
  if (args[0]->type() == FIELD_ITEM)
  {
    Field *field=((Item_field*) args[0])->field;
841
    if (field->can_be_compared_as_longlong())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
842
    {
843 844 845 846
      /*
        The following can't be recoded with || as convert_constant_item
        changes the argument
      */
847
      if (convert_constant_item(thd, field,&args[1]))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
848
	cmp_type=INT_RESULT;			// Works for all types.
849
      if (convert_constant_item(thd, field,&args[2]))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
850 851 852 853 854 855 856 857
	cmp_type=INT_RESULT;			// Works for all types.
    }
  }
}


longlong Item_func_between::val_int()
{						// ANSI BETWEEN
858
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
859 860 861 862 863 864 865 866 867
  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)
868 869
      return (sortcmp(value,a,cmp_collation.collation) >= 0 && 
	      sortcmp(value,b,cmp_collation.collation) <= 0) ? 1 : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
870 871 872 873
    if (args[1]->null_value && args[2]->null_value)
      null_value=1;
    else if (args[1]->null_value)
    {
monty@mysql.com's avatar
monty@mysql.com committed
874 875
      // Set to not null if false range.
      null_value= sortcmp(value,b,cmp_collation.collation) <= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
876 877 878
    }
    else
    {
monty@mysql.com's avatar
monty@mysql.com committed
879 880
      // Set to not null if false range.
      null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
881 882 883 884 885 886
    }
  }
  else if (cmp_type == INT_RESULT)
  {
    longlong value=args[0]->val_int(),a,b;
    if ((null_value=args[0]->null_value))
887
      return 0;					/* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
    a=args[1]->val_int();
    b=args[2]->val_int();
    if (!args[1]->null_value && !args[2]->null_value)
      return (value >= a && value <= b) ? 1 : 0;
    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))
907
      return 0;					/* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
    a=args[1]->val();
    b=args[2]->val();
    if (!args[1]->null_value && !args[2]->null_value)
      return (value >= a && value <= b) ? 1 : 0;
    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;
    }
  }
  return 0;
}

926 927 928 929 930

void Item_func_between::print(String *str)
{
  str->append('(');
  args[0]->print(str);
931
  str->append(" between ", 9);
932
  args[1]->print(str);
933
  str->append(" and ", 5);
934 935 936 937
  args[2]->print(str);
  str->append(')');
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
938 939 940 941 942 943
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);
944
  agg_result_type(&cached_result_type, args, 2);
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
945
  if (cached_result_type == STRING_RESULT)
bar@mysql.com's avatar
bar@mysql.com committed
946
    agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
947 948
  else if (cached_result_type != REAL_RESULT)
    decimals= 0;
949 950 951 952
  
  cached_field_type= args[0]->field_type();
  if (cached_field_type != args[1]->field_type())
    cached_field_type= Item_func::field_type();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
953 954
}

955 956 957
enum_field_types Item_func_ifnull::field_type() const 
{
  return cached_field_type;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
958 959
}

960 961 962 963
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
{
  return tmp_table_field_from_field_type(table);
}
964

bk@work.mysql.com's avatar
bk@work.mysql.com committed
965 966 967
double
Item_func_ifnull::val()
{
968
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
  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()
{
984
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
985 986 987 988 989 990 991 992 993 994 995 996 997 998 999
  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)
{
1000
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1001 1002 1003 1004
  String *res  =args[0]->val_str(str);
  if (!args[0]->null_value)
  {
    null_value=0;
1005
    res->set_charset(collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1006 1007 1008 1009 1010
    return res;
  }
  res=args[1]->val_str(str);
  if ((null_value=args[1]->null_value))
    return 0;
1011
  res->set_charset(collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1012 1013 1014
  return res;
}

1015

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1016 1017 1018 1019 1020
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);
1021
  decimals=max(args[1]->decimals,args[2]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1022 1023
  enum Item_result arg1_type=args[1]->result_type();
  enum Item_result arg2_type=args[2]->result_type();
1024 1025
  bool null1=args[1]->const_item() && args[1]->null_value;
  bool null2=args[2]->const_item() && args[2]->null_value;
1026 1027 1028 1029

  if (null1)
  {
    cached_result_type= arg2_type;
1030
    collation.set(args[2]->collation.collation);
1031 1032 1033
  }
  else if (null2)
  {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1034
    cached_result_type= arg1_type;
1035
    collation.set(args[1]->collation.collation);
1036
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1037
  else
1038
  {
1039 1040 1041
    agg_result_type(&cached_result_type, args+1, 2);
    if (cached_result_type == STRING_RESULT)
    {
bar@mysql.com's avatar
bar@mysql.com committed
1042
      if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV))
1043 1044
      return;
    }
1045
    else
1046
    {
1047
      collation.set(&my_charset_bin);	// Number
1048
    }
1049
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1050 1051 1052 1053 1054 1055
}


double
Item_func_if::val()
{
1056
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1057 1058 1059 1060 1061 1062 1063 1064 1065
  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()
{
1066
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1067 1068 1069 1070 1071 1072 1073 1074 1075
  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)
{
1076
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1077 1078
  Item *arg= args[0]->val_int() ? args[1] : args[2];
  String *res=arg->val_str(str);
1079
  if (res)
1080
    res->set_charset(collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
  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;
1095
    agg_result_type(&cached_result_type, args, 2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1096 1097 1098 1099
  }
}

/*
1100
  nullif () returns NULL if arguments are equal, else it returns the
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1101 1102 1103 1104 1105 1106 1107 1108
  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()
{
1109
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1110
  double value;
monty@mysql.com's avatar
monty@mysql.com committed
1111
  if (!cmp.compare())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
  {
    null_value=1;
    return 0.0;
  }
  value=args[0]->val();
  null_value=args[0]->null_value;
  return value;
}

longlong
Item_func_nullif::val_int()
{
1124
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1125
  longlong value;
monty@mysql.com's avatar
monty@mysql.com committed
1126
  if (!cmp.compare())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
  {
    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)
{
1139
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1140
  String *res;
monty@mysql.com's avatar
monty@mysql.com committed
1141
  if (!cmp.compare())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1142 1143 1144 1145 1146 1147 1148 1149 1150
  {
    null_value=1;
    return 0;
  }
  res=args[0]->val_str(str);
  null_value=args[0]->null_value;
  return res;
}

1151 1152 1153 1154

bool
Item_func_nullif::is_null()
{
monty@mysql.com's avatar
monty@mysql.com committed
1155 1156
  if (!cmp.compare())
    return (null_value=1);
1157 1158 1159
  return 0;
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1160
/*
1161 1162
  CASE expression 
  Return the matching ITEM or NULL if all compares (including else) failed
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1163 1164 1165 1166 1167 1168 1169
*/

Item *Item_func_case::find_item(String *str)
{
  String *first_expr_str,*tmp;
  longlong first_expr_int;
  double   first_expr_real;
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1170
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1171 1172 1173 1174 1175
  /* These will be initialized later */
  LINT_INIT(first_expr_str);
  LINT_INIT(first_expr_int);
  LINT_INIT(first_expr_real);

bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
  if (first_expr_num != -1)
  {
    switch (cmp_type)
    {
      case STRING_RESULT:
      	// We can't use 'str' here as this may be overwritten
	if (!(first_expr_str= args[first_expr_num]->val_str(&str_value)))
	  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;
    }
  }

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1203
  // Compare every WHEN argument with it and return the first match
1204
  for (uint i=0 ; i < ncases ; i+=2)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1205
  {
1206
    if (first_expr_num == -1)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1207
    {
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1208
      // No expression between CASE and the first WHEN
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1209 1210 1211 1212
      if (args[i]->val_int())
	return args[i+1];
      continue;
    }
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1213
    switch (cmp_type) {
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1214 1215
    case STRING_RESULT:
      if ((tmp=args[i]->val_str(str)))		// If not null
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1216
	if (sortcmp(tmp,first_expr_str,cmp_collation.collation)==0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1217 1218 1219 1220 1221 1222 1223 1224 1225
	  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];
1226
      break;
1227
    case ROW_RESULT:
1228
    default:
1229 1230 1231
      // This case should never be choosen
      DBUG_ASSERT(0);
      break;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1232 1233 1234
    }
  }
  // No, WHEN clauses all missed, return ELSE expression
1235
  return else_expr_num != -1 ? args[else_expr_num] : 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1236 1237 1238 1239 1240 1241
}



String *Item_func_case::val_str(String *str)
{
1242
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1243 1244 1245 1246 1247 1248 1249 1250
  String *res;
  Item *item=find_item(str);

  if (!item)
  {
    null_value=1;
    return 0;
  }
1251
  null_value= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1252
  if (!(res=item->val_str(str)))
1253
    null_value= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1254 1255 1256 1257 1258 1259
  return res;
}


longlong Item_func_case::val_int()
{
1260
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1261
  char buff[MAX_FIELD_WIDTH];
1262
  String dummy_str(buff,sizeof(buff),default_charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
  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()
{
1278
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1279
  char buff[MAX_FIELD_WIDTH];
1280
  String dummy_str(buff,sizeof(buff),default_charset());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
  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()
1295
{
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
  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) &&
bar@mysql.com's avatar
bar@mysql.com committed
1313
      agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV))
1314 1315 1316
    return;
  
  
1317 1318 1319 1320
  /*
    Aggregate first expression and all THEN expression types
    and collations when string comparison
  */
1321
  if (first_expr_num != -1)
1322
  {
1323 1324
    agg[0]= args[first_expr_num];
    for (nagg= 0; nagg < ncases/2 ; nagg++)
bar@bar.mysql.r18.ru's avatar
bar@bar.mysql.r18.ru committed
1325
      agg[nagg+1]= args[nagg*2];
1326 1327 1328
    nagg++;
    agg_cmp_type(&cmp_type, agg, nagg);
    if ((cmp_type == STRING_RESULT) &&
bar@mysql.com's avatar
bar@mysql.com committed
1329
        agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
1330
    return;
1331
  }
1332
  
1333
  if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
1334
    maybe_null=1;
1335
  
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1336 1337
  max_length=0;
  decimals=0;
1338
  for (uint i=0 ; i < ncases ; i+=2)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1339 1340 1341 1342
  {
    set_if_bigger(max_length,args[i+1]->max_length);
    set_if_bigger(decimals,args[i+1]->decimals);
  }
1343
  if (else_expr_num != -1) 
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1344
  {
1345 1346
    set_if_bigger(max_length,args[else_expr_num]->max_length);
    set_if_bigger(decimals,args[else_expr_num]->decimals);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1347 1348 1349
  }
}

1350

1351
/* TODO:  Fix this so that it prints the whole CASE expression */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1352 1353 1354

void Item_func_case::print(String *str)
{
1355
  str->append("(case ", 6);
1356 1357 1358 1359 1360 1361 1362
  if (first_expr_num != -1)
  {
    args[first_expr_num]->print(str);
    str->append(' ');
  }
  for (uint i=0 ; i < ncases ; i+=2)
  {
1363
    str->append("when ", 5);
1364
    args[i]->print(str);
1365
    str->append(" then ", 6);
1366 1367 1368 1369 1370
    args[i+1]->print(str);
    str->append(' ');
  }
  if (else_expr_num != -1)
  {
1371
    str->append("else ", 5);
1372 1373 1374
    args[else_expr_num]->print(str);
    str->append(' ');
  }
1375
  str->append("end)", 4);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1376 1377 1378
}

/*
1379
  Coalesce - return first not NULL argument.
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1380 1381 1382 1383
*/

String *Item_func_coalesce::val_str(String *str)
{
1384
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1385 1386 1387
  null_value=0;
  for (uint i=0 ; i < arg_count ; i++)
  {
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
1388 1389 1390
    String *res;
    if ((res=args[i]->val_str(str)))
      return res;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1391 1392 1393 1394 1395 1396 1397
  }
  null_value=1;
  return 0;
}

longlong Item_func_coalesce::val_int()
{
1398
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
  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()
{
1412
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
  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()
{
1427 1428
  max_length= 0;
  decimals= 0;
1429
  agg_result_type(&cached_result_type, args, arg_count);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1430 1431 1432 1433 1434
  for (uint i=0 ; i < arg_count ; i++)
  {
    set_if_bigger(max_length,args[i]->max_length);
    set_if_bigger(decimals,args[i]->decimals);
  }
1435
  if (cached_result_type == STRING_RESULT)
bar@mysql.com's avatar
bar@mysql.com committed
1436
    agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV);
1437 1438
  else if (cached_result_type != REAL_RESULT)
    decimals= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1439 1440 1441
}

/****************************************************************************
1442
 Classes and function for the IN operator
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1443 1444
****************************************************************************/

1445
static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1446 1447 1448 1449
{
  return *a < *b ? -1 : *a == *b ? 0 : 1;
}

1450
static int cmp_double(void *cmp_arg, double *a,double *b)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1451 1452 1453 1454
{
  return *a < *b ? -1 : *a == *b ? 0 : 1;
}

1455
static int cmp_row(void *cmp_arg, cmp_item_row* a, cmp_item_row* b)
1456 1457 1458 1459
{
  return a->compare(b);
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
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;
1472
    if ((res=(*compare)(collation, base+mid*size, result)) == 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1473 1474 1475 1476 1477 1478
      return 1;
    if (res < 0)
      start=mid;
    else
      end=mid-1;
  }
1479
  return (int) ((*compare)(collation, base+start*size, result) == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1480 1481
}

1482 1483
in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs)
  :in_vector(elements, sizeof(String), cmp_func, cs),
1484
   tmp(buff, sizeof(buff), &my_charset_bin)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1485 1486 1487 1488
{}

in_string::~in_string()
{
1489
  if (base)
1490
  {
1491
    // base was allocated with help of sql_alloc => following is OK
1492 1493
    for (uint i=0 ; i < count ; i++)
      ((String*) base)[i].free();
1494
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1495 1496 1497 1498 1499 1500 1501 1502
}

void in_string::set(uint pos,Item *item)
{
  String *str=((String*) base)+pos;
  String *res=item->val_str(str);
  if (res && res != str)
    *str= *res;
1503
  if (!str->charset())
1504 1505
  {
    CHARSET_INFO *cs;
1506
    if (!(cs= item->collation.collation))
1507
      cs= &my_charset_bin;		// Should never happen for STR items
1508 1509
    str->set_charset(cs);
  }
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1510 1511
}

1512

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1513 1514 1515 1516 1517
byte *in_string::get_value(Item *item)
{
  return (byte*) item->val_str(&tmp);
}

1518 1519
in_row::in_row(uint elements, Item * item)
{
1520
  base= (char*) new cmp_item_row[count= elements];
1521
  size= sizeof(cmp_item_row);
1522
  compare= (qsort2_cmp) cmp_row;
1523
  tmp.store_value(item);
1524 1525 1526 1527 1528
}

in_row::~in_row()
{
  if (base)
1529
    delete [] (cmp_item_row*) base;
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
}

byte *in_row::get_value(Item *item)
{
  tmp.store_value(item);
  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;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1545 1546

in_longlong::in_longlong(uint elements)
1547
  :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1548 1549 1550 1551 1552 1553 1554 1555 1556
{}

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

byte *in_longlong::get_value(Item *item)
{
1557
  tmp= item->val_int();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1558
  if (item->null_value)
1559
    return 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1560 1561 1562 1563
  return (byte*) &tmp;
}

in_double::in_double(uint elements)
1564
  :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1565 1566 1567 1568 1569 1570 1571 1572 1573
{}

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

byte *in_double::get_value(Item *item)
{
1574
  tmp= item->val();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1575
  if (item->null_value)
1576
    return 0;					/* purecov: inspected */
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1577 1578 1579
  return (byte*) &tmp;
}

1580
cmp_item* cmp_item::get_comparator(Item *item)
1581 1582 1583
{
  switch (item->result_type()) {
  case STRING_RESULT:
1584
    return new cmp_item_sort_string(item->collation.collation);
1585 1586 1587 1588 1589 1590
  case INT_RESULT:
    return new cmp_item_int;
  case REAL_RESULT:
    return new cmp_item_real;
  case ROW_RESULT:
    return new cmp_item_row;
1591 1592 1593
  default:
    DBUG_ASSERT(0);
    break;
1594 1595 1596 1597
  }
  return 0; // to satisfy compiler :)
}

1598

1599 1600
cmp_item* cmp_item_sort_string::make_same()
{
1601
  return new cmp_item_sort_string_in_static(cmp_charset);
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
}

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

1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635

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


1636 1637
void cmp_item_row::store_value(Item *item)
{
1638
  DBUG_ENTER("cmp_item_row::store_value");
1639
  n= item->cols();
1640
  if (!comparators)
1641
    comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n);
1642
  if (comparators)
1643
  {
1644
    item->bring_value();
1645
    item->null_value= 0;
1646
    for (uint i=0; i < n; i++)
1647
    {
1648 1649 1650
      if (!comparators[i])
	if (!(comparators[i]= cmp_item::get_comparator(item->el(i))))
	  break;					// new failed
1651 1652 1653
      comparators[i]->store_value(item->el(i));
      item->null_value|= item->el(i)->null_value;
    }
1654
  }
1655
  DBUG_VOID_RETURN;
1656 1657
}

1658

1659 1660 1661 1662 1663
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())
  {
1664
    my_error(ER_OPERAND_COLUMNS, MYF(0), tmpl->n);
1665 1666 1667 1668 1669
    return;
  }
  n= tmpl->n;
  if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
  {
1670
    item->bring_value();
1671 1672
    item->null_value= 0;
    for (uint i=0; i < n; i++)
1673 1674 1675 1676 1677 1678 1679
    {
      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;
    }
1680 1681 1682
  }
}

1683

1684 1685
int cmp_item_row::cmp(Item *arg)
{
1686 1687 1688
  arg->null_value= 0;
  if (arg->cols() != n)
  {
1689
    my_error(ER_OPERAND_COLUMNS, MYF(0), n);
1690 1691
    return 1;
  }
1692
  bool was_null= 0;
1693
  arg->bring_value();
1694
  for (uint i=0; i < n; i++)
1695
  {
1696
    if (comparators[i]->cmp(arg->el(i)))
1697
    {
1698 1699 1700
      if (!arg->el(i)->null_value)
	return 1;
      was_null= 1;
1701
    }
1702
  }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1703
  return (arg->null_value= was_null);
1704 1705
}

1706

1707 1708 1709
int cmp_item_row::compare(cmp_item *c)
{
  cmp_item_row *cmp= (cmp_item_row *) c;
1710
  for (uint i=0; i < n; i++)
1711 1712
  {
    int res;
1713
    if ((res= comparators[i]->compare(cmp->comparators[i])))
1714
      return res;
1715
  }
1716 1717
  return 0;
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1718

1719

1720 1721 1722
bool Item_func_in::nulls_in_row()
{
  Item **arg,**arg_end;
1723
  for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++)
1724 1725 1726 1727 1728 1729 1730
  {
    if ((*arg)->null_inside())
      return 1;
  }
  return 0;
}

1731

1732
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
1733
{
1734
  return cs->coll->strnncollsp(cs,
monty@mysql.com's avatar
monty@mysql.com committed
1735 1736
                               (uchar *) x->ptr(),x->length(),
                               (uchar *) y->ptr(),y->length());
1737 1738
}

1739

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1740 1741
void Item_func_in::fix_length_and_dec()
{
1742 1743
  Item **arg, **arg_end;
  uint const_itm= 1;
1744
  THD *thd= current_thd;
1745
  
1746
  agg_cmp_type(&cmp_type, args, arg_count);
1747

1748 1749
  for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
    const_itm&= arg[0]->const_item();
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765


  if (cmp_type == STRING_RESULT)
  {
    /*
      We allow consts character set conversion for

        item IN (const1, const2, const3, ...)

      if item is in a superset for all arguments,
      and if it is a stong side according to coercibility rules.
   
      TODO: add covnersion for non-constant IN values
      via creating Item_func_conv_charset().
    */

1766 1767
    if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count,
                                          MY_COLL_ALLOW_SUPERSET_CONV))
1768 1769 1770 1771
      return;
    if ((!my_charset_same(args[0]->collation.collation, 
                          cmp_collation.collation) || !const_itm))
    {
1772
      if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count))
1773 1774 1775 1776 1777 1778 1779 1780
        return;
    }
    else
    {
      /* 
         Conversion is possible:
         All IN arguments are constants.
      */
1781 1782 1783
      Item_arena *arena, backup;
      arena= thd->change_arena_if_needed(&backup);

1784 1785
      for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++)
      {
1786 1787
        if (!arg[0]->null_value &&
            !my_charset_same(cmp_collation.collation,
1788 1789 1790 1791
                             arg[0]->collation.collation))
        {
          Item_string *conv;
          String tmp, cstr, *ostr= arg[0]->val_str(&tmp);
1792
          uint dummy_errors;
1793
          cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
1794
                    cmp_collation.collation, &dummy_errors);
1795 1796 1797 1798 1799 1800
          conv= new Item_string(cstr.ptr(),cstr.length(), cstr.charset(),
                                arg[0]->collation.derivation);
          conv->str_value.copy();
          arg[0]= conv;
        }
      }
1801
      if (arena)
1802
        thd->restore_backup_item_arena(arena, &backup);
1803 1804
    }
  }
1805
  
1806 1807 1808 1809
  /*
    Row item with NULLs inside can return NULL or FALSE => 
    they can't be processed as static
  */
1810
  if (const_itm && !nulls_in_row())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1811
  {
1812
    switch (cmp_type) {
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1813
    case STRING_RESULT:
1814
      array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in, 
1815
			  cmp_collation.collation);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1816 1817
      break;
    case INT_RESULT:
1818
      array= new in_longlong(arg_count-1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1819 1820
      break;
    case REAL_RESULT:
1821
      array= new in_double(arg_count-1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1822
      break;
1823
    case ROW_RESULT:
1824
      array= new in_row(arg_count-1, args[0]);
1825
      break;
1826 1827 1828
    default:
      DBUG_ASSERT(0);
      return;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1829
    }
1830
    if (array && !(thd->is_fatal_error))		// If not EOM
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1831
    {
1832
      uint j=0;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1833
      for (uint i=1 ; i < arg_count ; i++)
1834 1835 1836 1837
      {
	array->set(j,args[i]);
	if (!args[i]->null_value)			// Skip NULL values
	  j++;
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
1838 1839
	else
	  have_null= 1;
1840 1841 1842
      }
      if ((array->used_count=j))
	array->sort();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1843 1844 1845 1846
    }
  }
  else
  {
1847
    in_item= cmp_item::get_comparator(args[0]);
1848
    if (cmp_type  == STRING_RESULT)
1849
      in_item->cmp_charset= cmp_collation.collation;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1850
  }
1851
  maybe_null= args[0]->maybe_null;
1852
  max_length= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1853 1854 1855 1856 1857 1858
}


void Item_func_in::print(String *str)
{
  str->append('(');
1859
  args[0]->print(str);
1860
  str->append(" in (", 5);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
1861
  print_args(str, 1);
1862
  str->append("))", 2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1863 1864 1865 1866 1867
}


longlong Item_func_in::val_int()
{
1868
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1869 1870
  if (array)
  {
1871 1872
    int tmp=array->find(args[0]);
    null_value=args[0]->null_value || (!tmp && have_null);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1873 1874
    return tmp;
  }
1875 1876
  in_item->store_value(args[0]);
  if ((null_value=args[0]->null_value))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1877
    return 0;
1878
  have_null= 0;
1879
  for (uint i=1 ; i < arg_count ; i++)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1880 1881 1882
  {
    if (!in_item->cmp(args[i]) && !args[i]->null_value)
      return 1;					// Would maybe be nice with i ?
1883
    have_null|= args[i]->null_value;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1884
  }
1885
  null_value= have_null;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1886 1887 1888 1889 1890 1891
  return 0;
}


longlong Item_func_bit_or::val_int()
{
1892
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911
  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()
{
1912
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928
  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);
}

1929
Item_cond::Item_cond(THD *thd, Item_cond *item)
1930
  :Item_bool_func(thd, item),
1931 1932
   abort_on_null(item->abort_on_null),
   and_tables_cache(item->and_tables_cache)
1933 1934
{
  /*
monty@mysql.com's avatar
monty@mysql.com committed
1935
    item->list will be copied by copy_andor_arguments() call
1936 1937 1938
  */
}

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

1940 1941 1942
void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item)
{
  List_iterator_fast<Item> li(item->list);
monty@mysql.com's avatar
monty@mysql.com committed
1943
  while (Item *it= li++)
1944 1945
    list.push_back(it->copy_andor_structure(thd));
}
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1946

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

bk@work.mysql.com's avatar
bk@work.mysql.com committed
1948
bool
1949
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1950
{
1951
  DBUG_ASSERT(fixed == 0);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1952 1953
  List_iterator<Item> li(list);
  Item *item;
1954
#ifndef EMBEDDED_LIBRARY
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1955
  char buff[sizeof(char*)];			// Max local vars in function
1956
#endif
1957 1958
  not_null_tables_cache= used_tables_cache= 0;
  const_item_cache= 0;
1959 1960 1961 1962 1963
  /*
    and_table_cache is the value that Item_cond_or() returns for
    not_null_tables()
  */
  and_tables_cache= ~(table_map) 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1964

1965
  if (check_stack_overrun(thd, buff))
1966
    return 1;					// Fatal error flag is set!
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1967 1968
  while ((item=li++))
  {
1969
    table_map tmp_table_map;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1970 1971 1972 1973 1974 1975 1976
    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
    }
1977 1978
    if (abort_on_null)
      item->top_level_item();
1979 1980

    // item can be substituted in fix_fields
1981
    if ((!item->fixed &&
1982 1983
	 item->fix_fields(thd, tables, li.ref())) ||
	(item= *li.ref())->check_cols(1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1984
      return 1; /* purecov: inspected */
1985 1986 1987 1988 1989 1990
    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;
1991 1992
    if (item->maybe_null)
      maybe_null=1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1993
  }
1994
  thd->lex->current_select->cond_count+= list.elements;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1995
  fix_length_and_dec();
1996
  fixed= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
1997 1998 1999
  return 0;
}

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
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);
}

2010 2011
void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
                               List<Item> &fields)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2012 2013 2014 2015 2016 2017 2018 2019
{
  List_iterator<Item> li(list);
  Item *item;
  used_tables_cache=0;
  const_item_cache=0;
  while ((item=li++))
  {
    if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
2020
      item->split_sum_func(thd, ref_pointer_array, fields);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2021 2022
    else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
    {
2023
      Item **ref= li.ref();
2024
      uint el= fields.elements;
2025
      Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2026
      fields.push_front(item);
2027
      ref_pointer_array[el]= item;
2028
      thd->change_item_tree(ref, new_item);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042
    }
    item->update_used_tables();
    used_tables_cache|=item->used_tables();
    const_item_cache&=item->const_item();
  }
}


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

2043

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2044 2045
void Item_cond::update_used_tables()
{
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2046
  List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2047
  Item *item;
2048 2049 2050

  used_tables_cache=0;
  const_item_cache=1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2051 2052 2053
  while ((item=li++))
  {
    item->update_used_tables();
2054 2055
    used_tables_cache|= item->used_tables();
    const_item_cache&=  item->const_item();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2056 2057 2058 2059 2060 2061 2062
  }
}


void Item_cond::print(String *str)
{
  str->append('(');
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2063
  List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076
  Item *item;
  if ((item=li++))
    item->print(str);
  while ((item=li++))
  {
    str->append(' ');
    str->append(func_name());
    str->append(' ');
    item->print(str);
  }
  str->append(')');
}

2077

2078
void Item_cond::neg_arguments(THD *thd)
2079 2080 2081 2082 2083
{
  List_iterator<Item> li(list);
  Item *item;
  while ((item= li++))		/* Apply not transformation to the arguments */
  {
2084 2085 2086
    Item *new_item= item->neg_transformer(thd);
    if (!new_item)
    {
monty@mysql.com's avatar
monty@mysql.com committed
2087 2088
      if (!(new_item= new Item_func_not(item)))
	return;					// Fatal OEM error
2089 2090
    }
    VOID(li.replace(new_item));
2091 2092 2093 2094
  }
}


2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111
/*
  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
*/

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2112 2113 2114

longlong Item_cond_and::val_int()
{
2115
  DBUG_ASSERT(fixed == 1);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2116
  List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2117
  Item *item;
2118
  null_value= 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2119 2120 2121 2122
  while ((item=li++))
  {
    if (item->val_int() == 0)
    {
2123 2124
      if (abort_on_null || !(null_value= item->null_value))
	return 0;				// return FALSE
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2125 2126
    }
  }
2127
  return null_value ? 0 : 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2128 2129
}

2130

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2131 2132
longlong Item_cond_or::val_int()
{
2133
  DBUG_ASSERT(fixed == 1);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2134
  List_iterator_fast<Item> li(list);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
  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;
}

2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
/*
  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)
2174
    return (*org_item= (Item*) b);
2175 2176 2177
  if (a == *org_item)
  {
    Item_cond *res;
2178
    if ((res= new Item_cond_and(a, (Item*) b)))
2179
    {
2180
      res->used_tables_cache= a->used_tables() | b->used_tables();
2181 2182
      res->not_null_tables_cache= a->not_null_tables() | b->not_null_tables();
    }
2183 2184
    return res;
  }
2185
  if (((Item_cond_and*) a)->add((Item*) b))
2186 2187
    return 0;
  ((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
2188
  ((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables();
2189 2190 2191 2192
  return a;
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2193 2194
longlong Item_func_isnull::val_int()
{
2195
  DBUG_ASSERT(fixed == 1);
2196 2197 2198 2199 2200
  /*
    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)
monty@hundin.mysql.fi's avatar
monty@hundin.mysql.fi committed
2201
    return cached_value;
2202
  return args[0]->is_null() ? 1: 0;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2203 2204
}

2205 2206
longlong Item_is_not_null_test::val_int()
{
2207
  DBUG_ASSERT(fixed == 1);
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242
  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();
    }
  }
}
2243

2244

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2245 2246
longlong Item_func_isnotnull::val_int()
{
2247
  DBUG_ASSERT(fixed == 1);
2248
  return args[0]->is_null() ? 0 : 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2249 2250 2251
}


2252 2253 2254 2255
void Item_func_isnotnull::print(String *str)
{
  str->append('(');
  args[0]->print(str);
2256
  str->append(" is not null)", 13);
2257 2258 2259
}


bk@work.mysql.com's avatar
bk@work.mysql.com committed
2260 2261
longlong Item_func_like::val_int()
{
2262
  DBUG_ASSERT(fixed == 1);
2263
  String* res = args[0]->val_str(&tmp_value1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2264 2265 2266 2267 2268
  if (args[0]->null_value)
  {
    null_value=1;
    return 0;
  }
2269
  String* res2 = args[1]->val_str(&tmp_value2);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2270 2271 2272 2273 2274 2275
  if (args[1]->null_value)
  {
    null_value=1;
    return 0;
  }
  null_value=0;
2276 2277
  if (canDoTurboBM)
    return turboBM_matches(res->ptr(), res->length()) ? 1 : 0;
2278
  return my_wildcmp(cmp.cmp_collation.collation,
2279 2280 2281
		    res->ptr(),res->ptr()+res->length(),
		    res2->ptr(),res2->ptr()+res2->length(),
		    escape,wild_one,wild_many) ? 0 : 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2282 2283 2284 2285 2286 2287 2288
}


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

Item_func::optimize_type Item_func_like::select_optimize() const
{
2289
  if (args[1]->const_item())
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2290
  {
2291 2292 2293 2294 2295 2296
    String* res2= args[1]->val_str((String *)&tmp_value2);

    if (!res2)
      return OPTIMIZE_NONE;

    if (*res2->ptr() != wild_many)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2297
    {
2298
      if (args[0]->result_type() != STRING_RESULT || *res2->ptr() != wild_one)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2299 2300 2301 2302 2303 2304
	return OPTIMIZE_OP;
    }
  }
  return OPTIMIZE_NONE;
}

2305

2306
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
2307
{
2308
  DBUG_ASSERT(fixed == 0);
2309 2310
  if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
      escape_item->fix_fields(thd, tlist, &escape_item))
2311 2312
    return 1;

2313
  if (!escape_item->const_during_execution())
2314
  {
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324
    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);
    escape= escape_str ? *(escape_str->ptr()) : '\\';
 
2325
    /*
2326 2327
      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.
2328
    */
2329 2330
    if (args[1]->const_item() && !use_strnxfrm(collation.collation) &&
       !(specialflag & SPECIAL_NO_NEW_FUNC))
2331
    {
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364
      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"));
      }
2365 2366 2367 2368 2369
    }
  }
  return 0;
}

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2370 2371 2372
#ifdef USE_REGEX

bool
2373
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2374
{
2375
  DBUG_ASSERT(fixed == 0);
2376 2377
  if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
      args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2378 2379
    return 1;					/* purecov: inspected */
  with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
2380 2381
  max_length= 1;
  decimals= 0;
2382

bar@mysql.com's avatar
bar@mysql.com committed
2383
  if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV))
2384
    return 1;
2385

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2386
  used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
2387 2388
  not_null_tables_cache= (args[0]->not_null_tables() |
			  args[1]->not_null_tables());
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2389 2390 2391 2392
  const_item_cache=args[0]->const_item() && args[1]->const_item();
  if (!regex_compiled && args[1]->const_item())
  {
    char buff[MAX_FIELD_WIDTH];
2393
    String tmp(buff,sizeof(buff),&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2394 2395 2396 2397 2398 2399 2400
    String *res=args[1]->val_str(&tmp);
    if (args[1]->null_value)
    {						// Will always return NULL
      maybe_null=1;
      return 0;
    }
    int error;
2401
    if ((error= regcomp(&preg,res->c_ptr(),
2402 2403
                        ((cmp_collation.collation->state &
                          (MY_CS_BINSORT | MY_CS_CSSORT)) ?
2404
                         REG_EXTENDED | REG_NOSUB :
2405
                         REG_EXTENDED | REG_NOSUB | REG_ICASE),
2406
                        cmp_collation.collation)))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2407 2408 2409 2410 2411 2412 2413 2414 2415 2416
    {
      (void) regerror(error,&preg,buff,sizeof(buff));
      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;
2417
  fixed= 1;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2418 2419 2420
  return 0;
}

2421

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2422 2423
longlong Item_func_regex::val_int()
{
2424
  DBUG_ASSERT(fixed == 1);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2425
  char buff[MAX_FIELD_WIDTH];
2426
  String *res, tmp(buff,sizeof(buff),&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436

  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];
2437
    String *res2, tmp2(buff2,sizeof(buff2),&my_charset_bin);
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2438 2439 2440 2441 2442 2443 2444

    res2= args[1]->val_str(&tmp2);
    if (args[1]->null_value)
    {
      null_value=1;
      return 0;
    }
monty@mysql.com's avatar
monty@mysql.com committed
2445
    if (!regex_compiled || stringcmp(res2,&prev_regexp))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2446 2447 2448 2449 2450 2451 2452 2453
    {
      prev_regexp.copy(*res2);
      if (regex_compiled)
      {
	regfree(&preg);
	regex_compiled=0;
      }
      if (regcomp(&preg,res2->c_ptr(),
2454 2455
                  ((cmp_collation.collation->state &
                    (MY_CS_BINSORT | MY_CS_CSSORT)) ?
2456
                   REG_EXTENDED | REG_NOSUB :
2457
                   REG_EXTENDED | REG_NOSUB | REG_ICASE),
2458
                   cmp_collation.collation))
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470
      {
	null_value=1;
	return 0;
      }
      regex_compiled=1;
    }
  }
  null_value=0;
  return regexec(&preg,res->c_ptr(),0,(regmatch_t*) 0,0) ? 0 : 1;
}


2471
void Item_func_regex::cleanup()
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2472
{
2473 2474
  DBUG_ENTER("Item_func_regex::cleanup");
  Item_bool_func::cleanup();
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2475 2476 2477 2478 2479
  if (regex_compiled)
  {
    regfree(&preg);
    regex_compiled=0;
  }
2480
  DBUG_VOID_RETURN;
bk@work.mysql.com's avatar
bk@work.mysql.com committed
2481 2482
}

2483

bk@work.mysql.com's avatar
bk@work.mysql.com committed
2484
#endif /* USE_REGEX */
2485 2486 2487


#ifdef LIKE_CMP_TOUPPER
2488
#define likeconv(cs,A) (uchar) (cs)->toupper(A)
2489
#else
2490
#define likeconv(cs,A) (uchar) (cs)->sort_order[(uchar) (A)]
2491 2492 2493 2494 2495 2496 2497 2498
#endif


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

2499
void Item_func_like::turboBM_compute_suffixes(int *suff)
2500 2501 2502 2503
{
  const int   plm1 = pattern_len - 1;
  int            f = 0;
  int            g = plm1;
2504
  int *const splm1 = suff + plm1;
2505
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
2506 2507 2508

  *splm1 = pattern_len;

bar@mysql.com's avatar
bar@mysql.com committed
2509
  if (!cs->sort_order)
2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540
  {
    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;
2541
	while (g >= 0 &&
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2542
	       likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f]))
2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555
	  g--;
	suff[i] = f - g;
      }
    }
  }
}


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

2556
void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff)
2557 2558 2559
{
  turboBM_compute_suffixes(suff);

2560 2561
  int *end = bmGs + pattern_len;
  int *k;
2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574
  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++)
      {
2575
	int *tmp2 = bmGs + j;
2576 2577 2578 2579 2580 2581
	if (*tmp2 == pattern_len)
	  *tmp2 = tmp;
      }
    }
  }

2582
  int *tmp2;
2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602
  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()
{
2603 2604 2605 2606
  int *i;
  int *end = bmBc + alphabet_size;
  int j;
  const int plm1 = pattern_len - 1;
2607
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
2608

2609 2610 2611
  for (i = bmBc; i < end; i++)
    *i = pattern_len;

bar@mysql.com's avatar
bar@mysql.com committed
2612
  if (!cs->sort_order)
2613
  {
2614
    for (j = 0; j < plm1; j++)
2615
      bmBc[(uint) (uchar) pattern[j]] = plm1 - j;
2616
  }
2617
  else
2618
  {
2619
    for (j = 0; j < plm1; j++)
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2620
      bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j;
2621
  }
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636
}


/**********************************************************************
  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;
2637
  CHARSET_INFO	*cs= cmp.cmp_collation.collation;
2638

2639 2640
  const int plm1=  pattern_len - 1;
  const int tlmpl= text_len - pattern_len;
2641 2642

  /* Searching */
bar@mysql.com's avatar
bar@mysql.com committed
2643
  if (!cs->sort_order)
2644 2645 2646
  {
    while (j <= tlmpl)
    {
2647
      register int i= plm1;
2648 2649 2650 2651
      while (i >= 0 && pattern[i] == text[i + j])
      {
	i--;
	if (i == plm1 - shift)
2652
	  i-= u;
2653 2654
      }
      if (i < 0)
2655
	return 1;
2656 2657 2658

      register const int v = plm1 - i;
      turboShift = u - v;
2659
      bcShift    = bmBc[(uint) (uchar) text[i + j]] - plm1 + i;
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669
      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;
      }
2670
      j+= shift;
2671
    }
2672
    return 0;
2673 2674 2675 2676 2677 2678
  }
  else
  {
    while (j <= tlmpl)
    {
      register int i = plm1;
2679
      while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j]))
2680 2681 2682
      {
	i--;
	if (i == plm1 - shift)
2683
	  i-= u;
2684 2685
      }
      if (i < 0)
2686
	return 1;
2687 2688 2689

      register const int v = plm1 - i;
      turboShift = u - v;
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
2690
      bcShift    = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i;
2691 2692 2693 2694 2695 2696 2697 2698 2699 2700
      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;
      }
2701
      j+= shift;
2702
    }
2703
    return 0;
2704 2705
  }
}
2706

2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727

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

2728 2729
longlong Item_cond_xor::val_int()
{
2730
  DBUG_ASSERT(fixed == 1);
2731 2732 2733
  List_iterator<Item> li(list);
  Item *item;
  int result=0;	
2734
  null_value=0;
2735 2736
  while ((item=li++))
  {
2737 2738 2739 2740 2741 2742
    result^= (item->val_int() != 0);
    if (item->null_value)
    {
      null_value=1;
      return 0;
    }
2743
  }
2744
  return (longlong) result;
2745
}
2746 2747 2748 2749 2750 2751

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

  SYNPOSIS
    neg_transformer()
2752
    thd		thread handler
2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772

  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()).
*/

2773
Item *Item_func_not::neg_transformer(THD *thd)	/* NOT(x)  ->  x */
2774
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
2775
  return args[0];
2776 2777
}

2778 2779

Item *Item_bool_rowready_func2::neg_transformer(THD *thd)
2780
{
2781 2782
  Item *item= negated_item();
  return item;
2783 2784
}

2785 2786 2787

/* a IS NULL  ->  a IS NOT NULL */
Item *Item_func_isnull::neg_transformer(THD *thd)
2788
{
2789 2790
  Item *item= new Item_func_isnotnull(args[0]);
  return item;
2791 2792
}

2793 2794 2795

/* a IS NOT NULL  ->  a IS NULL */
Item *Item_func_isnotnull::neg_transformer(THD *thd)
2796
{
2797 2798
  Item *item= new Item_func_isnull(args[0]);
  return item;
2799 2800
}

2801 2802 2803

Item *Item_cond_and::neg_transformer(THD *thd)	/* NOT(a AND b AND ...)  -> */
					/* NOT a OR NOT b OR ... */
2804
{
2805 2806 2807
  neg_arguments(thd);
  Item *item= new Item_cond_or(list);
  return item;
2808 2809
}

2810 2811 2812

Item *Item_cond_or::neg_transformer(THD *thd)	/* NOT(a OR b OR ...)  -> */
					/* NOT a AND NOT b AND ... */
2813
{
2814 2815 2816
  neg_arguments(thd);
  Item *item= new Item_cond_and(list);
  return item;
2817 2818
}

2819 2820

Item *Item_func_eq::negated_item()		/* a = b  ->  a != b */
2821
{
2822
  return new Item_func_ne(args[0], args[1]);
2823 2824
}

2825 2826

Item *Item_func_ne::negated_item()		/* a != b  ->  a = b */
2827
{
2828
  return new Item_func_eq(args[0], args[1]);
2829 2830
}

2831 2832

Item *Item_func_lt::negated_item()		/* a < b  ->  a >= b */
2833
{
2834
  return new Item_func_ge(args[0], args[1]);
2835 2836
}

2837 2838

Item *Item_func_ge::negated_item()		/* a >= b  ->  a < b */
2839
{
2840
  return new Item_func_lt(args[0], args[1]);
2841 2842
}

2843 2844

Item *Item_func_gt::negated_item()		/* a > b  ->  a <= b */
2845
{
2846
  return new Item_func_le(args[0], args[1]);
2847 2848
}

2849 2850

Item *Item_func_le::negated_item()		/* a <= b  ->  a > b */
2851
{
2852
  return new Item_func_gt(args[0], args[1]);
2853 2854
}

2855 2856
// just fake method, should never be called
Item *Item_bool_rowready_func2::negated_item()
2857
{
2858 2859
  DBUG_ASSERT(0);
  return 0;
2860
}