| 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 | |