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