item_cmpfunc.h 21.9 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2003 MySQL AB
unknown's avatar
unknown committed
2

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

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

unknown's avatar
unknown committed
13 14 15 16 17 18 19 20 21 22 23
   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 */


/* compare and test functions */

#ifdef __GNUC__
#pragma interface			/* gcc class implementation */
#endif

24 25 26 27 28 29 30 31 32 33 34 35 36 37
extern Item_result item_cmp_type(Item_result a,Item_result b);
class Item_bool_func2;
class Arg_comparator;

typedef int (Arg_comparator::*arg_cmp_func)();

class Arg_comparator: public Sql_alloc
{
  Item **a, **b;
  arg_cmp_func func;
  Item_bool_func2 *owner;
  Arg_comparator *comparators;   // used only for compare_row()

public:
38 39
  DTCollation cmp_collation;

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
  Arg_comparator() {};
  Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};

  int set_compare_func(Item_bool_func2 *owner, Item_result type);
  inline int set_compare_func(Item_bool_func2 *owner)
  {
    return set_compare_func(owner, item_cmp_type((*a)->result_type(),
						 (*b)->result_type()));
  }
  inline int set_cmp_func(Item_bool_func2 *owner,
			  Item **a1, Item **a2,
			  Item_result type)
  {
    a= a1;
    b= a2;
    return set_compare_func(owner, type);
  }
  inline int set_cmp_func(Item_bool_func2 *owner,
			  Item **a1, Item **a2)
  {
    return set_cmp_func(owner, a1, a2, item_cmp_type((*a1)->result_type(),
						     (*a2)->result_type()));
  }
  inline int compare() { return (this->*func)(); }

  int compare_string();		 // compare args[0] & args[1]
  int compare_real();            // compare args[0] & args[1]
  int compare_int();             // compare args[0] & args[1]
  int compare_row();             // compare args[0] & args[1]
  int compare_e_string();	 // compare args[0] & args[1]
  int compare_e_real();          // compare args[0] & args[1]
  int compare_e_int();           // compare args[0] & args[1]
  int compare_e_row();           // compare args[0] & args[1]

  static arg_cmp_func comparator_matrix [4][2];

  friend class Item_func;
};

unknown's avatar
unknown committed
79 80 81 82 83 84 85 86 87
class Item_bool_func :public Item_int_func
{
public:
  Item_bool_func() :Item_int_func() {}
  Item_bool_func(Item *a) :Item_int_func(a) {}
  Item_bool_func(Item *a,Item *b) :Item_int_func(a,b) {}
  void fix_length_and_dec() { decimals=0; max_length=1; }
};

88
class Item_cache;
89 90 91
class Item_in_optimizer: public Item_bool_func
{
protected:
92
  Item_cache *cache;
93
public:
unknown's avatar
unknown committed
94 95 96 97
  Item_in_optimizer(Item *a, Item_in_subselect *b):
    Item_bool_func(a, (Item *)b), cache(0) {}
  // used by row in transformer
  bool preallocate_row();
98 99
  bool fix_fields(THD *, struct st_table_list *, Item **);
  bool is_null();
unknown's avatar
unknown committed
100 101 102 103 104 105 106
  /*
    Item_in_optimizer item is special boolean function. On value request 
    (one of val, val_int or val_str methods) it evaluate left expression 
    of IN by storing it value in cache item (one of Item_cache* items), 
    then it test cache is it NULL. If left expression (cache) is NULL then
    Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
  */
107
  longlong val_int();
108
  
unknown's avatar
unknown committed
109
  Item_cache **get_cache() { return &cache; }
110 111
};

unknown's avatar
unknown committed
112 113 114
class Item_bool_func2 :public Item_int_func
{						/* Bool with 2 string args */
protected:
115
  Arg_comparator cmp;
unknown's avatar
unknown committed
116
  String tmp_value1,tmp_value2;
117

unknown's avatar
unknown committed
118
public:
119
  Item_bool_func2(Item *a,Item *b):
120
    Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
unknown's avatar
unknown committed
121
  void fix_length_and_dec();
122
  void set_cmp_func()
unknown's avatar
unknown committed
123
  {
124
    cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
unknown's avatar
unknown committed
125
  }
unknown's avatar
unknown committed
126 127 128 129
  optimize_type select_optimize() const { return OPTIMIZE_OP; }
  virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
  bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
  void print(String *str) { Item_func::print_op(str); }
unknown's avatar
unknown committed
130
  bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
unknown's avatar
unknown committed
131 132 133 134 135 136 137

  static Item_bool_func2* eq_creator(Item *a, Item *b);
  static Item_bool_func2* ne_creator(Item *a, Item *b);
  static Item_bool_func2* gt_creator(Item *a, Item *b);
  static Item_bool_func2* lt_creator(Item *a, Item *b);
  static Item_bool_func2* ge_creator(Item *a, Item *b);
  static Item_bool_func2* le_creator(Item *a, Item *b);
138 139

  friend class  Arg_comparator;
unknown's avatar
unknown committed
140 141
};

unknown's avatar
unknown committed
142 143 144 145 146 147 148 149
class Item_bool_rowready_func2 :public Item_bool_func2
{
public:
  Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b)
  {
    allowed_arg_cols= a->cols();
  }
};
unknown's avatar
unknown committed
150 151 152 153 154 155 156 157 158

class Item_func_not :public Item_bool_func
{
public:
  Item_func_not(Item *a) :Item_bool_func(a) {}
  longlong val_int();
  const char *func_name() const { return "not"; }
};

unknown's avatar
unknown committed
159
class Item_func_eq :public Item_bool_rowready_func2
unknown's avatar
unknown committed
160 161
{
public:
162
  Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
163 164 165 166 167 168 169
  longlong val_int();
  enum Functype functype() const { return EQ_FUNC; }
  enum Functype rev_functype() const { return EQ_FUNC; }
  cond_result eq_cmp_result() const { return COND_TRUE; }
  const char *func_name() const { return "="; }
};

unknown's avatar
unknown committed
170
class Item_func_equal :public Item_bool_rowready_func2
unknown's avatar
unknown committed
171 172
{
public:
unknown's avatar
unknown committed
173
  Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
174
  longlong val_int();
unknown's avatar
unknown committed
175
  void fix_length_and_dec();
unknown's avatar
unknown committed
176 177 178 179 180 181 182
  enum Functype functype() const { return EQUAL_FUNC; }
  enum Functype rev_functype() const { return EQUAL_FUNC; }
  cond_result eq_cmp_result() const { return COND_TRUE; }
  const char *func_name() const { return "<=>"; }
};


unknown's avatar
unknown committed
183
class Item_func_ge :public Item_bool_rowready_func2
unknown's avatar
unknown committed
184 185
{
public:
186
  Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
187 188 189 190 191 192 193 194
  longlong val_int();
  enum Functype functype() const { return GE_FUNC; }
  enum Functype rev_functype() const { return LE_FUNC; }
  cond_result eq_cmp_result() const { return COND_TRUE; }
  const char *func_name() const { return ">="; }
};


unknown's avatar
unknown committed
195
class Item_func_gt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
196 197
{
public:
198
  Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
199 200 201 202 203 204 205 206
  longlong val_int();
  enum Functype functype() const { return GT_FUNC; }
  enum Functype rev_functype() const { return LT_FUNC; }
  cond_result eq_cmp_result() const { return COND_FALSE; }
  const char *func_name() const { return ">"; }
};


unknown's avatar
unknown committed
207
class Item_func_le :public Item_bool_rowready_func2
unknown's avatar
unknown committed
208 209
{
public:
210
  Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
211 212 213 214 215 216 217 218
  longlong val_int();
  enum Functype functype() const { return LE_FUNC; }
  enum Functype rev_functype() const { return GE_FUNC; }
  cond_result eq_cmp_result() const { return COND_TRUE; }
  const char *func_name() const { return "<="; }
};


unknown's avatar
unknown committed
219
class Item_func_lt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
220 221
{
public:
222
  Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
223 224 225 226 227 228 229 230
  longlong val_int();
  enum Functype functype() const { return LT_FUNC; }
  enum Functype rev_functype() const { return GT_FUNC; }
  cond_result eq_cmp_result() const { return COND_FALSE; }
  const char *func_name() const { return "<"; }
};


unknown's avatar
unknown committed
231
class Item_func_ne :public Item_bool_rowready_func2
unknown's avatar
unknown committed
232 233
{
public:
234
  Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
235 236 237 238 239 240 241 242 243 244
  longlong val_int();
  enum Functype functype() const { return NE_FUNC; }
  cond_result eq_cmp_result() const { return COND_FALSE; }
  optimize_type select_optimize() const { return OPTIMIZE_NONE; }
  const char *func_name() const { return "<>"; }
};


class Item_func_between :public Item_int_func
{
245
  DTCollation cmp_collation;
unknown's avatar
unknown committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
public:
  Item_result cmp_type;
  String value0,value1,value2;
  Item_func_between(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {}
  longlong val_int();
  optimize_type select_optimize() const { return OPTIMIZE_KEY; }
  enum Functype functype() const   { return BETWEEN; }
  const char *func_name() const { return "between"; }
  void fix_length_and_dec();
};


class Item_func_strcmp :public Item_bool_func2
{
public:
  Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {}
  longlong val_int();
  optimize_type select_optimize() const { return OPTIMIZE_NONE; }
  const char *func_name() const { return "strcmp"; }
};


class Item_func_interval :public Item_int_func
{
270
  Item_row *row;
unknown's avatar
unknown committed
271 272
  double *intervals;
public:
273 274
  Item_func_interval(Item_row *a)
    :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
unknown's avatar
unknown committed
275 276 277 278 279 280 281 282 283 284
  longlong val_int();
  void fix_length_and_dec();
  const char *func_name() const { return "interval"; }
};


class Item_func_ifnull :public Item_func
{
  enum Item_result cached_result_type;
public:
285 286 287
  Item_func_ifnull(Item *a,Item *b)
    :Item_func(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
288 289 290 291 292 293 294 295 296 297 298 299 300
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
  void fix_length_and_dec();
  const char *func_name() const { return "ifnull"; }
};


class Item_func_if :public Item_func
{
  enum Item_result cached_result_type;
public:
301 302 303
  Item_func_if(Item *a,Item *b,Item *c)
    :Item_func(a,b,c), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
304 305 306 307
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
unknown's avatar
unknown committed
308
  bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
309 310
  {
    args[0]->top_level_item();
unknown's avatar
unknown committed
311
    return Item_func::fix_fields(thd, tlist, ref);
312
  }
unknown's avatar
unknown committed
313 314 315 316 317 318 319 320 321
  void fix_length_and_dec();
  const char *func_name() const { return "if"; }
};


class Item_func_nullif :public Item_bool_func2
{
  enum Item_result cached_result_type;
public:
322 323 324
  Item_func_nullif(Item *a,Item *b)
    :Item_bool_func2(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
325 326 327 328 329 330 331 332 333 334 335 336 337
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
  void fix_length_and_dec();
  const char *func_name() const { return "nullif"; }
};


class Item_func_coalesce :public Item_func
{
  enum Item_result cached_result_type;
public:
338 339 340
  Item_func_coalesce(List<Item> &list)
    :Item_func(list),cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
341 342 343 344 345 346 347 348 349 350
  double val();
  longlong val_int();
  String *val_str(String *);
  void fix_length_and_dec();
  enum Item_result result_type () const { return cached_result_type; }
  const char *func_name() const { return "coalesce"; }
};

class Item_func_case :public Item_func
{
351
  int first_expr_num, else_expr_num;
unknown's avatar
unknown committed
352 353
  enum Item_result cached_result_type;
  String tmp_value;
354
  uint ncases;
355 356
  Item_result cmp_type;
  DTCollation cmp_collation;
unknown's avatar
unknown committed
357
public:
358
  Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
359
    :Item_func(), first_expr_num(-1), else_expr_num(-1),
360
    cached_result_type(INT_RESULT)
361 362 363 364 365 366 367 368 369 370 371 372 373 374
  { 
    ncases= list.elements;
    if (first_expr_arg)
    {
      first_expr_num= list.elements;
      list.push_back(first_expr_arg);
    }
    if (else_expr_arg)
    {
      else_expr_num= list.elements;
      list.push_back(else_expr_arg);
    }
    set_arguments(list);
  }
unknown's avatar
unknown committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392
  double val();
  longlong val_int();
  String *val_str(String *);
  void fix_length_and_dec();
  enum Item_result result_type () const { return cached_result_type; }
  const char *func_name() const { return "case"; }
  void print(String *str);
  Item *find_item(String *str);
};


/* Functions to handle the optimized IN */

class in_vector :public Sql_alloc
{
 protected:
  char *base;
  uint size;
393 394
  qsort2_cmp compare;
  CHARSET_INFO *collation;
unknown's avatar
unknown committed
395 396 397
  uint count;
public:
  uint used_count;
unknown's avatar
unknown committed
398
  in_vector() {}
399 400
  in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, 
  	    CHARSET_INFO *cmp_coll)
unknown's avatar
unknown committed
401
    :base((char*) sql_calloc(elements*element_length)),
402 403
     size(element_length), compare(cmp_func), collation(cmp_coll),
     count(elements), used_count(elements) {}
unknown's avatar
unknown committed
404 405 406 407
  virtual ~in_vector() {}
  virtual void set(uint pos,Item *item)=0;
  virtual byte *get_value(Item *item)=0;
  void sort()
408
  {
409
    qsort2(base,used_count,size,compare,collation);
410
  }
unknown's avatar
unknown committed
411 412 413 414 415 416 417 418
  int find(Item *item);
};

class in_string :public in_vector
{
  char buff[80];
  String tmp;
public:
419
  in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
unknown's avatar
unknown committed
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
  ~in_string();
  void set(uint pos,Item *item);
  byte *get_value(Item *item);
};

class in_longlong :public in_vector
{
  longlong tmp;
public:
  in_longlong(uint elements);
  void set(uint pos,Item *item);
  byte *get_value(Item *item);
};

class in_double :public in_vector
{
  double tmp;
public:
  in_double(uint elements);
  void set(uint pos,Item *item);
  byte *get_value(Item *item);
};

/*
** Classes for easy comparing of non const items
*/

class cmp_item :public Sql_alloc
{
public:
450 451
  CHARSET_INFO *cmp_charset;
  cmp_item() { cmp_charset= &my_charset_bin; }
unknown's avatar
unknown committed
452
  virtual ~cmp_item() {}
unknown's avatar
unknown committed
453 454 455 456
  virtual void store_value(Item *item)= 0;
  virtual int cmp(Item *item)= 0;
  // for optimized IN with row
  virtual int compare(cmp_item *item)= 0;
457
  static cmp_item* get_comparator(Item *);
unknown's avatar
unknown committed
458 459 460 461 462
  virtual cmp_item *make_same()= 0;
  virtual void store_value_by_template(cmp_item *tmpl, Item *item)
  {
    store_value(item);
  }
unknown's avatar
unknown committed
463 464
};

unknown's avatar
unknown committed
465 466 467 468 469
class cmp_item_string :public cmp_item 
{
protected:
  String *value_res;
public:
470
  cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
unknown's avatar
unknown committed
471 472 473
  friend class cmp_item_sort_string;
  friend class cmp_item_sort_string_in_static;
};
unknown's avatar
unknown committed
474

unknown's avatar
unknown committed
475 476 477
class cmp_item_sort_string :public cmp_item_string
{
protected:
unknown's avatar
unknown committed
478
  char value_buff[80];
unknown's avatar
unknown committed
479
  String value;
unknown's avatar
unknown committed
480
public:
481 482 483
  cmp_item_sort_string(CHARSET_INFO *cs):
    cmp_item_string(cs),
    value(value_buff, sizeof(value_buff), cs) {}
unknown's avatar
unknown committed
484
  void store_value(Item *item)
unknown's avatar
unknown committed
485 486 487
  {
    value_res= item->val_str(&value);
  }
unknown's avatar
unknown committed
488
  int cmp(Item *arg)
unknown's avatar
unknown committed
489 490
  {
    char buff[80];
unknown's avatar
unknown committed
491
    String tmp(buff, sizeof(buff), cmp_charset), *res;
unknown's avatar
unknown committed
492 493
    if (!(res= arg->val_str(&tmp)))
      return 1;				/* Can't be right */
494
    return sortcmp(value_res, res, cmp_charset);
unknown's avatar
unknown committed
495 496 497 498
  }
  int compare(cmp_item *c)
  {
    cmp_item_string *cmp= (cmp_item_string *)c;
499
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
500 501
  } 
  cmp_item *make_same();
unknown's avatar
unknown committed
502 503 504 505 506 507 508
};

class cmp_item_int :public cmp_item
{
  longlong value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
509 510 511
  {
    value= item->val_int();
  }
unknown's avatar
unknown committed
512
  int cmp(Item *arg)
unknown's avatar
unknown committed
513 514 515 516 517 518 519 520 521
  {
    return value != arg->val_int();
  }
  int compare(cmp_item *c)
  {
    cmp_item_int *cmp= (cmp_item_int *)c;
    return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
  }
  cmp_item *make_same();
unknown's avatar
unknown committed
522 523 524 525 526 527 528
};

class cmp_item_real :public cmp_item
{
  double value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
529 530 531
  {
    value= item->val();
  }
unknown's avatar
unknown committed
532
  int cmp(Item *arg)
unknown's avatar
unknown committed
533 534 535 536 537 538 539 540 541
  {
    return value != arg->val();
  }
  int compare(cmp_item *c)
  {
    cmp_item_real *cmp= (cmp_item_real *)c;
    return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1);
  }
  cmp_item *make_same();
unknown's avatar
unknown committed
542 543
};

544 545 546 547 548
class cmp_item_row :public cmp_item
{
  cmp_item **comparators;
  uint n;
public:
unknown's avatar
unknown committed
549 550 551
  cmp_item_row(): comparators(0), n(0) {}
  ~cmp_item_row()
  {
unknown's avatar
unknown committed
552
    if (comparators)
unknown's avatar
unknown committed
553
    {
unknown's avatar
unknown committed
554
      for (uint i= 0; i < n; i++)
unknown's avatar
unknown committed
555
      {
unknown's avatar
unknown committed
556 557
	if (comparators[i])
	  delete comparators[i];
unknown's avatar
unknown committed
558
      }
unknown's avatar
unknown committed
559
    }
unknown's avatar
unknown committed
560
  }
561 562
  void store_value(Item *item);
  int cmp(Item *arg);
unknown's avatar
unknown committed
563 564 565 566 567 568 569 570 571 572 573
  int compare(cmp_item *arg);
  cmp_item *make_same();
  void store_value_by_template(cmp_item *tmpl, Item *);
};


class in_row :public in_vector
{
  cmp_item_row tmp;
public:
  in_row(uint elements, Item *);
574
  ~in_row();
unknown's avatar
unknown committed
575 576 577 578 579 580 581 582 583 584 585 586 587 588
  void set(uint pos,Item *item);
  byte *get_value(Item *item);
};

/* 
   cmp_item for optimized IN with row (right part string, which never
   be changed)
*/

class cmp_item_sort_string_in_static :public cmp_item_string
{
 protected:
  String value;
public:
589 590
  cmp_item_sort_string_in_static(CHARSET_INFO *cs):
    cmp_item_string(cs) {}
unknown's avatar
unknown committed
591 592 593 594 595 596 597 598 599 600 601 602 603
  void store_value(Item *item)
  {
    value_res= item->val_str(&value);
  }
  int cmp(Item *item)
  {
    // Should never be called
    DBUG_ASSERT(0);
    return 1;
  }
  int compare(cmp_item *c)
  {
    cmp_item_string *cmp= (cmp_item_string *)c;
604
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
605 606 607
  }
  cmp_item * make_same()
  {
608
    return new cmp_item_sort_string_in_static(cmp_charset);
unknown's avatar
unknown committed
609
  }
610
};
unknown's avatar
unknown committed
611 612 613

class Item_func_in :public Item_int_func
{
614
  Item_result cmp_type;
unknown's avatar
unknown committed
615 616
  in_vector *array;
  cmp_item *in_item;
617
  bool have_null;
618
  DTCollation cmp_collation;
unknown's avatar
unknown committed
619
 public:
620 621
  Item_func_in(List<Item> &list)
    :Item_int_func(list), array(0), in_item(0), have_null(0)
622
  {
623
    allowed_arg_cols= args[0]->cols();
624
  }
unknown's avatar
unknown committed
625 626
  longlong val_int();
  void fix_length_and_dec();
627
  ~Item_func_in() { delete array; delete in_item; }
unknown's avatar
unknown committed
628 629
  optimize_type select_optimize() const
    { return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
630
  Item *key_item() const { return args[0]; }
unknown's avatar
unknown committed
631 632 633
  void print(String *str);
  enum Functype functype() const { return IN_FUNC; }
  const char *func_name() const { return " IN "; }
unknown's avatar
unknown committed
634
  bool nulls_in_row();
unknown's avatar
unknown committed
635 636 637 638 639 640
};

/* Functions used by where clause */

class Item_func_isnull :public Item_bool_func
{
641
protected:
unknown's avatar
unknown committed
642
  longlong cached_value;
unknown's avatar
unknown committed
643 644 645 646 647 648 649
public:
  Item_func_isnull(Item *a) :Item_bool_func(a) {}
  longlong val_int();
  enum Functype functype() const { return ISNULL_FUNC; }
  void fix_length_and_dec()
  {
    decimals=0; max_length=1; maybe_null=0;
650
    update_used_tables();
unknown's avatar
unknown committed
651 652 653
  }
  const char *func_name() const { return "isnull"; }
  /* Optimize case of not_null_column IS NULL */
654
  virtual void update_used_tables()
unknown's avatar
unknown committed
655 656 657
  {
    if (!args[0]->maybe_null)
    {
658 659
      used_tables_cache= 0;			/* is always false */
      cached_value= (longlong) 0;
unknown's avatar
unknown committed
660
    }
661
    else
unknown's avatar
unknown committed
662
    {
663 664 665 666
      args[0]->update_used_tables();
      if (!(used_tables_cache=args[0]->used_tables()))
      {
	/* Remember if the value is always NULL or never NULL */
667
	cached_value= (longlong) args[0]->is_null();
668
      }
unknown's avatar
unknown committed
669
    }
unknown's avatar
unknown committed
670 671 672 673
  }
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
};

674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
/* Functions used by HAVING for rewriting IN subquery */

class Item_in_subselect;
class Item_is_not_null_test :public Item_func_isnull
{
  Item_in_subselect* owner;
public:
  Item_is_not_null_test(Item_in_subselect* ow, Item *a)
    :Item_func_isnull(a), owner(ow)
  {}
  longlong val_int();
  const char *func_name() const { return "is_not_null_test"; }
  void update_used_tables();
};


unknown's avatar
unknown committed
690 691 692 693 694 695
class Item_func_isnotnull :public Item_bool_func
{
public:
  Item_func_isnotnull(Item *a) :Item_bool_func(a) {}
  longlong val_int();
  enum Functype functype() const { return ISNOTNULL_FUNC; }
unknown's avatar
unknown committed
696 697 698 699
  void fix_length_and_dec()
  {
    decimals=0; max_length=1; maybe_null=0;
  }
unknown's avatar
unknown committed
700 701 702 703 704 705 706
  const char *func_name() const { return "isnotnull"; }
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
};

class Item_func_like :public Item_bool_func2
{
  char escape;
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722

  // Turbo Boyer-Moore data
  bool        canDoTurboBM;	// pattern is '%abcd%' case
  const char* pattern;
  int         pattern_len;

  // TurboBM buffers, *this is owner
  int* bmGs; //   good suffix shift table, size is pattern_len + 1
  int* bmBc; // bad character shift table, size is alphabet_size

  void turboBM_compute_suffixes(int* suff);
  void turboBM_compute_good_suffix_shifts(int* suff);
  void turboBM_compute_bad_character_shifts();
  bool turboBM_matches(const char* text, int text_len) const;
  enum { alphabet_size = 256 };

unknown's avatar
unknown committed
723
public:
724 725 726
  Item_func_like(Item *a,Item *b, char* escape_arg)
    :Item_bool_func2(a,b), escape(*escape_arg), canDoTurboBM(false),
    pattern(0), pattern_len(0), bmGs(0), bmBc(0)
unknown's avatar
unknown committed
727 728 729 730 731 732
  {}
  longlong val_int();
  enum Functype functype() const { return LIKE_FUNC; }
  optimize_type select_optimize() const;
  cond_result eq_cmp_result() const { return COND_TRUE; }
  const char *func_name() const { return "like"; }
unknown's avatar
unknown committed
733
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
unknown's avatar
unknown committed
734 735 736 737 738 739 740 741 742 743 744 745
};

#ifdef USE_REGEX

#include <regex.h>

class Item_func_regex :public Item_bool_func
{
  regex_t preg;
  bool regex_compiled;
  bool regex_is_const;
  String prev_regexp;
746
  DTCollation cmp_collation;
unknown's avatar
unknown committed
747 748 749 750 751
public:
  Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
    regex_compiled(0),regex_is_const(0) {}
  ~Item_func_regex();
  longlong val_int();
unknown's avatar
unknown committed
752
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
unknown's avatar
unknown committed
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
  const char *func_name() const { return "regex"; }
};

#else

class Item_func_regex :public Item_bool_func
{
public:
  Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b) {}
  longlong val_int() { return 0;}
  const char *func_name() const { return "regex"; }
};

#endif /* USE_REGEX */


typedef class Item COND;

class Item_cond :public Item_bool_func
{
protected:
  List<Item> list;
775
  bool abort_on_null;
unknown's avatar
unknown committed
776
public:
777 778 779 780
  /* Item_cond() is only used to create top level items */
  Item_cond() : Item_bool_func(), abort_on_null(1) { const_item_cache=0; }
  Item_cond(Item *i1,Item *i2) :Item_bool_func(), abort_on_null(0)
  { list.push_back(i1); list.push_back(i2); }
unknown's avatar
unknown committed
781 782
  ~Item_cond() { list.delete_elements(); }
  bool add(Item *item) { return list.push_back(item); }
unknown's avatar
unknown committed
783
  bool fix_fields(THD *, struct st_table_list *, Item **ref);
unknown's avatar
unknown committed
784 785 786 787 788 789

  enum Type type() const { return COND_ITEM; }
  List<Item>* argument_list() { return &list; }
  table_map used_tables() const;
  void update_used_tables();
  void print(String *str);
790
  void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
unknown's avatar
unknown committed
791
  friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
792
  void top_level_item() { abort_on_null=1; }
793
  void set_outer_resolving();
unknown's avatar
unknown committed
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
};


class Item_cond_and :public Item_cond
{
public:
  Item_cond_and() :Item_cond() {}
  Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
  enum Functype functype() const { return COND_AND_FUNC; }
  longlong val_int();
  const char *func_name() const { return "and"; }
};

class Item_cond_or :public Item_cond
{
public:
  Item_cond_or() :Item_cond() {}
  Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
  enum Functype functype() const { return COND_OR_FUNC; }
  longlong val_int();
  const char *func_name() const { return "or"; }
};


unknown's avatar
unknown committed
818 819 820 821 822 823 824 825 826 827 828
class Item_cond_xor :public Item_cond
{
public:
  Item_cond_xor() :Item_cond() {}
  Item_cond_xor(Item *i1,Item *i2) :Item_cond(i1,i2) {}
  enum Functype functype() const { return COND_XOR_FUNC; }
  longlong val_int();
  const char *func_name() const { return "xor"; }
};


unknown's avatar
unknown committed
829 830 831 832 833 834 835 836 837 838 839
/* Some usefull inline functions */

inline Item *and_conds(Item *a,Item *b)
{
  if (!b) return a;
  if (!a) return b;
  Item *cond=new Item_cond_and(a,b);
  if (cond)
    cond->update_used_tables();
  return cond;
}
unknown's avatar
unknown committed
840

unknown's avatar
unknown committed
841
Item *and_expressions(Item *a, Item *b, Item **org_item);