item_cmpfunc.h 29.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 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
  Arg_comparator() {};
  Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};

  int set_compare_func(Item_bool_func2 *owner, Item_result type);
44
  inline int set_compare_func(Item_bool_func2 *owner_arg)
45
  {
46 47 48 49 50
    Item_result ar= (*a)->result_as_longlong() && (*b)->const_item() ?
                      INT_RESULT : (*a)->result_type();
    Item_result br= (*b)->result_as_longlong() && (*a)->const_item() ?
                      INT_RESULT : (*b)->result_type();
    return set_compare_func(owner_arg, item_cmp_type(ar, br));
51
  }
52
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
53 54 55 56 57
			  Item **a1, Item **a2,
			  Item_result type)
  {
    a= a1;
    b= a2;
58
    return set_compare_func(owner_arg, type);
59
  }
60
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
61 62
			  Item **a1, Item **a2)
  {
63 64 65 66 67
    Item_result ar= (*a1)->result_as_longlong() && (*a2)->const_item() ?
                      INT_RESULT : (*a1)->result_type();
    Item_result br= (*a2)->result_as_longlong() && (*a1)->const_item() ?
                      INT_RESULT : (*a2)->result_type();
    return set_cmp_func(owner_arg, a1, a2, item_cmp_type(ar, br));
68 69 70 71
  }
  inline int compare() { return (this->*func)(); }

  int compare_string();		 // compare args[0] & args[1]
unknown's avatar
unknown committed
72
  int compare_binary_string();	 // compare args[0] & args[1]
73
  int compare_real();            // compare args[0] & args[1]
74
  int compare_int_signed();      // compare args[0] & args[1]
75 76 77
  int compare_int_signed_unsigned();
  int compare_int_unsigned_signed();
  int compare_int_unsigned();
78 79
  int compare_row();             // compare args[0] & args[1]
  int compare_e_string();	 // compare args[0] & args[1]
unknown's avatar
unknown committed
80
  int compare_e_binary_string(); // compare args[0] & args[1]
81 82
  int compare_e_real();          // compare args[0] & args[1]
  int compare_e_int();           // compare args[0] & args[1]
83
  int compare_e_int_diff_signedness();
84 85 86 87 88 89 90
  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
91 92 93 94 95 96
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) {}
97
  Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
unknown's avatar
unknown committed
98
  bool is_bool_func() { return 1; }
unknown's avatar
unknown committed
99 100 101
  void fix_length_and_dec() { decimals=0; max_length=1; }
};

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

unknown's avatar
unknown committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
class Comp_creator
{
public:
  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:
  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:
  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:
  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:
  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:
  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:
  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
192 193 194
class Item_bool_func2 :public Item_int_func
{						/* Bool with 2 string args */
protected:
195
  Arg_comparator cmp;
unknown's avatar
unknown committed
196
  String tmp_value1,tmp_value2;
197

unknown's avatar
unknown committed
198
public:
199 200
  Item_bool_func2(Item *a,Item *b)
    :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
unknown's avatar
unknown committed
201
  void fix_length_and_dec();
202
  void set_cmp_func()
unknown's avatar
unknown committed
203
  {
204
    cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
unknown's avatar
unknown committed
205
  }
unknown's avatar
unknown committed
206 207 208 209
  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
210
  bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
unknown's avatar
unknown committed
211
  bool is_bool_func() { return 1; }
212
  CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
unknown's avatar
unknown committed
213

214
  friend class  Arg_comparator;
unknown's avatar
unknown committed
215 216
};

unknown's avatar
unknown committed
217 218 219
class Item_bool_rowready_func2 :public Item_bool_func2
{
public:
220
  Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b)
unknown's avatar
unknown committed
221
  {
222
    allowed_arg_cols= 0;  // Fetch this value from first argument
unknown's avatar
unknown committed
223
  }
224 225
  Item *neg_transformer(THD *thd);
  virtual Item *negated_item();
unknown's avatar
unknown committed
226
};
unknown's avatar
unknown committed
227 228 229 230 231 232

class Item_func_not :public Item_bool_func
{
public:
  Item_func_not(Item *a) :Item_bool_func(a) {}
  longlong val_int();
233
  enum Functype functype() const { return NOT_FUNC; }
unknown's avatar
unknown committed
234
  const char *func_name() const { return "not"; }
235
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
236 237
};

238
class Item_maxmin_subselect;
239 240
class Item_func_not_all :public Item_func_not
{
241 242 243 244
  /* allow to check presence od values in max/min optimisation */
  Item_sum_hybrid *test_sum_item;
  Item_maxmin_subselect *test_sub_item;

245 246
  bool abort_on_null;
public:
unknown's avatar
unknown committed
247 248
  bool show;

249 250 251 252
  Item_func_not_all(Item *a)
    :Item_func_not(a), test_sum_item(0), test_sub_item(0), abort_on_null(0),
     show(0)
    {}
253 254 255
  virtual void top_level_item() { abort_on_null= 1; }
  bool top_level() { return abort_on_null; }
  longlong val_int();
256
  enum Functype functype() const { return NOT_ALL_FUNC; }
unknown's avatar
unknown committed
257 258
  const char *func_name() const { return "<not>"; }
  void print(String *str);
259 260 261
  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();
262 263
};

264 265 266 267 268 269 270 271 272 273 274

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


unknown's avatar
unknown committed
275
class Item_func_eq :public Item_bool_rowready_func2
unknown's avatar
unknown committed
276 277
{
public:
278
  Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
279 280 281 282 283
  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 "="; }
284
  Item *negated_item();
unknown's avatar
unknown committed
285 286
};

unknown's avatar
unknown committed
287
class Item_func_equal :public Item_bool_rowready_func2
unknown's avatar
unknown committed
288 289
{
public:
unknown's avatar
unknown committed
290
  Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
291
  longlong val_int();
unknown's avatar
unknown committed
292
  void fix_length_and_dec();
293
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
294 295 296 297
  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 "<=>"; }
298
  Item *neg_transformer(THD *thd) { return 0; }
unknown's avatar
unknown committed
299 300 301
};


unknown's avatar
unknown committed
302
class Item_func_ge :public Item_bool_rowready_func2
unknown's avatar
unknown committed
303 304
{
public:
305
  Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
306 307 308 309 310
  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 ">="; }
311
  Item *negated_item();
unknown's avatar
unknown committed
312 313 314
};


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


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


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


unknown's avatar
unknown committed
354
class Item_func_ne :public Item_bool_rowready_func2
unknown's avatar
unknown committed
355 356
{
public:
357
  Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
358 359 360
  longlong val_int();
  enum Functype functype() const { return NE_FUNC; }
  cond_result eq_cmp_result() const { return COND_FALSE; }
unknown's avatar
unknown committed
361
  optimize_type select_optimize() const { return OPTIMIZE_KEY; } 
unknown's avatar
unknown committed
362
  const char *func_name() const { return "<>"; }
363
  Item *negated_item();
unknown's avatar
unknown committed
364 365 366
};


unknown's avatar
unknown committed
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
/*
  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;
  }
};


class Item_func_between :public Item_func_opt_neg
unknown's avatar
unknown committed
398
{
399
  DTCollation cmp_collation;
unknown's avatar
unknown committed
400 401 402
public:
  Item_result cmp_type;
  String value0,value1,value2;
unknown's avatar
unknown committed
403 404
  Item_func_between(Item *a, Item *b, Item *c)
    :Item_func_opt_neg(a, b, c) {}
unknown's avatar
unknown committed
405 406 407 408
  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
409
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
410
  void fix_length_and_dec();
411
  void print(String *str);
412
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
};


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
{
428
  Item_row *row;
unknown's avatar
unknown committed
429 430
  double *intervals;
public:
431
  Item_func_interval(Item_row *a)
432 433 434 435
    :Item_int_func(a),row(a),intervals(0)
  {
    allowed_arg_cols= 0;    // Fetch this value from first argument
  }
unknown's avatar
unknown committed
436 437 438 439 440 441 442 443 444
  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;
445 446
  enum_field_types cached_field_type;
  bool field_type_defined;
unknown's avatar
unknown committed
447
public:
448 449 450
  Item_func_ifnull(Item *a,Item *b)
    :Item_func(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
451 452 453 454
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
455
  enum_field_types field_type() const;
unknown's avatar
unknown committed
456 457
  void fix_length_and_dec();
  const char *func_name() const { return "ifnull"; }
458
  Field *tmp_table_field(TABLE *table);
459
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
460 461 462 463 464 465 466
};


class Item_func_if :public Item_func
{
  enum Item_result cached_result_type;
public:
467 468 469
  Item_func_if(Item *a,Item *b,Item *c)
    :Item_func(a,b,c), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
470 471 472 473
  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
474
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
475 476 477 478 479 480 481 482 483
  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:
484 485 486
  Item_func_nullif(Item *a,Item *b)
    :Item_bool_func2(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
487 488 489 490 491 492
  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"; }
493
  void print(String *str) { Item_func::print(str); }
494
  table_map not_null_tables() const { return 0; }
495
  bool is_null();
unknown's avatar
unknown committed
496 497 498 499 500 501 502
};


class Item_func_coalesce :public Item_func
{
  enum Item_result cached_result_type;
public:
503 504 505
  Item_func_coalesce(List<Item> &list)
    :Item_func(list),cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
506 507 508 509 510 511
  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"; }
512
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
513 514
};

515

unknown's avatar
unknown committed
516 517
class Item_func_case :public Item_func
{
518
  int first_expr_num, else_expr_num;
unknown's avatar
unknown committed
519 520
  enum Item_result cached_result_type;
  String tmp_value;
521
  uint ncases;
522 523
  Item_result cmp_type;
  DTCollation cmp_collation;
unknown's avatar
unknown committed
524
public:
525
  Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
526
    :Item_func(), first_expr_num(-1), else_expr_num(-1),
527
    cached_result_type(INT_RESULT)
528 529 530 531 532 533 534 535 536 537 538 539 540 541
  { 
    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
542 543 544 545
  double val();
  longlong val_int();
  String *val_str(String *);
  void fix_length_and_dec();
546
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
547 548 549 550
  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);
551
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
552 553 554 555 556 557 558 559 560 561
};


/* Functions to handle the optimized IN */

class in_vector :public Sql_alloc
{
 protected:
  char *base;
  uint size;
562 563
  qsort2_cmp compare;
  CHARSET_INFO *collation;
unknown's avatar
unknown committed
564 565 566
  uint count;
public:
  uint used_count;
unknown's avatar
unknown committed
567
  in_vector() {}
568 569
  in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, 
  	    CHARSET_INFO *cmp_coll)
unknown's avatar
unknown committed
570
    :base((char*) sql_calloc(elements*element_length)),
571 572
     size(element_length), compare(cmp_func), collation(cmp_coll),
     count(elements), used_count(elements) {}
unknown's avatar
unknown committed
573 574 575 576
  virtual ~in_vector() {}
  virtual void set(uint pos,Item *item)=0;
  virtual byte *get_value(Item *item)=0;
  void sort()
577
  {
578
    qsort2(base,used_count,size,compare,collation);
579
  }
unknown's avatar
unknown committed
580 581 582 583 584 585 586 587
  int find(Item *item);
};

class in_string :public in_vector
{
  char buff[80];
  String tmp;
public:
588
  in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
unknown's avatar
unknown committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
  ~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:
619 620
  CHARSET_INFO *cmp_charset;
  cmp_item() { cmp_charset= &my_charset_bin; }
unknown's avatar
unknown committed
621
  virtual ~cmp_item() {}
unknown's avatar
unknown committed
622 623 624 625
  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;
626
  static cmp_item* get_comparator(Item *);
unknown's avatar
unknown committed
627 628 629 630 631
  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
632 633
};

unknown's avatar
unknown committed
634 635 636 637 638
class cmp_item_string :public cmp_item 
{
protected:
  String *value_res;
public:
639
  cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
unknown's avatar
unknown committed
640 641 642
  friend class cmp_item_sort_string;
  friend class cmp_item_sort_string_in_static;
};
unknown's avatar
unknown committed
643

unknown's avatar
unknown committed
644 645 646
class cmp_item_sort_string :public cmp_item_string
{
protected:
unknown's avatar
unknown committed
647
  char value_buff[80];
unknown's avatar
unknown committed
648
  String value;
unknown's avatar
unknown committed
649
public:
650 651 652
  cmp_item_sort_string(CHARSET_INFO *cs):
    cmp_item_string(cs),
    value(value_buff, sizeof(value_buff), cs) {}
unknown's avatar
unknown committed
653
  void store_value(Item *item)
unknown's avatar
unknown committed
654 655 656
  {
    value_res= item->val_str(&value);
  }
unknown's avatar
unknown committed
657
  int cmp(Item *arg)
unknown's avatar
unknown committed
658 659
  {
    char buff[80];
unknown's avatar
unknown committed
660
    String tmp(buff, sizeof(buff), cmp_charset), *res;
unknown's avatar
unknown committed
661 662
    if (!(res= arg->val_str(&tmp)))
      return 1;				/* Can't be right */
663
    return sortcmp(value_res, res, cmp_charset);
unknown's avatar
unknown committed
664 665 666 667
  }
  int compare(cmp_item *c)
  {
    cmp_item_string *cmp= (cmp_item_string *)c;
668
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
669 670
  } 
  cmp_item *make_same();
unknown's avatar
unknown committed
671 672 673 674 675 676 677
};

class cmp_item_int :public cmp_item
{
  longlong value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
678 679 680
  {
    value= item->val_int();
  }
unknown's avatar
unknown committed
681
  int cmp(Item *arg)
unknown's avatar
unknown committed
682 683 684 685 686 687 688 689 690
  {
    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
691 692 693 694 695 696 697
};

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

713 714 715 716 717
class cmp_item_row :public cmp_item
{
  cmp_item **comparators;
  uint n;
public:
unknown's avatar
unknown committed
718
  cmp_item_row(): comparators(0), n(0) {}
719
  ~cmp_item_row();
720 721
  void store_value(Item *item);
  int cmp(Item *arg);
unknown's avatar
unknown committed
722 723 724 725 726 727 728 729 730 731 732
  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 *);
733
  ~in_row();
unknown's avatar
unknown committed
734 735 736 737 738 739 740 741 742 743 744 745 746 747
  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:
748 749
  cmp_item_sort_string_in_static(CHARSET_INFO *cs):
    cmp_item_string(cs) {}
unknown's avatar
unknown committed
750 751 752 753 754 755 756 757 758 759 760 761 762
  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;
763
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
764
  }
765
  cmp_item *make_same()
unknown's avatar
unknown committed
766
  {
767
    return new cmp_item_sort_string_in_static(cmp_charset);
unknown's avatar
unknown committed
768
  }
769
};
unknown's avatar
unknown committed
770

unknown's avatar
unknown committed
771
class Item_func_in :public Item_func_opt_neg
unknown's avatar
unknown committed
772
{
773
  Item_result cmp_type;
unknown's avatar
unknown committed
774 775
  in_vector *array;
  cmp_item *in_item;
776
  bool have_null;
777
  DTCollation cmp_collation;
unknown's avatar
unknown committed
778
 public:
779
  Item_func_in(List<Item> &list)
unknown's avatar
unknown committed
780
    :Item_func_opt_neg(list), array(0), in_item(0), have_null(0)
781
  {
782
    allowed_arg_cols= 0;  // Fetch this value from first argument
783
  }
unknown's avatar
unknown committed
784
  longlong val_int();
unknown's avatar
unknown committed
785
  bool fix_fields(THD *, struct st_table_list *, Item **);
unknown's avatar
unknown committed
786
  void fix_length_and_dec();
787 788
  void cleanup()
  {
unknown's avatar
unknown committed
789
    DBUG_ENTER("Item_func_in::cleanup");
790
    Item_int_func::cleanup();
791 792 793 794
    delete array;
    delete in_item;
    array= 0;
    in_item= 0;
unknown's avatar
unknown committed
795
    DBUG_VOID_RETURN;
796
  }
unknown's avatar
unknown committed
797 798 799 800 801
  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
802
  bool nulls_in_row();
unknown's avatar
unknown committed
803
  bool is_bool_func() { return 1; }
804
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
805 806 807 808 809 810
};

/* Functions used by where clause */

class Item_func_isnull :public Item_bool_func
{
811
protected:
unknown's avatar
unknown committed
812
  longlong cached_value;
unknown's avatar
unknown committed
813 814 815 816 817 818 819
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;
820
    update_used_tables();
unknown's avatar
unknown committed
821 822 823
  }
  const char *func_name() const { return "isnull"; }
  /* Optimize case of not_null_column IS NULL */
824
  virtual void update_used_tables()
unknown's avatar
unknown committed
825 826 827
  {
    if (!args[0]->maybe_null)
    {
828
      used_tables_cache= 0;			/* is always false */
829
      const_item_cache= 1;
830
      cached_value= (longlong) 0;
unknown's avatar
unknown committed
831
    }
832
    else
unknown's avatar
unknown committed
833
    {
834
      args[0]->update_used_tables();
835
      if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())))
836 837
      {
	/* Remember if the value is always NULL or never NULL */
838
	cached_value= (longlong) args[0]->is_null();
839
      }
unknown's avatar
unknown committed
840
    }
unknown's avatar
unknown committed
841
  }
842
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
843
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
844
  Item *neg_transformer(THD *thd);
845
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
846 847
};

848 849 850 851 852 853 854 855 856 857
/* 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)
  {}
858
  enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
859
  longlong val_int();
860
  const char *func_name() const { return "<is_not_null_test>"; }
861
  void update_used_tables();
862 863 864 865 866
  /*
    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; }
867 868 869
};


unknown's avatar
unknown committed
870 871 872 873 874 875
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
876 877 878 879
  void fix_length_and_dec()
  {
    decimals=0; max_length=1; maybe_null=0;
  }
unknown's avatar
unknown committed
880 881
  const char *func_name() const { return "isnotnull"; }
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
882
  table_map not_null_tables() const { return 0; }
883
  Item *neg_transformer(THD *thd);
884
  void print(String *str);
885
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
886 887
};

888

unknown's avatar
unknown committed
889 890
class Item_func_like :public Item_bool_func2
{
891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
  // 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 };

906 907
  Item *escape_item;

unknown's avatar
unknown committed
908
public:
unknown's avatar
unknown committed
909
  int escape;
910

911
  Item_func_like(Item *a,Item *b, Item *escape_arg)
unknown's avatar
unknown committed
912
    :Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0), 
913
     bmGs(0), bmBc(0), escape_item(escape_arg) {}
unknown's avatar
unknown committed
914 915 916 917 918
  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
919
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
920
  void cleanup();
unknown's avatar
unknown committed
921 922 923 924
};

#ifdef USE_REGEX

unknown's avatar
unknown committed
925
#include "my_regex.h"
unknown's avatar
unknown committed
926 927 928

class Item_func_regex :public Item_bool_func
{
unknown's avatar
unknown committed
929
  my_regex_t preg;
unknown's avatar
unknown committed
930 931 932
  bool regex_compiled;
  bool regex_is_const;
  String prev_regexp;
933
  DTCollation cmp_collation;
unknown's avatar
unknown committed
934 935 936
public:
  Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b),
    regex_compiled(0),regex_is_const(0) {}
937
  void cleanup();
unknown's avatar
unknown committed
938
  longlong val_int();
unknown's avatar
unknown committed
939
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
940
  const char *func_name() const { return "regexp"; }
941
  void print(String *str) { print_op(str); }
942
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
943 944 945 946 947 948 949 950 951 952
};

#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"; }
953
  void print(String *str) { print_op(str); }
unknown's avatar
unknown committed
954 955 956 957 958 959 960 961 962 963 964
};

#endif /* USE_REGEX */


typedef class Item COND;

class Item_cond :public Item_bool_func
{
protected:
  List<Item> list;
965
  bool abort_on_null;
966 967
  table_map and_tables_cache;

unknown's avatar
unknown committed
968
public:
969
  /* Item_cond() is only used to create top level items */
970 971
  Item_cond(): Item_bool_func(), abort_on_null(1)
  { const_item_cache=0; }
972 973 974 975 976 977
  Item_cond(Item *i1,Item *i2) 
    :Item_bool_func(), abort_on_null(0)
  {
    list.push_back(i1);
    list.push_back(i2);
  }
978
  Item_cond(THD *thd, Item_cond *item);
979 980
  Item_cond(List<Item> &nlist)
    :Item_bool_func(), list(nlist), abort_on_null(0) {}
unknown's avatar
unknown committed
981
  bool add(Item *item) { return list.push_back(item); }
unknown's avatar
unknown committed
982
  bool fix_fields(THD *, struct st_table_list *, Item **ref);
unknown's avatar
unknown committed
983 984 985 986 987 988

  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);
989
  void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
unknown's avatar
unknown committed
990
  friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
991
  void top_level_item() { abort_on_null=1; }
992
  void copy_andor_arguments(THD *thd, Item_cond *item);
unknown's avatar
unknown committed
993
  bool walk(Item_processor processor, byte *arg);
994
  void neg_arguments(THD *thd);
unknown's avatar
unknown committed
995 996 997 998 999 1000 1001 1002
};


class Item_cond_and :public Item_cond
{
public:
  Item_cond_and() :Item_cond() {}
  Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
1003
  Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
1004
  Item_cond_and(List<Item> &list): Item_cond(list) {}
unknown's avatar
unknown committed
1005 1006 1007
  enum Functype functype() const { return COND_AND_FUNC; }
  longlong val_int();
  const char *func_name() const { return "and"; }
1008 1009
  table_map not_null_tables() const
  { return abort_on_null ? not_null_tables_cache: and_tables_cache; }
1010 1011 1012
  Item* copy_andor_structure(THD *thd)
  {
    Item_cond_and *item;
unknown's avatar
merge  
unknown committed
1013
    if ((item= new Item_cond_and(thd, this)))
1014 1015 1016
       item->copy_andor_arguments(thd, this);
    return item;
  }
1017
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
1018 1019 1020 1021 1022 1023 1024
};

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


1042 1043 1044 1045
/*
  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
1046

unknown's avatar
unknown committed
1047 1048 1049 1050 1051 1052
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; }
1053 1054
  /* TODO: remove the next line when implementing XOR optimization */
  enum Type type() const { return FUNC_ITEM; }
unknown's avatar
unknown committed
1055 1056
  longlong val_int();
  const char *func_name() const { return "xor"; }
1057
  void top_level_item() {}
unknown's avatar
unknown committed
1058 1059 1060
};


unknown's avatar
unknown committed
1061 1062
/* Some usefull inline functions */

unknown's avatar
unknown committed
1063
inline Item *and_conds(Item *a, Item *b)
unknown's avatar
unknown committed
1064 1065 1066
{
  if (!b) return a;
  if (!a) return b;
unknown's avatar
unknown committed
1067
  return new Item_cond_and(a, b);
unknown's avatar
unknown committed
1068
}
unknown's avatar
unknown committed
1069

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