item_cmpfunc.h 28.8 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
  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
    return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(),
						     (*b)->result_type()));
48
  }
49
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
50 51 52 53 54
			  Item **a1, Item **a2,
			  Item_result type)
  {
    a= a1;
    b= a2;
55
    return set_compare_func(owner_arg, type);
56
  }
57
  inline int set_cmp_func(Item_bool_func2 *owner_arg,
58 59
			  Item **a1, Item **a2)
  {
60 61
    return set_cmp_func(owner_arg, a1, a2, item_cmp_type((*a1)->result_type(),
							 (*a2)->result_type()));
62 63 64 65
  }
  inline int compare() { return (this->*func)(); }

  int compare_string();		 // compare args[0] & args[1]
unknown's avatar
unknown committed
66
  int compare_binary_string();	 // compare args[0] & args[1]
67 68 69 70
  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]
unknown's avatar
unknown committed
71
  int compare_e_binary_string(); // compare args[0] & args[1]
72 73 74 75 76 77 78 79 80
  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
81 82 83 84 85 86
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) {}
87
  Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
unknown's avatar
unknown committed
88 89 90
  void fix_length_and_dec() { decimals=0; max_length=1; }
};

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

unknown's avatar
unknown committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 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
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
181 182 183
class Item_bool_func2 :public Item_int_func
{						/* Bool with 2 string args */
protected:
184
  Arg_comparator cmp;
unknown's avatar
unknown committed
185
  String tmp_value1,tmp_value2;
186

unknown's avatar
unknown committed
187
public:
188 189
  Item_bool_func2(Item *a,Item *b)
    :Item_int_func(a,b), cmp(tmp_arg, tmp_arg+1) {}
unknown's avatar
unknown committed
190
  void fix_length_and_dec();
191
  void set_cmp_func()
unknown's avatar
unknown committed
192
  {
193
    cmp.set_cmp_func(this, tmp_arg, tmp_arg+1);
unknown's avatar
unknown committed
194
  }
unknown's avatar
unknown committed
195 196 197 198
  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
199
  bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
200
  CHARSET_INFO *compare_collation() { return cmp.cmp_collation.collation; }
unknown's avatar
unknown committed
201

202
  friend class  Arg_comparator;
unknown's avatar
unknown committed
203 204
};

unknown's avatar
unknown committed
205 206
class Item_bool_rowready_func2 :public Item_bool_func2
{
unknown's avatar
unknown committed
207
  Item *orig_a, *orig_b; /* propagate_const can change parameters */
unknown's avatar
unknown committed
208
public:
unknown's avatar
unknown committed
209 210
  Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b),
    orig_a(a), orig_b(b)
unknown's avatar
unknown committed
211 212 213
  {
    allowed_arg_cols= a->cols();
  }
unknown's avatar
unknown committed
214 215
  void cleanup()
  {
unknown's avatar
unknown committed
216
    DBUG_ENTER("Item_bool_rowready_func2::cleanup");
unknown's avatar
unknown committed
217 218 219
    Item_bool_func2::cleanup();
    tmp_arg[0]= orig_a;
    tmp_arg[1]= orig_b;
unknown's avatar
unknown committed
220
    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
221
  }
222 223
  Item *neg_transformer(THD *thd);
  virtual Item *negated_item();
unknown's avatar
unknown committed
224
};
unknown's avatar
unknown committed
225 226 227 228 229 230

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

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269

/*
  The class Item_func_trig_cond is used for guarded predicates 
  which are employed only for internal purposes.
  A guarded predicates is an object consisting of an a regular or
  a guarded predicate P and a pointer to a boolean guard variable g. 
  A guarded predicate P/g is evaluated to true if the value of the
  guard g is false, otherwise it is evaluated to the same value that
  the predicate P: val(P/g)= g ? val(P):true.
  Guarded predicates allow us to include predicates into a conjunction
  conditionally. Currently they are utilized for pushed down predicates
  in queries with outer join operations.

  In the future, probably, it makes sense to extend this class to
  the objects consisting of three elements: a predicate P, a pointer
  to a variable g and a firing value s with following evaluation
  rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only
  one item for the objects of the form P/g1/g2... 

  Objects of this class are built only for query execution after
  the execution plan has been already selected. That's why this
  class needs only val_int out of generic methods. 
*/

class Item_func_trig_cond: public Item_bool_func
{
  bool *trig_var;
public:
  Item_func_trig_cond(Item *a, bool *f) : Item_bool_func(a) { trig_var= f; }
  longlong val_int() { return *trig_var ? args[0]->val_int() : 1; }
  enum Functype functype() const { return TRIG_COND_FUNC; };
  const char *func_name() const { return "trigcond"; };
};

270 271 272 273
class Item_func_not_all :public Item_func_not
{
  bool abort_on_null;
public:
unknown's avatar
unknown committed
274 275 276
  bool show;

  Item_func_not_all(Item *a) :Item_func_not(a), abort_on_null(0), show(0) {}
277 278 279
  virtual void top_level_item() { abort_on_null= 1; }
  bool top_level() { return abort_on_null; }
  longlong val_int();
280
  enum Functype functype() const { return NOT_ALL_FUNC; }
unknown's avatar
unknown committed
281 282
  const char *func_name() const { return "<not>"; }
  void print(String *str);
283 284
};

unknown's avatar
unknown committed
285
class Item_func_eq :public Item_bool_rowready_func2
unknown's avatar
unknown committed
286 287
{
public:
288
  Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
289 290 291 292 293
  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 "="; }
294
  Item *negated_item();
unknown's avatar
unknown committed
295 296
};

unknown's avatar
unknown committed
297
class Item_func_equal :public Item_bool_rowready_func2
unknown's avatar
unknown committed
298 299
{
public:
unknown's avatar
unknown committed
300
  Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
301
  longlong val_int();
unknown's avatar
unknown committed
302
  void fix_length_and_dec();
unknown's avatar
unknown committed
303 304 305 306
  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 "<=>"; }
307
  Item* neg_transformer(THD *thd) { return 0; }
unknown's avatar
unknown committed
308 309 310
};


unknown's avatar
unknown committed
311
class Item_func_ge :public Item_bool_rowready_func2
unknown's avatar
unknown committed
312 313
{
public:
314
  Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
315 316 317 318 319
  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 ">="; }
320
  Item *negated_item();
unknown's avatar
unknown committed
321 322 323
};


unknown's avatar
unknown committed
324
class Item_func_gt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
325 326
{
public:
327
  Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
328 329 330 331 332
  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 ">"; }
333
  Item *negated_item();
unknown's avatar
unknown committed
334 335 336
};


unknown's avatar
unknown committed
337
class Item_func_le :public Item_bool_rowready_func2
unknown's avatar
unknown committed
338 339
{
public:
340
  Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {};
unknown's avatar
unknown committed
341 342 343 344 345
  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 "<="; }
346
  Item *negated_item();
unknown's avatar
unknown committed
347 348 349
};


unknown's avatar
unknown committed
350
class Item_func_lt :public Item_bool_rowready_func2
unknown's avatar
unknown committed
351 352
{
public:
353
  Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}
unknown's avatar
unknown committed
354 355 356 357 358
  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 "<"; }
359
  Item *negated_item();
unknown's avatar
unknown committed
360 361 362
};


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


class Item_func_between :public Item_int_func
{
378
  DTCollation cmp_collation;
unknown's avatar
unknown committed
379 380 381 382 383 384 385 386 387
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();
388
  void print(String *str);
389
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
};


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
{
405
  Item_row *row;
unknown's avatar
unknown committed
406 407
  double *intervals;
public:
408 409
  Item_func_interval(Item_row *a)
    :Item_int_func(a),row(a),intervals(0) { allowed_arg_cols= a->cols(); }
unknown's avatar
unknown committed
410 411 412 413 414 415 416 417 418
  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;
419 420
  enum_field_types cached_field_type;
  bool field_type_defined;
unknown's avatar
unknown committed
421
public:
422 423 424
  Item_func_ifnull(Item *a,Item *b)
    :Item_func(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
425 426 427 428
  double val();
  longlong val_int();
  String *val_str(String *str);
  enum Item_result result_type () const { return cached_result_type; }
429
  enum_field_types field_type() const;
unknown's avatar
unknown committed
430 431
  void fix_length_and_dec();
  const char *func_name() const { return "ifnull"; }
432
  Field *tmp_table_field(TABLE *table);
433
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
434 435 436 437 438 439 440
};


class Item_func_if :public Item_func
{
  enum Item_result cached_result_type;
public:
441 442 443
  Item_func_if(Item *a,Item *b,Item *c)
    :Item_func(a,b,c), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
444 445 446 447
  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
448
  bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
449
  {
450
    DBUG_ASSERT(fixed == 0);
451
    args[0]->top_level_item();
unknown's avatar
unknown committed
452
    return Item_func::fix_fields(thd, tlist, ref);
453
  }
unknown's avatar
unknown committed
454 455
  void fix_length_and_dec();
  const char *func_name() const { return "if"; }
456
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
457 458 459 460 461 462 463
};


class Item_func_nullif :public Item_bool_func2
{
  enum Item_result cached_result_type;
public:
464 465 466
  Item_func_nullif(Item *a,Item *b)
    :Item_bool_func2(a,b), cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
467 468 469 470 471 472
  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"; }
473
  void print(String *str) { Item_func::print(str); }
474
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
475 476 477 478 479 480 481
};


class Item_func_coalesce :public Item_func
{
  enum Item_result cached_result_type;
public:
482 483 484
  Item_func_coalesce(List<Item> &list)
    :Item_func(list),cached_result_type(INT_RESULT)
  {}
unknown's avatar
unknown committed
485 486 487 488 489 490
  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"; }
491
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
492 493
};

494

unknown's avatar
unknown committed
495 496
class Item_func_case :public Item_func
{
497
  int first_expr_num, else_expr_num;
unknown's avatar
unknown committed
498 499
  enum Item_result cached_result_type;
  String tmp_value;
500
  uint ncases;
501 502
  Item_result cmp_type;
  DTCollation cmp_collation;
unknown's avatar
unknown committed
503
public:
504
  Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
505
    :Item_func(), first_expr_num(-1), else_expr_num(-1),
506
    cached_result_type(INT_RESULT)
507 508 509 510 511 512 513 514 515 516 517 518 519 520
  { 
    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
521 522 523 524
  double val();
  longlong val_int();
  String *val_str(String *);
  void fix_length_and_dec();
525
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
526 527 528 529
  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);
530
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
531 532 533 534 535 536 537 538 539 540
};


/* Functions to handle the optimized IN */

class in_vector :public Sql_alloc
{
 protected:
  char *base;
  uint size;
541 542
  qsort2_cmp compare;
  CHARSET_INFO *collation;
unknown's avatar
unknown committed
543 544 545
  uint count;
public:
  uint used_count;
unknown's avatar
unknown committed
546
  in_vector() {}
547 548
  in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, 
  	    CHARSET_INFO *cmp_coll)
unknown's avatar
unknown committed
549
    :base((char*) sql_calloc(elements*element_length)),
550 551
     size(element_length), compare(cmp_func), collation(cmp_coll),
     count(elements), used_count(elements) {}
unknown's avatar
unknown committed
552 553 554 555
  virtual ~in_vector() {}
  virtual void set(uint pos,Item *item)=0;
  virtual byte *get_value(Item *item)=0;
  void sort()
556
  {
557
    qsort2(base,used_count,size,compare,collation);
558
  }
unknown's avatar
unknown committed
559 560 561 562 563 564 565 566
  int find(Item *item);
};

class in_string :public in_vector
{
  char buff[80];
  String tmp;
public:
567
  in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs);
unknown's avatar
unknown committed
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
  ~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:
598 599
  CHARSET_INFO *cmp_charset;
  cmp_item() { cmp_charset= &my_charset_bin; }
unknown's avatar
unknown committed
600
  virtual ~cmp_item() {}
unknown's avatar
unknown committed
601 602 603 604
  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;
605
  static cmp_item* get_comparator(Item *);
unknown's avatar
unknown committed
606 607 608 609 610
  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
611 612
};

unknown's avatar
unknown committed
613 614 615 616 617
class cmp_item_string :public cmp_item 
{
protected:
  String *value_res;
public:
618
  cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
unknown's avatar
unknown committed
619 620 621
  friend class cmp_item_sort_string;
  friend class cmp_item_sort_string_in_static;
};
unknown's avatar
unknown committed
622

unknown's avatar
unknown committed
623 624 625
class cmp_item_sort_string :public cmp_item_string
{
protected:
unknown's avatar
unknown committed
626
  char value_buff[80];
unknown's avatar
unknown committed
627
  String value;
unknown's avatar
unknown committed
628
public:
629 630 631
  cmp_item_sort_string(CHARSET_INFO *cs):
    cmp_item_string(cs),
    value(value_buff, sizeof(value_buff), cs) {}
unknown's avatar
unknown committed
632
  void store_value(Item *item)
unknown's avatar
unknown committed
633 634 635
  {
    value_res= item->val_str(&value);
  }
unknown's avatar
unknown committed
636
  int cmp(Item *arg)
unknown's avatar
unknown committed
637 638
  {
    char buff[80];
unknown's avatar
unknown committed
639
    String tmp(buff, sizeof(buff), cmp_charset), *res;
unknown's avatar
unknown committed
640 641
    if (!(res= arg->val_str(&tmp)))
      return 1;				/* Can't be right */
642
    return sortcmp(value_res, res, cmp_charset);
unknown's avatar
unknown committed
643 644 645 646
  }
  int compare(cmp_item *c)
  {
    cmp_item_string *cmp= (cmp_item_string *)c;
647
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
648 649
  } 
  cmp_item *make_same();
unknown's avatar
unknown committed
650 651 652 653 654 655 656
};

class cmp_item_int :public cmp_item
{
  longlong value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
657 658 659
  {
    value= item->val_int();
  }
unknown's avatar
unknown committed
660
  int cmp(Item *arg)
unknown's avatar
unknown committed
661 662 663 664 665 666 667 668 669
  {
    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
670 671 672 673 674 675 676
};

class cmp_item_real :public cmp_item
{
  double value;
public:
  void store_value(Item *item)
unknown's avatar
unknown committed
677 678 679
  {
    value= item->val();
  }
unknown's avatar
unknown committed
680
  int cmp(Item *arg)
unknown's avatar
unknown committed
681 682 683 684 685 686 687 688 689
  {
    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
690 691
};

692 693 694 695 696
class cmp_item_row :public cmp_item
{
  cmp_item **comparators;
  uint n;
public:
unknown's avatar
unknown committed
697
  cmp_item_row(): comparators(0), n(0) {}
698
  ~cmp_item_row();
699 700
  void store_value(Item *item);
  int cmp(Item *arg);
unknown's avatar
unknown committed
701 702 703 704 705 706 707 708 709 710 711
  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 *);
712
  ~in_row();
unknown's avatar
unknown committed
713 714 715 716 717 718 719 720 721 722 723 724 725 726
  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:
727 728
  cmp_item_sort_string_in_static(CHARSET_INFO *cs):
    cmp_item_string(cs) {}
unknown's avatar
unknown committed
729 730 731 732 733 734 735 736 737 738 739 740 741
  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;
742
    return sortcmp(value_res, cmp->value_res, cmp_charset);
unknown's avatar
unknown committed
743
  }
744
  cmp_item *make_same()
unknown's avatar
unknown committed
745
  {
746
    return new cmp_item_sort_string_in_static(cmp_charset);
unknown's avatar
unknown committed
747
  }
748
};
unknown's avatar
unknown committed
749 750 751

class Item_func_in :public Item_int_func
{
752
  Item_result cmp_type;
unknown's avatar
unknown committed
753 754
  in_vector *array;
  cmp_item *in_item;
755
  bool have_null;
756
  DTCollation cmp_collation;
unknown's avatar
unknown committed
757
 public:
758 759
  Item_func_in(List<Item> &list)
    :Item_int_func(list), array(0), in_item(0), have_null(0)
760
  {
761
    allowed_arg_cols= args[0]->cols();
762
  }
unknown's avatar
unknown committed
763 764
  longlong val_int();
  void fix_length_and_dec();
765 766
  void cleanup()
  {
unknown's avatar
unknown committed
767
    DBUG_ENTER("Item_func_in::cleanup");
768
    Item_int_func::cleanup();
769 770 771 772
    delete array;
    delete in_item;
    array= 0;
    in_item= 0;
unknown's avatar
unknown committed
773
    DBUG_VOID_RETURN;
774
  }
unknown's avatar
unknown committed
775 776 777 778 779
  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
780
  bool nulls_in_row();
781
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
782 783 784 785 786 787
};

/* Functions used by where clause */

class Item_func_isnull :public Item_bool_func
{
788
protected:
unknown's avatar
unknown committed
789
  longlong cached_value;
unknown's avatar
unknown committed
790 791 792 793 794 795 796
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;
797
    update_used_tables();
unknown's avatar
unknown committed
798 799 800
  }
  const char *func_name() const { return "isnull"; }
  /* Optimize case of not_null_column IS NULL */
801
  virtual void update_used_tables()
unknown's avatar
unknown committed
802 803 804
  {
    if (!args[0]->maybe_null)
    {
805
      used_tables_cache= 0;			/* is always false */
806
      const_item_cache= 1;
807
      cached_value= (longlong) 0;
unknown's avatar
unknown committed
808
    }
809
    else
unknown's avatar
unknown committed
810
    {
811 812 813 814
      args[0]->update_used_tables();
      if (!(used_tables_cache=args[0]->used_tables()))
      {
	/* Remember if the value is always NULL or never NULL */
815
	cached_value= (longlong) args[0]->is_null();
816
      }
unknown's avatar
unknown committed
817
    }
unknown's avatar
unknown committed
818
  }
819
  table_map not_null_tables() const { return 0; }
unknown's avatar
unknown committed
820
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
821
  Item *neg_transformer(THD *thd);
822
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
823 824
};

825 826 827 828 829 830 831 832 833 834
/* 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)
  {}
835
  enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
836
  longlong val_int();
837
  const char *func_name() const { return "<is_not_null_test>"; }
838 839 840 841
  void update_used_tables();
};


unknown's avatar
unknown committed
842 843 844 845 846 847
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
848 849 850 851
  void fix_length_and_dec()
  {
    decimals=0; max_length=1; maybe_null=0;
  }
unknown's avatar
unknown committed
852 853
  const char *func_name() const { return "isnotnull"; }
  optimize_type select_optimize() const { return OPTIMIZE_NULL; }
854
  table_map not_null_tables() const { return used_tables(); }
855
  Item *neg_transformer(THD *thd);
856
  void print(String *str);
857
  CHARSET_INFO *compare_collation() { return args[0]->collation.collation; }
unknown's avatar
unknown committed
858 859
};

860

unknown's avatar
unknown committed
861 862
class Item_func_like :public Item_bool_func2
{
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
  // 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
878
public:
879 880
  char escape;

881
  Item_func_like(Item *a,Item *b, char* escape_arg)
882 883
    :Item_bool_func2(a,b), canDoTurboBM(false), pattern(0), pattern_len(0), 
     bmGs(0), bmBc(0), escape(*escape_arg) {}
unknown's avatar
unknown committed
884 885 886 887 888
  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
889
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
unknown's avatar
unknown committed
890 891 892 893 894 895 896 897 898 899 900 901
};

#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;
902
  DTCollation cmp_collation;
unknown's avatar
unknown committed
903 904 905 906 907
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
908
  bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
909
  const char *func_name() const { return "regexp"; }
910
  void print(String *str) { print_op(str); }
911
  CHARSET_INFO *compare_collation() { return cmp_collation.collation; }
unknown's avatar
unknown committed
912 913 914 915 916 917 918 919 920 921
};

#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"; }
922
  void print(String *str) { print_op(str); }
unknown's avatar
unknown committed
923 924 925 926 927 928 929 930 931 932 933
};

#endif /* USE_REGEX */


typedef class Item COND;

class Item_cond :public Item_bool_func
{
protected:
  List<Item> list;
934
  bool abort_on_null;
935 936
  table_map and_tables_cache;

unknown's avatar
unknown committed
937
public:
938
  /* Item_cond() is only used to create top level items */
939 940
  Item_cond(): Item_bool_func(), abort_on_null(1)
  { const_item_cache=0; }
941 942 943 944 945 946
  Item_cond(Item *i1,Item *i2) 
    :Item_bool_func(), abort_on_null(0)
  {
    list.push_back(i1);
    list.push_back(i2);
  }
947
  Item_cond(THD *thd, Item_cond *item);
948 949
  Item_cond(List<Item> &nlist)
    :Item_bool_func(), list(nlist), abort_on_null(0) {}
unknown's avatar
unknown committed
950
  bool add(Item *item) { return list.push_back(item); }
unknown's avatar
unknown committed
951
  bool fix_fields(THD *, struct st_table_list *, Item **ref);
unknown's avatar
unknown committed
952 953 954 955 956 957

  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);
958
  void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
unknown's avatar
unknown committed
959
  friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
960
  void top_level_item() { abort_on_null=1; }
961
  void copy_andor_arguments(THD *thd, Item_cond *item);
unknown's avatar
unknown committed
962
  bool walk(Item_processor processor, byte *arg);
963
  void neg_arguments(THD *thd);
unknown's avatar
unknown committed
964 965 966 967 968 969 970 971
};


class Item_cond_and :public Item_cond
{
public:
  Item_cond_and() :Item_cond() {}
  Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
972
  Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
973
  Item_cond_and(List<Item> &list): Item_cond(list) {}
unknown's avatar
unknown committed
974 975 976
  enum Functype functype() const { return COND_AND_FUNC; }
  longlong val_int();
  const char *func_name() const { return "and"; }
977 978 979
  Item* copy_andor_structure(THD *thd)
  {
    Item_cond_and *item;
unknown's avatar
merge  
unknown committed
980
    if ((item= new Item_cond_and(thd, this)))
981 982 983
       item->copy_andor_arguments(thd, this);
    return item;
  }
984
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
985 986 987 988 989 990 991
};

class Item_cond_or :public Item_cond
{
public:
  Item_cond_or() :Item_cond() {}
  Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {}
992
  Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {}
993
  Item_cond_or(List<Item> &list): Item_cond(list) {}
unknown's avatar
unknown committed
994 995 996
  enum Functype functype() const { return COND_OR_FUNC; }
  longlong val_int();
  const char *func_name() const { return "or"; }
997
  table_map not_null_tables() const { return and_tables_cache; }
998 999 1000
  Item* copy_andor_structure(THD *thd)
  {
    Item_cond_or *item;
unknown's avatar
merge  
unknown committed
1001
    if ((item= new Item_cond_or(thd, this)))
1002 1003 1004
      item->copy_andor_arguments(thd, this);
    return item;
  }
1005
  Item *neg_transformer(THD *thd);
unknown's avatar
unknown committed
1006 1007 1008
};


1009 1010 1011 1012
/*
  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
1013

unknown's avatar
unknown committed
1014 1015 1016 1017 1018 1019
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; }
1020 1021
  /* TODO: remove the next line when implementing XOR optimization */
  enum Type type() const { return FUNC_ITEM; }
unknown's avatar
unknown committed
1022 1023 1024 1025 1026
  longlong val_int();
  const char *func_name() const { return "xor"; }
};


unknown's avatar
unknown committed
1027 1028
/* Some usefull inline functions */

unknown's avatar
unknown committed
1029
inline Item *and_conds(Item *a, Item *b)
unknown's avatar
unknown committed
1030 1031 1032
{
  if (!b) return a;
  if (!a) return b;
unknown's avatar
unknown committed
1033
  return new Item_cond_and(a, b);
unknown's avatar
unknown committed
1034
}
unknown's avatar
unknown committed
1035

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