item_cmpfunc.h 30.7 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
   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 */

20
#ifdef USE_PRAGMA_INTERFACE
unknown's avatar
unknown committed
21 22 23
#pragma interface			/* gcc class implementation */
#endif

24 25 26 27 28 29 30 31 32 33 34 35
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()
36
  double precision;
37 38

public:
39 40
  DTCollation cmp_collation;

41 42 43 44
  Arg_comparator() {};
  Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};

  int set_compare_func(Item_bool_func2 *owner, Item_result type);
45
  inline int set_compare_func(Item_bool_func2 *owner_arg)
46
  {
unknown's avatar
unknown committed
47 48
    return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
                                                     (*b)->result_type()));
49
  }
50
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
51 52 53 54 55
			  Item **a1, Item **a2,
			  Item_result type)
  {
    a= a1;
    b= a2;
56
    return set_compare_func(owner_arg, type);
57
  }
58
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
59 60
			  Item **a1, Item **a2)
  {
unknown's avatar
unknown committed
61 62 63
    return set_cmp_func(owner_arg, a1, a2,
                        item_cmp_type((*a1)->result_type(),
                                      (*a2)->result_type()));
64 65 66 67
  }
  inline int compare() { return (this->*func)(); }

  int compare_string();		 // compare args[0] & args[1]
unknown's avatar
unknown committed
68
  int compare_binary_string();	 // compare args[0] & args[1]
69
  int compare_real();            // compare args[0] & args[1]
70
  int compare_int_signed();      // compare args[0] & args[1]
71 72 73
  int compare_int_signed_unsigned();
  int compare_int_unsigned_signed();
  int compare_int_unsigned();
74 75
  int compare_row();             // compare args[0] & args[1]
  int compare_e_string();	 // compare args[0] & args[1]
unknown's avatar
unknown committed
76
  int compare_e_binary_string(); // compare args[0] & args[1]
77 78
  int compare_e_real();          // compare args[0] & args[1]
  int compare_e_int();           // compare args[0] & args[1]
79
  int compare_e_int_diff_signedness();
80
  int compare_e_row();           // compare args[0] & args[1]
81 82
  int compare_real_fixed();
  int compare_e_real_fixed();
83 84 85 86 87 88

  static arg_cmp_func comparator_matrix [4][2];

  friend class Item_func;
};

unknown's avatar
unknown committed
89 90 91 92 93 94
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) {}
95
  Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
unknown's avatar
unknown committed
96
  bool is_bool_func() { return 1; }
unknown's avatar
unknown committed
97 98 99
  void fix_length_and_dec() { decimals=0; max_length=1; }
};

100
class Item_cache;
101 102 103
class Item_in_optimizer: public Item_bool_func
{
protected:
104
  Item_cache *cache;
105
  bool save_cache;
106
public:
unknown's avatar
unknown committed
107
  Item_in_optimizer(Item *a, Item_in_subselect *b):
108 109
    Item_bool_func(a, my_reinterpret_cast(Item *)(b)), cache(0), save_cache(0)
  {}
110
  bool fix_fields(THD *, struct st_table_list *, Item **);
111
  bool fix_left(THD *thd, struct st_table_list *tables, Item **ref);
112
  bool is_null();
unknown's avatar
unknown committed
113 114 115 116 117 118 119
  /*
    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.
  */
120
  longlong val_int();
unknown's avatar
unknown committed
121
  void cleanup();
122
  const char *func_name() const { return "<in_optimizer>"; }
unknown's avatar
unknown committed
123
  Item_cache **get_cache() { return &cache; }
124
  void keep_top_level_cache();
125 126
};

unknown's avatar
unknown committed
127 128 129
class Comp_creator
{
public:
130 131
  Comp_creator() {}                             /* Remove gcc warning */
  virtual ~Comp_creator() {}                    /* Remove gcc warning */
unknown's avatar
unknown committed
132 133 134 135 136 137 138 139 140
  virtual Item_bool_func2* create(Item *a, Item *b) const = 0;
  virtual const char* symbol(bool invert) const = 0;
  virtual bool eqne_op() const = 0;
  virtual bool l_op() const = 0;
};

class Eq_creator :public Comp_creator
{
public:
141 142
  Eq_creator() {}                               /* Remove gcc warning */
  virtual ~Eq_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
143 144 145 146 147 148 149 150 151
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? "<>" : "="; }
  virtual bool eqne_op() const { return 1; }
  virtual bool l_op() const { return 0; }
};

class Ne_creator :public Comp_creator
{
public:
152 153
  Ne_creator() {}                               /* Remove gcc warning */
  virtual ~Ne_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
154 155 156 157 158 159 160 161 162
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? "=" : "<>"; }
  virtual bool eqne_op() const { return 1; }
  virtual bool l_op() const { return 0; }
};

class Gt_creator :public Comp_creator
{
public:
163 164
  Gt_creator() {}                               /* Remove gcc warning */
  virtual ~Gt_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
165 166 167 168 169 170 171 172 173
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? "<=" : ">"; }
  virtual bool eqne_op() const { return 0; }
  virtual bool l_op() const { return 0; }
};

class Lt_creator :public Comp_creator
{
public:
174 175
  Lt_creator() {}                               /* Remove gcc warning */
  virtual ~Lt_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
176 177 178 179 180 181 182 183 184
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? ">=" : "<"; }
  virtual bool eqne_op() const { return 0; }
  virtual bool l_op() const { return 1; }
};

class Ge_creator :public Comp_creator
{
public:
185 186
  Ge_creator() {}                               /* Remove gcc warning */
  virtual ~Ge_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
187 188 189 190 191 192 193 194 195
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? "<" : ">="; }
  virtual bool eqne_op() const { return 0; }
  virtual bool l_op() const { return 0; }
};

class Le_creator :public Comp_creator
{
public:
196 197
  Le_creator() {}                               /* Remove gcc warning */
  virtual ~Le_creator() {}                      /* Remove gcc warning */
unknown's avatar
unknown committed
198 199 200 201 202 203
  virtual Item_bool_func2* create(Item *a, Item *b) const;
  virtual const char* symbol(bool invert) const { return invert? ">" : "<="; }
  virtual bool eqne_op() const { return 0; }
  virtual bool l_op() const { return 1; }
};

unknown's avatar
unknown committed
204 205 206
class Item_bool_func2 :public Item_int_func
{						/* Bool with 2 string args */
protected:
207
  Arg_comparator cmp;
unknown's avatar
unknown committed
208
  String tmp_value1,tmp_value2;
209
  bool abort_on_null;
210

unknown's avatar
unknown committed
211
public:
212
  Item_bool_func2(Item *a,Item *b)
213
    :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {}
unknown's avatar
unknown committed
214
  void fix_length_and_dec();
215
  void set_cmp_func()
unknown's avatar
unknown committed
216
  {
217
    cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
unknown's avatar
unknown committed
218
  }
unknown's avatar
unknown committed
219 220 221 222
  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
223
  bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
unknown's avatar
unknown committed
224
  bool is_bool_func() { return 1; }
225
  CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
226
  void top_level_item() { abort_on_null= TRUE; }
unknown's avatar
unknown committed
227

228
  friend class  Arg_comparator;
unknown's avatar
unknown committed
229 230
};

unknown's avatar
unknown committed
231 232 233
class Item_bool_rowready_func2 :public Item_bool_func2
{
public:
234
  Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
unknown's avatar
unknown committed
235
  {
236
    allowed_arg_cols= 0;  // Fetch this value from first argument
unknown's avatar
unknown committed
237
  }
238 239
  Item *neg_transformer(THD *thd);
  virtual Item *negated_item();
unknown's avatar
unknown committed
240
};
unknown's avatar
unknown committed
241 242 243 244 245 246

class Item_func_not :public Item_bool_func
{
public:
  Item_func_not(Item *a) :Item_bool_func(a) {}
  longlong val_int();
247
  enum Functype functype() const { return NOT_FUNC; }
unknown's avatar
unknown committed
248
  const char *func_name() const { return "not"; }
249
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
250 251
};

252
class Item_maxmin_subselect;
253 254
class Item_func_not_all :public Item_func_not
{
255 256 257 258
  /* allow to check presence od values in max/min optimisation */
  Item_sum_hybrid *test_sum_item;
  Item_maxmin_subselect *test_sub_item;

259 260
  bool abort_on_null;
public:
unknown's avatar
unknown committed
261 262
  bool show;

263 264 265 266
  Item_func_not_all(Item *a)
    :Item_func_not(a), test_sum_item(0), test_sub_item(0), abort_on_null(0),
     show(0)
    {}
267 268 269
  virtual void top_level_item() { abort_on_null= 1; }
  bool top_level() { return abort_on_null; }
  longlong val_int();
270
  enum Functype functype() const { return NOT_ALL_FUNC; }
unknown's avatar
unknown committed
271 272
  const char *func_name() const { return "<not>"; }
  void print(String *str);
273 274 275
  void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; };
  void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; };
  bool empty_underlying_subquery();
276
  Item *neg_transformer(THD *thd);
277 278
};

279 280 281 282 283 284 285 286

class Item_func_nop_all :public Item_func_not_all
{
public:

  Item_func_nop_all(Item *a) :Item_func_not_all(a) {}
  longlong val_int();
  const char *func_name() const { return "<nop>"; }
287
  Item *neg_transformer(THD *thd);
288 289 290
};


unknown's avatar
unknown committed
291
class Item_func_eq :public Item_bool_rowready_func2
unknown's avatar
unknown committed
292 293
{
public:
294
  Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
295 296 297 298 299
  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 "="; }
300
  Item *negated_item();
unknown's avatar
unknown committed
301 302
};

unknown's avatar
unknown committed
303
class Item_func_equal :public Item_bool_rowready_func2
unknown's avatar
unknown committed
304 305
{
public:
unknown's avatar
unknown committed
306
  Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
307
  longlong val_int();
unknown's avatar
unknown committed
308
  void fix_length_and_dec();
309
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
310 311 312 313
  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 "<=>"; }
314
  Item *neg_transformer(THD *thd) { return 0; }
unknown's avatar
unknown committed
315 316 317
};


unknown's avatar
unknown committed
318
class Item_func_ge :public Item_bool_rowready_func2
unknown's avatar
unknown committed
319 320
{
public:
321
  Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
322 323 324 325 326
  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 ">="; }
327
  Item *negated_item();
unknown's avatar
unknown committed
328 329 330
};


unknown's avatar
unknown committed
331
class Item_func_gt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
332 333
{
public:
334
  Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
335 336 337 338 339
  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 ">"; }
340
  Item *negated_item();
unknown's avatar
unknown committed
341 342 343
};


unknown's avatar
unknown committed
344
class Item_func_le :public Item_bool_rowready_func2
unknown's avatar
unknown committed
345 346
{
public:
347
  Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
348 349 350 351 352
  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 "<="; }
353
  Item *negated_item();
unknown's avatar
unknown committed
354 355 356
};


unknown's avatar
unknown committed
357
class Item_func_lt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
358 359
{
public:
360
  Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
361 362 363 364 365
  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 "<"; }
366
  Item *negated_item();
unknown's avatar
unknown committed
367 368 369
};


unknown's avatar
unknown committed
370
class Item_func_ne :public Item_bool_rowready_func2
unknown's avatar
unknown committed
371 372
{
public:
373
  Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
374 375 376
  longlong val_int();
  enum Functype functype() const { return NE_FUNC; }
  cond_result eq_cmp_result() const { return COND_FALSE; }
unknown's avatar
unknown committed
377
  optimize_type select_optimize() const { return OPTIMIZE_KEY; } 
unknown's avatar
unknown committed
378
  const char *func_name() const { return "<>"; }
379
  Item *negated_item();
unknown's avatar
unknown committed
380 381 382
};


unknown's avatar
unknown committed
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
/*
  The class Item_func_opt_neg is defined to factor out the functionality
  common for the classes Item_func_between and Item_func_in. The objects
  of these classes can express predicates or there negations.
  The alternative approach would be to create pairs Item_func_between,
  Item_func_notbetween and Item_func_in, Item_func_notin.

*/

class Item_func_opt_neg :public Item_int_func
{
public:
  bool negated;     /* <=> the item represents NOT <func> */
  bool pred_level;  /* <=> [NOT] <func> is used on a predicate level */
public:
  Item_func_opt_neg(Item *a, Item *b, Item *c)
    :Item_int_func(a, b, c), negated(0), pred_level(0) {}
  Item_func_opt_neg(List<Item> &list)
    :Item_int_func(list), negated(0), pred_level(0) {}
public:
  inline void negate() { negated= !negated; }
  inline void top_level_item() { pred_level= 1; }
  Item *neg_transformer(THD *thd)
  {
    negated= !negated;
    return this;
  }
410
  bool eq(const Item *item, bool binary_cmp) const;
unknown's avatar
unknown committed
411 412 413 414
};


class Item_func_between :public Item_func_opt_neg
unknown's avatar
unknown committed
415
{
416
  DTCollation cmp_collation;
unknown's avatar
unknown committed
417 418 419
public:
  Item_result cmp_type;
  String value0,value1,value2;
unknown's avatar
unknown committed
420 421
  Item_func_between(Item *a, Item *b, Item *c)
    :Item_func_opt_neg(a, b, c) {}
unknown's avatar
unknown committed
422 423 424 425
  longlong val_int();
  optimize_type select_optimize() const { return OPTIMIZE_KEY; }
  enum Functype functype() const   { return BETWEEN; }
  const char *func_name() const { return "between"; }
unknown's avatar
unknown committed
426
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
427
  void fix_length_and_dec();
428
  void print(String *str);
429
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
};


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
{
445
  Item_row *row;
unknown's avatar
unknown committed
446 447
  double *intervals;
public:
448
  Item_func_interval(Item_row *a)
449 450 451 452
    :Item_int_func(a),row(a),intervals(0)
  {
    allowed_arg_cols= 0;    // Fetch this value from first argument
  }
unknown's avatar
unknown committed
453 454 455 456 457 458 459 460 461
  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;
462 463
  enum_field_types cached_field_type;
  bool field_type_defined;
unknown's avatar
unknown committed
464
public:
465 466 467
  Item_func_ifnull(Item *a,Item *b)
    :Item_func(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
468 469 470 471
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
472
  enum_field_types field_type() const;
unknown's avatar
unknown committed
473 474
  void fix_length_and_dec();
  const char *func_name() const { return "ifnull"; }
475
  Field *tmp_table_field(TABLE *table);
476
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
477 478 479 480 481 482 483
};


class Item_func_if :public Item_func
{
  enum Item_result cached_result_type;
public:
484 485 486
  Item_func_if(Item *a,Item *b,Item *c)
    :Item_func(a,b,c), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
487 488 489 490
  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
491
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
492 493 494 495 496 497 498 499 500
  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:
501 502 503
  Item_func_nullif(Item *a,Item *b)
    :Item_bool_func2(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
504 505 506 507 508 509
  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"; }
510
  void print(String *str) { Item_func::print(str); }
511
  table_map not_null_tables() const { return 0; }
512
  bool is_null();
unknown's avatar
unknown committed
513 514 515 516 517 518 519
};


class Item_func_coalesce :public Item_func
{
  enum Item_result cached_result_type;
public:
520 521 522
  Item_func_coalesce(List<Item> &list)
    :Item_func(list),cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
523 524 525 526 527 528
  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"; }
529
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
530 531
};

532

unknown's avatar
unknown committed
533 534
class Item_func_case :public Item_func
{
535
  int first_expr_num, else_expr_num;
unknown's avatar
unknown committed
536 537
  enum Item_result cached_result_type;
  String tmp_value;
538
  uint ncases;
539 540
  Item_result cmp_type;
  DTCollation cmp_collation;
unknown's avatar
unknown committed
541
public:
542
  Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
543
    :Item_func(), first_expr_num(-1), else_expr_num(-1),
544
    cached_result_type(INT_RESULT)
545 546 547 548 549 550 551 552 553 554 555 556 557 558
  { 
    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
559 560 561 562
  double val();
  longlong val_int();
  String *val_str(String *);
  void fix_length_and_dec();
563
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
564 565 566 567
  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);
568
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
569 570 571 572 573 574 575 576 577 578
};


/* Functions to handle the optimized IN */

class in_vector :public Sql_alloc
{
 protected:
  char *base;
  uint size;
579 580
  qsort2_cmp compare;
  CHARSET_INFO *collation;
unknown's avatar
unknown committed
581 582 583
  uint count;
public:
  uint used_count;
unknown's avatar
unknown committed
584
  in_vector() {}
585 586
  in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, 
  	    CHARSET_INFO *cmp_coll)
unknown's avatar
unknown committed
587
    :base((char*) sql_calloc(elements*element_length)),
588 589
     size(element_length), compare(cmp_func), collation(cmp_coll),
     count(elements), used_count(elements) {}
unknown's avatar
unknown committed
590 591 592 593
  virtual ~in_vector() {}
  virtual void set(uint pos,Item *item)=0;
  virtual byte *get_value(Item *item)=0;
  void sort()
594
  {
595
    qsort2(base,used_count,size,compare,collation);
596
  }
unknown's avatar
unknown committed
597 598 599 600 601 602 603 604
  int find(Item *item);
};

class in_string :public in_vector
{
  char buff[80];
  String tmp;
public:
605
  in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
unknown's avatar
unknown committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
  ~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:
636 637
  CHARSET_INFO *cmp_charset;
  cmp_item() { cmp_charset= &my_charset_bin; }
unknown's avatar
unknown committed
638
  virtual ~cmp_item() {}
unknown's avatar
unknown committed
639 640 641 642
  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;
643
  static cmp_item* get_comparator(Item *);
unknown's avatar
unknown committed
644 645 646 647 648
  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
649 650
};

unknown's avatar
unknown committed
651 652 653 654 655
class cmp_item_string :public cmp_item 
{
protected:
  String *value_res;
public:
656
  cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
unknown's avatar
unknown committed
657 658 659
  friend class cmp_item_sort_string;
  friend class cmp_item_sort_string_in_static;
};
unknown's avatar
unknown committed
660

unknown's avatar
unknown committed
661 662 663
class cmp_item_sort_string :public cmp_item_string
{
protected:
unknown's avatar
unknown committed
664
  char value_buff[80];
unknown's avatar
unknown committed
665
  String value;
unknown's avatar
unknown committed
666
public:
667 668 669
  cmp_item_sort_string(CHARSET_INFO *cs):
    cmp_item_string(cs),
    value(value_buff, sizeof(value_buff), cs) {}
unknown's avatar
unknown committed
670
  void store_value(Item *item)
unknown's avatar
unknown committed
671 672 673
  {
    value_res= item->val_str(&value);
  }
unknown's avatar
unknown committed
674
  int cmp(Item *arg)
unknown's avatar
unknown committed
675 676
  {
    char buff[80];
unknown's avatar
unknown committed
677
    String tmp(buff, sizeof(buff), cmp_charset), *res;
unknown's avatar
unknown committed
678 679
    if (!(res= arg->val_str(&tmp)))
      return 1;				/* Can't be right */
680
    return sortcmp(value_res, res, cmp_charset);
unknown's avatar
unknown committed
681 682 683 684
  }
  int compare(cmp_item *c)
  {
    cmp_item_string *cmp= (cmp_item_string *)c;
685
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
686 687
  } 
  cmp_item *make_same();
unknown's avatar
unknown committed
688 689 690 691 692 693 694
};

class cmp_item_int :public cmp_item
{
  longlong value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
695 696 697
  {
    value= item->val_int();
  }
unknown's avatar
unknown committed
698
  int cmp(Item *arg)
unknown's avatar
unknown committed
699 700 701 702 703 704 705 706 707
  {
    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
708 709 710 711 712 713 714
};

class cmp_item_real :public cmp_item
{
  double value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
715 716 717
  {
    value= item->val();
  }
unknown's avatar
unknown committed
718
  int cmp(Item *arg)
unknown's avatar
unknown committed
719 720 721 722 723 724 725 726 727
  {
    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
728 729
};

730 731 732 733 734
class cmp_item_row :public cmp_item
{
  cmp_item **comparators;
  uint n;
public:
unknown's avatar
unknown committed
735
  cmp_item_row(): comparators(0), n(0) {}
736
  ~cmp_item_row();
737 738
  void store_value(Item *item);
  int cmp(Item *arg);
unknown's avatar
unknown committed
739 740 741 742 743 744 745 746 747 748 749
  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 *);
750
  ~in_row();
unknown's avatar
unknown committed
751 752 753 754 755 756 757 758 759 760 761 762 763 764
  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:
765 766
  cmp_item_sort_string_in_static(CHARSET_INFO *cs):
    cmp_item_string(cs) {}
unknown's avatar
unknown committed
767 768 769 770 771 772 773 774 775 776 777 778 779
  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;
780
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
781
  }
782
  cmp_item *make_same()
unknown's avatar
unknown committed
783
  {
784
    return new cmp_item_sort_string_in_static(cmp_charset);
unknown's avatar
unknown committed
785
  }
786
};
unknown's avatar
unknown committed
787

unknown's avatar
unknown committed
788
class Item_func_in :public Item_func_opt_neg
unknown's avatar
unknown committed
789
{
790
  Item_result cmp_type;
unknown's avatar
unknown committed
791 792
  in_vector *array;
  cmp_item *in_item;
793
  bool have_null;
794
  DTCollation cmp_collation;
unknown's avatar
unknown committed
795
 public:
796
  Item_func_in(List<Item> &list)
unknown's avatar
unknown committed
797
    :Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
798
  {
799
    allowed_arg_cols= 0;  // Fetch this value from first argument
800
  }
unknown's avatar
unknown committed
801
  longlong val_int();
unknown's avatar
unknown committed
802
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
803
  void fix_length_and_dec();
804 805
  void cleanup()
  {
unknown's avatar
unknown committed
806
    DBUG_ENTER("Item_func_in::cleanup");
807
    Item_int_func::cleanup();
808 809 810 811
    delete array;
    delete in_item;
    array= 0;
    in_item= 0;
unknown's avatar
unknown committed
812
    DBUG_VOID_RETURN;
813
  }
unknown's avatar
unknown committed
814 815 816 817 818
  optimize_type select_optimize() const
    { return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
  void print(String *str);
  enum Functype functype() const { return IN_FUNC; }
  const char *func_name() const { return " IN "; }
unknown's avatar
unknown committed
819
  bool nulls_in_row();
unknown's avatar
unknown committed
820
  bool is_bool_func() { return 1; }
821
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
822 823 824 825 826 827
};

/* Functions used by where clause */

class Item_func_isnull :public Item_bool_func
{
828
protected:
unknown's avatar
unknown committed
829
  longlong cached_value;
unknown's avatar
unknown committed
830 831 832 833 834 835 836
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;
837
    update_used_tables();
unknown's avatar
unknown committed
838 839 840
  }
  const char *func_name() const { return "isnull"; }
  /* Optimize case of not_null_column IS NULL */
841
  virtual void update_used_tables()
unknown's avatar
unknown committed
842 843 844
  {
    if (!args[0]->maybe_null)
    {
845
      used_tables_cache= 0;			/* is always false */
846
      const_item_cache= 1;
847
      cached_value= (longlong) 0;
unknown's avatar
unknown committed
848
    }
849
    else
unknown's avatar
unknown committed
850
    {
851
      args[0]->update_used_tables();
unknown's avatar
unknown committed
852 853
      if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())) &&
           !with_subselect)
854 855
      {
	/* Remember if the value is always NULL or never NULL */
856
	cached_value= (longlong) args[0]->is_null();
857
      }
unknown's avatar
unknown committed
858
    }
unknown's avatar
unknown committed
859
  }
860
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
861
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
862
  Item *neg_transformer(THD *thd);
863
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
864 865
};

866 867 868 869 870 871 872 873 874 875
/* 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)
  {}
876
  enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
877
  longlong val_int();
878
  const char *func_name() const { return "<is_not_null_test>"; }
879
  void update_used_tables();
880 881 882 883 884
  /*
    we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
  */
  table_map used_tables() const
    { return used_tables_cache | RAND_TABLE_BIT; }
885 886 887
};


unknown's avatar
unknown committed
888 889 890 891 892 893
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
894 895 896 897
  void fix_length_and_dec()
  {
    decimals=0; max_length=1; maybe_null=0;
  }
unknown's avatar
unknown committed
898 899
  const char *func_name() const { return "isnotnull"; }
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
900
  table_map not_null_tables() const { return 0; }
901
  Item *neg_transformer(THD *thd);
902
  void print(String *str);
903
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
904 905
};

906

unknown's avatar
unknown committed
907 908
class Item_func_like :public Item_bool_func2
{
909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
  // 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 };

924 925
  Item *escape_item;

unknown's avatar
unknown committed
926
public:
unknown's avatar
unknown committed
927
  int escape;
928

929
  Item_func_like(Item *a,Item *b, Item *escape_arg)
unknown's avatar
unknown committed
930
    :Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0), 
931
     bmGs(0), bmBc(0), escape_item(escape_arg) {}
unknown's avatar
unknown committed
932 933 934 935 936
  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
937
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
938
  void cleanup();
unknown's avatar
unknown committed
939 940 941 942
};

#ifdef USE_REGEX

unknown's avatar
unknown committed
943
#include "my_regex.h"
unknown's avatar
unknown committed
944 945 946

class Item_func_regex :public Item_bool_func
{
unknown's avatar
unknown committed
947
  my_regex_t preg;
unknown's avatar
unknown committed
948 949 950
  bool regex_compiled;
  bool regex_is_const;
  String prev_regexp;
951
  DTCollation cmp_collation;
unknown's avatar
unknown committed
952 953 954
public:
  Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
    regex_compiled(0),regex_is_const(0) {}
955
  void cleanup();
unknown's avatar
unknown committed
956
  longlong val_int();
unknown's avatar
unknown committed
957
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
958
  const char *func_name() const { return "regexp"; }
959
  void print(String *str) { print_op(str); }
960
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
961 962 963 964 965 966 967 968 969 970
};

#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"; }
971
  void print(String *str) { print_op(str); }
unknown's avatar
unknown committed
972 973 974 975 976 977 978 979 980 981 982
};

#endif /* USE_REGEX */


typedef class Item COND;

class Item_cond :public Item_bool_func
{
protected:
  List<Item> list;
983
  bool abort_on_null;
984 985
  table_map and_tables_cache;

unknown's avatar
unknown committed
986
public:
987
  /* Item_cond() is only used to create top level items */
988 989
  Item_cond(): Item_bool_func(), abort_on_null(1)
  { const_item_cache=0; }
990 991 992 993 994 995
  Item_cond(Item *i1,Item *i2) 
    :Item_bool_func(), abort_on_null(0)
  {
    list.push_back(i1);
    list.push_back(i2);
  }
996
  Item_cond(THD *thd, Item_cond *item);
997 998
  Item_cond(List<Item> &nlist)
    :Item_bool_func(), list(nlist), abort_on_null(0) {}
unknown's avatar
unknown committed
999
  bool add(Item *item) { return list.push_back(item); }
unknown's avatar
unknown committed
1000
  bool fix_fields(THD *, struct st_table_list *, Item **ref);
unknown's avatar
unknown committed
1001 1002 1003 1004 1005 1006

  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);
1007
  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
unknown's avatar
unknown committed
1008
  friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
1009
  void top_level_item() { abort_on_null=1; }
1010
  void copy_andor_arguments(THD *thd, Item_cond *item);
unknown's avatar
unknown committed
1011
  bool walk(Item_processor processor, byte *arg);
1012
  void neg_arguments(THD *thd);
unknown's avatar
unknown committed
1013 1014 1015 1016 1017 1018 1019 1020
};


class Item_cond_and :public Item_cond
{
public:
  Item_cond_and() :Item_cond() {}
  Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
1021
  Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
1022
  Item_cond_and(List<Item> &list): Item_cond(list) {}
unknown's avatar
unknown committed
1023 1024 1025
  enum Functype functype() const { return COND_AND_FUNC; }
  longlong val_int();
  const char *func_name() const { return "and"; }
1026 1027
  table_map not_null_tables() const
  { return abort_on_null ? not_null_tables_cache: and_tables_cache; }
1028 1029 1030
  Item* copy_andor_structure(THD *thd)
  {
    Item_cond_and *item;
unknown's avatar
merge  
unknown committed
1031
    if ((item= new Item_cond_and(thd, this)))
1032 1033 1034
       item->copy_andor_arguments(thd, this);
    return item;
  }
1035
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
1036 1037 1038 1039 1040 1041 1042
};

class Item_cond_or :public Item_cond
{
public:
  Item_cond_or() :Item_cond() {}
  Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
1043
  Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {}
1044
  Item_cond_or(List<Item> &list): Item_cond(list) {}
unknown's avatar
unknown committed
1045 1046 1047
  enum Functype functype() const { return COND_OR_FUNC; }
  longlong val_int();
  const char *func_name() const { return "or"; }
1048
  table_map not_null_tables() const { return and_tables_cache; }
1049 1050 1051
  Item* copy_andor_structure(THD *thd)
  {
    Item_cond_or *item;
unknown's avatar
merge  
unknown committed
1052
    if ((item= new Item_cond_or(thd, this)))
1053 1054 1055
      item->copy_andor_arguments(thd, this);
    return item;
  }
1056
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
1057 1058 1059
};


1060 1061 1062 1063
/*
  XOR is Item_cond, not an Item_int_func bevause we could like to
  optimize (a XOR b) later on. It's low prio, though
*/
unknown's avatar
unknown committed
1064

unknown's avatar
unknown committed
1065 1066 1067 1068 1069 1070
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; }
1071 1072
  /* TODO: remove the next line when implementing XOR optimization */
  enum Type type() const { return FUNC_ITEM; }
unknown's avatar
unknown committed
1073 1074
  longlong val_int();
  const char *func_name() const { return "xor"; }
1075
  void top_level_item() {}
unknown's avatar
unknown committed
1076 1077 1078
};


unknown's avatar
unknown committed
1079 1080
/* Some usefull inline functions */

unknown's avatar
unknown committed
1081
inline Item *and_conds(Item *a, Item *b)
unknown's avatar
unknown committed
1082 1083 1084
{
  if (!b) return a;
  if (!a) return b;
unknown's avatar
unknown committed
1085
  return new Item_cond_and(a, b);
unknown's avatar
unknown committed
1086
}
unknown's avatar
unknown committed
1087

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