1 | /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. |
2 | Copyright (c) 2009, 2016, MariaDB |
3 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | it under the terms of the GNU General Public License as published by |
6 | the Free Software Foundation; version 2 of the License. |
7 | |
8 | This program is distributed in the hope that it will be useful, |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | GNU General Public License for more details. |
12 | |
13 | You should have received a copy of the GNU General Public License |
14 | along with this program; if not, write to the Free Software |
15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ |
16 | |
17 | |
18 | /** |
19 | @file |
20 | |
21 | @brief |
22 | This file defines all compare functions |
23 | */ |
24 | |
25 | #ifdef USE_PRAGMA_IMPLEMENTATION |
26 | #pragma implementation // gcc: Class implementation |
27 | #endif |
28 | |
29 | #include "mariadb.h" |
30 | #include "sql_priv.h" |
31 | #include <m_ctype.h> |
32 | #include "sql_select.h" |
33 | #include "sql_parse.h" // check_stack_overrun |
34 | #include "sql_time.h" // make_truncated_value_warning |
35 | #include "sql_base.h" // dynamic_column_error_message |
36 | |
37 | /** |
38 | find an temporal type (item) that others will be converted to |
39 | for the purpose of comparison. |
40 | |
41 | this is the type that will be used in warnings like |
42 | "Incorrect <<TYPE>> value". |
43 | */ |
44 | static Item *find_date_time_item(Item **args, uint nargs, uint col) |
45 | { |
46 | Item *date_arg= 0, **arg, **arg_end; |
47 | for (arg= args, arg_end= args + nargs; arg != arg_end ; arg++) |
48 | { |
49 | Item *item= arg[0]->element_index(col); |
50 | if (item->cmp_type() != TIME_RESULT) |
51 | continue; |
52 | if (item->field_type() == MYSQL_TYPE_DATETIME) |
53 | return item; |
54 | if (!date_arg) |
55 | date_arg= item; |
56 | } |
57 | return date_arg; |
58 | } |
59 | |
60 | |
61 | /* |
62 | Compare row signature of two expressions |
63 | |
64 | SYNOPSIS: |
65 | cmp_row_type() |
66 | item1 the first expression |
67 | item2 the second expression |
68 | |
69 | DESCRIPTION |
70 | The function checks that two expressions have compatible row signatures |
71 | i.e. that the number of columns they return are the same and that if they |
72 | are both row expressions then each component from the first expression has |
73 | a row signature compatible with the signature of the corresponding component |
74 | of the second expression. |
75 | |
76 | RETURN VALUES |
77 | 1 type incompatibility has been detected |
78 | 0 otherwise |
79 | */ |
80 | |
81 | static int cmp_row_type(Item* item1, Item* item2) |
82 | { |
83 | uint n= item1->cols(); |
84 | if (item2->check_cols(n)) |
85 | return 1; |
86 | for (uint i=0; i<n; i++) |
87 | { |
88 | if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) || |
89 | (item1->element_index(i)->result_type() == ROW_RESULT && |
90 | cmp_row_type(item1->element_index(i), item2->element_index(i)))) |
91 | return 1; |
92 | } |
93 | return 0; |
94 | } |
95 | |
96 | |
97 | /** |
98 | Aggregates result types from the array of items. |
99 | |
100 | This method aggregates comparison handler from the array of items. |
101 | The result handler is used later for comparison of values of these items. |
102 | |
103 | aggregate_for_comparison() |
104 | funcname the function or operator name, |
105 | for error reporting |
106 | items array of items to aggregate the type from |
107 | nitems number of items in the array |
108 | int_uint_as_dec what to do when comparing INT to UINT: |
109 | set the comparison handler to decimal or int. |
110 | |
111 | @retval true type incompatibility has been detected |
112 | @retval false otherwise |
113 | */ |
114 | |
115 | bool |
116 | Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname, |
117 | Item **items, |
118 | uint nitems, |
119 | bool int_uint_as_dec) |
120 | { |
121 | uint unsigned_count= items[0]->unsigned_flag; |
122 | /* |
123 | Convert sub-type to super-type (e.g. DATE to DATETIME, INT to BIGINT, etc). |
124 | Otherwise Predicant_to_list_comparator will treat sub-types of the same |
125 | super-type as different data types and won't be able to use bisection in |
126 | many cases. |
127 | */ |
128 | set_handler(items[0]->type_handler()->type_handler_for_comparison()); |
129 | for (uint i= 1 ; i < nitems ; i++) |
130 | { |
131 | unsigned_count+= items[i]->unsigned_flag; |
132 | if (aggregate_for_comparison(items[i]->type_handler()-> |
133 | type_handler_for_comparison())) |
134 | { |
135 | /* |
136 | For more precise error messages if aggregation failed on the first pair |
137 | {items[0],items[1]}, use the name of items[0]->data_handler(). |
138 | Otherwise use the name of this->type_handler(), which is already a |
139 | result of aggregation for items[0]..items[i-1]. |
140 | */ |
141 | my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0), |
142 | i == 1 ? items[0]->type_handler()->name().ptr() : |
143 | type_handler()->name().ptr(), |
144 | items[i]->type_handler()->name().ptr(), |
145 | funcname); |
146 | return true; |
147 | } |
148 | /* |
149 | When aggregating types of two row expressions we have to check |
150 | that they have the same cardinality and that each component |
151 | of the first row expression has a compatible row signature with |
152 | the signature of the corresponding component of the second row |
153 | expression. |
154 | */ |
155 | if (cmp_type() == ROW_RESULT && cmp_row_type(items[0], items[i])) |
156 | return true; // error found: invalid usage of rows |
157 | } |
158 | /** |
159 | If all arguments are of INT type but have different unsigned_flag values, |
160 | switch to DECIMAL_RESULT. |
161 | */ |
162 | if (int_uint_as_dec && |
163 | cmp_type() == INT_RESULT && |
164 | unsigned_count != nitems && unsigned_count != 0) |
165 | set_handler(&type_handler_newdecimal); |
166 | return 0; |
167 | } |
168 | |
169 | |
170 | /* |
171 | Collects different types for comparison of first item with each other items |
172 | |
173 | SYNOPSIS |
174 | collect_cmp_types() |
175 | items Array of items to collect types from |
176 | nitems Number of items in the array |
177 | skip_nulls Don't collect types of NULL items if TRUE |
178 | |
179 | DESCRIPTION |
180 | This function collects different result types for comparison of the first |
181 | item in the list with each of the remaining items in the 'items' array. |
182 | |
183 | RETURN |
184 | 0 - if row type incompatibility has been detected (see cmp_row_type) |
185 | Bitmap of collected types - otherwise |
186 | */ |
187 | |
188 | static uint collect_cmp_types(Item **items, uint nitems, bool skip_nulls= FALSE) |
189 | { |
190 | uint i; |
191 | uint found_types; |
192 | Item_result left_cmp_type= items[0]->cmp_type(); |
193 | DBUG_ASSERT(nitems > 1); |
194 | found_types= 0; |
195 | for (i= 1; i < nitems ; i++) |
196 | { |
197 | if (skip_nulls && items[i]->type() == Item::NULL_ITEM) |
198 | continue; // Skip NULL constant items |
199 | if ((left_cmp_type == ROW_RESULT || |
200 | items[i]->cmp_type() == ROW_RESULT) && |
201 | cmp_row_type(items[0], items[i])) |
202 | return 0; |
203 | found_types|= 1U << (uint) item_cmp_type(left_cmp_type, items[i]); |
204 | } |
205 | /* |
206 | Even if all right-hand items are NULLs and we are skipping them all, we need |
207 | at least one type bit in the found_type bitmask. |
208 | */ |
209 | if (skip_nulls && !found_types) |
210 | found_types= 1U << (uint) left_cmp_type; |
211 | return found_types; |
212 | } |
213 | |
214 | |
215 | /* |
216 | Test functions |
217 | Most of these returns 0LL if false and 1LL if true and |
218 | NULL if some arg is NULL. |
219 | */ |
220 | |
221 | longlong Item_func_not::val_int() |
222 | { |
223 | DBUG_ASSERT(fixed == 1); |
224 | bool value= args[0]->val_bool(); |
225 | null_value=args[0]->null_value; |
226 | return ((!null_value && value == 0) ? 1 : 0); |
227 | } |
228 | |
229 | void Item_func_not::print(String *str, enum_query_type query_type) |
230 | { |
231 | str->append('!'); |
232 | args[0]->print_parenthesised(str, query_type, precedence()); |
233 | } |
234 | |
235 | /** |
236 | special NOT for ALL subquery. |
237 | */ |
238 | |
239 | |
240 | longlong Item_func_not_all::val_int() |
241 | { |
242 | DBUG_ASSERT(fixed == 1); |
243 | bool value= args[0]->val_bool(); |
244 | |
245 | /* |
246 | return TRUE if there was records in underlying select in max/min |
247 | optimization (ALL subquery) |
248 | */ |
249 | if (empty_underlying_subquery()) |
250 | return 1; |
251 | |
252 | null_value= args[0]->null_value; |
253 | return ((!null_value && value == 0) ? 1 : 0); |
254 | } |
255 | |
256 | |
257 | bool Item_func_not_all::empty_underlying_subquery() |
258 | { |
259 | return ((test_sum_item && !test_sum_item->any_value()) || |
260 | (test_sub_item && !test_sub_item->any_value())); |
261 | } |
262 | |
263 | void Item_func_not_all::print(String *str, enum_query_type query_type) |
264 | { |
265 | if (show) |
266 | Item_func::print(str, query_type); |
267 | else |
268 | args[0]->print(str, query_type); |
269 | } |
270 | |
271 | |
272 | /** |
273 | Special NOP (No OPeration) for ALL subquery. It is like |
274 | Item_func_not_all. |
275 | |
276 | @return |
277 | (return TRUE if underlying subquery do not return rows) but if subquery |
278 | returns some rows it return same value as argument (TRUE/FALSE). |
279 | */ |
280 | |
281 | longlong Item_func_nop_all::val_int() |
282 | { |
283 | DBUG_ASSERT(fixed == 1); |
284 | longlong value= args[0]->val_int(); |
285 | |
286 | /* |
287 | return FALSE if there was records in underlying select in max/min |
288 | optimization (SAME/ANY subquery) |
289 | */ |
290 | if (empty_underlying_subquery()) |
291 | return 0; |
292 | |
293 | null_value= args[0]->null_value; |
294 | return (null_value || value == 0) ? 0 : 1; |
295 | } |
296 | |
297 | |
298 | /** |
299 | Convert a constant item to an int and replace the original item. |
300 | |
301 | The function converts a constant expression or string to an integer. |
302 | On successful conversion the original item is substituted for the |
303 | result of the item evaluation. |
304 | This is done when comparing DATE/TIME of different formats and |
305 | also when comparing bigint to strings (in which case strings |
306 | are converted to bigints). |
307 | |
308 | @param thd thread handle |
309 | @param field item will be converted using the type of this field |
310 | @param[in,out] item reference to the item to convert |
311 | |
312 | @note |
313 | This function is called only at prepare stage. |
314 | As all derived tables are filled only after all derived tables |
315 | are prepared we do not evaluate items with subselects here because |
316 | they can contain derived tables and thus we may attempt to use a |
317 | table that has not been populated yet. |
318 | |
319 | @retval |
320 | 0 Can't convert item |
321 | @retval |
322 | 1 Item was replaced with an integer version of the item |
323 | */ |
324 | |
325 | static bool convert_const_to_int(THD *thd, Item_field *field_item, |
326 | Item **item) |
327 | { |
328 | Field *field= field_item->field; |
329 | int result= 0; |
330 | |
331 | /* |
332 | We don't need to convert an integer to an integer, |
333 | pretend it's already converted. |
334 | |
335 | But we still convert it if it is compared with a Field_year, |
336 | as YEAR(2) may change the value of an integer when converting it |
337 | to an integer (say, 0 to 70). |
338 | */ |
339 | if ((*item)->cmp_type() == INT_RESULT && |
340 | field_item->field_type() != MYSQL_TYPE_YEAR) |
341 | return 1; |
342 | |
343 | if ((*item)->const_item() && !(*item)->is_expensive()) |
344 | { |
345 | TABLE *table= field->table; |
346 | sql_mode_t orig_sql_mode= thd->variables.sql_mode; |
347 | enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; |
348 | my_bitmap_map *old_maps[2]; |
349 | ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ |
350 | |
351 | LINT_INIT_STRUCT(old_maps); |
352 | |
353 | /* table->read_set may not be set if we come here from a CREATE TABLE */ |
354 | if (table && table->read_set) |
355 | dbug_tmp_use_all_columns(table, old_maps, |
356 | table->read_set, table->write_set); |
357 | /* For comparison purposes allow invalid dates like 2000-01-32 */ |
358 | thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | |
359 | MODE_INVALID_DATES; |
360 | thd->count_cuted_fields= CHECK_FIELD_IGNORE; |
361 | |
362 | /* |
363 | Store the value of the field/constant because the call to save_in_field |
364 | below overrides that value. Don't save field value if no data has been |
365 | read yet. |
366 | */ |
367 | bool save_field_value= (field_item->const_item() || |
368 | !(field->table->status & STATUS_NO_RECORD)); |
369 | if (save_field_value) |
370 | orig_field_val= field->val_int(); |
371 | if (!(*item)->save_in_field(field, 1) && !field->is_null()) |
372 | { |
373 | int field_cmp= 0; |
374 | // If item is a decimal value, we must reject it if it was truncated. |
375 | if (field->type() == MYSQL_TYPE_LONGLONG) |
376 | { |
377 | field_cmp= stored_field_cmp_to_item(thd, field, *item); |
378 | DBUG_PRINT("info" , ("convert_const_to_int %d" , field_cmp)); |
379 | } |
380 | |
381 | if (0 == field_cmp) |
382 | { |
383 | Item *tmp= new (thd->mem_root) Item_int_with_ref(thd, field->val_int(), *item, |
384 | MY_TEST(field->flags & UNSIGNED_FLAG)); |
385 | if (tmp) |
386 | thd->change_item_tree(item, tmp); |
387 | result= 1; // Item was replaced |
388 | } |
389 | } |
390 | /* Restore the original field value. */ |
391 | if (save_field_value) |
392 | { |
393 | result= field->store(orig_field_val, TRUE); |
394 | /* orig_field_val must be a valid value that can be restored back. */ |
395 | DBUG_ASSERT(!result); |
396 | } |
397 | thd->variables.sql_mode= orig_sql_mode; |
398 | thd->count_cuted_fields= orig_count_cuted_fields; |
399 | if (table && table->read_set) |
400 | dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_maps); |
401 | } |
402 | return result; |
403 | } |
404 | |
405 | |
406 | /* |
407 | Make a special case of compare with fields to get nicer comparisons |
408 | of bigint numbers with constant string. |
409 | This directly contradicts the manual (number and a string should |
410 | be compared as doubles), but seems to provide more |
411 | "intuitive" behavior in some cases (but less intuitive in others). |
412 | */ |
413 | void Item_func::convert_const_compared_to_int_field(THD *thd) |
414 | { |
415 | DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3 |
416 | if (!thd->lex->is_ps_or_view_context_analysis()) |
417 | { |
418 | int field; |
419 | if (args[field= 0]->real_item()->type() == FIELD_ITEM || |
420 | args[field= 1]->real_item()->type() == FIELD_ITEM) |
421 | { |
422 | Item_field *field_item= (Item_field*) (args[field]->real_item()); |
423 | if (((field_item->field_type() == MYSQL_TYPE_LONGLONG && |
424 | field_item->type_handler() != &type_handler_vers_trx_id) || |
425 | field_item->field_type() == MYSQL_TYPE_YEAR)) |
426 | convert_const_to_int(thd, field_item, &args[!field]); |
427 | } |
428 | } |
429 | } |
430 | |
431 | |
432 | bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) |
433 | { |
434 | DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3 |
435 | |
436 | if (args[0]->cmp_type() == STRING_RESULT && |
437 | args[1]->cmp_type() == STRING_RESULT) |
438 | { |
439 | DTCollation tmp; |
440 | if (agg_arg_charsets_for_comparison(tmp, args, 2)) |
441 | return true; |
442 | cmp->m_compare_collation= tmp.collation; |
443 | } |
444 | // Convert constants when compared to int/year field |
445 | DBUG_ASSERT(functype() != LIKE_FUNC); |
446 | convert_const_compared_to_int_field(thd); |
447 | |
448 | return cmp->set_cmp_func(this, &args[0], &args[1], true); |
449 | } |
450 | |
451 | |
452 | void Item_bool_rowready_func2::fix_length_and_dec() |
453 | { |
454 | max_length= 1; // Function returns 0 or 1 |
455 | |
456 | /* |
457 | As some compare functions are generated after sql_yacc, |
458 | we have to check for out of memory conditions here |
459 | */ |
460 | if (!args[0] || !args[1]) |
461 | return; |
462 | setup_args_and_comparator(current_thd, &cmp); |
463 | } |
464 | |
465 | |
466 | /** |
467 | Prepare the comparator (set the comparison function) for comparing |
468 | items *a1 and *a2 in the context of 'type'. |
469 | |
470 | @param[in] owner_arg Item, peforming the comparison (e.g. Item_func_eq) |
471 | @param[in,out] a1 first argument to compare |
472 | @param[in,out] a2 second argument to compare |
473 | @param[in] type type context to compare in |
474 | |
475 | Both *a1 and *a2 can be replaced by this method - typically by constant |
476 | items, holding the cached converted value of the original (constant) item. |
477 | */ |
478 | |
479 | int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg, |
480 | Item **a1, Item **a2) |
481 | { |
482 | owner= owner_arg; |
483 | set_null= set_null && owner_arg; |
484 | a= a1; |
485 | b= a2; |
486 | Item *tmp_args[2]= {*a1, *a2}; |
487 | Type_handler_hybrid_field_type tmp; |
488 | if (tmp.aggregate_for_comparison(owner_arg->func_name(), tmp_args, 2, false)) |
489 | { |
490 | DBUG_ASSERT(current_thd->is_error()); |
491 | return 1; |
492 | } |
493 | m_compare_handler= tmp.type_handler(); |
494 | return m_compare_handler->set_comparator_func(this); |
495 | } |
496 | |
497 | |
498 | bool Arg_comparator::set_cmp_func_for_row_arguments() |
499 | { |
500 | uint n= (*a)->cols(); |
501 | if (n != (*b)->cols()) |
502 | { |
503 | my_error(ER_OPERAND_COLUMNS, MYF(0), n); |
504 | comparators= 0; |
505 | return true; |
506 | } |
507 | if (!(comparators= new Arg_comparator[n])) |
508 | return true; |
509 | for (uint i=0; i < n; i++) |
510 | { |
511 | if ((*a)->element_index(i)->cols() != (*b)->element_index(i)->cols()) |
512 | { |
513 | my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); |
514 | return true; |
515 | } |
516 | if (comparators[i].set_cmp_func(owner, (*a)->addr(i), |
517 | (*b)->addr(i), set_null)) |
518 | return true; |
519 | } |
520 | return false; |
521 | } |
522 | |
523 | |
524 | bool Arg_comparator::set_cmp_func_row() |
525 | { |
526 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_row : |
527 | &Arg_comparator::compare_row; |
528 | return set_cmp_func_for_row_arguments(); |
529 | } |
530 | |
531 | |
532 | bool Arg_comparator::set_cmp_func_string() |
533 | { |
534 | THD *thd= current_thd; |
535 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_string : |
536 | &Arg_comparator::compare_string; |
537 | if (compare_type() == STRING_RESULT && |
538 | (*a)->result_type() == STRING_RESULT && |
539 | (*b)->result_type() == STRING_RESULT) |
540 | { |
541 | /* |
542 | We must set cmp_collation here as we may be called from for an automatic |
543 | generated item, like in natural join |
544 | */ |
545 | if (owner->agg_arg_charsets_for_comparison(&m_compare_collation, a, b)) |
546 | return true; |
547 | |
548 | if ((*a)->type() == Item::FUNC_ITEM && |
549 | ((Item_func *) (*a))->functype() == Item_func::JSON_EXTRACT_FUNC) |
550 | { |
551 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str: |
552 | &Arg_comparator::compare_json_str; |
553 | return 0; |
554 | } |
555 | else if ((*b)->type() == Item::FUNC_ITEM && |
556 | ((Item_func *) (*b))->functype() == Item_func::JSON_EXTRACT_FUNC) |
557 | { |
558 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_json_str: |
559 | &Arg_comparator::compare_str_json; |
560 | return 0; |
561 | } |
562 | } |
563 | |
564 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
565 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
566 | return false; |
567 | } |
568 | |
569 | |
570 | bool Arg_comparator::set_cmp_func_time() |
571 | { |
572 | THD *thd= current_thd; |
573 | m_compare_collation= &my_charset_numeric; |
574 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_time : |
575 | &Arg_comparator::compare_time; |
576 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
577 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
578 | return false; |
579 | } |
580 | |
581 | |
582 | bool Arg_comparator::set_cmp_func_datetime() |
583 | { |
584 | THD *thd= current_thd; |
585 | m_compare_collation= &my_charset_numeric; |
586 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime : |
587 | &Arg_comparator::compare_datetime; |
588 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
589 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
590 | return false; |
591 | } |
592 | |
593 | |
594 | bool Arg_comparator::set_cmp_func_int() |
595 | { |
596 | THD *thd= current_thd; |
597 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_int : |
598 | &Arg_comparator::compare_int_signed; |
599 | if ((*a)->field_type() == MYSQL_TYPE_YEAR && |
600 | (*b)->field_type() == MYSQL_TYPE_YEAR) |
601 | { |
602 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime : |
603 | &Arg_comparator::compare_datetime; |
604 | } |
605 | else if (func == &Arg_comparator::compare_int_signed) |
606 | { |
607 | if ((*a)->unsigned_flag) |
608 | func= (((*b)->unsigned_flag)? |
609 | &Arg_comparator::compare_int_unsigned : |
610 | &Arg_comparator::compare_int_unsigned_signed); |
611 | else if ((*b)->unsigned_flag) |
612 | func= &Arg_comparator::compare_int_signed_unsigned; |
613 | } |
614 | else if (func== &Arg_comparator::compare_e_int) |
615 | { |
616 | if ((*a)->unsigned_flag ^ (*b)->unsigned_flag) |
617 | func= &Arg_comparator::compare_e_int_diff_signedness; |
618 | } |
619 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
620 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
621 | return false; |
622 | } |
623 | |
624 | |
625 | bool Arg_comparator::set_cmp_func_real() |
626 | { |
627 | if ((((*a)->result_type() == DECIMAL_RESULT && !(*a)->const_item() && |
628 | (*b)->result_type() == STRING_RESULT && (*b)->const_item()) || |
629 | ((*b)->result_type() == DECIMAL_RESULT && !(*b)->const_item() && |
630 | (*a)->result_type() == STRING_RESULT && (*a)->const_item()))) |
631 | { |
632 | /* |
633 | <non-const decimal expression> <cmp> <const string expression> |
634 | or |
635 | <const string expression> <cmp> <non-const decimal expression> |
636 | |
637 | Do comparison as decimal rather than float, in order not to lose precision. |
638 | */ |
639 | m_compare_handler= &type_handler_newdecimal; |
640 | return set_cmp_func_decimal(); |
641 | } |
642 | |
643 | THD *thd= current_thd; |
644 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_real : |
645 | &Arg_comparator::compare_real; |
646 | if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC) |
647 | { |
648 | precision= 5 / log_10[MY_MAX((*a)->decimals, (*b)->decimals) + 1]; |
649 | if (func == &Arg_comparator::compare_real) |
650 | func= &Arg_comparator::compare_real_fixed; |
651 | else if (func == &Arg_comparator::compare_e_real) |
652 | func= &Arg_comparator::compare_e_real_fixed; |
653 | } |
654 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
655 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
656 | return false; |
657 | } |
658 | |
659 | bool Arg_comparator::set_cmp_func_decimal() |
660 | { |
661 | THD *thd= current_thd; |
662 | func= is_owner_equal_func() ? &Arg_comparator::compare_e_decimal : |
663 | &Arg_comparator::compare_decimal; |
664 | a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); |
665 | b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); |
666 | return false; |
667 | } |
668 | |
669 | |
670 | /** |
671 | Convert and cache a constant. |
672 | |
673 | @param value [in] An item to cache |
674 | @param cache_item [out] Placeholder for the cache item |
675 | @param type [in] Comparison type |
676 | |
677 | @details |
678 | When given item is a constant and its type differs from comparison type |
679 | then cache its value to avoid type conversion of this constant on each |
680 | evaluation. In this case the value is cached and the reference to the cache |
681 | is returned. |
682 | Original value is returned otherwise. |
683 | |
684 | @return cache item or original value. |
685 | */ |
686 | |
687 | Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value, |
688 | Item **cache_item, |
689 | const Type_handler *handler) |
690 | { |
691 | /* |
692 | Don't need cache if doing context analysis only. |
693 | */ |
694 | if (!thd_arg->lex->is_ps_or_view_context_analysis() && |
695 | (*value)->const_item() && |
696 | handler->type_handler_for_comparison() != |
697 | (*value)->type_handler_for_comparison()) |
698 | { |
699 | Item_cache *cache= handler->Item_get_cache(thd_arg, *value); |
700 | cache->setup(thd_arg, *value); |
701 | *cache_item= cache; |
702 | return cache_item; |
703 | } |
704 | return value; |
705 | } |
706 | |
707 | |
708 | int Arg_comparator::compare_time() |
709 | { |
710 | longlong val1= (*a)->val_time_packed(); |
711 | if (!(*a)->null_value) |
712 | { |
713 | longlong val2= (*b)->val_time_packed(); |
714 | if (!(*b)->null_value) |
715 | return compare_not_null_values(val1, val2); |
716 | } |
717 | if (set_null) |
718 | owner->null_value= true; |
719 | return -1; |
720 | } |
721 | |
722 | |
723 | int Arg_comparator::compare_e_time() |
724 | { |
725 | longlong val1= (*a)->val_time_packed(); |
726 | longlong val2= (*b)->val_time_packed(); |
727 | if ((*a)->null_value || (*b)->null_value) |
728 | return MY_TEST((*a)->null_value && (*b)->null_value); |
729 | return MY_TEST(val1 == val2); |
730 | } |
731 | |
732 | |
733 | |
734 | int Arg_comparator::compare_datetime() |
735 | { |
736 | longlong val1= (*a)->val_datetime_packed(); |
737 | if (!(*a)->null_value) |
738 | { |
739 | longlong val2= (*b)->val_datetime_packed(); |
740 | if (!(*b)->null_value) |
741 | return compare_not_null_values(val1, val2); |
742 | } |
743 | if (set_null) |
744 | owner->null_value= true; |
745 | return -1; |
746 | } |
747 | |
748 | |
749 | int Arg_comparator::compare_e_datetime() |
750 | { |
751 | longlong val1= (*a)->val_datetime_packed(); |
752 | longlong val2= (*b)->val_datetime_packed(); |
753 | if ((*a)->null_value || (*b)->null_value) |
754 | return MY_TEST((*a)->null_value && (*b)->null_value); |
755 | return MY_TEST(val1 == val2); |
756 | } |
757 | |
758 | |
759 | int Arg_comparator::compare_string() |
760 | { |
761 | String *res1,*res2; |
762 | if ((res1= (*a)->val_str(&value1))) |
763 | { |
764 | if ((res2= (*b)->val_str(&value2))) |
765 | { |
766 | if (set_null) |
767 | owner->null_value= 0; |
768 | return sortcmp(res1, res2, compare_collation()); |
769 | } |
770 | } |
771 | if (set_null) |
772 | owner->null_value= 1; |
773 | return -1; |
774 | } |
775 | |
776 | |
777 | /** |
778 | Compare strings, but take into account that NULL == NULL. |
779 | */ |
780 | |
781 | |
782 | int Arg_comparator::compare_e_string() |
783 | { |
784 | String *res1,*res2; |
785 | res1= (*a)->val_str(&value1); |
786 | res2= (*b)->val_str(&value2); |
787 | if (!res1 || !res2) |
788 | return MY_TEST(res1 == res2); |
789 | return MY_TEST(sortcmp(res1, res2, compare_collation()) == 0); |
790 | } |
791 | |
792 | |
793 | int Arg_comparator::compare_real() |
794 | { |
795 | /* |
796 | Fix yet another manifestation of Bug#2338. 'Volatile' will instruct |
797 | gcc to flush double values out of 80-bit Intel FPU registers before |
798 | performing the comparison. |
799 | */ |
800 | volatile double val1, val2; |
801 | val1= (*a)->val_real(); |
802 | if (!(*a)->null_value) |
803 | { |
804 | val2= (*b)->val_real(); |
805 | if (!(*b)->null_value) |
806 | { |
807 | if (set_null) |
808 | owner->null_value= 0; |
809 | if (val1 < val2) return -1; |
810 | if (val1 == val2) return 0; |
811 | return 1; |
812 | } |
813 | } |
814 | if (set_null) |
815 | owner->null_value= 1; |
816 | return -1; |
817 | } |
818 | |
819 | int Arg_comparator::compare_decimal() |
820 | { |
821 | my_decimal decimal1; |
822 | my_decimal *val1= (*a)->val_decimal(&decimal1); |
823 | if (!(*a)->null_value) |
824 | { |
825 | my_decimal decimal2; |
826 | my_decimal *val2= (*b)->val_decimal(&decimal2); |
827 | if (!(*b)->null_value) |
828 | { |
829 | if (set_null) |
830 | owner->null_value= 0; |
831 | return my_decimal_cmp(val1, val2); |
832 | } |
833 | } |
834 | if (set_null) |
835 | owner->null_value= 1; |
836 | return -1; |
837 | } |
838 | |
839 | int Arg_comparator::compare_e_real() |
840 | { |
841 | double val1= (*a)->val_real(); |
842 | double val2= (*b)->val_real(); |
843 | if ((*a)->null_value || (*b)->null_value) |
844 | return MY_TEST((*a)->null_value && (*b)->null_value); |
845 | return MY_TEST(val1 == val2); |
846 | } |
847 | |
848 | int Arg_comparator::compare_e_decimal() |
849 | { |
850 | my_decimal decimal1, decimal2; |
851 | my_decimal *val1= (*a)->val_decimal(&decimal1); |
852 | my_decimal *val2= (*b)->val_decimal(&decimal2); |
853 | if ((*a)->null_value || (*b)->null_value) |
854 | return MY_TEST((*a)->null_value && (*b)->null_value); |
855 | return MY_TEST(my_decimal_cmp(val1, val2) == 0); |
856 | } |
857 | |
858 | |
859 | int Arg_comparator::compare_real_fixed() |
860 | { |
861 | /* |
862 | Fix yet another manifestation of Bug#2338. 'Volatile' will instruct |
863 | gcc to flush double values out of 80-bit Intel FPU registers before |
864 | performing the comparison. |
865 | */ |
866 | volatile double val1, val2; |
867 | val1= (*a)->val_real(); |
868 | if (!(*a)->null_value) |
869 | { |
870 | val2= (*b)->val_real(); |
871 | if (!(*b)->null_value) |
872 | { |
873 | if (set_null) |
874 | owner->null_value= 0; |
875 | if (val1 == val2 || fabs(val1 - val2) < precision) |
876 | return 0; |
877 | if (val1 < val2) |
878 | return -1; |
879 | return 1; |
880 | } |
881 | } |
882 | if (set_null) |
883 | owner->null_value= 1; |
884 | return -1; |
885 | } |
886 | |
887 | |
888 | int Arg_comparator::compare_e_real_fixed() |
889 | { |
890 | double val1= (*a)->val_real(); |
891 | double val2= (*b)->val_real(); |
892 | if ((*a)->null_value || (*b)->null_value) |
893 | return MY_TEST((*a)->null_value && (*b)->null_value); |
894 | return MY_TEST(val1 == val2 || fabs(val1 - val2) < precision); |
895 | } |
896 | |
897 | |
898 | int Arg_comparator::compare_int_signed() |
899 | { |
900 | longlong val1= (*a)->val_int(); |
901 | if (!(*a)->null_value) |
902 | { |
903 | longlong val2= (*b)->val_int(); |
904 | if (!(*b)->null_value) |
905 | return compare_not_null_values(val1, val2); |
906 | } |
907 | if (set_null) |
908 | owner->null_value= 1; |
909 | return -1; |
910 | } |
911 | |
912 | |
913 | /** |
914 | Compare values as BIGINT UNSIGNED. |
915 | */ |
916 | |
917 | int Arg_comparator::compare_int_unsigned() |
918 | { |
919 | ulonglong val1= (*a)->val_int(); |
920 | if (!(*a)->null_value) |
921 | { |
922 | ulonglong val2= (*b)->val_int(); |
923 | if (!(*b)->null_value) |
924 | { |
925 | if (set_null) |
926 | owner->null_value= 0; |
927 | if (val1 < val2) return -1; |
928 | if (val1 == val2) return 0; |
929 | return 1; |
930 | } |
931 | } |
932 | if (set_null) |
933 | owner->null_value= 1; |
934 | return -1; |
935 | } |
936 | |
937 | |
938 | /** |
939 | Compare signed (*a) with unsigned (*B) |
940 | */ |
941 | |
942 | int Arg_comparator::compare_int_signed_unsigned() |
943 | { |
944 | longlong sval1= (*a)->val_int(); |
945 | if (!(*a)->null_value) |
946 | { |
947 | ulonglong uval2= (ulonglong)(*b)->val_int(); |
948 | if (!(*b)->null_value) |
949 | { |
950 | if (set_null) |
951 | owner->null_value= 0; |
952 | if (sval1 < 0 || (ulonglong)sval1 < uval2) |
953 | return -1; |
954 | if ((ulonglong)sval1 == uval2) |
955 | return 0; |
956 | return 1; |
957 | } |
958 | } |
959 | if (set_null) |
960 | owner->null_value= 1; |
961 | return -1; |
962 | } |
963 | |
964 | |
965 | /** |
966 | Compare unsigned (*a) with signed (*B) |
967 | */ |
968 | |
969 | int Arg_comparator::compare_int_unsigned_signed() |
970 | { |
971 | ulonglong uval1= (ulonglong)(*a)->val_int(); |
972 | if (!(*a)->null_value) |
973 | { |
974 | longlong sval2= (*b)->val_int(); |
975 | if (!(*b)->null_value) |
976 | { |
977 | if (set_null) |
978 | owner->null_value= 0; |
979 | if (sval2 < 0) |
980 | return 1; |
981 | if (uval1 < (ulonglong)sval2) |
982 | return -1; |
983 | if (uval1 == (ulonglong)sval2) |
984 | return 0; |
985 | return 1; |
986 | } |
987 | } |
988 | if (set_null) |
989 | owner->null_value= 1; |
990 | return -1; |
991 | } |
992 | |
993 | |
994 | int Arg_comparator::compare_e_int() |
995 | { |
996 | longlong val1= (*a)->val_int(); |
997 | longlong val2= (*b)->val_int(); |
998 | if ((*a)->null_value || (*b)->null_value) |
999 | return MY_TEST((*a)->null_value && (*b)->null_value); |
1000 | return MY_TEST(val1 == val2); |
1001 | } |
1002 | |
1003 | /** |
1004 | Compare unsigned *a with signed *b or signed *a with unsigned *b. |
1005 | */ |
1006 | int Arg_comparator::compare_e_int_diff_signedness() |
1007 | { |
1008 | longlong val1= (*a)->val_int(); |
1009 | longlong val2= (*b)->val_int(); |
1010 | if ((*a)->null_value || (*b)->null_value) |
1011 | return MY_TEST((*a)->null_value && (*b)->null_value); |
1012 | return (val1 >= 0) && MY_TEST(val1 == val2); |
1013 | } |
1014 | |
1015 | int Arg_comparator::compare_row() |
1016 | { |
1017 | int res= 0; |
1018 | bool was_null= 0; |
1019 | (*a)->bring_value(); |
1020 | (*b)->bring_value(); |
1021 | |
1022 | if ((*a)->null_value || (*b)->null_value) |
1023 | { |
1024 | owner->null_value= 1; |
1025 | return -1; |
1026 | } |
1027 | |
1028 | uint n= (*a)->cols(); |
1029 | for (uint i= 0; i<n; i++) |
1030 | { |
1031 | res= comparators[i].compare(); |
1032 | /* Aggregate functions don't need special null handling. */ |
1033 | if (owner->null_value && owner->type() == Item::FUNC_ITEM) |
1034 | { |
1035 | // NULL was compared |
1036 | switch (((Item_func*)owner)->functype()) { |
1037 | case Item_func::NE_FUNC: |
1038 | break; // NE never aborts on NULL even if abort_on_null is set |
1039 | case Item_func::LT_FUNC: |
1040 | case Item_func::LE_FUNC: |
1041 | case Item_func::GT_FUNC: |
1042 | case Item_func::GE_FUNC: |
1043 | return -1; // <, <=, > and >= always fail on NULL |
1044 | case Item_func::EQ_FUNC: |
1045 | if (((Item_func_eq*)owner)->abort_on_null) |
1046 | return -1; // We do not need correct NULL returning |
1047 | break; |
1048 | default: |
1049 | DBUG_ASSERT(0); |
1050 | break; |
1051 | } |
1052 | was_null= 1; |
1053 | owner->null_value= 0; |
1054 | res= 0; // continue comparison (maybe we will meet explicit difference) |
1055 | } |
1056 | else if (res) |
1057 | return res; |
1058 | } |
1059 | if (was_null) |
1060 | { |
1061 | /* |
1062 | There was NULL(s) in comparison in some parts, but there was no |
1063 | explicit difference in other parts, so we have to return NULL. |
1064 | */ |
1065 | owner->null_value= 1; |
1066 | return -1; |
1067 | } |
1068 | return 0; |
1069 | } |
1070 | |
1071 | |
1072 | int Arg_comparator::compare_e_row() |
1073 | { |
1074 | (*a)->bring_value(); |
1075 | (*b)->bring_value(); |
1076 | uint n= (*a)->cols(); |
1077 | for (uint i= 0; i<n; i++) |
1078 | { |
1079 | if (!comparators[i].compare()) |
1080 | return 0; |
1081 | } |
1082 | return 1; |
1083 | } |
1084 | |
1085 | |
1086 | int Arg_comparator::compare_json_str() |
1087 | { |
1088 | return compare_json_str_basic(*a, *b); |
1089 | } |
1090 | |
1091 | |
1092 | int Arg_comparator::compare_str_json() |
1093 | { |
1094 | return -compare_json_str_basic(*b, *a); |
1095 | } |
1096 | |
1097 | |
1098 | int Arg_comparator::compare_e_json_str() |
1099 | { |
1100 | return compare_e_json_str_basic(*a, *b); |
1101 | } |
1102 | |
1103 | |
1104 | int Arg_comparator::compare_e_str_json() |
1105 | { |
1106 | return compare_e_json_str_basic(*b, *a); |
1107 | } |
1108 | |
1109 | |
1110 | void Item_func_truth::fix_length_and_dec() |
1111 | { |
1112 | maybe_null= 0; |
1113 | null_value= 0; |
1114 | decimals= 0; |
1115 | max_length= 1; |
1116 | } |
1117 | |
1118 | |
1119 | void Item_func_truth::print(String *str, enum_query_type query_type) |
1120 | { |
1121 | args[0]->print_parenthesised(str, query_type, precedence()); |
1122 | str->append(STRING_WITH_LEN(" is " )); |
1123 | if (! affirmative) |
1124 | str->append(STRING_WITH_LEN("not " )); |
1125 | if (value) |
1126 | str->append(STRING_WITH_LEN("true" )); |
1127 | else |
1128 | str->append(STRING_WITH_LEN("false" )); |
1129 | } |
1130 | |
1131 | |
1132 | bool Item_func_truth::val_bool() |
1133 | { |
1134 | bool val= args[0]->val_bool(); |
1135 | if (args[0]->null_value) |
1136 | { |
1137 | /* |
1138 | NULL val IS {TRUE, FALSE} --> FALSE |
1139 | NULL val IS NOT {TRUE, FALSE} --> TRUE |
1140 | */ |
1141 | return (! affirmative); |
1142 | } |
1143 | |
1144 | if (affirmative) |
1145 | { |
1146 | /* {TRUE, FALSE} val IS {TRUE, FALSE} value */ |
1147 | return (val == value); |
1148 | } |
1149 | |
1150 | /* {TRUE, FALSE} val IS NOT {TRUE, FALSE} value */ |
1151 | return (val != value); |
1152 | } |
1153 | |
1154 | |
1155 | longlong Item_func_truth::val_int() |
1156 | { |
1157 | return (val_bool() ? 1 : 0); |
1158 | } |
1159 | |
1160 | |
1161 | bool Item_in_optimizer::is_top_level_item() |
1162 | { |
1163 | return ((Item_in_subselect *)args[1])->is_top_level_item(); |
1164 | } |
1165 | |
1166 | |
1167 | void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, |
1168 | Item **ref, bool merge) |
1169 | { |
1170 | DBUG_ASSERT(fixed); |
1171 | /* This will re-calculate attributes of our Item_in_subselect: */ |
1172 | Item_bool_func::fix_after_pullout(new_parent, ref, merge); |
1173 | |
1174 | /* Then, re-calculate not_null_tables_cache: */ |
1175 | eval_not_null_tables(NULL); |
1176 | } |
1177 | |
1178 | |
1179 | bool Item_in_optimizer::eval_not_null_tables(void *opt_arg) |
1180 | { |
1181 | not_null_tables_cache= 0; |
1182 | if (is_top_level_item()) |
1183 | { |
1184 | /* |
1185 | It is possible to determine NULL-rejectedness of the left arguments |
1186 | of IN only if it is a top-level predicate. |
1187 | */ |
1188 | not_null_tables_cache= args[0]->not_null_tables(); |
1189 | } |
1190 | return FALSE; |
1191 | } |
1192 | |
1193 | |
1194 | void Item_in_optimizer::print(String *str, enum_query_type query_type) |
1195 | { |
1196 | restore_first_argument(); |
1197 | Item_func::print(str, query_type); |
1198 | } |
1199 | |
1200 | |
1201 | /** |
1202 | "Restore" first argument before fix_fields() call (after it is harmless). |
1203 | |
1204 | @Note: Main pointer to left part of IN/ALL/ANY subselect is subselect's |
1205 | lest_expr (see Item_in_optimizer::fix_left) so changes made during |
1206 | fix_fields will be rolled back there which can make |
1207 | Item_in_optimizer::args[0] unusable on second execution before fix_left() |
1208 | call. This call fix the pointer. |
1209 | */ |
1210 | |
1211 | void Item_in_optimizer::restore_first_argument() |
1212 | { |
1213 | if (args[1]->type() == Item::SUBSELECT_ITEM && |
1214 | ((Item_subselect *)args[1])->is_in_predicate()) |
1215 | { |
1216 | args[0]= ((Item_in_subselect *)args[1])->left_expr; |
1217 | } |
1218 | } |
1219 | |
1220 | |
1221 | bool Item_in_optimizer::fix_left(THD *thd) |
1222 | { |
1223 | DBUG_ENTER("Item_in_optimizer::fix_left" ); |
1224 | /* |
1225 | Here we will store pointer on place of main storage of left expression. |
1226 | For usual IN (ALL/ANY) it is subquery left_expr. |
1227 | For other cases (MAX/MIN optimization, non-transformed EXISTS (10.0)) |
1228 | it is args[0]. |
1229 | */ |
1230 | Item **ref0= args; |
1231 | if (args[1]->type() == Item::SUBSELECT_ITEM && |
1232 | ((Item_subselect *)args[1])->is_in_predicate()) |
1233 | { |
1234 | /* |
1235 | left_expr->fix_fields() may cause left_expr to be substituted for |
1236 | another item. (e.g. an Item_field may be changed into Item_ref). This |
1237 | transformation is undone at the end of statement execution (e.g. the |
1238 | Item_ref is deleted). However, Item_in_optimizer::args[0] may keep |
1239 | the pointer to the post-transformation item. Because of that, on the |
1240 | next execution we need to copy args[1]->left_expr again. |
1241 | */ |
1242 | ref0= &(((Item_in_subselect *)args[1])->left_expr); |
1243 | args[0]= ((Item_in_subselect *)args[1])->left_expr; |
1244 | } |
1245 | if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) || |
1246 | (!cache && !(cache= (*ref0)->get_cache(thd)))) |
1247 | DBUG_RETURN(1); |
1248 | /* |
1249 | During fix_field() expression could be substituted. |
1250 | So we copy changes before use |
1251 | */ |
1252 | if (args[0] != (*ref0)) |
1253 | args[0]= (*ref0); |
1254 | DBUG_PRINT("info" , ("actual fix fields" )); |
1255 | |
1256 | cache->setup(thd, args[0]); |
1257 | if (cache->cols() == 1) |
1258 | { |
1259 | DBUG_ASSERT(args[0]->type() != ROW_ITEM); |
1260 | /* |
1261 | Note: there can be cases when used_tables()==0 && !const_item(). See |
1262 | Item_sum::update_used_tables for details. |
1263 | */ |
1264 | if ((used_tables_cache= args[0]->used_tables()) || !args[0]->const_item()) |
1265 | cache->set_used_tables(OUTER_REF_TABLE_BIT); |
1266 | else |
1267 | cache->set_used_tables(0); |
1268 | } |
1269 | else |
1270 | { |
1271 | uint n= cache->cols(); |
1272 | for (uint i= 0; i < n; i++) |
1273 | { |
1274 | /* Check that the expression (part of row) do not contain a subquery */ |
1275 | if (args[0]->element_index(i)->walk(&Item::is_subquery_processor, 0, 0)) |
1276 | { |
1277 | my_error(ER_NOT_SUPPORTED_YET, MYF(0), |
1278 | "SUBQUERY in ROW in left expression of IN/ALL/ANY" ); |
1279 | DBUG_RETURN(1); |
1280 | } |
1281 | Item *element=args[0]->element_index(i); |
1282 | if (element->used_tables() || !element->const_item()) |
1283 | { |
1284 | ((Item_cache *)cache->element_index(i))-> |
1285 | set_used_tables(OUTER_REF_TABLE_BIT); |
1286 | cache->set_used_tables(OUTER_REF_TABLE_BIT); |
1287 | } |
1288 | else |
1289 | ((Item_cache *)cache->element_index(i))->set_used_tables(0); |
1290 | } |
1291 | used_tables_cache= args[0]->used_tables(); |
1292 | } |
1293 | eval_not_null_tables(NULL); |
1294 | with_sum_func= args[0]->with_sum_func; |
1295 | with_param= args[0]->with_param || args[1]->with_param; |
1296 | with_field= args[0]->with_field; |
1297 | if ((const_item_cache= args[0]->const_item())) |
1298 | { |
1299 | cache->store(args[0]); |
1300 | cache->cache_value(); |
1301 | } |
1302 | if (args[1]->fixed) |
1303 | { |
1304 | /* to avoid overriding is called to update left expression */ |
1305 | used_tables_and_const_cache_join(args[1]); |
1306 | with_sum_func= with_sum_func || args[1]->with_sum_func; |
1307 | } |
1308 | DBUG_RETURN(0); |
1309 | } |
1310 | |
1311 | |
1312 | bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) |
1313 | { |
1314 | DBUG_ASSERT(fixed == 0); |
1315 | Item_subselect *sub= 0; |
1316 | uint col; |
1317 | |
1318 | /* |
1319 | MAX/MIN optimization can convert the subquery into |
1320 | expr + Item_singlerow_subselect |
1321 | */ |
1322 | if (args[1]->type() == Item::SUBSELECT_ITEM) |
1323 | sub= (Item_subselect *)args[1]; |
1324 | |
1325 | if (fix_left(thd)) |
1326 | return TRUE; |
1327 | if (args[0]->maybe_null) |
1328 | maybe_null=1; |
1329 | |
1330 | if (!args[1]->fixed && args[1]->fix_fields(thd, args+1)) |
1331 | return TRUE; |
1332 | if (!invisible_mode() && |
1333 | ((sub && ((col= args[0]->cols()) != sub->engine->cols())) || |
1334 | (!sub && (args[1]->cols() != (col= 1))))) |
1335 | { |
1336 | my_error(ER_OPERAND_COLUMNS, MYF(0), col); |
1337 | return TRUE; |
1338 | } |
1339 | if (args[1]->maybe_null) |
1340 | maybe_null=1; |
1341 | m_with_subquery= true; |
1342 | with_sum_func= with_sum_func || args[1]->with_sum_func; |
1343 | with_field= with_field || args[1]->with_field; |
1344 | with_param= args[0]->with_param || args[1]->with_param; |
1345 | used_tables_and_const_cache_join(args[1]); |
1346 | fixed= 1; |
1347 | return FALSE; |
1348 | } |
1349 | |
1350 | /** |
1351 | Check if Item_in_optimizer should work as a pass-through item for its |
1352 | arguments. |
1353 | |
1354 | @note |
1355 | Item_in_optimizer should work as pass-through for |
1356 | - subqueries that were processed by ALL/ANY->MIN/MAX rewrite |
1357 | - subqueries taht were originally EXISTS subqueries (and were coverted by |
1358 | the EXISTS->IN rewrite) |
1359 | |
1360 | When Item_in_optimizer is not not working as a pass-through, it |
1361 | - caches its "left argument", args[0]. |
1362 | - makes adjustments to subquery item's return value for proper NULL |
1363 | value handling |
1364 | */ |
1365 | |
1366 | bool Item_in_optimizer::invisible_mode() |
1367 | { |
1368 | /* MAX/MIN transformed or EXISTS->IN prepared => do nothing */ |
1369 | return (args[1]->type() != Item::SUBSELECT_ITEM || |
1370 | ((Item_subselect *)args[1])->substype() == |
1371 | Item_subselect::EXISTS_SUBS); |
1372 | } |
1373 | |
1374 | |
1375 | /** |
1376 | Add an expression cache for this subquery if it is needed |
1377 | |
1378 | @param thd_arg Thread handle |
1379 | |
1380 | @details |
1381 | The function checks whether an expression cache is needed for this item |
1382 | and if if so wraps the item into an item of the class |
1383 | Item_cache_wrapper with an appropriate expression cache set up there. |
1384 | |
1385 | @note |
1386 | used from Item::transform() |
1387 | |
1388 | @return |
1389 | new wrapper item if an expression cache is needed, |
1390 | this item - otherwise |
1391 | */ |
1392 | |
1393 | Item *Item_in_optimizer::expr_cache_insert_transformer(THD *thd, uchar *unused) |
1394 | { |
1395 | DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer" ); |
1396 | DBUG_ASSERT(fixed); |
1397 | |
1398 | if (invisible_mode()) |
1399 | DBUG_RETURN(this); |
1400 | |
1401 | if (expr_cache) |
1402 | DBUG_RETURN(expr_cache); |
1403 | |
1404 | if (args[1]->expr_cache_is_needed(thd) && |
1405 | (expr_cache= set_expr_cache(thd))) |
1406 | DBUG_RETURN(expr_cache); |
1407 | |
1408 | DBUG_RETURN(this); |
1409 | } |
1410 | |
1411 | |
1412 | |
1413 | /** |
1414 | Collect and add to the list cache parameters for this Item. |
1415 | |
1416 | @param parameters The list where to add parameters |
1417 | */ |
1418 | |
1419 | void Item_in_optimizer::get_cache_parameters(List<Item> ¶meters) |
1420 | { |
1421 | DBUG_ASSERT(fixed); |
1422 | /* Add left expression to the list of the parameters of the subquery */ |
1423 | if (!invisible_mode()) |
1424 | { |
1425 | if (args[0]->cols() == 1) |
1426 | parameters.add_unique(args[0], &cmp_items); |
1427 | else |
1428 | { |
1429 | for (uint i= 0; i < args[0]->cols(); i++) |
1430 | { |
1431 | parameters.add_unique(args[0]->element_index(i), &cmp_items); |
1432 | } |
1433 | } |
1434 | } |
1435 | args[1]->get_cache_parameters(parameters); |
1436 | } |
1437 | |
1438 | /** |
1439 | The implementation of optimized \<outer expression\> [NOT] IN \<subquery\> |
1440 | predicates. The implementation works as follows. |
1441 | |
1442 | For the current value of the outer expression |
1443 | |
1444 | - If it contains only NULL values, the original (before rewrite by the |
1445 | Item_in_subselect rewrite methods) inner subquery is non-correlated and |
1446 | was previously executed, there is no need to re-execute it, and the |
1447 | previous return value is returned. |
1448 | |
1449 | - If it contains NULL values, check if there is a partial match for the |
1450 | inner query block by evaluating it. For clarity we repeat here the |
1451 | transformation previously performed on the sub-query. The expression |
1452 | |
1453 | <tt> |
1454 | ( oc_1, ..., oc_n ) |
1455 | \<in predicate\> |
1456 | ( SELECT ic_1, ..., ic_n |
1457 | FROM \<table\> |
1458 | WHERE \<inner where\> |
1459 | ) |
1460 | </tt> |
1461 | |
1462 | was transformed into |
1463 | |
1464 | <tt> |
1465 | ( oc_1, ..., oc_n ) |
1466 | \<in predicate\> |
1467 | ( SELECT ic_1, ..., ic_n |
1468 | FROM \<table\> |
1469 | WHERE \<inner where\> AND ... ( ic_k = oc_k OR ic_k IS NULL ) |
1470 | HAVING ... NOT ic_k IS NULL |
1471 | ) |
1472 | </tt> |
1473 | |
1474 | The evaluation will now proceed according to special rules set up |
1475 | elsewhere. These rules include: |
1476 | |
1477 | - The HAVING NOT \<inner column\> IS NULL conditions added by the |
1478 | aforementioned rewrite methods will detect whether they evaluated (and |
1479 | rejected) a NULL value and if so, will cause the subquery to evaluate |
1480 | to NULL. |
1481 | |
1482 | - The added WHERE and HAVING conditions are present only for those inner |
1483 | columns that correspond to outer column that are not NULL at the moment. |
1484 | |
1485 | - If there is an eligible index for executing the subquery, the special |
1486 | access method "Full scan on NULL key" is employed which ensures that |
1487 | the inner query will detect if there are NULL values resulting from the |
1488 | inner query. This access method will quietly resort to table scan if it |
1489 | needs to find NULL values as well. |
1490 | |
1491 | - Under these conditions, the sub-query need only be evaluated in order to |
1492 | find out whether it produced any rows. |
1493 | |
1494 | - If it did, we know that there was a partial match since there are |
1495 | NULL values in the outer row expression. |
1496 | |
1497 | - If it did not, the result is FALSE or UNKNOWN. If at least one of the |
1498 | HAVING sub-predicates rejected a NULL value corresponding to an outer |
1499 | non-NULL, and hence the inner query block returns UNKNOWN upon |
1500 | evaluation, there was a partial match and the result is UNKNOWN. |
1501 | |
1502 | - If it contains no NULL values, the call is forwarded to the inner query |
1503 | block. |
1504 | |
1505 | @see Item_in_subselect::val_bool() |
1506 | @see Item_is_not_null_test::val_int() |
1507 | */ |
1508 | |
1509 | longlong Item_in_optimizer::val_int() |
1510 | { |
1511 | bool tmp; |
1512 | DBUG_ASSERT(fixed == 1); |
1513 | cache->store(args[0]); |
1514 | cache->cache_value(); |
1515 | DBUG_ENTER(" Item_in_optimizer::val_int" ); |
1516 | |
1517 | if (invisible_mode()) |
1518 | { |
1519 | longlong res= args[1]->val_int(); |
1520 | null_value= args[1]->null_value; |
1521 | DBUG_PRINT("info" , ("pass trough" )); |
1522 | DBUG_RETURN(res); |
1523 | } |
1524 | |
1525 | if (cache->null_value) |
1526 | { |
1527 | DBUG_PRINT("info" , ("Left NULL..." )); |
1528 | /* |
1529 | We're evaluating |
1530 | "<outer_value_list> [NOT] IN (SELECT <inner_value_list>...)" |
1531 | where one or more of the outer values is NULL. |
1532 | */ |
1533 | if (((Item_in_subselect*)args[1])->is_top_level_item()) |
1534 | { |
1535 | /* |
1536 | We're evaluating a top level item, e.g. |
1537 | "<outer_value_list> IN (SELECT <inner_value_list>...)", |
1538 | and in this case a NULL value in the outer_value_list means |
1539 | that the result shall be NULL/FALSE (makes no difference for |
1540 | top level items). The cached value is NULL, so just return |
1541 | NULL. |
1542 | */ |
1543 | null_value= 1; |
1544 | } |
1545 | else |
1546 | { |
1547 | /* |
1548 | We're evaluating an item where a NULL value in either the |
1549 | outer or inner value list does not automatically mean that we |
1550 | can return NULL/FALSE. An example of such a query is |
1551 | "<outer_value_list> NOT IN (SELECT <inner_value_list>...)" |
1552 | The result when there is at least one NULL value is: NULL if the |
1553 | SELECT evaluated over the non-NULL values produces at least |
1554 | one row, FALSE otherwise |
1555 | */ |
1556 | Item_in_subselect *item_subs=(Item_in_subselect*)args[1]; |
1557 | bool all_left_cols_null= true; |
1558 | const uint ncols= cache->cols(); |
1559 | |
1560 | /* |
1561 | Turn off the predicates that are based on column compares for |
1562 | which the left part is currently NULL |
1563 | */ |
1564 | for (uint i= 0; i < ncols; i++) |
1565 | { |
1566 | if (cache->element_index(i)->null_value) |
1567 | item_subs->set_cond_guard_var(i, FALSE); |
1568 | else |
1569 | all_left_cols_null= false; |
1570 | } |
1571 | |
1572 | if (!item_subs->is_correlated && |
1573 | all_left_cols_null && result_for_null_param != UNKNOWN) |
1574 | { |
1575 | /* |
1576 | This is a non-correlated subquery, all values in the outer |
1577 | value list are NULL, and we have already evaluated the |
1578 | subquery for all NULL values: Return the same result we |
1579 | did last time without evaluating the subquery. |
1580 | */ |
1581 | null_value= result_for_null_param; |
1582 | } |
1583 | else |
1584 | { |
1585 | /* The subquery has to be evaluated */ |
1586 | (void) item_subs->val_bool_result(); |
1587 | if (item_subs->engine->no_rows()) |
1588 | null_value= item_subs->null_value; |
1589 | else |
1590 | null_value= TRUE; |
1591 | if (all_left_cols_null) |
1592 | result_for_null_param= null_value; |
1593 | } |
1594 | |
1595 | /* Turn all predicates back on */ |
1596 | for (uint i= 0; i < ncols; i++) |
1597 | item_subs->set_cond_guard_var(i, TRUE); |
1598 | } |
1599 | DBUG_RETURN(0); |
1600 | } |
1601 | tmp= args[1]->val_bool_result(); |
1602 | null_value= args[1]->null_value; |
1603 | DBUG_RETURN(tmp); |
1604 | } |
1605 | |
1606 | |
1607 | void Item_in_optimizer::keep_top_level_cache() |
1608 | { |
1609 | cache->keep_array(); |
1610 | save_cache= 1; |
1611 | } |
1612 | |
1613 | |
1614 | void Item_in_optimizer::cleanup() |
1615 | { |
1616 | DBUG_ENTER("Item_in_optimizer::cleanup" ); |
1617 | Item_bool_func::cleanup(); |
1618 | if (!save_cache) |
1619 | cache= 0; |
1620 | expr_cache= 0; |
1621 | DBUG_VOID_RETURN; |
1622 | } |
1623 | |
1624 | |
1625 | bool Item_in_optimizer::is_null() |
1626 | { |
1627 | val_int(); |
1628 | return null_value; |
1629 | } |
1630 | |
1631 | |
1632 | /** |
1633 | Transform an Item_in_optimizer and its arguments with a callback function. |
1634 | |
1635 | @param transformer the transformer callback function to be applied to the |
1636 | nodes of the tree of the object |
1637 | @param parameter to be passed to the transformer |
1638 | |
1639 | @detail |
1640 | Recursively transform the left and the right operand of this Item. The |
1641 | Right operand is an Item_in_subselect or its subclass. To avoid the |
1642 | creation of new Items, we use the fact the the left operand of the |
1643 | Item_in_subselect is the same as the one of 'this', so instead of |
1644 | transforming its operand, we just assign the left operand of the |
1645 | Item_in_subselect to be equal to the left operand of 'this'. |
1646 | The transformation is not applied further to the subquery operand |
1647 | if the IN predicate. |
1648 | |
1649 | @returns |
1650 | @retval pointer to the transformed item |
1651 | @retval NULL if an error occurred |
1652 | */ |
1653 | |
1654 | Item *Item_in_optimizer::transform(THD *thd, Item_transformer transformer, |
1655 | uchar *argument) |
1656 | { |
1657 | Item *new_item; |
1658 | |
1659 | DBUG_ASSERT(fixed); |
1660 | DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); |
1661 | DBUG_ASSERT(arg_count == 2); |
1662 | |
1663 | /* Transform the left IN operand. */ |
1664 | new_item= (*args)->transform(thd, transformer, argument); |
1665 | if (!new_item) |
1666 | return 0; |
1667 | /* |
1668 | THD::change_item_tree() should be called only if the tree was |
1669 | really transformed, i.e. when a new item has been created. |
1670 | Otherwise we'll be allocating a lot of unnecessary memory for |
1671 | change records at each execution. |
1672 | */ |
1673 | if ((*args) != new_item) |
1674 | thd->change_item_tree(args, new_item); |
1675 | |
1676 | if (invisible_mode()) |
1677 | { |
1678 | /* MAX/MIN transformed => pass through */ |
1679 | new_item= args[1]->transform(thd, transformer, argument); |
1680 | if (!new_item) |
1681 | return 0; |
1682 | if (args[1] != new_item) |
1683 | thd->change_item_tree(args + 1, new_item); |
1684 | } |
1685 | else |
1686 | { |
1687 | /* |
1688 | Transform the right IN operand which should be an Item_in_subselect or a |
1689 | subclass of it. The left operand of the IN must be the same as the left |
1690 | operand of this Item_in_optimizer, so in this case there is no further |
1691 | transformation, we only make both operands the same. |
1692 | TODO: is it the way it should be? |
1693 | */ |
1694 | DBUG_ASSERT((args[1])->type() == Item::SUBSELECT_ITEM && |
1695 | (((Item_subselect*)(args[1]))->substype() == |
1696 | Item_subselect::IN_SUBS || |
1697 | ((Item_subselect*)(args[1]))->substype() == |
1698 | Item_subselect::ALL_SUBS || |
1699 | ((Item_subselect*)(args[1]))->substype() == |
1700 | Item_subselect::ANY_SUBS)); |
1701 | |
1702 | Item_in_subselect *in_arg= (Item_in_subselect*)args[1]; |
1703 | thd->change_item_tree(&in_arg->left_expr, args[0]); |
1704 | } |
1705 | return (this->*transformer)(thd, argument); |
1706 | } |
1707 | |
1708 | |
1709 | bool Item_in_optimizer::is_expensive_processor(void *arg) |
1710 | { |
1711 | DBUG_ASSERT(fixed); |
1712 | return args[0]->is_expensive_processor(arg) || |
1713 | args[1]->is_expensive_processor(arg); |
1714 | } |
1715 | |
1716 | |
1717 | bool Item_in_optimizer::is_expensive() |
1718 | { |
1719 | DBUG_ASSERT(fixed); |
1720 | return args[0]->is_expensive() || args[1]->is_expensive(); |
1721 | } |
1722 | |
1723 | |
1724 | longlong Item_func_eq::val_int() |
1725 | { |
1726 | DBUG_ASSERT(fixed == 1); |
1727 | int value= cmp.compare(); |
1728 | return value == 0 ? 1 : 0; |
1729 | } |
1730 | |
1731 | |
1732 | /** Same as Item_func_eq, but NULL = NULL. */ |
1733 | |
1734 | void Item_func_equal::fix_length_and_dec() |
1735 | { |
1736 | Item_bool_rowready_func2::fix_length_and_dec(); |
1737 | maybe_null=null_value=0; |
1738 | } |
1739 | |
1740 | longlong Item_func_equal::val_int() |
1741 | { |
1742 | DBUG_ASSERT(fixed == 1); |
1743 | return cmp.compare(); |
1744 | } |
1745 | |
1746 | longlong Item_func_ne::val_int() |
1747 | { |
1748 | DBUG_ASSERT(fixed == 1); |
1749 | int value= cmp.compare(); |
1750 | return value != 0 && !null_value ? 1 : 0; |
1751 | } |
1752 | |
1753 | |
1754 | longlong Item_func_ge::val_int() |
1755 | { |
1756 | DBUG_ASSERT(fixed == 1); |
1757 | int value= cmp.compare(); |
1758 | return value >= 0 ? 1 : 0; |
1759 | } |
1760 | |
1761 | |
1762 | longlong Item_func_gt::val_int() |
1763 | { |
1764 | DBUG_ASSERT(fixed == 1); |
1765 | int value= cmp.compare(); |
1766 | return value > 0 ? 1 : 0; |
1767 | } |
1768 | |
1769 | longlong Item_func_le::val_int() |
1770 | { |
1771 | DBUG_ASSERT(fixed == 1); |
1772 | int value= cmp.compare(); |
1773 | return value <= 0 && !null_value ? 1 : 0; |
1774 | } |
1775 | |
1776 | |
1777 | longlong Item_func_lt::val_int() |
1778 | { |
1779 | DBUG_ASSERT(fixed == 1); |
1780 | int value= cmp.compare(); |
1781 | return value < 0 && !null_value ? 1 : 0; |
1782 | } |
1783 | |
1784 | |
1785 | longlong Item_func_strcmp::val_int() |
1786 | { |
1787 | DBUG_ASSERT(fixed == 1); |
1788 | String *a= args[0]->val_str(&value1); |
1789 | String *b= args[1]->val_str(&value2); |
1790 | if (!a || !b) |
1791 | { |
1792 | null_value=1; |
1793 | return 0; |
1794 | } |
1795 | int value= cmp_collation.sortcmp(a, b); |
1796 | null_value=0; |
1797 | return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1); |
1798 | } |
1799 | |
1800 | |
1801 | bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const |
1802 | { |
1803 | /* Assume we don't have rtti */ |
1804 | if (this == item) |
1805 | return 1; |
1806 | if (item->type() != FUNC_ITEM) |
1807 | return 0; |
1808 | Item_func *item_func=(Item_func*) item; |
1809 | if (arg_count != item_func->argument_count() || |
1810 | functype() != item_func->functype()) |
1811 | return 0; |
1812 | if (negated != ((Item_func_opt_neg *) item_func)->negated) |
1813 | return 0; |
1814 | for (uint i=0; i < arg_count ; i++) |
1815 | if (!args[i]->eq(item_func->arguments()[i], binary_cmp)) |
1816 | return 0; |
1817 | return 1; |
1818 | } |
1819 | |
1820 | |
1821 | bool Item_func_interval::fix_fields(THD *thd, Item **ref) |
1822 | { |
1823 | if (Item_long_func::fix_fields(thd, ref)) |
1824 | return true; |
1825 | for (uint i= 0 ; i < row->cols(); i++) |
1826 | { |
1827 | if (row->element_index(i)->check_cols(1)) |
1828 | return true; |
1829 | } |
1830 | return false; |
1831 | } |
1832 | |
1833 | |
1834 | void Item_func_interval::fix_length_and_dec() |
1835 | { |
1836 | uint rows= row->cols(); |
1837 | |
1838 | use_decimal_comparison= ((row->element_index(0)->result_type() == |
1839 | DECIMAL_RESULT) || |
1840 | (row->element_index(0)->result_type() == |
1841 | INT_RESULT)); |
1842 | if (rows > 8) |
1843 | { |
1844 | bool not_null_consts= TRUE; |
1845 | |
1846 | for (uint i= 1; not_null_consts && i < rows; i++) |
1847 | { |
1848 | Item *el= row->element_index(i); |
1849 | not_null_consts&= el->const_item() && !el->is_null(); |
1850 | } |
1851 | |
1852 | if (not_null_consts && |
1853 | (intervals= (interval_range*) current_thd->alloc(sizeof(interval_range) * |
1854 | (rows - 1)))) |
1855 | { |
1856 | if (use_decimal_comparison) |
1857 | { |
1858 | for (uint i= 1; i < rows; i++) |
1859 | { |
1860 | Item *el= row->element_index(i); |
1861 | interval_range *range= intervals + (i-1); |
1862 | if ((el->result_type() == DECIMAL_RESULT) || |
1863 | (el->result_type() == INT_RESULT)) |
1864 | { |
1865 | range->type= DECIMAL_RESULT; |
1866 | range->dec.init(); |
1867 | my_decimal *dec= el->val_decimal(&range->dec); |
1868 | if (dec != &range->dec) |
1869 | { |
1870 | range->dec= *dec; |
1871 | } |
1872 | } |
1873 | else |
1874 | { |
1875 | range->type= REAL_RESULT; |
1876 | range->dbl= el->val_real(); |
1877 | } |
1878 | } |
1879 | } |
1880 | else |
1881 | { |
1882 | for (uint i= 1; i < rows; i++) |
1883 | { |
1884 | intervals[i-1].dbl= row->element_index(i)->val_real(); |
1885 | } |
1886 | } |
1887 | } |
1888 | } |
1889 | maybe_null= 0; |
1890 | max_length= 2; |
1891 | used_tables_and_const_cache_join(row); |
1892 | not_null_tables_cache= row->not_null_tables(); |
1893 | with_sum_func= with_sum_func || row->with_sum_func; |
1894 | with_param= with_param || row->with_param; |
1895 | with_field= with_field || row->with_field; |
1896 | } |
1897 | |
1898 | |
1899 | /** |
1900 | Execute Item_func_interval(). |
1901 | |
1902 | @note |
1903 | If we are doing a decimal comparison, we are evaluating the first |
1904 | item twice. |
1905 | |
1906 | @return |
1907 | - -1 if null value, |
1908 | - 0 if lower than lowest |
1909 | - 1 - arg_count-1 if between args[n] and args[n+1] |
1910 | - arg_count if higher than biggest argument |
1911 | */ |
1912 | |
1913 | longlong Item_func_interval::val_int() |
1914 | { |
1915 | DBUG_ASSERT(fixed == 1); |
1916 | double value; |
1917 | my_decimal dec_buf, *dec= NULL; |
1918 | uint i; |
1919 | |
1920 | if (use_decimal_comparison) |
1921 | { |
1922 | dec= row->element_index(0)->val_decimal(&dec_buf); |
1923 | if (row->element_index(0)->null_value) |
1924 | return -1; |
1925 | my_decimal2double(E_DEC_FATAL_ERROR, dec, &value); |
1926 | } |
1927 | else |
1928 | { |
1929 | value= row->element_index(0)->val_real(); |
1930 | if (row->element_index(0)->null_value) |
1931 | return -1; |
1932 | } |
1933 | |
1934 | if (intervals) |
1935 | { // Use binary search to find interval |
1936 | uint start,end; |
1937 | start= 0; |
1938 | end= row->cols()-2; |
1939 | while (start != end) |
1940 | { |
1941 | uint mid= (start + end + 1) / 2; |
1942 | interval_range *range= intervals + mid; |
1943 | my_bool cmp_result; |
1944 | /* |
1945 | The values in the range intervall may have different types, |
1946 | Only do a decimal comparision of the first argument is a decimal |
1947 | and we are comparing against a decimal |
1948 | */ |
1949 | if (dec && range->type == DECIMAL_RESULT) |
1950 | cmp_result= my_decimal_cmp(&range->dec, dec) <= 0; |
1951 | else |
1952 | cmp_result= (range->dbl <= value); |
1953 | if (cmp_result) |
1954 | start= mid; |
1955 | else |
1956 | end= mid - 1; |
1957 | } |
1958 | interval_range *range= intervals+start; |
1959 | return ((dec && range->type == DECIMAL_RESULT) ? |
1960 | my_decimal_cmp(dec, &range->dec) < 0 : |
1961 | value < range->dbl) ? 0 : start + 1; |
1962 | } |
1963 | |
1964 | for (i=1 ; i < row->cols() ; i++) |
1965 | { |
1966 | Item *el= row->element_index(i); |
1967 | if (use_decimal_comparison && |
1968 | ((el->result_type() == DECIMAL_RESULT) || |
1969 | (el->result_type() == INT_RESULT))) |
1970 | { |
1971 | my_decimal e_dec_buf, *e_dec= el->val_decimal(&e_dec_buf); |
1972 | /* Skip NULL ranges. */ |
1973 | if (el->null_value) |
1974 | continue; |
1975 | if (my_decimal_cmp(e_dec, dec) > 0) |
1976 | return i - 1; |
1977 | } |
1978 | else |
1979 | { |
1980 | double val= el->val_real(); |
1981 | /* Skip NULL ranges. */ |
1982 | if (el->null_value) |
1983 | continue; |
1984 | if (val > value) |
1985 | return i - 1; |
1986 | } |
1987 | } |
1988 | return i-1; |
1989 | } |
1990 | |
1991 | |
1992 | /** |
1993 | Perform context analysis of a BETWEEN item tree. |
1994 | |
1995 | This function performs context analysis (name resolution) and calculates |
1996 | various attributes of the item tree with Item_func_between as its root. |
1997 | The function saves in ref the pointer to the item or to a newly created |
1998 | item that is considered as a replacement for the original one. |
1999 | |
2000 | @param thd reference to the global context of the query thread |
2001 | @param ref pointer to Item* variable where pointer to resulting "fixed" |
2002 | item is to be assigned |
2003 | |
2004 | @note |
2005 | Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on |
2006 | a predicate/function level. Then it's easy to show that: |
2007 | @verbatim |
2008 | T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2)) |
2009 | T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) |
2010 | T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) |
2011 | T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) |
2012 | @endverbatim |
2013 | |
2014 | @retval |
2015 | 0 ok |
2016 | @retval |
2017 | 1 got error |
2018 | */ |
2019 | |
2020 | |
2021 | bool Item_func_between::eval_not_null_tables(void *opt_arg) |
2022 | { |
2023 | if (Item_func_opt_neg::eval_not_null_tables(NULL)) |
2024 | return 1; |
2025 | |
2026 | /* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */ |
2027 | if (pred_level && !negated) |
2028 | return 0; |
2029 | |
2030 | /* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */ |
2031 | not_null_tables_cache= (args[0]->not_null_tables() | |
2032 | (args[1]->not_null_tables() & |
2033 | args[2]->not_null_tables())); |
2034 | return 0; |
2035 | } |
2036 | |
2037 | |
2038 | bool Item_func_between::count_sargable_conds(void *arg) |
2039 | { |
2040 | SELECT_LEX *sel= (SELECT_LEX *) arg; |
2041 | sel->cond_count++; |
2042 | sel->between_count++; |
2043 | return 0; |
2044 | } |
2045 | |
2046 | |
2047 | void Item_func_between::fix_after_pullout(st_select_lex *new_parent, |
2048 | Item **ref, bool merge) |
2049 | { |
2050 | /* This will re-calculate attributes of the arguments */ |
2051 | Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge); |
2052 | /* Then, re-calculate not_null_tables_cache according to our special rules */ |
2053 | eval_not_null_tables(NULL); |
2054 | } |
2055 | |
2056 | void Item_func_between::fix_length_and_dec() |
2057 | { |
2058 | max_length= 1; |
2059 | |
2060 | /* |
2061 | As some compare functions are generated after sql_yacc, |
2062 | we have to check for out of memory conditions here |
2063 | */ |
2064 | if (!args[0] || !args[1] || !args[2]) |
2065 | return; |
2066 | if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(), |
2067 | args, 3, true)) |
2068 | { |
2069 | DBUG_ASSERT(current_thd->is_error()); |
2070 | return; |
2071 | } |
2072 | |
2073 | m_comparator.type_handler()->Item_func_between_fix_length_and_dec(this); |
2074 | } |
2075 | |
2076 | |
2077 | bool Item_func_between::fix_length_and_dec_numeric(THD *thd) |
2078 | { |
2079 | /* See the comment about the similar block in Item_bool_func2 */ |
2080 | if (args[0]->real_item()->type() == FIELD_ITEM && |
2081 | !thd->lex->is_ps_or_view_context_analysis()) |
2082 | { |
2083 | Item_field *field_item= (Item_field*) (args[0]->real_item()); |
2084 | if (field_item->field_type() == MYSQL_TYPE_LONGLONG || |
2085 | field_item->field_type() == MYSQL_TYPE_YEAR) |
2086 | { |
2087 | const bool cvt_arg1= convert_const_to_int(thd, field_item, &args[1]); |
2088 | const bool cvt_arg2= convert_const_to_int(thd, field_item, &args[2]); |
2089 | if (cvt_arg1 && cvt_arg2) |
2090 | { |
2091 | // Works for all types |
2092 | m_comparator.set_handler(&type_handler_longlong); |
2093 | } |
2094 | } |
2095 | } |
2096 | return false; |
2097 | } |
2098 | |
2099 | |
2100 | bool Item_func_between::fix_length_and_dec_temporal(THD *thd) |
2101 | { |
2102 | if (!thd->lex->is_ps_or_view_context_analysis()) |
2103 | { |
2104 | for (uint i= 0; i < 3; i ++) |
2105 | { |
2106 | if (args[i]->const_item() && |
2107 | args[i]->type_handler_for_comparison() != m_comparator.type_handler()) |
2108 | { |
2109 | Item_cache *cache= m_comparator.type_handler()->Item_get_cache(thd, args[i]); |
2110 | if (!cache || cache->setup(thd, args[i])) |
2111 | return true; |
2112 | thd->change_item_tree(&args[i], cache); |
2113 | } |
2114 | } |
2115 | } |
2116 | return false; |
2117 | } |
2118 | |
2119 | |
2120 | longlong Item_func_between::val_int_cmp_temporal() |
2121 | { |
2122 | enum_field_types f_type= m_comparator.type_handler()->field_type(); |
2123 | longlong value= args[0]->val_temporal_packed(f_type), a, b; |
2124 | if ((null_value= args[0]->null_value)) |
2125 | return 0; |
2126 | a= args[1]->val_temporal_packed(f_type); |
2127 | b= args[2]->val_temporal_packed(f_type); |
2128 | if (!args[1]->null_value && !args[2]->null_value) |
2129 | return (longlong) ((value >= a && value <= b) != negated); |
2130 | if (args[1]->null_value && args[2]->null_value) |
2131 | null_value= true; |
2132 | else if (args[1]->null_value) |
2133 | null_value= value <= b; // not null if false range. |
2134 | else |
2135 | null_value= value >= a; |
2136 | return (longlong) (!null_value && negated); |
2137 | } |
2138 | |
2139 | |
2140 | longlong Item_func_between::val_int_cmp_string() |
2141 | { |
2142 | String *value,*a,*b; |
2143 | value=args[0]->val_str(&value0); |
2144 | if ((null_value=args[0]->null_value)) |
2145 | return 0; |
2146 | a= args[1]->val_str(&value1); |
2147 | b= args[2]->val_str(&value2); |
2148 | if (!args[1]->null_value && !args[2]->null_value) |
2149 | return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 && |
2150 | sortcmp(value,b,cmp_collation.collation) <= 0) != |
2151 | negated); |
2152 | if (args[1]->null_value && args[2]->null_value) |
2153 | null_value= true; |
2154 | else if (args[1]->null_value) |
2155 | { |
2156 | // Set to not null if false range. |
2157 | null_value= sortcmp(value,b,cmp_collation.collation) <= 0; |
2158 | } |
2159 | else |
2160 | { |
2161 | // Set to not null if false range. |
2162 | null_value= sortcmp(value,a,cmp_collation.collation) >= 0; |
2163 | } |
2164 | return (longlong) (!null_value && negated); |
2165 | } |
2166 | |
2167 | |
2168 | longlong Item_func_between::val_int_cmp_int() |
2169 | { |
2170 | longlong value= args[0]->val_int(), a, b; |
2171 | if ((null_value= args[0]->null_value)) |
2172 | return 0; /* purecov: inspected */ |
2173 | a= args[1]->val_int(); |
2174 | b= args[2]->val_int(); |
2175 | if (!args[1]->null_value && !args[2]->null_value) |
2176 | return (longlong) ((value >= a && value <= b) != negated); |
2177 | if (args[1]->null_value && args[2]->null_value) |
2178 | null_value= true; |
2179 | else if (args[1]->null_value) |
2180 | { |
2181 | null_value= value <= b; // not null if false range. |
2182 | } |
2183 | else |
2184 | { |
2185 | null_value= value >= a; |
2186 | } |
2187 | return (longlong) (!null_value && negated); |
2188 | } |
2189 | |
2190 | |
2191 | longlong Item_func_between::val_int_cmp_decimal() |
2192 | { |
2193 | my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf), |
2194 | a_buf, *a_dec, b_buf, *b_dec; |
2195 | if ((null_value=args[0]->null_value)) |
2196 | return 0; /* purecov: inspected */ |
2197 | a_dec= args[1]->val_decimal(&a_buf); |
2198 | b_dec= args[2]->val_decimal(&b_buf); |
2199 | if (!args[1]->null_value && !args[2]->null_value) |
2200 | return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 && |
2201 | my_decimal_cmp(dec, b_dec) <= 0) != negated); |
2202 | if (args[1]->null_value && args[2]->null_value) |
2203 | null_value= true; |
2204 | else if (args[1]->null_value) |
2205 | null_value= (my_decimal_cmp(dec, b_dec) <= 0); |
2206 | else |
2207 | null_value= (my_decimal_cmp(dec, a_dec) >= 0); |
2208 | return (longlong) (!null_value && negated); |
2209 | } |
2210 | |
2211 | |
2212 | longlong Item_func_between::val_int_cmp_real() |
2213 | { |
2214 | double value= args[0]->val_real(),a,b; |
2215 | if ((null_value=args[0]->null_value)) |
2216 | return 0; /* purecov: inspected */ |
2217 | a= args[1]->val_real(); |
2218 | b= args[2]->val_real(); |
2219 | if (!args[1]->null_value && !args[2]->null_value) |
2220 | return (longlong) ((value >= a && value <= b) != negated); |
2221 | if (args[1]->null_value && args[2]->null_value) |
2222 | null_value= true; |
2223 | else if (args[1]->null_value) |
2224 | { |
2225 | null_value= value <= b; // not null if false range. |
2226 | } |
2227 | else |
2228 | { |
2229 | null_value= value >= a; |
2230 | } |
2231 | return (longlong) (!null_value && negated); |
2232 | } |
2233 | |
2234 | |
2235 | void Item_func_between::print(String *str, enum_query_type query_type) |
2236 | { |
2237 | args[0]->print_parenthesised(str, query_type, precedence()); |
2238 | if (negated) |
2239 | str->append(STRING_WITH_LEN(" not" )); |
2240 | str->append(STRING_WITH_LEN(" between " )); |
2241 | args[1]->print_parenthesised(str, query_type, precedence()); |
2242 | str->append(STRING_WITH_LEN(" and " )); |
2243 | args[2]->print_parenthesised(str, query_type, precedence()); |
2244 | } |
2245 | |
2246 | |
2247 | double |
2248 | Item_func_ifnull::real_op() |
2249 | { |
2250 | DBUG_ASSERT(fixed == 1); |
2251 | double value= args[0]->val_real(); |
2252 | if (!args[0]->null_value) |
2253 | { |
2254 | null_value=0; |
2255 | return value; |
2256 | } |
2257 | value= args[1]->val_real(); |
2258 | if ((null_value=args[1]->null_value)) |
2259 | return 0.0; |
2260 | return value; |
2261 | } |
2262 | |
2263 | longlong |
2264 | Item_func_ifnull::int_op() |
2265 | { |
2266 | DBUG_ASSERT(fixed == 1); |
2267 | longlong value=args[0]->val_int(); |
2268 | if (!args[0]->null_value) |
2269 | { |
2270 | null_value=0; |
2271 | return value; |
2272 | } |
2273 | value=args[1]->val_int(); |
2274 | if ((null_value=args[1]->null_value)) |
2275 | return 0; |
2276 | return value; |
2277 | } |
2278 | |
2279 | |
2280 | my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value) |
2281 | { |
2282 | DBUG_ASSERT(fixed == 1); |
2283 | my_decimal *value= args[0]->val_decimal(decimal_value); |
2284 | if (!args[0]->null_value) |
2285 | { |
2286 | null_value= 0; |
2287 | return value; |
2288 | } |
2289 | value= args[1]->val_decimal(decimal_value); |
2290 | if ((null_value= args[1]->null_value)) |
2291 | return 0; |
2292 | return value; |
2293 | } |
2294 | |
2295 | |
2296 | String * |
2297 | Item_func_ifnull::str_op(String *str) |
2298 | { |
2299 | DBUG_ASSERT(fixed == 1); |
2300 | String *res =args[0]->val_str(str); |
2301 | if (!args[0]->null_value) |
2302 | { |
2303 | null_value=0; |
2304 | res->set_charset(collation.collation); |
2305 | return res; |
2306 | } |
2307 | res=args[1]->val_str(str); |
2308 | if ((null_value=args[1]->null_value)) |
2309 | return 0; |
2310 | res->set_charset(collation.collation); |
2311 | return res; |
2312 | } |
2313 | |
2314 | |
2315 | bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) |
2316 | { |
2317 | DBUG_ASSERT(fixed == 1); |
2318 | for (uint i= 0; i < 2; i++) |
2319 | { |
2320 | Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); |
2321 | if (!(dt.copy_to_mysql_time(ltime, mysql_timestamp_type()))) |
2322 | return (null_value= false); |
2323 | } |
2324 | return (null_value= true); |
2325 | } |
2326 | |
2327 | |
2328 | bool Item_func_ifnull::time_op(MYSQL_TIME *ltime) |
2329 | { |
2330 | DBUG_ASSERT(fixed == 1); |
2331 | for (uint i= 0; i < 2; i++) |
2332 | { |
2333 | if (!Time(args[i]).copy_to_mysql_time(ltime)) |
2334 | return (null_value= false); |
2335 | } |
2336 | return (null_value= true); |
2337 | } |
2338 | |
2339 | |
2340 | /** |
2341 | Perform context analysis of an IF item tree. |
2342 | |
2343 | This function performs context analysis (name resolution) and calculates |
2344 | various attributes of the item tree with Item_func_if as its root. |
2345 | The function saves in ref the pointer to the item or to a newly created |
2346 | item that is considered as a replacement for the original one. |
2347 | |
2348 | @param thd reference to the global context of the query thread |
2349 | @param ref pointer to Item* variable where pointer to resulting "fixed" |
2350 | item is to be assigned |
2351 | |
2352 | @note |
2353 | Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on |
2354 | a predicate/function level. Then it's easy to show that: |
2355 | @verbatim |
2356 | T0(IF(e,e1,e2) = T1(IF(e,e1,e2)) |
2357 | T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2)) |
2358 | @endverbatim |
2359 | |
2360 | @retval |
2361 | 0 ok |
2362 | @retval |
2363 | 1 got error |
2364 | */ |
2365 | |
2366 | bool |
2367 | Item_func_if::fix_fields(THD *thd, Item **ref) |
2368 | { |
2369 | DBUG_ASSERT(fixed == 0); |
2370 | args[0]->top_level_item(); |
2371 | |
2372 | if (Item_func::fix_fields(thd, ref)) |
2373 | return 1; |
2374 | |
2375 | return 0; |
2376 | } |
2377 | |
2378 | |
2379 | bool |
2380 | Item_func_if::eval_not_null_tables(void *opt_arg) |
2381 | { |
2382 | if (Item_func::eval_not_null_tables(NULL)) |
2383 | return 1; |
2384 | |
2385 | not_null_tables_cache= (args[1]->not_null_tables() & |
2386 | args[2]->not_null_tables()); |
2387 | |
2388 | return 0; |
2389 | } |
2390 | |
2391 | |
2392 | void Item_func_if::fix_after_pullout(st_select_lex *new_parent, |
2393 | Item **ref, bool merge) |
2394 | { |
2395 | /* This will re-calculate attributes of the arguments */ |
2396 | Item_func::fix_after_pullout(new_parent, ref, merge); |
2397 | /* Then, re-calculate not_null_tables_cache according to our special rules */ |
2398 | eval_not_null_tables(NULL); |
2399 | } |
2400 | |
2401 | |
2402 | void Item_func_nullif::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, |
2403 | List<Item> &fields, uint flags) |
2404 | { |
2405 | if (m_cache) |
2406 | { |
2407 | flags|= SPLIT_SUM_SKIP_REGISTERED; // See Item_func::split_sum_func |
2408 | m_cache->split_sum_func2_example(thd, ref_pointer_array, fields, flags); |
2409 | args[1]->split_sum_func2(thd, ref_pointer_array, fields, &args[1], flags); |
2410 | } |
2411 | else |
2412 | { |
2413 | Item_func::split_sum_func(thd, ref_pointer_array, fields, flags); |
2414 | } |
2415 | } |
2416 | |
2417 | |
2418 | bool Item_func_nullif::walk(Item_processor processor, |
2419 | bool walk_subquery, void *arg) |
2420 | { |
2421 | /* |
2422 | No needs to iterate through args[2] when it's just a copy of args[0]. |
2423 | See MDEV-9712 Performance degradation of nested NULLIF |
2424 | */ |
2425 | uint tmp_count= arg_count == 2 || args[0] == args[2] ? 2 : 3; |
2426 | for (uint i= 0; i < tmp_count; i++) |
2427 | { |
2428 | if (args[i]->walk(processor, walk_subquery, arg)) |
2429 | return true; |
2430 | } |
2431 | return (this->*processor)(arg); |
2432 | } |
2433 | |
2434 | |
2435 | void Item_func_nullif::update_used_tables() |
2436 | { |
2437 | if (m_cache) |
2438 | { |
2439 | used_tables_and_const_cache_init(); |
2440 | used_tables_and_const_cache_update_and_join(m_cache->get_example()); |
2441 | used_tables_and_const_cache_update_and_join(arg_count, args); |
2442 | } |
2443 | else |
2444 | { |
2445 | /* |
2446 | MDEV-9712 Performance degradation of nested NULLIF |
2447 | No needs to iterate through args[2] when it's just a copy of args[0]. |
2448 | */ |
2449 | DBUG_ASSERT(arg_count == 3); |
2450 | used_tables_and_const_cache_init(); |
2451 | used_tables_and_const_cache_update_and_join(args[0] == args[2] ? 2 : 3, |
2452 | args); |
2453 | } |
2454 | } |
2455 | |
2456 | |
2457 | |
2458 | void |
2459 | Item_func_nullif::fix_length_and_dec() |
2460 | { |
2461 | /* |
2462 | If this is the first invocation of fix_length_and_dec(), create the |
2463 | third argument as a copy of the first. This cannot be done before |
2464 | fix_fields(), because fix_fields() might replace items, |
2465 | for exampe NOT x --> x==0, or (SELECT 1) --> 1. |
2466 | See also class Item_func_nullif declaration. |
2467 | */ |
2468 | if (arg_count == 2) |
2469 | args[arg_count++]= m_arg0 ? m_arg0 : args[0]; |
2470 | |
2471 | THD *thd= current_thd; |
2472 | /* |
2473 | At prepared statement EXECUTE time, args[0] can already |
2474 | point to a different Item, created during PREPARE time fix_length_and_dec(). |
2475 | For example, if character set conversion was needed, arguments can look |
2476 | like this: |
2477 | |
2478 | args[0]= > Item_func_conv_charset \ |
2479 | l_expr |
2480 | args[2]= >------------------------/ |
2481 | |
2482 | Otherwise (during PREPARE or convensional execution), |
2483 | args[0] and args[2] should still point to the same original l_expr. |
2484 | */ |
2485 | DBUG_ASSERT(args[0] == args[2] || thd->stmt_arena->is_stmt_execute()); |
2486 | if (args[0]->type() == SUM_FUNC_ITEM && |
2487 | !thd->lex->is_ps_or_view_context_analysis()) |
2488 | { |
2489 | /* |
2490 | NULLIF(l_expr, r_expr) |
2491 | |
2492 | is calculated in the way to return a result equal to: |
2493 | |
2494 | CASE WHEN l_expr = r_expr THEN NULL ELSE r_expr END. |
2495 | |
2496 | There's nothing special with r_expr, because it's referenced |
2497 | only by args[1] and nothing else. |
2498 | |
2499 | l_expr needs a special treatment, as it's referenced by both |
2500 | args[0] and args[2] initially. |
2501 | |
2502 | args[2] is used to return the value. Afrer all transformations |
2503 | (e.g. in fix_length_and_dec(), equal field propagation, etc) |
2504 | args[2] points to a an Item which preserves the exact data type and |
2505 | attributes (e.g. collation) of the original l_expr. |
2506 | It can point: |
2507 | - to the original l_expr |
2508 | - to an Item_cache pointing to l_expr |
2509 | - to a constant of the same data type with l_expr. |
2510 | |
2511 | args[0] is used for comparison. It can be replaced: |
2512 | |
2513 | - to Item_func_conv_charset by character set aggregation routines |
2514 | - to a constant Item by equal field propagation routines |
2515 | (in case of Item_field) |
2516 | |
2517 | The data type and/or the attributes of args[0] can differ from |
2518 | the data type and the attributes of the original l_expr, to make |
2519 | it comparable to args[1] (which points to r_expr or its replacement). |
2520 | |
2521 | For aggregate functions we have to wrap the original args[0]/args[2] |
2522 | into Item_cache (see MDEV-9181). In this case the Item_cache |
2523 | instance becomes the subject to character set conversion instead of |
2524 | the original args[0]/args[2], while the original args[0]/args[2] get |
2525 | hidden inside the cache. |
2526 | |
2527 | Some examples of what NULLIF can end up with after argument |
2528 | substitution (we don't mention args[1] in some cases for simplicity): |
2529 | |
2530 | 1. l_expr is not an aggragate function: |
2531 | |
2532 | a. No conversion happened. |
2533 | args[0] and args[2] were not replaced to something else |
2534 | (i.e. neither by character set conversion, nor by propagation): |
2535 | |
2536 | args[1] > r_expr |
2537 | args[0] \ |
2538 | l_expr |
2539 | args[2] / |
2540 | |
2541 | b. Conversion of args[0] happened: |
2542 | |
2543 | CREATE OR REPLACE TABLE t1 ( |
2544 | a CHAR(10) CHARACTER SET latin1, |
2545 | b CHAR(10) CHARACTER SET utf8); |
2546 | SELECT * FROM t1 WHERE NULLIF(a,b); |
2547 | |
2548 | args[1] > r_expr (Item_field for t1.b) |
2549 | args[0] > Item_func_conv_charset\ |
2550 | l_expr (Item_field for t1.a) |
2551 | args[2] > ----------------------/ |
2552 | |
2553 | c. Conversion of args[1] happened: |
2554 | |
2555 | CREATE OR REPLACE TABLE t1 ( |
2556 | a CHAR(10) CHARACTER SET utf8, |
2557 | b CHAR(10) CHARACTER SET latin1); |
2558 | SELECT * FROM t1 WHERE NULLIF(a,b); |
2559 | |
2560 | args[1] > Item_func_conv_charset -> r_expr (Item_field for t1.b) |
2561 | args[0] \ |
2562 | l_expr (Item_field for t1.a) |
2563 | args[2] / |
2564 | |
2565 | d. Conversion of only args[0] happened (by equal field proparation): |
2566 | |
2567 | CREATE OR REPLACE TABLE t1 ( |
2568 | a CHAR(10), |
2569 | b CHAR(10)); |
2570 | SELECT * FROM t1 WHERE NULLIF(a,b) AND a='a'; |
2571 | |
2572 | args[1] > r_expr (Item_field for t1.b) |
2573 | args[0] > Item_string('a') (constant replacement for t1.a) |
2574 | args[2] > l_expr (Item_field for t1.a) |
2575 | |
2576 | e. Conversion of both args[0] and args[2] happened |
2577 | (by equal field propagation): |
2578 | |
2579 | CREATE OR REPLACE TABLE t1 (a INT,b INT); |
2580 | SELECT * FROM t1 WHERE NULLIF(a,b) AND a=5; |
2581 | |
2582 | args[1] > r_expr (Item_field for "b") |
2583 | args[0] \ |
2584 | Item_int (5) (constant replacement for "a") |
2585 | args[2] / |
2586 | |
2587 | 2. In case if l_expr is an aggregate function: |
2588 | |
2589 | a. No conversion happened: |
2590 | |
2591 | args[0] \ |
2592 | Item_cache > l_expr |
2593 | args[2] / |
2594 | |
2595 | b. Conversion of args[0] happened: |
2596 | |
2597 | args[0] > Item_func_conv_charset \ |
2598 | Item_cache > l_expr |
2599 | args[2] >------------------------/ |
2600 | |
2601 | c. Conversion of both args[0] and args[2] happened. |
2602 | (e.g. by equal expression propagation) |
2603 | TODO: check if it's possible (and add an example query if so). |
2604 | */ |
2605 | m_cache= args[0]->cmp_type() == STRING_RESULT ? |
2606 | new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) : |
2607 | args[0]->get_cache(thd); |
2608 | m_cache->setup(thd, args[0]); |
2609 | m_cache->store(args[0]); |
2610 | m_cache->set_used_tables(args[0]->used_tables()); |
2611 | thd->change_item_tree(&args[0], m_cache); |
2612 | thd->change_item_tree(&args[2], m_cache); |
2613 | } |
2614 | set_handler(args[2]->type_handler()); |
2615 | collation.set(args[2]->collation); |
2616 | decimals= args[2]->decimals; |
2617 | unsigned_flag= args[2]->unsigned_flag; |
2618 | fix_char_length(args[2]->max_char_length()); |
2619 | maybe_null=1; |
2620 | m_arg0= args[0]; |
2621 | setup_args_and_comparator(thd, &cmp); |
2622 | /* |
2623 | A special code for EXECUTE..PREPARE. |
2624 | |
2625 | If args[0] did not change, then we don't remember it, as it can point |
2626 | to a temporary Item object which will be destroyed between PREPARE |
2627 | and EXECUTE. EXECUTE time fix_length_and_dec() will correctly set args[2] |
2628 | from args[0] again. |
2629 | |
2630 | If args[0] changed, then it can be Item_func_conv_charset() for the |
2631 | original args[0], which was permanently installed during PREPARE time |
2632 | into the item tree as a wrapper for args[0], using change_item_tree(), i.e. |
2633 | |
2634 | NULLIF(latin1_field, 'a' COLLATE utf8_bin) |
2635 | |
2636 | was "rewritten" to: |
2637 | |
2638 | CASE WHEN CONVERT(latin1_field USING utf8) = 'a' COLLATE utf8_bin |
2639 | THEN NULL |
2640 | ELSE latin1_field |
2641 | |
2642 | - m_args0 points to Item_field corresponding to latin1_field |
2643 | - args[0] points to Item_func_conv_charset |
2644 | - args[0]->args[0] is equal to m_args0 |
2645 | - args[1] points to Item_func_set_collation |
2646 | - args[2] points is eqial to m_args0 |
2647 | |
2648 | In this case we remember and reuse m_arg0 during EXECUTE time as args[2]. |
2649 | |
2650 | QQ: How to make sure that m_args0 does not point |
2651 | to something temporary which will be destoyed between PREPARE and EXECUTE. |
2652 | The condition below should probably be more strict and somehow check that: |
2653 | - change_item_tree() was called for the new args[0] |
2654 | - m_args0 is referenced from inside args[0], e.g. as a function argument, |
2655 | and therefore it is also something that won't be destroyed between |
2656 | PREPARE and EXECUTE. |
2657 | Any ideas? |
2658 | */ |
2659 | if (args[0] == m_arg0) |
2660 | m_arg0= NULL; |
2661 | } |
2662 | |
2663 | |
2664 | void Item_func_nullif::print(String *str, enum_query_type query_type) |
2665 | { |
2666 | /* |
2667 | NULLIF(a,b) is implemented according to the SQL standard as a short for |
2668 | CASE WHEN a=b THEN NULL ELSE a END |
2669 | |
2670 | The constructor of Item_func_nullif sets args[0] and args[2] to the |
2671 | same item "a", and sets args[1] to "b". |
2672 | |
2673 | If "this" is a part of a WHERE or ON condition, then: |
2674 | - the left "a" is a subject to equal field propagation with ANY_SUBST. |
2675 | - the right "a" is a subject to equal field propagation with IDENTITY_SUBST. |
2676 | Therefore, after equal field propagation args[0] and args[2] can point |
2677 | to different items. |
2678 | */ |
2679 | if ((query_type & QT_ITEM_ORIGINAL_FUNC_NULLIF) || |
2680 | (arg_count == 2) || |
2681 | (args[0] == args[2])) |
2682 | { |
2683 | /* |
2684 | If QT_ITEM_ORIGINAL_FUNC_NULLIF is requested, |
2685 | that means we want the original NULLIF() representation, |
2686 | e.g. when we are in: |
2687 | SHOW CREATE {VIEW|FUNCTION|PROCEDURE} |
2688 | |
2689 | The original representation is possible only if |
2690 | args[0] and args[2] still point to the same Item. |
2691 | |
2692 | The caller must never pass call print() with QT_ITEM_ORIGINAL_FUNC_NULLIF |
2693 | if an expression has undergone some optimization |
2694 | (e.g. equal field propagation done in optimize_cond()) already and |
2695 | NULLIF() potentially has two different representations of "a": |
2696 | - one "a" for comparison |
2697 | - another "a" for the returned value! |
2698 | */ |
2699 | DBUG_ASSERT(arg_count == 2 || |
2700 | args[0] == args[2] || current_thd->lex->context_analysis_only); |
2701 | str->append(func_name()); |
2702 | str->append('('); |
2703 | if (arg_count == 2) |
2704 | args[0]->print(str, query_type); |
2705 | else |
2706 | args[2]->print(str, query_type); |
2707 | str->append(','); |
2708 | args[1]->print(str, query_type); |
2709 | str->append(')'); |
2710 | } |
2711 | else |
2712 | { |
2713 | /* |
2714 | args[0] and args[2] are different items. |
2715 | This is possible after WHERE optimization (equal fields propagation etc), |
2716 | e.g. in EXPLAIN EXTENDED or EXPLAIN FORMAT=JSON. |
2717 | As it's not possible to print as a function with 2 arguments any more, |
2718 | do it in the CASE style. |
2719 | */ |
2720 | str->append(STRING_WITH_LEN("(case when " )); |
2721 | args[0]->print(str, query_type); |
2722 | str->append(STRING_WITH_LEN(" = " )); |
2723 | args[1]->print(str, query_type); |
2724 | str->append(STRING_WITH_LEN(" then NULL else " )); |
2725 | args[2]->print(str, query_type); |
2726 | str->append(STRING_WITH_LEN(" end)" )); |
2727 | } |
2728 | } |
2729 | |
2730 | |
2731 | int Item_func_nullif::compare() |
2732 | { |
2733 | if (m_cache) |
2734 | m_cache->cache_value(); |
2735 | return cmp.compare(); |
2736 | } |
2737 | |
2738 | /** |
2739 | @note |
2740 | Note that we have to evaluate the first argument twice as the compare |
2741 | may have been done with a different type than return value |
2742 | @return |
2743 | NULL if arguments are equal |
2744 | @return |
2745 | the first argument if not equal |
2746 | */ |
2747 | |
2748 | double |
2749 | Item_func_nullif::real_op() |
2750 | { |
2751 | DBUG_ASSERT(fixed == 1); |
2752 | double value; |
2753 | if (!compare()) |
2754 | { |
2755 | null_value=1; |
2756 | return 0.0; |
2757 | } |
2758 | value= args[2]->val_real(); |
2759 | null_value= args[2]->null_value; |
2760 | return value; |
2761 | } |
2762 | |
2763 | longlong |
2764 | Item_func_nullif::int_op() |
2765 | { |
2766 | DBUG_ASSERT(fixed == 1); |
2767 | longlong value; |
2768 | if (!compare()) |
2769 | { |
2770 | null_value=1; |
2771 | return 0; |
2772 | } |
2773 | value= args[2]->val_int(); |
2774 | null_value= args[2]->null_value; |
2775 | return value; |
2776 | } |
2777 | |
2778 | String * |
2779 | Item_func_nullif::str_op(String *str) |
2780 | { |
2781 | DBUG_ASSERT(fixed == 1); |
2782 | String *res; |
2783 | if (!compare()) |
2784 | { |
2785 | null_value=1; |
2786 | return 0; |
2787 | } |
2788 | res= args[2]->val_str(str); |
2789 | null_value= args[2]->null_value; |
2790 | return res; |
2791 | } |
2792 | |
2793 | |
2794 | my_decimal * |
2795 | Item_func_nullif::decimal_op(my_decimal * decimal_value) |
2796 | { |
2797 | DBUG_ASSERT(fixed == 1); |
2798 | my_decimal *res; |
2799 | if (!compare()) |
2800 | { |
2801 | null_value=1; |
2802 | return 0; |
2803 | } |
2804 | res= args[2]->val_decimal(decimal_value); |
2805 | null_value= args[2]->null_value; |
2806 | return res; |
2807 | } |
2808 | |
2809 | |
2810 | bool |
2811 | Item_func_nullif::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) |
2812 | { |
2813 | DBUG_ASSERT(fixed == 1); |
2814 | if (!compare()) |
2815 | return (null_value= true); |
2816 | Datetime dt(current_thd, args[2], fuzzydate); |
2817 | return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); |
2818 | } |
2819 | |
2820 | |
2821 | bool |
2822 | Item_func_nullif::time_op(MYSQL_TIME *ltime) |
2823 | { |
2824 | DBUG_ASSERT(fixed == 1); |
2825 | if (!compare()) |
2826 | return (null_value= true); |
2827 | return (null_value= Time(args[2]).copy_to_mysql_time(ltime)); |
2828 | |
2829 | } |
2830 | |
2831 | |
2832 | bool |
2833 | Item_func_nullif::is_null() |
2834 | { |
2835 | return (null_value= (!compare() ? 1 : args[2]->is_null())); |
2836 | } |
2837 | |
2838 | void Item_func_case::reorder_args(uint start) |
2839 | { |
2840 | /* |
2841 | Reorder args, to have at first the optional CASE expression, then all WHEN |
2842 | expressions, then all THEN expressions. And the optional ELSE expression |
2843 | at the end. |
2844 | |
2845 | We reorder an even number of arguments, starting from start. |
2846 | */ |
2847 | uint count = (arg_count - start) / 2; |
2848 | const size_t size= sizeof(Item*) * count * 2; |
2849 | Item **arg_buffer= (Item **)my_safe_alloca(size); |
2850 | memcpy(arg_buffer, &args[start], size); |
2851 | for (uint i= 0; i < count; i++) |
2852 | { |
2853 | args[start + i]= arg_buffer[i*2]; |
2854 | args[start + i + count]= arg_buffer[i*2 + 1]; |
2855 | } |
2856 | my_safe_afree(arg_buffer, size); |
2857 | } |
2858 | |
2859 | |
2860 | |
2861 | /** |
2862 | Find and return matching items for CASE or ELSE item if all compares |
2863 | are failed or NULL if ELSE item isn't defined. |
2864 | |
2865 | IMPLEMENTATION |
2866 | In order to do correct comparisons of the CASE expression (the expression |
2867 | between CASE and the first WHEN) with each WHEN expression several |
2868 | comparators are used. One for each result type. CASE expression can be |
2869 | evaluated up to # of different result types are used. To check whether |
2870 | the CASE expression already was evaluated for a particular result type |
2871 | a bit mapped variable value_added_map is used. Result types are mapped |
2872 | to it according to their int values i.e. STRING_RESULT is mapped to bit |
2873 | 0, REAL_RESULT to bit 1, so on. |
2874 | |
2875 | @retval |
2876 | NULL Nothing found and there is no ELSE expression defined |
2877 | @retval |
2878 | item Found item or ELSE item if defined and all comparisons are |
2879 | failed |
2880 | */ |
2881 | |
2882 | Item *Item_func_case_searched::find_item() |
2883 | { |
2884 | uint count= when_count(); |
2885 | for (uint i= 0 ; i < count ; i++) |
2886 | { |
2887 | if (args[i]->val_bool()) |
2888 | return args[i + count]; |
2889 | } |
2890 | Item **pos= Item_func_case_searched::else_expr_addr(); |
2891 | return pos ? pos[0] : 0; |
2892 | } |
2893 | |
2894 | |
2895 | Item *Item_func_case_simple::find_item() |
2896 | { |
2897 | /* Compare every WHEN argument with it and return the first match */ |
2898 | uint idx; |
2899 | if (!Predicant_to_list_comparator::cmp(this, &idx, NULL)) |
2900 | return args[idx + when_count()]; |
2901 | Item **pos= Item_func_case_simple::else_expr_addr(); |
2902 | return pos ? pos[0] : 0; |
2903 | } |
2904 | |
2905 | |
2906 | Item *Item_func_decode_oracle::find_item() |
2907 | { |
2908 | uint idx; |
2909 | if (!Predicant_to_list_comparator::cmp_nulls_equal(this, &idx)) |
2910 | return args[idx + when_count()]; |
2911 | Item **pos= Item_func_decode_oracle::else_expr_addr(); |
2912 | return pos ? pos[0] : 0; |
2913 | } |
2914 | |
2915 | |
2916 | String *Item_func_case::str_op(String *str) |
2917 | { |
2918 | DBUG_ASSERT(fixed == 1); |
2919 | String *res; |
2920 | Item *item= find_item(); |
2921 | |
2922 | if (!item) |
2923 | { |
2924 | null_value=1; |
2925 | return 0; |
2926 | } |
2927 | null_value= 0; |
2928 | if (!(res=item->val_str(str))) |
2929 | null_value= 1; |
2930 | return res; |
2931 | } |
2932 | |
2933 | |
2934 | longlong Item_func_case::int_op() |
2935 | { |
2936 | DBUG_ASSERT(fixed == 1); |
2937 | Item *item= find_item(); |
2938 | longlong res; |
2939 | |
2940 | if (!item) |
2941 | { |
2942 | null_value=1; |
2943 | return 0; |
2944 | } |
2945 | res=item->val_int(); |
2946 | null_value=item->null_value; |
2947 | return res; |
2948 | } |
2949 | |
2950 | double Item_func_case::real_op() |
2951 | { |
2952 | DBUG_ASSERT(fixed == 1); |
2953 | Item *item= find_item(); |
2954 | double res; |
2955 | |
2956 | if (!item) |
2957 | { |
2958 | null_value=1; |
2959 | return 0; |
2960 | } |
2961 | res= item->val_real(); |
2962 | null_value=item->null_value; |
2963 | return res; |
2964 | } |
2965 | |
2966 | |
2967 | my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value) |
2968 | { |
2969 | DBUG_ASSERT(fixed == 1); |
2970 | Item *item= find_item(); |
2971 | my_decimal *res; |
2972 | |
2973 | if (!item) |
2974 | { |
2975 | null_value=1; |
2976 | return 0; |
2977 | } |
2978 | |
2979 | res= item->val_decimal(decimal_value); |
2980 | null_value= item->null_value; |
2981 | return res; |
2982 | } |
2983 | |
2984 | |
2985 | bool Item_func_case::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) |
2986 | { |
2987 | DBUG_ASSERT(fixed == 1); |
2988 | Item *item= find_item(); |
2989 | if (!item) |
2990 | return (null_value= true); |
2991 | Datetime dt(current_thd, item, fuzzydate); |
2992 | return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type())); |
2993 | } |
2994 | |
2995 | |
2996 | bool Item_func_case::time_op(MYSQL_TIME *ltime) |
2997 | { |
2998 | DBUG_ASSERT(fixed == 1); |
2999 | Item *item= find_item(); |
3000 | if (!item) |
3001 | return (null_value= true); |
3002 | return (null_value= Time(item).copy_to_mysql_time(ltime)); |
3003 | } |
3004 | |
3005 | |
3006 | bool Item_func_case::fix_fields(THD *thd, Item **ref) |
3007 | { |
3008 | bool res= Item_func::fix_fields(thd, ref); |
3009 | |
3010 | Item **pos= else_expr_addr(); |
3011 | if (!pos || pos[0]->maybe_null) |
3012 | maybe_null= 1; |
3013 | return res; |
3014 | } |
3015 | |
3016 | |
3017 | /** |
3018 | Check if (*place) and new_value points to different Items and call |
3019 | THD::change_item_tree() if needed. |
3020 | */ |
3021 | |
3022 | static void propagate_and_change_item_tree(THD *thd, Item **place, |
3023 | COND_EQUAL *cond, |
3024 | const Item::Context &ctx) |
3025 | { |
3026 | Item *new_value= (*place)->propagate_equal_fields(thd, ctx, cond); |
3027 | if (new_value && *place != new_value) |
3028 | thd->change_item_tree(place, new_value); |
3029 | } |
3030 | |
3031 | |
3032 | bool Item_func_case_simple::prepare_predicant_and_values(THD *thd, |
3033 | uint *found_types, |
3034 | bool nulls_equal) |
3035 | { |
3036 | bool have_null= false; |
3037 | uint type_cnt; |
3038 | Type_handler_hybrid_field_type tmp; |
3039 | uint ncases= when_count(); |
3040 | add_predicant(this, 0); |
3041 | for (uint i= 0 ; i < ncases; i++) |
3042 | { |
3043 | if (nulls_equal ? |
3044 | add_value("case..when" , this, i + 1) : |
3045 | add_value_skip_null("case..when" , this, i + 1, &have_null)) |
3046 | return true; |
3047 | } |
3048 | all_values_added(&tmp, &type_cnt, &m_found_types); |
3049 | #ifndef DBUG_OFF |
3050 | Predicant_to_list_comparator::debug_print(thd); |
3051 | #endif |
3052 | return false; |
3053 | } |
3054 | |
3055 | |
3056 | void Item_func_case_searched::fix_length_and_dec() |
3057 | { |
3058 | THD *thd= current_thd; |
3059 | aggregate_then_and_else_arguments(thd, when_count()); |
3060 | } |
3061 | |
3062 | |
3063 | void Item_func_case_simple::fix_length_and_dec() |
3064 | { |
3065 | THD *thd= current_thd; |
3066 | if (!aggregate_then_and_else_arguments(thd, when_count() + 1)) |
3067 | aggregate_switch_and_when_arguments(thd, false); |
3068 | } |
3069 | |
3070 | |
3071 | void Item_func_decode_oracle::fix_length_and_dec() |
3072 | { |
3073 | THD *thd= current_thd; |
3074 | if (!aggregate_then_and_else_arguments(thd, when_count() + 1)) |
3075 | aggregate_switch_and_when_arguments(thd, true); |
3076 | } |
3077 | |
3078 | |
3079 | /* |
3080 | Aggregate all THEN and ELSE expression types |
3081 | and collations when string result |
3082 | |
3083 | @param THD - current thd |
3084 | @param start - an element in args to start aggregating from |
3085 | */ |
3086 | bool Item_func_case::aggregate_then_and_else_arguments(THD *thd, uint start) |
3087 | { |
3088 | if (aggregate_for_result(func_name(), args + start, arg_count - start, true)) |
3089 | return true; |
3090 | |
3091 | if (fix_attributes(args + start, arg_count - start)) |
3092 | return true; |
3093 | |
3094 | return false; |
3095 | } |
3096 | |
3097 | |
3098 | /* |
3099 | Aggregate the predicant expression and all WHEN expression types |
3100 | and collations when string comparison |
3101 | */ |
3102 | bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd, |
3103 | bool nulls_eq) |
3104 | { |
3105 | uint ncases= when_count(); |
3106 | m_found_types= 0; |
3107 | if (prepare_predicant_and_values(thd, &m_found_types, nulls_eq)) |
3108 | { |
3109 | /* |
3110 | If Predicant_to_list_comparator() fails to prepare components, |
3111 | it must put an error into the diagnostics area. This is needed |
3112 | to make fix_fields() catches such errors. |
3113 | */ |
3114 | DBUG_ASSERT(thd->is_error()); |
3115 | return true; |
3116 | } |
3117 | |
3118 | if (!(m_found_types= collect_cmp_types(args, ncases + 1))) |
3119 | return true; |
3120 | |
3121 | if (m_found_types & (1U << STRING_RESULT)) |
3122 | { |
3123 | /* |
3124 | If we'll do string comparison, we also need to aggregate |
3125 | character set and collation for first/WHEN items and |
3126 | install converters for some of them to cmp_collation when necessary. |
3127 | This is done because cmp_item compatators cannot compare |
3128 | strings in two different character sets. |
3129 | Some examples when we install converters: |
3130 | |
3131 | 1. Converter installed for the first expression: |
3132 | |
3133 | CASE latin1_item WHEN utf16_item THEN ... END |
3134 | |
3135 | is replaced to: |
3136 | |
3137 | CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END |
3138 | |
3139 | 2. Converter installed for the left WHEN item: |
3140 | |
3141 | CASE utf16_item WHEN latin1_item THEN ... END |
3142 | |
3143 | is replaced to: |
3144 | |
3145 | CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END |
3146 | */ |
3147 | if (agg_arg_charsets_for_comparison(cmp_collation, args, ncases + 1)) |
3148 | return true; |
3149 | } |
3150 | |
3151 | if (make_unique_cmp_items(thd, cmp_collation.collation)) |
3152 | return true; |
3153 | |
3154 | return false; |
3155 | } |
3156 | |
3157 | |
3158 | Item* Item_func_case_simple::propagate_equal_fields(THD *thd, |
3159 | const Context &ctx, |
3160 | COND_EQUAL *cond) |
3161 | { |
3162 | const Type_handler *first_expr_cmp_handler; |
3163 | |
3164 | first_expr_cmp_handler= args[0]->type_handler_for_comparison(); |
3165 | /* |
3166 | Cannot replace the CASE (the switch) argument if |
3167 | there are multiple comparison types were found, or found a single |
3168 | comparison type that is not equal to args[0]->cmp_type(). |
3169 | |
3170 | - Example: multiple comparison types, can't propagate: |
3171 | WHERE CASE str_column |
3172 | WHEN 'string' THEN TRUE |
3173 | WHEN 1 THEN TRUE |
3174 | ELSE FALSE END; |
3175 | |
3176 | - Example: a single incompatible comparison type, can't propagate: |
3177 | WHERE CASE str_column |
3178 | WHEN DATE'2001-01-01' THEN TRUE |
3179 | ELSE FALSE END; |
3180 | |
3181 | - Example: a single incompatible comparison type, can't propagate: |
3182 | WHERE CASE str_column |
3183 | WHEN 1 THEN TRUE |
3184 | ELSE FALSE END; |
3185 | |
3186 | - Example: a single compatible comparison type, ok to propagate: |
3187 | WHERE CASE str_column |
3188 | WHEN 'str1' THEN TRUE |
3189 | WHEN 'str2' THEN TRUE |
3190 | ELSE FALSE END; |
3191 | */ |
3192 | if (m_found_types == (1UL << first_expr_cmp_handler->cmp_type())) |
3193 | propagate_and_change_item_tree(thd, &args[0], cond, |
3194 | Context(ANY_SUBST, first_expr_cmp_handler, cmp_collation.collation)); |
3195 | |
3196 | /* |
3197 | These arguments are in comparison. |
3198 | Allow invariants of the same value during propagation. |
3199 | Note, as we pass ANY_SUBST, none of the WHEN arguments will be |
3200 | replaced to zero-filled constants (only IDENTITY_SUBST allows this). |
3201 | Such a change for WHEN arguments would require rebuilding cmp_items. |
3202 | */ |
3203 | uint i, count= when_count(); |
3204 | for (i= 1; i <= count; i++) |
3205 | { |
3206 | Type_handler_hybrid_field_type tmp(first_expr_cmp_handler); |
3207 | if (!tmp.aggregate_for_comparison(args[i]->type_handler_for_comparison())) |
3208 | propagate_and_change_item_tree(thd, &args[i], cond, |
3209 | Context(ANY_SUBST, tmp.type_handler(), cmp_collation.collation)); |
3210 | } |
3211 | |
3212 | // THEN and ELSE arguments (they are not in comparison) |
3213 | for (; i < arg_count; i++) |
3214 | propagate_and_change_item_tree(thd, &args[i], cond, Context_identity()); |
3215 | |
3216 | return this; |
3217 | } |
3218 | |
3219 | |
3220 | void Item_func_case::print_when_then_arguments(String *str, |
3221 | enum_query_type query_type, |
3222 | Item **items, uint count) |
3223 | { |
3224 | for (uint i=0 ; i < count ; i++) |
3225 | { |
3226 | str->append(STRING_WITH_LEN("when " )); |
3227 | items[i]->print_parenthesised(str, query_type, precedence()); |
3228 | str->append(STRING_WITH_LEN(" then " )); |
3229 | items[i + count]->print_parenthesised(str, query_type, precedence()); |
3230 | str->append(' '); |
3231 | } |
3232 | } |
3233 | |
3234 | |
3235 | void Item_func_case::print_else_argument(String *str, |
3236 | enum_query_type query_type, |
3237 | Item *item) |
3238 | { |
3239 | str->append(STRING_WITH_LEN("else " )); |
3240 | item->print_parenthesised(str, query_type, precedence()); |
3241 | str->append(' '); |
3242 | } |
3243 | |
3244 | |
3245 | void Item_func_case_searched::print(String *str, enum_query_type query_type) |
3246 | { |
3247 | Item **pos; |
3248 | str->append(STRING_WITH_LEN("case " )); |
3249 | print_when_then_arguments(str, query_type, &args[0], when_count()); |
3250 | if ((pos= Item_func_case_searched::else_expr_addr())) |
3251 | print_else_argument(str, query_type, pos[0]); |
3252 | str->append(STRING_WITH_LEN("end" )); |
3253 | } |
3254 | |
3255 | |
3256 | void Item_func_case_simple::print(String *str, enum_query_type query_type) |
3257 | { |
3258 | Item **pos; |
3259 | str->append(STRING_WITH_LEN("case " )); |
3260 | args[0]->print_parenthesised(str, query_type, precedence()); |
3261 | str->append(' '); |
3262 | print_when_then_arguments(str, query_type, &args[1], when_count()); |
3263 | if ((pos= Item_func_case_simple::else_expr_addr())) |
3264 | print_else_argument(str, query_type, pos[0]); |
3265 | str->append(STRING_WITH_LEN("end" )); |
3266 | } |
3267 | |
3268 | |
3269 | void Item_func_decode_oracle::print(String *str, enum_query_type query_type) |
3270 | { |
3271 | str->append(func_name()); |
3272 | str->append('('); |
3273 | args[0]->print(str, query_type); |
3274 | for (uint i= 1, count= when_count() ; i <= count; i++) |
3275 | { |
3276 | str->append(','); |
3277 | args[i]->print(str, query_type); |
3278 | str->append(','); |
3279 | args[i+count]->print(str, query_type); |
3280 | } |
3281 | Item **else_expr= Item_func_case_simple::else_expr_addr(); |
3282 | if (else_expr) |
3283 | { |
3284 | str->append(','); |
3285 | (*else_expr)->print(str, query_type); |
3286 | } |
3287 | str->append(')'); |
3288 | } |
3289 | |
3290 | |
3291 | /** |
3292 | Coalesce - return first not NULL argument. |
3293 | */ |
3294 | |
3295 | String *Item_func_coalesce::str_op(String *str) |
3296 | { |
3297 | DBUG_ASSERT(fixed == 1); |
3298 | null_value=0; |
3299 | for (uint i=0 ; i < arg_count ; i++) |
3300 | { |
3301 | String *res; |
3302 | if ((res=args[i]->val_str(str))) |
3303 | return res; |
3304 | } |
3305 | null_value=1; |
3306 | return 0; |
3307 | } |
3308 | |
3309 | longlong Item_func_coalesce::int_op() |
3310 | { |
3311 | DBUG_ASSERT(fixed == 1); |
3312 | null_value=0; |
3313 | for (uint i=0 ; i < arg_count ; i++) |
3314 | { |
3315 | longlong res=args[i]->val_int(); |
3316 | if (!args[i]->null_value) |
3317 | return res; |
3318 | } |
3319 | null_value=1; |
3320 | return 0; |
3321 | } |
3322 | |
3323 | double Item_func_coalesce::real_op() |
3324 | { |
3325 | DBUG_ASSERT(fixed == 1); |
3326 | null_value=0; |
3327 | for (uint i=0 ; i < arg_count ; i++) |
3328 | { |
3329 | double res= args[i]->val_real(); |
3330 | if (!args[i]->null_value) |
3331 | return res; |
3332 | } |
3333 | null_value=1; |
3334 | return 0; |
3335 | } |
3336 | |
3337 | |
3338 | bool Item_func_coalesce::date_op(MYSQL_TIME *ltime, ulonglong fuzzydate) |
3339 | { |
3340 | DBUG_ASSERT(fixed == 1); |
3341 | for (uint i= 0; i < arg_count; i++) |
3342 | { |
3343 | Datetime dt(current_thd, args[i], fuzzydate & ~TIME_FUZZY_DATES); |
3344 | if (!dt.copy_to_mysql_time(ltime, mysql_timestamp_type())) |
3345 | return (null_value= false); |
3346 | } |
3347 | return (null_value= true); |
3348 | } |
3349 | |
3350 | |
3351 | bool Item_func_coalesce::time_op(MYSQL_TIME *ltime) |
3352 | { |
3353 | DBUG_ASSERT(fixed == 1); |
3354 | for (uint i= 0; i < arg_count; i++) |
3355 | { |
3356 | if (!Time(args[i]).copy_to_mysql_time(ltime)) |
3357 | return (null_value= false); |
3358 | } |
3359 | return (null_value= true); |
3360 | } |
3361 | |
3362 | |
3363 | my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) |
3364 | { |
3365 | DBUG_ASSERT(fixed == 1); |
3366 | null_value= 0; |
3367 | for (uint i= 0; i < arg_count; i++) |
3368 | { |
3369 | my_decimal *res= args[i]->val_decimal(decimal_value); |
3370 | if (!args[i]->null_value) |
3371 | return res; |
3372 | } |
3373 | null_value=1; |
3374 | return 0; |
3375 | } |
3376 | |
3377 | |
3378 | /**************************************************************************** |
3379 | Classes and function for the IN operator |
3380 | ****************************************************************************/ |
3381 | |
3382 | /* |
3383 | Determine which of the signed longlong arguments is bigger |
3384 | |
3385 | SYNOPSIS |
3386 | cmp_longs() |
3387 | a_val left argument |
3388 | b_val right argument |
3389 | |
3390 | DESCRIPTION |
3391 | This function will compare two signed longlong arguments |
3392 | and will return -1, 0, or 1 if left argument is smaller than, |
3393 | equal to or greater than the right argument. |
3394 | |
3395 | RETURN VALUE |
3396 | -1 left argument is smaller than the right argument. |
3397 | 0 left argument is equal to the right argument. |
3398 | 1 left argument is greater than the right argument. |
3399 | */ |
3400 | static inline int cmp_longs (longlong a_val, longlong b_val) |
3401 | { |
3402 | return a_val < b_val ? -1 : a_val == b_val ? 0 : 1; |
3403 | } |
3404 | |
3405 | |
3406 | /* |
3407 | Determine which of the unsigned longlong arguments is bigger |
3408 | |
3409 | SYNOPSIS |
3410 | cmp_ulongs() |
3411 | a_val left argument |
3412 | b_val right argument |
3413 | |
3414 | DESCRIPTION |
3415 | This function will compare two unsigned longlong arguments |
3416 | and will return -1, 0, or 1 if left argument is smaller than, |
3417 | equal to or greater than the right argument. |
3418 | |
3419 | RETURN VALUE |
3420 | -1 left argument is smaller than the right argument. |
3421 | 0 left argument is equal to the right argument. |
3422 | 1 left argument is greater than the right argument. |
3423 | */ |
3424 | static inline int cmp_ulongs (ulonglong a_val, ulonglong b_val) |
3425 | { |
3426 | return a_val < b_val ? -1 : a_val == b_val ? 0 : 1; |
3427 | } |
3428 | |
3429 | |
3430 | /* |
3431 | Compare two integers in IN value list format (packed_longlong) |
3432 | |
3433 | SYNOPSIS |
3434 | cmp_longlong() |
3435 | cmp_arg an argument passed to the calling function (my_qsort2) |
3436 | a left argument |
3437 | b right argument |
3438 | |
3439 | DESCRIPTION |
3440 | This function will compare two integer arguments in the IN value list |
3441 | format and will return -1, 0, or 1 if left argument is smaller than, |
3442 | equal to or greater than the right argument. |
3443 | It's used in sorting the IN values list and finding an element in it. |
3444 | Depending on the signedness of the arguments cmp_longlong() will |
3445 | compare them as either signed (using cmp_longs()) or unsigned (using |
3446 | cmp_ulongs()). |
3447 | |
3448 | RETURN VALUE |
3449 | -1 left argument is smaller than the right argument. |
3450 | 0 left argument is equal to the right argument. |
3451 | 1 left argument is greater than the right argument. |
3452 | */ |
3453 | int cmp_longlong(void *cmp_arg, |
3454 | in_longlong::packed_longlong *a, |
3455 | in_longlong::packed_longlong *b) |
3456 | { |
3457 | if (a->unsigned_flag != b->unsigned_flag) |
3458 | { |
3459 | /* |
3460 | One of the args is unsigned and is too big to fit into the |
3461 | positive signed range. Report no match. |
3462 | */ |
3463 | if ((a->unsigned_flag && ((ulonglong) a->val) > (ulonglong) LONGLONG_MAX) |
3464 | || |
3465 | (b->unsigned_flag && ((ulonglong) b->val) > (ulonglong) LONGLONG_MAX)) |
3466 | return a->unsigned_flag ? 1 : -1; |
3467 | /* |
3468 | Although the signedness differs both args can fit into the signed |
3469 | positive range. Make them signed and compare as usual. |
3470 | */ |
3471 | return cmp_longs(a->val, b->val); |
3472 | } |
3473 | if (a->unsigned_flag) |
3474 | return cmp_ulongs((ulonglong) a->val, (ulonglong) b->val); |
3475 | return cmp_longs(a->val, b->val); |
3476 | } |
3477 | |
3478 | static int cmp_double(void *cmp_arg, double *a,double *b) |
3479 | { |
3480 | return *a < *b ? -1 : *a == *b ? 0 : 1; |
3481 | } |
3482 | |
3483 | static int cmp_row(void *cmp_arg, cmp_item_row *a, cmp_item_row *b) |
3484 | { |
3485 | return a->compare(b); |
3486 | } |
3487 | |
3488 | |
3489 | static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b) |
3490 | { |
3491 | /* |
3492 | We need call of fixing buffer pointer, because fast sort just copy |
3493 | decimal buffers in memory and pointers left pointing on old buffer place |
3494 | */ |
3495 | a->fix_buffer_pointer(); |
3496 | b->fix_buffer_pointer(); |
3497 | return my_decimal_cmp(a, b); |
3498 | } |
3499 | |
3500 | |
3501 | bool in_vector::find(Item *item) |
3502 | { |
3503 | uchar *result=get_value(item); |
3504 | if (!result || !used_count) |
3505 | return false; // Null value |
3506 | |
3507 | uint start,end; |
3508 | start=0; end=used_count-1; |
3509 | while (start != end) |
3510 | { |
3511 | uint mid=(start+end+1)/2; |
3512 | int res; |
3513 | if ((res=(*compare)(collation, base+mid*size, result)) == 0) |
3514 | return true; |
3515 | if (res < 0) |
3516 | start=mid; |
3517 | else |
3518 | end=mid-1; |
3519 | } |
3520 | return ((*compare)(collation, base+start*size, result) == 0); |
3521 | } |
3522 | |
3523 | in_string::in_string(THD *thd, uint elements, qsort2_cmp cmp_func, |
3524 | CHARSET_INFO *cs) |
3525 | :in_vector(thd, elements, sizeof(String), cmp_func, cs), |
3526 | tmp(buff, sizeof(buff), &my_charset_bin) |
3527 | {} |
3528 | |
3529 | in_string::~in_string() |
3530 | { |
3531 | if (base) |
3532 | { |
3533 | // base was allocated on THD::mem_root => following is OK |
3534 | for (uint i=0 ; i < count ; i++) |
3535 | ((String*) base)[i].free(); |
3536 | } |
3537 | } |
3538 | |
3539 | void in_string::set(uint pos,Item *item) |
3540 | { |
3541 | String *str=((String*) base)+pos; |
3542 | String *res=item->val_str(str); |
3543 | if (res && res != str) |
3544 | { |
3545 | if (res->uses_buffer_owned_by(str)) |
3546 | res->copy(); |
3547 | if (item->type() == Item::FUNC_ITEM) |
3548 | str->copy(*res); |
3549 | else |
3550 | *str= *res; |
3551 | } |
3552 | if (!str->charset()) |
3553 | { |
3554 | CHARSET_INFO *cs; |
3555 | if (!(cs= item->collation.collation)) |
3556 | cs= &my_charset_bin; // Should never happen for STR items |
3557 | str->set_charset(cs); |
3558 | } |
3559 | } |
3560 | |
3561 | |
3562 | uchar *in_string::get_value(Item *item) |
3563 | { |
3564 | return (uchar*) item->val_str(&tmp); |
3565 | } |
3566 | |
3567 | Item *in_string::create_item(THD *thd) |
3568 | { |
3569 | return new (thd->mem_root) Item_string_for_in_vector(thd, collation); |
3570 | } |
3571 | |
3572 | |
3573 | in_row::in_row(THD *thd, uint elements, Item * item) |
3574 | { |
3575 | base= (char*) new (thd->mem_root) cmp_item_row[count= elements]; |
3576 | size= sizeof(cmp_item_row); |
3577 | compare= (qsort2_cmp) cmp_row; |
3578 | /* |
3579 | We need to reset these as otherwise we will call sort() with |
3580 | uninitialized (even if not used) elements |
3581 | */ |
3582 | used_count= elements; |
3583 | collation= 0; |
3584 | } |
3585 | |
3586 | in_row::~in_row() |
3587 | { |
3588 | if (base) |
3589 | delete [] (cmp_item_row*) base; |
3590 | } |
3591 | |
3592 | uchar *in_row::get_value(Item *item) |
3593 | { |
3594 | tmp.store_value(item); |
3595 | if (item->is_null()) |
3596 | return 0; |
3597 | return (uchar *)&tmp; |
3598 | } |
3599 | |
3600 | void in_row::set(uint pos, Item *item) |
3601 | { |
3602 | DBUG_ENTER("in_row::set" ); |
3603 | DBUG_PRINT("enter" , ("pos: %u item: %p" , pos,item)); |
3604 | ((cmp_item_row*) base)[pos].store_value_by_template(current_thd, &tmp, item); |
3605 | DBUG_VOID_RETURN; |
3606 | } |
3607 | |
3608 | in_longlong::in_longlong(THD *thd, uint elements) |
3609 | :in_vector(thd, elements, sizeof(packed_longlong), |
3610 | (qsort2_cmp) cmp_longlong, 0) |
3611 | {} |
3612 | |
3613 | void in_longlong::set(uint pos,Item *item) |
3614 | { |
3615 | struct packed_longlong *buff= &((packed_longlong*) base)[pos]; |
3616 | |
3617 | buff->val= item->val_int(); |
3618 | buff->unsigned_flag= item->unsigned_flag; |
3619 | } |
3620 | |
3621 | uchar *in_longlong::get_value(Item *item) |
3622 | { |
3623 | tmp.val= item->val_int(); |
3624 | if (item->null_value) |
3625 | return 0; |
3626 | tmp.unsigned_flag= item->unsigned_flag; |
3627 | return (uchar*) &tmp; |
3628 | } |
3629 | |
3630 | Item *in_longlong::create_item(THD *thd) |
3631 | { |
3632 | /* |
3633 | We're created a signed INT, this may not be correct in |
3634 | general case (see BUG#19342). |
3635 | */ |
3636 | return new (thd->mem_root) Item_int(thd, (longlong)0); |
3637 | } |
3638 | |
3639 | |
3640 | void in_datetime::set(uint pos,Item *item) |
3641 | { |
3642 | struct packed_longlong *buff= &((packed_longlong*) base)[pos]; |
3643 | |
3644 | buff->val= item->val_datetime_packed(); |
3645 | buff->unsigned_flag= 1L; |
3646 | } |
3647 | |
3648 | void in_time::set(uint pos,Item *item) |
3649 | { |
3650 | struct packed_longlong *buff= &((packed_longlong*) base)[pos]; |
3651 | |
3652 | buff->val= item->val_time_packed(); |
3653 | buff->unsigned_flag= 1L; |
3654 | } |
3655 | |
3656 | uchar *in_temporal::get_value_internal(Item *item, enum_field_types f_type) |
3657 | { |
3658 | tmp.val= item->val_temporal_packed(f_type); |
3659 | if (item->null_value) |
3660 | return 0; |
3661 | tmp.unsigned_flag= 1L; |
3662 | return (uchar*) &tmp; |
3663 | } |
3664 | |
3665 | Item *in_temporal::create_item(THD *thd) |
3666 | { |
3667 | return new (thd->mem_root) Item_datetime(thd); |
3668 | } |
3669 | |
3670 | |
3671 | in_double::in_double(THD *thd, uint elements) |
3672 | :in_vector(thd, elements, sizeof(double), (qsort2_cmp) cmp_double, 0) |
3673 | {} |
3674 | |
3675 | void in_double::set(uint pos,Item *item) |
3676 | { |
3677 | ((double*) base)[pos]= item->val_real(); |
3678 | } |
3679 | |
3680 | uchar *in_double::get_value(Item *item) |
3681 | { |
3682 | tmp= item->val_real(); |
3683 | if (item->null_value) |
3684 | return 0; /* purecov: inspected */ |
3685 | return (uchar*) &tmp; |
3686 | } |
3687 | |
3688 | Item *in_double::create_item(THD *thd) |
3689 | { |
3690 | return new (thd->mem_root) Item_float(thd, 0.0, 0); |
3691 | } |
3692 | |
3693 | |
3694 | in_decimal::in_decimal(THD *thd, uint elements) |
3695 | :in_vector(thd, elements, sizeof(my_decimal), (qsort2_cmp) cmp_decimal, 0) |
3696 | {} |
3697 | |
3698 | |
3699 | void in_decimal::set(uint pos, Item *item) |
3700 | { |
3701 | /* as far as 'item' is constant, we can store reference on my_decimal */ |
3702 | my_decimal *dec= ((my_decimal *)base) + pos; |
3703 | dec->len= DECIMAL_BUFF_LENGTH; |
3704 | dec->fix_buffer_pointer(); |
3705 | my_decimal *res= item->val_decimal(dec); |
3706 | /* if item->val_decimal() is evaluated to NULL then res == 0 */ |
3707 | if (!item->null_value && res != dec) |
3708 | my_decimal2decimal(res, dec); |
3709 | } |
3710 | |
3711 | |
3712 | uchar *in_decimal::get_value(Item *item) |
3713 | { |
3714 | my_decimal *result= item->val_decimal(&val); |
3715 | if (item->null_value) |
3716 | return 0; |
3717 | return (uchar *)result; |
3718 | } |
3719 | |
3720 | Item *in_decimal::create_item(THD *thd) |
3721 | { |
3722 | return new (thd->mem_root) Item_decimal(thd, 0, FALSE); |
3723 | } |
3724 | |
3725 | |
3726 | bool Predicant_to_list_comparator::alloc_comparators(THD *thd, uint nargs) |
3727 | { |
3728 | size_t nbytes= sizeof(Predicant_to_value_comparator) * nargs; |
3729 | if (!(m_comparators= (Predicant_to_value_comparator *) thd->alloc(nbytes))) |
3730 | return true; |
3731 | memset(m_comparators, 0, nbytes); |
3732 | return false; |
3733 | } |
3734 | |
3735 | |
3736 | bool Predicant_to_list_comparator::add_value(const char *funcname, |
3737 | Item_args *args, |
3738 | uint value_index) |
3739 | { |
3740 | DBUG_ASSERT(m_predicant_index < args->argument_count()); |
3741 | DBUG_ASSERT(value_index < args->argument_count()); |
3742 | Type_handler_hybrid_field_type tmp; |
3743 | Item *tmpargs[2]; |
3744 | tmpargs[0]= args->arguments()[m_predicant_index]; |
3745 | tmpargs[1]= args->arguments()[value_index]; |
3746 | if (tmp.aggregate_for_comparison(funcname, tmpargs, 2, true)) |
3747 | { |
3748 | DBUG_ASSERT(current_thd->is_error()); |
3749 | return true; |
3750 | } |
3751 | m_comparators[m_comparator_count].m_handler= tmp.type_handler(); |
3752 | m_comparators[m_comparator_count].m_arg_index= value_index; |
3753 | m_comparator_count++; |
3754 | return false; |
3755 | } |
3756 | |
3757 | |
3758 | bool Predicant_to_list_comparator::add_value_skip_null(const char *funcname, |
3759 | Item_args *args, |
3760 | uint value_index, |
3761 | bool *nulls_found) |
3762 | { |
3763 | /* |
3764 | Skip explicit NULL constant items. |
3765 | Using real_item() to correctly detect references to explicit NULLs |
3766 | in HAVING clause, e.g. in this example "b" is skipped: |
3767 | SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A'); |
3768 | */ |
3769 | if (args->arguments()[value_index]->real_item()->type() == Item::NULL_ITEM) |
3770 | { |
3771 | *nulls_found= true; |
3772 | return false; |
3773 | } |
3774 | return add_value(funcname, args, value_index); |
3775 | } |
3776 | |
3777 | |
3778 | void Predicant_to_list_comparator:: |
3779 | detect_unique_handlers(Type_handler_hybrid_field_type *compatible, |
3780 | uint *unique_count, |
3781 | uint *found_types) |
3782 | { |
3783 | *unique_count= 0; |
3784 | *found_types= 0; |
3785 | for (uint i= 0; i < m_comparator_count; i++) |
3786 | { |
3787 | uint idx; |
3788 | if (find_handler(&idx, m_comparators[i].m_handler, i)) |
3789 | { |
3790 | m_comparators[i].m_handler_index= i; // New unique handler |
3791 | (*unique_count)++; |
3792 | (*found_types)|= 1U << m_comparators[i].m_handler->cmp_type(); |
3793 | compatible->set_handler(m_comparators[i].m_handler); |
3794 | } |
3795 | else |
3796 | { |
3797 | m_comparators[i].m_handler_index= idx; // Non-unique handler |
3798 | } |
3799 | } |
3800 | } |
3801 | |
3802 | |
3803 | bool Predicant_to_list_comparator::make_unique_cmp_items(THD *thd, |
3804 | CHARSET_INFO *cs) |
3805 | { |
3806 | for (uint i= 0; i < m_comparator_count; i++) |
3807 | { |
3808 | if (m_comparators[i].m_handler && // Skip implicit NULLs |
3809 | m_comparators[i].m_handler_index == i && // Skip non-unuque |
3810 | !(m_comparators[i].m_cmp_item= |
3811 | m_comparators[i].m_handler->make_cmp_item(thd, cs))) |
3812 | return true; |
3813 | } |
3814 | return false; |
3815 | } |
3816 | |
3817 | |
3818 | cmp_item* cmp_item_sort_string::make_same() |
3819 | { |
3820 | return new cmp_item_sort_string_in_static(cmp_charset); |
3821 | } |
3822 | |
3823 | cmp_item* cmp_item_int::make_same() |
3824 | { |
3825 | return new cmp_item_int(); |
3826 | } |
3827 | |
3828 | cmp_item* cmp_item_real::make_same() |
3829 | { |
3830 | return new cmp_item_real(); |
3831 | } |
3832 | |
3833 | cmp_item* cmp_item_row::make_same() |
3834 | { |
3835 | return new cmp_item_row(); |
3836 | } |
3837 | |
3838 | |
3839 | cmp_item_row::~cmp_item_row() |
3840 | { |
3841 | DBUG_ENTER("~cmp_item_row" ); |
3842 | DBUG_PRINT("enter" ,("this: %p" , this)); |
3843 | if (comparators) |
3844 | { |
3845 | for (uint i= 0; i < n; i++) |
3846 | { |
3847 | if (comparators[i]) |
3848 | delete comparators[i]; |
3849 | } |
3850 | } |
3851 | DBUG_VOID_RETURN; |
3852 | } |
3853 | |
3854 | |
3855 | bool cmp_item_row::alloc_comparators(THD *thd, uint cols) |
3856 | { |
3857 | if (comparators) |
3858 | { |
3859 | DBUG_ASSERT(cols == n); |
3860 | return false; |
3861 | } |
3862 | return |
3863 | !(comparators= (cmp_item **) thd->calloc(sizeof(cmp_item *) * (n= cols))); |
3864 | } |
3865 | |
3866 | |
3867 | void cmp_item_row::store_value(Item *item) |
3868 | { |
3869 | DBUG_ENTER("cmp_item_row::store_value" ); |
3870 | THD *thd= current_thd; |
3871 | if (!alloc_comparators(thd, item->cols())) |
3872 | { |
3873 | item->bring_value(); |
3874 | item->null_value= 0; |
3875 | for (uint i=0; i < n; i++) |
3876 | { |
3877 | if (!comparators[i]) |
3878 | { |
3879 | /** |
3880 | Comparators for the row elements that have temporal data types |
3881 | are installed at initialization time by prepare_comparators(). |
3882 | Here we install comparators for the other data types. |
3883 | There is a bug in the below code. See MDEV-11511. |
3884 | When performing: |
3885 | (predicant0,predicant1) IN ((value00,value01),(value10,value11)) |
3886 | It uses only the data type and the collation of the predicant |
3887 | elements only. It should be fixed to aggregate the data type and |
3888 | the collation for all elements at the N-th positions of the |
3889 | predicate and all values: |
3890 | - predicate0, value00, value01 |
3891 | - predicate1, value10, value11 |
3892 | */ |
3893 | Item *elem= item->element_index(i); |
3894 | const Type_handler *handler= elem->type_handler(); |
3895 | DBUG_ASSERT(elem->cmp_type() != TIME_RESULT); |
3896 | if (!(comparators[i]= |
3897 | handler->make_cmp_item(thd, elem->collation.collation))) |
3898 | break; // new failed |
3899 | } |
3900 | comparators[i]->store_value(item->element_index(i)); |
3901 | item->null_value|= item->element_index(i)->null_value; |
3902 | } |
3903 | } |
3904 | DBUG_VOID_RETURN; |
3905 | } |
3906 | |
3907 | |
3908 | void cmp_item_row::store_value_by_template(THD *thd, cmp_item *t, Item *item) |
3909 | { |
3910 | cmp_item_row *tmpl= (cmp_item_row*) t; |
3911 | if (tmpl->n != item->cols()) |
3912 | { |
3913 | my_error(ER_OPERAND_COLUMNS, MYF(0), tmpl->n); |
3914 | return; |
3915 | } |
3916 | n= tmpl->n; |
3917 | if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n))) |
3918 | { |
3919 | item->bring_value(); |
3920 | item->null_value= 0; |
3921 | for (uint i=0; i < n; i++) |
3922 | { |
3923 | if (!(comparators[i]= tmpl->comparators[i]->make_same())) |
3924 | break; // new failed |
3925 | comparators[i]->store_value_by_template(thd, tmpl->comparators[i], |
3926 | item->element_index(i)); |
3927 | item->null_value|= item->element_index(i)->null_value; |
3928 | } |
3929 | } |
3930 | } |
3931 | |
3932 | |
3933 | int cmp_item_row::cmp(Item *arg) |
3934 | { |
3935 | arg->null_value= 0; |
3936 | if (arg->cols() != n) |
3937 | { |
3938 | my_error(ER_OPERAND_COLUMNS, MYF(0), n); |
3939 | return 1; |
3940 | } |
3941 | bool was_null= 0; |
3942 | arg->bring_value(); |
3943 | for (uint i=0; i < n; i++) |
3944 | { |
3945 | const int rc= comparators[i]->cmp(arg->element_index(i)); |
3946 | switch (rc) |
3947 | { |
3948 | case UNKNOWN: |
3949 | was_null= true; |
3950 | break; |
3951 | case TRUE: |
3952 | return TRUE; |
3953 | case FALSE: |
3954 | break; // elements #i are equal |
3955 | } |
3956 | arg->null_value|= arg->element_index(i)->null_value; |
3957 | } |
3958 | return was_null ? UNKNOWN : FALSE; |
3959 | } |
3960 | |
3961 | |
3962 | int cmp_item_row::compare(cmp_item *c) |
3963 | { |
3964 | cmp_item_row *l_cmp= (cmp_item_row *) c; |
3965 | for (uint i=0; i < n; i++) |
3966 | { |
3967 | int res; |
3968 | if ((res= comparators[i]->compare(l_cmp->comparators[i]))) |
3969 | return res; |
3970 | } |
3971 | return 0; |
3972 | } |
3973 | |
3974 | |
3975 | void cmp_item_decimal::store_value(Item *item) |
3976 | { |
3977 | my_decimal *val= item->val_decimal(&value); |
3978 | /* val may be zero if item is nnull */ |
3979 | if (val && val != &value) |
3980 | my_decimal2decimal(val, &value); |
3981 | m_null_value= item->null_value; |
3982 | } |
3983 | |
3984 | |
3985 | int cmp_item_decimal::cmp_not_null(const Value *val) |
3986 | { |
3987 | DBUG_ASSERT(!val->is_null()); |
3988 | DBUG_ASSERT(val->is_decimal()); |
3989 | return my_decimal_cmp(&value, &val->m_decimal); |
3990 | } |
3991 | |
3992 | |
3993 | int cmp_item_decimal::cmp(Item *arg) |
3994 | { |
3995 | my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf); |
3996 | return (m_null_value || arg->null_value) ? |
3997 | UNKNOWN : (my_decimal_cmp(&value, tmp) != 0); |
3998 | } |
3999 | |
4000 | |
4001 | int cmp_item_decimal::compare(cmp_item *arg) |
4002 | { |
4003 | cmp_item_decimal *l_cmp= (cmp_item_decimal*) arg; |
4004 | return my_decimal_cmp(&value, &l_cmp->value); |
4005 | } |
4006 | |
4007 | |
4008 | cmp_item* cmp_item_decimal::make_same() |
4009 | { |
4010 | return new cmp_item_decimal(); |
4011 | } |
4012 | |
4013 | |
4014 | void cmp_item_temporal::store_value_internal(Item *item, |
4015 | enum_field_types f_type) |
4016 | { |
4017 | value= item->val_temporal_packed(f_type); |
4018 | m_null_value= item->null_value; |
4019 | } |
4020 | |
4021 | |
4022 | int cmp_item_datetime::cmp_not_null(const Value *val) |
4023 | { |
4024 | DBUG_ASSERT(!val->is_null()); |
4025 | DBUG_ASSERT(val->is_temporal()); |
4026 | return value != pack_time(&val->value.m_time); |
4027 | } |
4028 | |
4029 | |
4030 | int cmp_item_datetime::cmp(Item *arg) |
4031 | { |
4032 | const bool rc= value != arg->val_datetime_packed(); |
4033 | return (m_null_value || arg->null_value) ? UNKNOWN : rc; |
4034 | } |
4035 | |
4036 | |
4037 | int cmp_item_time::cmp_not_null(const Value *val) |
4038 | { |
4039 | DBUG_ASSERT(!val->is_null()); |
4040 | DBUG_ASSERT(val->is_temporal()); |
4041 | return value != pack_time(&val->value.m_time); |
4042 | } |
4043 | |
4044 | |
4045 | int cmp_item_time::cmp(Item *arg) |
4046 | { |
4047 | const bool rc= value != arg->val_time_packed(); |
4048 | return (m_null_value || arg->null_value) ? UNKNOWN : rc; |
4049 | } |
4050 | |
4051 | |
4052 | int cmp_item_temporal::compare(cmp_item *ci) |
4053 | { |
4054 | cmp_item_temporal *l_cmp= (cmp_item_temporal *)ci; |
4055 | return (value < l_cmp->value) ? -1 : ((value == l_cmp->value) ? 0 : 1); |
4056 | } |
4057 | |
4058 | |
4059 | cmp_item *cmp_item_datetime::make_same() |
4060 | { |
4061 | return new cmp_item_datetime(); |
4062 | } |
4063 | |
4064 | |
4065 | cmp_item *cmp_item_time::make_same() |
4066 | { |
4067 | return new cmp_item_time(); |
4068 | } |
4069 | |
4070 | |
4071 | bool Item_func_in::count_sargable_conds(void *arg) |
4072 | { |
4073 | ((SELECT_LEX*) arg)->cond_count++; |
4074 | return 0; |
4075 | } |
4076 | |
4077 | |
4078 | bool Item_func_in::list_contains_null() |
4079 | { |
4080 | Item **arg,**arg_end; |
4081 | for (arg= args + 1, arg_end= args+arg_count; arg != arg_end ; arg++) |
4082 | { |
4083 | if ((*arg)->null_inside()) |
4084 | return 1; |
4085 | } |
4086 | return 0; |
4087 | } |
4088 | |
4089 | |
4090 | /** |
4091 | Perform context analysis of an IN item tree. |
4092 | |
4093 | This function performs context analysis (name resolution) and calculates |
4094 | various attributes of the item tree with Item_func_in as its root. |
4095 | The function saves in ref the pointer to the item or to a newly created |
4096 | item that is considered as a replacement for the original one. |
4097 | |
4098 | @param thd reference to the global context of the query thread |
4099 | @param ref pointer to Item* variable where pointer to resulting "fixed" |
4100 | item is to be assigned |
4101 | |
4102 | @note |
4103 | Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on |
4104 | a predicate/function level. Then it's easy to show that: |
4105 | @verbatim |
4106 | T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) |
4107 | T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) |
4108 | T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei))) |
4109 | T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) |
4110 | @endverbatim |
4111 | |
4112 | @retval |
4113 | 0 ok |
4114 | @retval |
4115 | 1 got error |
4116 | */ |
4117 | |
4118 | bool |
4119 | Item_func_in::fix_fields(THD *thd, Item **ref) |
4120 | { |
4121 | |
4122 | if (Item_func_opt_neg::fix_fields(thd, ref)) |
4123 | return 1; |
4124 | |
4125 | return 0; |
4126 | } |
4127 | |
4128 | |
4129 | bool |
4130 | Item_func_in::eval_not_null_tables(void *opt_arg) |
4131 | { |
4132 | Item **arg, **arg_end; |
4133 | |
4134 | if (Item_func_opt_neg::eval_not_null_tables(NULL)) |
4135 | return 1; |
4136 | |
4137 | /* not_null_tables_cache == union(T1(e),union(T1(ei))) */ |
4138 | if (pred_level && negated) |
4139 | return 0; |
4140 | |
4141 | /* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */ |
4142 | not_null_tables_cache= ~(table_map) 0; |
4143 | for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++) |
4144 | not_null_tables_cache&= (*arg)->not_null_tables(); |
4145 | not_null_tables_cache|= (*args)->not_null_tables(); |
4146 | return 0; |
4147 | } |
4148 | |
4149 | |
4150 | void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref, |
4151 | bool merge) |
4152 | { |
4153 | /* This will re-calculate attributes of the arguments */ |
4154 | Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge); |
4155 | /* Then, re-calculate not_null_tables_cache according to our special rules */ |
4156 | eval_not_null_tables(NULL); |
4157 | } |
4158 | |
4159 | |
4160 | bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types) |
4161 | { |
4162 | uint type_cnt; |
4163 | have_null= false; |
4164 | |
4165 | add_predicant(this, 0); |
4166 | for (uint i= 1 ; i < arg_count; i++) |
4167 | { |
4168 | if (add_value_skip_null(Item_func_in::func_name(), this, i, &have_null)) |
4169 | return true; |
4170 | } |
4171 | all_values_added(&m_comparator, &type_cnt, found_types); |
4172 | arg_types_compatible= type_cnt < 2; |
4173 | |
4174 | #ifndef DBUG_OFF |
4175 | Predicant_to_list_comparator::debug_print(thd); |
4176 | #endif |
4177 | return false; |
4178 | } |
4179 | |
4180 | |
4181 | void Item_func_in::fix_length_and_dec() |
4182 | { |
4183 | THD *thd= current_thd; |
4184 | uint found_types; |
4185 | m_comparator.set_handler(type_handler_varchar.type_handler_for_comparison()); |
4186 | max_length= 1; |
4187 | |
4188 | if (prepare_predicant_and_values(thd, &found_types)) |
4189 | { |
4190 | DBUG_ASSERT(thd->is_error()); // Must set error |
4191 | return; |
4192 | } |
4193 | |
4194 | if (arg_types_compatible) // Bisection condition #1 |
4195 | { |
4196 | m_comparator.type_handler()-> |
4197 | Item_func_in_fix_comparator_compatible_types(thd, this); |
4198 | } |
4199 | else |
4200 | { |
4201 | DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT); |
4202 | fix_for_scalar_comparison_using_cmp_items(thd, found_types); |
4203 | } |
4204 | |
4205 | DBUG_EXECUTE_IF("Item_func_in" , |
4206 | push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, |
4207 | ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s" , |
4208 | arg_types_compatible ? "yes" : "no" , |
4209 | array != NULL ? "yes" : "no" );); |
4210 | } |
4211 | |
4212 | |
4213 | /** |
4214 | Populate Item_func_in::array with constant not-NULL arguments and sort them. |
4215 | |
4216 | Sets "have_null" to true if some of the values appeared to be NULL. |
4217 | Note, explicit NULLs were found during prepare_predicant_and_values(). |
4218 | So "have_null" can already be true before the fix_in_vector() call. |
4219 | Here we additionally catch implicit NULLs. |
4220 | */ |
4221 | void Item_func_in::fix_in_vector() |
4222 | { |
4223 | DBUG_ASSERT(array); |
4224 | uint j=0; |
4225 | for (uint i=1 ; i < arg_count ; i++) |
4226 | { |
4227 | array->set(j,args[i]); |
4228 | if (!args[i]->null_value) |
4229 | j++; // include this cell in the array. |
4230 | else |
4231 | { |
4232 | /* |
4233 | We don't put NULL values in array, to avoid erronous matches in |
4234 | bisection. |
4235 | */ |
4236 | have_null= 1; |
4237 | } |
4238 | } |
4239 | if ((array->used_count= j)) |
4240 | array->sort(); |
4241 | } |
4242 | |
4243 | |
4244 | /** |
4245 | Convert all items in <in value list> to INT. |
4246 | |
4247 | IN must compare INT columns and constants as int values (the same |
4248 | way as equality does). |
4249 | So we must check here if the column on the left and all the constant |
4250 | values on the right can be compared as integers and adjust the |
4251 | comparison type accordingly. |
4252 | |
4253 | See the comment about the similar block in Item_bool_func2 |
4254 | */ |
4255 | bool Item_func_in::value_list_convert_const_to_int(THD *thd) |
4256 | { |
4257 | if (args[0]->real_item()->type() == FIELD_ITEM && |
4258 | !thd->lex->is_view_context_analysis()) |
4259 | { |
4260 | Item_field *field_item= (Item_field*) (args[0]->real_item()); |
4261 | if (field_item->field_type() == MYSQL_TYPE_LONGLONG || |
4262 | field_item->field_type() == MYSQL_TYPE_YEAR) |
4263 | { |
4264 | bool all_converted= TRUE; |
4265 | Item **arg, **arg_end; |
4266 | for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) |
4267 | { |
4268 | if (!convert_const_to_int(thd, field_item, &arg[0])) |
4269 | all_converted= FALSE; |
4270 | } |
4271 | if (all_converted) |
4272 | m_comparator.set_handler(&type_handler_longlong); |
4273 | } |
4274 | } |
4275 | return thd->is_fatal_error; // Catch errrors in convert_const_to_int |
4276 | } |
4277 | |
4278 | |
4279 | /** |
4280 | Historically this code installs comparators at initialization time |
4281 | for temporal ROW elements only. All other comparators are installed later, |
4282 | during the first store_value(). This causes the bug MDEV-11511. |
4283 | See also comments in cmp_item_row::store_value(). |
4284 | */ |
4285 | bool cmp_item_row::prepare_comparators(THD *thd, Item **args, uint arg_count) |
4286 | { |
4287 | for (uint col= 0; col < n; col++) |
4288 | { |
4289 | Item *date_arg= find_date_time_item(args, arg_count, col); |
4290 | if (date_arg) |
4291 | { |
4292 | // TODO: do like the scalar comparators do |
4293 | const Type_handler *h= date_arg->type_handler(); |
4294 | comparators[col]= h->field_type() == MYSQL_TYPE_TIME ? |
4295 | (cmp_item *) new (thd->mem_root) cmp_item_time() : |
4296 | (cmp_item *) new (thd->mem_root) cmp_item_datetime(); |
4297 | if (!comparators[col]) |
4298 | return true; |
4299 | } |
4300 | } |
4301 | return false; |
4302 | } |
4303 | |
4304 | |
4305 | bool Item_func_in::fix_for_row_comparison_using_bisection(THD *thd) |
4306 | { |
4307 | uint cols= args[0]->cols(); |
4308 | if (unlikely(!(array= new (thd->mem_root) in_row(thd, arg_count-1, 0)))) |
4309 | return true; |
4310 | cmp_item_row *cmp= &((in_row*)array)->tmp; |
4311 | if (cmp->alloc_comparators(thd, cols) || |
4312 | cmp->prepare_comparators(thd, args, arg_count)) |
4313 | return true; |
4314 | /* |
4315 | Only DATETIME items comparators were initialized. |
4316 | Call store_value() to setup others. |
4317 | */ |
4318 | cmp->store_value(args[0]); |
4319 | if (unlikely(thd->is_fatal_error)) // OOM |
4320 | return true; |
4321 | fix_in_vector(); |
4322 | return false; |
4323 | } |
4324 | |
4325 | |
4326 | /** |
4327 | This method is called for scalar data types when bisection is not possible, |
4328 | for example: |
4329 | - Some of args[1..arg_count] are not constants. |
4330 | - args[1..arg_count] are constants, but pairs {args[0],args[1..arg_count]} |
4331 | are compared by different data types, e.g.: |
4332 | WHERE decimal_expr IN (1, 1e0) |
4333 | The pair {args[0],args[1]} is compared by type_handler_decimal. |
4334 | The pair {args[0],args[2]} is compared by type_handler_double. |
4335 | */ |
4336 | bool Item_func_in::fix_for_scalar_comparison_using_cmp_items(THD *thd, |
4337 | uint found_types) |
4338 | { |
4339 | if (found_types & (1U << STRING_RESULT) && |
4340 | agg_arg_charsets_for_comparison(cmp_collation, args, arg_count)) |
4341 | return true; |
4342 | if (make_unique_cmp_items(thd, cmp_collation.collation)) |
4343 | return true; |
4344 | return false; |
4345 | } |
4346 | |
4347 | |
4348 | /** |
4349 | This method is called for the ROW data type when bisection is not possible. |
4350 | */ |
4351 | bool Item_func_in::fix_for_row_comparison_using_cmp_items(THD *thd) |
4352 | { |
4353 | if (make_unique_cmp_items(thd, cmp_collation.collation)) |
4354 | return true; |
4355 | DBUG_ASSERT(get_comparator_type_handler(0) == &type_handler_row); |
4356 | DBUG_ASSERT(get_comparator_cmp_item(0)); |
4357 | cmp_item_row *cmp_row= (cmp_item_row*) get_comparator_cmp_item(0); |
4358 | return cmp_row->alloc_comparators(thd, args[0]->cols()) || |
4359 | cmp_row->prepare_comparators(thd, args, arg_count); |
4360 | } |
4361 | |
4362 | |
4363 | void Item_func_in::print(String *str, enum_query_type query_type) |
4364 | { |
4365 | args[0]->print_parenthesised(str, query_type, precedence()); |
4366 | if (negated) |
4367 | str->append(STRING_WITH_LEN(" not" )); |
4368 | str->append(STRING_WITH_LEN(" in (" )); |
4369 | print_args(str, 1, query_type); |
4370 | str->append(STRING_WITH_LEN(")" )); |
4371 | } |
4372 | |
4373 | |
4374 | /* |
4375 | Evaluate the function and return its value. |
4376 | |
4377 | SYNOPSIS |
4378 | val_int() |
4379 | |
4380 | DESCRIPTION |
4381 | Evaluate the function and return its value. |
4382 | |
4383 | IMPLEMENTATION |
4384 | If the array object is defined then the value of the function is |
4385 | calculated by means of this array. |
4386 | Otherwise several cmp_item objects are used in order to do correct |
4387 | comparison of left expression and an expression from the values list. |
4388 | One cmp_item object correspond to one used comparison type. Left |
4389 | expression can be evaluated up to number of different used comparison |
4390 | types. A bit mapped variable value_added_map is used to check whether |
4391 | the left expression already was evaluated for a particular result type. |
4392 | Result types are mapped to it according to their integer values i.e. |
4393 | STRING_RESULT is mapped to bit 0, REAL_RESULT to bit 1, so on. |
4394 | |
4395 | RETURN |
4396 | Value of the function |
4397 | */ |
4398 | |
4399 | longlong Item_func_in::val_int() |
4400 | { |
4401 | DBUG_ASSERT(fixed == 1); |
4402 | if (array) |
4403 | { |
4404 | bool tmp=array->find(args[0]); |
4405 | /* |
4406 | NULL on left -> UNKNOWN. |
4407 | Found no match, and NULL on right -> UNKNOWN. |
4408 | NULL on right can never give a match, as it is not stored in |
4409 | array. |
4410 | See also the 'bisection_possible' variable in fix_length_and_dec(). |
4411 | */ |
4412 | null_value=args[0]->null_value || (!tmp && have_null); |
4413 | return (longlong) (!null_value && tmp != negated); |
4414 | } |
4415 | |
4416 | if ((null_value= args[0]->real_item()->type() == NULL_ITEM)) |
4417 | return 0; |
4418 | |
4419 | null_value= have_null; |
4420 | uint idx; |
4421 | if (!Predicant_to_list_comparator::cmp(this, &idx, &null_value)) |
4422 | { |
4423 | null_value= false; |
4424 | return (longlong) (!negated); |
4425 | } |
4426 | return (longlong) (!null_value && negated); |
4427 | } |
4428 | |
4429 | |
4430 | void Item_func_in::mark_as_condition_AND_part(TABLE_LIST *embedding) |
4431 | { |
4432 | THD *thd= current_thd; |
4433 | |
4434 | Query_arena *arena, backup; |
4435 | arena= thd->activate_stmt_arena_if_needed(&backup); |
4436 | |
4437 | if (to_be_transformed_into_in_subq(thd)) |
4438 | { |
4439 | transform_into_subq= true; |
4440 | thd->lex->current_select->in_funcs.push_back(this, thd->mem_root); |
4441 | } |
4442 | |
4443 | if (arena) |
4444 | thd->restore_active_arena(arena, &backup); |
4445 | |
4446 | emb_on_expr_nest= embedding; |
4447 | } |
4448 | |
4449 | |
4450 | longlong Item_func_bit_or::val_int() |
4451 | { |
4452 | DBUG_ASSERT(fixed == 1); |
4453 | ulonglong arg1= (ulonglong) args[0]->val_int(); |
4454 | if (args[0]->null_value) |
4455 | { |
4456 | null_value=1; /* purecov: inspected */ |
4457 | return 0; /* purecov: inspected */ |
4458 | } |
4459 | ulonglong arg2= (ulonglong) args[1]->val_int(); |
4460 | if (args[1]->null_value) |
4461 | { |
4462 | null_value=1; |
4463 | return 0; |
4464 | } |
4465 | null_value=0; |
4466 | return (longlong) (arg1 | arg2); |
4467 | } |
4468 | |
4469 | |
4470 | longlong Item_func_bit_and::val_int() |
4471 | { |
4472 | DBUG_ASSERT(fixed == 1); |
4473 | ulonglong arg1= (ulonglong) args[0]->val_int(); |
4474 | if (args[0]->null_value) |
4475 | { |
4476 | null_value=1; /* purecov: inspected */ |
4477 | return 0; /* purecov: inspected */ |
4478 | } |
4479 | ulonglong arg2= (ulonglong) args[1]->val_int(); |
4480 | if (args[1]->null_value) |
4481 | { |
4482 | null_value=1; /* purecov: inspected */ |
4483 | return 0; /* purecov: inspected */ |
4484 | } |
4485 | null_value=0; |
4486 | return (longlong) (arg1 & arg2); |
4487 | } |
4488 | |
4489 | Item_cond::Item_cond(THD *thd, Item_cond *item) |
4490 | :Item_bool_func(thd, item), |
4491 | abort_on_null(item->abort_on_null), |
4492 | and_tables_cache(item->and_tables_cache) |
4493 | { |
4494 | /* |
4495 | item->list will be copied by copy_andor_arguments() call |
4496 | */ |
4497 | } |
4498 | |
4499 | |
4500 | Item_cond::Item_cond(THD *thd, Item *i1, Item *i2): |
4501 | Item_bool_func(thd), abort_on_null(0) |
4502 | { |
4503 | list.push_back(i1, thd->mem_root); |
4504 | list.push_back(i2, thd->mem_root); |
4505 | } |
4506 | |
4507 | |
4508 | Item *Item_cond_and::copy_andor_structure(THD *thd) |
4509 | { |
4510 | Item_cond_and *item; |
4511 | if ((item= new (thd->mem_root) Item_cond_and(thd, this))) |
4512 | item->copy_andor_arguments(thd, this); |
4513 | return item; |
4514 | } |
4515 | |
4516 | |
4517 | void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) |
4518 | { |
4519 | List_iterator_fast<Item> li(item->list); |
4520 | while (Item *it= li++) |
4521 | list.push_back(it->copy_andor_structure(thd), thd->mem_root); |
4522 | } |
4523 | |
4524 | |
4525 | bool |
4526 | Item_cond::fix_fields(THD *thd, Item **ref) |
4527 | { |
4528 | DBUG_ASSERT(fixed == 0); |
4529 | List_iterator<Item> li(list); |
4530 | Item *item; |
4531 | uchar buff[sizeof(char*)]; // Max local vars in function |
4532 | longlong is_and_cond= functype() == Item_func::COND_AND_FUNC; |
4533 | not_null_tables_cache= 0; |
4534 | used_tables_and_const_cache_init(); |
4535 | |
4536 | /* |
4537 | and_table_cache is the value that Item_cond_or() returns for |
4538 | not_null_tables() |
4539 | */ |
4540 | and_tables_cache= ~(table_map) 0; |
4541 | |
4542 | if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) |
4543 | return TRUE; // Fatal error flag is set! |
4544 | /* |
4545 | The following optimization reduces the depth of an AND-OR tree. |
4546 | E.g. a WHERE clause like |
4547 | F1 AND (F2 AND (F2 AND F4)) |
4548 | is parsed into a tree with the same nested structure as defined |
4549 | by braces. This optimization will transform such tree into |
4550 | AND (F1, F2, F3, F4). |
4551 | Trees of OR items are flattened as well: |
4552 | ((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4) |
4553 | Items for removed AND/OR levels will dangle until the death of the |
4554 | entire statement. |
4555 | The optimization is currently prepared statements and stored procedures |
4556 | friendly as it doesn't allocate any memory and its effects are durable |
4557 | (i.e. do not depend on PS/SP arguments). |
4558 | */ |
4559 | while ((item=li++)) |
4560 | { |
4561 | while (item->type() == Item::COND_ITEM && |
4562 | ((Item_cond*) item)->functype() == functype() && |
4563 | !((Item_cond*) item)->list.is_empty()) |
4564 | { // Identical function |
4565 | li.replace(((Item_cond*) item)->list); |
4566 | ((Item_cond*) item)->list.empty(); |
4567 | item= *li.ref(); // new current item |
4568 | } |
4569 | if (abort_on_null) |
4570 | item->top_level_item(); |
4571 | |
4572 | /* |
4573 | replace degraded condition: |
4574 | was: <field> |
4575 | become: <field> = 1 |
4576 | */ |
4577 | Item::Type type= item->type(); |
4578 | if (type == Item::FIELD_ITEM || type == Item::REF_ITEM) |
4579 | { |
4580 | Query_arena backup, *arena; |
4581 | Item *new_item; |
4582 | arena= thd->activate_stmt_arena_if_needed(&backup); |
4583 | if ((new_item= new (thd->mem_root) Item_func_ne(thd, item, new (thd->mem_root) Item_int(thd, 0, 1)))) |
4584 | li.replace(item= new_item); |
4585 | if (arena) |
4586 | thd->restore_active_arena(arena, &backup); |
4587 | } |
4588 | |
4589 | // item can be substituted in fix_fields |
4590 | if ((!item->fixed && |
4591 | item->fix_fields(thd, li.ref())) || |
4592 | (item= *li.ref())->check_cols(1)) |
4593 | return TRUE; /* purecov: inspected */ |
4594 | used_tables_cache|= item->used_tables(); |
4595 | if (item->const_item() && !item->with_param && |
4596 | !item->is_expensive() && !cond_has_datetime_is_null(item)) |
4597 | { |
4598 | if (item->val_int() == is_and_cond && top_level()) |
4599 | { |
4600 | /* |
4601 | a. This is "... AND true_cond AND ..." |
4602 | In this case, true_cond has no effect on cond_and->not_null_tables() |
4603 | b. This is "... OR false_cond/null cond OR ..." |
4604 | In this case, false_cond has no effect on cond_or->not_null_tables() |
4605 | */ |
4606 | } |
4607 | else |
4608 | { |
4609 | /* |
4610 | a. This is "... AND false_cond/null_cond AND ..." |
4611 | The whole condition is FALSE/UNKNOWN. |
4612 | b. This is "... OR const_cond OR ..." |
4613 | In this case, cond_or->not_null_tables()=0, because the condition |
4614 | const_cond might evaluate to true (regardless of whether some tables |
4615 | were NULL-complemented). |
4616 | */ |
4617 | not_null_tables_cache= (table_map) 0; |
4618 | and_tables_cache= (table_map) 0; |
4619 | } |
4620 | if (thd->is_error()) |
4621 | return TRUE; |
4622 | } |
4623 | else |
4624 | { |
4625 | table_map tmp_table_map= item->not_null_tables(); |
4626 | not_null_tables_cache|= tmp_table_map; |
4627 | and_tables_cache&= tmp_table_map; |
4628 | |
4629 | const_item_cache= FALSE; |
4630 | } |
4631 | |
4632 | with_sum_func|= item->with_sum_func; |
4633 | with_param|= item->with_param; |
4634 | with_field|= item->with_field; |
4635 | m_with_subquery|= item->with_subquery(); |
4636 | with_window_func|= item->with_window_func; |
4637 | maybe_null|= item->maybe_null; |
4638 | } |
4639 | fix_length_and_dec(); |
4640 | fixed= 1; |
4641 | return FALSE; |
4642 | } |
4643 | |
4644 | |
4645 | bool |
4646 | Item_cond::eval_not_null_tables(void *opt_arg) |
4647 | { |
4648 | Item *item; |
4649 | longlong is_and_cond= functype() == Item_func::COND_AND_FUNC; |
4650 | List_iterator<Item> li(list); |
4651 | not_null_tables_cache= (table_map) 0; |
4652 | and_tables_cache= ~(table_map) 0; |
4653 | while ((item=li++)) |
4654 | { |
4655 | table_map tmp_table_map; |
4656 | if (item->const_item() && !item->with_param && |
4657 | !item->is_expensive() && !cond_has_datetime_is_null(item)) |
4658 | { |
4659 | if (item->val_int() == is_and_cond && top_level()) |
4660 | { |
4661 | /* |
4662 | a. This is "... AND true_cond AND ..." |
4663 | In this case, true_cond has no effect on cond_and->not_null_tables() |
4664 | b. This is "... OR false_cond/null cond OR ..." |
4665 | In this case, false_cond has no effect on cond_or->not_null_tables() |
4666 | */ |
4667 | } |
4668 | else |
4669 | { |
4670 | /* |
4671 | a. This is "... AND false_cond/null_cond AND ..." |
4672 | The whole condition is FALSE/UNKNOWN. |
4673 | b. This is "... OR const_cond OR ..." |
4674 | In this case, cond_or->not_null_tables()=0, because the condition |
4675 | const_cond might evaluate to true (regardless of whether some tables |
4676 | were NULL-complemented). |
4677 | */ |
4678 | not_null_tables_cache= (table_map) 0; |
4679 | and_tables_cache= (table_map) 0; |
4680 | } |
4681 | } |
4682 | else |
4683 | { |
4684 | tmp_table_map= item->not_null_tables(); |
4685 | not_null_tables_cache|= tmp_table_map; |
4686 | and_tables_cache&= tmp_table_map; |
4687 | } |
4688 | } |
4689 | return 0; |
4690 | } |
4691 | |
4692 | |
4693 | void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref, |
4694 | bool merge) |
4695 | { |
4696 | List_iterator<Item> li(list); |
4697 | Item *item; |
4698 | |
4699 | used_tables_and_const_cache_init(); |
4700 | |
4701 | and_tables_cache= ~(table_map) 0; // Here and below we do as fix_fields does |
4702 | not_null_tables_cache= 0; |
4703 | |
4704 | while ((item=li++)) |
4705 | { |
4706 | table_map tmp_table_map; |
4707 | item->fix_after_pullout(new_parent, li.ref(), merge); |
4708 | item= *li.ref(); |
4709 | used_tables_and_const_cache_join(item); |
4710 | |
4711 | if (item->const_item()) |
4712 | and_tables_cache= (table_map) 0; |
4713 | else |
4714 | { |
4715 | tmp_table_map= item->not_null_tables(); |
4716 | not_null_tables_cache|= tmp_table_map; |
4717 | and_tables_cache&= tmp_table_map; |
4718 | const_item_cache= FALSE; |
4719 | } |
4720 | } |
4721 | } |
4722 | |
4723 | |
4724 | bool Item_cond::walk(Item_processor processor, bool walk_subquery, void *arg) |
4725 | { |
4726 | List_iterator_fast<Item> li(list); |
4727 | Item *item; |
4728 | while ((item= li++)) |
4729 | if (item->walk(processor, walk_subquery, arg)) |
4730 | return 1; |
4731 | return Item_func::walk(processor, walk_subquery, arg); |
4732 | } |
4733 | |
4734 | /** |
4735 | Transform an Item_cond object with a transformer callback function. |
4736 | |
4737 | The function recursively applies the transform method to each |
4738 | member item of the condition list. |
4739 | If the call of the method for a member item returns a new item |
4740 | the old item is substituted for a new one. |
4741 | After this the transformer is applied to the root node |
4742 | of the Item_cond object. |
4743 | |
4744 | @param transformer the transformer callback function to be applied to |
4745 | the nodes of the tree of the object |
4746 | @param arg parameter to be passed to the transformer |
4747 | |
4748 | @return |
4749 | Item returned as the result of transformation of the root node |
4750 | */ |
4751 | |
4752 | Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) |
4753 | { |
4754 | DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); |
4755 | |
4756 | List_iterator<Item> li(list); |
4757 | Item *item; |
4758 | while ((item= li++)) |
4759 | { |
4760 | Item *new_item= item->transform(thd, transformer, arg); |
4761 | if (!new_item) |
4762 | return 0; |
4763 | |
4764 | /* |
4765 | THD::change_item_tree() should be called only if the tree was |
4766 | really transformed, i.e. when a new item has been created. |
4767 | Otherwise we'll be allocating a lot of unnecessary memory for |
4768 | change records at each execution. |
4769 | */ |
4770 | if (new_item != item) |
4771 | thd->change_item_tree(li.ref(), new_item); |
4772 | } |
4773 | return Item_func::transform(thd, transformer, arg); |
4774 | } |
4775 | |
4776 | |
4777 | /** |
4778 | Compile Item_cond object with a processor and a transformer |
4779 | callback functions. |
4780 | |
4781 | First the function applies the analyzer to the root node of |
4782 | the Item_func object. Then if the analyzer succeeeds (returns TRUE) |
4783 | the function recursively applies the compile method to member |
4784 | item of the condition list. |
4785 | If the call of the method for a member item returns a new item |
4786 | the old item is substituted for a new one. |
4787 | After this the transformer is applied to the root node |
4788 | of the Item_cond object. |
4789 | |
4790 | @param analyzer the analyzer callback function to be applied to the |
4791 | nodes of the tree of the object |
4792 | @param[in,out] arg_p parameter to be passed to the analyzer |
4793 | @param transformer the transformer callback function to be applied to the |
4794 | nodes of the tree of the object |
4795 | @param arg_t parameter to be passed to the transformer |
4796 | |
4797 | @return |
4798 | Item returned as the result of transformation of the root node |
4799 | */ |
4800 | |
4801 | Item *Item_cond::compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, |
4802 | Item_transformer transformer, uchar *arg_t) |
4803 | { |
4804 | if (!(this->*analyzer)(arg_p)) |
4805 | return 0; |
4806 | |
4807 | List_iterator<Item> li(list); |
4808 | Item *item; |
4809 | while ((item= li++)) |
4810 | { |
4811 | /* |
4812 | The same parameter value of arg_p must be passed |
4813 | to analyze any argument of the condition formula. |
4814 | */ |
4815 | uchar *arg_v= *arg_p; |
4816 | Item *new_item= item->compile(thd, analyzer, &arg_v, transformer, arg_t); |
4817 | if (new_item && new_item != item) |
4818 | thd->change_item_tree(li.ref(), new_item); |
4819 | } |
4820 | return Item_func::transform(thd, transformer, arg_t); |
4821 | } |
4822 | |
4823 | |
4824 | Item *Item_cond::propagate_equal_fields(THD *thd, |
4825 | const Context &ctx, |
4826 | COND_EQUAL *cond) |
4827 | { |
4828 | DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); |
4829 | DBUG_ASSERT(arg_count == 0); |
4830 | List_iterator<Item> li(list); |
4831 | while (li++) |
4832 | { |
4833 | /* |
4834 | The exact value of the last parameter to propagate_and_change_item_tree() |
4835 | is not important at this point. Item_func derivants will create and |
4836 | pass their own context to the arguments. |
4837 | */ |
4838 | propagate_and_change_item_tree(thd, li.ref(), cond, Context_boolean()); |
4839 | } |
4840 | return this; |
4841 | } |
4842 | |
4843 | void Item_cond::traverse_cond(Cond_traverser traverser, |
4844 | void *arg, traverse_order order) |
4845 | { |
4846 | List_iterator<Item> li(list); |
4847 | Item *item; |
4848 | |
4849 | switch(order) { |
4850 | case(PREFIX): |
4851 | (*traverser)(this, arg); |
4852 | while ((item= li++)) |
4853 | { |
4854 | item->traverse_cond(traverser, arg, order); |
4855 | } |
4856 | (*traverser)(NULL, arg); |
4857 | break; |
4858 | case(POSTFIX): |
4859 | while ((item= li++)) |
4860 | { |
4861 | item->traverse_cond(traverser, arg, order); |
4862 | } |
4863 | (*traverser)(this, arg); |
4864 | } |
4865 | } |
4866 | |
4867 | /** |
4868 | Move SUM items out from item tree and replace with reference. |
4869 | |
4870 | The split is done to get an unique item for each SUM function |
4871 | so that we can easily find and calculate them. |
4872 | (Calculation done by update_sum_func() and copy_sum_funcs() in |
4873 | sql_select.cc) |
4874 | |
4875 | @param thd Thread handler |
4876 | @param ref_pointer_array Pointer to array of reference fields |
4877 | @param fields All fields in select |
4878 | |
4879 | @note |
4880 | This function is run on all expression (SELECT list, WHERE, HAVING etc) |
4881 | that have or refer (HAVING) to a SUM expression. |
4882 | */ |
4883 | |
4884 | void Item_cond::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, |
4885 | List<Item> &fields, uint flags) |
4886 | { |
4887 | List_iterator<Item> li(list); |
4888 | Item *item; |
4889 | while ((item= li++)) |
4890 | item->split_sum_func2(thd, ref_pointer_array, fields, li.ref(), |
4891 | flags | SPLIT_SUM_SKIP_REGISTERED); |
4892 | } |
4893 | |
4894 | |
4895 | table_map |
4896 | Item_cond::used_tables() const |
4897 | { // This caches used_tables |
4898 | return used_tables_cache; |
4899 | } |
4900 | |
4901 | |
4902 | void Item_cond::print(String *str, enum_query_type query_type) |
4903 | { |
4904 | List_iterator_fast<Item> li(list); |
4905 | Item *item; |
4906 | if ((item=li++)) |
4907 | item->print_parenthesised(str, query_type, precedence()); |
4908 | while ((item=li++)) |
4909 | { |
4910 | str->append(' '); |
4911 | str->append(func_name()); |
4912 | str->append(' '); |
4913 | item->print_parenthesised(str, query_type, precedence()); |
4914 | } |
4915 | } |
4916 | |
4917 | |
4918 | void Item_cond::neg_arguments(THD *thd) |
4919 | { |
4920 | List_iterator<Item> li(list); |
4921 | Item *item; |
4922 | while ((item= li++)) /* Apply not transformation to the arguments */ |
4923 | { |
4924 | Item *new_item= item->neg_transformer(thd); |
4925 | if (!new_item) |
4926 | { |
4927 | if (!(new_item= new (thd->mem_root) Item_func_not(thd, item))) |
4928 | return; // Fatal OEM error |
4929 | } |
4930 | (void) li.replace(new_item); |
4931 | } |
4932 | } |
4933 | |
4934 | |
4935 | /** |
4936 | @brief |
4937 | Building clone for Item_cond |
4938 | |
4939 | @param thd thread handle |
4940 | @param mem_root part of the memory for the clone |
4941 | |
4942 | @details |
4943 | This method gets copy of the current item and also |
4944 | build clones for its elements. For this elements |
4945 | build_copy is called again. |
4946 | |
4947 | @retval |
4948 | clone of the item |
4949 | 0 if an error occured |
4950 | */ |
4951 | |
4952 | Item *Item_cond::build_clone(THD *thd) |
4953 | { |
4954 | List_iterator_fast<Item> li(list); |
4955 | Item *item; |
4956 | Item_cond *copy= (Item_cond *) get_copy(thd); |
4957 | if (!copy) |
4958 | return 0; |
4959 | copy->list.empty(); |
4960 | while ((item= li++)) |
4961 | { |
4962 | Item *arg_clone= item->build_clone(thd); |
4963 | if (!arg_clone) |
4964 | return 0; |
4965 | if (copy->list.push_back(arg_clone, thd->mem_root)) |
4966 | return 0; |
4967 | } |
4968 | return copy; |
4969 | } |
4970 | |
4971 | |
4972 | void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding) |
4973 | { |
4974 | List_iterator<Item> li(list); |
4975 | Item *item; |
4976 | while ((item=li++)) |
4977 | { |
4978 | item->mark_as_condition_AND_part(embedding); |
4979 | } |
4980 | } |
4981 | |
4982 | /** |
4983 | Evaluation of AND(expr, expr, expr ...). |
4984 | |
4985 | @note |
4986 | abort_if_null is set for AND expressions for which we don't care if the |
4987 | result is NULL or 0. This is set for: |
4988 | - WHERE clause |
4989 | - HAVING clause |
4990 | - IF(expression) |
4991 | |
4992 | @retval |
4993 | 1 If all expressions are true |
4994 | @retval |
4995 | 0 If all expressions are false or if we find a NULL expression and |
4996 | 'abort_on_null' is set. |
4997 | @retval |
4998 | NULL if all expression are either 1 or NULL |
4999 | */ |
5000 | |
5001 | |
5002 | longlong Item_cond_and::val_int() |
5003 | { |
5004 | DBUG_ASSERT(fixed == 1); |
5005 | List_iterator_fast<Item> li(list); |
5006 | Item *item; |
5007 | null_value= 0; |
5008 | while ((item=li++)) |
5009 | { |
5010 | if (!item->val_bool()) |
5011 | { |
5012 | if (abort_on_null || !(null_value= item->null_value)) |
5013 | return 0; // return FALSE |
5014 | } |
5015 | } |
5016 | return null_value ? 0 : 1; |
5017 | } |
5018 | |
5019 | |
5020 | longlong Item_cond_or::val_int() |
5021 | { |
5022 | DBUG_ASSERT(fixed == 1); |
5023 | List_iterator_fast<Item> li(list); |
5024 | Item *item; |
5025 | null_value=0; |
5026 | while ((item=li++)) |
5027 | { |
5028 | if (item->val_bool()) |
5029 | { |
5030 | null_value=0; |
5031 | return 1; |
5032 | } |
5033 | if (item->null_value) |
5034 | null_value=1; |
5035 | } |
5036 | return 0; |
5037 | } |
5038 | |
5039 | Item *Item_cond_or::copy_andor_structure(THD *thd) |
5040 | { |
5041 | Item_cond_or *item; |
5042 | if ((item= new (thd->mem_root) Item_cond_or(thd, this))) |
5043 | item->copy_andor_arguments(thd, this); |
5044 | return item; |
5045 | } |
5046 | |
5047 | |
5048 | /** |
5049 | Create an AND expression from two expressions. |
5050 | |
5051 | @param a expression or NULL |
5052 | @param b expression. |
5053 | @param org_item Don't modify a if a == *org_item. |
5054 | If a == NULL, org_item is set to point at b, |
5055 | to ensure that future calls will not modify b. |
5056 | |
5057 | @note |
5058 | This will not modify item pointed to by org_item or b |
5059 | The idea is that one can call this in a loop and create and |
5060 | 'and' over all items without modifying any of the original items. |
5061 | |
5062 | @retval |
5063 | NULL Error |
5064 | @retval |
5065 | Item |
5066 | */ |
5067 | |
5068 | Item *and_expressions(THD *thd, Item *a, Item *b, Item **org_item) |
5069 | { |
5070 | if (!a) |
5071 | return (*org_item= (Item*) b); |
5072 | if (a == *org_item) |
5073 | { |
5074 | Item_cond *res; |
5075 | if ((res= new (thd->mem_root) Item_cond_and(thd, a, (Item*) b))) |
5076 | { |
5077 | res->used_tables_cache= a->used_tables() | b->used_tables(); |
5078 | res->not_null_tables_cache= a->not_null_tables() | b->not_null_tables(); |
5079 | } |
5080 | return res; |
5081 | } |
5082 | if (((Item_cond_and*) a)->add((Item*) b, thd->mem_root)) |
5083 | return 0; |
5084 | ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); |
5085 | ((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables(); |
5086 | return a; |
5087 | } |
5088 | |
5089 | |
5090 | bool Item_func_null_predicate::count_sargable_conds(void *arg) |
5091 | { |
5092 | ((SELECT_LEX*) arg)->cond_count++; |
5093 | return 0; |
5094 | } |
5095 | |
5096 | |
5097 | longlong Item_func_isnull::val_int() |
5098 | { |
5099 | DBUG_ASSERT(fixed == 1); |
5100 | if (const_item() && !args[0]->maybe_null) |
5101 | return 0; |
5102 | return args[0]->is_null() ? 1: 0; |
5103 | } |
5104 | |
5105 | |
5106 | void Item_func_isnull::print(String *str, enum_query_type query_type) |
5107 | { |
5108 | args[0]->print_parenthesised(str, query_type, precedence()); |
5109 | str->append(STRING_WITH_LEN(" is null" )); |
5110 | } |
5111 | |
5112 | |
5113 | longlong Item_is_not_null_test::val_int() |
5114 | { |
5115 | DBUG_ASSERT(fixed == 1); |
5116 | DBUG_ENTER("Item_is_not_null_test::val_int" ); |
5117 | if (const_item() && !args[0]->maybe_null) |
5118 | DBUG_RETURN(1); |
5119 | if (args[0]->is_null()) |
5120 | { |
5121 | DBUG_PRINT("info" , ("null" )); |
5122 | owner->was_null|= 1; |
5123 | DBUG_RETURN(0); |
5124 | } |
5125 | else |
5126 | DBUG_RETURN(1); |
5127 | } |
5128 | |
5129 | /** |
5130 | Optimize case of not_null_column IS NULL. |
5131 | */ |
5132 | void Item_is_not_null_test::update_used_tables() |
5133 | { |
5134 | if (!args[0]->maybe_null) |
5135 | used_tables_cache= 0; /* is always true */ |
5136 | else |
5137 | args[0]->update_used_tables(); |
5138 | } |
5139 | |
5140 | |
5141 | longlong Item_func_isnotnull::val_int() |
5142 | { |
5143 | DBUG_ASSERT(fixed == 1); |
5144 | return args[0]->is_null() ? 0 : 1; |
5145 | } |
5146 | |
5147 | |
5148 | void Item_func_isnotnull::print(String *str, enum_query_type query_type) |
5149 | { |
5150 | args[0]->print_parenthesised(str, query_type, precedence()); |
5151 | str->append(STRING_WITH_LEN(" is not null" )); |
5152 | } |
5153 | |
5154 | |
5155 | bool Item_bool_func2::count_sargable_conds(void *arg) |
5156 | { |
5157 | ((SELECT_LEX*) arg)->cond_count++; |
5158 | return 0; |
5159 | } |
5160 | |
5161 | void Item_func_like::print(String *str, enum_query_type query_type) |
5162 | { |
5163 | args[0]->print_parenthesised(str, query_type, precedence()); |
5164 | str->append(' '); |
5165 | if (negated) |
5166 | str->append(STRING_WITH_LEN(" not " )); |
5167 | str->append(func_name()); |
5168 | str->append(' '); |
5169 | args[1]->print_parenthesised(str, query_type, precedence()); |
5170 | if (escape_used_in_parsing) |
5171 | { |
5172 | str->append(STRING_WITH_LEN(" escape " )); |
5173 | escape_item->print(str, query_type); |
5174 | } |
5175 | } |
5176 | |
5177 | |
5178 | longlong Item_func_like::val_int() |
5179 | { |
5180 | DBUG_ASSERT(fixed == 1); |
5181 | String* res= args[0]->val_str(&cmp_value1); |
5182 | if (args[0]->null_value) |
5183 | { |
5184 | null_value=1; |
5185 | return 0; |
5186 | } |
5187 | String* res2= args[1]->val_str(&cmp_value2); |
5188 | if (args[1]->null_value) |
5189 | { |
5190 | null_value=1; |
5191 | return 0; |
5192 | } |
5193 | null_value=0; |
5194 | if (canDoTurboBM) |
5195 | return turboBM_matches(res->ptr(), res->length()) ? !negated : negated; |
5196 | return my_wildcmp(cmp_collation.collation, |
5197 | res->ptr(),res->ptr()+res->length(), |
5198 | res2->ptr(),res2->ptr()+res2->length(), |
5199 | escape,wild_one,wild_many) ? negated : !negated; |
5200 | } |
5201 | |
5202 | |
5203 | /** |
5204 | We can optimize a where if first character isn't a wildcard |
5205 | */ |
5206 | |
5207 | bool Item_func_like::with_sargable_pattern() const |
5208 | { |
5209 | if (negated) |
5210 | return false; |
5211 | |
5212 | if (!args[1]->const_item() || args[1]->is_expensive()) |
5213 | return false; |
5214 | |
5215 | String* res2= args[1]->val_str((String *) &cmp_value2); |
5216 | if (!res2) |
5217 | return false; |
5218 | |
5219 | if (!res2->length()) // Can optimize empty wildcard: column LIKE '' |
5220 | return true; |
5221 | |
5222 | DBUG_ASSERT(res2->ptr()); |
5223 | char first= res2->ptr()[0]; |
5224 | return first != wild_many && first != wild_one; |
5225 | } |
5226 | |
5227 | |
5228 | SEL_TREE *Item_func_like::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) |
5229 | { |
5230 | MEM_ROOT *tmp_root= param->mem_root; |
5231 | param->thd->mem_root= param->old_root; |
5232 | bool sargable_pattern= with_sargable_pattern(); |
5233 | param->thd->mem_root= tmp_root; |
5234 | return sargable_pattern ? |
5235 | Item_bool_func2::get_mm_tree(param, cond_ptr) : |
5236 | Item_func::get_mm_tree(param, cond_ptr); |
5237 | } |
5238 | |
5239 | |
5240 | bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str, |
5241 | bool escape_used_in_parsing, CHARSET_INFO *cmp_cs, |
5242 | int *escape) |
5243 | { |
5244 | if (!escape_item->const_during_execution()) |
5245 | { |
5246 | my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE" ); |
5247 | return TRUE; |
5248 | } |
5249 | |
5250 | if (escape_item->const_item()) |
5251 | { |
5252 | /* If we are on execution stage */ |
5253 | String *escape_str= escape_item->val_str(tmp_str); |
5254 | if (escape_str) |
5255 | { |
5256 | const char *escape_str_ptr= escape_str->ptr(); |
5257 | if (escape_used_in_parsing && ( |
5258 | (((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) && |
5259 | escape_str->numchars() != 1) || |
5260 | escape_str->numchars() > 1))) |
5261 | { |
5262 | my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE" ); |
5263 | return TRUE; |
5264 | } |
5265 | |
5266 | if (use_mb(cmp_cs)) |
5267 | { |
5268 | CHARSET_INFO *cs= escape_str->charset(); |
5269 | my_wc_t wc; |
5270 | int rc= cs->cset->mb_wc(cs, &wc, |
5271 | (const uchar*) escape_str_ptr, |
5272 | (const uchar*) escape_str_ptr + |
5273 | escape_str->length()); |
5274 | *escape= (int) (rc > 0 ? wc : '\\'); |
5275 | } |
5276 | else |
5277 | { |
5278 | /* |
5279 | In the case of 8bit character set, we pass native |
5280 | code instead of Unicode code as "escape" argument. |
5281 | Convert to "cs" if charset of escape differs. |
5282 | */ |
5283 | uint32 unused; |
5284 | if (escape_str->needs_conversion(escape_str->length(), |
5285 | escape_str->charset(),cmp_cs,&unused)) |
5286 | { |
5287 | char ch; |
5288 | uint errors; |
5289 | uint32 cnvlen= copy_and_convert(&ch, 1, cmp_cs, escape_str_ptr, |
5290 | escape_str->length(), |
5291 | escape_str->charset(), &errors); |
5292 | *escape= cnvlen ? ch : '\\'; |
5293 | } |
5294 | else |
5295 | *escape= escape_str_ptr ? *escape_str_ptr : '\\'; |
5296 | } |
5297 | } |
5298 | else |
5299 | *escape= '\\'; |
5300 | } |
5301 | |
5302 | return FALSE; |
5303 | } |
5304 | |
5305 | bool Item_func_like::fix_fields(THD *thd, Item **ref) |
5306 | { |
5307 | DBUG_ASSERT(fixed == 0); |
5308 | if (Item_bool_func2::fix_fields(thd, ref) || |
5309 | escape_item->fix_fields(thd, &escape_item) || |
5310 | fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing, |
5311 | cmp_collation.collation, &escape)) |
5312 | return TRUE; |
5313 | |
5314 | if (escape_item->const_item()) |
5315 | { |
5316 | /* |
5317 | We could also do boyer-more for non-const items, but as we would have to |
5318 | recompute the tables for each row it's not worth it. |
5319 | */ |
5320 | if (args[1]->const_item() && !use_strnxfrm(collation.collation) && |
5321 | !args[1]->is_expensive()) |
5322 | { |
5323 | String* res2= args[1]->val_str(&cmp_value2); |
5324 | if (!res2) |
5325 | return FALSE; // Null argument |
5326 | |
5327 | const size_t len = res2->length(); |
5328 | const char* first = res2->ptr(); |
5329 | const char* last = first + len - 1; |
5330 | /* |
5331 | len must be > 2 ('%pattern%') |
5332 | heuristic: only do TurboBM for pattern_len > 2 |
5333 | */ |
5334 | |
5335 | if (len > MIN_TURBOBM_PATTERN_LEN + 2 && |
5336 | *first == wild_many && |
5337 | *last == wild_many) |
5338 | { |
5339 | const char* tmp = first + 1; |
5340 | for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ; |
5341 | canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation); |
5342 | } |
5343 | if (canDoTurboBM) |
5344 | { |
5345 | pattern_len = (int) len - 2; |
5346 | pattern = thd->strmake(first + 1, pattern_len); |
5347 | DBUG_PRINT("info" , ("Initializing pattern: '%s'" , first)); |
5348 | int *suff = (int*) thd->alloc((int) (sizeof(int)* |
5349 | ((pattern_len + 1)*2+ |
5350 | alphabet_size))); |
5351 | bmGs = suff + pattern_len + 1; |
5352 | bmBc = bmGs + pattern_len + 1; |
5353 | turboBM_compute_good_suffix_shifts(suff); |
5354 | turboBM_compute_bad_character_shifts(); |
5355 | DBUG_PRINT("info" ,("done" )); |
5356 | } |
5357 | use_sampling= (len > 2 && (*first == wild_many || *first == wild_one)); |
5358 | } |
5359 | } |
5360 | return FALSE; |
5361 | } |
5362 | |
5363 | |
5364 | void Item_func_like::cleanup() |
5365 | { |
5366 | canDoTurboBM= FALSE; |
5367 | Item_bool_func2::cleanup(); |
5368 | } |
5369 | |
5370 | |
5371 | bool Item_func_like::find_selective_predicates_list_processor(void *arg) |
5372 | { |
5373 | find_selective_predicates_list_processor_data *data= |
5374 | (find_selective_predicates_list_processor_data *) arg; |
5375 | if (use_sampling && used_tables() == data->table->map) |
5376 | { |
5377 | THD *thd= data->table->in_use; |
5378 | COND_STATISTIC *stat; |
5379 | Item *arg0; |
5380 | if (!(stat= (COND_STATISTIC *) thd->alloc(sizeof(COND_STATISTIC)))) |
5381 | return TRUE; |
5382 | stat->cond= this; |
5383 | arg0= args[0]->real_item(); |
5384 | if (args[1]->const_item() && arg0->type() == FIELD_ITEM) |
5385 | stat->field_arg= ((Item_field *)arg0)->field; |
5386 | else |
5387 | stat->field_arg= NULL; |
5388 | data->list.push_back(stat, thd->mem_root); |
5389 | } |
5390 | return FALSE; |
5391 | } |
5392 | |
5393 | |
5394 | int Regexp_processor_pcre::default_regex_flags() |
5395 | { |
5396 | return default_regex_flags_pcre(current_thd); |
5397 | } |
5398 | |
5399 | void Regexp_processor_pcre::set_recursion_limit(THD *thd) |
5400 | { |
5401 | long stack_used; |
5402 | DBUG_ASSERT(thd == current_thd); |
5403 | stack_used= available_stack_size(thd->thread_stack, &stack_used); |
5404 | m_pcre_extra.match_limit_recursion= |
5405 | (ulong)((my_thread_stack_size - STACK_MIN_SIZE - stack_used)/my_pcre_frame_size); |
5406 | } |
5407 | |
5408 | |
5409 | /** |
5410 | Convert string to lib_charset, if needed. |
5411 | */ |
5412 | String *Regexp_processor_pcre::convert_if_needed(String *str, String *converter) |
5413 | { |
5414 | if (m_conversion_is_needed) |
5415 | { |
5416 | uint dummy_errors; |
5417 | if (converter->copy(str->ptr(), str->length(), str->charset(), |
5418 | m_library_charset, &dummy_errors)) |
5419 | return NULL; |
5420 | str= converter; |
5421 | } |
5422 | return str; |
5423 | } |
5424 | |
5425 | |
5426 | /** |
5427 | @brief Compile regular expression. |
5428 | |
5429 | @param[in] pattern the pattern to compile from. |
5430 | @param[in] send_error send error message if any. |
5431 | |
5432 | @details Make necessary character set conversion then |
5433 | compile regular expression passed in the args[1]. |
5434 | |
5435 | @retval false success. |
5436 | @retval true error occurred. |
5437 | */ |
5438 | |
5439 | bool Regexp_processor_pcre::compile(String *pattern, bool send_error) |
5440 | { |
5441 | const char *pcreErrorStr; |
5442 | int pcreErrorOffset; |
5443 | |
5444 | if (is_compiled()) |
5445 | { |
5446 | if (!stringcmp(pattern, &m_prev_pattern)) |
5447 | return false; |
5448 | cleanup(); |
5449 | m_prev_pattern.copy(*pattern); |
5450 | } |
5451 | |
5452 | if (!(pattern= convert_if_needed(pattern, &pattern_converter))) |
5453 | return true; |
5454 | |
5455 | m_pcre= pcre_compile(pattern->c_ptr_safe(), m_library_flags, |
5456 | &pcreErrorStr, &pcreErrorOffset, NULL); |
5457 | |
5458 | if (unlikely(m_pcre == NULL)) |
5459 | { |
5460 | if (send_error) |
5461 | { |
5462 | char buff[MAX_FIELD_WIDTH]; |
5463 | my_snprintf(buff, sizeof(buff), "%s at offset %d" , pcreErrorStr, pcreErrorOffset); |
5464 | my_error(ER_REGEXP_ERROR, MYF(0), buff); |
5465 | } |
5466 | return true; |
5467 | } |
5468 | return false; |
5469 | } |
5470 | |
5471 | |
5472 | bool Regexp_processor_pcre::compile(Item *item, bool send_error) |
5473 | { |
5474 | char buff[MAX_FIELD_WIDTH]; |
5475 | String tmp(buff, sizeof(buff), &my_charset_bin); |
5476 | String *pattern= item->val_str(&tmp); |
5477 | if (unlikely(item->null_value) || (unlikely(compile(pattern, send_error)))) |
5478 | return true; |
5479 | return false; |
5480 | } |
5481 | |
5482 | |
5483 | /** |
5484 | Send a warning explaining an error code returned by pcre_exec(). |
5485 | */ |
5486 | void Regexp_processor_pcre::pcre_exec_warn(int rc) const |
5487 | { |
5488 | char buf[64]; |
5489 | const char *errmsg= NULL; |
5490 | THD *thd= current_thd; |
5491 | |
5492 | /* |
5493 | Make a descriptive message only for those pcre_exec() error codes |
5494 | that can actually happen in MariaDB. |
5495 | */ |
5496 | switch (rc) |
5497 | { |
5498 | case PCRE_ERROR_NULL: |
5499 | errmsg= "pcre_exec: null argument passed" ; |
5500 | break; |
5501 | case PCRE_ERROR_BADOPTION: |
5502 | errmsg= "pcre_exec: bad option" ; |
5503 | break; |
5504 | case PCRE_ERROR_BADMAGIC: |
5505 | errmsg= "pcre_exec: bad magic - not a compiled regex" ; |
5506 | break; |
5507 | case PCRE_ERROR_UNKNOWN_OPCODE: |
5508 | errmsg= "pcre_exec: error in compiled regex" ; |
5509 | break; |
5510 | case PCRE_ERROR_NOMEMORY: |
5511 | errmsg= "pcre_exec: Out of memory" ; |
5512 | break; |
5513 | case PCRE_ERROR_NOSUBSTRING: |
5514 | errmsg= "pcre_exec: no substring" ; |
5515 | break; |
5516 | case PCRE_ERROR_MATCHLIMIT: |
5517 | errmsg= "pcre_exec: match limit exceeded" ; |
5518 | break; |
5519 | case PCRE_ERROR_CALLOUT: |
5520 | errmsg= "pcre_exec: callout error" ; |
5521 | break; |
5522 | case PCRE_ERROR_BADUTF8: |
5523 | errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string" ; |
5524 | break; |
5525 | case PCRE_ERROR_BADUTF8_OFFSET: |
5526 | errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence" ; |
5527 | break; |
5528 | case PCRE_ERROR_PARTIAL: |
5529 | errmsg= "pcre_exec: partial match" ; |
5530 | break; |
5531 | case PCRE_ERROR_INTERNAL: |
5532 | errmsg= "pcre_exec: internal error" ; |
5533 | break; |
5534 | case PCRE_ERROR_BADCOUNT: |
5535 | errmsg= "pcre_exec: ovesize is negative" ; |
5536 | break; |
5537 | case PCRE_ERROR_RECURSIONLIMIT: |
5538 | my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded" , |
5539 | m_pcre_extra.match_limit_recursion); |
5540 | errmsg= buf; |
5541 | break; |
5542 | case PCRE_ERROR_BADNEWLINE: |
5543 | errmsg= "pcre_exec: bad newline options" ; |
5544 | break; |
5545 | case PCRE_ERROR_BADOFFSET: |
5546 | errmsg= "pcre_exec: start offset negative or greater than string length" ; |
5547 | break; |
5548 | case PCRE_ERROR_SHORTUTF8: |
5549 | errmsg= "pcre_exec: ended in middle of utf8 sequence" ; |
5550 | break; |
5551 | case PCRE_ERROR_JIT_STACKLIMIT: |
5552 | errmsg= "pcre_exec: insufficient stack memory for JIT compile" ; |
5553 | break; |
5554 | case PCRE_ERROR_RECURSELOOP: |
5555 | errmsg= "pcre_exec: Recursion loop detected" ; |
5556 | break; |
5557 | case PCRE_ERROR_BADMODE: |
5558 | errmsg= "pcre_exec: compiled pattern passed to wrong bit library function" ; |
5559 | break; |
5560 | case PCRE_ERROR_BADENDIANNESS: |
5561 | errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor" ; |
5562 | break; |
5563 | case PCRE_ERROR_JIT_BADOPTION: |
5564 | errmsg= "pcre_exec: bad jit option" ; |
5565 | break; |
5566 | case PCRE_ERROR_BADLENGTH: |
5567 | errmsg= "pcre_exec: negative length" ; |
5568 | break; |
5569 | default: |
5570 | /* |
5571 | As other error codes should normally not happen, |
5572 | we just report the error code without textual description |
5573 | of the code. |
5574 | */ |
5575 | my_snprintf(buf, sizeof(buf), "pcre_exec: Internal error (%d)" , rc); |
5576 | errmsg= buf; |
5577 | } |
5578 | push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, |
5579 | ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR), errmsg); |
5580 | } |
5581 | |
5582 | |
5583 | /** |
5584 | Call pcre_exec() and send a warning if pcre_exec() returned with an error. |
5585 | */ |
5586 | int Regexp_processor_pcre::(const pcre *code, |
5587 | const pcre_extra *, |
5588 | const char *subject, |
5589 | int length, int startoffset, |
5590 | int options, int *ovector, |
5591 | int ovecsize) |
5592 | { |
5593 | int rc= pcre_exec(code, extra, subject, length, |
5594 | startoffset, options, ovector, ovecsize); |
5595 | DBUG_EXECUTE_IF("pcre_exec_error_123" , rc= -123;); |
5596 | if (unlikely(rc < PCRE_ERROR_NOMATCH)) |
5597 | pcre_exec_warn(rc); |
5598 | return rc; |
5599 | } |
5600 | |
5601 | |
5602 | bool Regexp_processor_pcre::exec(const char *str, size_t length, size_t offset) |
5603 | { |
5604 | m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, (int)length, (int)offset, 0, |
5605 | m_SubStrVec, array_elements(m_SubStrVec)); |
5606 | return false; |
5607 | } |
5608 | |
5609 | |
5610 | bool Regexp_processor_pcre::exec(String *str, int offset, |
5611 | uint n_result_offsets_to_convert) |
5612 | { |
5613 | if (!(str= convert_if_needed(str, &subject_converter))) |
5614 | return true; |
5615 | m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, |
5616 | str->c_ptr_safe(), str->length(), |
5617 | offset, 0, |
5618 | m_SubStrVec, array_elements(m_SubStrVec)); |
5619 | if (m_pcre_exec_rc > 0) |
5620 | { |
5621 | uint i; |
5622 | for (i= 0; i < n_result_offsets_to_convert; i++) |
5623 | { |
5624 | /* |
5625 | Convert byte offset into character offset. |
5626 | */ |
5627 | m_SubStrVec[i]= (int) str->charset()->cset->numchars(str->charset(), |
5628 | str->ptr(), |
5629 | str->ptr() + |
5630 | m_SubStrVec[i]); |
5631 | } |
5632 | } |
5633 | return false; |
5634 | } |
5635 | |
5636 | |
5637 | bool Regexp_processor_pcre::exec(Item *item, int offset, |
5638 | uint n_result_offsets_to_convert) |
5639 | { |
5640 | char buff[MAX_FIELD_WIDTH]; |
5641 | String tmp(buff,sizeof(buff),&my_charset_bin); |
5642 | String *res= item->val_str(&tmp); |
5643 | if (item->null_value) |
5644 | return true; |
5645 | return exec(res, offset, n_result_offsets_to_convert); |
5646 | } |
5647 | |
5648 | |
5649 | void Regexp_processor_pcre::fix_owner(Item_func *owner, |
5650 | Item *subject_arg, |
5651 | Item *pattern_arg) |
5652 | { |
5653 | if (!is_compiled() && pattern_arg->const_item()) |
5654 | { |
5655 | if (compile(pattern_arg, true)) |
5656 | { |
5657 | owner->maybe_null= 1; // Will always return NULL |
5658 | return; |
5659 | } |
5660 | set_const(true); |
5661 | owner->maybe_null= subject_arg->maybe_null; |
5662 | } |
5663 | else |
5664 | owner->maybe_null= 1; |
5665 | } |
5666 | |
5667 | |
5668 | bool Item_func_regex::fix_fields(THD *thd, Item **ref) |
5669 | { |
5670 | re.set_recursion_limit(thd); |
5671 | return Item_bool_func::fix_fields(thd, ref); |
5672 | } |
5673 | |
5674 | void |
5675 | Item_func_regex::fix_length_and_dec() |
5676 | { |
5677 | Item_bool_func::fix_length_and_dec(); |
5678 | |
5679 | if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) |
5680 | return; |
5681 | |
5682 | re.init(cmp_collation.collation, 0); |
5683 | re.fix_owner(this, args[0], args[1]); |
5684 | } |
5685 | |
5686 | |
5687 | longlong Item_func_regex::val_int() |
5688 | { |
5689 | DBUG_ASSERT(fixed == 1); |
5690 | if ((null_value= re.recompile(args[1]))) |
5691 | return 0; |
5692 | |
5693 | if ((null_value= re.exec(args[0], 0, 0))) |
5694 | return 0; |
5695 | |
5696 | return re.match(); |
5697 | } |
5698 | |
5699 | |
5700 | bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref) |
5701 | { |
5702 | re.set_recursion_limit(thd); |
5703 | return Item_int_func::fix_fields(thd, ref); |
5704 | } |
5705 | |
5706 | |
5707 | void |
5708 | Item_func_regexp_instr::fix_length_and_dec() |
5709 | { |
5710 | if (agg_arg_charsets_for_comparison(cmp_collation, args, 2)) |
5711 | return; |
5712 | |
5713 | re.init(cmp_collation.collation, 0); |
5714 | re.fix_owner(this, args[0], args[1]); |
5715 | max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate |
5716 | } |
5717 | |
5718 | |
5719 | longlong Item_func_regexp_instr::val_int() |
5720 | { |
5721 | DBUG_ASSERT(fixed == 1); |
5722 | if ((null_value= re.recompile(args[1]))) |
5723 | return 0; |
5724 | |
5725 | if ((null_value= re.exec(args[0], 0, 1))) |
5726 | return 0; |
5727 | |
5728 | return re.match() ? re.subpattern_start(0) + 1 : 0; |
5729 | } |
5730 | |
5731 | |
5732 | #ifdef LIKE_CMP_TOUPPER |
5733 | #define likeconv(cs,A) (uchar) (cs)->toupper(A) |
5734 | #else |
5735 | #define likeconv(cs,A) (uchar) (cs)->sort_order[(uchar) (A)] |
5736 | #endif |
5737 | |
5738 | |
5739 | /** |
5740 | Precomputation dependent only on pattern_len. |
5741 | */ |
5742 | |
5743 | void Item_func_like::turboBM_compute_suffixes(int *suff) |
5744 | { |
5745 | const int plm1 = pattern_len - 1; |
5746 | int f = 0; |
5747 | int g = plm1; |
5748 | int *const splm1 = suff + plm1; |
5749 | CHARSET_INFO *cs= cmp_collation.collation; |
5750 | |
5751 | *splm1 = pattern_len; |
5752 | |
5753 | if (!cs->sort_order) |
5754 | { |
5755 | int i; |
5756 | for (i = pattern_len - 2; i >= 0; i--) |
5757 | { |
5758 | int tmp = *(splm1 + i - f); |
5759 | if (g < i && tmp < i - g) |
5760 | suff[i] = tmp; |
5761 | else |
5762 | { |
5763 | if (i < g) |
5764 | g = i; // g = MY_MIN(i, g) |
5765 | f = i; |
5766 | while (g >= 0 && pattern[g] == pattern[g + plm1 - f]) |
5767 | g--; |
5768 | suff[i] = f - g; |
5769 | } |
5770 | } |
5771 | } |
5772 | else |
5773 | { |
5774 | int i; |
5775 | for (i = pattern_len - 2; 0 <= i; --i) |
5776 | { |
5777 | int tmp = *(splm1 + i - f); |
5778 | if (g < i && tmp < i - g) |
5779 | suff[i] = tmp; |
5780 | else |
5781 | { |
5782 | if (i < g) |
5783 | g = i; // g = MY_MIN(i, g) |
5784 | f = i; |
5785 | while (g >= 0 && |
5786 | likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f])) |
5787 | g--; |
5788 | suff[i] = f - g; |
5789 | } |
5790 | } |
5791 | } |
5792 | } |
5793 | |
5794 | |
5795 | /** |
5796 | Precomputation dependent only on pattern_len. |
5797 | */ |
5798 | |
5799 | void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff) |
5800 | { |
5801 | turboBM_compute_suffixes(suff); |
5802 | |
5803 | int *end = bmGs + pattern_len; |
5804 | int *k; |
5805 | for (k = bmGs; k < end; k++) |
5806 | *k = pattern_len; |
5807 | |
5808 | int tmp; |
5809 | int i; |
5810 | int j = 0; |
5811 | const int plm1 = pattern_len - 1; |
5812 | for (i = plm1; i > -1; i--) |
5813 | { |
5814 | if (suff[i] == i + 1) |
5815 | { |
5816 | for (tmp = plm1 - i; j < tmp; j++) |
5817 | { |
5818 | int *tmp2 = bmGs + j; |
5819 | if (*tmp2 == pattern_len) |
5820 | *tmp2 = tmp; |
5821 | } |
5822 | } |
5823 | } |
5824 | |
5825 | int *tmp2; |
5826 | for (tmp = plm1 - i; j < tmp; j++) |
5827 | { |
5828 | tmp2 = bmGs + j; |
5829 | if (*tmp2 == pattern_len) |
5830 | *tmp2 = tmp; |
5831 | } |
5832 | |
5833 | tmp2 = bmGs + plm1; |
5834 | for (i = 0; i <= pattern_len - 2; i++) |
5835 | *(tmp2 - suff[i]) = plm1 - i; |
5836 | } |
5837 | |
5838 | |
5839 | /** |
5840 | Precomputation dependent on pattern_len. |
5841 | */ |
5842 | |
5843 | void Item_func_like::turboBM_compute_bad_character_shifts() |
5844 | { |
5845 | int *i; |
5846 | int *end = bmBc + alphabet_size; |
5847 | int j; |
5848 | const int plm1 = pattern_len - 1; |
5849 | CHARSET_INFO *cs= cmp_collation.collation; |
5850 | |
5851 | for (i = bmBc; i < end; i++) |
5852 | *i = pattern_len; |
5853 | |
5854 | if (!cs->sort_order) |
5855 | { |
5856 | for (j = 0; j < plm1; j++) |
5857 | bmBc[(uint) (uchar) pattern[j]] = plm1 - j; |
5858 | } |
5859 | else |
5860 | { |
5861 | for (j = 0; j < plm1; j++) |
5862 | bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j; |
5863 | } |
5864 | } |
5865 | |
5866 | |
5867 | /** |
5868 | Search for pattern in text. |
5869 | |
5870 | @return |
5871 | returns true/false for match/no match |
5872 | */ |
5873 | |
5874 | bool Item_func_like::turboBM_matches(const char* text, int text_len) const |
5875 | { |
5876 | int bcShift; |
5877 | int turboShift; |
5878 | int shift = pattern_len; |
5879 | int j = 0; |
5880 | int u = 0; |
5881 | CHARSET_INFO *cs= cmp_collation.collation; |
5882 | |
5883 | const int plm1= pattern_len - 1; |
5884 | const int tlmpl= text_len - pattern_len; |
5885 | |
5886 | /* Searching */ |
5887 | if (!cs->sort_order) |
5888 | { |
5889 | while (j <= tlmpl) |
5890 | { |
5891 | int i= plm1; |
5892 | while (i >= 0 && pattern[i] == text[i + j]) |
5893 | { |
5894 | i--; |
5895 | if (i == plm1 - shift) |
5896 | i-= u; |
5897 | } |
5898 | if (i < 0) |
5899 | return 1; |
5900 | |
5901 | const int v= plm1 - i; |
5902 | turboShift = u - v; |
5903 | bcShift = bmBc[(uint) (uchar) text[i + j]] - plm1 + i; |
5904 | shift = MY_MAX(turboShift, bcShift); |
5905 | shift = MY_MAX(shift, bmGs[i]); |
5906 | if (shift == bmGs[i]) |
5907 | u = MY_MIN(pattern_len - shift, v); |
5908 | else |
5909 | { |
5910 | if (turboShift < bcShift) |
5911 | shift = MY_MAX(shift, u + 1); |
5912 | u = 0; |
5913 | } |
5914 | j+= shift; |
5915 | } |
5916 | return 0; |
5917 | } |
5918 | else |
5919 | { |
5920 | while (j <= tlmpl) |
5921 | { |
5922 | int i= plm1; |
5923 | while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j])) |
5924 | { |
5925 | i--; |
5926 | if (i == plm1 - shift) |
5927 | i-= u; |
5928 | } |
5929 | if (i < 0) |
5930 | return 1; |
5931 | |
5932 | const int v= plm1 - i; |
5933 | turboShift = u - v; |
5934 | bcShift = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i; |
5935 | shift = MY_MAX(turboShift, bcShift); |
5936 | shift = MY_MAX(shift, bmGs[i]); |
5937 | if (shift == bmGs[i]) |
5938 | u = MY_MIN(pattern_len - shift, v); |
5939 | else |
5940 | { |
5941 | if (turboShift < bcShift) |
5942 | shift = MY_MAX(shift, u + 1); |
5943 | u = 0; |
5944 | } |
5945 | j+= shift; |
5946 | } |
5947 | return 0; |
5948 | } |
5949 | } |
5950 | |
5951 | |
5952 | /** |
5953 | Make a logical XOR of the arguments. |
5954 | |
5955 | If either operator is NULL, return NULL. |
5956 | |
5957 | @todo |
5958 | (low priority) Change this to be optimized as: @n |
5959 | A XOR B -> (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1) @n |
5960 | To be able to do this, we would however first have to extend the MySQL |
5961 | range optimizer to handle OR better. |
5962 | |
5963 | @note |
5964 | As we don't do any index optimization on XOR this is not going to be |
5965 | very fast to use. |
5966 | */ |
5967 | |
5968 | longlong Item_func_xor::val_int() |
5969 | { |
5970 | DBUG_ASSERT(fixed == 1); |
5971 | int result= 0; |
5972 | null_value= false; |
5973 | for (uint i= 0; i < arg_count; i++) |
5974 | { |
5975 | result^= (args[i]->val_int() != 0); |
5976 | if (args[i]->null_value) |
5977 | { |
5978 | null_value= true; |
5979 | return 0; |
5980 | } |
5981 | } |
5982 | return result; |
5983 | } |
5984 | |
5985 | /** |
5986 | Apply NOT transformation to the item and return a new one. |
5987 | |
5988 | |
5989 | Transform the item using next rules: |
5990 | @verbatim |
5991 | a AND b AND ... -> NOT(a) OR NOT(b) OR ... |
5992 | a OR b OR ... -> NOT(a) AND NOT(b) AND ... |
5993 | NOT(a) -> a |
5994 | a = b -> a != b |
5995 | a != b -> a = b |
5996 | a < b -> a >= b |
5997 | a >= b -> a < b |
5998 | a > b -> a <= b |
5999 | a <= b -> a > b |
6000 | IS NULL(a) -> IS NOT NULL(a) |
6001 | IS NOT NULL(a) -> IS NULL(a) |
6002 | @endverbatim |
6003 | |
6004 | @param thd thread handler |
6005 | |
6006 | @return |
6007 | New item or |
6008 | NULL if we cannot apply NOT transformation (see Item::neg_transformer()). |
6009 | */ |
6010 | |
6011 | Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */ |
6012 | { |
6013 | return args[0]; |
6014 | } |
6015 | |
6016 | |
6017 | bool Item_func_not::fix_fields(THD *thd, Item **ref) |
6018 | { |
6019 | args[0]->under_not(this); |
6020 | if (args[0]->type() == FIELD_ITEM) |
6021 | { |
6022 | /* replace "NOT <field>" with "<field> == 0" */ |
6023 | Query_arena backup, *arena; |
6024 | Item *new_item; |
6025 | bool rc= TRUE; |
6026 | arena= thd->activate_stmt_arena_if_needed(&backup); |
6027 | if ((new_item= new (thd->mem_root) Item_func_eq(thd, args[0], new (thd->mem_root) Item_int(thd, 0, 1)))) |
6028 | { |
6029 | new_item->name= name; |
6030 | rc= (*ref= new_item)->fix_fields(thd, ref); |
6031 | } |
6032 | if (arena) |
6033 | thd->restore_active_arena(arena, &backup); |
6034 | return rc; |
6035 | } |
6036 | return Item_func::fix_fields(thd, ref); |
6037 | } |
6038 | |
6039 | |
6040 | Item *Item_bool_rowready_func2::neg_transformer(THD *thd) |
6041 | { |
6042 | Item *item= negated_item(thd); |
6043 | return item; |
6044 | } |
6045 | |
6046 | /** |
6047 | XOR can be negated by negating one of the operands: |
6048 | |
6049 | NOT (a XOR b) => (NOT a) XOR b |
6050 | => a XOR (NOT b) |
6051 | |
6052 | @param thd Thread handle |
6053 | @return New negated item |
6054 | */ |
6055 | Item *Item_func_xor::neg_transformer(THD *thd) |
6056 | { |
6057 | Item *neg_operand; |
6058 | Item_func_xor *new_item; |
6059 | if ((neg_operand= args[0]->neg_transformer(thd))) |
6060 | // args[0] has neg_tranformer |
6061 | new_item= new(thd->mem_root) Item_func_xor(thd, neg_operand, args[1]); |
6062 | else if ((neg_operand= args[1]->neg_transformer(thd))) |
6063 | // args[1] has neg_tranformer |
6064 | new_item= new(thd->mem_root) Item_func_xor(thd, args[0], neg_operand); |
6065 | else |
6066 | { |
6067 | neg_operand= new(thd->mem_root) Item_func_not(thd, args[0]); |
6068 | new_item= new(thd->mem_root) Item_func_xor(thd, neg_operand, args[1]); |
6069 | } |
6070 | return new_item; |
6071 | } |
6072 | |
6073 | |
6074 | /** |
6075 | a IS NULL -> a IS NOT NULL. |
6076 | */ |
6077 | Item *Item_func_isnull::neg_transformer(THD *thd) |
6078 | { |
6079 | Item *item= new (thd->mem_root) Item_func_isnotnull(thd, args[0]); |
6080 | return item; |
6081 | } |
6082 | |
6083 | |
6084 | /** |
6085 | a IS NOT NULL -> a IS NULL. |
6086 | */ |
6087 | Item *Item_func_isnotnull::neg_transformer(THD *thd) |
6088 | { |
6089 | Item *item= new (thd->mem_root) Item_func_isnull(thd, args[0]); |
6090 | return item; |
6091 | } |
6092 | |
6093 | |
6094 | Item *Item_cond_and::neg_transformer(THD *thd) /* NOT(a AND b AND ...) -> */ |
6095 | /* NOT a OR NOT b OR ... */ |
6096 | { |
6097 | neg_arguments(thd); |
6098 | Item *item= new (thd->mem_root) Item_cond_or(thd, list); |
6099 | return item; |
6100 | } |
6101 | |
6102 | |
6103 | Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */ |
6104 | /* NOT a AND NOT b AND ... */ |
6105 | { |
6106 | neg_arguments(thd); |
6107 | Item *item= new (thd->mem_root) Item_cond_and(thd, list); |
6108 | return item; |
6109 | } |
6110 | |
6111 | |
6112 | Item *Item_func_nop_all::neg_transformer(THD *thd) |
6113 | { |
6114 | /* "NOT (e $cmp$ ANY (SELECT ...)) -> e $rev_cmp$" ALL (SELECT ...) */ |
6115 | Item_func_not_all *new_item= new (thd->mem_root) Item_func_not_all(thd, args[0]); |
6116 | Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; |
6117 | allany->create_comp_func(FALSE); |
6118 | allany->all= !allany->all; |
6119 | allany->upper_item= new_item; |
6120 | return new_item; |
6121 | } |
6122 | |
6123 | Item *Item_func_not_all::neg_transformer(THD *thd) |
6124 | { |
6125 | /* "NOT (e $cmp$ ALL (SELECT ...)) -> e $rev_cmp$" ANY (SELECT ...) */ |
6126 | Item_func_nop_all *new_item= new (thd->mem_root) Item_func_nop_all(thd, args[0]); |
6127 | Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; |
6128 | allany->all= !allany->all; |
6129 | allany->create_comp_func(TRUE); |
6130 | allany->upper_item= new_item; |
6131 | return new_item; |
6132 | } |
6133 | |
6134 | Item *Item_func_eq::negated_item(THD *thd) /* a = b -> a != b */ |
6135 | { |
6136 | return new (thd->mem_root) Item_func_ne(thd, args[0], args[1]); |
6137 | } |
6138 | |
6139 | |
6140 | Item *Item_func_ne::negated_item(THD *thd) /* a != b -> a = b */ |
6141 | { |
6142 | return new (thd->mem_root) Item_func_eq(thd, args[0], args[1]); |
6143 | } |
6144 | |
6145 | |
6146 | Item *Item_func_lt::negated_item(THD *thd) /* a < b -> a >= b */ |
6147 | { |
6148 | return new (thd->mem_root) Item_func_ge(thd, args[0], args[1]); |
6149 | } |
6150 | |
6151 | |
6152 | Item *Item_func_ge::negated_item(THD *thd) /* a >= b -> a < b */ |
6153 | { |
6154 | return new (thd->mem_root) Item_func_lt(thd, args[0], args[1]); |
6155 | } |
6156 | |
6157 | |
6158 | Item *Item_func_gt::negated_item(THD *thd) /* a > b -> a <= b */ |
6159 | { |
6160 | return new (thd->mem_root) Item_func_le(thd, args[0], args[1]); |
6161 | } |
6162 | |
6163 | |
6164 | Item *Item_func_le::negated_item(THD *thd) /* a <= b -> a > b */ |
6165 | { |
6166 | return new (thd->mem_root) Item_func_gt(thd, args[0], args[1]); |
6167 | } |
6168 | |
6169 | /** |
6170 | just fake method, should never be called. |
6171 | */ |
6172 | Item *Item_bool_rowready_func2::negated_item(THD *thd) |
6173 | { |
6174 | DBUG_ASSERT(0); |
6175 | return 0; |
6176 | } |
6177 | |
6178 | |
6179 | /** |
6180 | Construct a minimal multiple equality item |
6181 | |
6182 | @param f1 the first equal item |
6183 | @param f2 the second equal item |
6184 | @param with_const_item TRUE if the first item is constant |
6185 | |
6186 | @details |
6187 | The constructor builds a new item equal object for the equality f1=f2. |
6188 | One of the equal items can be constant. If this is the case it is passed |
6189 | always as the first parameter and the parameter with_const_item serves |
6190 | as an indicator of this case. |
6191 | Currently any non-constant parameter items must point to an item of the |
6192 | of the type Item_field or Item_direct_view_ref(Item_field). |
6193 | */ |
6194 | |
6195 | Item_equal::Item_equal(THD *thd, const Type_handler *handler, |
6196 | Item *f1, Item *f2, bool with_const_item): |
6197 | Item_bool_func(thd), eval_item(0), cond_false(0), cond_true(0), |
6198 | context_field(NULL), link_equal_fields(FALSE), |
6199 | m_compare_handler(handler), |
6200 | m_compare_collation(f2->collation.collation) |
6201 | { |
6202 | const_item_cache= 0; |
6203 | with_const= with_const_item; |
6204 | equal_items.push_back(f1, thd->mem_root); |
6205 | equal_items.push_back(f2, thd->mem_root); |
6206 | upper_levels= NULL; |
6207 | } |
6208 | |
6209 | |
6210 | /** |
6211 | Copy constructor for a multiple equality |
6212 | |
6213 | @param item_equal source item for the constructor |
6214 | |
6215 | @details |
6216 | The function creates a copy of an Item_equal object. |
6217 | This constructor is used when an item belongs to a multiple equality |
6218 | of an upper level (an upper AND/OR level or an upper level of a nested |
6219 | outer join). |
6220 | */ |
6221 | |
6222 | Item_equal::Item_equal(THD *thd, Item_equal *item_equal): |
6223 | Item_bool_func(thd), eval_item(0), cond_false(0), cond_true(0), |
6224 | context_field(NULL), link_equal_fields(FALSE), |
6225 | m_compare_handler(item_equal->m_compare_handler), |
6226 | m_compare_collation(item_equal->m_compare_collation) |
6227 | { |
6228 | const_item_cache= 0; |
6229 | List_iterator_fast<Item> li(item_equal->equal_items); |
6230 | Item *item; |
6231 | while ((item= li++)) |
6232 | { |
6233 | equal_items.push_back(item, thd->mem_root); |
6234 | } |
6235 | with_const= item_equal->with_const; |
6236 | cond_false= item_equal->cond_false; |
6237 | upper_levels= item_equal->upper_levels; |
6238 | } |
6239 | |
6240 | |
6241 | /** |
6242 | @brief |
6243 | Add a constant item to the Item_equal object |
6244 | |
6245 | @param[in] c the constant to add |
6246 | @param[in] f item from the list equal_items the item c is equal to |
6247 | (this parameter is optional) |
6248 | |
6249 | @details |
6250 | The method adds the constant item c to the equal_items list. If the list |
6251 | doesn't have any constant item yet the item c is just put in the front |
6252 | the list. Otherwise the value of c is compared with the value of the |
6253 | constant item from equal_items. If they are not equal cond_false is set |
6254 | to TRUE. This serves as an indicator that this Item_equal is always FALSE. |
6255 | */ |
6256 | |
6257 | void Item_equal::add_const(THD *thd, Item *c) |
6258 | { |
6259 | if (cond_false) |
6260 | return; |
6261 | if (!with_const) |
6262 | { |
6263 | with_const= TRUE; |
6264 | equal_items.push_front(c, thd->mem_root); |
6265 | return; |
6266 | } |
6267 | Item *const_item= get_const(); |
6268 | switch (Item_equal::compare_type_handler()->cmp_type()) { |
6269 | case TIME_RESULT: |
6270 | { |
6271 | enum_field_types f_type= context_field->field_type(); |
6272 | longlong value0= c->val_temporal_packed(f_type); |
6273 | longlong value1= const_item->val_temporal_packed(f_type); |
6274 | cond_false= c->null_value || const_item->null_value || value0 != value1; |
6275 | break; |
6276 | } |
6277 | case STRING_RESULT: |
6278 | { |
6279 | String *str1, *str2; |
6280 | /* |
6281 | Suppose we have an expression (with a string type field) like this: |
6282 | WHERE field=const1 AND field=const2 ... |
6283 | |
6284 | For all pairs field=constXXX we know that: |
6285 | |
6286 | - Item_func_eq::fix_length_and_dec() performed collation and character |
6287 | set aggregation and added character set converters when needed. |
6288 | Note, the case like: |
6289 | WHERE field=const1 COLLATE latin1_bin AND field=const2 |
6290 | is not handled here, because the field would be replaced to |
6291 | Item_func_set_collation, which cannot get into Item_equal. |
6292 | So all constXXX that are handled by Item_equal |
6293 | already have compatible character sets with "field". |
6294 | |
6295 | - Also, Field_str::test_if_equality_guarantees_uniqueness() guarantees |
6296 | that the comparison collation of all equalities handled by Item_equal |
6297 | match the the collation of the field. |
6298 | |
6299 | Therefore, at Item_equal::add_const() time all constants constXXX |
6300 | should be directly comparable to each other without an additional |
6301 | character set conversion. |
6302 | It's safe to do val_str() for "const_item" and "c" and compare |
6303 | them according to the collation of the *field*. |
6304 | |
6305 | So in a script like this: |
6306 | CREATE TABLE t1 (a VARCHAR(10) COLLATE xxx); |
6307 | INSERT INTO t1 VALUES ('a'),('A'); |
6308 | SELECT * FROM t1 WHERE a='a' AND a='A'; |
6309 | Item_equal::add_const() effectively rewrites the condition to: |
6310 | SELECT * FROM t1 WHERE a='a' AND 'a' COLLATE xxx='A'; |
6311 | and then to: |
6312 | SELECT * FROM t1 WHERE a='a'; // if the two constants were equal |
6313 | // e.g. in case of latin1_swedish_ci |
6314 | or to: |
6315 | SELECT * FROM t1 WHERE FALSE; // if the two constants were not equal |
6316 | // e.g. in case of latin1_bin |
6317 | |
6318 | Note, both "const_item" and "c" can return NULL, e.g.: |
6319 | SELECT * FROM t1 WHERE a=NULL AND a='const'; |
6320 | SELECT * FROM t1 WHERE a='const' AND a=NULL; |
6321 | SELECT * FROM t1 WHERE a='const' AND a=(SELECT MAX(a) FROM t2) |
6322 | */ |
6323 | cond_false= !(str1= const_item->val_str(&cmp_value1)) || |
6324 | !(str2= c->val_str(&cmp_value2)) || |
6325 | !str1->eq(str2, compare_collation()); |
6326 | break; |
6327 | } |
6328 | default: |
6329 | { |
6330 | Item_func_eq *func= new (thd->mem_root) Item_func_eq(thd, c, const_item); |
6331 | if (func->set_cmp_func()) |
6332 | return; |
6333 | func->quick_fix_field(); |
6334 | cond_false= !func->val_int(); |
6335 | } |
6336 | } |
6337 | if (with_const && equal_items.elements == 1) |
6338 | cond_true= TRUE; |
6339 | if (cond_false || cond_true) |
6340 | const_item_cache= 1; |
6341 | } |
6342 | |
6343 | |
6344 | /** |
6345 | @brief |
6346 | Check whether a field is referred to in the multiple equality |
6347 | |
6348 | @param field field whose occurrence is to be checked |
6349 | |
6350 | @details |
6351 | The function checks whether field is referred to by one of the |
6352 | items from the equal_items list. |
6353 | |
6354 | @retval |
6355 | 1 if multiple equality contains a reference to field |
6356 | @retval |
6357 | 0 otherwise |
6358 | */ |
6359 | |
6360 | bool Item_equal::contains(Field *field) |
6361 | { |
6362 | Item_equal_fields_iterator it(*this); |
6363 | while (it++) |
6364 | { |
6365 | if (field->eq(it.get_curr_field())) |
6366 | return 1; |
6367 | } |
6368 | return 0; |
6369 | } |
6370 | |
6371 | |
6372 | /** |
6373 | @brief |
6374 | Join members of another Item_equal object |
6375 | |
6376 | @param item multiple equality whose members are to be joined |
6377 | |
6378 | @details |
6379 | The function actually merges two multiple equalities. After this operation |
6380 | the Item_equal object additionally contains the field items of another item of |
6381 | the type Item_equal. |
6382 | If the optional constant items are not equal the cond_false flag is set to TRUE. |
6383 | |
6384 | @notes |
6385 | The function is called for any equality f1=f2 such that f1 and f2 are items |
6386 | of the type Item_field or Item_direct_view_ref(Item_field), and, f1->field is |
6387 | referred to in the list this->equal_items, while the list item->equal_items |
6388 | contains a reference to f2->field. |
6389 | */ |
6390 | |
6391 | void Item_equal::merge(THD *thd, Item_equal *item) |
6392 | { |
6393 | Item *c= item->get_const(); |
6394 | if (c) |
6395 | item->equal_items.pop(); |
6396 | equal_items.append(&item->equal_items); |
6397 | if (c) |
6398 | { |
6399 | /* |
6400 | The flag cond_false will be set to TRUE after this if |
6401 | the multiple equality already contains a constant and its |
6402 | value is not equal to the value of c. |
6403 | */ |
6404 | add_const(thd, c); |
6405 | } |
6406 | cond_false|= item->cond_false; |
6407 | } |
6408 | |
6409 | |
6410 | /** |
6411 | @brief |
6412 | Merge members of another Item_equal object into this one |
6413 | |
6414 | @param item multiple equality whose members are to be merged |
6415 | @param save_merged keep the list of equalities in 'item' intact |
6416 | (e.g. for other merges) |
6417 | |
6418 | @details |
6419 | If the Item_equal 'item' happens to have some elements of the list |
6420 | of equal items belonging to 'this' object then the function merges |
6421 | the equal items from 'item' into this list. |
6422 | If both lists contains constants and they are different then |
6423 | the value of the cond_false flag is set to TRUE. |
6424 | |
6425 | @retval |
6426 | 1 the lists of equal items in 'item' and 'this' contain common elements |
6427 | @retval |
6428 | 0 otherwise |
6429 | |
6430 | @notes |
6431 | The method 'merge' just joins the list of equal items belonging to 'item' |
6432 | to the list of equal items belonging to this object assuming that the lists |
6433 | are disjoint. It would be more correct to call the method 'join'. |
6434 | The method 'merge_into_with_check' really merges two lists of equal items if |
6435 | they have common members. |
6436 | */ |
6437 | |
6438 | bool Item_equal::merge_with_check(THD *thd, Item_equal *item, bool save_merged) |
6439 | { |
6440 | bool intersected= FALSE; |
6441 | Item_equal_fields_iterator_slow fi(*item); |
6442 | |
6443 | while (fi++) |
6444 | { |
6445 | if (contains(fi.get_curr_field())) |
6446 | { |
6447 | intersected= TRUE; |
6448 | if (!save_merged) |
6449 | fi.remove(); |
6450 | } |
6451 | } |
6452 | if (intersected) |
6453 | { |
6454 | if (!save_merged) |
6455 | merge(thd, item); |
6456 | else |
6457 | { |
6458 | Item *c= item->get_const(); |
6459 | if (c) |
6460 | add_const(thd, c); |
6461 | if (!cond_false) |
6462 | { |
6463 | Item *item; |
6464 | fi.rewind(); |
6465 | while ((item= fi++)) |
6466 | { |
6467 | if (!contains(fi.get_curr_field())) |
6468 | add(item, thd->mem_root); |
6469 | } |
6470 | } |
6471 | } |
6472 | } |
6473 | return intersected; |
6474 | } |
6475 | |
6476 | |
6477 | /** |
6478 | @brief |
6479 | Merge this object into a list of Item_equal objects |
6480 | |
6481 | @param list the list of Item_equal objects to merge into |
6482 | @param save_merged keep the list of equalities in 'this' intact |
6483 | (e.g. for other merges) |
6484 | @param only_intersected do not merge if there are no common members |
6485 | in any of Item_equal objects from the list |
6486 | and this Item_equal |
6487 | |
6488 | @details |
6489 | If the list of equal items from 'this' object contains common members |
6490 | with the lists of equal items belonging to Item_equal objects from 'list' |
6491 | then all involved Item_equal objects e1,...,ek are merged into one |
6492 | Item equal that replaces e1,...,ek in the 'list'. Otherwise, in the case |
6493 | when the value of the parameter only_if_intersected is false, this |
6494 | Item_equal is joined to the 'list'. |
6495 | */ |
6496 | |
6497 | void Item_equal::merge_into_list(THD *thd, List<Item_equal> *list, |
6498 | bool save_merged, |
6499 | bool only_intersected) |
6500 | { |
6501 | Item_equal *item; |
6502 | List_iterator<Item_equal> it(*list); |
6503 | Item_equal *merge_into= NULL; |
6504 | while((item= it++)) |
6505 | { |
6506 | if (!merge_into) |
6507 | { |
6508 | if (item->merge_with_check(thd, this, save_merged)) |
6509 | merge_into= item; |
6510 | } |
6511 | else |
6512 | { |
6513 | if (merge_into->merge_with_check(thd, item, false)) |
6514 | it.remove(); |
6515 | } |
6516 | } |
6517 | if (!only_intersected && !merge_into) |
6518 | list->push_back(this, thd->mem_root); |
6519 | } |
6520 | |
6521 | |
6522 | /** |
6523 | @brief |
6524 | Order equal items of the multiple equality according to a sorting criteria |
6525 | |
6526 | @param compare function to compare items from the equal_items list |
6527 | @param arg context extra parameter for the cmp function |
6528 | |
6529 | @details |
6530 | The function performs ordering of the items from the equal_items list |
6531 | according to the criteria determined by the cmp callback parameter. |
6532 | If cmp(item1,item2,arg)<0 than item1 must be placed after item2. |
6533 | |
6534 | @notes |
6535 | The function sorts equal items by the bubble sort algorithm. |
6536 | The list of field items is looked through and whenever two neighboring |
6537 | members follow in a wrong order they are swapped. This is performed |
6538 | again and again until we get all members in a right order. |
6539 | */ |
6540 | |
6541 | void Item_equal::sort(Item_field_cmpfunc compare, void *arg) |
6542 | { |
6543 | bubble_sort<Item>(&equal_items, compare, arg); |
6544 | } |
6545 | |
6546 | |
6547 | /** |
6548 | @brief |
6549 | Check appearance of new constant items in the multiple equality object |
6550 | |
6551 | @details |
6552 | The function checks appearance of new constant items among the members |
6553 | of the equal_items list. Each new constant item is compared with |
6554 | the constant item from the list if there is any. If there is none the first |
6555 | new constant item is placed at the very beginning of the list and |
6556 | with_const is set to TRUE. If it happens that the compared constant items |
6557 | are unequal then the flag cond_false is set to TRUE. |
6558 | |
6559 | @notes |
6560 | Currently this function is called only after substitution of constant tables. |
6561 | */ |
6562 | |
6563 | void Item_equal::update_const(THD *thd) |
6564 | { |
6565 | List_iterator<Item> it(equal_items); |
6566 | if (with_const) |
6567 | it++; |
6568 | Item *item; |
6569 | while ((item= it++)) |
6570 | { |
6571 | if (item->const_item() && !item->is_expensive() && |
6572 | /* |
6573 | Don't propagate constant status of outer-joined column. |
6574 | Such a constant status here is a result of: |
6575 | a) empty outer-joined table: in this case such a column has a |
6576 | value of NULL; but at the same time other arguments of |
6577 | Item_equal don't have to be NULLs and the value of the whole |
6578 | multiple equivalence expression doesn't have to be NULL or FALSE |
6579 | because of the outer join nature; |
6580 | or |
6581 | b) outer-joined table contains only 1 row: the result of |
6582 | this column is equal to a row field value *or* NULL. |
6583 | Both values are inacceptable as Item_equal constants. |
6584 | */ |
6585 | !item->is_outer_field()) |
6586 | { |
6587 | if (item == equal_items.head()) |
6588 | with_const= TRUE; |
6589 | else |
6590 | { |
6591 | it.remove(); |
6592 | add_const(thd, item); |
6593 | } |
6594 | } |
6595 | } |
6596 | } |
6597 | |
6598 | |
6599 | /** |
6600 | @brief |
6601 | Fix fields in a completely built multiple equality |
6602 | |
6603 | @param thd currently not used thread handle |
6604 | @param ref not used |
6605 | |
6606 | @details |
6607 | This function is called once the multiple equality has been built out of |
6608 | the WHERE/ON condition and no new members are expected to be added to the |
6609 | equal_items list anymore. |
6610 | As any implementation of the virtual fix_fields method the function |
6611 | calculates the cached values of not_null_tables_cache, used_tables_cache, |
6612 | const_item_cache and calls fix_length_and_dec(). |
6613 | Additionally the function sets a reference to the Item_equal object in |
6614 | the non-constant items of the equal_items list unless such a reference has |
6615 | been already set. |
6616 | |
6617 | @notes |
6618 | Currently this function is called only in the function |
6619 | build_equal_items_for_cond. |
6620 | |
6621 | @retval |
6622 | FALSE always |
6623 | */ |
6624 | |
6625 | bool Item_equal::fix_fields(THD *thd, Item **ref) |
6626 | { |
6627 | DBUG_ASSERT(fixed == 0); |
6628 | Item_equal_fields_iterator it(*this); |
6629 | Item *item; |
6630 | Field *first_equal_field= NULL; |
6631 | Field *last_equal_field= NULL; |
6632 | Field *prev_equal_field= NULL; |
6633 | not_null_tables_cache= used_tables_cache= 0; |
6634 | const_item_cache= 0; |
6635 | while ((item= it++)) |
6636 | { |
6637 | table_map tmp_table_map; |
6638 | used_tables_cache|= item->used_tables(); |
6639 | tmp_table_map= item->not_null_tables(); |
6640 | not_null_tables_cache|= tmp_table_map; |
6641 | DBUG_ASSERT(!item->with_sum_func && !item->with_subquery()); |
6642 | if (item->maybe_null) |
6643 | maybe_null= 1; |
6644 | if (!item->get_item_equal()) |
6645 | item->set_item_equal(this); |
6646 | if (link_equal_fields && item->real_item()->type() == FIELD_ITEM) |
6647 | { |
6648 | last_equal_field= ((Item_field *) (item->real_item()))->field; |
6649 | if (!prev_equal_field) |
6650 | first_equal_field= last_equal_field; |
6651 | else |
6652 | prev_equal_field->next_equal_field= last_equal_field; |
6653 | prev_equal_field= last_equal_field; |
6654 | } |
6655 | } |
6656 | if (prev_equal_field && last_equal_field != first_equal_field) |
6657 | last_equal_field->next_equal_field= first_equal_field; |
6658 | fix_length_and_dec(); |
6659 | fixed= 1; |
6660 | return FALSE; |
6661 | } |
6662 | |
6663 | |
6664 | /** |
6665 | Update the value of the used table attribute and other attributes |
6666 | */ |
6667 | |
6668 | void Item_equal::update_used_tables() |
6669 | { |
6670 | not_null_tables_cache= used_tables_cache= 0; |
6671 | if ((const_item_cache= cond_false || cond_true)) |
6672 | return; |
6673 | Item_equal_fields_iterator it(*this); |
6674 | Item *item; |
6675 | const_item_cache= 1; |
6676 | while ((item= it++)) |
6677 | { |
6678 | item->update_used_tables(); |
6679 | used_tables_cache|= item->used_tables(); |
6680 | /* see commentary at Item_equal::update_const() */ |
6681 | const_item_cache&= item->const_item() && !item->is_outer_field(); |
6682 | } |
6683 | } |
6684 | |
6685 | |
6686 | bool Item_equal::count_sargable_conds(void *arg) |
6687 | { |
6688 | SELECT_LEX *sel= (SELECT_LEX *) arg; |
6689 | uint m= equal_items.elements; |
6690 | sel->cond_count+= m*(m-1); |
6691 | return 0; |
6692 | } |
6693 | |
6694 | |
6695 | /** |
6696 | @brief |
6697 | Evaluate multiple equality |
6698 | |
6699 | @details |
6700 | The function evaluate multiple equality to a boolean value. |
6701 | The function ignores non-constant items from the equal_items list. |
6702 | The function returns 1 if all constant items from the list are equal. |
6703 | It returns 0 if there are unequal constant items in the list or |
6704 | one of the constant items is evaluated to NULL. |
6705 | |
6706 | @notes |
6707 | Currently this function can be called only at the optimization |
6708 | stage after the constant table substitution, since all Item_equals |
6709 | are eliminated before the execution stage. |
6710 | |
6711 | @retval |
6712 | 0 multiple equality is always FALSE or NULL |
6713 | 1 otherwise |
6714 | */ |
6715 | |
6716 | longlong Item_equal::val_int() |
6717 | { |
6718 | if (cond_false) |
6719 | return 0; |
6720 | if (cond_true) |
6721 | return 1; |
6722 | Item *item= get_const(); |
6723 | Item_equal_fields_iterator it(*this); |
6724 | if (!item) |
6725 | item= it++; |
6726 | eval_item->store_value(item); |
6727 | if ((null_value= item->null_value)) |
6728 | return 0; |
6729 | while ((item= it++)) |
6730 | { |
6731 | Field *field= it.get_curr_field(); |
6732 | /* Skip fields of tables that has not been read yet */ |
6733 | if (!field->table->status || (field->table->status & STATUS_NULL_ROW)) |
6734 | { |
6735 | const int rc= eval_item->cmp(item); |
6736 | if ((rc == TRUE) || (null_value= (rc == UNKNOWN))) |
6737 | return 0; |
6738 | } |
6739 | } |
6740 | return 1; |
6741 | } |
6742 | |
6743 | |
6744 | void Item_equal::fix_length_and_dec() |
6745 | { |
6746 | Item *item= get_first(NO_PARTICULAR_TAB, NULL); |
6747 | const Type_handler *handler= item->type_handler(); |
6748 | eval_item= handler->make_cmp_item(current_thd, item->collation.collation); |
6749 | } |
6750 | |
6751 | |
6752 | bool Item_equal::walk(Item_processor processor, bool walk_subquery, void *arg) |
6753 | { |
6754 | Item *item; |
6755 | Item_equal_fields_iterator it(*this); |
6756 | while ((item= it++)) |
6757 | { |
6758 | if (item->walk(processor, walk_subquery, arg)) |
6759 | return 1; |
6760 | } |
6761 | return Item_func::walk(processor, walk_subquery, arg); |
6762 | } |
6763 | |
6764 | |
6765 | Item *Item_equal::transform(THD *thd, Item_transformer transformer, uchar *arg) |
6766 | { |
6767 | DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); |
6768 | |
6769 | Item *item; |
6770 | Item_equal_fields_iterator it(*this); |
6771 | while ((item= it++)) |
6772 | { |
6773 | Item *new_item= item->transform(thd, transformer, arg); |
6774 | if (!new_item) |
6775 | return 0; |
6776 | |
6777 | /* |
6778 | THD::change_item_tree() should be called only if the tree was |
6779 | really transformed, i.e. when a new item has been created. |
6780 | Otherwise we'll be allocating a lot of unnecessary memory for |
6781 | change records at each execution. |
6782 | */ |
6783 | if (new_item != item) |
6784 | thd->change_item_tree((Item **) it.ref(), new_item); |
6785 | } |
6786 | return Item_func::transform(thd, transformer, arg); |
6787 | } |
6788 | |
6789 | |
6790 | void Item_equal::print(String *str, enum_query_type query_type) |
6791 | { |
6792 | if (cond_false) |
6793 | { |
6794 | str->append('0'); |
6795 | return; |
6796 | } |
6797 | str->append(func_name()); |
6798 | str->append('('); |
6799 | List_iterator_fast<Item> it(equal_items); |
6800 | Item *item; |
6801 | item= it++; |
6802 | item->print(str, query_type); |
6803 | while ((item= it++)) |
6804 | { |
6805 | str->append(','); |
6806 | str->append(' '); |
6807 | item->print(str, query_type); |
6808 | } |
6809 | str->append(')'); |
6810 | } |
6811 | |
6812 | |
6813 | /* |
6814 | @brief Get the first equal field of multiple equality. |
6815 | @param[in] field the field to get equal field to |
6816 | |
6817 | @details Get the first field of multiple equality that is equal to the |
6818 | given field. In order to make semi-join materialization strategy work |
6819 | correctly we can't propagate equal fields from upper select to a |
6820 | materialized semi-join. |
6821 | Thus the fields is returned according to following rules: |
6822 | |
6823 | 1) If the given field belongs to a semi-join then the first field in |
6824 | multiple equality which belong to the same semi-join is returned. |
6825 | Otherwise NULL is returned. |
6826 | 2) If the given field doesn't belong to a semi-join then |
6827 | the first field in the multiple equality that doesn't belong to any |
6828 | semi-join is returned. |
6829 | If all fields in the equality are belong to semi-join(s) then NULL |
6830 | is returned. |
6831 | 3) If no field is given then the first field in the multiple equality |
6832 | is returned without regarding whether it belongs to a semi-join or not. |
6833 | |
6834 | @retval Found first field in the multiple equality. |
6835 | @retval 0 if no field found. |
6836 | */ |
6837 | |
6838 | Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item) |
6839 | { |
6840 | Item_equal_fields_iterator it(*this); |
6841 | Item *item; |
6842 | if (!field_item) |
6843 | return (it++); |
6844 | Field *field= ((Item_field *) (field_item->real_item()))->field; |
6845 | |
6846 | /* |
6847 | Of all equal fields, return the first one we can use. Normally, this is the |
6848 | field which belongs to the table that is the first in the join order. |
6849 | |
6850 | There is one exception to this: When semi-join materialization strategy is |
6851 | used, and the given field belongs to a table within the semi-join nest, we |
6852 | must pick the first field in the semi-join nest. |
6853 | |
6854 | Example: suppose we have a join order: |
6855 | |
6856 | ot1 ot2 SJ-Mat(it1 it2 it3) ot3 |
6857 | |
6858 | and equality ot2.col = it1.col = it2.col |
6859 | If we're looking for best substitute for 'it2.col', we should pick it1.col |
6860 | and not ot2.col. |
6861 | |
6862 | eliminate_item_equal() also has code that deals with equality substitution |
6863 | in presense of SJM nests. |
6864 | */ |
6865 | |
6866 | TABLE_LIST *emb_nest; |
6867 | if (context != NO_PARTICULAR_TAB) |
6868 | emb_nest= context->emb_sj_nest; |
6869 | else |
6870 | emb_nest= field->table->pos_in_table_list->embedding; |
6871 | |
6872 | if (emb_nest && emb_nest->sj_mat_info && emb_nest->sj_mat_info->is_used) |
6873 | { |
6874 | /* |
6875 | It's a field from an materialized semi-join. We can substitute it for |
6876 | - a constant item |
6877 | - a field from the same semi-join |
6878 | Find the first of such items: |
6879 | */ |
6880 | while ((item= it++)) |
6881 | { |
6882 | if (item->const_item() || |
6883 | it.get_curr_field()->table->pos_in_table_list->embedding == emb_nest) |
6884 | { |
6885 | /* |
6886 | If we found given field then return NULL to avoid unnecessary |
6887 | substitution. |
6888 | */ |
6889 | return (item != field_item) ? item : NULL; |
6890 | } |
6891 | } |
6892 | } |
6893 | else |
6894 | { |
6895 | /* |
6896 | The field is not in SJ-Materialization nest. We must return the first |
6897 | field in the join order. The field may be inside a semi-join nest, i.e |
6898 | a join order may look like this: |
6899 | |
6900 | SJ-Mat(it1 it2) ot1 ot2 |
6901 | |
6902 | where we're looking what to substitute ot2.col for. In this case we must |
6903 | still return it1.col, here's a proof why: |
6904 | |
6905 | First let's note that either it1.col or it2.col participates in |
6906 | subquery's IN-equality. It can't be otherwise, because materialization is |
6907 | only applicable to uncorrelated subqueries, so the only way we could |
6908 | infer "it1.col=ot1.col" is from the IN-equality. Ok, so IN-eqality has |
6909 | it1.col or it2.col on its inner side. it1.col is first such item in the |
6910 | join order, so it's not possible for SJ-Mat to be |
6911 | SJ-Materialization-lookup, it is SJ-Materialization-Scan. The scan part |
6912 | of this strategy will unpack value of it1.col=it2.col into it1.col |
6913 | (that's the first equal item inside the subquery), and we'll be able to |
6914 | get it from there. qed. |
6915 | */ |
6916 | |
6917 | return equal_items.head(); |
6918 | } |
6919 | // Shouldn't get here. |
6920 | DBUG_ASSERT(0); |
6921 | return NULL; |
6922 | } |
6923 | |
6924 | |
6925 | longlong Item_func_dyncol_check::val_int() |
6926 | { |
6927 | char buff[STRING_BUFFER_USUAL_SIZE]; |
6928 | String tmp(buff, sizeof(buff), &my_charset_bin); |
6929 | DYNAMIC_COLUMN col; |
6930 | String *str; |
6931 | enum enum_dyncol_func_result rc; |
6932 | |
6933 | str= args[0]->val_str(&tmp); |
6934 | if (args[0]->null_value) |
6935 | goto null; |
6936 | col.length= str->length(); |
6937 | /* We do not change the string, so could do this trick */ |
6938 | col.str= (char *)str->ptr(); |
6939 | rc= mariadb_dyncol_check(&col); |
6940 | if (rc < 0 && rc != ER_DYNCOL_FORMAT) |
6941 | { |
6942 | dynamic_column_error_message(rc); |
6943 | goto null; |
6944 | } |
6945 | null_value= FALSE; |
6946 | return rc == ER_DYNCOL_OK; |
6947 | |
6948 | null: |
6949 | null_value= TRUE; |
6950 | return 0; |
6951 | } |
6952 | |
6953 | longlong Item_func_dyncol_exists::val_int() |
6954 | { |
6955 | char buff[STRING_BUFFER_USUAL_SIZE], nmstrbuf[11]; |
6956 | String tmp(buff, sizeof(buff), &my_charset_bin), |
6957 | nmbuf(nmstrbuf, sizeof(nmstrbuf), system_charset_info); |
6958 | DYNAMIC_COLUMN col; |
6959 | String *str; |
6960 | LEX_STRING buf, *name= NULL; |
6961 | ulonglong num= 0; |
6962 | enum enum_dyncol_func_result rc; |
6963 | |
6964 | if (args[1]->result_type() == INT_RESULT) |
6965 | num= args[1]->val_int(); |
6966 | else |
6967 | { |
6968 | String *nm= args[1]->val_str(&nmbuf); |
6969 | if (!nm || args[1]->null_value) |
6970 | { |
6971 | null_value= 1; |
6972 | return 1; |
6973 | } |
6974 | if (my_charset_same(nm->charset(), DYNCOL_UTF)) |
6975 | { |
6976 | buf.str= (char *) nm->ptr(); |
6977 | buf.length= nm->length(); |
6978 | } |
6979 | else |
6980 | { |
6981 | uint strlen= nm->length() * DYNCOL_UTF->mbmaxlen + 1; |
6982 | uint dummy_errors; |
6983 | buf.str= (char *) current_thd->alloc(strlen); |
6984 | if (buf.str) |
6985 | { |
6986 | buf.length= |
6987 | copy_and_convert(buf.str, strlen, DYNCOL_UTF, |
6988 | nm->ptr(), nm->length(), nm->charset(), |
6989 | &dummy_errors); |
6990 | } |
6991 | else |
6992 | buf.length= 0; |
6993 | } |
6994 | name= &buf; |
6995 | } |
6996 | str= args[0]->val_str(&tmp); |
6997 | if (args[0]->null_value || args[1]->null_value || num > UINT_MAX16) |
6998 | goto null; |
6999 | col.length= str->length(); |
7000 | /* We do not change the string, so could do this trick */ |
7001 | col.str= (char *)str->ptr(); |
7002 | rc= ((name == NULL) ? |
7003 | mariadb_dyncol_exists_num(&col, (uint) num) : |
7004 | mariadb_dyncol_exists_named(&col, name)); |
7005 | if (rc < 0) |
7006 | { |
7007 | dynamic_column_error_message(rc); |
7008 | goto null; |
7009 | } |
7010 | null_value= FALSE; |
7011 | return rc == ER_DYNCOL_YES; |
7012 | |
7013 | null: |
7014 | null_value= TRUE; |
7015 | return 0; |
7016 | } |
7017 | |
7018 | |
7019 | Item_bool_rowready_func2 *Eq_creator::create(THD *thd, Item *a, Item *b) const |
7020 | { |
7021 | return new(thd->mem_root) Item_func_eq(thd, a, b); |
7022 | } |
7023 | |
7024 | |
7025 | Item_bool_rowready_func2* Eq_creator::create_swap(THD *thd, Item *a, Item *b) const |
7026 | { |
7027 | return new(thd->mem_root) Item_func_eq(thd, b, a); |
7028 | } |
7029 | |
7030 | |
7031 | Item_bool_rowready_func2* Ne_creator::create(THD *thd, Item *a, Item *b) const |
7032 | { |
7033 | return new(thd->mem_root) Item_func_ne(thd, a, b); |
7034 | } |
7035 | |
7036 | |
7037 | Item_bool_rowready_func2* Ne_creator::create_swap(THD *thd, Item *a, Item *b) const |
7038 | { |
7039 | return new(thd->mem_root) Item_func_ne(thd, b, a); |
7040 | } |
7041 | |
7042 | |
7043 | Item_bool_rowready_func2* Gt_creator::create(THD *thd, Item *a, Item *b) const |
7044 | { |
7045 | return new(thd->mem_root) Item_func_gt(thd, a, b); |
7046 | } |
7047 | |
7048 | |
7049 | Item_bool_rowready_func2* Gt_creator::create_swap(THD *thd, Item *a, Item *b) const |
7050 | { |
7051 | return new(thd->mem_root) Item_func_lt(thd, b, a); |
7052 | } |
7053 | |
7054 | |
7055 | Item_bool_rowready_func2* Lt_creator::create(THD *thd, Item *a, Item *b) const |
7056 | { |
7057 | return new(thd->mem_root) Item_func_lt(thd, a, b); |
7058 | } |
7059 | |
7060 | |
7061 | Item_bool_rowready_func2* Lt_creator::create_swap(THD *thd, Item *a, Item *b) const |
7062 | { |
7063 | return new(thd->mem_root) Item_func_gt(thd, b, a); |
7064 | } |
7065 | |
7066 | |
7067 | Item_bool_rowready_func2* Ge_creator::create(THD *thd, Item *a, Item *b) const |
7068 | { |
7069 | return new(thd->mem_root) Item_func_ge(thd, a, b); |
7070 | } |
7071 | |
7072 | |
7073 | Item_bool_rowready_func2* Ge_creator::create_swap(THD *thd, Item *a, Item *b) const |
7074 | { |
7075 | return new(thd->mem_root) Item_func_le(thd, b, a); |
7076 | } |
7077 | |
7078 | |
7079 | Item_bool_rowready_func2* Le_creator::create(THD *thd, Item *a, Item *b) const |
7080 | { |
7081 | return new(thd->mem_root) Item_func_le(thd, a, b); |
7082 | } |
7083 | |
7084 | |
7085 | Item_bool_rowready_func2* Le_creator::create_swap(THD *thd, Item *a, Item *b) const |
7086 | { |
7087 | return new(thd->mem_root) Item_func_ge(thd, b, a); |
7088 | } |
7089 | |