1 #ifndef ITEM_CMPFUNC_INCLUDED
2 #define ITEM_CMPFUNC_INCLUDED
3 /* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
4 Copyright (c) 2009, 2020, MariaDB
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
18
19
20 /* compare and test functions */
21
22 #ifdef USE_PRAGMA_INTERFACE
23 #pragma interface /* gcc class implementation */
24 #endif
25
26 #include "item_func.h" /* Item_int_func, Item_bool_func */
27 #define PCRE_STATIC 1 /* Important on Windows */
28 #include "pcre.h" /* pcre header file */
29 #include "item.h"
30
31 extern Item_result item_cmp_type(Item_result a,Item_result b);
item_cmp_type(const Item * a,const Item * b)32 inline Item_result item_cmp_type(const Item *a, const Item *b)
33 {
34 return item_cmp_type(a->cmp_type(), b->cmp_type());
35 }
item_cmp_type(Item_result a,const Item * b)36 inline Item_result item_cmp_type(Item_result a, const Item *b)
37 {
38 return item_cmp_type(a, b->cmp_type());
39 }
40 class Item_bool_func2;
41 class Arg_comparator;
42
43 typedef int (Arg_comparator::*arg_cmp_func)();
44
45 typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg);
46
47 class Arg_comparator: public Sql_alloc
48 {
49 Item **a, **b;
50 const Type_handler *m_compare_handler;
51 CHARSET_INFO *m_compare_collation;
52 arg_cmp_func func;
53 Item_func_or_sum *owner;
54 bool set_null; // TRUE <=> set owner->null_value
55 Arg_comparator *comparators; // used only for compare_row()
56 double precision;
57 /* Fields used in DATE/DATETIME comparison. */
58 Item *a_cache, *b_cache; // Cached values of a and b items
59 // when one of arguments is NULL.
60
61 int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2);
62
compare_not_null_values(longlong val1,longlong val2)63 int compare_not_null_values(longlong val1, longlong val2)
64 {
65 if (set_null)
66 owner->null_value= false;
67 if (val1 < val2) return -1;
68 if (val1 == val2) return 0;
69 return 1;
70 }
71 public:
72 /* Allow owner function to use string buffers. */
73 String value1, value2;
74
Arg_comparator()75 Arg_comparator():
76 m_compare_handler(&type_handler_null),
77 m_compare_collation(&my_charset_bin),
78 set_null(TRUE), comparators(0),
79 a_cache(0), b_cache(0) {};
Arg_comparator(Item ** a1,Item ** a2)80 Arg_comparator(Item **a1, Item **a2): a(a1), b(a2),
81 m_compare_handler(&type_handler_null),
82 m_compare_collation(&my_charset_bin),
83 set_null(TRUE), comparators(0),
84 a_cache(0), b_cache(0) {};
85
86 public:
87 bool set_cmp_func_for_row_arguments();
88 bool set_cmp_func_row();
89 bool set_cmp_func_string();
90 bool set_cmp_func_time();
91 bool set_cmp_func_datetime();
92 bool set_cmp_func_int();
93 bool set_cmp_func_real();
94 bool set_cmp_func_decimal();
95
set_cmp_func(Item_func_or_sum * owner_arg,Item ** a1,Item ** a2,bool set_null_arg)96 inline int set_cmp_func(Item_func_or_sum *owner_arg,
97 Item **a1, Item **a2, bool set_null_arg)
98 {
99 set_null= set_null_arg;
100 return set_cmp_func(owner_arg, a1, a2);
101 }
compare()102 inline int compare() { return (this->*func)(); }
103
104 int compare_string(); // compare args[0] & args[1]
105 int compare_real(); // compare args[0] & args[1]
106 int compare_decimal(); // compare args[0] & args[1]
107 int compare_int_signed(); // compare args[0] & args[1]
108 int compare_int_signed_unsigned();
109 int compare_int_unsigned_signed();
110 int compare_int_unsigned();
111 int compare_row(); // compare args[0] & args[1]
112 int compare_e_string(); // compare args[0] & args[1]
113 int compare_e_real(); // compare args[0] & args[1]
114 int compare_e_decimal(); // compare args[0] & args[1]
115 int compare_e_int(); // compare args[0] & args[1]
116 int compare_e_int_diff_signedness();
117 int compare_e_row(); // compare args[0] & args[1]
118 int compare_real_fixed();
119 int compare_e_real_fixed();
120 int compare_datetime();
121 int compare_e_datetime();
122 int compare_time();
123 int compare_e_time();
124 int compare_json_str_basic(Item *j, Item *s);
125 int compare_json_str();
126 int compare_str_json();
127 int compare_e_json_str_basic(Item *j, Item *s);
128 int compare_e_json_str();
129 int compare_e_str_json();
130
131 Item** cache_converted_constant(THD *thd, Item **value, Item **cache,
132 const Type_handler *type);
is_owner_equal_func()133 inline bool is_owner_equal_func()
134 {
135 return (owner->type() == Item::FUNC_ITEM &&
136 ((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC);
137 }
compare_type_handler()138 const Type_handler *compare_type_handler() const { return m_compare_handler; }
compare_type()139 Item_result compare_type() const { return m_compare_handler->cmp_type(); }
compare_collation()140 CHARSET_INFO *compare_collation() const { return m_compare_collation; }
subcomparators()141 Arg_comparator *subcomparators() const { return comparators; }
cleanup()142 void cleanup()
143 {
144 delete [] comparators;
145 comparators= 0;
146 }
147 friend class Item_func;
148 friend class Item_bool_rowready_func2;
149 };
150
151
152 class SEL_ARG;
153 struct KEY_PART;
154
155 class Item_bool_func :public Item_int_func
156 {
157 protected:
158 /*
159 Build a SEL_TREE for a simple predicate
160 @param param PARAM from SQL_SELECT::test_quick_select
161 @param field field in the predicate
162 @param value constant in the predicate
163 @return Pointer to the tree built tree
164 */
get_func_mm_tree(RANGE_OPT_PARAM * param,Field * field,Item * value)165 virtual SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
166 Field *field, Item *value)
167 {
168 DBUG_ENTER("Item_bool_func::get_func_mm_tree");
169 DBUG_ASSERT(0);
170 DBUG_RETURN(0);
171 }
172 /*
173 Return the full select tree for "field_item" and "value":
174 - a single SEL_TREE if the field is not in a multiple equality, or
175 - a conjunction of all SEL_TREEs for all fields from
176 the same multiple equality with "field_item".
177 */
178 SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
179 Item_field *field_item, Item *value);
180 /**
181 Test if "item" and "value" are suitable for the range optimization
182 and get their full select tree.
183
184 "Suitable" means:
185 - "item" is a field or a field reference
186 - "value" is NULL (e.g. WHERE field IS NULL), or
187 "value" is an unexpensive item (e.g. WHERE field OP value)
188
189 @param item - the argument that is checked to be a field
190 @param value - the other argument
191 @returns - NULL if the arguments are not suitable for the range optimizer.
192 @returns - the full select tree if the arguments are suitable.
193 */
get_full_func_mm_tree_for_args(RANGE_OPT_PARAM * param,Item * item,Item * value)194 SEL_TREE *get_full_func_mm_tree_for_args(RANGE_OPT_PARAM *param,
195 Item *item, Item *value)
196 {
197 DBUG_ENTER("Item_bool_func::get_full_func_mm_tree_for_args");
198 Item *field= item->real_item();
199 if (field->type() == Item::FIELD_ITEM && !field->const_item() &&
200 (!value || !value->is_expensive()))
201 DBUG_RETURN(get_full_func_mm_tree(param, (Item_field *) field, value));
202 DBUG_RETURN(NULL);
203 }
204 SEL_TREE *get_mm_parts(RANGE_OPT_PARAM *param, Field *field,
205 Item_func::Functype type, Item *value);
206 SEL_TREE *get_ne_mm_tree(RANGE_OPT_PARAM *param,
207 Field *field, Item *lt_value, Item *gt_value);
208 virtual SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
209 KEY_PART *key_part,
210 Item_func::Functype type, Item *value);
211 public:
Item_bool_func(THD * thd)212 Item_bool_func(THD *thd): Item_int_func(thd) {}
Item_bool_func(THD * thd,Item * a)213 Item_bool_func(THD *thd, Item *a): Item_int_func(thd, a) {}
Item_bool_func(THD * thd,Item * a,Item * b)214 Item_bool_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
Item_bool_func(THD * thd,Item * a,Item * b,Item * c)215 Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
Item_bool_func(THD * thd,List<Item> & list)216 Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_bool_func(THD * thd,Item_bool_func * item)217 Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
type_handler()218 const Type_handler *type_handler() const { return &type_handler_long; }
is_bool_type()219 bool is_bool_type() { return true; }
compare_collation()220 virtual CHARSET_INFO *compare_collation() const { return NULL; }
fix_length_and_dec()221 bool fix_length_and_dec() { decimals=0; max_length=1; return FALSE; }
decimal_precision()222 uint decimal_precision() const { return 1; }
need_parentheses_in_default()223 bool need_parentheses_in_default() { return true; }
224 };
225
226
227 /**
228 Abstract Item class, to represent <code>X IS [NOT] (TRUE | FALSE)</code>
229 boolean predicates.
230 */
231
232 class Item_func_truth : public Item_bool_func
233 {
234 public:
235 virtual bool val_bool();
236 virtual longlong val_int();
237 virtual bool fix_length_and_dec();
238 virtual void print(String *str, enum_query_type query_type);
precedence()239 enum precedence precedence() const { return CMP_PRECEDENCE; }
240
241 protected:
Item_func_truth(THD * thd,Item * a,bool a_value,bool a_affirmative)242 Item_func_truth(THD *thd, Item *a, bool a_value, bool a_affirmative):
243 Item_bool_func(thd, a), value(a_value), affirmative(a_affirmative)
244 {}
245
~Item_func_truth()246 ~Item_func_truth()
247 {}
248 private:
249 /**
250 True for <code>X IS [NOT] TRUE</code>,
251 false for <code>X IS [NOT] FALSE</code> predicates.
252 */
253 const bool value;
254 /**
255 True for <code>X IS Y</code>, false for <code>X IS NOT Y</code> predicates.
256 */
257 const bool affirmative;
258 };
259
260
261 /**
262 This Item represents a <code>X IS TRUE</code> boolean predicate.
263 */
264
265 class Item_func_istrue : public Item_func_truth
266 {
267 public:
Item_func_istrue(THD * thd,Item * a)268 Item_func_istrue(THD *thd, Item *a): Item_func_truth(thd, a, true, true) {}
~Item_func_istrue()269 ~Item_func_istrue() {}
func_name()270 virtual const char* func_name() const { return "istrue"; }
get_copy(THD * thd)271 Item *get_copy(THD *thd)
272 { return get_item_copy<Item_func_istrue>(thd, this); }
273 };
274
275
276 /**
277 This Item represents a <code>X IS NOT TRUE</code> boolean predicate.
278 */
279
280 class Item_func_isnottrue : public Item_func_truth
281 {
282 public:
Item_func_isnottrue(THD * thd,Item * a)283 Item_func_isnottrue(THD *thd, Item *a):
284 Item_func_truth(thd, a, true, false) {}
~Item_func_isnottrue()285 ~Item_func_isnottrue() {}
func_name()286 virtual const char* func_name() const { return "isnottrue"; }
get_copy(THD * thd)287 Item *get_copy(THD *thd)
288 { return get_item_copy<Item_func_isnottrue>(thd, this); }
eval_not_null_tables(void *)289 bool eval_not_null_tables(void *) { not_null_tables_cache= 0; return false; }
290 };
291
292
293 /**
294 This Item represents a <code>X IS FALSE</code> boolean predicate.
295 */
296
297 class Item_func_isfalse : public Item_func_truth
298 {
299 public:
Item_func_isfalse(THD * thd,Item * a)300 Item_func_isfalse(THD *thd, Item *a): Item_func_truth(thd, a, false, true) {}
~Item_func_isfalse()301 ~Item_func_isfalse() {}
func_name()302 virtual const char* func_name() const { return "isfalse"; }
get_copy(THD * thd)303 Item *get_copy(THD *thd)
304 { return get_item_copy<Item_func_isfalse>(thd, this); }
305 };
306
307
308 /**
309 This Item represents a <code>X IS NOT FALSE</code> boolean predicate.
310 */
311
312 class Item_func_isnotfalse : public Item_func_truth
313 {
314 public:
Item_func_isnotfalse(THD * thd,Item * a)315 Item_func_isnotfalse(THD *thd, Item *a):
316 Item_func_truth(thd, a, false, false) {}
~Item_func_isnotfalse()317 ~Item_func_isnotfalse() {}
func_name()318 virtual const char* func_name() const { return "isnotfalse"; }
get_copy(THD * thd)319 Item *get_copy(THD *thd)
320 { return get_item_copy<Item_func_isnotfalse>(thd, this); }
eval_not_null_tables(void *)321 bool eval_not_null_tables(void *) { not_null_tables_cache= 0; return false; }
322 };
323
324
325 class Item_cache;
326 #define UNKNOWN (-1)
327
328
329 /*
330 Item_in_optimizer(left_expr, Item_in_subselect(...))
331
332 Item_in_optimizer is used to wrap an instance of Item_in_subselect. This
333 class does the following:
334 - Evaluate the left expression and store it in Item_cache_* object (to
335 avoid re-evaluating it many times during subquery execution)
336 - Shortcut the evaluation of "NULL IN (...)" to NULL in the cases where we
337 don't care if the result is NULL or FALSE.
338
339 NOTE
340 It is not quite clear why the above listed functionality should be
341 placed into a separate class called 'Item_in_optimizer'.
342 */
343
344 class Item_in_optimizer: public Item_bool_func
345 {
346 protected:
347 Item_cache *cache;
348 Item *expr_cache;
349 bool save_cache;
350 /*
351 Stores the value of "NULL IN (SELECT ...)" for uncorrelated subqueries:
352 UNKNOWN - "NULL in (SELECT ...)" has not yet been evaluated
353 FALSE - result is FALSE
354 TRUE - result is NULL
355 */
356 int result_for_null_param;
357 public:
Item_in_optimizer(THD * thd,Item * a,Item * b)358 Item_in_optimizer(THD *thd, Item *a, Item *b):
359 Item_bool_func(thd, a, b), cache(0), expr_cache(0),
360 save_cache(0), result_for_null_param(UNKNOWN)
361 { m_with_subquery= true; }
362 bool fix_fields(THD *, Item **);
363 bool fix_left(THD *thd);
not_null_tables()364 table_map not_null_tables() const { return 0; }
365 bool is_null();
366 longlong val_int();
367 void cleanup();
functype()368 enum Functype functype() const { return IN_OPTIMIZER_FUNC; }
func_name()369 const char *func_name() const { return "<in_optimizer>"; }
get_cache()370 Item_cache **get_cache() { return &cache; }
371 void keep_top_level_cache();
372 Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
373 virtual Item *expr_cache_insert_transformer(THD *thd, uchar *unused);
374 bool is_expensive_processor(void *arg);
375 bool is_expensive();
set_join_tab_idx(uint join_tab_idx_arg)376 void set_join_tab_idx(uint join_tab_idx_arg)
377 { args[1]->set_join_tab_idx(join_tab_idx_arg); }
378 virtual void get_cache_parameters(List<Item> ¶meters);
379 bool is_top_level_item();
380 bool eval_not_null_tables(void *opt_arg);
381 void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
382 bool invisible_mode();
reset_cache()383 void reset_cache() { cache= NULL; }
384 virtual void print(String *str, enum_query_type query_type);
385 void restore_first_argument();
get_wrapped_in_subselect_item()386 Item* get_wrapped_in_subselect_item()
387 { return args[1]; }
get_copy(THD * thd)388 Item *get_copy(THD *thd)
389 { return get_item_copy<Item_in_optimizer>(thd, this); }
390 };
391
392
393 /*
394 Functions and operators with two arguments that can use range optimizer.
395 */
396 class Item_bool_func2 :public Item_bool_func
397 { /* Bool with 2 string args */
398 protected:
399 void add_key_fields_optimize_op(JOIN *join, KEY_FIELD **key_fields,
400 uint *and_level, table_map usable_tables,
401 SARGABLE_PARAM **sargables, bool equal_func);
402 public:
Item_bool_func2(THD * thd,Item * a,Item * b)403 Item_bool_func2(THD *thd, Item *a, Item *b):
404 Item_bool_func(thd, a, b) { }
405
is_null()406 bool is_null() { return MY_TEST(args[0]->is_null() || args[1]->is_null()); }
407 COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
408 bool top_level);
409 bool count_sargable_conds(void *arg);
410 /*
411 Specifies which result type the function uses to compare its arguments.
412 This method is used in equal field propagation.
413 */
compare_type_handler()414 virtual const Type_handler *compare_type_handler() const
415 {
416 /*
417 Have STRING_RESULT by default, which means the function compares
418 val_str() results of the arguments. This is suitable for Item_func_like
419 and for Item_func_spatial_rel.
420 Note, Item_bool_rowready_func2 overrides this default behaviour.
421 */
422 return &type_handler_varchar;
423 }
get_mm_tree(RANGE_OPT_PARAM * param,Item ** cond_ptr)424 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
425 {
426 DBUG_ENTER("Item_bool_func2::get_mm_tree");
427 DBUG_ASSERT(arg_count == 2);
428 SEL_TREE *ftree= get_full_func_mm_tree_for_args(param, args[0], args[1]);
429 if (!ftree)
430 ftree= Item_func::get_mm_tree(param, cond_ptr);
431 DBUG_RETURN(ftree);
432 }
433 };
434
435
436 /**
437 A class for functions and operators that can use the range optimizer and
438 have a reverse function/operator that can also use the range optimizer,
439 so this condition:
440 WHERE value OP field
441 can be optimized as equivalent to:
442 WHERE field REV_OP value
443
444 This class covers:
445 - scalar comparison predicates: <, <=, =, <=>, >=, >
446 - MBR and precise spatial relation predicates (e.g. SP_TOUCHES(x,y))
447
448 For example:
449 WHERE 10 > field
450 can be optimized as:
451 WHERE field < 10
452 */
453 class Item_bool_func2_with_rev :public Item_bool_func2
454 {
455 protected:
get_func_mm_tree(RANGE_OPT_PARAM * param,Field * field,Item * value)456 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
457 Field *field, Item *value)
458 {
459 DBUG_ENTER("Item_bool_func2_with_rev::get_func_mm_tree");
460 Item_func::Functype func_type=
461 (value != arguments()[0]) ? functype() : rev_functype();
462 DBUG_RETURN(get_mm_parts(param, field, func_type, value));
463 }
464 public:
Item_bool_func2_with_rev(THD * thd,Item * a,Item * b)465 Item_bool_func2_with_rev(THD *thd, Item *a, Item *b):
466 Item_bool_func2(thd, a, b) { }
467 virtual enum Functype rev_functype() const= 0;
get_mm_tree(RANGE_OPT_PARAM * param,Item ** cond_ptr)468 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
469 {
470 DBUG_ENTER("Item_bool_func2_with_rev::get_mm_tree");
471 DBUG_ASSERT(arg_count == 2);
472 SEL_TREE *ftree;
473 /*
474 Even if get_full_func_mm_tree_for_args(param, args[0], args[1]) will not
475 return a range predicate it may still be possible to create one
476 by reversing the order of the operands. Note that this only
477 applies to predicates where both operands are fields. Example: A
478 query of the form
479
480 WHERE t1.a OP t2.b
481
482 In this case, args[0] == t1.a and args[1] == t2.b.
483 When creating range predicates for t2,
484 get_full_func_mm_tree_for_args(param, args[0], args[1])
485 will return NULL because 'field' belongs to t1 and only
486 predicates that applies to t2 are of interest. In this case a
487 call to get_full_func_mm_tree_for_args() with reversed operands
488 may succeed.
489 */
490 if (!(ftree= get_full_func_mm_tree_for_args(param, args[0], args[1])) &&
491 !(ftree= get_full_func_mm_tree_for_args(param, args[1], args[0])))
492 ftree= Item_func::get_mm_tree(param, cond_ptr);
493 DBUG_RETURN(ftree);
494 }
495 };
496
497
498 class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
499 {
500 protected:
501 Arg_comparator cmp;
check_arguments()502 bool check_arguments() const
503 {
504 return check_argument_types_like_args0();
505 }
506 public:
Item_bool_rowready_func2(THD * thd,Item * a,Item * b)507 Item_bool_rowready_func2(THD *thd, Item *a, Item *b):
508 Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1)
509 { }
510 Sql_mode_dependency value_depends_on_sql_mode() const;
print(String * str,enum_query_type query_type)511 void print(String *str, enum_query_type query_type)
512 {
513 Item_func::print_op(str, query_type);
514 }
precedence()515 enum precedence precedence() const { return CMP_PRECEDENCE; }
516 Item *neg_transformer(THD *thd);
517 virtual Item *negated_item(THD *thd);
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)518 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
519 {
520 Item_args::propagate_equal_fields(thd,
521 Context(ANY_SUBST,
522 cmp.compare_type_handler(),
523 compare_collation()),
524 cond);
525 return this;
526 }
527 bool fix_length_and_dec();
set_cmp_func()528 int set_cmp_func()
529 {
530 return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
531 }
compare_collation()532 CHARSET_INFO *compare_collation() const { return cmp.compare_collation(); }
compare_type_handler()533 const Type_handler *compare_type_handler() const
534 {
535 return cmp.compare_type_handler();
536 }
get_comparator()537 Arg_comparator *get_comparator() { return &cmp; }
cleanup()538 void cleanup()
539 {
540 Item_bool_func2::cleanup();
541 cmp.cleanup();
542 }
add_key_fields(JOIN * join,KEY_FIELD ** key_fields,uint * and_level,table_map usable_tables,SARGABLE_PARAM ** sargables)543 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
544 uint *and_level, table_map usable_tables,
545 SARGABLE_PARAM **sargables)
546 {
547 return add_key_fields_optimize_op(join, key_fields, and_level,
548 usable_tables, sargables, false);
549 }
build_clone(THD * thd)550 Item *build_clone(THD *thd)
551 {
552 Item_bool_rowready_func2 *clone=
553 (Item_bool_rowready_func2 *) Item_func::build_clone(thd);
554 if (clone)
555 {
556 clone->cmp.comparators= 0;
557 }
558 return clone;
559 }
560 };
561
562 /**
563 XOR inherits from Item_bool_func because it is not optimized yet.
564 Later, when XOR is optimized, it needs to inherit from
565 Item_cond instead. See WL#5800.
566 */
567 class Item_func_xor :public Item_bool_func
568 {
569 public:
Item_func_xor(THD * thd,Item * i1,Item * i2)570 Item_func_xor(THD *thd, Item *i1, Item *i2): Item_bool_func(thd, i1, i2) {}
functype()571 enum Functype functype() const { return XOR_FUNC; }
func_name()572 const char *func_name() const { return "xor"; }
precedence()573 enum precedence precedence() const { return XOR_PRECEDENCE; }
print(String * str,enum_query_type query_type)574 void print(String *str, enum_query_type query_type)
575 { Item_func::print_op(str, query_type); }
576 longlong val_int();
577 Item *neg_transformer(THD *thd);
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)578 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
579 {
580 Item_args::propagate_equal_fields(thd, Context_boolean(), cond);
581 return this;
582 }
get_copy(THD * thd)583 Item *get_copy(THD *thd)
584 { return get_item_copy<Item_func_xor>(thd, this); }
585 };
586
587 class Item_func_not :public Item_bool_func
588 {
589 bool abort_on_null;
590 public:
Item_func_not(THD * thd,Item * a)591 Item_func_not(THD *thd, Item *a):
592 Item_bool_func(thd, a), abort_on_null(FALSE) {}
top_level_item()593 virtual void top_level_item() { abort_on_null= 1; }
is_top_level_item()594 bool is_top_level_item() { return abort_on_null; }
595 longlong val_int();
functype()596 enum Functype functype() const { return NOT_FUNC; }
func_name()597 const char *func_name() const { return "not"; }
precedence()598 enum precedence precedence() const { return NEG_PRECEDENCE; }
599 Item *neg_transformer(THD *thd);
600 bool fix_fields(THD *, Item **);
601 virtual void print(String *str, enum_query_type query_type);
get_copy(THD * thd)602 Item *get_copy(THD *thd)
603 { return get_item_copy<Item_func_not>(thd, this); }
604 };
605
606 class Item_maxmin_subselect;
607
608 /*
609 trigcond<param>(arg) ::= param? arg : TRUE
610
611 The class Item_func_trig_cond is used for guarded predicates
612 which are employed only for internal purposes.
613 A guarded predicate is an object consisting of an a regular or
614 a guarded predicate P and a pointer to a boolean guard variable g.
615 A guarded predicate P/g is evaluated to true if the value of the
616 guard g is false, otherwise it is evaluated to the same value that
617 the predicate P: val(P/g)= g ? val(P):true.
618 Guarded predicates allow us to include predicates into a conjunction
619 conditionally. Currently they are utilized for pushed down predicates
620 in queries with outer join operations.
621
622 In the future, probably, it makes sense to extend this class to
623 the objects consisting of three elements: a predicate P, a pointer
624 to a variable g and a firing value s with following evaluation
625 rule: val(P/g,s)= g==s? val(P) : true. It will allow us to build only
626 one item for the objects of the form P/g1/g2...
627
628 Objects of this class are built only for query execution after
629 the execution plan has been already selected. That's why this
630 class needs only val_int out of generic methods.
631
632 Current uses of Item_func_trig_cond objects:
633 - To wrap selection conditions when executing outer joins
634 - To wrap condition that is pushed down into subquery
635 */
636
637 class Item_func_trig_cond: public Item_bool_func
638 {
639 bool *trig_var;
640 public:
Item_func_trig_cond(THD * thd,Item * a,bool * f)641 Item_func_trig_cond(THD *thd, Item *a, bool *f): Item_bool_func(thd, a)
642 { trig_var= f; }
val_int()643 longlong val_int() { return *trig_var ? args[0]->val_int() : 1; }
functype()644 enum Functype functype() const { return TRIG_COND_FUNC; };
func_name()645 const char *func_name() const { return "trigcond"; };
const_item()646 bool const_item() const { return FALSE; }
get_trig_var()647 bool *get_trig_var() { return trig_var; }
648 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
649 uint *and_level, table_map usable_tables,
650 SARGABLE_PARAM **sargables);
get_copy(THD * thd)651 Item *get_copy(THD *thd)
652 { return get_item_copy<Item_func_trig_cond>(thd, this); }
653 };
654
655 class Item_func_not_all :public Item_func_not
656 {
657 /* allow to check presence of values in max/min optimization */
658 Item_sum_min_max *test_sum_item;
659 Item_maxmin_subselect *test_sub_item;
660
661 public:
662 bool show;
663
Item_func_not_all(THD * thd,Item * a)664 Item_func_not_all(THD *thd, Item *a):
665 Item_func_not(thd, a), test_sum_item(0), test_sub_item(0), show(0)
666 {}
not_null_tables()667 table_map not_null_tables() const { return 0; }
668 longlong val_int();
functype()669 enum Functype functype() const { return NOT_ALL_FUNC; }
func_name()670 const char *func_name() const { return "<not>"; }
fix_fields(THD * thd,Item ** ref)671 bool fix_fields(THD *thd, Item **ref)
672 {return Item_func::fix_fields(thd, ref);}
673 virtual void print(String *str, enum_query_type query_type);
set_sum_test(Item_sum_min_max * item)674 void set_sum_test(Item_sum_min_max *item) { test_sum_item= item; test_sub_item= 0; };
set_sub_test(Item_maxmin_subselect * item)675 void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; test_sum_item= 0;};
676 bool empty_underlying_subquery();
677 Item *neg_transformer(THD *thd);
678 };
679
680
681 class Item_func_nop_all :public Item_func_not_all
682 {
683 public:
684
Item_func_nop_all(THD * thd,Item * a)685 Item_func_nop_all(THD *thd, Item *a): Item_func_not_all(thd, a) {}
686 longlong val_int();
func_name()687 const char *func_name() const { return "<nop>"; }
688 Item *neg_transformer(THD *thd);
get_copy(THD * thd)689 Item *get_copy(THD *thd)
690 { return get_item_copy<Item_func_nop_all>(thd, this); }
691 };
692
693
694 class Item_func_eq :public Item_bool_rowready_func2
695 {
696 bool abort_on_null;
697 public:
Item_func_eq(THD * thd,Item * a,Item * b)698 Item_func_eq(THD *thd, Item *a, Item *b):
699 Item_bool_rowready_func2(thd, a, b),
700 abort_on_null(false), in_equality_no(UINT_MAX)
701 {}
702 longlong val_int();
functype()703 enum Functype functype() const { return EQ_FUNC; }
rev_functype()704 enum Functype rev_functype() const { return EQ_FUNC; }
eq_cmp_result()705 cond_result eq_cmp_result() const { return COND_TRUE; }
func_name()706 const char *func_name() const { return "="; }
top_level_item()707 void top_level_item() { abort_on_null= true; }
708 Item *negated_item(THD *thd);
709 COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
710 bool link_item_fields,
711 COND_EQUAL **cond_equal_ref);
add_key_fields(JOIN * join,KEY_FIELD ** key_fields,uint * and_level,table_map usable_tables,SARGABLE_PARAM ** sargables)712 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
713 uint *and_level, table_map usable_tables,
714 SARGABLE_PARAM **sargables)
715 {
716 return add_key_fields_optimize_op(join, key_fields, and_level,
717 usable_tables, sargables, true);
718 }
719 bool check_equality(THD *thd, COND_EQUAL *cond, List<Item> *eq_list);
720 /*
721 - If this equality is created from the subquery's IN-equality:
722 number of the item it was created from, e.g. for
723 (a,b) IN (SELECT c,d ...) a=c will have in_equality_no=0,
724 and b=d will have in_equality_no=1.
725 - Otherwise, UINT_MAX
726 */
727 uint in_equality_no;
exists2in_reserved_items()728 virtual uint exists2in_reserved_items() { return 1; };
729 friend class Arg_comparator;
get_copy(THD * thd)730 Item *get_copy(THD *thd)
731 { return get_item_copy<Item_func_eq>(thd, this); }
732 };
733
734 class Item_func_equal :public Item_bool_rowready_func2
735 {
736 public:
Item_func_equal(THD * thd,Item * a,Item * b)737 Item_func_equal(THD *thd, Item *a, Item *b):
738 Item_bool_rowready_func2(thd, a, b) {}
739 longlong val_int();
740 bool fix_length_and_dec();
not_null_tables()741 table_map not_null_tables() const { return 0; }
functype()742 enum Functype functype() const { return EQUAL_FUNC; }
rev_functype()743 enum Functype rev_functype() const { return EQUAL_FUNC; }
eq_cmp_result()744 cond_result eq_cmp_result() const { return COND_TRUE; }
func_name()745 const char *func_name() const { return "<=>"; }
neg_transformer(THD * thd)746 Item *neg_transformer(THD *thd) { return 0; }
add_key_fields(JOIN * join,KEY_FIELD ** key_fields,uint * and_level,table_map usable_tables,SARGABLE_PARAM ** sargables)747 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
748 uint *and_level, table_map usable_tables,
749 SARGABLE_PARAM **sargables)
750 {
751 return add_key_fields_optimize_op(join, key_fields, and_level,
752 usable_tables, sargables, true);
753 }
get_copy(THD * thd)754 Item *get_copy(THD *thd)
755 { return get_item_copy<Item_func_equal>(thd, this); }
756 };
757
758
759 class Item_func_ge :public Item_bool_rowready_func2
760 {
761 public:
Item_func_ge(THD * thd,Item * a,Item * b)762 Item_func_ge(THD *thd, Item *a, Item *b):
763 Item_bool_rowready_func2(thd, a, b) {};
764 longlong val_int();
functype()765 enum Functype functype() const { return GE_FUNC; }
rev_functype()766 enum Functype rev_functype() const { return LE_FUNC; }
eq_cmp_result()767 cond_result eq_cmp_result() const { return COND_TRUE; }
func_name()768 const char *func_name() const { return ">="; }
769 Item *negated_item(THD *thd);
get_copy(THD * thd)770 Item *get_copy(THD *thd)
771 { return get_item_copy<Item_func_ge>(thd, this); }
772 };
773
774
775 class Item_func_gt :public Item_bool_rowready_func2
776 {
777 public:
Item_func_gt(THD * thd,Item * a,Item * b)778 Item_func_gt(THD *thd, Item *a, Item *b):
779 Item_bool_rowready_func2(thd, a, b) {};
780 longlong val_int();
functype()781 enum Functype functype() const { return GT_FUNC; }
rev_functype()782 enum Functype rev_functype() const { return LT_FUNC; }
eq_cmp_result()783 cond_result eq_cmp_result() const { return COND_FALSE; }
func_name()784 const char *func_name() const { return ">"; }
785 Item *negated_item(THD *thd);
get_copy(THD * thd)786 Item *get_copy(THD *thd)
787 { return get_item_copy<Item_func_gt>(thd, this); }
788 };
789
790
791 class Item_func_le :public Item_bool_rowready_func2
792 {
793 public:
Item_func_le(THD * thd,Item * a,Item * b)794 Item_func_le(THD *thd, Item *a, Item *b):
795 Item_bool_rowready_func2(thd, a, b) {};
796 longlong val_int();
functype()797 enum Functype functype() const { return LE_FUNC; }
rev_functype()798 enum Functype rev_functype() const { return GE_FUNC; }
eq_cmp_result()799 cond_result eq_cmp_result() const { return COND_TRUE; }
func_name()800 const char *func_name() const { return "<="; }
801 Item *negated_item(THD *thd);
get_copy(THD * thd)802 Item *get_copy(THD *thd)
803 { return get_item_copy<Item_func_le>(thd, this); }
804 };
805
806
807 class Item_func_lt :public Item_bool_rowready_func2
808 {
809 public:
Item_func_lt(THD * thd,Item * a,Item * b)810 Item_func_lt(THD *thd, Item *a, Item *b):
811 Item_bool_rowready_func2(thd, a, b) {}
812 longlong val_int();
functype()813 enum Functype functype() const { return LT_FUNC; }
rev_functype()814 enum Functype rev_functype() const { return GT_FUNC; }
eq_cmp_result()815 cond_result eq_cmp_result() const { return COND_FALSE; }
func_name()816 const char *func_name() const { return "<"; }
817 Item *negated_item(THD *thd);
get_copy(THD * thd)818 Item *get_copy(THD *thd)
819 { return get_item_copy<Item_func_lt>(thd, this); }
820 };
821
822
823 class Item_func_ne :public Item_bool_rowready_func2
824 {
825 protected:
get_func_mm_tree(RANGE_OPT_PARAM * param,Field * field,Item * value)826 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
827 Field *field, Item *value)
828 {
829 DBUG_ENTER("Item_func_ne::get_func_mm_tree");
830 DBUG_RETURN(get_ne_mm_tree(param, field, value, value));
831 }
832 public:
Item_func_ne(THD * thd,Item * a,Item * b)833 Item_func_ne(THD *thd, Item *a, Item *b):
834 Item_bool_rowready_func2(thd, a, b) {}
835 longlong val_int();
functype()836 enum Functype functype() const { return NE_FUNC; }
rev_functype()837 enum Functype rev_functype() const { return NE_FUNC; }
eq_cmp_result()838 cond_result eq_cmp_result() const { return COND_FALSE; }
func_name()839 const char *func_name() const { return "<>"; }
840 Item *negated_item(THD *thd);
841 void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
842 table_map usable_tables, SARGABLE_PARAM **sargables);
get_copy(THD * thd)843 Item *get_copy(THD *thd)
844 { return get_item_copy<Item_func_ne>(thd, this); }
845 };
846
847
848 /*
849 The class Item_func_opt_neg is defined to factor out the functionality
850 common for the classes Item_func_between and Item_func_in. The objects
851 of these classes can express predicates or there negations.
852 The alternative approach would be to create pairs Item_func_between,
853 Item_func_notbetween and Item_func_in, Item_func_notin.
854
855 */
856
857 class Item_func_opt_neg :public Item_bool_func
858 {
859 protected:
860 /*
861 The data type handler that will be used for comparison.
862 Data type handlers of all arguments are mixed to here.
863 */
864 Type_handler_hybrid_field_type m_comparator;
865 /*
866 The collation that will be used for comparison in case
867 when m_compare_type is STRING_RESULT.
868 */
869 DTCollation cmp_collation;
870 public:
871 bool negated; /* <=> the item represents NOT <func> */
872 bool pred_level; /* <=> [NOT] <func> is used on a predicate level */
873 public:
Item_func_opt_neg(THD * thd,Item * a,Item * b,Item * c)874 Item_func_opt_neg(THD *thd, Item *a, Item *b, Item *c):
875 Item_bool_func(thd, a, b, c), negated(0), pred_level(0) {}
Item_func_opt_neg(THD * thd,List<Item> & list)876 Item_func_opt_neg(THD *thd, List<Item> &list):
877 Item_bool_func(thd, list), negated(0), pred_level(0) {}
878 public:
top_level_item()879 inline void top_level_item() { pred_level= 1; }
is_top_level_item()880 bool is_top_level_item() const { return pred_level; }
neg_transformer(THD * thd)881 Item *neg_transformer(THD *thd)
882 {
883 negated= !negated;
884 return this;
885 }
886 bool eq(const Item *item, bool binary_cmp) const;
compare_collation()887 CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
888 Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) = 0;
889 };
890
891
892 class Item_func_between :public Item_func_opt_neg
893 {
894 protected:
895 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
896 Field *field, Item *value);
897 public:
898 String value0,value1,value2;
Item_func_between(THD * thd,Item * a,Item * b,Item * c)899 Item_func_between(THD *thd, Item *a, Item *b, Item *c):
900 Item_func_opt_neg(thd, a, b, c) { }
val_int()901 longlong val_int()
902 {
903 DBUG_ASSERT(fixed);
904 return m_comparator.type_handler()->Item_func_between_val_int(this);
905 }
functype()906 enum Functype functype() const { return BETWEEN; }
func_name()907 const char *func_name() const { return "between"; }
precedence()908 enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
909 bool fix_length_and_dec();
fix_length_and_dec_string(THD *)910 bool fix_length_and_dec_string(THD *)
911 {
912 return agg_arg_charsets_for_comparison(cmp_collation, args, 3);
913 }
914 bool fix_length_and_dec_temporal(THD *);
915 bool fix_length_and_dec_numeric(THD *);
916 virtual void print(String *str, enum_query_type query_type);
917 bool eval_not_null_tables(void *opt_arg);
918 void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
919 bool count_sargable_conds(void *arg);
920 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
921 uint *and_level, table_map usable_tables,
922 SARGABLE_PARAM **sargables);
923 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)924 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
925 {
926 Item_args::propagate_equal_fields(thd,
927 Context(ANY_SUBST,
928 m_comparator.type_handler(),
929 compare_collation()),
930 cond);
931 return this;
932 }
get_copy(THD * thd)933 Item *get_copy(THD *thd)
934 { return get_item_copy<Item_func_between>(thd, this); }
935
936 longlong val_int_cmp_string();
937 longlong val_int_cmp_temporal();
938 longlong val_int_cmp_int();
939 longlong val_int_cmp_real();
940 longlong val_int_cmp_decimal();
941 };
942
943
944 class Item_func_strcmp :public Item_long_func
945 {
check_arguments()946 bool check_arguments() const
947 { return check_argument_types_can_return_str(0, 2); }
948 String value1, value2;
949 DTCollation cmp_collation;
950 public:
Item_func_strcmp(THD * thd,Item * a,Item * b)951 Item_func_strcmp(THD *thd, Item *a, Item *b):
952 Item_long_func(thd, a, b) {}
953 longlong val_int();
decimal_precision()954 uint decimal_precision() const { return 1; }
func_name()955 const char *func_name() const { return "strcmp"; }
fix_length_and_dec()956 bool fix_length_and_dec()
957 {
958 if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
959 return TRUE;
960 fix_char_length(2);
961 return FALSE;
962 }
get_copy(THD * thd)963 Item *get_copy(THD *thd)
964 { return get_item_copy<Item_func_strcmp>(thd, this); }
965 };
966
967
968 struct interval_range
969 {
970 Item_result type;
971 double dbl;
972 my_decimal dec;
973 };
974
975 class Item_func_interval :public Item_long_func
976 {
977 Item_row *row;
978 bool use_decimal_comparison;
979 interval_range *intervals;
check_arguments()980 bool check_arguments() const
981 {
982 return check_argument_types_like_args0();
983 }
984 public:
Item_func_interval(THD * thd,Item_row * a)985 Item_func_interval(THD *thd, Item_row *a):
986 Item_long_func(thd, a), row(a), intervals(0)
987 { }
988 bool fix_fields(THD *, Item **);
989 longlong val_int();
990 bool fix_length_and_dec();
func_name()991 const char *func_name() const { return "interval"; }
decimal_precision()992 uint decimal_precision() const { return 2; }
print(String * str,enum_query_type query_type)993 void print(String *str, enum_query_type query_type)
994 {
995 str->append(func_name());
996 print_args(str, 0, query_type);
997 }
get_copy(THD * thd)998 Item *get_copy(THD *thd)
999 { return get_item_copy<Item_func_interval>(thd, this); }
1000 };
1001
1002
1003 class Item_func_coalesce :public Item_func_case_expression
1004 {
1005 public:
Item_func_coalesce(THD * thd,Item * a,Item * b)1006 Item_func_coalesce(THD *thd, Item *a, Item *b):
1007 Item_func_case_expression(thd, a, b) {}
Item_func_coalesce(THD * thd,List<Item> & list)1008 Item_func_coalesce(THD *thd, List<Item> &list):
1009 Item_func_case_expression(thd, list) {}
1010 double real_op();
1011 longlong int_op();
1012 String *str_op(String *);
1013 my_decimal *decimal_op(my_decimal *);
1014 bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
1015 bool time_op(MYSQL_TIME *ltime);
fix_length_and_dec()1016 bool fix_length_and_dec()
1017 {
1018 if (aggregate_for_result(func_name(), args, arg_count, true))
1019 return TRUE;
1020 fix_attributes(args, arg_count);
1021 return FALSE;
1022 }
func_name()1023 const char *func_name() const { return "coalesce"; }
not_null_tables()1024 table_map not_null_tables() const { return 0; }
get_copy(THD * thd)1025 Item *get_copy(THD *thd)
1026 { return get_item_copy<Item_func_coalesce>(thd, this); }
1027 };
1028
1029
1030 /*
1031 Case abbreviations that aggregate its result field type by two arguments:
1032 IFNULL(arg1, arg2)
1033 IF(switch, arg1, arg2)
1034 NVL2(switch, arg1, arg2)
1035 */
1036 class Item_func_case_abbreviation2 :public Item_func_case_expression
1037 {
1038 protected:
fix_length_and_dec2(Item ** items)1039 bool fix_length_and_dec2(Item **items)
1040 {
1041 if (aggregate_for_result(func_name(), items, 2, true))
1042 return TRUE;
1043 fix_attributes(items, 2);
1044 return FALSE;
1045 }
1046
cache_type_info(const Item * source,bool maybe_null_arg)1047 void cache_type_info(const Item *source, bool maybe_null_arg)
1048 {
1049 Type_std_attributes::set(source);
1050 set_handler(source->type_handler());
1051 maybe_null= maybe_null_arg;
1052 }
1053
fix_length_and_dec2_eliminate_null(Item ** items)1054 bool fix_length_and_dec2_eliminate_null(Item **items)
1055 {
1056 // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
1057 if (items[0]->type() == NULL_ITEM)
1058 {
1059 cache_type_info(items[1], true);
1060 // If both arguments are NULL, make resulting type BINARY(0).
1061 if (items[1]->type() == NULL_ITEM)
1062 set_handler(&type_handler_string);
1063 }
1064 else if (items[1]->type() == NULL_ITEM)
1065 {
1066 cache_type_info(items[0], true);
1067 }
1068 else
1069 {
1070 if (fix_length_and_dec2(items))
1071 return TRUE;
1072 }
1073 return FALSE;
1074 }
1075
1076 public:
Item_func_case_abbreviation2(THD * thd,Item * a,Item * b)1077 Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
1078 Item_func_case_expression(thd, a, b) { }
Item_func_case_abbreviation2(THD * thd,Item * a,Item * b,Item * c)1079 Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c):
1080 Item_func_case_expression(thd, a, b, c) { }
1081 };
1082
1083
1084 class Item_func_ifnull :public Item_func_case_abbreviation2
1085 {
1086 public:
Item_func_ifnull(THD * thd,Item * a,Item * b)1087 Item_func_ifnull(THD *thd, Item *a, Item *b):
1088 Item_func_case_abbreviation2(thd, a, b) {}
1089 double real_op();
1090 longlong int_op();
1091 String *str_op(String *str);
1092 my_decimal *decimal_op(my_decimal *);
1093 bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
1094 bool time_op(MYSQL_TIME *ltime);
fix_length_and_dec()1095 bool fix_length_and_dec()
1096 {
1097 if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
1098 return TRUE;
1099 maybe_null= args[1]->maybe_null;
1100 return FALSE;
1101 }
func_name()1102 const char *func_name() const { return "ifnull"; }
1103
not_null_tables()1104 table_map not_null_tables() const { return 0; }
get_copy(THD * thd)1105 Item *get_copy(THD *thd)
1106 { return get_item_copy<Item_func_ifnull>(thd, this); }
1107 };
1108
1109
1110 /**
1111 Case abbreviations that have a switch argument and
1112 two return arguments to choose from. Returns the value
1113 of either of the two return arguments depending on the switch argument value.
1114
1115 IF(switch, arg1, arg2)
1116 NVL(switch, arg1, arg2)
1117 */
1118 class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
1119 {
1120 protected:
1121 virtual Item *find_item() const= 0;
1122
1123 public:
Item_func_case_abbreviation2_switch(THD * thd,Item * a,Item * b,Item * c)1124 Item_func_case_abbreviation2_switch(THD *thd, Item *a, Item *b, Item *c)
1125 :Item_func_case_abbreviation2(thd, a, b, c)
1126 { }
1127
date_op(MYSQL_TIME * ltime,ulonglong fuzzydate)1128 bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
1129 {
1130 Datetime dt(current_thd, find_item(), fuzzydate);
1131 return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
1132 }
time_op(MYSQL_TIME * ltime)1133 bool time_op(MYSQL_TIME *ltime)
1134 {
1135 return (null_value= Time(find_item()).copy_to_mysql_time(ltime));
1136 }
int_op()1137 longlong int_op()
1138 {
1139 return val_int_from_item(find_item());
1140 }
real_op()1141 double real_op()
1142 {
1143 return val_real_from_item(find_item());
1144 }
decimal_op(my_decimal * decimal_value)1145 my_decimal *decimal_op(my_decimal *decimal_value)
1146 {
1147 return val_decimal_from_item(find_item(), decimal_value);
1148 }
str_op(String * str)1149 String *str_op(String *str)
1150 {
1151 return val_str_from_item(find_item(), str);
1152 }
1153 };
1154
1155
1156 class Item_func_if :public Item_func_case_abbreviation2_switch
1157 {
1158 protected:
find_item()1159 Item *find_item() const { return args[0]->val_bool() ? args[1] : args[2]; }
1160
1161 public:
Item_func_if(THD * thd,Item * a,Item * b,Item * c)1162 Item_func_if(THD *thd, Item *a, Item *b, Item *c):
1163 Item_func_case_abbreviation2_switch(thd, a, b, c)
1164 {}
1165 bool fix_fields(THD *, Item **);
fix_length_and_dec()1166 bool fix_length_and_dec()
1167 {
1168 return fix_length_and_dec2_eliminate_null(args + 1);
1169 }
func_name()1170 const char *func_name() const { return "if"; }
1171 bool eval_not_null_tables(void *opt_arg);
1172 void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
get_copy(THD * thd)1173 Item *get_copy(THD *thd)
1174 { return get_item_copy<Item_func_if>(thd, this); }
1175 private:
1176 void cache_type_info(Item *source);
1177 };
1178
1179
1180 class Item_func_nvl2 :public Item_func_case_abbreviation2_switch
1181 {
1182 protected:
find_item()1183 Item *find_item() const { return args[0]->is_null() ? args[2] : args[1]; }
1184
1185 public:
Item_func_nvl2(THD * thd,Item * a,Item * b,Item * c)1186 Item_func_nvl2(THD *thd, Item *a, Item *b, Item *c):
1187 Item_func_case_abbreviation2_switch(thd, a, b, c)
1188 {}
func_name()1189 const char *func_name() const { return "nvl2"; }
fix_length_and_dec()1190 bool fix_length_and_dec()
1191 {
1192 return fix_length_and_dec2_eliminate_null(args + 1);
1193 }
get_copy(THD * thd)1194 Item *get_copy(THD *thd)
1195 { return get_item_copy<Item_func_nvl2>(thd, this); }
1196 };
1197
1198
1199 class Item_func_nullif :public Item_func_case_expression
1200 {
1201 Arg_comparator cmp;
1202 /*
1203 NULLIF(a,b) is a short for:
1204 CASE WHEN a=b THEN NULL ELSE a END
1205
1206 The left "a" is for comparison purposes.
1207 The right "a" is for return value purposes.
1208 These are two different "a" and they can be replaced to different items.
1209
1210 The left "a" is in a comparison and can be replaced by:
1211 - Item_func::convert_const_compared_to_int_field()
1212 - agg_item_set_converter() in set_cmp_func()
1213 - cache_converted_constant() in set_cmp_func()
1214
1215 Both "a"s are subject to equal fields propagation and can be replaced by:
1216 - Item_field::propagate_equal_fields(ANY_SUBST) for the left "a"
1217 - Item_field::propagate_equal_fields(IDENTITY_SUBST) for the right "a"
1218 */
1219 Item_cache *m_cache;
1220 int compare();
reset_first_arg_if_needed()1221 void reset_first_arg_if_needed()
1222 {
1223 if (arg_count == 3 && args[0] != args[2])
1224 args[0]= args[2];
1225 }
1226 Item *m_arg0;
1227 public:
1228 /*
1229 Here we pass three arguments to the parent constructor, as NULLIF
1230 is a three-argument function, it needs two copies of the first argument
1231 (see above). But fix_fields() will be confused if we try to prepare the
1232 same Item twice (if args[0]==args[2]), so we hide the third argument
1233 (decrementing arg_count) and copy args[2]=args[0] again after fix_fields().
1234 See also Item_func_nullif::fix_length_and_dec().
1235 */
Item_func_nullif(THD * thd,Item * a,Item * b)1236 Item_func_nullif(THD *thd, Item *a, Item *b):
1237 Item_func_case_expression(thd, a, b, a),
1238 m_cache(NULL),
1239 m_arg0(NULL)
1240 { arg_count--; }
cleanup()1241 void cleanup()
1242 {
1243 Item_func_hybrid_field_type::cleanup();
1244 arg_count= 2; // See the comment to the constructor
1245 }
1246 bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
1247 bool time_op(MYSQL_TIME *ltime);
1248 double real_op();
1249 longlong int_op();
1250 String *str_op(String *str);
1251 my_decimal *decimal_op(my_decimal *);
1252 bool fix_length_and_dec();
1253 bool walk(Item_processor processor, bool walk_subquery, void *arg);
func_name()1254 const char *func_name() const { return "nullif"; }
1255 void print(String *str, enum_query_type query_type);
1256 void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
1257 List<Item> &fields, uint flags);
1258 void update_used_tables();
not_null_tables()1259 table_map not_null_tables() const { return 0; }
1260 bool is_null();
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)1261 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
1262 {
1263 Context cmpctx(ANY_SUBST, cmp.compare_type_handler(),
1264 cmp.compare_collation());
1265 const Item *old0= args[0];
1266 args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
1267 cond, &args[0]);
1268 args[1]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
1269 cond, &args[1]);
1270 /*
1271 MDEV-9712 Performance degradation of nested NULLIF
1272 ANY_SUBST is more relaxed than IDENTITY_SUBST.
1273 If ANY_SUBST did not change args[0],
1274 then we can skip propagation for args[2].
1275 */
1276 if (old0 != args[0])
1277 args[2]->propagate_equal_fields_and_change_item_tree(thd,
1278 Context_identity(),
1279 cond, &args[2]);
1280 return this;
1281 }
get_copy(THD * thd)1282 Item *get_copy(THD *thd)
1283 { return get_item_copy<Item_func_nullif>(thd, this); }
derived_field_transformer_for_having(THD * thd,uchar * arg)1284 Item *derived_field_transformer_for_having(THD *thd, uchar *arg)
1285 { reset_first_arg_if_needed(); return this; }
derived_field_transformer_for_where(THD * thd,uchar * arg)1286 Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
1287 { reset_first_arg_if_needed(); return this; }
derived_grouping_field_transformer_for_where(THD * thd,uchar * arg)1288 Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg)
1289 { reset_first_arg_if_needed(); return this; }
1290 };
1291
1292
1293 /* Functions to handle the optimized IN */
1294
1295
1296 /* A vector of values of some type */
1297
1298 class in_vector :public Sql_alloc
1299 {
1300 public:
1301 char *base;
1302 uint size;
1303 qsort2_cmp compare;
1304 CHARSET_INFO *collation;
1305 uint count;
1306 uint used_count;
in_vector()1307 in_vector() {}
in_vector(THD * thd,uint elements,uint element_length,qsort2_cmp cmp_func,CHARSET_INFO * cmp_coll)1308 in_vector(THD *thd, uint elements, uint element_length, qsort2_cmp cmp_func,
1309 CHARSET_INFO *cmp_coll)
1310 :base((char*) thd_calloc(thd, elements * element_length)),
1311 size(element_length), compare(cmp_func), collation(cmp_coll),
1312 count(elements), used_count(elements) {}
~in_vector()1313 virtual ~in_vector() {}
1314 virtual void set(uint pos,Item *item)=0;
1315 virtual uchar *get_value(Item *item)=0;
sort()1316 void sort()
1317 {
1318 my_qsort2(base,used_count,size,compare,(void*)collation);
1319 }
1320 bool find(Item *item);
1321
1322 /*
1323 Create an instance of Item_{type} (e.g. Item_decimal) constant object
1324 which type allows it to hold an element of this vector without any
1325 conversions.
1326 The purpose of this function is to be able to get elements of this
1327 vector in form of Item_xxx constants without creating Item_xxx object
1328 for every array element you get (i.e. this implements "FlyWeight" pattern)
1329 */
create_item(THD * thd)1330 virtual Item* create_item(THD *thd) { return NULL; }
1331
1332 /*
1333 Store the value at position #pos into provided item object
1334 SYNOPSIS
1335 value_to_item()
1336 pos Index of value to store
1337 item Constant item to store value into. The item must be of the same
1338 type that create_item() returns.
1339 */
value_to_item(uint pos,Item * item)1340 virtual void value_to_item(uint pos, Item *item) { }
1341
1342 /* Compare values number pos1 and pos2 for equality */
compare_elems(uint pos1,uint pos2)1343 bool compare_elems(uint pos1, uint pos2)
1344 {
1345 return MY_TEST(compare(collation, base + pos1 * size, base + pos2 * size));
1346 }
1347 virtual const Type_handler *type_handler() const= 0;
1348 };
1349
1350 class in_string :public in_vector
1351 {
1352 char buff[STRING_BUFFER_USUAL_SIZE];
1353 String tmp;
1354 class Item_string_for_in_vector: public Item_string
1355 {
1356 public:
Item_string_for_in_vector(THD * thd,CHARSET_INFO * cs)1357 Item_string_for_in_vector(THD *thd, CHARSET_INFO *cs):
1358 Item_string(thd, cs)
1359 { }
set_value(const String * str)1360 void set_value(const String *str)
1361 {
1362 str_value= *str;
1363 collation.set(str->charset());
1364 }
1365 };
1366 public:
1367 in_string(THD *thd, uint elements, qsort2_cmp cmp_func, CHARSET_INFO *cs);
1368 ~in_string();
1369 void set(uint pos,Item *item);
1370 uchar *get_value(Item *item);
1371 Item* create_item(THD *thd);
value_to_item(uint pos,Item * item)1372 void value_to_item(uint pos, Item *item)
1373 {
1374 String *str=((String*) base)+pos;
1375 Item_string_for_in_vector *to= (Item_string_for_in_vector*) item;
1376 to->set_value(str);
1377 }
type_handler()1378 const Type_handler *type_handler() const { return &type_handler_varchar; }
1379 };
1380
1381 class in_longlong :public in_vector
1382 {
1383 protected:
1384 /*
1385 Here we declare a temporary variable (tmp) of the same type as the
1386 elements of this vector. tmp is used in finding if a given value is in
1387 the list.
1388 */
1389 struct packed_longlong
1390 {
1391 longlong val;
1392 longlong unsigned_flag; // Use longlong, not bool, to preserve alignment
1393 } tmp;
1394 public:
1395 in_longlong(THD *thd, uint elements);
1396 void set(uint pos,Item *item);
1397 uchar *get_value(Item *item);
1398 Item* create_item(THD *thd);
value_to_item(uint pos,Item * item)1399 void value_to_item(uint pos, Item *item)
1400 {
1401 ((Item_int*) item)->value= ((packed_longlong*) base)[pos].val;
1402 ((Item_int*) item)->unsigned_flag= (bool)
1403 ((packed_longlong*) base)[pos].unsigned_flag;
1404 }
type_handler()1405 const Type_handler *type_handler() const { return &type_handler_longlong; }
1406
1407 friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
1408 };
1409
1410
1411 /*
1412 Class to represent a vector of constant DATE/DATETIME values.
1413 */
1414 class in_temporal :public in_longlong
1415 {
1416 protected:
1417 uchar *get_value_internal(Item *item, enum_field_types f_type);
1418 public:
1419 /* Cache for the left item. */
1420
in_temporal(THD * thd,uint elements)1421 in_temporal(THD *thd, uint elements)
1422 :in_longlong(thd, elements) {};
1423 Item *create_item(THD *thd);
value_to_item(uint pos,Item * item)1424 void value_to_item(uint pos, Item *item)
1425 {
1426 packed_longlong *val= reinterpret_cast<packed_longlong*>(base)+pos;
1427 Item_datetime *dt= static_cast<Item_datetime*>(item);
1428 dt->set(val->val, type_handler()->mysql_timestamp_type());
1429 }
get_value(Item * item)1430 uchar *get_value(Item *item)
1431 { return get_value_internal(item, type_handler()->field_type()); }
1432 friend int cmp_longlong(void *cmp_arg, packed_longlong *a,packed_longlong *b);
1433 };
1434
1435
1436 class in_datetime :public in_temporal
1437 {
1438 public:
in_datetime(THD * thd,uint elements)1439 in_datetime(THD *thd, uint elements)
1440 :in_temporal(thd, elements)
1441 {}
1442 void set(uint pos,Item *item);
type_handler()1443 const Type_handler *type_handler() const { return &type_handler_datetime2; }
1444 };
1445
1446
1447 class in_time :public in_temporal
1448 {
1449 public:
in_time(THD * thd,uint elements)1450 in_time(THD *thd, uint elements)
1451 :in_temporal(thd, elements)
1452 {}
1453 void set(uint pos,Item *item);
type_handler()1454 const Type_handler *type_handler() const { return &type_handler_time2; }
1455 };
1456
1457
1458 class in_double :public in_vector
1459 {
1460 double tmp;
1461 public:
1462 in_double(THD *thd, uint elements);
1463 void set(uint pos,Item *item);
1464 uchar *get_value(Item *item);
1465 Item *create_item(THD *thd);
value_to_item(uint pos,Item * item)1466 void value_to_item(uint pos, Item *item)
1467 {
1468 ((Item_float*)item)->value= ((double*) base)[pos];
1469 }
type_handler()1470 const Type_handler *type_handler() const { return &type_handler_double; }
1471 };
1472
1473
1474 class in_decimal :public in_vector
1475 {
1476 my_decimal val;
1477 public:
1478 in_decimal(THD *thd, uint elements);
1479 void set(uint pos, Item *item);
1480 uchar *get_value(Item *item);
1481 Item *create_item(THD *thd);
value_to_item(uint pos,Item * item)1482 void value_to_item(uint pos, Item *item)
1483 {
1484 my_decimal *dec= ((my_decimal *)base) + pos;
1485 Item_decimal *item_dec= (Item_decimal*)item;
1486 item_dec->set_decimal_value(dec);
1487 }
type_handler()1488 const Type_handler *type_handler() const { return &type_handler_newdecimal; }
1489 };
1490
1491
1492 /*
1493 ** Classes for easy comparing of non const items
1494 */
1495
1496 class cmp_item :public Sql_alloc
1497 {
1498 public:
1499 CHARSET_INFO *cmp_charset;
cmp_item()1500 cmp_item() { cmp_charset= &my_charset_bin; }
~cmp_item()1501 virtual ~cmp_item() {}
1502 virtual void store_value(Item *item)= 0;
1503 /**
1504 @returns result (TRUE, FALSE or UNKNOWN) of
1505 "stored argument's value <> item's value"
1506 */
1507 virtual int cmp(Item *item)= 0;
1508 virtual int cmp_not_null(const Value *value)= 0;
1509 // for optimized IN with row
1510 virtual int compare(cmp_item *item)= 0;
1511 virtual cmp_item *make_same()= 0;
store_value_by_template(THD * thd,cmp_item * tmpl,Item * item)1512 virtual void store_value_by_template(THD *thd, cmp_item *tmpl, Item *item)
1513 {
1514 store_value(item);
1515 }
1516 };
1517
1518 /// cmp_item which stores a scalar (i.e. non-ROW).
1519 class cmp_item_scalar : public cmp_item
1520 {
1521 protected:
1522 bool m_null_value; ///< If stored value is NULL
1523 };
1524
1525 class cmp_item_string : public cmp_item_scalar
1526 {
1527 protected:
1528 String *value_res;
1529 public:
cmp_item_string()1530 cmp_item_string () {}
cmp_item_string(CHARSET_INFO * cs)1531 cmp_item_string (CHARSET_INFO *cs) { cmp_charset= cs; }
set_charset(CHARSET_INFO * cs)1532 void set_charset(CHARSET_INFO *cs) { cmp_charset= cs; }
1533 friend class cmp_item_sort_string;
1534 friend class cmp_item_sort_string_in_static;
1535 };
1536
1537 class cmp_item_sort_string :public cmp_item_string
1538 {
1539 protected:
1540 char value_buff[STRING_BUFFER_USUAL_SIZE];
1541 String value;
1542 public:
cmp_item_sort_string()1543 cmp_item_sort_string():
1544 cmp_item_string() {}
cmp_item_sort_string(CHARSET_INFO * cs)1545 cmp_item_sort_string(CHARSET_INFO *cs):
1546 cmp_item_string(cs),
1547 value(value_buff, sizeof(value_buff), cs) {}
store_value(Item * item)1548 void store_value(Item *item)
1549 {
1550 value_res= item->val_str(&value);
1551 m_null_value= item->null_value;
1552 // Make sure to cache the result String inside "value"
1553 if (value_res && value_res != &value)
1554 {
1555 if (value.copy(*value_res))
1556 value.set("", 0, item->collation.collation);
1557 value_res= &value;
1558 }
1559 }
cmp_not_null(const Value * val)1560 int cmp_not_null(const Value *val)
1561 {
1562 DBUG_ASSERT(!val->is_null());
1563 DBUG_ASSERT(val->is_string());
1564 return sortcmp(value_res, &val->m_string, cmp_charset) != 0;
1565 }
cmp(Item * arg)1566 int cmp(Item *arg)
1567 {
1568 char buff[STRING_BUFFER_USUAL_SIZE];
1569 String tmp(buff, sizeof(buff), cmp_charset), *res= arg->val_str(&tmp);
1570 if (m_null_value || arg->null_value)
1571 return UNKNOWN;
1572 if (value_res && res)
1573 return sortcmp(value_res, res, cmp_charset) != 0;
1574 else if (!value_res && !res)
1575 return FALSE;
1576 else
1577 return TRUE;
1578 }
compare(cmp_item * ci)1579 int compare(cmp_item *ci)
1580 {
1581 cmp_item_string *l_cmp= (cmp_item_string *) ci;
1582 return sortcmp(value_res, l_cmp->value_res, cmp_charset);
1583 }
1584 cmp_item *make_same();
set_charset(CHARSET_INFO * cs)1585 void set_charset(CHARSET_INFO *cs)
1586 {
1587 cmp_charset= cs;
1588 value.set_quick(value_buff, sizeof(value_buff), cs);
1589 }
1590 };
1591
1592 class cmp_item_int : public cmp_item_scalar
1593 {
1594 longlong value;
1595 public:
cmp_item_int()1596 cmp_item_int() {} /* Remove gcc warning */
store_value(Item * item)1597 void store_value(Item *item)
1598 {
1599 value= item->val_int();
1600 m_null_value= item->null_value;
1601 }
cmp_not_null(const Value * val)1602 int cmp_not_null(const Value *val)
1603 {
1604 DBUG_ASSERT(!val->is_null());
1605 DBUG_ASSERT(val->is_longlong());
1606 return value != val->value.m_longlong;
1607 }
cmp(Item * arg)1608 int cmp(Item *arg)
1609 {
1610 const bool rc= value != arg->val_int();
1611 return (m_null_value || arg->null_value) ? UNKNOWN : rc;
1612 }
compare(cmp_item * ci)1613 int compare(cmp_item *ci)
1614 {
1615 cmp_item_int *l_cmp= (cmp_item_int *)ci;
1616 return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1);
1617 }
1618 cmp_item *make_same();
1619 };
1620
1621 /*
1622 Compare items in the DATETIME context.
1623 */
1624 class cmp_item_temporal: public cmp_item_scalar
1625 {
1626 protected:
1627 longlong value;
1628 void store_value_internal(Item *item, enum_field_types type);
1629 public:
cmp_item_temporal()1630 cmp_item_temporal() {}
1631 int compare(cmp_item *ci);
1632 };
1633
1634
1635 class cmp_item_datetime: public cmp_item_temporal
1636 {
1637 public:
cmp_item_datetime()1638 cmp_item_datetime()
1639 :cmp_item_temporal()
1640 { }
store_value(Item * item)1641 void store_value(Item *item)
1642 {
1643 store_value_internal(item, MYSQL_TYPE_DATETIME);
1644 }
1645 int cmp_not_null(const Value *val);
1646 int cmp(Item *arg);
1647 cmp_item *make_same();
1648 };
1649
1650
1651 class cmp_item_time: public cmp_item_temporal
1652 {
1653 public:
cmp_item_time()1654 cmp_item_time()
1655 :cmp_item_temporal()
1656 { }
store_value(Item * item)1657 void store_value(Item *item)
1658 {
1659 store_value_internal(item, MYSQL_TYPE_TIME);
1660 }
1661 int cmp_not_null(const Value *val);
1662 int cmp(Item *arg);
1663 cmp_item *make_same();
1664 };
1665
1666 class cmp_item_real : public cmp_item_scalar
1667 {
1668 double value;
1669 public:
cmp_item_real()1670 cmp_item_real() {} /* Remove gcc warning */
store_value(Item * item)1671 void store_value(Item *item)
1672 {
1673 value= item->val_real();
1674 m_null_value= item->null_value;
1675 }
cmp_not_null(const Value * val)1676 int cmp_not_null(const Value *val)
1677 {
1678 DBUG_ASSERT(!val->is_null());
1679 DBUG_ASSERT(val->is_double());
1680 return value != val->value.m_double;
1681 }
cmp(Item * arg)1682 int cmp(Item *arg)
1683 {
1684 const bool rc= value != arg->val_real();
1685 return (m_null_value || arg->null_value) ? UNKNOWN : rc;
1686 }
compare(cmp_item * ci)1687 int compare(cmp_item *ci)
1688 {
1689 cmp_item_real *l_cmp= (cmp_item_real *) ci;
1690 return (value < l_cmp->value)? -1 : ((value == l_cmp->value) ? 0 : 1);
1691 }
1692 cmp_item *make_same();
1693 };
1694
1695
1696 class cmp_item_decimal : public cmp_item_scalar
1697 {
1698 my_decimal value;
1699 public:
cmp_item_decimal()1700 cmp_item_decimal() {} /* Remove gcc warning */
1701 void store_value(Item *item);
1702 int cmp(Item *arg);
1703 int cmp_not_null(const Value *val);
1704 int compare(cmp_item *c);
1705 cmp_item *make_same();
1706 };
1707
1708
1709 /*
1710 cmp_item for optimized IN with row (right part string, which never
1711 be changed)
1712 */
1713
1714 class cmp_item_sort_string_in_static :public cmp_item_string
1715 {
1716 protected:
1717 String value;
1718 public:
cmp_item_sort_string_in_static(CHARSET_INFO * cs)1719 cmp_item_sort_string_in_static(CHARSET_INFO *cs):
1720 cmp_item_string(cs) {}
store_value(Item * item)1721 void store_value(Item *item)
1722 {
1723 value_res= item->val_str(&value);
1724 m_null_value= item->null_value;
1725 }
cmp_not_null(const Value * val)1726 int cmp_not_null(const Value *val)
1727 {
1728 DBUG_ASSERT(false);
1729 return TRUE;
1730 }
cmp(Item * item)1731 int cmp(Item *item)
1732 {
1733 // Should never be called
1734 DBUG_ASSERT(false);
1735 return TRUE;
1736 }
compare(cmp_item * ci)1737 int compare(cmp_item *ci)
1738 {
1739 cmp_item_string *l_cmp= (cmp_item_string *) ci;
1740 return sortcmp(value_res, l_cmp->value_res, cmp_charset);
1741 }
make_same()1742 cmp_item *make_same()
1743 {
1744 return new cmp_item_sort_string_in_static(cmp_charset);
1745 }
1746 };
1747
1748
1749 /**
1750 A helper class to handle situations when some item "pred" (the predicant)
1751 is consequently compared to a list of other items value0..valueN (the values).
1752 Currently used to handle:
1753 - <in predicate>
1754 pred IN (value0, value1, value2)
1755 - <simple case>
1756 CASE pred WHEN value0 .. WHEN value1 .. WHEN value2 .. END
1757
1758 Every pair {pred,valueN} can be compared by its own Type_handler.
1759 Some pairs can use the same Type_handler.
1760 In cases when all pairs use exactly the same Type_handler,
1761 we say "all types are compatible".
1762
1763 For example, for an expression
1764 1 IN (1, 1e0, 1.0, 2)
1765 - pred is 1
1766 - value0 is 1
1767 - value1 is 1e0
1768 - value2 is 1.1
1769 - value3 is 2
1770
1771 Pairs (pred,valueN) are compared as follows:
1772 N expr1 Type
1773 - ----- ----
1774 0 1 INT
1775 1 1e0 DOUBLE
1776 2 1.0 DECIMAL
1777 3 2 INT
1778
1779 Types are not compatible in this example.
1780
1781 During add_value() calls, each pair {pred,valueN} is analysed:
1782 - If valueN is an explicit NULL, it can be ignored in the caller asks to do so
1783 - If valueN is not an explicit NULL (or if the caller didn't ask to skip
1784 NULLs), then the value add an element in the array m_comparators[].
1785
1786 Every element m_comparators[] stores the following information:
1787 1. m_arg_index - the position of the value expression in the original
1788 argument array, e.g. in Item_func_in::args[] or Item_func_case::args[].
1789
1790 2. m_handler - the pointer to the data type handler that the owner
1791 will use to compare the pair {args[m_predicate_index],args[m_arg_index]}.
1792
1793 3. m_handler_index - the index of an m_comparators[] element corresponding
1794 to the leftmost pair that uses exactly the same Type_handler for
1795 comparison. m_handler_index helps to maintain unique data type handlers.
1796 - m_comparators[i].m_handler_index==i means that this is the
1797 leftmost pair that uses the Type_handler m_handler for comparision.
1798 - If m_comparators[i].m_handlex_index!=i, it means that some earlier
1799 element m_comparators[j<i] is already using this Type_handler
1800 pointed by m_handler.
1801
1802 4. m_cmp_item - the pointer to a cmp_item instance to handle comparison
1803 for this pair. Only unique type handlers have m_cmp_item!=NULL.
1804 Non-unique type handlers share the same cmp_item instance.
1805 For all m_comparators[] elements the following assersion it true:
1806 (m_handler_index==i) == (m_cmp_item!=NULL)
1807 */
1808 class Predicant_to_list_comparator
1809 {
1810 // Allocate memory on thd memory root for "nvalues" values.
1811 bool alloc_comparators(THD *thd, uint nvalues);
1812
1813 /**
1814 Look up m_comparators[] for a comparator using the given data type handler.
1815 @param [OUT] idx - the index of the found comparator is returned here
1816 @param [IN] handler - the data type handler to find
1817 @param [IN] count - search in the range [0,count) only
1818 @retval true - this type handler was not found
1819 (*idx is not defined in this case).
1820 @retval false - this type handler was found (the position of the
1821 found handler is returned in idx).
1822 */
find_handler(uint * idx,const Type_handler * handler,uint count)1823 bool find_handler(uint *idx, const Type_handler *handler, uint count)
1824 {
1825 DBUG_ASSERT(count < m_comparator_count);
1826 for (uint i= 0 ; i < count; i++)
1827 {
1828 if (m_comparators[i].m_handler == handler)
1829 {
1830 *idx= i;
1831 return false;
1832 }
1833 }
1834 return true;
1835 }
1836
1837 /**
1838 Populate m_comparators[i].m_handler_index for all elements in
1839 m_comparators using the information in m_comparators[i].m_handlers,
1840 which was previously populated by a add_predicant() call and a number
1841 of add_value() calls.
1842 @param [OUT] compatible - If all comparator types are compatible,
1843 their data type handler is returned here.
1844 @param [OUT] unuque_cnt - The number of unique data type handlers found.
1845 If the value returned in *unique_cnt is 0,
1846 it means all values were explicit NULLs:
1847 expr0 IN (NULL,NULL,..,NULL)
1848 @param [OUT] found_type - The bit mask for all found cmp_type()'s.
1849 */
1850 void detect_unique_handlers(Type_handler_hybrid_field_type *compatible,
1851 uint *unique_cnt, uint *found_types);
1852 /**
1853 Creates a cmp_item instances for all unique handlers and stores
1854 them into m_comparators[i].m_cmp_item, using the information previously
1855 populated by add_predicant(), add_value(), detect_unque_handlers().
1856 */
1857
1858 /*
1859 Compare the predicant to the value pointed by m_comparators[i].
1860 @param args - the same argument array which was previously used
1861 with add_predicant() and add_value().
1862 @param i - which pair to check.
1863 @retval true - the predicant is not equal to the value.
1864 @retval false - the predicant is equal to the value.
1865 @retval UNKNOWN - the result is uncertain yet because the predicant
1866 and/or the value returned NULL,
1867 more pairs {pred,valueN} should be checked.
1868 */
cmp_arg(Item_args * args,uint i)1869 int cmp_arg(Item_args *args, uint i)
1870 {
1871 Predicant_to_value_comparator *cmp=
1872 &m_comparators[m_comparators[i].m_handler_index];
1873 cmp_item *in_item= cmp->m_cmp_item;
1874 DBUG_ASSERT(in_item);
1875 /*
1876 If this is the leftmost pair that uses the data type handler
1877 pointed by m_comparators[i].m_handler, then we need to cache
1878 the predicant value representation used by this handler.
1879 */
1880 if (m_comparators[i].m_handler_index == i)
1881 in_item->store_value(args->arguments()[m_predicant_index]);
1882 /*
1883 If the predicant item has null_value==true then:
1884 - In case of scalar expression we can returns UNKNOWN immediately.
1885 No needs to check the result of the value item.
1886 - In case of ROW, null_value==true means that *some* row elements
1887 returned NULL, but *some* elements can still be non-NULL!
1888 We need to get the result of the value item and test
1889 if non-NULL elements in the predicant and the value produce
1890 TRUE (not equal), or UNKNOWN.
1891 */
1892 if (args->arguments()[m_predicant_index]->null_value &&
1893 m_comparators[i].m_handler != &type_handler_row)
1894 return UNKNOWN;
1895 return in_item->cmp(args->arguments()[m_comparators[i].m_arg_index]);
1896 }
cmp_args_nulls_equal(Item_args * args,uint i)1897 int cmp_args_nulls_equal(Item_args *args, uint i)
1898 {
1899 Predicant_to_value_comparator *cmp=
1900 &m_comparators[m_comparators[i].m_handler_index];
1901 cmp_item *in_item= cmp->m_cmp_item;
1902 DBUG_ASSERT(in_item);
1903 Item *predicant= args->arguments()[m_predicant_index];
1904 Item *arg= args->arguments()[m_comparators[i].m_arg_index];
1905 ValueBuffer<MAX_FIELD_WIDTH> val;
1906 if (m_comparators[i].m_handler_index == i)
1907 in_item->store_value(predicant);
1908 m_comparators[i].m_handler->Item_save_in_value(arg, &val);
1909 if (predicant->null_value && val.is_null())
1910 return FALSE; // Two nulls are equal
1911 if (predicant->null_value || val.is_null())
1912 return UNKNOWN;
1913 return in_item->cmp_not_null(&val);
1914 }
1915 /**
1916 Predicant_to_value_comparator - a comparator for one pair (pred,valueN).
1917 See comments above.
1918 */
1919 struct Predicant_to_value_comparator
1920 {
1921 const Type_handler *m_handler;
1922 cmp_item *m_cmp_item;
1923 uint m_arg_index;
1924 uint m_handler_index;
cleanupPredicant_to_value_comparator1925 void cleanup()
1926 {
1927 if (m_cmp_item)
1928 delete m_cmp_item;
1929 memset(this, 0, sizeof(*this));
1930 }
1931 };
1932
1933 Predicant_to_value_comparator *m_comparators; // The comparator array
1934 uint m_comparator_count;// The number of elements in m_comparators[]
1935 uint m_predicant_index; // The position of the predicant in its argument list,
1936 // e.g. for Item_func_in m_predicant_index is 0,
1937 // as predicant is stored in Item_func_in::args[0].
1938 // For Item_func_case m_predicant_index is
1939 // set to Item_func_case::first_expr_num.
1940
1941 public:
Predicant_to_list_comparator(THD * thd,uint nvalues)1942 Predicant_to_list_comparator(THD *thd, uint nvalues)
1943 :m_comparator_count(0),
1944 m_predicant_index(0)
1945 {
1946 alloc_comparators(thd, nvalues);
1947 }
1948
comparator_count()1949 uint comparator_count() const { return m_comparator_count; }
get_comparator_type_handler(uint i)1950 const Type_handler *get_comparator_type_handler(uint i) const
1951 {
1952 DBUG_ASSERT(i < m_comparator_count);
1953 return m_comparators[i].m_handler;
1954 }
get_comparator_arg_index(uint i)1955 uint get_comparator_arg_index(uint i) const
1956 {
1957 DBUG_ASSERT(i < m_comparator_count);
1958 return m_comparators[i].m_arg_index;
1959 }
get_comparator_cmp_item(uint i)1960 cmp_item *get_comparator_cmp_item(uint i) const
1961 {
1962 DBUG_ASSERT(i < m_comparator_count);
1963 return m_comparators[i].m_cmp_item;
1964 }
1965
1966 #ifndef DBUG_OFF
debug_print(THD * thd)1967 void debug_print(THD *thd)
1968 {
1969 for (uint i= 0; i < m_comparator_count; i++)
1970 {
1971 DBUG_EXECUTE_IF("Predicant_to_list_comparator",
1972 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
1973 ER_UNKNOWN_ERROR, "DBUG: [%d] arg=%d handler=%d (%s)", i,
1974 m_comparators[i].m_arg_index,
1975 m_comparators[i].m_handler_index,
1976 m_comparators[m_comparators[i].m_handler_index].
1977 m_handler->name().ptr()););
1978 }
1979 }
1980 #endif
1981
add_predicant(Item_args * args,uint predicant_index)1982 void add_predicant(Item_args *args, uint predicant_index)
1983 {
1984 DBUG_ASSERT(m_comparator_count == 0); // Set in constructor
1985 DBUG_ASSERT(m_predicant_index == 0); // Set in constructor
1986 DBUG_ASSERT(predicant_index < args->argument_count());
1987 m_predicant_index= predicant_index;
1988 }
1989 /**
1990 Add a new element into m_comparators[], using a {pred,valueN} pair.
1991
1992 @param funcname - the name of the operation, for error reporting
1993 @param args - the owner function's argument list
1994 @param value_index - the value position in args
1995 @retval true - could not add an element because of non-comparable
1996 arguments (e.g. ROWs with size)
1997 @retval false - a new element was successfully added.
1998 */
1999 bool add_value(const char *funcname, Item_args *args, uint value_index);
2000
2001 /**
2002 Add a new element into m_comparators[], ignoring explicit NULL values.
2003 If the value appeared to be an explicit NULL, nulls_found[0] is set to true.
2004 */
2005 bool add_value_skip_null(const char *funcname,
2006 Item_args *args, uint value_index,
2007 bool *nulls_found);
2008
2009 /**
2010 Signal "this" that there will be no new add_value*() calls,
2011 so it can prepare its internal structures for comparison.
2012
2013 @param [OUT] compatible - If all comparators are compatible,
2014 their data type handler is returned here.
2015 @param [OUT] unuque_cnt - The number of unique data type handlers found.
2016 If the value returned in *unique_cnt is 0,
2017 it means all values were explicit NULLs:
2018 expr0 IN (NULL,NULL,..,NULL)
2019 @param [OUT] found_type - The bit mask for all found cmp_type()'s.
2020 */
all_values_added(Type_handler_hybrid_field_type * compatible,uint * unique_cnt,uint * found_types)2021 void all_values_added(Type_handler_hybrid_field_type *compatible,
2022 uint *unique_cnt, uint *found_types)
2023 {
2024 detect_unique_handlers(compatible, unique_cnt, found_types);
2025 }
2026 /**
2027 Creates cmp_item instances for all unique handlers and stores
2028 them into m_comparators[].m_cmp_item, using the information previously
2029 populated by add_predicant(), add_value() and detect_unque_handlers().
2030 */
2031 bool make_unique_cmp_items(THD *thd, CHARSET_INFO *cs);
cleanup()2032 void cleanup()
2033 {
2034 DBUG_ASSERT(m_comparators);
2035 for (uint i= 0; i < m_comparator_count; i++)
2036 m_comparators[i].cleanup();
2037 memset(m_comparators, 0, sizeof(m_comparators[0]) * m_comparator_count);
2038 m_comparator_count= 0;
2039 m_predicant_index= 0;
2040 }
init_clone(THD * thd,uint nvalues)2041 bool init_clone(THD *thd, uint nvalues)
2042 {
2043 m_comparator_count= 0;
2044 m_predicant_index= 0;
2045 return alloc_comparators(thd, nvalues);
2046 }
2047 /**
2048 @param [IN] args - The argument list that was previously used with
2049 add_predicant() and add_value().
2050 @param [OUT] idx - In case if a value that is equal to the predicant
2051 was found, the index of the matching value is returned
2052 here. Otherwise, *idx is not changed.
2053 @param [IN/OUT] found_unknown_values - how to handle UNKNOWN results.
2054 If found_unknown_values is NULL (e.g. Item_func_case),
2055 cmp() returns immediately when the first UNKNOWN
2056 result is found.
2057 If found_unknown_values is non-NULL (Item_func_in),
2058 cmp() does not return when an UNKNOWN result is found,
2059 sets *found_unknown_values to true, and continues
2060 to compare the remaining pairs to find FALSE
2061 (i.e. the value that is equal to the predicant).
2062
2063 @retval false - Found a value that is equal to the predicant
2064 @retval true - Didn't find an equal value
2065 */
cmp(Item_args * args,uint * idx,bool * found_unknown_values)2066 bool cmp(Item_args *args, uint *idx, bool *found_unknown_values)
2067 {
2068 for (uint i= 0 ; i < m_comparator_count ; i++)
2069 {
2070 DBUG_ASSERT(m_comparators[i].m_handler != NULL);
2071 const int rc= cmp_arg(args, i);
2072 if (rc == FALSE)
2073 {
2074 *idx= m_comparators[i].m_arg_index;
2075 return false; // Found a matching value
2076 }
2077 if (rc == UNKNOWN)
2078 {
2079 if (!found_unknown_values)
2080 return true;
2081 *found_unknown_values= true;
2082 }
2083 }
2084 return true; // Not found
2085 }
2086 /*
2087 Same as above, but treats two NULLs as equal, e.g. as in DECODE_ORACLE().
2088 */
cmp_nulls_equal(Item_args * args,uint * idx)2089 bool cmp_nulls_equal(Item_args *args, uint *idx)
2090 {
2091 for (uint i= 0 ; i < m_comparator_count ; i++)
2092 {
2093 DBUG_ASSERT(m_comparators[i].m_handler != NULL);
2094 if (cmp_args_nulls_equal(args, i) == FALSE)
2095 {
2096 *idx= m_comparators[i].m_arg_index;
2097 return false; // Found a matching value
2098 }
2099 }
2100 return true; // Not found
2101 }
2102 };
2103
2104
2105 /*
2106 The class Item_func_case is the CASE ... WHEN ... THEN ... END function
2107 implementation.
2108 */
2109
2110 class Item_func_case :public Item_func_case_expression
2111 {
2112 protected:
2113 String tmp_value;
2114 DTCollation cmp_collation;
2115 bool aggregate_then_and_else_arguments(THD *thd, uint count);
2116 virtual Item **else_expr_addr() const= 0;
2117 virtual Item *find_item()= 0;
2118 inline void print_when_then_arguments(String *str,
2119 enum_query_type query_type,
2120 Item **items, uint count);
2121 inline void print_else_argument(String *str, enum_query_type query_type,
2122 Item *item);
2123 void reorder_args(uint start);
2124 public:
Item_func_case(THD * thd,List<Item> & list)2125 Item_func_case(THD *thd, List<Item> &list)
2126 :Item_func_case_expression(thd, list)
2127 { }
2128 double real_op();
2129 longlong int_op();
2130 String *str_op(String *);
2131 my_decimal *decimal_op(my_decimal *);
2132 bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
2133 bool time_op(MYSQL_TIME *ltime);
2134 bool fix_fields(THD *thd, Item **ref);
not_null_tables()2135 table_map not_null_tables() const { return 0; }
func_name()2136 const char *func_name() const { return "case"; }
compare_collation()2137 CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
need_parentheses_in_default()2138 bool need_parentheses_in_default() { return true; }
2139 };
2140
2141
2142 /*
2143 CASE WHEN cond THEN res [WHEN cond THEN res...] [ELSE res] END
2144
2145 Searched CASE checks all WHEN expressions one after another.
2146 When some WHEN expression evaluated to TRUE then the
2147 value of the corresponding THEN expression is returned.
2148 */
2149 class Item_func_case_searched: public Item_func_case
2150 {
when_count()2151 uint when_count() const { return arg_count / 2; }
with_else()2152 bool with_else() const { return arg_count % 2; }
else_expr_addr()2153 Item **else_expr_addr() const { return with_else() ? &args[arg_count - 1] : 0; }
2154 public:
Item_func_case_searched(THD * thd,List<Item> & list)2155 Item_func_case_searched(THD *thd, List<Item> &list)
2156 :Item_func_case(thd, list)
2157 {
2158 DBUG_ASSERT(arg_count >= 2);
2159 reorder_args(0);
2160 }
functype()2161 enum Functype functype() const { return CASE_SEARCHED_FUNC; }
2162 void print(String *str, enum_query_type query_type);
2163 bool fix_length_and_dec();
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)2164 Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
2165 {
2166 // None of the arguments are in a comparison context
2167 Item_args::propagate_equal_fields(thd, Context_identity(), cond);
2168 return this;
2169 }
2170 Item *find_item();
get_copy(THD * thd)2171 Item *get_copy(THD *thd)
2172 { return get_item_copy<Item_func_case_searched>(thd, this); }
2173 };
2174
2175
2176 /*
2177 CASE pred WHEN value THEN res [WHEN value THEN res...] [ELSE res] END
2178
2179 When the predicant expression is specified then it is compared to each WHEN
2180 expression individually. When an equal WHEN expression is found
2181 the corresponding THEN expression is returned.
2182 In order to do correct comparisons several comparators are used. One for
2183 each result type. Different result types that are used in particular
2184 CASE ... END expression are collected in the fix_length_and_dec() member
2185 function and only comparators for there result types are used.
2186 */
2187 class Item_func_case_simple: public Item_func_case,
2188 public Predicant_to_list_comparator
2189 {
2190 protected:
2191 uint m_found_types;
when_count()2192 uint when_count() const { return (arg_count - 1) / 2; }
with_else()2193 bool with_else() const { return arg_count % 2 == 0; }
else_expr_addr()2194 Item **else_expr_addr() const { return with_else() ? &args[arg_count - 1] : 0; }
2195 bool aggregate_switch_and_when_arguments(THD *thd, bool nulls_equal);
2196 bool prepare_predicant_and_values(THD *thd, uint *found_types,
2197 bool nulls_equal);
2198 public:
Item_func_case_simple(THD * thd,List<Item> & list)2199 Item_func_case_simple(THD *thd, List<Item> &list)
2200 :Item_func_case(thd, list),
2201 Predicant_to_list_comparator(thd, arg_count),
2202 m_found_types(0)
2203 {
2204 DBUG_ASSERT(arg_count >= 3);
2205 reorder_args(1);
2206 }
cleanup()2207 void cleanup()
2208 {
2209 DBUG_ENTER("Item_func_case_simple::cleanup");
2210 Item_func::cleanup();
2211 Predicant_to_list_comparator::cleanup();
2212 DBUG_VOID_RETURN;
2213 }
functype()2214 enum Functype functype() const { return CASE_SIMPLE_FUNC; }
2215 void print(String *str, enum_query_type query_type);
2216 bool fix_length_and_dec();
2217 Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
2218 Item *find_item();
build_clone(THD * thd)2219 Item *build_clone(THD *thd)
2220 {
2221 Item_func_case_simple *clone= (Item_func_case_simple *)
2222 Item_func_case::build_clone(thd);
2223 uint ncases= when_count();
2224 if (clone && clone->Predicant_to_list_comparator::init_clone(thd, ncases))
2225 return NULL;
2226 return clone;
2227 }
get_copy(THD * thd)2228 Item *get_copy(THD *thd)
2229 { return get_item_copy<Item_func_case_simple>(thd, this); }
2230 };
2231
2232
2233 class Item_func_decode_oracle: public Item_func_case_simple
2234 {
2235 public:
Item_func_decode_oracle(THD * thd,List<Item> & list)2236 Item_func_decode_oracle(THD *thd, List<Item> &list)
2237 :Item_func_case_simple(thd, list)
2238 { }
func_name()2239 const char *func_name() const { return "decode_oracle"; }
2240 void print(String *str, enum_query_type query_type);
2241 bool fix_length_and_dec();
2242 Item *find_item();
get_copy(THD * thd)2243 Item *get_copy(THD *thd)
2244 { return get_item_copy<Item_func_decode_oracle>(thd, this); }
2245 };
2246
2247
2248 /*
2249 The Item_func_in class implements
2250 in_expr IN (<in value list>)
2251 and
2252 in_expr NOT IN (<in value list>)
2253
2254 The current implementation distinguishes 2 cases:
2255 1) all items in <in value list> are constants and have the same
2256 result type. This case is handled by in_vector class,
2257 implementing fast bisection search.
2258 2) otherwise Item_func_in employs several cmp_item objects to perform
2259 comparisons of in_expr and an item from <in value list>. One cmp_item
2260 object for each result type. Different result types are collected in the
2261 fix_length_and_dec() member function by means of collect_cmp_types()
2262 function.
2263
2264 Bisection is possible when:
2265 1. All types are similar
2266 2. All expressions in <in value list> are const
2267 In the presence of NULLs, the correct result of evaluating this item
2268 must be UNKNOWN or FALSE. To achieve that:
2269 - If type is scalar, we can use bisection and the "have_null" boolean.
2270 - If type is ROW, we will need to scan all of <in value list> when
2271 searching, so bisection is impossible. Unless:
2272 3. UNKNOWN and FALSE are equivalent results
2273 4. Neither left expression nor <in value list> contain any NULL value
2274 */
2275 class Item_func_in :public Item_func_opt_neg,
2276 public Predicant_to_list_comparator
2277 {
2278 /**
2279 Usable if <in value list> is made only of constants. Returns true if one
2280 of these constants contains a NULL. Example:
2281 IN ( (-5, (12,NULL)), ... ).
2282 */
2283 bool list_contains_null();
all_items_are_consts(Item ** items,uint nitems)2284 bool all_items_are_consts(Item **items, uint nitems) const
2285 {
2286 for (uint i= 0; i < nitems; i++)
2287 {
2288 if (!items[i]->const_item() || items[i]->is_expensive())
2289 return false;
2290 }
2291 return true;
2292 }
2293 bool prepare_predicant_and_values(THD *thd, uint *found_types);
check_arguments()2294 bool check_arguments() const
2295 {
2296 return check_argument_types_like_args0();
2297 }
2298 protected:
2299 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
2300 Field *field, Item *value);
2301 bool transform_into_subq;
2302 public:
2303 /// An array of values, created when the bisection lookup method is used
2304 in_vector *array;
2305 /**
2306 If there is some NULL among <in value list>, during a val_int() call; for
2307 example
2308 IN ( (1,(3,'col')), ... ), where 'col' is a column which evaluates to
2309 NULL.
2310 */
2311 bool have_null;
2312 /**
2313 true when all arguments of the IN list are of compatible types
2314 and can be used safely as comparisons for key conditions
2315 */
2316 bool arg_types_compatible;
2317
2318 TABLE_LIST *emb_on_expr_nest;
2319
Item_func_in(THD * thd,List<Item> & list)2320 Item_func_in(THD *thd, List<Item> &list):
2321 Item_func_opt_neg(thd, list),
2322 Predicant_to_list_comparator(thd, arg_count - 1),
2323 transform_into_subq(false),
2324 array(0), have_null(0),
2325 arg_types_compatible(FALSE), emb_on_expr_nest(0)
2326 { }
2327 longlong val_int();
2328 bool fix_fields(THD *, Item **);
2329 bool fix_length_and_dec();
compatible_types_scalar_bisection_possible()2330 bool compatible_types_scalar_bisection_possible()
2331 {
2332 DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
2333 return all_items_are_consts(args + 1, arg_count - 1); // Bisection #2
2334 }
compatible_types_row_bisection_possible()2335 bool compatible_types_row_bisection_possible()
2336 {
2337 DBUG_ASSERT(m_comparator.cmp_type() == ROW_RESULT);
2338 return all_items_are_consts(args + 1, arg_count - 1) && // Bisection #2
2339 ((is_top_level_item() && !negated) || // Bisection #3
2340 (!list_contains_null() && !args[0]->maybe_null)); // Bisection #4
2341 }
agg_all_arg_charsets_for_comparison()2342 bool agg_all_arg_charsets_for_comparison()
2343 {
2344 return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
2345 }
2346 void fix_in_vector();
2347 bool value_list_convert_const_to_int(THD *thd);
fix_for_scalar_comparison_using_bisection(THD * thd)2348 bool fix_for_scalar_comparison_using_bisection(THD *thd)
2349 {
2350 array= m_comparator.type_handler()->make_in_vector(thd, this, arg_count - 1);
2351 if (!array) // OOM
2352 return true;
2353 fix_in_vector();
2354 return false;
2355 }
2356 bool fix_for_scalar_comparison_using_cmp_items(THD *thd, uint found_types);
2357
2358 bool fix_for_row_comparison_using_cmp_items(THD *thd);
2359 bool fix_for_row_comparison_using_bisection(THD *thd);
2360
cleanup()2361 void cleanup()
2362 {
2363 DBUG_ENTER("Item_func_in::cleanup");
2364 Item_int_func::cleanup();
2365 delete array;
2366 array= 0;
2367 Predicant_to_list_comparator::cleanup();
2368 DBUG_VOID_RETURN;
2369 }
2370 void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
2371 table_map usable_tables, SARGABLE_PARAM **sargables);
2372 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
2373 SEL_TREE *get_func_row_mm_tree(RANGE_OPT_PARAM *param, Item_row *key_row);
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)2374 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
2375 {
2376 /*
2377 Note, we pass ANY_SUBST, this makes sure that non of the args
2378 will be replaced to a zero-filled Item_string.
2379 Such a change would require rebuilding of cmp_items.
2380 */
2381 if (arg_types_compatible)
2382 {
2383 Context cmpctx(ANY_SUBST, m_comparator.type_handler(),
2384 Item_func_in::compare_collation());
2385 args[0]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
2386 cond, &args[0]);
2387 }
2388 for (uint i= 0; i < comparator_count(); i++)
2389 {
2390 Context cmpctx(ANY_SUBST, get_comparator_type_handler(i),
2391 Item_func_in::compare_collation());
2392 uint idx= get_comparator_arg_index(i);
2393 args[idx]->propagate_equal_fields_and_change_item_tree(thd, cmpctx,
2394 cond, &args[idx]);
2395 }
2396 return this;
2397 }
2398 virtual void print(String *str, enum_query_type query_type);
functype()2399 enum Functype functype() const { return IN_FUNC; }
func_name()2400 const char *func_name() const { return "in"; }
precedence()2401 enum precedence precedence() const { return IN_PRECEDENCE; }
2402 bool eval_not_null_tables(void *opt_arg);
2403 void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
2404 bool count_sargable_conds(void *arg);
get_copy(THD * thd)2405 Item *get_copy(THD *thd)
2406 { return get_item_copy<Item_func_in>(thd, this); }
build_clone(THD * thd)2407 Item *build_clone(THD *thd)
2408 {
2409 Item_func_in *clone= (Item_func_in *) Item_func::build_clone(thd);
2410 if (clone)
2411 {
2412 clone->array= 0;
2413 if (clone->Predicant_to_list_comparator::init_clone(thd, arg_count - 1))
2414 return NULL;
2415 }
2416 return clone;
2417 }
2418 void mark_as_condition_AND_part(TABLE_LIST *embedding);
2419 bool to_be_transformed_into_in_subq(THD *thd);
2420 bool create_value_list_for_tvc(THD *thd, List< List<Item> > *values);
2421 Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg);
2422 uint32 max_length_of_left_expr();
2423 };
2424
2425 class cmp_item_row :public cmp_item
2426 {
2427 cmp_item **comparators;
2428 uint n;
2429 public:
cmp_item_row()2430 cmp_item_row(): comparators(0), n(0) {}
2431 ~cmp_item_row();
2432 void store_value(Item *item);
2433 bool alloc_comparators(THD *thd, uint n);
2434 bool prepare_comparators(THD *, Item **args, uint arg_count);
2435 int cmp(Item *arg);
cmp_not_null(const Value * val)2436 int cmp_not_null(const Value *val)
2437 {
2438 DBUG_ASSERT(false);
2439 return TRUE;
2440 }
2441 int compare(cmp_item *arg);
2442 cmp_item *make_same();
2443 void store_value_by_template(THD *thd, cmp_item *tmpl, Item *);
2444 friend class Item_func_in;
get_comparator(uint i)2445 cmp_item *get_comparator(uint i) { return comparators[i]; }
2446 };
2447
2448
2449 class in_row :public in_vector
2450 {
2451 cmp_item_row tmp;
2452 public:
2453 in_row(THD *thd, uint elements, Item *);
2454 ~in_row();
2455 void set(uint pos,Item *item);
2456 uchar *get_value(Item *item);
2457 friend class Item_func_in;
type_handler()2458 const Type_handler *type_handler() const { return &type_handler_row; }
get_cmp_item()2459 cmp_item *get_cmp_item() { return &tmp; }
2460 };
2461
2462 /* Functions used by where clause */
2463 class Item_func_null_predicate :public Item_bool_func
2464 {
2465 protected:
get_func_mm_tree(RANGE_OPT_PARAM * param,Field * field,Item * value)2466 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
2467 Field *field, Item *value)
2468 {
2469 DBUG_ENTER("Item_func_null_predicate::get_func_mm_tree");
2470 DBUG_RETURN(get_mm_parts(param, field, functype(), value));
2471 }
2472 SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
2473 KEY_PART *key_part,
2474 Item_func::Functype type, Item *value);
2475 public:
Item_func_null_predicate(THD * thd,Item * a)2476 Item_func_null_predicate(THD *thd, Item *a): Item_bool_func(thd, a) { }
2477 void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
2478 table_map usable_tables, SARGABLE_PARAM **sargables);
get_mm_tree(RANGE_OPT_PARAM * param,Item ** cond_ptr)2479 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
2480 {
2481 DBUG_ENTER("Item_func_null_predicate::get_mm_tree");
2482 SEL_TREE *ftree= get_full_func_mm_tree_for_args(param, args[0], NULL);
2483 if (!ftree)
2484 ftree= Item_func::get_mm_tree(param, cond_ptr);
2485 DBUG_RETURN(ftree);
2486 }
compare_collation()2487 CHARSET_INFO *compare_collation() const
2488 { return args[0]->collation.collation; }
fix_length_and_dec()2489 bool fix_length_and_dec()
2490 {
2491 decimals=0; max_length=1; maybe_null=0;
2492 return FALSE;
2493 }
2494 bool count_sargable_conds(void *arg);
2495 };
2496
2497
2498 class Item_func_isnull :public Item_func_null_predicate
2499 {
2500 public:
Item_func_isnull(THD * thd,Item * a)2501 Item_func_isnull(THD *thd, Item *a): Item_func_null_predicate(thd, a) {}
2502 longlong val_int();
functype()2503 enum Functype functype() const { return ISNULL_FUNC; }
func_name()2504 const char *func_name() const { return "isnull"; }
2505 void print(String *str, enum_query_type query_type);
precedence()2506 enum precedence precedence() const { return CMP_PRECEDENCE; }
2507
arg_is_datetime_notnull_field()2508 bool arg_is_datetime_notnull_field()
2509 {
2510 Item **args= arguments();
2511 if (args[0]->real_item()->type() == Item::FIELD_ITEM)
2512 {
2513 Field *field=((Item_field*) args[0]->real_item())->field;
2514
2515 if (((field->type() == MYSQL_TYPE_DATE) ||
2516 (field->type() == MYSQL_TYPE_DATETIME)) &&
2517 (field->flags & NOT_NULL_FLAG))
2518 return true;
2519 }
2520 return false;
2521 }
2522
2523 /* Optimize case of not_null_column IS NULL */
update_used_tables()2524 virtual void update_used_tables()
2525 {
2526 if (!args[0]->maybe_null && !arg_is_datetime_notnull_field())
2527 {
2528 used_tables_cache= 0; /* is always false */
2529 const_item_cache= 1;
2530 }
2531 else
2532 {
2533 args[0]->update_used_tables();
2534 used_tables_cache= args[0]->used_tables();
2535 const_item_cache= args[0]->const_item();
2536 }
2537 }
2538 COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
2539 bool top_level);
not_null_tables()2540 table_map not_null_tables() const { return 0; }
2541 Item *neg_transformer(THD *thd);
get_copy(THD * thd)2542 Item *get_copy(THD *thd)
2543 { return get_item_copy<Item_func_isnull>(thd, this); }
2544 };
2545
2546 /* Functions used by HAVING for rewriting IN subquery */
2547
2548 class Item_in_subselect;
2549
2550 /*
2551 This is like IS NOT NULL but it also remembers if it ever has
2552 encountered a NULL.
2553 */
2554 class Item_is_not_null_test :public Item_func_isnull
2555 {
2556 Item_in_subselect* owner;
2557 public:
Item_is_not_null_test(THD * thd,Item_in_subselect * ow,Item * a)2558 Item_is_not_null_test(THD *thd, Item_in_subselect* ow, Item *a):
2559 Item_func_isnull(thd, a), owner(ow)
2560 {}
functype()2561 enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
2562 longlong val_int();
func_name()2563 const char *func_name() const { return "<is_not_null_test>"; }
2564 void update_used_tables();
2565 /*
2566 we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE
2567 */
used_tables()2568 table_map used_tables() const
2569 { return used_tables_cache | RAND_TABLE_BIT; }
const_item()2570 bool const_item() const { return FALSE; }
2571 };
2572
2573
2574 class Item_func_isnotnull :public Item_func_null_predicate
2575 {
2576 bool abort_on_null;
2577 public:
Item_func_isnotnull(THD * thd,Item * a)2578 Item_func_isnotnull(THD *thd, Item *a):
2579 Item_func_null_predicate(thd, a), abort_on_null(0)
2580 { }
2581 longlong val_int();
functype()2582 enum Functype functype() const { return ISNOTNULL_FUNC; }
func_name()2583 const char *func_name() const { return "isnotnull"; }
precedence()2584 enum precedence precedence() const { return CMP_PRECEDENCE; }
not_null_tables()2585 table_map not_null_tables() const
2586 { return abort_on_null ? not_null_tables_cache : 0; }
2587 Item *neg_transformer(THD *thd);
2588 void print(String *str, enum_query_type query_type);
top_level_item()2589 void top_level_item() { abort_on_null=1; }
get_copy(THD * thd)2590 Item *get_copy(THD *thd)
2591 { return get_item_copy<Item_func_isnotnull>(thd, this); }
2592 };
2593
2594
2595 class Item_func_like :public Item_bool_func2
2596 {
2597 // Turbo Boyer-Moore data
2598 bool canDoTurboBM; // pattern is '%abcd%' case
2599 const char* pattern;
2600 int pattern_len;
2601
2602 // TurboBM buffers, *this is owner
2603 int* bmGs; // good suffix shift table, size is pattern_len + 1
2604 int* bmBc; // bad character shift table, size is alphabet_size
2605
2606 void turboBM_compute_suffixes(int* suff);
2607 void turboBM_compute_good_suffix_shifts(int* suff);
2608 void turboBM_compute_bad_character_shifts();
2609 bool turboBM_matches(const char* text, int text_len) const;
2610 enum { alphabet_size = 256 };
2611
2612 Item *escape_item;
2613
2614 bool escape_used_in_parsing;
2615 bool use_sampling;
2616
2617 DTCollation cmp_collation;
2618 String cmp_value1, cmp_value2;
2619 bool with_sargable_pattern() const;
2620 protected:
get_func_mm_tree(RANGE_OPT_PARAM * param,Field * field,Item * value)2621 SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param,
2622 Field *field, Item *value)
2623 {
2624 DBUG_ENTER("Item_func_like::get_func_mm_tree");
2625 DBUG_RETURN(get_mm_parts(param, field, LIKE_FUNC, value));
2626 }
2627 SEL_ARG *get_mm_leaf(RANGE_OPT_PARAM *param, Field *field,
2628 KEY_PART *key_part,
2629 Item_func::Functype type, Item *value);
2630 public:
2631 int escape;
2632 bool negated;
2633
Item_func_like(THD * thd,Item * a,Item * b,Item * escape_arg,bool escape_used)2634 Item_func_like(THD *thd, Item *a, Item *b, Item *escape_arg, bool escape_used):
2635 Item_bool_func2(thd, a, b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
2636 bmGs(0), bmBc(0), escape_item(escape_arg),
2637 escape_used_in_parsing(escape_used), use_sampling(0), negated(0) {}
2638 Sql_mode_dependency value_depends_on_sql_mode() const;
2639 longlong val_int();
functype()2640 enum Functype functype() const { return LIKE_FUNC; }
2641 void print(String *str, enum_query_type query_type);
compare_collation()2642 CHARSET_INFO *compare_collation() const
2643 { return cmp_collation.collation; }
eq_cmp_result()2644 cond_result eq_cmp_result() const
2645 {
2646 /**
2647 We cannot always rewrite conditions as follows:
2648 from: WHERE expr1=const AND expr1 LIKE expr2
2649 to: WHERE expr1=const AND const LIKE expr2
2650 or
2651 from: WHERE expr1=const AND expr2 LIKE expr1
2652 to: WHERE expr1=const AND expr2 LIKE const
2653
2654 because LIKE works differently comparing to the regular "=" operator:
2655
2656 1. LIKE performs a stricter one-character-to-one-character comparison
2657 and does not recognize contractions and expansions.
2658 Replacing "expr1" to "const in LIKE would make the condition
2659 stricter in case of a complex collation.
2660
2661 2. LIKE does not ignore trailing spaces and thus works differently
2662 from the "=" operator in case of "PAD SPACE" collations
2663 (which are the majority in MariaDB). So, for "PAD SPACE" collations:
2664
2665 - expr1=const - ignores trailing spaces
2666 - const LIKE expr2 - does not ignore trailing spaces
2667 - expr2 LIKE const - does not ignore trailing spaces
2668
2669 Allow only "binary" for now.
2670 It neither ignores trailing spaces nor has contractions/expansions.
2671
2672 TODO:
2673 We could still replace "expr1" to "const" in "expr1 LIKE expr2"
2674 in case of a "PAD SPACE" collation, but only if "expr2" has '%'
2675 at the end.
2676 */
2677 return compare_collation() == &my_charset_bin ? COND_TRUE : COND_OK;
2678 }
2679 void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
2680 table_map usable_tables, SARGABLE_PARAM **sargables);
2681 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
propagate_equal_fields(THD * thd,const Context & ctx,COND_EQUAL * cond)2682 Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
2683 {
2684 /*
2685 LIKE differs from the regular comparison operator ('=') in the following:
2686 - LIKE never ignores trailing spaces (even for PAD SPACE collations)
2687 Propagation of equal fields with a PAD SPACE collation into LIKE
2688 is not safe.
2689 Example:
2690 WHERE a='a ' AND a LIKE 'a' - returns true for 'a'
2691 cannot be rewritten to:
2692 WHERE a='a ' AND 'a ' LIKE 'a' - returns false for 'a'
2693 Note, binary collations in MySQL/MariaDB, e.g. latin1_bin,
2694 still have the PAD SPACE attribute and ignore trailing spaces!
2695 - LIKE does not take into account contractions, expansions,
2696 and ignorable characters.
2697 Propagation of equal fields with contractions/expansions/ignorables
2698 is also not safe.
2699
2700 It's safe to propagate my_charset_bin (BINARY/VARBINARY/BLOB) values,
2701 because they do not ignore trailing spaces and have one-to-one mapping
2702 between a string and its weights.
2703 The below condition should be true only for my_charset_bin
2704 (as of version 10.1.7).
2705 */
2706 uint flags= Item_func_like::compare_collation()->state;
2707 if ((flags & MY_CS_NOPAD) && !(flags & MY_CS_NON1TO1))
2708 Item_args::propagate_equal_fields(thd,
2709 Context(ANY_SUBST,
2710 &type_handler_long_blob,
2711 compare_collation()),
2712 cond);
2713 return this;
2714 }
func_name()2715 const char *func_name() const { return "like"; }
precedence()2716 enum precedence precedence() const { return IN_PRECEDENCE; }
2717 bool fix_fields(THD *thd, Item **ref);
fix_length_and_dec()2718 bool fix_length_and_dec()
2719 {
2720 max_length= 1;
2721 return agg_arg_charsets_for_comparison(cmp_collation, args, 2);
2722 }
2723 void cleanup();
2724
neg_transformer(THD * thd)2725 Item *neg_transformer(THD *thd)
2726 {
2727 negated= !negated;
2728 return this;
2729 }
2730
walk(Item_processor processor,bool walk_subquery,void * arg)2731 bool walk(Item_processor processor, bool walk_subquery, void *arg)
2732 {
2733 return walk_args(processor, walk_subquery, arg)
2734 || escape_item->walk(processor, walk_subquery, arg)
2735 || (this->*processor)(arg);
2736 }
2737
2738 bool find_selective_predicates_list_processor(void *arg);
2739
get_copy(THD * thd)2740 Item *get_copy(THD *thd)
2741 { return get_item_copy<Item_func_like>(thd, this); }
2742 };
2743
2744
2745 class Regexp_processor_pcre
2746 {
2747 pcre *m_pcre;
2748 pcre_extra m_pcre_extra;
2749 bool m_conversion_is_needed;
2750 bool m_is_const;
2751 int m_library_flags;
2752 CHARSET_INFO *m_data_charset;
2753 CHARSET_INFO *m_library_charset;
2754 String m_prev_pattern;
2755 int m_pcre_exec_rc;
2756 int m_SubStrVec[30];
2757 void pcre_exec_warn(int rc) const;
2758 int pcre_exec_with_warn(const pcre *code, const pcre_extra *extra,
2759 const char *subject, int length, int startoffset,
2760 int options, int *ovector, int ovecsize);
2761 public:
2762 String *convert_if_needed(String *src, String *converter);
2763 String subject_converter;
2764 String pattern_converter;
2765 String replace_converter;
Regexp_processor_pcre()2766 Regexp_processor_pcre() :
2767 m_pcre(NULL), m_conversion_is_needed(true), m_is_const(0),
2768 m_library_flags(0),
2769 m_data_charset(&my_charset_utf8_general_ci),
2770 m_library_charset(&my_charset_utf8_general_ci)
2771 {
2772 m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
2773 m_pcre_extra.match_limit_recursion= 100L;
2774 }
2775 int default_regex_flags();
2776 void set_recursion_limit(THD *);
init(CHARSET_INFO * data_charset,int extra_flags)2777 void init(CHARSET_INFO *data_charset, int extra_flags)
2778 {
2779 m_library_flags= default_regex_flags() | extra_flags |
2780 (data_charset != &my_charset_bin ?
2781 (PCRE_UTF8 | PCRE_UCP) : 0) |
2782 ((data_charset->state &
2783 (MY_CS_BINSORT | MY_CS_CSSORT)) ? 0 : PCRE_CASELESS);
2784
2785 // Convert text data to utf-8.
2786 m_library_charset= data_charset == &my_charset_bin ?
2787 &my_charset_bin : &my_charset_utf8_general_ci;
2788
2789 m_conversion_is_needed= (data_charset != &my_charset_bin) &&
2790 !my_charset_same(data_charset, m_library_charset);
2791 }
2792 void fix_owner(Item_func *owner, Item *subject_arg, Item *pattern_arg);
2793 bool compile(String *pattern, bool send_error);
2794 bool compile(Item *item, bool send_error);
recompile(Item * item)2795 bool recompile(Item *item)
2796 {
2797 return !m_is_const && compile(item, false);
2798 }
2799 bool exec(const char *str, size_t length, size_t offset);
2800 bool exec(String *str, int offset, uint n_result_offsets_to_convert);
2801 bool exec(Item *item, int offset, uint n_result_offsets_to_convert);
match()2802 bool match() const { return m_pcre_exec_rc < 0 ? 0 : 1; }
nsubpatterns()2803 int nsubpatterns() const { return m_pcre_exec_rc <= 0 ? 0 : m_pcre_exec_rc; }
subpattern_start(int n)2804 int subpattern_start(int n) const
2805 {
2806 return m_pcre_exec_rc <= 0 ? 0 : m_SubStrVec[n * 2];
2807 }
subpattern_end(int n)2808 int subpattern_end(int n) const
2809 {
2810 return m_pcre_exec_rc <= 0 ? 0 : m_SubStrVec[n * 2 + 1];
2811 }
subpattern_length(int n)2812 int subpattern_length(int n) const
2813 {
2814 return subpattern_end(n) - subpattern_start(n);
2815 }
reset()2816 void reset()
2817 {
2818 m_pcre= NULL;
2819 m_prev_pattern.length(0);
2820 }
cleanup()2821 void cleanup()
2822 {
2823 pcre_free(m_pcre);
2824 reset();
2825 }
is_compiled()2826 bool is_compiled() const { return m_pcre != NULL; }
is_const()2827 bool is_const() const { return m_is_const; }
set_const(bool arg)2828 void set_const(bool arg) { m_is_const= arg; }
library_charset()2829 CHARSET_INFO * library_charset() const { return m_library_charset; }
2830 };
2831
2832
2833 class Item_func_regex :public Item_bool_func
2834 {
2835 Regexp_processor_pcre re;
2836 DTCollation cmp_collation;
2837 public:
Item_func_regex(THD * thd,Item * a,Item * b)2838 Item_func_regex(THD *thd, Item *a, Item *b): Item_bool_func(thd, a, b)
2839 {}
cleanup()2840 void cleanup()
2841 {
2842 DBUG_ENTER("Item_func_regex::cleanup");
2843 Item_bool_func::cleanup();
2844 re.cleanup();
2845 DBUG_VOID_RETURN;
2846 }
2847 longlong val_int();
2848 bool fix_fields(THD *thd, Item **ref);
2849 bool fix_length_and_dec();
func_name()2850 const char *func_name() const { return "regexp"; }
precedence()2851 enum precedence precedence() const { return IN_PRECEDENCE; }
get_copy(THD *)2852 Item *get_copy(THD *) { return 0; }
print(String * str,enum_query_type query_type)2853 void print(String *str, enum_query_type query_type)
2854 {
2855 print_op(str, query_type);
2856 }
2857
compare_collation()2858 CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
2859 };
2860
2861
2862 /*
2863 In the corner case REGEXP_INSTR could return (2^32 + 1),
2864 which would not fit into Item_long_func range.
2865 But string lengths are limited with max_allowed_packet,
2866 which cannot be bigger than 1024*1024*1024.
2867 */
2868 class Item_func_regexp_instr :public Item_long_func
2869 {
check_arguments()2870 bool check_arguments() const
2871 {
2872 return args[0]->check_type_can_return_str(func_name()) ||
2873 args[1]->check_type_can_return_text(func_name());
2874 }
2875 Regexp_processor_pcre re;
2876 DTCollation cmp_collation;
2877 public:
Item_func_regexp_instr(THD * thd,Item * a,Item * b)2878 Item_func_regexp_instr(THD *thd, Item *a, Item *b)
2879 :Item_long_func(thd, a, b)
2880 {}
cleanup()2881 void cleanup()
2882 {
2883 DBUG_ENTER("Item_func_regexp_instr::cleanup");
2884 Item_int_func::cleanup();
2885 re.cleanup();
2886 DBUG_VOID_RETURN;
2887 }
2888 longlong val_int();
2889 bool fix_fields(THD *thd, Item **ref);
2890 bool fix_length_and_dec();
func_name()2891 const char *func_name() const { return "regexp_instr"; }
get_copy(THD * thd)2892 Item *get_copy(THD *thd) { return 0; }
2893 };
2894
2895
2896 typedef class Item COND;
2897
2898 class Item_cond :public Item_bool_func
2899 {
2900 protected:
2901 List<Item> list;
2902 bool abort_on_null;
2903 table_map and_tables_cache;
2904
2905 public:
2906 /* Item_cond() is only used to create top level items */
Item_cond(THD * thd)2907 Item_cond(THD *thd): Item_bool_func(thd), abort_on_null(1)
2908 { const_item_cache=0; }
2909 Item_cond(THD *thd, Item *i1, Item *i2);
2910 Item_cond(THD *thd, Item_cond *item);
Item_cond(THD * thd,List<Item> & nlist)2911 Item_cond(THD *thd, List<Item> &nlist):
2912 Item_bool_func(thd), list(nlist), abort_on_null(0) {}
add(Item * item,MEM_ROOT * root)2913 bool add(Item *item, MEM_ROOT *root)
2914 {
2915 DBUG_ASSERT(item);
2916 return list.push_back(item, root);
2917 }
add_at_head(Item * item,MEM_ROOT * root)2918 bool add_at_head(Item *item, MEM_ROOT *root)
2919 {
2920 DBUG_ASSERT(item);
2921 return list.push_front(item, root);
2922 }
add_at_head(List<Item> * nlist)2923 void add_at_head(List<Item> *nlist)
2924 {
2925 DBUG_ASSERT(nlist->elements);
2926 list.prepend(nlist);
2927 }
add_at_end(List<Item> * nlist)2928 void add_at_end(List<Item> *nlist)
2929 {
2930 DBUG_ASSERT(nlist->elements);
2931 list.append(nlist);
2932 }
2933 bool fix_fields(THD *, Item **ref);
2934 void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
2935
type()2936 enum Type type() const { return COND_ITEM; }
argument_list()2937 List<Item>* argument_list() { return &list; }
2938 table_map used_tables() const;
update_used_tables()2939 void update_used_tables()
2940 {
2941 used_tables_and_const_cache_init();
2942 used_tables_and_const_cache_update_and_join(list);
2943 }
2944 COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
2945 bool link_item_fields,
2946 COND_EQUAL **cond_equal_ref);
2947 COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
2948 bool top_level);
2949 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
2950 uint *and_level, table_map usable_tables,
2951 SARGABLE_PARAM **sargables);
2952 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
2953 virtual void print(String *str, enum_query_type query_type);
2954 void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
2955 List<Item> &fields, uint flags);
2956 friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
2957 COND **conds);
top_level_item()2958 void top_level_item() { abort_on_null=1; }
top_level()2959 bool top_level() { return abort_on_null; }
2960 void copy_andor_arguments(THD *thd, Item_cond *item);
2961 bool walk(Item_processor processor, bool walk_subquery, void *arg);
2962 Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
2963 void traverse_cond(Cond_traverser, void *arg, traverse_order order);
2964 void neg_arguments(THD *thd);
2965 Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
2966 Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p,
2967 Item_transformer transformer, uchar *arg_t);
2968 bool eval_not_null_tables(void *opt_arg);
2969 Item *build_clone(THD *thd);
2970 bool excl_dep_on_table(table_map tab_map);
2971 bool excl_dep_on_grouping_fields(st_select_lex *sel);
2972 };
2973
2974 template <template<class> class LI, class T> class Item_equal_iterator;
2975
2976 /*
2977 The class Item_equal is used to represent conjunctions of equality
2978 predicates of the form field1 = field2, and field=const in where
2979 conditions and on expressions.
2980
2981 All equality predicates of the form field1=field2 contained in a
2982 conjunction are substituted for a sequence of items of this class.
2983 An item of this class Item_equal(f1,f2,...fk) represents a
2984 multiple equality f1=f2=...=fk.l
2985
2986 If a conjunction contains predicates f1=f2 and f2=f3, a new item of
2987 this class is created Item_equal(f1,f2,f3) representing the multiple
2988 equality f1=f2=f3 that substitutes the above equality predicates in
2989 the conjunction.
2990 A conjunction of the predicates f2=f1 and f3=f1 and f3=f2 will be
2991 substituted for the item representing the same multiple equality
2992 f1=f2=f3.
2993 An item Item_equal(f1,f2) can appear instead of a conjunction of
2994 f2=f1 and f1=f2, or instead of just the predicate f1=f2.
2995
2996 An item of the class Item_equal inherits equalities from outer
2997 conjunctive levels.
2998
2999 Suppose we have a where condition of the following form:
3000 WHERE f1=f2 AND f3=f4 AND f3=f5 AND ... AND (...OR (f1=f3 AND ...)).
3001 In this case:
3002 f1=f2 will be substituted for Item_equal(f1,f2);
3003 f3=f4 and f3=f5 will be substituted for Item_equal(f3,f4,f5);
3004 f1=f3 will be substituted for Item_equal(f1,f2,f3,f4,f5);
3005
3006 An object of the class Item_equal can contain an optional constant
3007 item c. Then it represents a multiple equality of the form
3008 c=f1=...=fk.
3009
3010 Objects of the class Item_equal are used for the following:
3011
3012 1. An object Item_equal(t1.f1,...,tk.fk) allows us to consider any
3013 pair of tables ti and tj as joined by an equi-condition.
3014 Thus it provide us with additional access paths from table to table.
3015
3016 2. An object Item_equal(t1.f1,...,tk.fk) is applied to deduce new
3017 SARGable predicates:
3018 f1=...=fk AND P(fi) => f1=...=fk AND P(fi) AND P(fj).
3019 It also can give us additional index scans and can allow us to
3020 improve selectivity estimates.
3021
3022 3. An object Item_equal(t1.f1,...,tk.fk) is used to optimize the
3023 selected execution plan for the query: if table ti is accessed
3024 before the table tj then in any predicate P in the where condition
3025 the occurrence of tj.fj is substituted for ti.fi. This can allow
3026 an evaluation of the predicate at an earlier step.
3027
3028 When feature 1 is supported they say that join transitive closure
3029 is employed.
3030 When feature 2 is supported they say that search argument transitive
3031 closure is employed.
3032 Both features are usually supported by preprocessing original query and
3033 adding additional predicates.
3034 We do not just add predicates, we rather dynamically replace some
3035 predicates that can not be used to access tables in the investigated
3036 plan for those, obtained by substitution of some fields for equal fields,
3037 that can be used.
3038
3039 Prepared Statements/Stored Procedures note: instances of class
3040 Item_equal are created only at the time a PS/SP is executed and
3041 are deleted in the end of execution. All changes made to these
3042 objects need not be registered in the list of changes of the parse
3043 tree and do not harm PS/SP re-execution.
3044
3045 Item equal objects are employed only at the optimize phase. Usually they are
3046 not supposed to be evaluated. Yet in some cases we call the method val_int()
3047 for them. We have to take care of restricting the predicate such an
3048 object represents f1=f2= ...=fn to the projection of known fields fi1=...=fik.
3049 */
3050
3051 class Item_equal: public Item_bool_func
3052 {
3053 /*
3054 The list of equal items. Currently the list can contain:
3055 - Item_fields items for references to table columns
3056 - Item_direct_view_ref items for references to view columns
3057 - one const item
3058
3059 If the list contains a constant item this item is always first in the list.
3060 The list contains at least two elements.
3061 Currently all Item_fields/Item_direct_view_ref items in the list should
3062 refer to table columns with equavalent type definitions. In particular
3063 if these are string columns they should have the same charset/collation.
3064
3065 Use objects of the companion class Item_equal_fields_iterator to iterate
3066 over all items from the list of the Item_field/Item_direct_view_ref classes.
3067 */
3068 List<Item> equal_items;
3069 /*
3070 TRUE <-> one of the items is a const item.
3071 Such item is always first in in the equal_items list
3072 */
3073 bool with_const;
3074 /*
3075 The field eval_item is used when this item is evaluated
3076 with the method val_int()
3077 */
3078 cmp_item *eval_item;
3079 /*
3080 This initially is set to FALSE. It becomes TRUE when this item is evaluated
3081 as being always false. If the flag is TRUE the contents of the list
3082 the equal_items should be ignored.
3083 */
3084 bool cond_false;
3085 /*
3086 This initially is set to FALSE. It becomes TRUE when this item is evaluated
3087 as being always true. If the flag is TRUE the contents of the list
3088 the equal_items should be ignored.
3089 */
3090 bool cond_true;
3091 /*
3092 For Item_equal objects inside an OR clause: one of the fields that were
3093 used in the original equality.
3094 */
3095 Item_field *context_field;
3096
3097 bool link_equal_fields;
3098
3099 const Type_handler *m_compare_handler;
3100 CHARSET_INFO *m_compare_collation;
3101 String cmp_value1, cmp_value2;
3102 public:
3103
3104 COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
3105
3106 Item_equal(THD *thd, const Type_handler *handler,
3107 Item *f1, Item *f2, bool with_const_item);
3108 Item_equal(THD *thd, Item_equal *item_equal);
3109 /* Currently the const item is always the first in the list of equal items */
get_const()3110 inline Item* get_const() { return with_const ? equal_items.head() : NULL; }
3111 void add_const(THD *thd, Item *c);
3112 /** Add a non-constant item to the multiple equality */
add(Item * f,MEM_ROOT * root)3113 void add(Item *f, MEM_ROOT *root) { equal_items.push_back(f, root); }
3114 bool contains(Field *field);
3115 Item* get_first(struct st_join_table *context, Item *field);
3116 /** Get number of field items / references to field items in this object */
n_field_items()3117 uint n_field_items() { return equal_items.elements - MY_TEST(with_const); }
3118 void merge(THD *thd, Item_equal *item);
3119 bool merge_with_check(THD *thd, Item_equal *equal_item, bool save_merged);
3120 void merge_into_list(THD *thd, List<Item_equal> *list, bool save_merged,
3121 bool only_intersected);
3122 void update_const(THD *thd);
functype()3123 enum Functype functype() const { return MULT_EQUAL_FUNC; }
3124 longlong val_int();
func_name()3125 const char *func_name() const { return "multiple equal"; }
3126 void sort(Item_field_cmpfunc compare, void *arg);
3127 bool fix_length_and_dec();
3128 bool fix_fields(THD *thd, Item **ref);
cleanup()3129 void cleanup()
3130 {
3131 delete eval_item;
3132 eval_item= NULL;
3133 }
3134 void update_used_tables();
3135 COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
3136 bool link_item_fields,
3137 COND_EQUAL **cond_equal_ref);
3138 void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
3139 uint *and_level, table_map usable_tables,
3140 SARGABLE_PARAM **sargables);
3141 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
3142 bool walk(Item_processor processor, bool walk_subquery, void *arg);
3143 Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
3144 virtual void print(String *str, enum_query_type query_type);
compare_type_handler()3145 const Type_handler *compare_type_handler() const { return m_compare_handler; }
compare_collation()3146 CHARSET_INFO *compare_collation() const { return m_compare_collation; }
3147
set_context_field(Item_field * ctx_field)3148 void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }
set_link_equal_fields(bool flag)3149 void set_link_equal_fields(bool flag) { link_equal_fields= flag; }
get_copy(THD * thd)3150 Item* get_copy(THD *thd) { return 0; }
3151 /*
3152 This does not comply with the specification of the virtual method,
3153 but Item_equal items are processed distinguishly anyway
3154 */
excl_dep_on_table(table_map tab_map)3155 bool excl_dep_on_table(table_map tab_map)
3156 {
3157 return used_tables() & tab_map;
3158 }
3159 friend class Item_equal_fields_iterator;
3160 bool count_sargable_conds(void *arg);
3161 friend class Item_equal_iterator<List_iterator_fast,Item>;
3162 friend class Item_equal_iterator<List_iterator,Item>;
3163 friend Item *eliminate_item_equal(THD *thd, COND *cond,
3164 COND_EQUAL *upper_levels,
3165 Item_equal *item_equal);
3166 friend bool setup_sj_materialization_part1(struct st_join_table *tab);
3167 friend bool setup_sj_materialization_part2(struct st_join_table *tab);
3168 };
3169
3170 class COND_EQUAL: public Sql_alloc
3171 {
3172 public:
3173 uint max_members; /* max number of members the current level
3174 list and all lower level lists */
3175 COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
3176 List<Item_equal> current_level; /* list of multiple equalities of
3177 the current and level */
COND_EQUAL()3178 COND_EQUAL()
3179 {
3180 upper_levels= 0;
3181 }
COND_EQUAL(Item_equal * item,MEM_ROOT * mem_root)3182 COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root)
3183 :upper_levels(0)
3184 {
3185 current_level.push_back(item, mem_root);
3186 }
copy(COND_EQUAL & cond_equal)3187 void copy(COND_EQUAL &cond_equal)
3188 {
3189 max_members= cond_equal.max_members;
3190 upper_levels= cond_equal.upper_levels;
3191 if (cond_equal.current_level.is_empty())
3192 current_level.empty();
3193 else
3194 current_level= cond_equal.current_level;
3195 }
3196 };
3197
3198
3199 /*
3200 The template Item_equal_iterator is used to define classes
3201 Item_equal_fields_iterator and Item_equal_fields_iterator_slow.
3202 These are helper classes for the class Item equal
3203 Both classes are used to iterate over references to table/view columns
3204 from the list of equal items that included in an Item_equal object.
3205 The second class supports the operation of removal of the current member
3206 from the list when performing an iteration.
3207 */
3208
3209 template <template<class> class LI, typename T> class Item_equal_iterator
3210 : public LI<T>
3211 {
3212 protected:
3213 Item_equal *item_equal;
3214 Item *curr_item;
3215 public:
3216 Item_equal_iterator<LI,T>(Item_equal &item_eq)
3217 :LI<T> (item_eq.equal_items)
3218 {
3219 curr_item= NULL;
3220 item_equal= &item_eq;
3221 if (item_eq.with_const)
3222 {
3223 LI<T> *list_it= this;
3224 curr_item= (*list_it)++;
3225 }
3226 }
3227 Item* operator++(int)
3228 {
3229 LI<T> *list_it= this;
3230 curr_item= (*list_it)++;
3231 return curr_item;
3232 }
rewind(void)3233 void rewind(void)
3234 {
3235 LI<T> *list_it= this;
3236 list_it->rewind();
3237 if (item_equal->with_const)
3238 curr_item= (*list_it)++;
3239 }
get_curr_field()3240 Field *get_curr_field()
3241 {
3242 Item_field *item= (Item_field *) (curr_item->real_item());
3243 return item->field;
3244 }
3245 };
3246
3247 typedef Item_equal_iterator<List_iterator_fast,Item > Item_equal_iterator_fast;
3248
3249 class Item_equal_fields_iterator
3250 :public Item_equal_iterator_fast
3251 {
3252 public:
Item_equal_fields_iterator(Item_equal & item_eq)3253 Item_equal_fields_iterator(Item_equal &item_eq)
3254 :Item_equal_iterator_fast(item_eq)
3255 { }
ref()3256 Item ** ref()
3257 {
3258 return List_iterator_fast<Item>::ref();
3259 }
3260 };
3261
3262 typedef Item_equal_iterator<List_iterator,Item > Item_equal_iterator_iterator_slow;
3263
3264 class Item_equal_fields_iterator_slow
3265 :public Item_equal_iterator_iterator_slow
3266 {
3267 public:
Item_equal_fields_iterator_slow(Item_equal & item_eq)3268 Item_equal_fields_iterator_slow(Item_equal &item_eq)
3269 :Item_equal_iterator_iterator_slow(item_eq)
3270 { }
remove()3271 void remove()
3272 {
3273 List_iterator<Item>::remove();
3274 }
3275 };
3276
3277
3278 class Item_cond_and :public Item_cond
3279 {
3280 public:
3281 COND_EQUAL m_cond_equal; /* contains list of Item_equal objects for
3282 the current and level and reference
3283 to multiple equalities of upper and levels */
Item_cond_and(THD * thd)3284 Item_cond_and(THD *thd): Item_cond(thd) {}
Item_cond_and(THD * thd,Item * i1,Item * i2)3285 Item_cond_and(THD *thd, Item *i1,Item *i2): Item_cond(thd, i1, i2) {}
Item_cond_and(THD * thd,Item_cond_and * item)3286 Item_cond_and(THD *thd, Item_cond_and *item): Item_cond(thd, item) {}
Item_cond_and(THD * thd,List<Item> & list_arg)3287 Item_cond_and(THD *thd, List<Item> &list_arg): Item_cond(thd, list_arg) {}
functype()3288 enum Functype functype() const { return COND_AND_FUNC; }
3289 longlong val_int();
func_name()3290 const char *func_name() const { return "and"; }
precedence()3291 enum precedence precedence() const { return AND_PRECEDENCE; }
not_null_tables()3292 table_map not_null_tables() const
3293 { return abort_on_null ? not_null_tables_cache: and_tables_cache; }
3294 Item *copy_andor_structure(THD *thd);
3295 Item *neg_transformer(THD *thd);
3296 void mark_as_condition_AND_part(TABLE_LIST *embedding);
exists2in_reserved_items()3297 virtual uint exists2in_reserved_items() { return list.elements; };
3298 COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
3299 bool link_item_fields,
3300 COND_EQUAL **cond_equal_ref);
3301 void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
3302 table_map usable_tables, SARGABLE_PARAM **sargables);
3303 SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
get_copy(THD * thd)3304 Item *get_copy(THD *thd)
3305 { return get_item_copy<Item_cond_and>(thd, this); }
3306 };
3307
is_cond_and(Item * item)3308 inline bool is_cond_and(Item *item)
3309 {
3310 if (item->type() != Item::COND_ITEM)
3311 return FALSE;
3312
3313 Item_cond *cond_item= (Item_cond*) item;
3314 return (cond_item->functype() == Item_func::COND_AND_FUNC);
3315 }
3316
3317 class Item_cond_or :public Item_cond
3318 {
3319 public:
Item_cond_or(THD * thd)3320 Item_cond_or(THD *thd): Item_cond(thd) {}
Item_cond_or(THD * thd,Item * i1,Item * i2)3321 Item_cond_or(THD *thd, Item *i1,Item *i2): Item_cond(thd, i1, i2) {}
Item_cond_or(THD * thd,Item_cond_or * item)3322 Item_cond_or(THD *thd, Item_cond_or *item): Item_cond(thd, item) {}
Item_cond_or(THD * thd,List<Item> & list_arg)3323 Item_cond_or(THD *thd, List<Item> &list_arg): Item_cond(thd, list_arg) {}
functype()3324 enum Functype functype() const { return COND_OR_FUNC; }
3325 longlong val_int();
func_name()3326 const char *func_name() const { return "or"; }
precedence()3327 enum precedence precedence() const { return OR_PRECEDENCE; }
not_null_tables()3328 table_map not_null_tables() const { return and_tables_cache; }
3329 Item *copy_andor_structure(THD *thd);
3330 Item *neg_transformer(THD *thd);
get_copy(THD * thd)3331 Item *get_copy(THD *thd)
3332 { return get_item_copy<Item_cond_or>(thd, this); }
3333 };
3334
3335 class Item_func_dyncol_check :public Item_bool_func
3336 {
3337 public:
Item_func_dyncol_check(THD * thd,Item * str)3338 Item_func_dyncol_check(THD *thd, Item *str): Item_bool_func(thd, str) {}
3339 longlong val_int();
func_name()3340 const char *func_name() const { return "column_check"; }
need_parentheses_in_default()3341 bool need_parentheses_in_default() { return false; }
get_copy(THD * thd)3342 Item *get_copy(THD *thd)
3343 { return get_item_copy<Item_func_dyncol_check>(thd, this); }
3344 };
3345
3346 class Item_func_dyncol_exists :public Item_bool_func
3347 {
3348 public:
Item_func_dyncol_exists(THD * thd,Item * str,Item * num)3349 Item_func_dyncol_exists(THD *thd, Item *str, Item *num):
3350 Item_bool_func(thd, str, num) {}
3351 longlong val_int();
func_name()3352 const char *func_name() const { return "column_exists"; }
need_parentheses_in_default()3353 bool need_parentheses_in_default() { return false; }
get_copy(THD * thd)3354 Item *get_copy(THD *thd)
3355 { return get_item_copy<Item_func_dyncol_exists>(thd, this); }
3356 };
3357
3358
3359 class Item_func_cursor_bool_attr: public Item_bool_func, public Cursor_ref
3360 {
3361 public:
Item_func_cursor_bool_attr(THD * thd,const LEX_CSTRING * name,uint offset)3362 Item_func_cursor_bool_attr(THD *thd, const LEX_CSTRING *name, uint offset)
3363 :Item_bool_func(thd), Cursor_ref(name, offset)
3364 { }
check_vcol_func_processor(void * arg)3365 bool check_vcol_func_processor(void *arg)
3366 {
3367 return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
3368 }
print(String * str,enum_query_type query_type)3369 void print(String *str, enum_query_type query_type)
3370 {
3371 Cursor_ref::print_func(str, func_name());
3372 }
3373 };
3374
3375
3376 class Item_func_cursor_isopen: public Item_func_cursor_bool_attr
3377 {
3378 public:
Item_func_cursor_isopen(THD * thd,const LEX_CSTRING * name,uint offset)3379 Item_func_cursor_isopen(THD *thd, const LEX_CSTRING *name, uint offset)
3380 :Item_func_cursor_bool_attr(thd, name, offset) { }
func_name()3381 const char *func_name() const { return "%ISOPEN"; }
3382 longlong val_int();
get_copy(THD * thd)3383 Item *get_copy(THD *thd)
3384 { return get_item_copy<Item_func_cursor_isopen>(thd, this); }
3385 };
3386
3387
3388 class Item_func_cursor_found: public Item_func_cursor_bool_attr
3389 {
3390 public:
Item_func_cursor_found(THD * thd,const LEX_CSTRING * name,uint offset)3391 Item_func_cursor_found(THD *thd, const LEX_CSTRING *name, uint offset)
3392 :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
func_name()3393 const char *func_name() const { return "%FOUND"; }
3394 longlong val_int();
get_copy(THD * thd)3395 Item *get_copy(THD *thd)
3396 { return get_item_copy<Item_func_cursor_found>(thd, this); }
3397 };
3398
3399
3400 class Item_func_cursor_notfound: public Item_func_cursor_bool_attr
3401 {
3402 public:
Item_func_cursor_notfound(THD * thd,const LEX_CSTRING * name,uint offset)3403 Item_func_cursor_notfound(THD *thd, const LEX_CSTRING *name, uint offset)
3404 :Item_func_cursor_bool_attr(thd, name, offset) { maybe_null= true; }
func_name()3405 const char *func_name() const { return "%NOTFOUND"; }
3406 longlong val_int();
get_copy(THD * thd)3407 Item *get_copy(THD *thd)
3408 { return get_item_copy<Item_func_cursor_notfound>(thd, this); }
3409 };
3410
3411
3412
is_cond_or(Item * item)3413 inline bool is_cond_or(Item *item)
3414 {
3415 if (item->type() != Item::COND_ITEM)
3416 return FALSE;
3417
3418 Item_cond *cond_item= (Item_cond*) item;
3419 return (cond_item->functype() == Item_func::COND_OR_FUNC);
3420 }
3421
3422 Item *and_expressions(Item *a, Item *b, Item **org_item);
3423
3424 class Comp_creator
3425 {
3426 public:
Comp_creator()3427 Comp_creator() {} /* Remove gcc warning */
~Comp_creator()3428 virtual ~Comp_creator() {} /* Remove gcc warning */
3429 /**
3430 Create operation with given arguments.
3431 */
3432 virtual Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b)
3433 const = 0;
3434 /**
3435 Create operation with given arguments in swap order.
3436 */
3437 virtual Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b)
3438 const = 0;
3439 virtual const char* symbol(bool invert) const = 0;
3440 virtual bool eqne_op() const = 0;
3441 virtual bool l_op() const = 0;
3442 };
3443
3444 class Eq_creator :public Comp_creator
3445 {
3446 public:
Eq_creator()3447 Eq_creator() {} /* Remove gcc warning */
~Eq_creator()3448 virtual ~Eq_creator() {} /* Remove gcc warning */
3449 Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const;
3450 Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const;
symbol(bool invert)3451 const char* symbol(bool invert) const { return invert? "<>" : "="; }
eqne_op()3452 bool eqne_op() const { return 1; }
l_op()3453 bool l_op() const { return 0; }
3454 };
3455
3456 class Ne_creator :public Comp_creator
3457 {
3458 public:
Ne_creator()3459 Ne_creator() {} /* Remove gcc warning */
~Ne_creator()3460 virtual ~Ne_creator() {} /* Remove gcc warning */
3461 Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const;
3462 Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const;
symbol(bool invert)3463 const char* symbol(bool invert) const { return invert? "=" : "<>"; }
eqne_op()3464 bool eqne_op() const { return 1; }
l_op()3465 bool l_op() const { return 0; }
3466 };
3467
3468 class Gt_creator :public Comp_creator
3469 {
3470 public:
Gt_creator()3471 Gt_creator() {} /* Remove gcc warning */
~Gt_creator()3472 virtual ~Gt_creator() {} /* Remove gcc warning */
3473 Item_bool_rowready_func2* create(THD *thd, Item *a, Item *b) const;
3474 Item_bool_rowready_func2* create_swap(THD *thd, Item *a, Item *b) const;
symbol(bool invert)3475 const char* symbol(bool invert) const { return invert? "<=" : ">"; }
eqne_op()3476