My Project
|
00001 #ifndef ITEM_CMPFUNC_INCLUDED 00002 #define ITEM_CMPFUNC_INCLUDED 00003 00004 /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; version 2 of the License. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00018 00019 00020 /* compare and test functions */ 00021 00022 #include "thr_malloc.h" /* sql_calloc */ 00023 #include "item_func.h" /* Item_int_func, Item_bool_func */ 00024 #include "my_regex.h" 00025 00026 extern Item_result item_cmp_type(Item_result a,Item_result b); 00027 class Item_bool_func2; 00028 class Arg_comparator; 00029 00030 typedef int (Arg_comparator::*arg_cmp_func)(); 00031 00032 typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg); 00033 00034 class Arg_comparator: public Sql_alloc 00035 { 00036 Item **a, **b; 00037 arg_cmp_func func; 00038 Item_result_field *owner; 00039 Arg_comparator *comparators; // used only for compare_row() 00040 double precision; 00041 /* Fields used in DATE/DATETIME comparison. */ 00042 THD *thd; 00043 enum_field_types a_type, b_type; // Types of a and b items 00044 Item *a_cache, *b_cache; // Cached values of a and b items 00045 bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC 00046 bool set_null; // TRUE <=> set owner->null_value 00047 // when one of arguments is NULL. 00048 longlong (*get_value_a_func)(THD *thd, Item ***item_arg, Item **cache_arg, 00049 Item *warn_item, bool *is_null); 00050 longlong (*get_value_b_func)(THD *thd, Item ***item_arg, Item **cache_arg, 00051 Item *warn_item, bool *is_null); 00052 bool try_year_cmp_func(Item_result type); 00053 static bool get_date_from_const(Item *date_arg, Item *str_arg, 00054 ulonglong *value); 00055 public: 00056 DTCollation cmp_collation; 00057 /* Allow owner function to use string buffers. */ 00058 String value1, value2; 00059 00060 Arg_comparator(): comparators(0), thd(0), a_cache(0), b_cache(0), set_null(TRUE), 00061 get_value_a_func(0), get_value_b_func(0) {}; 00062 Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), comparators(0), thd(0), 00063 a_cache(0), b_cache(0), set_null(TRUE), 00064 get_value_a_func(0), get_value_b_func(0) {}; 00065 00066 int set_compare_func(Item_result_field *owner, Item_result type); 00067 inline int set_compare_func(Item_result_field *owner_arg) 00068 { 00069 return set_compare_func(owner_arg, item_cmp_type((*a)->result_type(), 00070 (*b)->result_type())); 00071 } 00072 int set_cmp_func(Item_result_field *owner_arg, 00073 Item **a1, Item **a2, 00074 Item_result type); 00075 00076 inline int set_cmp_func(Item_result_field *owner_arg, 00077 Item **a1, Item **a2, bool set_null_arg) 00078 { 00079 set_null= set_null_arg; 00080 return set_cmp_func(owner_arg, a1, a2, 00081 item_cmp_type((*a1)->result_type(), 00082 (*a2)->result_type())); 00083 } 00084 inline int compare() { return (this->*func)(); } 00085 00086 int compare_string(); // compare args[0] & args[1] 00087 int compare_binary_string(); // compare args[0] & args[1] 00088 int compare_real(); // compare args[0] & args[1] 00089 int compare_decimal(); // compare args[0] & args[1] 00090 int compare_int_signed(); // compare args[0] & args[1] 00091 int compare_int_signed_unsigned(); 00092 int compare_int_unsigned_signed(); 00093 int compare_int_unsigned(); 00094 int compare_time_packed(); 00095 int compare_e_time_packed(); 00096 int compare_row(); // compare args[0] & args[1] 00097 int compare_e_string(); // compare args[0] & args[1] 00098 int compare_e_binary_string(); // compare args[0] & args[1] 00099 int compare_e_real(); // compare args[0] & args[1] 00100 int compare_e_decimal(); // compare args[0] & args[1] 00101 int compare_e_int(); // compare args[0] & args[1] 00102 int compare_e_int_diff_signedness(); 00103 int compare_e_row(); // compare args[0] & args[1] 00104 int compare_real_fixed(); 00105 int compare_e_real_fixed(); 00106 int compare_datetime(); // compare args[0] & args[1] as DATETIMEs 00107 00108 static bool can_compare_as_dates(Item *a, Item *b, ulonglong *const_val_arg); 00109 00110 Item** cache_converted_constant(THD *thd, Item **value, Item **cache, 00111 Item_result type); 00112 void set_datetime_cmp_func(Item_result_field *owner_arg, Item **a1, Item **b1); 00113 static arg_cmp_func comparator_matrix [5][2]; 00114 inline bool is_owner_equal_func() 00115 { 00116 return (owner->type() == Item::FUNC_ITEM && 00117 ((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC); 00118 } 00119 void cleanup() 00120 { 00121 delete [] comparators; 00122 comparators= 0; 00123 } 00124 /* 00125 Set correct cmp_context if items would be compared as INTs. 00126 */ 00127 inline void set_cmp_context_for_datetime() 00128 { 00129 DBUG_ASSERT(func == &Arg_comparator::compare_datetime); 00130 if ((*a)->is_temporal()) 00131 (*a)->cmp_context= INT_RESULT; 00132 if ((*b)->is_temporal()) 00133 (*b)->cmp_context= INT_RESULT; 00134 } 00135 friend class Item_func; 00136 }; 00137 00138 class Item_bool_func :public Item_int_func 00139 { 00140 public: 00141 Item_bool_func() : Item_int_func(), m_created_by_in2exists(false) {} 00142 Item_bool_func(Item *a) : Item_int_func(a), 00143 m_created_by_in2exists(false) {} 00144 Item_bool_func(Item *a,Item *b) : Item_int_func(a,b), 00145 m_created_by_in2exists(false) {} 00146 Item_bool_func(THD *thd, Item_bool_func *item) : Item_int_func(thd, item), 00147 m_created_by_in2exists(item->m_created_by_in2exists) {} 00148 bool is_bool_func() { return 1; } 00149 void fix_length_and_dec() { decimals=0; max_length=1; } 00150 uint decimal_precision() const { return 1; } 00151 virtual bool created_by_in2exists() const { return m_created_by_in2exists; } 00152 void set_created_by_in2exists() { m_created_by_in2exists= true; } 00153 private: 00158 bool m_created_by_in2exists; 00159 }; 00160 00161 00167 class Item_func_truth : public Item_bool_func 00168 { 00169 public: 00170 virtual bool val_bool(); 00171 virtual longlong val_int(); 00172 virtual void fix_length_and_dec(); 00173 virtual void print(String *str, enum_query_type query_type); 00174 00175 protected: 00176 Item_func_truth(Item *a, bool a_value, bool a_affirmative) 00177 : Item_bool_func(a), value(a_value), affirmative(a_affirmative) 00178 {} 00179 00180 ~Item_func_truth() 00181 {} 00182 private: 00187 const bool value; 00191 const bool affirmative; 00192 }; 00193 00194 00199 class Item_func_istrue : public Item_func_truth 00200 { 00201 public: 00202 Item_func_istrue(Item *a) : Item_func_truth(a, true, true) {} 00203 ~Item_func_istrue() {} 00204 virtual const char* func_name() const { return "istrue"; } 00205 }; 00206 00207 00212 class Item_func_isnottrue : public Item_func_truth 00213 { 00214 public: 00215 Item_func_isnottrue(Item *a) : Item_func_truth(a, true, false) {} 00216 ~Item_func_isnottrue() {} 00217 virtual const char* func_name() const { return "isnottrue"; } 00218 }; 00219 00220 00225 class Item_func_isfalse : public Item_func_truth 00226 { 00227 public: 00228 Item_func_isfalse(Item *a) : Item_func_truth(a, false, true) {} 00229 ~Item_func_isfalse() {} 00230 virtual const char* func_name() const { return "isfalse"; } 00231 }; 00232 00233 00238 class Item_func_isnotfalse : public Item_func_truth 00239 { 00240 public: 00241 Item_func_isnotfalse(Item *a) : Item_func_truth(a, false, false) {} 00242 ~Item_func_isnotfalse() {} 00243 virtual const char* func_name() const { return "isnotfalse"; } 00244 }; 00245 00246 00247 class Item_cache; 00248 #define UNKNOWN ((my_bool)-1) 00249 00250 00251 /* 00252 Item_in_optimizer(left_expr, Item_in_subselect(...)) 00253 00254 Item_in_optimizer is used to wrap an instance of Item_in_subselect. This 00255 class does the following: 00256 - Evaluate the left expression and store it in Item_cache_* object (to 00257 avoid re-evaluating it many times during subquery execution) 00258 - Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we 00259 don't care if the result is NULL or FALSE. 00260 00261 args[1] keeps a reference to the Item_in_subselect object. 00262 00263 args[0] is a copy of Item_in_subselect's left expression and should be 00264 kept equal also after resolving. 00265 00266 NOTE 00267 It is not quite clear why the above listed functionality should be 00268 placed into a separate class called 'Item_in_optimizer'. 00269 */ 00270 00271 class Item_in_optimizer: public Item_bool_func 00272 { 00273 private: 00274 Item_cache *cache; 00275 bool save_cache; 00276 /* 00277 Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries: 00278 UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated 00279 FALSE - result is FALSE 00280 TRUE - result is NULL 00281 */ 00282 my_bool result_for_null_param; 00283 public: 00284 Item_in_optimizer(Item *a, Item_in_subselect *b): 00285 Item_bool_func(a, reinterpret_cast<Item *>(b)), cache(0), 00286 save_cache(0), result_for_null_param(UNKNOWN) 00287 { with_subselect= TRUE; } 00288 bool fix_fields(THD *, Item **); 00289 bool fix_left(THD *thd, Item **ref); 00290 void fix_after_pullout(st_select_lex *parent_select, 00291 st_select_lex *removed_select); 00292 bool is_null(); 00293 longlong val_int(); 00294 void cleanup(); 00295 const char *func_name() const { return "<in_optimizer>"; } 00296 Item_cache **get_cache() { return &cache; } 00297 void keep_top_level_cache(); 00298 Item *transform(Item_transformer transformer, uchar *arg); 00299 }; 00300 00301 class Comp_creator 00302 { 00303 public: 00304 Comp_creator() {} /* Remove gcc warning */ 00305 virtual ~Comp_creator() {} /* Remove gcc warning */ 00306 virtual Item_bool_func2* create(Item *a, Item *b) const = 0; 00307 virtual const char* symbol(bool invert) const = 0; 00308 virtual bool eqne_op() const = 0; 00309 virtual bool l_op() const = 0; 00310 }; 00311 00312 class Eq_creator :public Comp_creator 00313 { 00314 public: 00315 Eq_creator() {} /* Remove gcc warning */ 00316 virtual ~Eq_creator() {} /* Remove gcc warning */ 00317 virtual Item_bool_func2* create(Item *a, Item *b) const; 00318 virtual const char* symbol(bool invert) const { return invert? "<>" : "="; } 00319 virtual bool eqne_op() const { return 1; } 00320 virtual bool l_op() const { return 0; } 00321 }; 00322 00323 class Ne_creator :public Comp_creator 00324 { 00325 public: 00326 Ne_creator() {} /* Remove gcc warning */ 00327 virtual ~Ne_creator() {} /* Remove gcc warning */ 00328 virtual Item_bool_func2* create(Item *a, Item *b) const; 00329 virtual const char* symbol(bool invert) const { return invert? "=" : "<>"; } 00330 virtual bool eqne_op() const { return 1; } 00331 virtual bool l_op() const { return 0; } 00332 }; 00333 00334 class Gt_creator :public Comp_creator 00335 { 00336 public: 00337 Gt_creator() {} /* Remove gcc warning */ 00338 virtual ~Gt_creator() {} /* Remove gcc warning */ 00339 virtual Item_bool_func2* create(Item *a, Item *b) const; 00340 virtual const char* symbol(bool invert) const { return invert? "<=" : ">"; } 00341 virtual bool eqne_op() const { return 0; } 00342 virtual bool l_op() const { return 0; } 00343 }; 00344 00345 class Lt_creator :public Comp_creator 00346 { 00347 public: 00348 Lt_creator() {} /* Remove gcc warning */ 00349 virtual ~Lt_creator() {} /* Remove gcc warning */ 00350 virtual Item_bool_func2* create(Item *a, Item *b) const; 00351 virtual const char* symbol(bool invert) const { return invert? ">=" : "<"; } 00352 virtual bool eqne_op() const { return 0; } 00353 virtual bool l_op() const { return 1; } 00354 }; 00355 00356 class Ge_creator :public Comp_creator 00357 { 00358 public: 00359 Ge_creator() {} /* Remove gcc warning */ 00360 virtual ~Ge_creator() {} /* Remove gcc warning */ 00361 virtual Item_bool_func2* create(Item *a, Item *b) const; 00362 virtual const char* symbol(bool invert) const { return invert? "<" : ">="; } 00363 virtual bool eqne_op() const { return 0; } 00364 virtual bool l_op() const { return 0; } 00365 }; 00366 00367 class Le_creator :public Comp_creator 00368 { 00369 public: 00370 Le_creator() {} /* Remove gcc warning */ 00371 virtual ~Le_creator() {} /* Remove gcc warning */ 00372 virtual Item_bool_func2* create(Item *a, Item *b) const; 00373 virtual const char* symbol(bool invert) const { return invert? ">" : "<="; } 00374 virtual bool eqne_op() const { return 0; } 00375 virtual bool l_op() const { return 1; } 00376 }; 00377 00378 class Item_bool_func2 :public Item_bool_func 00379 { /* Bool with 2 string args */ 00380 private: 00381 bool convert_constant_arg(THD *thd, Item *field, Item **item); 00382 protected: 00383 Arg_comparator cmp; 00384 bool abort_on_null; 00385 00386 public: 00387 Item_bool_func2(Item *a,Item *b) 00388 :Item_bool_func(a,b), cmp(tmp_arg, tmp_arg+1), abort_on_null(FALSE) {} 00389 void fix_length_and_dec(); 00390 int set_cmp_func() 00391 { 00392 return cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, TRUE); 00393 } 00394 optimize_type select_optimize() const { return OPTIMIZE_OP; } 00395 virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } 00396 bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } 00397 00398 virtual inline void print(String *str, enum_query_type query_type) 00399 { 00400 Item_func::print_op(str, query_type); 00401 } 00402 00403 bool is_null() { return MY_TEST(args[0]->is_null() || args[1]->is_null()); } 00404 const CHARSET_INFO *compare_collation() 00405 { return cmp.cmp_collation.collation; } 00406 void top_level_item() { abort_on_null= TRUE; } 00407 void cleanup() 00408 { 00409 Item_bool_func::cleanup(); 00410 cmp.cleanup(); 00411 } 00412 00413 friend class Arg_comparator; 00414 }; 00415 00416 class Item_bool_rowready_func2 :public Item_bool_func2 00417 { 00418 public: 00419 Item_bool_rowready_func2(Item *a, Item *b) :Item_bool_func2(a, b) 00420 { 00421 allowed_arg_cols= 0; // Fetch this value from first argument 00422 } 00423 Item *neg_transformer(THD *thd); 00424 virtual Item *negated_item(); 00425 bool subst_argument_checker(uchar **arg) { return TRUE; } 00426 }; 00427 00433 class Item_func_xor :public Item_bool_func2 00434 { 00435 public: 00436 Item_func_xor(Item *i1, Item *i2) :Item_bool_func2(i1, i2) {} 00437 enum Functype functype() const { return XOR_FUNC; } 00438 const char *func_name() const { return "xor"; } 00439 longlong val_int(); 00440 void top_level_item() {} 00441 Item *neg_transformer(THD *thd); 00442 }; 00443 00444 class Item_func_not :public Item_bool_func 00445 { 00446 public: 00447 Item_func_not(Item *a) :Item_bool_func(a) {} 00448 longlong val_int(); 00449 enum Functype functype() const { return NOT_FUNC; } 00450 const char *func_name() const { return "not"; } 00451 Item *neg_transformer(THD *thd); 00452 virtual void print(String *str, enum_query_type query_type); 00453 }; 00454 00455 class Item_maxmin_subselect; 00456 struct st_join_table; 00457 /* 00458 trigcond<param>(arg) ::= param? arg : TRUE 00459 00460 The class Item_func_trig_cond is used for guarded predicates 00461 which are employed only for internal purposes. 00462 A guarded predicate is an object consisting of an a regular or 00463 a guarded predicate P and a pointer to a boolean guard variable g. 00464 A guarded predicate P/g is evaluated to true if the value of the 00465 guard g is false, otherwise it is evaluated to the same value that 00466 the predicate P: val(P/g)= g ? val(P):true. 00467 Guarded predicates allow us to include predicates into a conjunction 00468 conditionally. Currently they are utilized for pushed down predicates 00469 in queries with outer join operations. 00470 00471 In the future, probably, it makes sense to extend this class to 00472 the objects consisting of three elements: a predicate P, a pointer 00473 to a variable g and a firing value s with following evaluation 00474 rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only 00475 one item for the objects of the form P/g1/g2... 00476 00477 Objects of this class are built only for query execution after 00478 the execution plan has been already selected. That's why this 00479 class needs only val_int out of generic methods. 00480 00481 Current uses of Item_func_trig_cond objects: 00482 - To wrap selection conditions when executing outer joins 00483 - To wrap condition that is pushed down into subquery 00484 */ 00485 00486 class Item_func_trig_cond: public Item_bool_func 00487 { 00488 public: 00489 enum enum_trig_type 00490 { 00495 IS_NOT_NULL_COMPL, 00500 FOUND_MATCH, 00508 OUTER_FIELD_IS_NOT_NULL 00509 }; 00510 private: 00512 bool *trig_var; 00514 const struct st_join_table *trig_tab; 00516 enum_trig_type trig_type; 00517 public: 00525 Item_func_trig_cond(Item *a, bool *f, struct st_join_table *tab, 00526 enum_trig_type trig_type_arg) 00527 : Item_bool_func(a), trig_var(f), trig_tab(tab), trig_type(trig_type_arg) 00528 {} 00529 longlong val_int() { return *trig_var ? args[0]->val_int() : 1; } 00530 enum Functype functype() const { return TRIG_COND_FUNC; }; 00532 const char *func_name() const { return "<if>"; }; 00533 bool const_item() const { return FALSE; } 00534 bool *get_trig_var() { return trig_var; } 00535 /* The following is needed for ICP: */ 00536 table_map used_tables() const { return args[0]->used_tables(); } 00537 void print(String *str, enum_query_type query_type); 00538 }; 00539 00540 00541 class Item_func_not_all :public Item_func_not 00542 { 00543 /* allow to check presence of values in max/min optimization */ 00544 Item_sum_hybrid *test_sum_item; 00545 Item_maxmin_subselect *test_sub_item; 00546 Item_subselect *subselect; 00547 00548 bool abort_on_null; 00549 public: 00550 bool show; 00551 00552 Item_func_not_all(Item *a) 00553 :Item_func_not(a), test_sum_item(0), test_sub_item(0), subselect(0), 00554 abort_on_null(0), show(0) 00555 {} 00556 virtual void top_level_item() { abort_on_null= 1; } 00557 bool top_level() { return abort_on_null; } 00558 longlong val_int(); 00559 enum Functype functype() const { return NOT_ALL_FUNC; } 00560 const char *func_name() const { return "<not>"; } 00561 virtual void print(String *str, enum_query_type query_type); 00562 void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; }; 00563 void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; }; 00564 void set_subselect(Item_subselect *item) { subselect= item; } 00565 table_map not_null_tables() const 00566 { 00567 /* 00568 See handling of not_null_tables_cache in 00569 Item_in_optimizer::fix_fields(). 00570 00571 This item is the result of a transformation from an ALL clause 00572 such as 00573 left-expr < ALL(subquery) 00574 into 00575 <not>(left-expr >= (subquery) 00576 00577 An inequality usually rejects NULLs from both operands, so the 00578 not_null_tables() of the inequality is the union of the 00579 null-rejecting tables of both operands. However, since this is a 00580 transformed ALL clause that should return true if the subquery 00581 is empty (even if left-expr is NULL), it is not null rejecting 00582 for left-expr. The not null tables mask for left-expr should be 00583 removed, leaving only the null-rejecting tables of the 00584 subquery. Item_subselect::not_null_tables() always returns 0 (no 00585 null-rejecting tables). Therefore, always return 0. 00586 */ 00587 return 0; 00588 } 00589 bool empty_underlying_subquery(); 00590 Item *neg_transformer(THD *thd); 00591 }; 00592 00593 00594 class Item_func_nop_all :public Item_func_not_all 00595 { 00596 public: 00597 00598 Item_func_nop_all(Item *a) :Item_func_not_all(a) {} 00599 longlong val_int(); 00600 const char *func_name() const { return "<nop>"; } 00601 table_map not_null_tables() const { return not_null_tables_cache; } 00602 Item *neg_transformer(THD *thd); 00603 }; 00604 00605 00606 class Item_func_eq :public Item_bool_rowready_func2 00607 { 00608 public: 00609 Item_func_eq(Item *a,Item *b) : 00610 Item_bool_rowready_func2(a,b) 00611 {} 00612 longlong val_int(); 00613 enum Functype functype() const { return EQ_FUNC; } 00614 enum Functype rev_functype() const { return EQ_FUNC; } 00615 cond_result eq_cmp_result() const { return COND_TRUE; } 00616 const char *func_name() const { return "="; } 00617 Item *negated_item(); 00618 virtual bool equality_substitution_analyzer(uchar **arg) { return true; } 00619 virtual Item* equality_substitution_transformer(uchar *arg); 00620 }; 00621 00622 class Item_func_equal :public Item_bool_rowready_func2 00623 { 00624 public: 00625 Item_func_equal(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; 00626 longlong val_int(); 00627 void fix_length_and_dec(); 00628 table_map not_null_tables() const { return 0; } 00629 enum Functype functype() const { return EQUAL_FUNC; } 00630 enum Functype rev_functype() const { return EQUAL_FUNC; } 00631 cond_result eq_cmp_result() const { return COND_TRUE; } 00632 const char *func_name() const { return "<=>"; } 00633 Item *neg_transformer(THD *thd) { return 0; } 00634 }; 00635 00636 00637 class Item_func_ge :public Item_bool_rowready_func2 00638 { 00639 public: 00640 Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; 00641 longlong val_int(); 00642 enum Functype functype() const { return GE_FUNC; } 00643 enum Functype rev_functype() const { return LE_FUNC; } 00644 cond_result eq_cmp_result() const { return COND_TRUE; } 00645 const char *func_name() const { return ">="; } 00646 Item *negated_item(); 00647 }; 00648 00649 00650 class Item_func_gt :public Item_bool_rowready_func2 00651 { 00652 public: 00653 Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; 00654 longlong val_int(); 00655 enum Functype functype() const { return GT_FUNC; } 00656 enum Functype rev_functype() const { return LT_FUNC; } 00657 cond_result eq_cmp_result() const { return COND_FALSE; } 00658 const char *func_name() const { return ">"; } 00659 Item *negated_item(); 00660 }; 00661 00662 00663 class Item_func_le :public Item_bool_rowready_func2 00664 { 00665 public: 00666 Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {}; 00667 longlong val_int(); 00668 enum Functype functype() const { return LE_FUNC; } 00669 enum Functype rev_functype() const { return GE_FUNC; } 00670 cond_result eq_cmp_result() const { return COND_TRUE; } 00671 const char *func_name() const { return "<="; } 00672 Item *negated_item(); 00673 }; 00674 00675 00676 class Item_func_lt :public Item_bool_rowready_func2 00677 { 00678 public: 00679 Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} 00680 longlong val_int(); 00681 enum Functype functype() const { return LT_FUNC; } 00682 enum Functype rev_functype() const { return GT_FUNC; } 00683 cond_result eq_cmp_result() const { return COND_FALSE; } 00684 const char *func_name() const { return "<"; } 00685 Item *negated_item(); 00686 }; 00687 00688 00689 class Item_func_ne :public Item_bool_rowready_func2 00690 { 00691 public: 00692 Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) {} 00693 longlong val_int(); 00694 enum Functype functype() const { return NE_FUNC; } 00695 cond_result eq_cmp_result() const { return COND_FALSE; } 00696 optimize_type select_optimize() const { return OPTIMIZE_KEY; } 00697 const char *func_name() const { return "<>"; } 00698 Item *negated_item(); 00699 }; 00700 00701 00702 /* 00703 The class Item_func_opt_neg is defined to factor out the functionality 00704 common for the classes Item_func_between and Item_func_in. The objects 00705 of these classes can express predicates or there negations. 00706 The alternative approach would be to create pairs Item_func_between, 00707 Item_func_notbetween and Item_func_in, Item_func_notin. 00708 00709 */ 00710 00711 class Item_func_opt_neg :public Item_int_func 00712 { 00713 public: 00714 bool negated; /* <=> the item represents NOT <func> */ 00715 bool pred_level; /* <=> [NOT] <func> is used on a predicate level */ 00716 public: 00717 Item_func_opt_neg(Item *a, Item *b, Item *c) 00718 :Item_int_func(a, b, c), negated(0), pred_level(0) {} 00719 Item_func_opt_neg(List<Item> &list) 00720 :Item_int_func(list), negated(0), pred_level(0) {} 00721 public: 00722 inline void negate() { negated= !negated; } 00723 inline void top_level_item() { pred_level= 1; } 00724 Item *neg_transformer(THD *thd) 00725 { 00726 negated= !negated; 00727 return this; 00728 } 00729 bool eq(const Item *item, bool binary_cmp) const; 00730 bool subst_argument_checker(uchar **arg) { return TRUE; } 00731 }; 00732 00733 00734 class Item_func_between :public Item_func_opt_neg 00735 { 00736 DTCollation cmp_collation; 00737 public: 00738 Item_result cmp_type; 00739 String value0,value1,value2; 00740 /* TRUE <=> arguments will be compared as dates. */ 00741 bool compare_as_dates_with_strings; 00742 bool compare_as_temporal_dates; 00743 bool compare_as_temporal_times; 00744 00745 /* Comparators used for DATE/DATETIME comparison. */ 00746 Arg_comparator ge_cmp, le_cmp; 00747 Item_func_between(Item *a, Item *b, Item *c) 00748 :Item_func_opt_neg(a, b, c), compare_as_dates_with_strings(FALSE), 00749 compare_as_temporal_dates(FALSE), 00750 compare_as_temporal_times(FALSE) {} 00751 longlong val_int(); 00752 optimize_type select_optimize() const { return OPTIMIZE_KEY; } 00753 enum Functype functype() const { return BETWEEN; } 00754 const char *func_name() const { return "between"; } 00755 bool fix_fields(THD *, Item **); 00756 void fix_after_pullout(st_select_lex *parent_select, 00757 st_select_lex *removed_select); 00758 void fix_length_and_dec(); 00759 virtual void print(String *str, enum_query_type query_type); 00760 bool is_bool_func() { return 1; } 00761 const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } 00762 uint decimal_precision() const { return 1; } 00763 }; 00764 00765 00766 class Item_func_strcmp :public Item_bool_func2 00767 { 00768 public: 00769 Item_func_strcmp(Item *a,Item *b) :Item_bool_func2(a,b) {} 00770 longlong val_int(); 00771 optimize_type select_optimize() const { return OPTIMIZE_NONE; } 00772 const char *func_name() const { return "strcmp"; } 00773 00774 virtual inline void print(String *str, enum_query_type query_type) 00775 { 00776 Item_func::print(str, query_type); 00777 } 00778 void fix_length_and_dec() 00779 { 00780 Item_bool_func2::fix_length_and_dec(); 00781 fix_char_length(2); // returns "1" or "0" or "-1" 00782 } 00783 }; 00784 00785 00786 struct interval_range 00787 { 00788 Item_result type; 00789 double dbl; 00790 my_decimal dec; 00791 }; 00792 00793 class Item_func_interval :public Item_int_func 00794 { 00795 Item_row *row; 00796 my_bool use_decimal_comparison; 00797 interval_range *intervals; 00798 public: 00799 Item_func_interval(Item_row *a) 00800 :Item_int_func(a),row(a),intervals(0) 00801 { 00802 allowed_arg_cols= 0; // Fetch this value from first argument 00803 } 00804 longlong val_int(); 00805 void fix_length_and_dec(); 00806 const char *func_name() const { return "interval"; } 00807 uint decimal_precision() const { return 2; } 00808 }; 00809 00810 00811 class Item_func_coalesce :public Item_func_numhybrid 00812 { 00813 protected: 00814 enum_field_types cached_field_type; 00815 Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {} 00816 public: 00817 Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {} 00818 double real_op(); 00819 longlong int_op(); 00820 String *str_op(String *); 00821 bool date_op(MYSQL_TIME *ltime, uint fuzzydate); 00822 bool time_op(MYSQL_TIME *ltime); 00823 my_decimal *decimal_op(my_decimal *); 00824 void fix_length_and_dec(); 00825 void find_num_type() {} 00826 enum Item_result result_type () const { return hybrid_type; } 00827 const char *func_name() const { return "coalesce"; } 00828 table_map not_null_tables() const { return 0; } 00829 enum_field_types field_type() const { return cached_field_type; } 00830 }; 00831 00832 00833 class Item_func_ifnull :public Item_func_coalesce 00834 { 00835 protected: 00836 bool field_type_defined; 00837 public: 00838 Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} 00839 double real_op(); 00840 longlong int_op(); 00841 String *str_op(String *str); 00842 bool date_op(MYSQL_TIME *ltime, uint fuzzydate); 00843 bool time_op(MYSQL_TIME *ltime); 00844 my_decimal *decimal_op(my_decimal *); 00845 void fix_length_and_dec(); 00846 const char *func_name() const { return "ifnull"; } 00847 Field *tmp_table_field(TABLE *table); 00848 uint decimal_precision() const; 00849 }; 00850 00851 00852 class Item_func_if :public Item_func 00853 { 00854 enum Item_result cached_result_type; 00855 enum_field_types cached_field_type; 00856 public: 00857 Item_func_if(Item *a,Item *b,Item *c) 00858 :Item_func(a,b,c), cached_result_type(INT_RESULT) 00859 {} 00860 double val_real(); 00861 longlong val_int(); 00862 String *val_str(String *str); 00863 my_decimal *val_decimal(my_decimal *); 00864 bool get_date(MYSQL_TIME *ltime, uint fuzzydate); 00865 bool get_time(MYSQL_TIME *ltime); 00866 enum Item_result result_type () const { return cached_result_type; } 00867 enum_field_types field_type() const { return cached_field_type; } 00868 bool fix_fields(THD *, Item **); 00869 void fix_length_and_dec(); 00870 void fix_after_pullout(st_select_lex *parent_select, 00871 st_select_lex *removed_select); 00872 uint decimal_precision() const; 00873 const char *func_name() const { return "if"; } 00874 private: 00875 void cache_type_info(Item *source); 00876 }; 00877 00878 00879 class Item_func_nullif :public Item_bool_func2 00880 { 00881 enum Item_result cached_result_type; 00882 public: 00883 Item_func_nullif(Item *a,Item *b) 00884 :Item_bool_func2(a,b), cached_result_type(INT_RESULT) 00885 {} 00886 double val_real(); 00887 longlong val_int(); 00888 String *val_str(String *str); 00889 my_decimal *val_decimal(my_decimal *); 00890 enum Item_result result_type () const { return cached_result_type; } 00891 void fix_length_and_dec(); 00892 uint decimal_precision() const { return args[0]->decimal_precision(); } 00893 const char *func_name() const { return "nullif"; } 00894 00895 virtual inline void print(String *str, enum_query_type query_type) 00896 { 00897 Item_func::print(str, query_type); 00898 } 00899 00900 table_map not_null_tables() const { return 0; } 00901 bool is_null(); 00902 }; 00903 00904 00905 /* Functions to handle the optimized IN */ 00906 00907 00908 /* A vector of values of some type */ 00909 00910 class in_vector :public Sql_alloc 00911 { 00912 public: 00913 char *base; 00914 uint size; 00915 qsort2_cmp compare; 00916 const CHARSET_INFO *collation; 00917 uint count; 00918 uint used_count; 00919 in_vector() {} 00920 in_vector(uint elements,uint element_length,qsort2_cmp cmp_func, 00921 const CHARSET_INFO *cmp_coll) 00922 :base((char*) sql_calloc(elements*element_length)), 00923 size(element_length), compare(cmp_func), collation(cmp_coll), 00924 count(elements), used_count(elements) {} 00925 virtual ~in_vector() {} 00926 virtual void set(uint pos,Item *item)=0; 00927 virtual uchar *get_value(Item *item)=0; 00928 void sort() 00929 { 00930 my_qsort2(base,used_count,size,compare,collation); 00931 } 00932 int find(Item *item); 00933 00934 /* 00935 Create an instance of Item_{type} (e.g. Item_decimal) constant object 00936 which type allows it to hold an element of this vector without any 00937 conversions. 00938 The purpose of this function is to be able to get elements of this 00939 vector in form of Item_xxx constants without creating Item_xxx object 00940 for every array element you get (i.e. this implements "FlyWeight" pattern) 00941 */ 00942 virtual Item* create_item() { return NULL; } 00943 00944 /* 00945 Store the value at position #pos into provided item object 00946 SYNOPSIS 00947 value_to_item() 00948 pos Index of value to store 00949 item Constant item to store value into. The item must be of the same 00950 type that create_item() returns. 00951 */ 00952 virtual void value_to_item(uint pos, Item *item) { } 00953 00954 /* Compare values number pos1 and pos2 for equality */ 00955 bool compare_elems(uint pos1, uint pos2) 00956 { 00957 return MY_TEST(compare(collation, base + pos1*size, base + pos2*size)); 00958 } 00959 virtual Item_result result_type()= 0; 00960 }; 00961 00962 class in_string :public in_vector 00963 { 00964 char buff[STRING_BUFFER_USUAL_SIZE]; 00965 String tmp; 00966 public: 00967 in_string(uint elements,qsort2_cmp cmp_func, const CHARSET_INFO *cs); 00968 ~in_string(); 00969 void set(uint pos,Item *item); 00970 uchar *get_value(Item *item); 00971 Item* create_item() 00972 { 00973 return new Item_string(collation); 00974 } 00975 void value_to_item(uint pos, Item *item) 00976 { 00977 String *str=((String*) base)+pos; 00978 Item_string *to= (Item_string*)item; 00979 to->str_value= *str; 00980 } 00981 Item_result result_type() { return STRING_RESULT; } 00982 }; 00983 00984 class in_longlong :public in_vector 00985 { 00986 protected: 00987 /* 00988 Here we declare a temporary variable (tmp) of the same type as the 00989 elements of this vector. tmp is used in finding if a given value is in 00990 the list. 00991 */ 00992 struct packed_longlong 00993 { 00994 longlong val; 00995 longlong unsigned_flag; // Use longlong, not bool, to preserve alignment 00996 } tmp; 00997 public: 00998 in_longlong(uint elements); 00999 void set(uint pos,Item *item); 01000 uchar *get_value(Item *item); 01001 01002 Item* create_item() 01003 { 01004 /* 01005 We're created a signed INT, this may not be correct in 01006 general case (see BUG#19342). 01007 */ 01008 return new Item_int((longlong)0); 01009 } 01010 void value_to_item(uint pos, Item *item) 01011 { 01012 ((Item_int*) item)->value= ((packed_longlong*) base)[pos].val; 01013 ((Item_int*) item)->unsigned_flag= (my_bool) 01014 ((packed_longlong*) base)[pos].unsigned_flag; 01015 } 01016 Item_result result_type() { return INT_RESULT; } 01017 01018 friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); 01019 }; 01020 01021 01022 class in_datetime_as_longlong :public in_longlong 01023 { 01024 public: 01025 in_datetime_as_longlong(uint elements) 01026 :in_longlong(elements) {}; 01027 Item *create_item() 01028 { 01029 return new Item_temporal(MYSQL_TYPE_DATETIME, 0LL); 01030 } 01031 void set(uint pos, Item *item); 01032 uchar *get_value(Item *item); 01033 }; 01034 01035 01036 class in_time_as_longlong :public in_longlong 01037 { 01038 public: 01039 in_time_as_longlong(uint elements) 01040 :in_longlong(elements) {}; 01041 Item *create_item() 01042 { 01043 return new Item_temporal(MYSQL_TYPE_TIME, 0LL); 01044 } 01045 void set(uint pos, Item *item); 01046 uchar *get_value(Item *item); 01047 }; 01048 01049 01050 /* 01051 Class to represent a vector of constant DATE/DATETIME values. 01052 Values are obtained with help of the get_datetime_value() function. 01053 If the left item is a constant one then its value is cached in the 01054 lval_cache variable. 01055 */ 01056 class in_datetime :public in_longlong 01057 { 01058 public: 01059 THD *thd; 01060 /* An item used to issue warnings. */ 01061 Item *warn_item; 01062 /* Cache for the left item. */ 01063 Item *lval_cache; 01064 01065 in_datetime(Item *warn_item_arg, uint elements) 01066 :in_longlong(elements), thd(current_thd), warn_item(warn_item_arg), 01067 lval_cache(0) {}; 01068 void set(uint pos,Item *item); 01069 uchar *get_value(Item *item); 01070 friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b); 01071 Item* create_item() 01072 { 01073 return new Item_temporal(MYSQL_TYPE_DATETIME, (longlong) 0); 01074 } 01075 }; 01076 01077 01078 class in_double :public in_vector 01079 { 01080 double tmp; 01081 public: 01082 in_double(uint elements); 01083 void set(uint pos,Item *item); 01084 uchar *get_value(Item *item); 01085 Item *create_item() 01086 { 01087 return new Item_float(0.0, 0); 01088 } 01089 void value_to_item(uint pos, Item *item) 01090 { 01091 ((Item_float*)item)->value= ((double*) base)[pos]; 01092 } 01093 Item_result result_type() { return REAL_RESULT; } 01094 }; 01095 01096 01097 class in_decimal :public in_vector 01098 { 01099 my_decimal val; 01100 public: 01101 in_decimal(uint elements); 01102 void set(uint pos, Item *item); 01103 uchar *get_value(Item *item); 01104 Item *create_item() 01105 { 01106 return new Item_decimal(0, FALSE); 01107 } 01108 void value_to_item(uint pos, Item *item) 01109 { 01110 my_decimal *dec= ((my_decimal *)base) + pos; 01111 Item_decimal *item_dec= (Item_decimal*)item; 01112 item_dec->set_decimal_value(dec); 01113 } 01114 Item_result result_type() { return DECIMAL_RESULT; } 01115 01116 }; 01117 01118 01119 /* 01120 ** Classes for easy comparing of non const items 01121 */ 01122 01123 class cmp_item :public Sql_alloc 01124 { 01125 public: 01126 const CHARSET_INFO *cmp_charset; 01127 cmp_item() { cmp_charset= &my_charset_bin; } 01128 virtual ~cmp_item() {} 01129 virtual void store_value(Item *item)= 0; 01130 virtual int cmp(Item *item)= 0; 01131 // for optimized IN with row 01132 virtual int compare(cmp_item *item)= 0; 01133 static cmp_item* get_comparator(Item_result type, const CHARSET_INFO *cs); 01134 virtual cmp_item *make_same()= 0; 01135 virtual void store_value_by_template(cmp_item *tmpl, Item *item) 01136 { 01137 store_value(item); 01138 } 01139 }; 01140 01141 class cmp_item_string :public cmp_item 01142 { 01143 protected: 01144 String *value_res; 01145 public: 01146 cmp_item_string () {} 01147 cmp_item_string (const CHARSET_INFO *cs) { cmp_charset= cs; } 01148 void set_charset(const CHARSET_INFO *cs) { cmp_charset= cs; } 01149 friend class cmp_item_sort_string; 01150 friend class cmp_item_sort_string_in_static; 01151 }; 01152 01153 class cmp_item_sort_string :public cmp_item_string 01154 { 01155 protected: 01156 char value_buff[STRING_BUFFER_USUAL_SIZE]; 01157 String value; 01158 public: 01159 cmp_item_sort_string(): 01160 cmp_item_string() {} 01161 cmp_item_sort_string(const CHARSET_INFO *cs): 01162 cmp_item_string(cs), 01163 value(value_buff, sizeof(value_buff), cs) {} 01164 void store_value(Item *item) 01165 { 01166 String *res= item->val_str(&value); 01167 if(res && (res != &value)) 01168 { 01169 // 'res' may point in item's temporary internal data, so make a copy 01170 value.copy(*res); 01171 } 01172 value_res= &value; 01173 } 01174 int cmp(Item *arg) 01175 { 01176 char buff[STRING_BUFFER_USUAL_SIZE]; 01177 String tmp(buff, sizeof(buff), cmp_charset), *res; 01178 res= arg->val_str(&tmp); 01179 return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) : 01180 (res ? -1 : 0)); 01181 } 01182 int compare(cmp_item *ci) 01183 { 01184 cmp_item_string *l_cmp= (cmp_item_string *) ci; 01185 return sortcmp(value_res, l_cmp->value_res, cmp_charset); 01186 } 01187 cmp_item *make_same(); 01188 void set_charset(const CHARSET_INFO *cs) 01189 { 01190 cmp_charset= cs; 01191 value.set_quick(value_buff, sizeof(value_buff), cs); 01192 } 01193 }; 01194 01195 class cmp_item_int :public cmp_item 01196 { 01197 longlong value; 01198 public: 01199 cmp_item_int() {} /* Remove gcc warning */ 01200 void store_value(Item *item) 01201 { 01202 value= item->val_int(); 01203 } 01204 int cmp(Item *arg) 01205 { 01206 return value != arg->val_int(); 01207 } 01208 int compare(cmp_item *ci) 01209 { 01210 cmp_item_int *l_cmp= (cmp_item_int *)ci; 01211 return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1); 01212 } 01213 cmp_item *make_same(); 01214 }; 01215 01216 /* 01217 Compare items in the DATETIME context. 01218 Values are obtained with help of the get_datetime_value() function. 01219 If the left item is a constant one then its value is cached in the 01220 lval_cache variable. 01221 */ 01222 class cmp_item_datetime :public cmp_item 01223 { 01224 longlong value; 01225 public: 01226 THD *thd; 01227 /* Item used for issuing warnings. */ 01228 Item *warn_item; 01229 /* Cache for the left item. */ 01230 Item *lval_cache; 01231 01232 cmp_item_datetime(Item *warn_item_arg) 01233 :thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {} 01234 void store_value(Item *item); 01235 int cmp(Item *arg); 01236 int compare(cmp_item *ci); 01237 cmp_item *make_same(); 01238 }; 01239 01240 class cmp_item_real :public cmp_item 01241 { 01242 double value; 01243 public: 01244 cmp_item_real() {} /* Remove gcc warning */ 01245 void store_value(Item *item) 01246 { 01247 value= item->val_real(); 01248 } 01249 int cmp(Item *arg) 01250 { 01251 return value != arg->val_real(); 01252 } 01253 int compare(cmp_item *ci) 01254 { 01255 cmp_item_real *l_cmp= (cmp_item_real *) ci; 01256 return (value < l_cmp->value)? -1 : ((value == l_cmp->value) ? 0 : 1); 01257 } 01258 cmp_item *make_same(); 01259 }; 01260 01261 01262 class cmp_item_decimal :public cmp_item 01263 { 01264 my_decimal value; 01265 public: 01266 cmp_item_decimal() {} /* Remove gcc warning */ 01267 void store_value(Item *item); 01268 int cmp(Item *arg); 01269 int compare(cmp_item *c); 01270 cmp_item *make_same(); 01271 }; 01272 01273 01274 /* 01275 cmp_item for optimized IN with row (right part string, which never 01276 be changed) 01277 */ 01278 01279 class cmp_item_sort_string_in_static :public cmp_item_string 01280 { 01281 protected: 01282 String value; 01283 public: 01284 cmp_item_sort_string_in_static(const CHARSET_INFO *cs): 01285 cmp_item_string(cs) {} 01286 void store_value(Item *item) 01287 { 01288 value_res= item->val_str(&value); 01289 } 01290 int cmp(Item *item) 01291 { 01292 // Should never be called 01293 DBUG_ASSERT(0); 01294 return 1; 01295 } 01296 int compare(cmp_item *ci) 01297 { 01298 cmp_item_string *l_cmp= (cmp_item_string *) ci; 01299 return sortcmp(value_res, l_cmp->value_res, cmp_charset); 01300 } 01301 cmp_item *make_same() 01302 { 01303 return new cmp_item_sort_string_in_static(cmp_charset); 01304 } 01305 }; 01306 01307 01308 /* 01309 The class Item_func_case is the CASE ... WHEN ... THEN ... END function 01310 implementation. 01311 01312 When there is no expression between CASE and the first WHEN 01313 (the CASE expression) then this function simple checks all WHEN expressions 01314 one after another. When some WHEN expression evaluated to TRUE then the 01315 value of the corresponding THEN expression is returned. 01316 01317 When the CASE expression is specified then it is compared to each WHEN 01318 expression individually. When an equal WHEN expression is found 01319 corresponding THEN expression is returned. 01320 In order to do correct comparisons several comparators are used. One for 01321 each result type. Different result types that are used in particular 01322 CASE ... END expression are collected in the fix_length_and_dec() member 01323 function and only comparators for there result types are used. 01324 */ 01325 01326 class Item_func_case :public Item_func 01327 { 01328 int first_expr_num, else_expr_num; 01329 enum Item_result cached_result_type, left_result_type; 01330 String tmp_value; 01331 uint ncases; 01332 Item_result cmp_type; 01333 DTCollation cmp_collation; 01334 enum_field_types cached_field_type; 01335 cmp_item *cmp_items[5]; /* For all result types */ 01336 cmp_item *case_item; 01337 public: 01338 Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg) 01339 :Item_func(), first_expr_num(-1), else_expr_num(-1), 01340 cached_result_type(INT_RESULT), left_result_type(INT_RESULT), case_item(0) 01341 { 01342 ncases= list.elements; 01343 if (first_expr_arg) 01344 { 01345 first_expr_num= list.elements; 01346 list.push_back(first_expr_arg); 01347 } 01348 if (else_expr_arg) 01349 { 01350 else_expr_num= list.elements; 01351 list.push_back(else_expr_arg); 01352 } 01353 set_arguments(list); 01354 memset(&cmp_items, 0, sizeof(cmp_items)); 01355 } 01356 double val_real(); 01357 longlong val_int(); 01358 String *val_str(String *); 01359 my_decimal *val_decimal(my_decimal *); 01360 bool get_date(MYSQL_TIME *ltime, uint fuzzydate); 01361 bool get_time(MYSQL_TIME *ltime); 01362 bool fix_fields(THD *thd, Item **ref); 01363 void fix_length_and_dec(); 01364 uint decimal_precision() const; 01365 table_map not_null_tables() const { return 0; } 01366 enum Item_result result_type () const { return cached_result_type; } 01367 enum_field_types field_type() const { return cached_field_type; } 01368 const char *func_name() const { return "case"; } 01369 virtual void print(String *str, enum_query_type query_type); 01370 Item *find_item(String *str); 01371 const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } 01372 void cleanup(); 01373 void agg_num_lengths(Item *arg); 01374 }; 01375 01376 /* 01377 The Item_func_in class implements the in_expr IN(values_list) function. 01378 01379 The current implementation distinguishes 2 cases: 01380 1) all items in the value_list are constants and have the same 01381 result type. This case is handled by in_vector class. 01382 2) items in the value_list have different result types or there is some 01383 non-constant items. 01384 In this case Item_func_in employs several cmp_item objects to performs 01385 comparisons of in_expr and an item from the values_list. One cmp_item 01386 object for each result type. Different result types are collected in the 01387 fix_length_and_dec() member function by means of collect_cmp_types() 01388 function. 01389 */ 01390 class Item_func_in :public Item_func_opt_neg 01391 { 01392 public: 01393 /* 01394 an array of values when the right hand arguments of IN 01395 are all SQL constant and there are no nulls 01396 */ 01397 in_vector *array; 01398 bool have_null; 01399 /* 01400 true when all arguments of the IN clause are of compatible types 01401 and can be used safely as comparisons for key conditions 01402 */ 01403 bool arg_types_compatible; 01404 Item_result left_result_type; 01405 cmp_item *cmp_items[6]; /* One cmp_item for each result type */ 01406 DTCollation cmp_collation; 01407 01408 Item_func_in(List<Item> &list) 01409 :Item_func_opt_neg(list), array(0), have_null(0), 01410 arg_types_compatible(FALSE) 01411 { 01412 memset(&cmp_items, 0, sizeof(cmp_items)); 01413 allowed_arg_cols= 0; // Fetch this value from first argument 01414 } 01415 longlong val_int(); 01416 bool fix_fields(THD *, Item **); 01417 void fix_after_pullout(st_select_lex *parent_select, 01418 st_select_lex *removed_select); 01419 void fix_length_and_dec(); 01420 uint decimal_precision() const { return 1; } 01421 void cleanup() 01422 { 01423 uint i; 01424 DBUG_ENTER("Item_func_in::cleanup"); 01425 Item_int_func::cleanup(); 01426 delete array; 01427 array= 0; 01428 for (i= 0; i <= (uint)DECIMAL_RESULT + 1; i++) 01429 { 01430 delete cmp_items[i]; 01431 cmp_items[i]= 0; 01432 } 01433 DBUG_VOID_RETURN; 01434 } 01435 optimize_type select_optimize() const 01436 { return OPTIMIZE_KEY; } 01437 virtual void print(String *str, enum_query_type query_type); 01438 enum Functype functype() const { return IN_FUNC; } 01439 const char *func_name() const { return " IN "; } 01440 bool nulls_in_row(); 01441 bool is_bool_func() { return 1; } 01442 const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } 01443 }; 01444 01445 class cmp_item_row :public cmp_item 01446 { 01447 cmp_item **comparators; 01448 uint n; 01449 public: 01450 cmp_item_row(): comparators(0), n(0) {} 01451 ~cmp_item_row(); 01452 void store_value(Item *item); 01453 inline void alloc_comparators(); 01454 int cmp(Item *arg); 01455 int compare(cmp_item *arg); 01456 cmp_item *make_same(); 01457 void store_value_by_template(cmp_item *tmpl, Item *); 01458 friend void Item_func_in::fix_length_and_dec(); 01459 }; 01460 01461 01462 class in_row :public in_vector 01463 { 01464 cmp_item_row tmp; 01465 public: 01466 in_row(uint elements, Item *); 01467 ~in_row(); 01468 void set(uint pos,Item *item); 01469 uchar *get_value(Item *item); 01470 friend void Item_func_in::fix_length_and_dec(); 01471 Item_result result_type() { return ROW_RESULT; } 01472 }; 01473 01474 /* Functions used by where clause */ 01475 01476 class Item_func_isnull :public Item_bool_func 01477 { 01478 protected: 01479 longlong cached_value; 01480 public: 01481 Item_func_isnull(Item *a) :Item_bool_func(a) {} 01482 longlong val_int(); 01483 enum Functype functype() const { return ISNULL_FUNC; } 01484 void fix_length_and_dec() 01485 { 01486 decimals=0; max_length=1; maybe_null=0; 01487 update_used_tables(); 01488 } 01489 const char *func_name() const { return "isnull"; } 01490 /* Optimize case of not_null_column IS NULL */ 01491 virtual void update_used_tables() 01492 { 01493 if (!args[0]->maybe_null) 01494 { 01495 used_tables_cache= 0; /* is always false */ 01496 const_item_cache= 1; 01497 cached_value= (longlong) 0; 01498 } 01499 else 01500 { 01501 args[0]->update_used_tables(); 01502 with_subselect= args[0]->has_subquery(); 01503 with_stored_program= args[0]->has_stored_program(); 01504 01505 if ((const_item_cache= !(used_tables_cache= args[0]->used_tables()) && 01506 !with_subselect && !with_stored_program)) 01507 { 01508 /* Remember if the value is always NULL or never NULL */ 01509 cached_value= (longlong) args[0]->is_null(); 01510 } 01511 } 01512 } 01513 table_map not_null_tables() const { return 0; } 01514 optimize_type select_optimize() const { return OPTIMIZE_NULL; } 01515 Item *neg_transformer(THD *thd); 01516 const CHARSET_INFO *compare_collation() 01517 { return args[0]->collation.collation; } 01518 }; 01519 01520 /* Functions used by HAVING for rewriting IN subquery */ 01521 01522 class Item_in_subselect; 01523 01524 /* 01525 This is like IS NOT NULL but it also remembers if it ever has 01526 encountered a NULL; it remembers this in the "was_null" property of the 01527 "owner" item. 01528 */ 01529 class Item_is_not_null_test :public Item_func_isnull 01530 { 01531 Item_in_subselect* owner; 01532 public: 01533 Item_is_not_null_test(Item_in_subselect* ow, Item *a) 01534 :Item_func_isnull(a), owner(ow) 01535 {} 01536 enum Functype functype() const { return ISNOTNULLTEST_FUNC; } 01537 longlong val_int(); 01538 const char *func_name() const { return "<is_not_null_test>"; } 01539 void update_used_tables(); 01545 table_map get_initial_pseudo_tables() const { return RAND_TABLE_BIT; } 01546 }; 01547 01548 01549 class Item_func_isnotnull :public Item_bool_func 01550 { 01551 bool abort_on_null; 01552 public: 01553 Item_func_isnotnull(Item *a) :Item_bool_func(a), abort_on_null(0) {} 01554 longlong val_int(); 01555 enum Functype functype() const { return ISNOTNULL_FUNC; } 01556 void fix_length_and_dec() 01557 { 01558 decimals=0; max_length=1; maybe_null=0; 01559 } 01560 const char *func_name() const { return "isnotnull"; } 01561 optimize_type select_optimize() const { return OPTIMIZE_NULL; } 01562 table_map not_null_tables() const 01563 { return abort_on_null ? not_null_tables_cache : 0; } 01564 Item *neg_transformer(THD *thd); 01565 virtual void print(String *str, enum_query_type query_type); 01566 const CHARSET_INFO *compare_collation() 01567 { return args[0]->collation.collation; } 01568 void top_level_item() { abort_on_null=1; } 01569 }; 01570 01571 01572 class Item_func_like :public Item_bool_func2 01573 { 01574 // Turbo Boyer-Moore data 01575 bool canDoTurboBM; // pattern is '%abcd%' case 01576 const char* pattern; 01577 int pattern_len; 01578 01579 // TurboBM buffers, *this is owner 01580 int* bmGs; // good suffix shift table, size is pattern_len + 1 01581 int* bmBc; // bad character shift table, size is alphabet_size 01582 01583 void turboBM_compute_suffixes(int* suff); 01584 void turboBM_compute_good_suffix_shifts(int* suff); 01585 void turboBM_compute_bad_character_shifts(); 01586 bool turboBM_matches(const char* text, int text_len) const; 01587 enum { alphabet_size = 256 }; 01588 01589 Item *escape_item; 01590 01591 bool escape_used_in_parsing; 01592 01593 public: 01594 int escape; 01595 01596 Item_func_like(Item *a,Item *b, Item *escape_arg, bool escape_used) 01597 :Item_bool_func2(a,b), canDoTurboBM(FALSE), pattern(0), pattern_len(0), 01598 bmGs(0), bmBc(0), escape_item(escape_arg), 01599 escape_used_in_parsing(escape_used) {} 01600 longlong val_int(); 01601 enum Functype functype() const { return LIKE_FUNC; } 01602 optimize_type select_optimize() const; 01603 cond_result eq_cmp_result() const { return COND_TRUE; } 01604 const char *func_name() const { return "like"; } 01605 bool fix_fields(THD *thd, Item **ref); 01606 void cleanup(); 01611 bool escape_was_used_in_parsing() const { return escape_used_in_parsing; } 01612 }; 01613 01614 01615 class Item_func_regex :public Item_bool_func 01616 { 01617 my_regex_t preg; 01618 bool regex_compiled; 01619 bool regex_is_const; 01620 String prev_regexp; 01621 DTCollation cmp_collation; 01622 const CHARSET_INFO *regex_lib_charset; 01623 int regex_lib_flags; 01624 String conv; 01625 int regcomp(bool send_error); 01626 public: 01627 Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b), 01628 regex_compiled(0),regex_is_const(0) {} 01629 void cleanup(); 01630 longlong val_int(); 01631 bool fix_fields(THD *thd, Item **ref); 01632 const char *func_name() const { return "regexp"; } 01633 01634 virtual inline void print(String *str, enum_query_type query_type) 01635 { 01636 print_op(str, query_type); 01637 } 01638 01639 const CHARSET_INFO *compare_collation() { return cmp_collation.collation; } 01640 }; 01641 01642 01643 class Item_cond :public Item_bool_func 01644 { 01645 protected: 01646 List<Item> list; 01647 bool abort_on_null; 01648 01649 public: 01650 /* Item_cond() is only used to create top level items */ 01651 Item_cond(): Item_bool_func(), abort_on_null(1) 01652 { const_item_cache=0; } 01653 Item_cond(Item *i1,Item *i2) 01654 :Item_bool_func(), abort_on_null(0) 01655 { 01656 list.push_back(i1); 01657 list.push_back(i2); 01658 } 01659 Item_cond(THD *thd, Item_cond *item); 01660 Item_cond(List<Item> &nlist) 01661 :Item_bool_func(), list(nlist), abort_on_null(0) {} 01662 bool add(Item *item) 01663 { 01664 DBUG_ASSERT(item); 01665 return list.push_back(item); 01666 } 01667 bool add_at_head(Item *item) 01668 { 01669 DBUG_ASSERT(item); 01670 return list.push_front(item); 01671 } 01672 void add_at_head(List<Item> *nlist) 01673 { 01674 DBUG_ASSERT(nlist->elements); 01675 list.prepand(nlist); 01676 } 01677 bool fix_fields(THD *, Item **ref); 01678 void fix_after_pullout(st_select_lex *parent_select, 01679 st_select_lex *removed_select); 01680 01681 enum Type type() const { return COND_ITEM; } 01682 List<Item>* argument_list() { return &list; } 01683 table_map used_tables() const { return used_tables_cache; } 01684 void update_used_tables(); 01685 virtual void print(String *str, enum_query_type query_type); 01686 void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, 01687 List<Item> &fields); 01688 friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, 01689 Item **conds); 01690 void top_level_item() { abort_on_null=1; } 01691 void copy_andor_arguments(THD *thd, Item_cond *item, bool real_items= false); 01692 bool walk(Item_processor processor, bool walk_subquery, uchar *arg); 01693 Item *transform(Item_transformer transformer, uchar *arg); 01694 void traverse_cond(Cond_traverser, void *arg, traverse_order order); 01695 void neg_arguments(THD *thd); 01696 enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } 01697 bool subst_argument_checker(uchar **arg) { return TRUE; } 01698 Item *compile(Item_analyzer analyzer, uchar **arg_p, 01699 Item_transformer transformer, uchar *arg_t); 01700 01701 virtual bool equality_substitution_analyzer(uchar **arg) { return true; } 01702 }; 01703 01704 01705 /* 01706 The class Item_equal is used to represent conjunctions of equality 01707 predicates of the form field1 = field2, and field=const in where 01708 conditions and on expressions. 01709 01710 All equality predicates of the form field1=field2 contained in a 01711 conjunction are substituted for a sequence of items of this class. 01712 An item of this class Item_equal(f1,f2,...fk) represents a 01713 multiple equality f1=f2=...=fk. 01714 01715 If a conjunction contains predicates f1=f2 and f2=f3, a new item of 01716 this class is created Item_equal(f1,f2,f3) representing the multiple 01717 equality f1=f2=f3 that substitutes the above equality predicates in 01718 the conjunction. 01719 A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be 01720 substituted for the item representing the same multiple equality 01721 f1=f2=f3. 01722 An item Item_equal(f1,f2) can appear instead of a conjunction of 01723 f2=f1 and f1=f2, or instead of just the predicate f1=f2. 01724 01725 An item of the class Item_equal inherits equalities from outer 01726 conjunctive levels. 01727 01728 Suppose we have a where condition of the following form: 01729 WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)). 01730 In this case: 01731 f1=f2 will be substituted for Item_equal(f1,f2); 01732 f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5); 01733 f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5); 01734 01735 An object of the class Item_equal can contain an optional constant 01736 item c. Then it represents a multiple equality of the form 01737 c=f1=...=fk. 01738 01739 Objects of the class Item_equal are used for the following: 01740 01741 1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any 01742 pair of tables ti and tj as joined by an equi-condition. 01743 Thus it provide us with additional access paths from table to table. 01744 01745 2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new 01746 SARGable predicates: 01747 f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj). 01748 It also can give us additional index scans and can allow us to 01749 improve selectivity estimates. 01750 01751 3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the 01752 selected execution plan for the query: if table ti is accessed 01753 before the table tj then in any predicate P in the where condition 01754 the occurrence of tj.fj is substituted for ti.fi. This can allow 01755 an evaluation of the predicate at an earlier step. 01756 01757 When feature 1 is supported they say that join transitive closure 01758 is employed. 01759 When feature 2 is supported they say that search argument transitive 01760 closure is employed. 01761 Both features are usually supported by preprocessing original query and 01762 adding additional predicates. 01763 We do not just add predicates, we rather dynamically replace some 01764 predicates that can not be used to access tables in the investigated 01765 plan for those, obtained by substitution of some fields for equal fields, 01766 that can be used. 01767 01768 Prepared Statements/Stored Procedures note: instances of class 01769 Item_equal are created only at the time a PS/SP is executed and 01770 are deleted in the end of execution. All changes made to these 01771 objects need not be registered in the list of changes of the parse 01772 tree and do not harm PS/SP re-execution. 01773 01774 Item equal objects are employed only at the optimize phase. Usually they are 01775 not supposed to be evaluated. Yet in some cases we call the method val_int() 01776 for them. We have to take care of restricting the predicate such an 01777 object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik. 01778 */ 01779 struct st_join_table; 01780 01781 class Item_equal: public Item_bool_func 01782 { 01783 List<Item_field> fields; /* list of equal field items */ 01784 Item *const_item; /* optional constant item equal to fields items */ 01785 cmp_item *eval_item; 01786 Arg_comparator cmp; 01787 bool cond_false; 01788 bool compare_as_dates; 01789 public: 01790 inline Item_equal() 01791 : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) 01792 { const_item_cache=0 ;} 01793 Item_equal(Item_field *f1, Item_field *f2); 01794 Item_equal(Item *c, Item_field *f); 01795 Item_equal(Item_equal *item_equal); 01796 virtual ~Item_equal() 01797 { 01798 delete eval_item; 01799 } 01800 01801 inline Item* get_const() { return const_item; } 01802 void compare_const(Item *c); 01803 void add(Item *c, Item_field *f); 01804 void add(Item *c); 01805 void add(Item_field *f); 01806 uint members(); 01807 bool contains(Field *field); 01813 Item_field* get_first() { return fields.head(); } 01814 Item_field* get_subst_item(const Item_field *field); 01815 void merge(Item_equal *item); 01816 void update_const(); 01817 enum Functype functype() const { return MULT_EQUAL_FUNC; } 01818 longlong val_int(); 01819 const char *func_name() const { return "multiple equal"; } 01820 optimize_type select_optimize() const { return OPTIMIZE_EQUAL; } 01821 void sort(Item_field_cmpfunc compare, void *arg); 01822 friend class Item_equal_iterator; 01823 void fix_length_and_dec(); 01824 bool fix_fields(THD *thd, Item **ref); 01825 void update_used_tables(); 01826 bool walk(Item_processor processor, bool walk_subquery, uchar *arg); 01827 Item *transform(Item_transformer transformer, uchar *arg); 01828 virtual void print(String *str, enum_query_type query_type); 01829 const CHARSET_INFO *compare_collation() 01830 { return fields.head()->collation.collation; } 01831 01832 virtual bool equality_substitution_analyzer(uchar **arg) { return true; } 01833 01834 virtual Item* equality_substitution_transformer(uchar *arg); 01835 }; 01836 01837 class COND_EQUAL: public Sql_alloc 01838 { 01839 public: 01840 uint max_members; /* max number of members the current level 01841 list and all lower level lists */ 01842 COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */ 01843 List<Item_equal> current_level; /* list of multiple equalities of 01844 the current and level */ 01845 COND_EQUAL() 01846 { 01847 upper_levels= 0; 01848 } 01849 }; 01850 01851 01852 class Item_equal_iterator : public List_iterator_fast<Item_field> 01853 { 01854 public: 01855 inline Item_equal_iterator(Item_equal &item_equal) 01856 :List_iterator_fast<Item_field> (item_equal.fields) 01857 {} 01858 inline Item_field* operator++(int) 01859 { 01860 Item_field *item= (*(List_iterator_fast<Item_field> *) this)++; 01861 return item; 01862 } 01863 inline void rewind(void) 01864 { 01865 List_iterator_fast<Item_field>::rewind(); 01866 } 01867 }; 01868 01869 class Item_cond_and :public Item_cond 01870 { 01871 public: 01872 COND_EQUAL cond_equal; /* contains list of Item_equal objects for 01873 the current and level and reference 01874 to multiple equalities of upper and levels */ 01875 Item_cond_and() :Item_cond() {} 01876 Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {} 01877 Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {} 01878 Item_cond_and(List<Item> &list_arg): Item_cond(list_arg) {} 01879 enum Functype functype() const { return COND_AND_FUNC; } 01880 longlong val_int(); 01881 const char *func_name() const { return "and"; } 01882 Item* copy_andor_structure(THD *thd, bool real_items) 01883 { 01884 Item_cond_and *item; 01885 if ((item= new Item_cond_and(thd, this))) 01886 item->copy_andor_arguments(thd, this, real_items); 01887 return item; 01888 } 01889 Item *neg_transformer(THD *thd); 01890 }; 01891 01892 inline bool is_cond_and(Item *item) 01893 { 01894 if (item->type() != Item::COND_ITEM) 01895 return FALSE; 01896 01897 Item_cond *cond_item= (Item_cond*) item; 01898 return (cond_item->functype() == Item_func::COND_AND_FUNC); 01899 } 01900 01901 class Item_cond_or :public Item_cond 01902 { 01903 public: 01904 Item_cond_or() :Item_cond() {} 01905 Item_cond_or(Item *i1,Item *i2) :Item_cond(i1,i2) {} 01906 Item_cond_or(THD *thd, Item_cond_or *item) :Item_cond(thd, item) {} 01907 Item_cond_or(List<Item> &list_arg): Item_cond(list_arg) {} 01908 enum Functype functype() const { return COND_OR_FUNC; } 01909 longlong val_int(); 01910 const char *func_name() const { return "or"; } 01911 Item* copy_andor_structure(THD *thd, bool real_items) 01912 { 01913 Item_cond_or *item; 01914 if ((item= new Item_cond_or(thd, this))) 01915 item->copy_andor_arguments(thd, this, real_items); 01916 return item; 01917 } 01918 Item *neg_transformer(THD *thd); 01919 }; 01920 01921 inline bool is_cond_or(Item *item) 01922 { 01923 if (item->type() != Item::COND_ITEM) 01924 return FALSE; 01925 01926 Item_cond *cond_item= (Item_cond*) item; 01927 return (cond_item->functype() == Item_func::COND_OR_FUNC); 01928 } 01929 01930 /* Some useful inline functions */ 01931 01932 inline Item *and_conds(Item *a, Item *b) 01933 { 01934 if (!b) return a; 01935 if (!a) return b; 01936 return new Item_cond_and(a, b); 01937 } 01938 01939 01940 Item *and_expressions(Item *a, Item *b, Item **org_item); 01941 01942 longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, 01943 Item *warn_item, bool *is_null); 01944 01945 01946 bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, 01947 const char *warn_name, MYSQL_TIME *l_time); 01948 01949 /* 01950 These need definitions from this file but the variables are defined 01951 in mysqld.h. The variables really belong in this component, but for 01952 the time being we leave them in mysqld.cc to avoid merge problems. 01953 */ 01954 extern Eq_creator eq_creator; 01955 extern Ne_creator ne_creator; 01956 extern Gt_creator gt_creator; 01957 extern Lt_creator lt_creator; 01958 extern Ge_creator ge_creator; 01959 extern Le_creator le_creator; 01960 01961 #endif /* ITEM_CMPFUNC_INCLUDED */