00001 /* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 /* This file defines all compare functions */ 00019 00020 #ifdef USE_PRAGMA_IMPLEMENTATION 00021 #pragma implementation // gcc: Class implementation 00022 #endif 00023 00024 #include "mysql_priv.h" 00025 #include <m_ctype.h> 00026 #include "sql_select.h" 00027 00028 static bool convert_constant_item(THD *thd, Field *field, Item **item); 00029 00030 static Item_result item_store_type(Item_result a,Item_result b) 00031 { 00032 if (a == STRING_RESULT || b == STRING_RESULT) 00033 return STRING_RESULT; 00034 else if (a == REAL_RESULT || b == REAL_RESULT) 00035 return REAL_RESULT; 00036 else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT) 00037 return DECIMAL_RESULT; 00038 else 00039 return INT_RESULT; 00040 } 00041 00042 static void agg_result_type(Item_result *type, Item **items, uint nitems) 00043 { 00044 Item **item, **item_end; 00045 00046 *type= STRING_RESULT; 00047 /* Skip beginning NULL items */ 00048 for (item= items, item_end= item + nitems; item < item_end; item++) 00049 { 00050 if ((*item)->type() != Item::NULL_ITEM) 00051 { 00052 *type= (*item)->result_type(); 00053 item++; 00054 break; 00055 } 00056 } 00057 /* Combine result types. Note: NULL items don't affect the result */ 00058 for (; item < item_end; item++) 00059 { 00060 if ((*item)->type() != Item::NULL_ITEM) 00061 *type= item_store_type(type[0], (*item)->result_type()); 00062 } 00063 } 00064 00065 00066 /* 00067 Aggregates result types from the array of items. 00068 00069 SYNOPSIS: 00070 agg_cmp_type() 00071 thd thread handle 00072 type [out] the aggregated type 00073 items array of items to aggregate the type from 00074 nitems number of items in the array 00075 00076 DESCRIPTION 00077 This function aggregates result types from the array of items. Found type 00078 supposed to be used later for comparison of values of these items. 00079 Aggregation itself is performed by the item_cmp_type() function. 00080 00081 NOTES 00082 Aggregation rules: 00083 If there are DATE/TIME fields/functions in the list and no string 00084 fields/functions in the list then: 00085 The INT_RESULT type will be used for aggregation instead of original 00086 result type of any DATE/TIME field/function in the list 00087 All constant items in the list will be converted to a DATE/TIME using 00088 found field or result field of found function. 00089 00090 Implementation notes: 00091 The code is equivalent to: 00092 1. Check the list for presence of a STRING field/function. 00093 Collect the is_const flag. 00094 2. Get a Field* object to use for type coercion 00095 3. Perform type conversion. 00096 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME 00097 field/function and checks presence of a STRING field/function. 00098 The second loop works only if a DATE/TIME field/function is found. 00099 It checks presence of a STRING field/function in the rest of the list. 00100 00101 TODO 00102 1) The current implementation can produce false comparison results for 00103 expressions like: 00104 date_time_field BETWEEN string_field_with_dates AND string_constant 00105 if the string_constant will omit some of leading zeroes. 00106 In order to fully implement correct comparison of DATE/TIME the new 00107 DATETIME_RESULT result type should be introduced and agg_cmp_type() 00108 should return the DATE/TIME field used for the conversion. Later 00109 this field can be used by comparison functions like Item_func_between to 00110 convert string values to ints on the fly and thus return correct results. 00111 This modification will affect functions BETWEEN, IN and CASE. 00112 00113 2) If in the list a DATE field/function and a DATETIME field/function 00114 are present in the list then the first found field/function will be 00115 used for conversion. This may lead to wrong results and probably should 00116 be fixed. 00117 */ 00118 00119 static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) 00120 { 00121 uint i; 00122 Item::Type res= (Item::Type)0; 00123 /* Used only for date/time fields, max_length = 19 */ 00124 char buff[20]; 00125 uchar null_byte; 00126 Field *field= NULL; 00127 00128 /* Search for date/time fields/functions */ 00129 for (i= 0; i < nitems; i++) 00130 { 00131 if (!items[i]->result_as_longlong()) 00132 { 00133 /* Do not convert anything if a string field/function is present */ 00134 if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) 00135 { 00136 i= nitems; 00137 break; 00138 } 00139 continue; 00140 } 00141 if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && 00142 items[i]->result_type() != INT_RESULT) 00143 { 00144 field= ((Item_field *)items[i]->real_item())->field; 00145 break; 00146 } 00147 else if (res == Item::FUNC_ITEM) 00148 { 00149 field= items[i]->tmp_table_field_from_field_type(0, 0); 00150 if (field) 00151 field->move_field(buff, &null_byte, 0); 00152 break; 00153 } 00154 } 00155 if (field) 00156 { 00157 /* Check the rest of the list for presence of a string field/function. */ 00158 for (i++ ; i < nitems; i++) 00159 { 00160 if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && 00161 !items[i]->result_as_longlong()) 00162 { 00163 if (res == Item::FUNC_ITEM) 00164 delete field; 00165 field= 0; 00166 break; 00167 } 00168 } 00169 } 00170 /* 00171 If the first item is a date/time function then its result should be 00172 compared as int 00173 */ 00174 if (field) 00175 /* Suppose we are comparing dates */ 00176 type[0]= INT_RESULT; 00177 else 00178 type[0]= items[0]->result_type(); 00179 00180 for (i= 0; i < nitems ; i++) 00181 { 00182 Item_result result= items[i]->result_type(); 00183 /* 00184 Use INT_RESULT as result type for DATE/TIME fields/functions and 00185 for constants successfully converted to DATE/TIME 00186 */ 00187 if (field && 00188 ((!items[i]->const_item() && items[i]->result_as_longlong()) || 00189 (items[i]->const_item() && convert_constant_item(thd, field, 00190 &items[i])))) 00191 result= INT_RESULT; 00192 type[0]= item_cmp_type(type[0], result); 00193 } 00194 00195 if (res == Item::FUNC_ITEM && field) 00196 delete field; 00197 } 00198 00199 00200 static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, 00201 const char *fname) 00202 { 00203 my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), 00204 c1.collation->name,c1.derivation_name(), 00205 c2.collation->name,c2.derivation_name(), 00206 fname); 00207 } 00208 00209 00210 Item_bool_func2* Eq_creator::create(Item *a, Item *b) const 00211 { 00212 return new Item_func_eq(a, b); 00213 } 00214 00215 00216 Item_bool_func2* Ne_creator::create(Item *a, Item *b) const 00217 { 00218 return new Item_func_ne(a, b); 00219 } 00220 00221 00222 Item_bool_func2* Gt_creator::create(Item *a, Item *b) const 00223 { 00224 return new Item_func_gt(a, b); 00225 } 00226 00227 00228 Item_bool_func2* Lt_creator::create(Item *a, Item *b) const 00229 { 00230 return new Item_func_lt(a, b); 00231 } 00232 00233 00234 Item_bool_func2* Ge_creator::create(Item *a, Item *b) const 00235 { 00236 return new Item_func_ge(a, b); 00237 } 00238 00239 00240 Item_bool_func2* Le_creator::create(Item *a, Item *b) const 00241 { 00242 return new Item_func_le(a, b); 00243 } 00244 00245 /* 00246 Test functions 00247 Most of these returns 0LL if false and 1LL if true and 00248 NULL if some arg is NULL. 00249 */ 00250 00251 longlong Item_func_not::val_int() 00252 { 00253 DBUG_ASSERT(fixed == 1); 00254 bool value= args[0]->val_bool(); 00255 null_value=args[0]->null_value; 00256 return ((!null_value && value == 0) ? 1 : 0); 00257 } 00258 00259 /* 00260 special NOT for ALL subquery 00261 */ 00262 00263 longlong Item_func_not_all::val_int() 00264 { 00265 DBUG_ASSERT(fixed == 1); 00266 bool value= args[0]->val_bool(); 00267 00268 /* 00269 return TRUE if there was records in underlying select in max/min 00270 optimization (ALL subquery) 00271 */ 00272 if (empty_underlying_subquery()) 00273 return 1; 00274 00275 null_value= args[0]->null_value; 00276 return ((!null_value && value == 0) ? 1 : 0); 00277 } 00278 00279 00280 bool Item_func_not_all::empty_underlying_subquery() 00281 { 00282 return ((test_sum_item && !test_sum_item->any_value()) || 00283 (test_sub_item && !test_sub_item->any_value())); 00284 } 00285 00286 void Item_func_not_all::print(String *str) 00287 { 00288 if (show) 00289 Item_func::print(str); 00290 else 00291 args[0]->print(str); 00292 } 00293 00294 00295 /* 00296 Special NOP (No OPeration) for ALL subquery it is like Item_func_not_all 00297 (return TRUE if underlying subquery do not return rows) but if subquery 00298 returns some rows it return same value as argument (TRUE/FALSE). 00299 */ 00300 00301 longlong Item_func_nop_all::val_int() 00302 { 00303 DBUG_ASSERT(fixed == 1); 00304 longlong value= args[0]->val_int(); 00305 00306 /* 00307 return FALSE if there was records in underlying select in max/min 00308 optimization (SAME/ANY subquery) 00309 */ 00310 if (empty_underlying_subquery()) 00311 return 0; 00312 00313 null_value= args[0]->null_value; 00314 return (null_value || value == 0) ? 0 : 1; 00315 } 00316 00317 00318 /* 00319 Convert a constant item to an int and replace the original item 00320 00321 SYNOPSIS 00322 convert_constant_item() 00323 thd thread handle 00324 field item will be converted using the type of this field 00325 item [in/out] reference to the item to convert 00326 00327 DESCRIPTION 00328 The function converts a constant expression or string to an integer. 00329 On successful conversion the original item is substituted for the 00330 result of the item evaluation. 00331 This is done when comparing DATE/TIME of different formats and 00332 also when comparing bigint to strings (in which case strings 00333 are converted to bigints). 00334 00335 NOTES 00336 This function is called only at prepare stage. 00337 As all derived tables are filled only after all derived tables 00338 are prepared we do not evaluate items with subselects here because 00339 they can contain derived tables and thus we may attempt to use a 00340 table that has not been populated yet. 00341 00342 RESULT VALUES 00343 0 Can't convert item 00344 1 Item was replaced with an integer version of the item 00345 */ 00346 00347 static bool convert_constant_item(THD *thd, Field *field, Item **item) 00348 { 00349 int result= 0; 00350 00351 if (!(*item)->with_subselect && (*item)->const_item()) 00352 { 00353 TABLE *table= field->table; 00354 ulong orig_sql_mode= thd->variables.sql_mode; 00355 my_bitmap_map *old_write_map; 00356 my_bitmap_map *old_read_map; 00357 00358 if (table) 00359 { 00360 old_write_map= dbug_tmp_use_all_columns(table, table->write_set); 00361 old_read_map= dbug_tmp_use_all_columns(table, table->read_set); 00362 } 00363 /* For comparison purposes allow invalid dates like 2000-01-32 */ 00364 thd->variables.sql_mode|= MODE_INVALID_DATES; 00365 if (!(*item)->save_in_field(field, 1) && !((*item)->null_value)) 00366 { 00367 Item *tmp= new Item_int_with_ref(field->val_int(), *item, 00368 test(field->flags & UNSIGNED_FLAG)); 00369 if (tmp) 00370 thd->change_item_tree(item, tmp); 00371 result= 1; // Item was replaced 00372 } 00373 thd->variables.sql_mode= orig_sql_mode; 00374 if (table) 00375 { 00376 dbug_tmp_restore_column_map(table->write_set, old_write_map); 00377 dbug_tmp_restore_column_map(table->read_set, old_read_map); 00378 } 00379 } 00380 return result; 00381 } 00382 00383 00384 void Item_bool_func2::fix_length_and_dec() 00385 { 00386 max_length= 1; // Function returns 0 or 1 00387 THD *thd= current_thd; 00388 00389 /* 00390 As some compare functions are generated after sql_yacc, 00391 we have to check for out of memory conditions here 00392 */ 00393 if (!args[0] || !args[1]) 00394 return; 00395 00396 /* 00397 We allow to convert to Unicode character sets in some cases. 00398 The conditions when conversion is possible are: 00399 - arguments A and B have different charsets 00400 - A wins according to coercibility rules 00401 - character set of A is superset for character set of B 00402 00403 If all of the above is true, then it's possible to convert 00404 B into the character set of A, and then compare according 00405 to the collation of A. 00406 */ 00407 00408 00409 DTCollation coll; 00410 if (args[0]->result_type() == STRING_RESULT && 00411 args[1]->result_type() == STRING_RESULT && 00412 agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV, 1)) 00413 return; 00414 00415 00416 // Make a special case of compare with fields to get nicer DATE comparisons 00417 00418 if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function. 00419 { 00420 set_cmp_func(); 00421 return; 00422 } 00423 00424 if (!thd->is_context_analysis_only()) 00425 { 00426 Item *real_item= args[0]->real_item(); 00427 if (real_item->type() == FIELD_ITEM) 00428 { 00429 Field *field=((Item_field*) real_item)->field; 00430 if (field->can_be_compared_as_longlong()) 00431 { 00432 if (convert_constant_item(thd, field,&args[1])) 00433 { 00434 cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, 00435 INT_RESULT); // Works for all types. 00436 return; 00437 } 00438 } 00439 } 00440 real_item= args[1]->real_item(); 00441 if (real_item->type() == FIELD_ITEM /* && !real_item->const_item() */) 00442 { 00443 Field *field=((Item_field*) real_item)->field; 00444 if (field->can_be_compared_as_longlong()) 00445 { 00446 if (convert_constant_item(thd, field,&args[0])) 00447 { 00448 cmp.set_cmp_func(this, tmp_arg, tmp_arg+1, 00449 INT_RESULT); // Works for all types. 00450 return; 00451 } 00452 } 00453 } 00454 } 00455 set_cmp_func(); 00456 } 00457 00458 00459 int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) 00460 { 00461 owner= item; 00462 func= comparator_matrix[type] 00463 [test(owner->functype() == Item_func::EQUAL_FUNC)]; 00464 switch (type) { 00465 case ROW_RESULT: 00466 { 00467 uint n= (*a)->cols(); 00468 if (n != (*b)->cols()) 00469 { 00470 my_error(ER_OPERAND_COLUMNS, MYF(0), n); 00471 comparators= 0; 00472 return 1; 00473 } 00474 if (!(comparators= new Arg_comparator[n])) 00475 return 1; 00476 for (uint i=0; i < n; i++) 00477 { 00478 if ((*a)->el(i)->cols() != (*b)->el(i)->cols()) 00479 { 00480 my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->el(i)->cols()); 00481 return 1; 00482 } 00483 comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); 00484 } 00485 break; 00486 } 00487 case STRING_RESULT: 00488 { 00489 /* 00490 We must set cmp_charset here as we may be called from for an automatic 00491 generated item, like in natural join 00492 */ 00493 if (cmp_collation.set((*a)->collation, (*b)->collation) || 00494 cmp_collation.derivation == DERIVATION_NONE) 00495 { 00496 my_coll_agg_error((*a)->collation, (*b)->collation, owner->func_name()); 00497 return 1; 00498 } 00499 if (cmp_collation.collation == &my_charset_bin) 00500 { 00501 /* 00502 We are using BLOB/BINARY/VARBINARY, change to compare byte by byte, 00503 without removing end space 00504 */ 00505 if (func == &Arg_comparator::compare_string) 00506 func= &Arg_comparator::compare_binary_string; 00507 else if (func == &Arg_comparator::compare_e_string) 00508 func= &Arg_comparator::compare_e_binary_string; 00509 00510 /* 00511 As this is binary compassion, mark all fields that they can't be 00512 transformed. Otherwise we would get into trouble with comparisons 00513 like: 00514 WHERE col= 'j' AND col LIKE BINARY 'j' 00515 which would be transformed to: 00516 WHERE col= 'j' 00517 */ 00518 (*a)->transform(&Item::set_no_const_sub, (byte*) 0); 00519 (*b)->transform(&Item::set_no_const_sub, (byte*) 0); 00520 } 00521 break; 00522 } 00523 case INT_RESULT: 00524 { 00525 if (func == &Arg_comparator::compare_int_signed) 00526 { 00527 if ((*a)->unsigned_flag) 00528 func= (((*b)->unsigned_flag)? 00529 &Arg_comparator::compare_int_unsigned : 00530 &Arg_comparator::compare_int_unsigned_signed); 00531 else if ((*b)->unsigned_flag) 00532 func= &Arg_comparator::compare_int_signed_unsigned; 00533 } 00534 else if (func== &Arg_comparator::compare_e_int) 00535 { 00536 if ((*a)->unsigned_flag ^ (*b)->unsigned_flag) 00537 func= &Arg_comparator::compare_e_int_diff_signedness; 00538 } 00539 break; 00540 } 00541 case DECIMAL_RESULT: 00542 case REAL_RESULT: 00543 break; 00544 default: 00545 DBUG_ASSERT(0); 00546 } 00547 return 0; 00548 } 00549 00550 00551 int Arg_comparator::compare_string() 00552 { 00553 String *res1,*res2; 00554 if ((res1= (*a)->val_str(&owner->tmp_value1))) 00555 { 00556 if ((res2= (*b)->val_str(&owner->tmp_value2))) 00557 { 00558 owner->null_value= 0; 00559 return sortcmp(res1,res2,cmp_collation.collation); 00560 } 00561 } 00562 owner->null_value= 1; 00563 return -1; 00564 } 00565 00566 00567 /* 00568 Compare strings byte by byte. End spaces are also compared. 00569 00570 RETURN 00571 < 0 *a < *b 00572 0 *b == *b 00573 > 0 *a > *b 00574 */ 00575 00576 int Arg_comparator::compare_binary_string() 00577 { 00578 String *res1,*res2; 00579 if ((res1= (*a)->val_str(&owner->tmp_value1))) 00580 { 00581 if ((res2= (*b)->val_str(&owner->tmp_value2))) 00582 { 00583 owner->null_value= 0; 00584 uint res1_length= res1->length(); 00585 uint res2_length= res2->length(); 00586 int cmp= memcmp(res1->ptr(), res2->ptr(), min(res1_length,res2_length)); 00587 return cmp ? cmp : (int) (res1_length - res2_length); 00588 } 00589 } 00590 owner->null_value= 1; 00591 return -1; 00592 } 00593 00594 00595 /* 00596 Compare strings, but take into account that NULL == NULL 00597 */ 00598 00599 int Arg_comparator::compare_e_string() 00600 { 00601 String *res1,*res2; 00602 res1= (*a)->val_str(&owner->tmp_value1); 00603 res2= (*b)->val_str(&owner->tmp_value2); 00604 if (!res1 || !res2) 00605 return test(res1 == res2); 00606 return test(sortcmp(res1, res2, cmp_collation.collation) == 0); 00607 } 00608 00609 00610 int Arg_comparator::compare_e_binary_string() 00611 { 00612 String *res1,*res2; 00613 res1= (*a)->val_str(&owner->tmp_value1); 00614 res2= (*b)->val_str(&owner->tmp_value2); 00615 if (!res1 || !res2) 00616 return test(res1 == res2); 00617 return test(stringcmp(res1, res2) == 0); 00618 } 00619 00620 00621 int Arg_comparator::compare_real() 00622 { 00623 /* 00624 Fix yet another manifestation of Bug#2338. 'Volatile' will instruct 00625 gcc to flush double values out of 80-bit Intel FPU registers before 00626 performing the comparison. 00627 */ 00628 volatile double val1, val2; 00629 val1= (*a)->val_real(); 00630 if (!(*a)->null_value) 00631 { 00632 val2= (*b)->val_real(); 00633 if (!(*b)->null_value) 00634 { 00635 owner->null_value= 0; 00636 if (val1 < val2) return -1; 00637 if (val1 == val2) return 0; 00638 return 1; 00639 } 00640 } 00641 owner->null_value= 1; 00642 return -1; 00643 } 00644 00645 int Arg_comparator::compare_decimal() 00646 { 00647 my_decimal value1; 00648 my_decimal *val1= (*a)->val_decimal(&value1); 00649 if (!(*a)->null_value) 00650 { 00651 my_decimal value2; 00652 my_decimal *val2= (*b)->val_decimal(&value2); 00653 if (!(*b)->null_value) 00654 { 00655 owner->null_value= 0; 00656 return my_decimal_cmp(val1, val2); 00657 } 00658 } 00659 owner->null_value= 1; 00660 return -1; 00661 } 00662 00663 int Arg_comparator::compare_e_real() 00664 { 00665 double val1= (*a)->val_real(); 00666 double val2= (*b)->val_real(); 00667 if ((*a)->null_value || (*b)->null_value) 00668 return test((*a)->null_value && (*b)->null_value); 00669 return test(val1 == val2); 00670 } 00671 00672 int Arg_comparator::compare_e_decimal() 00673 { 00674 my_decimal value1, value2; 00675 my_decimal *val1= (*a)->val_decimal(&value1); 00676 my_decimal *val2= (*b)->val_decimal(&value2); 00677 if ((*a)->null_value || (*b)->null_value) 00678 return test((*a)->null_value && (*b)->null_value); 00679 return test(my_decimal_cmp(val1, val2) == 0); 00680 } 00681 00682 int Arg_comparator::compare_int_signed() 00683 { 00684 longlong val1= (*a)->val_int(); 00685 if (!(*a)->null_value) 00686 { 00687 longlong val2= (*b)->val_int(); 00688 if (!(*b)->null_value) 00689 { 00690 owner->null_value= 0; 00691 if (val1 < val2) return -1; 00692 if (val1 == val2) return 0; 00693 return 1; 00694 } 00695 } 00696 owner->null_value= 1; 00697 return -1; 00698 } 00699 00700 00701 /* 00702 Compare values as BIGINT UNSIGNED. 00703 */ 00704 00705 int Arg_comparator::compare_int_unsigned() 00706 { 00707 ulonglong val1= (*a)->val_int(); 00708 if (!(*a)->null_value) 00709 { 00710 ulonglong val2= (*b)->val_int(); 00711 if (!(*b)->null_value) 00712 { 00713 owner->null_value= 0; 00714 if (val1 < val2) return -1; 00715 if (val1 == val2) return 0; 00716 return 1; 00717 } 00718 } 00719 owner->null_value= 1; 00720 return -1; 00721 } 00722 00723 00724 /* 00725 Compare signed (*a) with unsigned (*B) 00726 */ 00727 00728 int Arg_comparator::compare_int_signed_unsigned() 00729 { 00730 longlong sval1= (*a)->val_int(); 00731 if (!(*a)->null_value) 00732 { 00733 ulonglong uval2= (ulonglong)(*b)->val_int(); 00734 if (!(*b)->null_value) 00735 { 00736 owner->null_value= 0; 00737 if (sval1 < 0 || (ulonglong)sval1 < uval2) 00738 return -1; 00739 if ((ulonglong)sval1 == uval2) 00740 return 0; 00741 return 1; 00742 } 00743 } 00744 owner->null_value= 1; 00745 return -1; 00746 } 00747 00748 00749 /* 00750 Compare unsigned (*a) with signed (*B) 00751 */ 00752 00753 int Arg_comparator::compare_int_unsigned_signed() 00754 { 00755 ulonglong uval1= (ulonglong)(*a)->val_int(); 00756 if (!(*a)->null_value) 00757 { 00758 longlong sval2= (*b)->val_int(); 00759 if (!(*b)->null_value) 00760 { 00761 owner->null_value= 0; 00762 if (sval2 < 0) 00763 return 1; 00764 if (uval1 < (ulonglong)sval2) 00765 return -1; 00766 if (uval1 == (ulonglong)sval2) 00767 return 0; 00768 return 1; 00769 } 00770 } 00771 owner->null_value= 1; 00772 return -1; 00773 } 00774 00775 00776 int Arg_comparator::compare_e_int() 00777 { 00778 longlong val1= (*a)->val_int(); 00779 longlong val2= (*b)->val_int(); 00780 if ((*a)->null_value || (*b)->null_value) 00781 return test((*a)->null_value && (*b)->null_value); 00782 return test(val1 == val2); 00783 } 00784 00785 /* 00786 Compare unsigned *a with signed *b or signed *a with unsigned *b. 00787 */ 00788 int Arg_comparator::compare_e_int_diff_signedness() 00789 { 00790 longlong val1= (*a)->val_int(); 00791 longlong val2= (*b)->val_int(); 00792 if ((*a)->null_value || (*b)->null_value) 00793 return test((*a)->null_value && (*b)->null_value); 00794 return (val1 >= 0) && test(val1 == val2); 00795 } 00796 00797 int Arg_comparator::compare_row() 00798 { 00799 int res= 0; 00800 bool was_null= 0; 00801 (*a)->bring_value(); 00802 (*b)->bring_value(); 00803 uint n= (*a)->cols(); 00804 for (uint i= 0; i<n; i++) 00805 { 00806 res= comparators[i].compare(); 00807 if (owner->null_value) 00808 { 00809 // NULL was compared 00810 if (owner->abort_on_null) 00811 return -1; // We do not need correct NULL returning 00812 was_null= 1; 00813 owner->null_value= 0; 00814 res= 0; // continue comparison (maybe we will meet explicit difference) 00815 } 00816 else if (res) 00817 return res; 00818 } 00819 if (was_null) 00820 { 00821 /* 00822 There was NULL(s) in comparison in some parts, but there was not 00823 explicit difference in other parts, so we have to return NULL 00824 */ 00825 owner->null_value= 1; 00826 return -1; 00827 } 00828 return 0; 00829 } 00830 00831 00832 int Arg_comparator::compare_e_row() 00833 { 00834 (*a)->bring_value(); 00835 (*b)->bring_value(); 00836 uint n= (*a)->cols(); 00837 for (uint i= 0; i<n; i++) 00838 { 00839 if (!comparators[i].compare()) 00840 return 0; 00841 } 00842 return 1; 00843 } 00844 00845 00846 bool Item_in_optimizer::fix_left(THD *thd, Item **ref) 00847 { 00848 if (!args[0]->fixed && args[0]->fix_fields(thd, args) || 00849 !cache && !(cache= Item_cache::get_cache(args[0]->result_type()))) 00850 return 1; 00851 00852 cache->setup(args[0]); 00853 if (cache->cols() == 1) 00854 { 00855 if ((used_tables_cache= args[0]->used_tables())) 00856 cache->set_used_tables(OUTER_REF_TABLE_BIT); 00857 else 00858 cache->set_used_tables(0); 00859 } 00860 else 00861 { 00862 uint n= cache->cols(); 00863 for (uint i= 0; i < n; i++) 00864 { 00865 if (args[0]->el(i)->used_tables()) 00866 ((Item_cache *)cache->el(i))->set_used_tables(OUTER_REF_TABLE_BIT); 00867 else 00868 ((Item_cache *)cache->el(i))->set_used_tables(0); 00869 } 00870 used_tables_cache= args[0]->used_tables(); 00871 } 00872 not_null_tables_cache= args[0]->not_null_tables(); 00873 with_sum_func= args[0]->with_sum_func; 00874 const_item_cache= args[0]->const_item(); 00875 return 0; 00876 } 00877 00878 00879 bool Item_in_optimizer::fix_fields(THD *thd, Item **ref) 00880 { 00881 DBUG_ASSERT(fixed == 0); 00882 if (fix_left(thd, ref)) 00883 return TRUE; 00884 if (args[0]->maybe_null) 00885 maybe_null=1; 00886 00887 if (!args[1]->fixed && args[1]->fix_fields(thd, args+1)) 00888 return TRUE; 00889 Item_in_subselect * sub= (Item_in_subselect *)args[1]; 00890 if (args[0]->cols() != sub->engine->cols()) 00891 { 00892 my_error(ER_OPERAND_COLUMNS, MYF(0), args[0]->cols()); 00893 return TRUE; 00894 } 00895 if (args[1]->maybe_null) 00896 maybe_null=1; 00897 with_sum_func= with_sum_func || args[1]->with_sum_func; 00898 used_tables_cache|= args[1]->used_tables(); 00899 not_null_tables_cache|= args[1]->not_null_tables(); 00900 const_item_cache&= args[1]->const_item(); 00901 fixed= 1; 00902 return FALSE; 00903 } 00904 00905 00906 longlong Item_in_optimizer::val_int() 00907 { 00908 DBUG_ASSERT(fixed == 1); 00909 cache->store(args[0]); 00910 if (cache->null_value) 00911 { 00912 null_value= 1; 00913 return 0; 00914 } 00915 bool tmp= args[1]->val_bool_result(); 00916 null_value= args[1]->null_value; 00917 return tmp; 00918 } 00919 00920 00921 void Item_in_optimizer::keep_top_level_cache() 00922 { 00923 cache->keep_array(); 00924 save_cache= 1; 00925 } 00926 00927 00928 void Item_in_optimizer::cleanup() 00929 { 00930 DBUG_ENTER("Item_in_optimizer::cleanup"); 00931 Item_bool_func::cleanup(); 00932 if (!save_cache) 00933 cache= 0; 00934 DBUG_VOID_RETURN; 00935 } 00936 00937 00938 bool Item_in_optimizer::is_null() 00939 { 00940 cache->store(args[0]); 00941 return (null_value= (cache->null_value || args[1]->is_null())); 00942 } 00943 00944 00945 longlong Item_func_eq::val_int() 00946 { 00947 DBUG_ASSERT(fixed == 1); 00948 int value= cmp.compare(); 00949 return value == 0 ? 1 : 0; 00950 } 00951 00952 00953 /* Same as Item_func_eq, but NULL = NULL */ 00954 00955 void Item_func_equal::fix_length_and_dec() 00956 { 00957 Item_bool_func2::fix_length_and_dec(); 00958 maybe_null=null_value=0; 00959 } 00960 00961 longlong Item_func_equal::val_int() 00962 { 00963 DBUG_ASSERT(fixed == 1); 00964 return cmp.compare(); 00965 } 00966 00967 longlong Item_func_ne::val_int() 00968 { 00969 DBUG_ASSERT(fixed == 1); 00970 int value= cmp.compare(); 00971 return value != 0 && !null_value ? 1 : 0; 00972 } 00973 00974 00975 longlong Item_func_ge::val_int() 00976 { 00977 DBUG_ASSERT(fixed == 1); 00978 int value= cmp.compare(); 00979 return value >= 0 ? 1 : 0; 00980 } 00981 00982 00983 longlong Item_func_gt::val_int() 00984 { 00985 DBUG_ASSERT(fixed == 1); 00986 int value= cmp.compare(); 00987 return value > 0 ? 1 : 0; 00988 } 00989 00990 longlong Item_func_le::val_int() 00991 { 00992 DBUG_ASSERT(fixed == 1); 00993 int value= cmp.compare(); 00994 return value <= 0 && !null_value ? 1 : 0; 00995 } 00996 00997 00998 longlong Item_func_lt::val_int() 00999 { 01000 DBUG_ASSERT(fixed == 1); 01001 int value= cmp.compare(); 01002 return value < 0 && !null_value ? 1 : 0; 01003 } 01004 01005 01006 longlong Item_func_strcmp::val_int() 01007 { 01008 DBUG_ASSERT(fixed == 1); 01009 String *a=args[0]->val_str(&tmp_value1); 01010 String *b=args[1]->val_str(&tmp_value2); 01011 if (!a || !b) 01012 { 01013 null_value=1; 01014 return 0; 01015 } 01016 int value= sortcmp(a,b,cmp.cmp_collation.collation); 01017 null_value=0; 01018 return !value ? 0 : (value < 0 ? (longlong) -1 : (longlong) 1); 01019 } 01020 01021 01022 void Item_func_interval::fix_length_and_dec() 01023 { 01024 use_decimal_comparison= (row->el(0)->result_type() == DECIMAL_RESULT) || 01025 (row->el(0)->result_type() == INT_RESULT); 01026 if (row->cols() > 8) 01027 { 01028 bool consts=1; 01029 01030 for (uint i=1 ; consts && i < row->cols() ; i++) 01031 { 01032 consts&= row->el(i)->const_item(); 01033 } 01034 01035 if (consts && 01036 (intervals= 01037 (interval_range*) sql_alloc(sizeof(interval_range)*(row->cols()-1)))) 01038 { 01039 if (use_decimal_comparison) 01040 { 01041 for (uint i=1 ; i < row->cols(); i++) 01042 { 01043 Item *el= row->el(i); 01044 interval_range *range= intervals + (i-1); 01045 if ((el->result_type() == DECIMAL_RESULT) || 01046 (el->result_type() == INT_RESULT)) 01047 { 01048 range->type= DECIMAL_RESULT; 01049 range->dec.init(); 01050 my_decimal *dec= el->val_decimal(&range->dec); 01051 if (dec != &range->dec) 01052 { 01053 range->dec= *dec; 01054 range->dec.fix_buffer_pointer(); 01055 } 01056 } 01057 else 01058 { 01059 range->type= REAL_RESULT; 01060 range->dbl= el->val_real(); 01061 } 01062 } 01063 } 01064 else 01065 { 01066 for (uint i=1 ; i < row->cols(); i++) 01067 { 01068 intervals[i-1].dbl= row->el(i)->val_real(); 01069 } 01070 } 01071 } 01072 } 01073 maybe_null= 0; 01074 max_length= 2; 01075 used_tables_cache|= row->used_tables(); 01076 not_null_tables_cache= row->not_null_tables(); 01077 with_sum_func= with_sum_func || row->with_sum_func; 01078 const_item_cache&= row->const_item(); 01079 } 01080 01081 01082 /* 01083 Execute Item_func_interval() 01084 01085 SYNOPSIS 01086 Item_func_interval::val_int() 01087 01088 NOTES 01089 If we are doing a decimal comparison, we are 01090 evaluating the first item twice. 01091 01092 RETURN 01093 -1 if null value, 01094 0 if lower than lowest 01095 1 - arg_count-1 if between args[n] and args[n+1] 01096 arg_count if higher than biggest argument 01097 */ 01098 01099 longlong Item_func_interval::val_int() 01100 { 01101 DBUG_ASSERT(fixed == 1); 01102 double value; 01103 my_decimal dec_buf, *dec= NULL; 01104 uint i; 01105 01106 if (use_decimal_comparison) 01107 { 01108 dec= row->el(0)->val_decimal(&dec_buf); 01109 if (row->el(0)->null_value) 01110 return -1; 01111 my_decimal2double(E_DEC_FATAL_ERROR, dec, &value); 01112 } 01113 else 01114 { 01115 value= row->el(0)->val_real(); 01116 if (row->el(0)->null_value) 01117 return -1; 01118 } 01119 01120 if (intervals) 01121 { // Use binary search to find interval 01122 uint start,end; 01123 start= 0; 01124 end= row->cols()-2; 01125 while (start != end) 01126 { 01127 uint mid= (start + end + 1) / 2; 01128 interval_range *range= intervals + mid; 01129 my_bool cmp_result; 01130 /* 01131 The values in the range intervall may have different types, 01132 Only do a decimal comparision of the first argument is a decimal 01133 and we are comparing against a decimal 01134 */ 01135 if (dec && range->type == DECIMAL_RESULT) 01136 cmp_result= my_decimal_cmp(&range->dec, dec) <= 0; 01137 else 01138 cmp_result= (range->dbl <= value); 01139 if (cmp_result) 01140 start= mid; 01141 else 01142 end= mid - 1; 01143 } 01144 interval_range *range= intervals+start; 01145 return ((dec && range->type == DECIMAL_RESULT) ? 01146 my_decimal_cmp(dec, &range->dec) < 0 : 01147 value < range->dbl) ? 0 : start + 1; 01148 } 01149 01150 for (i=1 ; i < row->cols() ; i++) 01151 { 01152 Item *el= row->el(i); 01153 if (use_decimal_comparison && 01154 ((el->result_type() == DECIMAL_RESULT) || 01155 (el->result_type() == INT_RESULT))) 01156 { 01157 my_decimal e_dec_buf, *e_dec= row->el(i)->val_decimal(&e_dec_buf); 01158 if (my_decimal_cmp(e_dec, dec) > 0) 01159 return i-1; 01160 } 01161 else if (row->el(i)->val_real() > value) 01162 return i-1; 01163 } 01164 return i-1; 01165 } 01166 01167 01168 /* 01169 Perform context analysis of a BETWEEN item tree 01170 01171 SYNOPSIS: 01172 fix_fields() 01173 thd reference to the global context of the query thread 01174 tables list of all open tables involved in the query 01175 ref pointer to Item* variable where pointer to resulting "fixed" 01176 item is to be assigned 01177 01178 DESCRIPTION 01179 This function performs context analysis (name resolution) and calculates 01180 various attributes of the item tree with Item_func_between as its root. 01181 The function saves in ref the pointer to the item or to a newly created 01182 item that is considered as a replacement for the original one. 01183 01184 NOTES 01185 Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on 01186 a predicate/function level. Then it's easy to show that: 01187 T0(e BETWEEN e1 AND e2) = union(T1(e),T1(e1),T1(e2)) 01188 T1(e BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) 01189 T0(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) 01190 T1(e NOT BETWEEN e1 AND e2) = union(T1(e),intersection(T1(e1),T1(e2))) 01191 01192 RETURN 01193 0 ok 01194 1 got error 01195 */ 01196 01197 bool Item_func_between::fix_fields(THD *thd, Item **ref) 01198 { 01199 if (Item_func_opt_neg::fix_fields(thd, ref)) 01200 return 1; 01201 01202 /* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */ 01203 if (pred_level && !negated) 01204 return 0; 01205 01206 /* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */ 01207 not_null_tables_cache= (args[0]->not_null_tables() | 01208 (args[1]->not_null_tables() & 01209 args[2]->not_null_tables())); 01210 01211 return 0; 01212 } 01213 01214 01215 void Item_func_between::fix_length_and_dec() 01216 { 01217 max_length= 1; 01218 THD *thd= current_thd; 01219 01220 /* 01221 As some compare functions are generated after sql_yacc, 01222 we have to check for out of memory conditions here 01223 */ 01224 if (!args[0] || !args[1] || !args[2]) 01225 return; 01226 agg_cmp_type(thd, &cmp_type, args, 3); 01227 01228 if (cmp_type == STRING_RESULT) 01229 agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1); 01230 } 01231 01232 01233 longlong Item_func_between::val_int() 01234 { // ANSI BETWEEN 01235 DBUG_ASSERT(fixed == 1); 01236 if (cmp_type == STRING_RESULT) 01237 { 01238 String *value,*a,*b; 01239 value=args[0]->val_str(&value0); 01240 if ((null_value=args[0]->null_value)) 01241 return 0; 01242 a=args[1]->val_str(&value1); 01243 b=args[2]->val_str(&value2); 01244 if (!args[1]->null_value && !args[2]->null_value) 01245 return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 && 01246 sortcmp(value,b,cmp_collation.collation) <= 0) != 01247 negated); 01248 if (args[1]->null_value && args[2]->null_value) 01249 null_value=1; 01250 else if (args[1]->null_value) 01251 { 01252 // Set to not null if false range. 01253 null_value= sortcmp(value,b,cmp_collation.collation) <= 0; 01254 } 01255 else 01256 { 01257 // Set to not null if false range. 01258 null_value= sortcmp(value,a,cmp_collation.collation) >= 0; 01259 } 01260 } 01261 else if (cmp_type == INT_RESULT) 01262 { 01263 longlong value=args[0]->val_int(), a, b; 01264 if ((null_value=args[0]->null_value)) 01265 return 0; /* purecov: inspected */ 01266 a=args[1]->val_int(); 01267 b=args[2]->val_int(); 01268 if (!args[1]->null_value && !args[2]->null_value) 01269 return (longlong) ((value >= a && value <= b) != negated); 01270 if (args[1]->null_value && args[2]->null_value) 01271 null_value=1; 01272 else if (args[1]->null_value) 01273 { 01274 null_value= value <= b; // not null if false range. 01275 } 01276 else 01277 { 01278 null_value= value >= a; 01279 } 01280 } 01281 else if (cmp_type == DECIMAL_RESULT) 01282 { 01283 my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf), 01284 a_buf, *a_dec, b_buf, *b_dec; 01285 if ((null_value=args[0]->null_value)) 01286 return 0; /* purecov: inspected */ 01287 a_dec= args[1]->val_decimal(&a_buf); 01288 b_dec= args[2]->val_decimal(&b_buf); 01289 if (!args[1]->null_value && !args[2]->null_value) 01290 return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 && 01291 my_decimal_cmp(dec, b_dec) <= 0) != negated); 01292 if (args[1]->null_value && args[2]->null_value) 01293 null_value=1; 01294 else if (args[1]->null_value) 01295 null_value= (my_decimal_cmp(dec, b_dec) <= 0); 01296 else 01297 null_value= (my_decimal_cmp(dec, a_dec) >= 0); 01298 } 01299 else 01300 { 01301 double value= args[0]->val_real(),a,b; 01302 if ((null_value=args[0]->null_value)) 01303 return 0; /* purecov: inspected */ 01304 a= args[1]->val_real(); 01305 b= args[2]->val_real(); 01306 if (!args[1]->null_value && !args[2]->null_value) 01307 return (longlong) ((value >= a && value <= b) != negated); 01308 if (args[1]->null_value && args[2]->null_value) 01309 null_value=1; 01310 else if (args[1]->null_value) 01311 { 01312 null_value= value <= b; // not null if false range. 01313 } 01314 else 01315 { 01316 null_value= value >= a; 01317 } 01318 } 01319 return (longlong) (!null_value && negated); 01320 } 01321 01322 01323 void Item_func_between::print(String *str) 01324 { 01325 str->append('('); 01326 args[0]->print(str); 01327 if (negated) 01328 str->append(STRING_WITH_LEN(" not")); 01329 str->append(STRING_WITH_LEN(" between ")); 01330 args[1]->print(str); 01331 str->append(STRING_WITH_LEN(" and ")); 01332 args[2]->print(str); 01333 str->append(')'); 01334 } 01335 01336 void 01337 Item_func_ifnull::fix_length_and_dec() 01338 { 01339 agg_result_type(&hybrid_type, args, 2); 01340 maybe_null=args[1]->maybe_null; 01341 decimals= max(args[0]->decimals, args[1]->decimals); 01342 max_length= (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) ? 01343 (max(args[0]->max_length - args[0]->decimals, 01344 args[1]->max_length - args[1]->decimals) + decimals) : 01345 max(args[0]->max_length, args[1]->max_length); 01346 01347 switch (hybrid_type) { 01348 case STRING_RESULT: 01349 agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1); 01350 break; 01351 case DECIMAL_RESULT: 01352 case REAL_RESULT: 01353 break; 01354 case INT_RESULT: 01355 decimals= 0; 01356 break; 01357 case ROW_RESULT: 01358 default: 01359 DBUG_ASSERT(0); 01360 } 01361 cached_field_type= args[0]->field_type(); 01362 if (cached_field_type != args[1]->field_type()) 01363 cached_field_type= Item_func::field_type(); 01364 } 01365 01366 01367 uint Item_func_ifnull::decimal_precision() const 01368 { 01369 int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part()); 01370 return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); 01371 } 01372 01373 01374 enum_field_types Item_func_ifnull::field_type() const 01375 { 01376 return cached_field_type; 01377 } 01378 01379 Field *Item_func_ifnull::tmp_table_field(TABLE *table) 01380 { 01381 return tmp_table_field_from_field_type(table, 0); 01382 } 01383 01384 double 01385 Item_func_ifnull::real_op() 01386 { 01387 DBUG_ASSERT(fixed == 1); 01388 double value= args[0]->val_real(); 01389 if (!args[0]->null_value) 01390 { 01391 null_value=0; 01392 return value; 01393 } 01394 value= args[1]->val_real(); 01395 if ((null_value=args[1]->null_value)) 01396 return 0.0; 01397 return value; 01398 } 01399 01400 longlong 01401 Item_func_ifnull::int_op() 01402 { 01403 DBUG_ASSERT(fixed == 1); 01404 longlong value=args[0]->val_int(); 01405 if (!args[0]->null_value) 01406 { 01407 null_value=0; 01408 return value; 01409 } 01410 value=args[1]->val_int(); 01411 if ((null_value=args[1]->null_value)) 01412 return 0; 01413 return value; 01414 } 01415 01416 01417 my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value) 01418 { 01419 DBUG_ASSERT(fixed == 1); 01420 my_decimal *value= args[0]->val_decimal(decimal_value); 01421 if (!args[0]->null_value) 01422 { 01423 null_value= 0; 01424 return value; 01425 } 01426 value= args[1]->val_decimal(decimal_value); 01427 if ((null_value= args[1]->null_value)) 01428 return 0; 01429 return value; 01430 } 01431 01432 01433 String * 01434 Item_func_ifnull::str_op(String *str) 01435 { 01436 DBUG_ASSERT(fixed == 1); 01437 String *res =args[0]->val_str(str); 01438 if (!args[0]->null_value) 01439 { 01440 null_value=0; 01441 res->set_charset(collation.collation); 01442 return res; 01443 } 01444 res=args[1]->val_str(str); 01445 if ((null_value=args[1]->null_value)) 01446 return 0; 01447 res->set_charset(collation.collation); 01448 return res; 01449 } 01450 01451 01452 /* 01453 Perform context analysis of an IF item tree 01454 01455 SYNOPSIS: 01456 fix_fields() 01457 thd reference to the global context of the query thread 01458 tables list of all open tables involved in the query 01459 ref pointer to Item* variable where pointer to resulting "fixed" 01460 item is to be assigned 01461 01462 DESCRIPTION 01463 This function performs context analysis (name resolution) and calculates 01464 various attributes of the item tree with Item_func_if as its root. 01465 The function saves in ref the pointer to the item or to a newly created 01466 item that is considered as a replacement for the original one. 01467 01468 NOTES 01469 Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on 01470 a predicate/function level. Then it's easy to show that: 01471 T0(IF(e,e1,e2) = T1(IF(e,e1,e2)) 01472 T1(IF(e,e1,e2)) = intersection(T1(e1),T1(e2)) 01473 01474 RETURN 01475 0 ok 01476 1 got error 01477 */ 01478 01479 bool 01480 Item_func_if::fix_fields(THD *thd, Item **ref) 01481 { 01482 DBUG_ASSERT(fixed == 0); 01483 args[0]->top_level_item(); 01484 01485 if (Item_func::fix_fields(thd, ref)) 01486 return 1; 01487 01488 not_null_tables_cache= (args[1]->not_null_tables() & 01489 args[2]->not_null_tables()); 01490 01491 return 0; 01492 } 01493 01494 01495 void 01496 Item_func_if::fix_length_and_dec() 01497 { 01498 maybe_null=args[1]->maybe_null || args[2]->maybe_null; 01499 decimals= max(args[1]->decimals, args[2]->decimals); 01500 01501 enum Item_result arg1_type=args[1]->result_type(); 01502 enum Item_result arg2_type=args[2]->result_type(); 01503 bool null1=args[1]->const_item() && args[1]->null_value; 01504 bool null2=args[2]->const_item() && args[2]->null_value; 01505 01506 if (null1) 01507 { 01508 cached_result_type= arg2_type; 01509 collation.set(args[2]->collation.collation); 01510 } 01511 else if (null2) 01512 { 01513 cached_result_type= arg1_type; 01514 collation.set(args[1]->collation.collation); 01515 } 01516 else 01517 { 01518 agg_result_type(&cached_result_type, args+1, 2); 01519 if (cached_result_type == STRING_RESULT) 01520 { 01521 if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV, 1)) 01522 return; 01523 } 01524 else 01525 { 01526 collation.set(&my_charset_bin); // Number 01527 } 01528 } 01529 max_length= 01530 (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT) ? 01531 (max(args[1]->max_length - args[1]->decimals, 01532 args[2]->max_length - args[2]->decimals) + decimals + 01533 (unsigned_flag ? 0 : 1) ) : 01534 max(args[1]->max_length, args[2]->max_length); 01535 } 01536 01537 01538 uint Item_func_if::decimal_precision() const 01539 { 01540 int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+ 01541 decimals); 01542 return min(precision, DECIMAL_MAX_PRECISION); 01543 } 01544 01545 01546 double 01547 Item_func_if::val_real() 01548 { 01549 DBUG_ASSERT(fixed == 1); 01550 Item *arg= args[0]->val_bool() ? args[1] : args[2]; 01551 double value= arg->val_real(); 01552 null_value=arg->null_value; 01553 return value; 01554 } 01555 01556 longlong 01557 Item_func_if::val_int() 01558 { 01559 DBUG_ASSERT(fixed == 1); 01560 Item *arg= args[0]->val_bool() ? args[1] : args[2]; 01561 longlong value=arg->val_int(); 01562 null_value=arg->null_value; 01563 return value; 01564 } 01565 01566 String * 01567 Item_func_if::val_str(String *str) 01568 { 01569 DBUG_ASSERT(fixed == 1); 01570 Item *arg= args[0]->val_bool() ? args[1] : args[2]; 01571 String *res=arg->val_str(str); 01572 if (res) 01573 res->set_charset(collation.collation); 01574 null_value=arg->null_value; 01575 return res; 01576 } 01577 01578 01579 my_decimal * 01580 Item_func_if::val_decimal(my_decimal *decimal_value) 01581 { 01582 DBUG_ASSERT(fixed == 1); 01583 Item *arg= args[0]->val_bool() ? args[1] : args[2]; 01584 my_decimal *value= arg->val_decimal(decimal_value); 01585 null_value= arg->null_value; 01586 return value; 01587 } 01588 01589 01590 void 01591 Item_func_nullif::fix_length_and_dec() 01592 { 01593 Item_bool_func2::fix_length_and_dec(); 01594 maybe_null=1; 01595 if (args[0]) // Only false if EOM 01596 { 01597 max_length=args[0]->max_length; 01598 decimals=args[0]->decimals; 01599 unsigned_flag= args[0]->unsigned_flag; 01600 cached_result_type= args[0]->result_type(); 01601 if (cached_result_type == STRING_RESULT && 01602 agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV, 1)) 01603 return; 01604 } 01605 } 01606 01607 01608 /* 01609 nullif () returns NULL if arguments are equal, else it returns the 01610 first argument. 01611 Note that we have to evaluate the first argument twice as the compare 01612 may have been done with a different type than return value 01613 */ 01614 01615 double 01616 Item_func_nullif::val_real() 01617 { 01618 DBUG_ASSERT(fixed == 1); 01619 double value; 01620 if (!cmp.compare()) 01621 { 01622 null_value=1; 01623 return 0.0; 01624 } 01625 value= args[0]->val_real(); 01626 null_value=args[0]->null_value; 01627 return value; 01628 } 01629 01630 longlong 01631 Item_func_nullif::val_int() 01632 { 01633 DBUG_ASSERT(fixed == 1); 01634 longlong value; 01635 if (!cmp.compare()) 01636 { 01637 null_value=1; 01638 return 0; 01639 } 01640 value=args[0]->val_int(); 01641 null_value=args[0]->null_value; 01642 return value; 01643 } 01644 01645 String * 01646 Item_func_nullif::val_str(String *str) 01647 { 01648 DBUG_ASSERT(fixed == 1); 01649 String *res; 01650 if (!cmp.compare()) 01651 { 01652 null_value=1; 01653 return 0; 01654 } 01655 res=args[0]->val_str(str); 01656 null_value=args[0]->null_value; 01657 return res; 01658 } 01659 01660 01661 my_decimal * 01662 Item_func_nullif::val_decimal(my_decimal * decimal_value) 01663 { 01664 DBUG_ASSERT(fixed == 1); 01665 my_decimal *res; 01666 if (!cmp.compare()) 01667 { 01668 null_value=1; 01669 return 0; 01670 } 01671 res= args[0]->val_decimal(decimal_value); 01672 null_value= args[0]->null_value; 01673 return res; 01674 } 01675 01676 01677 bool 01678 Item_func_nullif::is_null() 01679 { 01680 return (null_value= (!cmp.compare() ? 1 : args[0]->null_value)); 01681 } 01682 01683 /* 01684 CASE expression 01685 Return the matching ITEM or NULL if all compares (including else) failed 01686 */ 01687 01688 Item *Item_func_case::find_item(String *str) 01689 { 01690 String *first_expr_str, *tmp; 01691 my_decimal *first_expr_dec, first_expr_dec_val; 01692 longlong first_expr_int; 01693 double first_expr_real; 01694 char buff[MAX_FIELD_WIDTH]; 01695 String buff_str(buff,sizeof(buff),default_charset()); 01696 01697 /* These will be initialized later */ 01698 LINT_INIT(first_expr_str); 01699 LINT_INIT(first_expr_int); 01700 LINT_INIT(first_expr_real); 01701 LINT_INIT(first_expr_dec); 01702 01703 if (first_expr_num != -1) 01704 { 01705 switch (cmp_type) 01706 { 01707 case STRING_RESULT: 01708 // We can't use 'str' here as this may be overwritten 01709 if (!(first_expr_str= args[first_expr_num]->val_str(&buff_str))) 01710 return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible 01711 break; 01712 case INT_RESULT: 01713 first_expr_int= args[first_expr_num]->val_int(); 01714 if (args[first_expr_num]->null_value) 01715 return else_expr_num != -1 ? args[else_expr_num] : 0; 01716 break; 01717 case REAL_RESULT: 01718 first_expr_real= args[first_expr_num]->val_real(); 01719 if (args[first_expr_num]->null_value) 01720 return else_expr_num != -1 ? args[else_expr_num] : 0; 01721 break; 01722 case DECIMAL_RESULT: 01723 first_expr_dec= args[first_expr_num]->val_decimal(&first_expr_dec_val); 01724 if (args[first_expr_num]->null_value) 01725 return else_expr_num != -1 ? args[else_expr_num] : 0; 01726 break; 01727 case ROW_RESULT: 01728 default: 01729 // This case should never be chosen 01730 DBUG_ASSERT(0); 01731 break; 01732 } 01733 } 01734 01735 // Compare every WHEN argument with it and return the first match 01736 for (uint i=0 ; i < ncases ; i+=2) 01737 { 01738 if (first_expr_num == -1) 01739 { 01740 // No expression between CASE and the first WHEN 01741 if (args[i]->val_bool()) 01742 return args[i+1]; 01743 continue; 01744 } 01745 switch (cmp_type) { 01746 case STRING_RESULT: 01747 if ((tmp=args[i]->val_str(str))) // If not null 01748 if (sortcmp(tmp,first_expr_str,cmp_collation.collation)==0) 01749 return args[i+1]; 01750 break; 01751 case INT_RESULT: 01752 if (args[i]->val_int()==first_expr_int && !args[i]->null_value) 01753 return args[i+1]; 01754 break; 01755 case REAL_RESULT: 01756 if (args[i]->val_real() == first_expr_real && !args[i]->null_value) 01757 return args[i+1]; 01758 break; 01759 case DECIMAL_RESULT: 01760 { 01761 my_decimal value; 01762 if (my_decimal_cmp(args[i]->val_decimal(&value), first_expr_dec) == 0) 01763 return args[i+1]; 01764 break; 01765 } 01766 case ROW_RESULT: 01767 default: 01768 // This case should never be chosen 01769 DBUG_ASSERT(0); 01770 break; 01771 } 01772 } 01773 // No, WHEN clauses all missed, return ELSE expression 01774 return else_expr_num != -1 ? args[else_expr_num] : 0; 01775 } 01776 01777 01778 String *Item_func_case::val_str(String *str) 01779 { 01780 DBUG_ASSERT(fixed == 1); 01781 String *res; 01782 Item *item=find_item(str); 01783 01784 if (!item) 01785 { 01786 null_value=1; 01787 return 0; 01788 } 01789 null_value= 0; 01790 if (!(res=item->val_str(str))) 01791 null_value= 1; 01792 return res; 01793 } 01794 01795 01796 longlong Item_func_case::val_int() 01797 { 01798 DBUG_ASSERT(fixed == 1); 01799 char buff[MAX_FIELD_WIDTH]; 01800 String dummy_str(buff,sizeof(buff),default_charset()); 01801 Item *item=find_item(&dummy_str); 01802 longlong res; 01803 01804 if (!item) 01805 { 01806 null_value=1; 01807 return 0; 01808 } 01809 res=item->val_int(); 01810 null_value=item->null_value; 01811 return res; 01812 } 01813 01814 double Item_func_case::val_real() 01815 { 01816 DBUG_ASSERT(fixed == 1); 01817 char buff[MAX_FIELD_WIDTH]; 01818 String dummy_str(buff,sizeof(buff),default_charset()); 01819 Item *item=find_item(&dummy_str); 01820 double res; 01821 01822 if (!item) 01823 { 01824 null_value=1; 01825 return 0; 01826 } 01827 res= item->val_real(); 01828 null_value=item->null_value; 01829 return res; 01830 } 01831 01832 01833 my_decimal *Item_func_case::val_decimal(my_decimal *decimal_value) 01834 { 01835 DBUG_ASSERT(fixed == 1); 01836 char buff[MAX_FIELD_WIDTH]; 01837 String dummy_str(buff, sizeof(buff), default_charset()); 01838 Item *item= find_item(&dummy_str); 01839 my_decimal *res; 01840 01841 if (!item) 01842 { 01843 null_value=1; 01844 return 0; 01845 } 01846 01847 res= item->val_decimal(decimal_value); 01848 null_value= item->null_value; 01849 return res; 01850 } 01851 01852 01853 bool Item_func_case::fix_fields(THD *thd, Item **ref) 01854 { 01855 /* 01856 buff should match stack usage from 01857 Item_func_case::val_int() -> Item_func_case::find_item() 01858 */ 01859 char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2]; 01860 bool res= Item_func::fix_fields(thd, ref); 01861 /* 01862 Call check_stack_overrun after fix_fields to be sure that stack variable 01863 is not optimized away 01864 */ 01865 if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) 01866 return TRUE; // Fatal error flag is set! 01867 return res; 01868 } 01869 01870 01871 01872 void Item_func_case::fix_length_and_dec() 01873 { 01874 Item **agg; 01875 uint nagg; 01876 THD *thd= current_thd; 01877 01878 if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) 01879 return; 01880 01881 /* 01882 Aggregate all THEN and ELSE expression types 01883 and collations when string result 01884 */ 01885 01886 for (nagg= 0 ; nagg < ncases/2 ; nagg++) 01887 agg[nagg]= args[nagg*2+1]; 01888 01889 if (else_expr_num != -1) 01890 agg[nagg++]= args[else_expr_num]; 01891 01892 agg_result_type(&cached_result_type, agg, nagg); 01893 if ((cached_result_type == STRING_RESULT) && 01894 agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV, 1)) 01895 return; 01896 01897 01898 /* 01899 Aggregate first expression and all THEN expression types 01900 and collations when string comparison 01901 */ 01902 if (first_expr_num != -1) 01903 { 01904 agg[0]= args[first_expr_num]; 01905 for (nagg= 0; nagg < ncases/2 ; nagg++) 01906 agg[nagg+1]= args[nagg*2]; 01907 nagg++; 01908 agg_cmp_type(thd, &cmp_type, agg, nagg); 01909 if ((cmp_type == STRING_RESULT) && 01910 agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1)) 01911 return; 01912 } 01913 01914 if (else_expr_num == -1 || args[else_expr_num]->maybe_null) 01915 maybe_null=1; 01916 01917 max_length=0; 01918 decimals=0; 01919 for (uint i=0 ; i < ncases ; i+=2) 01920 { 01921 set_if_bigger(max_length,args[i+1]->max_length); 01922 set_if_bigger(decimals,args[i+1]->decimals); 01923 } 01924 if (else_expr_num != -1) 01925 { 01926 set_if_bigger(max_length,args[else_expr_num]->max_length); 01927 set_if_bigger(decimals,args[else_expr_num]->decimals); 01928 } 01929 } 01930 01931 01932 uint Item_func_case::decimal_precision() const 01933 { 01934 int max_int_part=0; 01935 for (uint i=0 ; i < ncases ; i+=2) 01936 set_if_bigger(max_int_part, args[i+1]->decimal_int_part()); 01937 01938 if (else_expr_num != -1) 01939 set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part()); 01940 return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); 01941 } 01942 01943 01944 /* TODO: Fix this so that it prints the whole CASE expression */ 01945 01946 void Item_func_case::print(String *str) 01947 { 01948 str->append(STRING_WITH_LEN("(case ")); 01949 if (first_expr_num != -1) 01950 { 01951 args[first_expr_num]->print(str); 01952 str->append(' '); 01953 } 01954 for (uint i=0 ; i < ncases ; i+=2) 01955 { 01956 str->append(STRING_WITH_LEN("when ")); 01957 args[i]->print(str); 01958 str->append(STRING_WITH_LEN(" then ")); 01959 args[i+1]->print(str); 01960 str->append(' '); 01961 } 01962 if (else_expr_num != -1) 01963 { 01964 str->append(STRING_WITH_LEN("else ")); 01965 args[else_expr_num]->print(str); 01966 str->append(' '); 01967 } 01968 str->append(STRING_WITH_LEN("end)")); 01969 } 01970 01971 /* 01972 Coalesce - return first not NULL argument. 01973 */ 01974 01975 String *Item_func_coalesce::str_op(String *str) 01976 { 01977 DBUG_ASSERT(fixed == 1); 01978 null_value=0; 01979 for (uint i=0 ; i < arg_count ; i++) 01980 { 01981 String *res; 01982 if ((res=args[i]->val_str(str))) 01983 return res; 01984 } 01985 null_value=1; 01986 return 0; 01987 } 01988 01989 longlong Item_func_coalesce::int_op() 01990 { 01991 DBUG_ASSERT(fixed == 1); 01992 null_value=0; 01993 for (uint i=0 ; i < arg_count ; i++) 01994 { 01995 longlong res=args[i]->val_int(); 01996 if (!args[i]->null_value) 01997 return res; 01998 } 01999 null_value=1; 02000 return 0; 02001 } 02002 02003 double Item_func_coalesce::real_op() 02004 { 02005 DBUG_ASSERT(fixed == 1); 02006 null_value=0; 02007 for (uint i=0 ; i < arg_count ; i++) 02008 { 02009 double res= args[i]->val_real(); 02010 if (!args[i]->null_value) 02011 return res; 02012 } 02013 null_value=1; 02014 return 0; 02015 } 02016 02017 02018 my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value) 02019 { 02020 DBUG_ASSERT(fixed == 1); 02021 null_value= 0; 02022 for (uint i= 0; i < arg_count; i++) 02023 { 02024 my_decimal *res= args[i]->val_decimal(decimal_value); 02025 if (!args[i]->null_value) 02026 return res; 02027 } 02028 null_value=1; 02029 return 0; 02030 } 02031 02032 02033 void Item_func_coalesce::fix_length_and_dec() 02034 { 02035 agg_result_type(&hybrid_type, args, arg_count); 02036 switch (hybrid_type) { 02037 case STRING_RESULT: 02038 count_only_length(); 02039 decimals= NOT_FIXED_DEC; 02040 agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1); 02041 break; 02042 case DECIMAL_RESULT: 02043 count_decimal_length(); 02044 break; 02045 case REAL_RESULT: 02046 count_real_length(); 02047 break; 02048 case INT_RESULT: 02049 count_only_length(); 02050 decimals= 0; 02051 break; 02052 case ROW_RESULT: 02053 default: 02054 DBUG_ASSERT(0); 02055 } 02056 } 02057 02058 /**************************************************************************** 02059 Classes and function for the IN operator 02060 ****************************************************************************/ 02061 02062 static int cmp_longlong(void *cmp_arg, longlong *a,longlong *b) 02063 { 02064 return *a < *b ? -1 : *a == *b ? 0 : 1; 02065 } 02066 02067 static int cmp_double(void *cmp_arg, double *a,double *b) 02068 { 02069 return *a < *b ? -1 : *a == *b ? 0 : 1; 02070 } 02071 02072 static int cmp_row(void *cmp_arg, cmp_item_row *a, cmp_item_row *b) 02073 { 02074 return a->compare(b); 02075 } 02076 02077 02078 static int cmp_decimal(void *cmp_arg, my_decimal *a, my_decimal *b) 02079 { 02080 /* 02081 We need call of fixing buffer pointer, because fast sort just copy 02082 decimal buffers in memory and pointers left pointing on old buffer place 02083 */ 02084 a->fix_buffer_pointer(); 02085 b->fix_buffer_pointer(); 02086 return my_decimal_cmp(a, b); 02087 } 02088 02089 02090 int in_vector::find(Item *item) 02091 { 02092 byte *result=get_value(item); 02093 if (!result || !used_count) 02094 return 0; // Null value 02095 02096 uint start,end; 02097 start=0; end=used_count-1; 02098 while (start != end) 02099 { 02100 uint mid=(start+end+1)/2; 02101 int res; 02102 if ((res=(*compare)(collation, base+mid*size, result)) == 0) 02103 return 1; 02104 if (res < 0) 02105 start=mid; 02106 else 02107 end=mid-1; 02108 } 02109 return (int) ((*compare)(collation, base+start*size, result) == 0); 02110 } 02111 02112 in_string::in_string(uint elements,qsort2_cmp cmp_func, CHARSET_INFO *cs) 02113 :in_vector(elements, sizeof(String), cmp_func, cs), 02114 tmp(buff, sizeof(buff), &my_charset_bin) 02115 {} 02116 02117 in_string::~in_string() 02118 { 02119 if (base) 02120 { 02121 // base was allocated with help of sql_alloc => following is OK 02122 for (uint i=0 ; i < count ; i++) 02123 ((String*) base)[i].free(); 02124 } 02125 } 02126 02127 void in_string::set(uint pos,Item *item) 02128 { 02129 String *str=((String*) base)+pos; 02130 String *res=item->val_str(str); 02131 if (res && res != str) 02132 { 02133 if (res->uses_buffer_owned_by(str)) 02134 res->copy(); 02135 *str= *res; 02136 } 02137 if (!str->charset()) 02138 { 02139 CHARSET_INFO *cs; 02140 if (!(cs= item->collation.collation)) 02141 cs= &my_charset_bin; // Should never happen for STR items 02142 str->set_charset(cs); 02143 } 02144 } 02145 02146 02147 byte *in_string::get_value(Item *item) 02148 { 02149 return (byte*) item->val_str(&tmp); 02150 } 02151 02152 in_row::in_row(uint elements, Item * item) 02153 { 02154 base= (char*) new cmp_item_row[count= elements]; 02155 size= sizeof(cmp_item_row); 02156 compare= (qsort2_cmp) cmp_row; 02157 tmp.store_value(item); 02158 /* 02159 We need to reset these as otherwise we will call sort() with 02160 uninitialized (even if not used) elements 02161 */ 02162 used_count= elements; 02163 collation= 0; 02164 } 02165 02166 in_row::~in_row() 02167 { 02168 if (base) 02169 delete [] (cmp_item_row*) base; 02170 } 02171 02172 byte *in_row::get_value(Item *item) 02173 { 02174 tmp.store_value(item); 02175 if (item->is_null()) 02176 return 0; 02177 return (byte *)&tmp; 02178 } 02179 02180 void in_row::set(uint pos, Item *item) 02181 { 02182 DBUG_ENTER("in_row::set"); 02183 DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item)); 02184 ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item); 02185 DBUG_VOID_RETURN; 02186 } 02187 02188 in_longlong::in_longlong(uint elements) 02189 :in_vector(elements,sizeof(longlong),(qsort2_cmp) cmp_longlong, 0) 02190 {} 02191 02192 void in_longlong::set(uint pos,Item *item) 02193 { 02194 ((longlong*) base)[pos]=item->val_int(); 02195 } 02196 02197 byte *in_longlong::get_value(Item *item) 02198 { 02199 tmp= item->val_int(); 02200 if (item->null_value) 02201 return 0; 02202 return (byte*) &tmp; 02203 } 02204 02205 in_double::in_double(uint elements) 02206 :in_vector(elements,sizeof(double),(qsort2_cmp) cmp_double, 0) 02207 {} 02208 02209 void in_double::set(uint pos,Item *item) 02210 { 02211 ((double*) base)[pos]= item->val_real(); 02212 } 02213 02214 byte *in_double::get_value(Item *item) 02215 { 02216 tmp= item->val_real(); 02217 if (item->null_value) 02218 return 0; /* purecov: inspected */ 02219 return (byte*) &tmp; 02220 } 02221 02222 02223 in_decimal::in_decimal(uint elements) 02224 :in_vector(elements, sizeof(my_decimal),(qsort2_cmp) cmp_decimal, 0) 02225 {} 02226 02227 02228 void in_decimal::set(uint pos, Item *item) 02229 { 02230 /* as far as 'item' is constant, we can store reference on my_decimal */ 02231 my_decimal *dec= ((my_decimal *)base) + pos; 02232 dec->len= DECIMAL_BUFF_LENGTH; 02233 dec->fix_buffer_pointer(); 02234 my_decimal *res= item->val_decimal(dec); 02235 if (res != dec) 02236 my_decimal2decimal(res, dec); 02237 } 02238 02239 02240 byte *in_decimal::get_value(Item *item) 02241 { 02242 my_decimal *result= item->val_decimal(&val); 02243 if (item->null_value) 02244 return 0; 02245 return (byte *)result; 02246 } 02247 02248 02249 cmp_item* cmp_item::get_comparator(Item_result type, 02250 CHARSET_INFO *cs) 02251 { 02252 switch (type) { 02253 case STRING_RESULT: 02254 return new cmp_item_sort_string(cs); 02255 case INT_RESULT: 02256 return new cmp_item_int; 02257 case REAL_RESULT: 02258 return new cmp_item_real; 02259 case ROW_RESULT: 02260 return new cmp_item_row; 02261 case DECIMAL_RESULT: 02262 return new cmp_item_decimal; 02263 default: 02264 DBUG_ASSERT(0); 02265 break; 02266 } 02267 return 0; // to satisfy compiler :) 02268 } 02269 02270 02271 cmp_item* cmp_item_sort_string::make_same() 02272 { 02273 return new cmp_item_sort_string_in_static(cmp_charset); 02274 } 02275 02276 cmp_item* cmp_item_int::make_same() 02277 { 02278 return new cmp_item_int(); 02279 } 02280 02281 cmp_item* cmp_item_real::make_same() 02282 { 02283 return new cmp_item_real(); 02284 } 02285 02286 cmp_item* cmp_item_row::make_same() 02287 { 02288 return new cmp_item_row(); 02289 } 02290 02291 02292 cmp_item_row::~cmp_item_row() 02293 { 02294 DBUG_ENTER("~cmp_item_row"); 02295 DBUG_PRINT("enter",("this: 0x%lx", this)); 02296 if (comparators) 02297 { 02298 for (uint i= 0; i < n; i++) 02299 { 02300 if (comparators[i]) 02301 delete comparators[i]; 02302 } 02303 } 02304 DBUG_VOID_RETURN; 02305 } 02306 02307 02308 void cmp_item_row::store_value(Item *item) 02309 { 02310 DBUG_ENTER("cmp_item_row::store_value"); 02311 n= item->cols(); 02312 if (!comparators) 02313 comparators= (cmp_item **) current_thd->calloc(sizeof(cmp_item *)*n); 02314 if (comparators) 02315 { 02316 item->bring_value(); 02317 item->null_value= 0; 02318 for (uint i=0; i < n; i++) 02319 { 02320 if (!comparators[i]) 02321 if (!(comparators[i]= 02322 cmp_item::get_comparator(item->el(i)->result_type(), 02323 item->el(i)->collation.collation))) 02324 break; // new failed 02325 comparators[i]->store_value(item->el(i)); 02326 item->null_value|= item->el(i)->null_value; 02327 } 02328 } 02329 DBUG_VOID_RETURN; 02330 } 02331 02332 02333 void cmp_item_row::store_value_by_template(cmp_item *t, Item *item) 02334 { 02335 cmp_item_row *tmpl= (cmp_item_row*) t; 02336 if (tmpl->n != item->cols()) 02337 { 02338 my_error(ER_OPERAND_COLUMNS, MYF(0), tmpl->n); 02339 return; 02340 } 02341 n= tmpl->n; 02342 if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n))) 02343 { 02344 item->bring_value(); 02345 item->null_value= 0; 02346 for (uint i=0; i < n; i++) 02347 { 02348 if (!(comparators[i]= tmpl->comparators[i]->make_same())) 02349 break; // new failed 02350 comparators[i]->store_value_by_template(tmpl->comparators[i], 02351 item->el(i)); 02352 item->null_value|= item->el(i)->null_value; 02353 } 02354 } 02355 } 02356 02357 02358 int cmp_item_row::cmp(Item *arg) 02359 { 02360 arg->null_value= 0; 02361 if (arg->cols() != n) 02362 { 02363 my_error(ER_OPERAND_COLUMNS, MYF(0), n); 02364 return 1; 02365 } 02366 bool was_null= 0; 02367 arg->bring_value(); 02368 for (uint i=0; i < n; i++) 02369 { 02370 if (comparators[i]->cmp(arg->el(i))) 02371 { 02372 if (!arg->el(i)->null_value) 02373 return 1; 02374 was_null= 1; 02375 } 02376 } 02377 return (arg->null_value= was_null); 02378 } 02379 02380 02381 int cmp_item_row::compare(cmp_item *c) 02382 { 02383 cmp_item_row *cmp= (cmp_item_row *) c; 02384 for (uint i=0; i < n; i++) 02385 { 02386 int res; 02387 if ((res= comparators[i]->compare(cmp->comparators[i]))) 02388 return res; 02389 } 02390 return 0; 02391 } 02392 02393 02394 void cmp_item_decimal::store_value(Item *item) 02395 { 02396 my_decimal *val= item->val_decimal(&value); 02397 /* val may be zero if item is nnull */ 02398 if (val && val != &value) 02399 my_decimal2decimal(val, &value); 02400 } 02401 02402 02403 int cmp_item_decimal::cmp(Item *arg) 02404 { 02405 my_decimal tmp_buf, *tmp= arg->val_decimal(&tmp_buf); 02406 if (arg->null_value) 02407 return 1; 02408 return my_decimal_cmp(&value, tmp); 02409 } 02410 02411 02412 int cmp_item_decimal::compare(cmp_item *arg) 02413 { 02414 cmp_item_decimal *cmp= (cmp_item_decimal*) arg; 02415 return my_decimal_cmp(&value, &cmp->value); 02416 } 02417 02418 02419 cmp_item* cmp_item_decimal::make_same() 02420 { 02421 return new cmp_item_decimal(); 02422 } 02423 02424 02425 bool Item_func_in::nulls_in_row() 02426 { 02427 Item **arg,**arg_end; 02428 for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++) 02429 { 02430 if ((*arg)->null_inside()) 02431 return 1; 02432 } 02433 return 0; 02434 } 02435 02436 02437 /* 02438 Perform context analysis of an IN item tree 02439 02440 SYNOPSIS: 02441 fix_fields() 02442 thd reference to the global context of the query thread 02443 tables list of all open tables involved in the query 02444 ref pointer to Item* variable where pointer to resulting "fixed" 02445 item is to be assigned 02446 02447 DESCRIPTION 02448 This function performs context analysis (name resolution) and calculates 02449 various attributes of the item tree with Item_func_in as its root. 02450 The function saves in ref the pointer to the item or to a newly created 02451 item that is considered as a replacement for the original one. 02452 02453 NOTES 02454 Let T0(e)/T1(e) be the value of not_null_tables(e) when e is used on 02455 a predicate/function level. Then it's easy to show that: 02456 T0(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) 02457 T1(e IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) 02458 T0(e NOT IN(e1,...,en)) = union(T1(e),union(T1(ei))) 02459 T1(e NOT IN(e1,...,en)) = union(T1(e),intersection(T1(ei))) 02460 02461 RETURN 02462 0 ok 02463 1 got error 02464 */ 02465 02466 bool 02467 Item_func_in::fix_fields(THD *thd, Item **ref) 02468 { 02469 Item **arg, **arg_end; 02470 02471 if (Item_func_opt_neg::fix_fields(thd, ref)) 02472 return 1; 02473 02474 /* not_null_tables_cache == union(T1(e),union(T1(ei))) */ 02475 if (pred_level && negated) 02476 return 0; 02477 02478 /* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */ 02479 not_null_tables_cache= ~(table_map) 0; 02480 for (arg= args + 1, arg_end= args + arg_count; arg != arg_end; arg++) 02481 not_null_tables_cache&= (*arg)->not_null_tables(); 02482 not_null_tables_cache|= (*args)->not_null_tables(); 02483 return 0; 02484 } 02485 02486 02487 static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y) 02488 { 02489 return cs->coll->strnncollsp(cs, 02490 (uchar *) x->ptr(),x->length(), 02491 (uchar *) y->ptr(),y->length(), 0); 02492 } 02493 02494 02495 void Item_func_in::fix_length_and_dec() 02496 { 02497 Item **arg, **arg_end; 02498 uint const_itm= 1; 02499 THD *thd= current_thd; 02500 02501 agg_cmp_type(thd, &cmp_type, args, arg_count); 02502 02503 if (cmp_type == STRING_RESULT && 02504 agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV, 1)) 02505 return; 02506 02507 for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++) 02508 { 02509 if (!arg[0]->const_item()) 02510 { 02511 const_itm= 0; 02512 break; 02513 } 02514 } 02515 02516 /* 02517 Row item with NULLs inside can return NULL or FALSE => 02518 they can't be processed as static 02519 */ 02520 if (const_itm && !nulls_in_row()) 02521 { 02522 switch (cmp_type) { 02523 case STRING_RESULT: 02524 array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in, 02525 cmp_collation.collation); 02526 break; 02527 case INT_RESULT: 02528 array= new in_longlong(arg_count-1); 02529 break; 02530 case REAL_RESULT: 02531 array= new in_double(arg_count-1); 02532 break; 02533 case ROW_RESULT: 02534 array= new in_row(arg_count-1, args[0]); 02535 break; 02536 case DECIMAL_RESULT: 02537 array= new in_decimal(arg_count - 1); 02538 break; 02539 default: 02540 DBUG_ASSERT(0); 02541 return; 02542 } 02543 if (array && !(thd->is_fatal_error)) // If not EOM 02544 { 02545 uint j=0; 02546 for (uint i=1 ; i < arg_count ; i++) 02547 { 02548 array->set(j,args[i]); 02549 if (!args[i]->null_value) // Skip NULL values 02550 j++; 02551 else 02552 have_null= 1; 02553 } 02554 if ((array->used_count=j)) 02555 array->sort(); 02556 } 02557 } 02558 else 02559 { 02560 in_item= cmp_item::get_comparator(cmp_type, cmp_collation.collation); 02561 if (cmp_type == STRING_RESULT) 02562 in_item->cmp_charset= cmp_collation.collation; 02563 } 02564 maybe_null= args[0]->maybe_null; 02565 max_length= 1; 02566 } 02567 02568 02569 void Item_func_in::print(String *str) 02570 { 02571 str->append('('); 02572 args[0]->print(str); 02573 if (negated) 02574 str->append(STRING_WITH_LEN(" not")); 02575 str->append(STRING_WITH_LEN(" in (")); 02576 print_args(str, 1); 02577 str->append(STRING_WITH_LEN("))")); 02578 } 02579 02580 02581 longlong Item_func_in::val_int() 02582 { 02583 DBUG_ASSERT(fixed == 1); 02584 if (array) 02585 { 02586 int tmp=array->find(args[0]); 02587 null_value=args[0]->null_value || (!tmp && have_null); 02588 return (longlong) (!null_value && tmp != negated); 02589 } 02590 in_item->store_value(args[0]); 02591 if ((null_value=args[0]->null_value)) 02592 return 0; 02593 have_null= 0; 02594 for (uint i=1 ; i < arg_count ; i++) 02595 { 02596 if (!in_item->cmp(args[i]) && !args[i]->null_value) 02597 return (longlong) (!negated); 02598 have_null|= args[i]->null_value; 02599 } 02600 null_value= have_null; 02601 return (longlong) (!null_value && negated); 02602 } 02603 02604 02605 longlong Item_func_bit_or::val_int() 02606 { 02607 DBUG_ASSERT(fixed == 1); 02608 ulonglong arg1= (ulonglong) args[0]->val_int(); 02609 if (args[0]->null_value) 02610 { 02611 null_value=1; /* purecov: inspected */ 02612 return 0; /* purecov: inspected */ 02613 } 02614 ulonglong arg2= (ulonglong) args[1]->val_int(); 02615 if (args[1]->null_value) 02616 { 02617 null_value=1; 02618 return 0; 02619 } 02620 null_value=0; 02621 return (longlong) (arg1 | arg2); 02622 } 02623 02624 02625 longlong Item_func_bit_and::val_int() 02626 { 02627 DBUG_ASSERT(fixed == 1); 02628 ulonglong arg1= (ulonglong) args[0]->val_int(); 02629 if (args[0]->null_value) 02630 { 02631 null_value=1; /* purecov: inspected */ 02632 return 0; /* purecov: inspected */ 02633 } 02634 ulonglong arg2= (ulonglong) args[1]->val_int(); 02635 if (args[1]->null_value) 02636 { 02637 null_value=1; /* purecov: inspected */ 02638 return 0; /* purecov: inspected */ 02639 } 02640 null_value=0; 02641 return (longlong) (arg1 & arg2); 02642 } 02643 02644 Item_cond::Item_cond(THD *thd, Item_cond *item) 02645 :Item_bool_func(thd, item), 02646 abort_on_null(item->abort_on_null), 02647 and_tables_cache(item->and_tables_cache) 02648 { 02649 /* 02650 item->list will be copied by copy_andor_arguments() call 02651 */ 02652 } 02653 02654 02655 void Item_cond::copy_andor_arguments(THD *thd, Item_cond *item) 02656 { 02657 List_iterator_fast<Item> li(item->list); 02658 while (Item *it= li++) 02659 list.push_back(it->copy_andor_structure(thd)); 02660 } 02661 02662 02663 bool 02664 Item_cond::fix_fields(THD *thd, Item **ref) 02665 { 02666 DBUG_ASSERT(fixed == 0); 02667 List_iterator<Item> li(list); 02668 Item *item; 02669 #ifndef EMBEDDED_LIBRARY 02670 char buff[sizeof(char*)]; // Max local vars in function 02671 #endif 02672 not_null_tables_cache= used_tables_cache= 0; 02673 const_item_cache= 1; 02674 /* 02675 and_table_cache is the value that Item_cond_or() returns for 02676 not_null_tables() 02677 */ 02678 and_tables_cache= ~(table_map) 0; 02679 02680 if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) 02681 return TRUE; // Fatal error flag is set! 02682 /* 02683 The following optimization reduces the depth of an AND-OR tree. 02684 E.g. a WHERE clause like 02685 F1 AND (F2 AND (F2 AND F4)) 02686 is parsed into a tree with the same nested structure as defined 02687 by braces. This optimization will transform such tree into 02688 AND (F1, F2, F3, F4). 02689 Trees of OR items are flattened as well: 02690 ((F1 OR F2) OR (F3 OR F4)) => OR (F1, F2, F3, F4) 02691 Items for removed AND/OR levels will dangle until the death of the 02692 entire statement. 02693 The optimization is currently prepared statements and stored procedures 02694 friendly as it doesn't allocate any memory and its effects are durable 02695 (i.e. do not depend on PS/SP arguments). 02696 */ 02697 while ((item=li++)) 02698 { 02699 table_map tmp_table_map; 02700 while (item->type() == Item::COND_ITEM && 02701 ((Item_cond*) item)->functype() == functype() && 02702 !((Item_cond*) item)->list.is_empty()) 02703 { // Identical function 02704 li.replace(((Item_cond*) item)->list); 02705 ((Item_cond*) item)->list.empty(); 02706 item= *li.ref(); // new current item 02707 } 02708 if (abort_on_null) 02709 item->top_level_item(); 02710 02711 // item can be substituted in fix_fields 02712 if ((!item->fixed && 02713 item->fix_fields(thd, li.ref())) || 02714 (item= *li.ref())->check_cols(1)) 02715 return TRUE; /* purecov: inspected */ 02716 used_tables_cache|= item->used_tables(); 02717 if (item->const_item()) 02718 and_tables_cache= (table_map) 0; 02719 else 02720 { 02721 tmp_table_map= item->not_null_tables(); 02722 not_null_tables_cache|= tmp_table_map; 02723 and_tables_cache&= tmp_table_map; 02724 const_item_cache= FALSE; 02725 } 02726 with_sum_func= with_sum_func || item->with_sum_func; 02727 with_subselect|= item->with_subselect; 02728 if (item->maybe_null) 02729 maybe_null=1; 02730 } 02731 thd->lex->current_select->cond_count+= list.elements; 02732 fix_length_and_dec(); 02733 fixed= 1; 02734 return FALSE; 02735 } 02736 02737 bool Item_cond::walk(Item_processor processor, bool walk_subquery, byte *arg) 02738 { 02739 List_iterator_fast<Item> li(list); 02740 Item *item; 02741 while ((item= li++)) 02742 if (item->walk(processor, walk_subquery, arg)) 02743 return 1; 02744 return Item_func::walk(processor, walk_subquery, arg); 02745 } 02746 02747 02748 /* 02749 Transform an Item_cond object with a transformer callback function 02750 02751 SYNOPSIS 02752 transform() 02753 transformer the transformer callback function to be applied to the nodes 02754 of the tree of the object 02755 arg parameter to be passed to the transformer 02756 02757 DESCRIPTION 02758 The function recursively applies the transform method with the 02759 same transformer to each member item of the condition list. 02760 If the call of the method for a member item returns a new item 02761 the old item is substituted for a new one. 02762 After this the transform method is applied to the root node 02763 of the Item_cond object. 02764 02765 RETURN VALUES 02766 Item returned as the result of transformation of the root node 02767 */ 02768 02769 Item *Item_cond::transform(Item_transformer transformer, byte *arg) 02770 { 02771 List_iterator<Item> li(list); 02772 Item *item; 02773 while ((item= li++)) 02774 { 02775 Item *new_item= item->transform(transformer, arg); 02776 if (!new_item) 02777 return 0; 02778 if (new_item != item) 02779 li.replace(new_item); 02780 } 02781 return Item_func::transform(transformer, arg); 02782 } 02783 02784 void Item_cond::traverse_cond(Cond_traverser traverser, 02785 void *arg, traverse_order order) 02786 { 02787 List_iterator<Item> li(list); 02788 Item *item; 02789 02790 switch(order) { 02791 case(PREFIX): 02792 (*traverser)(this, arg); 02793 while ((item= li++)) 02794 { 02795 item->traverse_cond(traverser, arg, order); 02796 } 02797 (*traverser)(NULL, arg); 02798 break; 02799 case(POSTFIX): 02800 while ((item= li++)) 02801 { 02802 item->traverse_cond(traverser, arg, order); 02803 } 02804 (*traverser)(this, arg); 02805 } 02806 } 02807 02808 /* 02809 Move SUM items out from item tree and replace with reference 02810 02811 SYNOPSIS 02812 split_sum_func() 02813 thd Thread handler 02814 ref_pointer_array Pointer to array of reference fields 02815 fields All fields in select 02816 02817 NOTES 02818 This function is run on all expression (SELECT list, WHERE, HAVING etc) 02819 that have or refer (HAVING) to a SUM expression. 02820 02821 The split is done to get an unique item for each SUM function 02822 so that we can easily find and calculate them. 02823 (Calculation done by update_sum_func() and copy_sum_funcs() in 02824 sql_select.cc) 02825 */ 02826 02827 void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, 02828 List<Item> &fields) 02829 { 02830 List_iterator<Item> li(list); 02831 Item *item; 02832 while ((item= li++)) 02833 item->split_sum_func2(thd, ref_pointer_array, fields, li.ref(), TRUE); 02834 } 02835 02836 02837 table_map 02838 Item_cond::used_tables() const 02839 { // This caches used_tables 02840 return used_tables_cache; 02841 } 02842 02843 02844 void Item_cond::update_used_tables() 02845 { 02846 List_iterator_fast<Item> li(list); 02847 Item *item; 02848 02849 used_tables_cache=0; 02850 const_item_cache=1; 02851 while ((item=li++)) 02852 { 02853 item->update_used_tables(); 02854 used_tables_cache|= item->used_tables(); 02855 const_item_cache&= item->const_item(); 02856 } 02857 } 02858 02859 02860 void Item_cond::print(String *str) 02861 { 02862 str->append('('); 02863 List_iterator_fast<Item> li(list); 02864 Item *item; 02865 if ((item=li++)) 02866 item->print(str); 02867 while ((item=li++)) 02868 { 02869 str->append(' '); 02870 str->append(func_name()); 02871 str->append(' '); 02872 item->print(str); 02873 } 02874 str->append(')'); 02875 } 02876 02877 02878 void Item_cond::neg_arguments(THD *thd) 02879 { 02880 List_iterator<Item> li(list); 02881 Item *item; 02882 while ((item= li++)) /* Apply not transformation to the arguments */ 02883 { 02884 Item *new_item= item->neg_transformer(thd); 02885 if (!new_item) 02886 { 02887 if (!(new_item= new Item_func_not(item))) 02888 return; // Fatal OEM error 02889 } 02890 VOID(li.replace(new_item)); 02891 } 02892 } 02893 02894 02895 /* 02896 Evaluation of AND(expr, expr, expr ...) 02897 02898 NOTES: 02899 abort_if_null is set for AND expressions for which we don't care if the 02900 result is NULL or 0. This is set for: 02901 - WHERE clause 02902 - HAVING clause 02903 - IF(expression) 02904 02905 RETURN VALUES 02906 1 If all expressions are true 02907 0 If all expressions are false or if we find a NULL expression and 02908 'abort_on_null' is set. 02909 NULL if all expression are either 1 or NULL 02910 */ 02911 02912 02913 longlong Item_cond_and::val_int() 02914 { 02915 DBUG_ASSERT(fixed == 1); 02916 List_iterator_fast<Item> li(list); 02917 Item *item; 02918 null_value= 0; 02919 while ((item=li++)) 02920 { 02921 if (!item->val_bool()) 02922 { 02923 if (abort_on_null || !(null_value= item->null_value)) 02924 return 0; // return FALSE 02925 } 02926 } 02927 return null_value ? 0 : 1; 02928 } 02929 02930 02931 longlong Item_cond_or::val_int() 02932 { 02933 DBUG_ASSERT(fixed == 1); 02934 List_iterator_fast<Item> li(list); 02935 Item *item; 02936 null_value=0; 02937 while ((item=li++)) 02938 { 02939 if (item->val_bool()) 02940 { 02941 null_value=0; 02942 return 1; 02943 } 02944 if (item->null_value) 02945 null_value=1; 02946 } 02947 return 0; 02948 } 02949 02950 /* 02951 Create an AND expression from two expressions 02952 02953 SYNOPSIS 02954 and_expressions() 02955 a expression or NULL 02956 b expression. 02957 org_item Don't modify a if a == *org_item 02958 If a == NULL, org_item is set to point at b, 02959 to ensure that future calls will not modify b. 02960 02961 NOTES 02962 This will not modify item pointed to by org_item or b 02963 The idea is that one can call this in a loop and create and 02964 'and' over all items without modifying any of the original items. 02965 02966 RETURN 02967 NULL Error 02968 Item 02969 */ 02970 02971 Item *and_expressions(Item *a, Item *b, Item **org_item) 02972 { 02973 if (!a) 02974 return (*org_item= (Item*) b); 02975 if (a == *org_item) 02976 { 02977 Item_cond *res; 02978 if ((res= new Item_cond_and(a, (Item*) b))) 02979 { 02980 res->used_tables_cache= a->used_tables() | b->used_tables(); 02981 res->not_null_tables_cache= a->not_null_tables() | b->not_null_tables(); 02982 } 02983 return res; 02984 } 02985 if (((Item_cond_and*) a)->add((Item*) b)) 02986 return 0; 02987 ((Item_cond_and*) a)->used_tables_cache|= b->used_tables(); 02988 ((Item_cond_and*) a)->not_null_tables_cache|= b->not_null_tables(); 02989 return a; 02990 } 02991 02992 02993 longlong Item_func_isnull::val_int() 02994 { 02995 DBUG_ASSERT(fixed == 1); 02996 /* 02997 Handle optimization if the argument can't be null 02998 This has to be here because of the test in update_used_tables(). 02999 */ 03000 if (!used_tables_cache) 03001 return cached_value; 03002 return args[0]->is_null() ? 1: 0; 03003 } 03004 03005 longlong Item_is_not_null_test::val_int() 03006 { 03007 DBUG_ASSERT(fixed == 1); 03008 DBUG_ENTER("Item_is_not_null_test::val_int"); 03009 if (!used_tables_cache) 03010 { 03011 owner->was_null|= (!cached_value); 03012 DBUG_PRINT("info", ("cached :%d", cached_value)); 03013 DBUG_RETURN(cached_value); 03014 } 03015 if (args[0]->is_null()) 03016 { 03017 DBUG_PRINT("info", ("null")); 03018 owner->was_null|= 1; 03019 DBUG_RETURN(0); 03020 } 03021 else 03022 DBUG_RETURN(1); 03023 } 03024 03025 /* Optimize case of not_null_column IS NULL */ 03026 void Item_is_not_null_test::update_used_tables() 03027 { 03028 if (!args[0]->maybe_null) 03029 { 03030 used_tables_cache= 0; /* is always true */ 03031 cached_value= (longlong) 1; 03032 } 03033 else 03034 { 03035 args[0]->update_used_tables(); 03036 if (!(used_tables_cache=args[0]->used_tables())) 03037 { 03038 /* Remember if the value is always NULL or never NULL */ 03039 cached_value= (longlong) !args[0]->is_null(); 03040 } 03041 } 03042 } 03043 03044 03045 longlong Item_func_isnotnull::val_int() 03046 { 03047 DBUG_ASSERT(fixed == 1); 03048 return args[0]->is_null() ? 0 : 1; 03049 } 03050 03051 03052 void Item_func_isnotnull::print(String *str) 03053 { 03054 str->append('('); 03055 args[0]->print(str); 03056 str->append(STRING_WITH_LEN(" is not null)")); 03057 } 03058 03059 03060 longlong Item_func_like::val_int() 03061 { 03062 DBUG_ASSERT(fixed == 1); 03063 String* res = args[0]->val_str(&tmp_value1); 03064 if (args[0]->null_value) 03065 { 03066 null_value=1; 03067 return 0; 03068 } 03069 String* res2 = args[1]->val_str(&tmp_value2); 03070 if (args[1]->null_value) 03071 { 03072 null_value=1; 03073 return 0; 03074 } 03075 null_value=0; 03076 if (canDoTurboBM) 03077 return turboBM_matches(res->ptr(), res->length()) ? 1 : 0; 03078 return my_wildcmp(cmp.cmp_collation.collation, 03079 res->ptr(),res->ptr()+res->length(), 03080 res2->ptr(),res2->ptr()+res2->length(), 03081 escape,wild_one,wild_many) ? 0 : 1; 03082 } 03083 03084 03085 /* We can optimize a where if first character isn't a wildcard */ 03086 03087 Item_func::optimize_type Item_func_like::select_optimize() const 03088 { 03089 if (args[1]->const_item()) 03090 { 03091 String* res2= args[1]->val_str((String *)&tmp_value2); 03092 03093 if (!res2) 03094 return OPTIMIZE_NONE; 03095 03096 if (*res2->ptr() != wild_many) 03097 { 03098 if (args[0]->result_type() != STRING_RESULT || *res2->ptr() != wild_one) 03099 return OPTIMIZE_OP; 03100 } 03101 } 03102 return OPTIMIZE_NONE; 03103 } 03104 03105 03106 bool Item_func_like::fix_fields(THD *thd, Item **ref) 03107 { 03108 DBUG_ASSERT(fixed == 0); 03109 if (Item_bool_func2::fix_fields(thd, ref) || 03110 escape_item->fix_fields(thd, &escape_item)) 03111 return TRUE; 03112 03113 if (!escape_item->const_during_execution()) 03114 { 03115 my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE"); 03116 return TRUE; 03117 } 03118 03119 if (escape_item->const_item()) 03120 { 03121 /* If we are on execution stage */ 03122 String *escape_str= escape_item->val_str(&tmp_value1); 03123 if (escape_str) 03124 { 03125 if (escape_used_in_parsing && ( 03126 (((thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) && 03127 escape_str->numchars() != 1) || 03128 escape_str->numchars() > 1))) 03129 { 03130 my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE"); 03131 return TRUE; 03132 } 03133 03134 if (use_mb(cmp.cmp_collation.collation)) 03135 { 03136 CHARSET_INFO *cs= escape_str->charset(); 03137 my_wc_t wc; 03138 int rc= cs->cset->mb_wc(cs, &wc, 03139 (const uchar*) escape_str->ptr(), 03140 (const uchar*) escape_str->ptr() + 03141 escape_str->length()); 03142 escape= (int) (rc > 0 ? wc : '\\'); 03143 } 03144 else 03145 { 03146 /* 03147 In the case of 8bit character set, we pass native 03148 code instead of Unicode code as "escape" argument. 03149 Convert to "cs" if charset of escape differs. 03150 */ 03151 CHARSET_INFO *cs= cmp.cmp_collation.collation; 03152 uint32 unused; 03153 if (escape_str->needs_conversion(escape_str->length(), 03154 escape_str->charset(), cs, &unused)) 03155 { 03156 char ch; 03157 uint errors; 03158 uint32 cnvlen= copy_and_convert(&ch, 1, cs, escape_str->ptr(), 03159 escape_str->length(), 03160 escape_str->charset(), &errors); 03161 escape= cnvlen ? ch : '\\'; 03162 } 03163 else 03164 escape= *(escape_str->ptr()); 03165 } 03166 } 03167 else 03168 escape= '\\'; 03169 03170 /* 03171 We could also do boyer-more for non-const items, but as we would have to 03172 recompute the tables for each row it's not worth it. 03173 */ 03174 if (args[1]->const_item() && !use_strnxfrm(collation.collation) && 03175 !(specialflag & SPECIAL_NO_NEW_FUNC)) 03176 { 03177 String* res2 = args[1]->val_str(&tmp_value2); 03178 if (!res2) 03179 return FALSE; // Null argument 03180 03181 const size_t len = res2->length(); 03182 const char* first = res2->ptr(); 03183 const char* last = first + len - 1; 03184 /* 03185 len must be > 2 ('%pattern%') 03186 heuristic: only do TurboBM for pattern_len > 2 03187 */ 03188 03189 if (len > MIN_TURBOBM_PATTERN_LEN + 2 && 03190 *first == wild_many && 03191 *last == wild_many) 03192 { 03193 const char* tmp = first + 1; 03194 for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ; 03195 canDoTurboBM = (tmp == last) && !use_mb(args[0]->collation.collation); 03196 } 03197 if (canDoTurboBM) 03198 { 03199 pattern = first + 1; 03200 pattern_len = (int) len - 2; 03201 DBUG_PRINT("info", ("Initializing pattern: '%s'", first)); 03202 int *suff = (int*) thd->alloc((int) (sizeof(int)* 03203 ((pattern_len + 1)*2+ 03204 alphabet_size))); 03205 bmGs = suff + pattern_len + 1; 03206 bmBc = bmGs + pattern_len + 1; 03207 turboBM_compute_good_suffix_shifts(suff); 03208 turboBM_compute_bad_character_shifts(); 03209 DBUG_PRINT("info",("done")); 03210 } 03211 } 03212 } 03213 return FALSE; 03214 } 03215 03216 void Item_func_like::cleanup() 03217 { 03218 canDoTurboBM= FALSE; 03219 Item_bool_func2::cleanup(); 03220 } 03221 03222 #ifdef USE_REGEX 03223 03224 bool 03225 Item_func_regex::fix_fields(THD *thd, Item **ref) 03226 { 03227 DBUG_ASSERT(fixed == 0); 03228 if ((!args[0]->fixed && 03229 args[0]->fix_fields(thd, args)) || args[0]->check_cols(1) || 03230 (!args[1]->fixed && 03231 args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1)) 03232 return TRUE; /* purecov: inspected */ 03233 with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; 03234 max_length= 1; 03235 decimals= 0; 03236 03237 if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV, 1)) 03238 return TRUE; 03239 03240 used_tables_cache=args[0]->used_tables() | args[1]->used_tables(); 03241 not_null_tables_cache= (args[0]->not_null_tables() | 03242 args[1]->not_null_tables()); 03243 const_item_cache=args[0]->const_item() && args[1]->const_item(); 03244 if (!regex_compiled && args[1]->const_item()) 03245 { 03246 char buff[MAX_FIELD_WIDTH]; 03247 String tmp(buff,sizeof(buff),&my_charset_bin); 03248 String *res=args[1]->val_str(&tmp); 03249 if (args[1]->null_value) 03250 { // Will always return NULL 03251 maybe_null=1; 03252 return FALSE; 03253 } 03254 int error; 03255 if ((error= my_regcomp(&preg,res->c_ptr(), 03256 ((cmp_collation.collation->state & 03257 (MY_CS_BINSORT | MY_CS_CSSORT)) ? 03258 REG_EXTENDED | REG_NOSUB : 03259 REG_EXTENDED | REG_NOSUB | REG_ICASE), 03260 cmp_collation.collation))) 03261 { 03262 (void) my_regerror(error,&preg,buff,sizeof(buff)); 03263 my_error(ER_REGEXP_ERROR, MYF(0), buff); 03264 return TRUE; 03265 } 03266 regex_compiled=regex_is_const=1; 03267 maybe_null=args[0]->maybe_null; 03268 } 03269 else 03270 maybe_null=1; 03271 fixed= 1; 03272 return FALSE; 03273 } 03274 03275 03276 longlong Item_func_regex::val_int() 03277 { 03278 DBUG_ASSERT(fixed == 1); 03279 char buff[MAX_FIELD_WIDTH]; 03280 String *res, tmp(buff,sizeof(buff),&my_charset_bin); 03281 03282 res=args[0]->val_str(&tmp); 03283 if (args[0]->null_value) 03284 { 03285 null_value=1; 03286 return 0; 03287 } 03288 if (!regex_is_const) 03289 { 03290 char buff2[MAX_FIELD_WIDTH]; 03291 String *res2, tmp2(buff2,sizeof(buff2),&my_charset_bin); 03292 03293 res2= args[1]->val_str(&tmp2); 03294 if (args[1]->null_value) 03295 { 03296 null_value=1; 03297 return 0; 03298 } 03299 if (!regex_compiled || stringcmp(res2,&prev_regexp)) 03300 { 03301 prev_regexp.copy(*res2); 03302 if (regex_compiled) 03303 { 03304 my_regfree(&preg); 03305 regex_compiled=0; 03306 } 03307 if (my_regcomp(&preg,res2->c_ptr_safe(), 03308 ((cmp_collation.collation->state & 03309 (MY_CS_BINSORT | MY_CS_CSSORT)) ? 03310 REG_EXTENDED | REG_NOSUB : 03311 REG_EXTENDED | REG_NOSUB | REG_ICASE), 03312 cmp_collation.collation)) 03313 { 03314 null_value=1; 03315 return 0; 03316 } 03317 regex_compiled=1; 03318 } 03319 } 03320 null_value=0; 03321 return my_regexec(&preg,res->c_ptr_safe(),0,(my_regmatch_t*) 0,0) ? 0 : 1; 03322 } 03323 03324 03325 void Item_func_regex::cleanup() 03326 { 03327 DBUG_ENTER("Item_func_regex::cleanup"); 03328 Item_bool_func::cleanup(); 03329 if (regex_compiled) 03330 { 03331 my_regfree(&preg); 03332 regex_compiled=0; 03333 } 03334 DBUG_VOID_RETURN; 03335 } 03336 03337 03338 #endif /* USE_REGEX */ 03339 03340 03341 #ifdef LIKE_CMP_TOUPPER 03342 #define likeconv(cs,A) (uchar) (cs)->toupper(A) 03343 #else 03344 #define likeconv(cs,A) (uchar) (cs)->sort_order[(uchar) (A)] 03345 #endif 03346 03347 03348 /********************************************************************** 03349 turboBM_compute_suffixes() 03350 Precomputation dependent only on pattern_len. 03351 **********************************************************************/ 03352 03353 void Item_func_like::turboBM_compute_suffixes(int *suff) 03354 { 03355 const int plm1 = pattern_len - 1; 03356 int f = 0; 03357 int g = plm1; 03358 int *const splm1 = suff + plm1; 03359 CHARSET_INFO *cs= cmp.cmp_collation.collation; 03360 03361 *splm1 = pattern_len; 03362 03363 if (!cs->sort_order) 03364 { 03365 int i; 03366 for (i = pattern_len - 2; i >= 0; i--) 03367 { 03368 int tmp = *(splm1 + i - f); 03369 if (g < i && tmp < i - g) 03370 suff[i] = tmp; 03371 else 03372 { 03373 if (i < g) 03374 g = i; // g = min(i, g) 03375 f = i; 03376 while (g >= 0 && pattern[g] == pattern[g + plm1 - f]) 03377 g--; 03378 suff[i] = f - g; 03379 } 03380 } 03381 } 03382 else 03383 { 03384 int i; 03385 for (i = pattern_len - 2; 0 <= i; --i) 03386 { 03387 int tmp = *(splm1 + i - f); 03388 if (g < i && tmp < i - g) 03389 suff[i] = tmp; 03390 else 03391 { 03392 if (i < g) 03393 g = i; // g = min(i, g) 03394 f = i; 03395 while (g >= 0 && 03396 likeconv(cs, pattern[g]) == likeconv(cs, pattern[g + plm1 - f])) 03397 g--; 03398 suff[i] = f - g; 03399 } 03400 } 03401 } 03402 } 03403 03404 03405 /********************************************************************** 03406 turboBM_compute_good_suffix_shifts() 03407 Precomputation dependent only on pattern_len. 03408 **********************************************************************/ 03409 03410 void Item_func_like::turboBM_compute_good_suffix_shifts(int *suff) 03411 { 03412 turboBM_compute_suffixes(suff); 03413 03414 int *end = bmGs + pattern_len; 03415 int *k; 03416 for (k = bmGs; k < end; k++) 03417 *k = pattern_len; 03418 03419 int tmp; 03420 int i; 03421 int j = 0; 03422 const int plm1 = pattern_len - 1; 03423 for (i = plm1; i > -1; i--) 03424 { 03425 if (suff[i] == i + 1) 03426 { 03427 for (tmp = plm1 - i; j < tmp; j++) 03428 { 03429 int *tmp2 = bmGs + j; 03430 if (*tmp2 == pattern_len) 03431 *tmp2 = tmp; 03432 } 03433 } 03434 } 03435 03436 int *tmp2; 03437 for (tmp = plm1 - i; j < tmp; j++) 03438 { 03439 tmp2 = bmGs + j; 03440 if (*tmp2 == pattern_len) 03441 *tmp2 = tmp; 03442 } 03443 03444 tmp2 = bmGs + plm1; 03445 for (i = 0; i <= pattern_len - 2; i++) 03446 *(tmp2 - suff[i]) = plm1 - i; 03447 } 03448 03449 03450 /********************************************************************** 03451 turboBM_compute_bad_character_shifts() 03452 Precomputation dependent on pattern_len. 03453 **********************************************************************/ 03454 03455 void Item_func_like::turboBM_compute_bad_character_shifts() 03456 { 03457 int *i; 03458 int *end = bmBc + alphabet_size; 03459 int j; 03460 const int plm1 = pattern_len - 1; 03461 CHARSET_INFO *cs= cmp.cmp_collation.collation; 03462 03463 for (i = bmBc; i < end; i++) 03464 *i = pattern_len; 03465 03466 if (!cs->sort_order) 03467 { 03468 for (j = 0; j < plm1; j++) 03469 bmBc[(uint) (uchar) pattern[j]] = plm1 - j; 03470 } 03471 else 03472 { 03473 for (j = 0; j < plm1; j++) 03474 bmBc[(uint) likeconv(cs,pattern[j])] = plm1 - j; 03475 } 03476 } 03477 03478 03479 /********************************************************************** 03480 turboBM_matches() 03481 Search for pattern in text, returns true/false for match/no match 03482 **********************************************************************/ 03483 03484 bool Item_func_like::turboBM_matches(const char* text, int text_len) const 03485 { 03486 register int bcShift; 03487 register int turboShift; 03488 int shift = pattern_len; 03489 int j = 0; 03490 int u = 0; 03491 CHARSET_INFO *cs= cmp.cmp_collation.collation; 03492 03493 const int plm1= pattern_len - 1; 03494 const int tlmpl= text_len - pattern_len; 03495 03496 /* Searching */ 03497 if (!cs->sort_order) 03498 { 03499 while (j <= tlmpl) 03500 { 03501 register int i= plm1; 03502 while (i >= 0 && pattern[i] == text[i + j]) 03503 { 03504 i--; 03505 if (i == plm1 - shift) 03506 i-= u; 03507 } 03508 if (i < 0) 03509 return 1; 03510 03511 register const int v = plm1 - i; 03512 turboShift = u - v; 03513 bcShift = bmBc[(uint) (uchar) text[i + j]] - plm1 + i; 03514 shift = max(turboShift, bcShift); 03515 shift = max(shift, bmGs[i]); 03516 if (shift == bmGs[i]) 03517 u = min(pattern_len - shift, v); 03518 else 03519 { 03520 if (turboShift < bcShift) 03521 shift = max(shift, u + 1); 03522 u = 0; 03523 } 03524 j+= shift; 03525 } 03526 return 0; 03527 } 03528 else 03529 { 03530 while (j <= tlmpl) 03531 { 03532 register int i = plm1; 03533 while (i >= 0 && likeconv(cs,pattern[i]) == likeconv(cs,text[i + j])) 03534 { 03535 i--; 03536 if (i == plm1 - shift) 03537 i-= u; 03538 } 03539 if (i < 0) 03540 return 1; 03541 03542 register const int v = plm1 - i; 03543 turboShift = u - v; 03544 bcShift = bmBc[(uint) likeconv(cs, text[i + j])] - plm1 + i; 03545 shift = max(turboShift, bcShift); 03546 shift = max(shift, bmGs[i]); 03547 if (shift == bmGs[i]) 03548 u = min(pattern_len - shift, v); 03549 else 03550 { 03551 if (turboShift < bcShift) 03552 shift = max(shift, u + 1); 03553 u = 0; 03554 } 03555 j+= shift; 03556 } 03557 return 0; 03558 } 03559 } 03560 03561 03562 /* 03563 Make a logical XOR of the arguments. 03564 03565 SYNOPSIS 03566 val_int() 03567 03568 DESCRIPTION 03569 If either operator is NULL, return NULL. 03570 03571 NOTE 03572 As we don't do any index optimization on XOR this is not going to be 03573 very fast to use. 03574 03575 TODO (low priority) 03576 Change this to be optimized as: 03577 A XOR B -> (A) == 1 AND (B) <> 1) OR (A <> 1 AND (B) == 1) 03578 To be able to do this, we would however first have to extend the MySQL 03579 range optimizer to handle OR better. 03580 */ 03581 03582 longlong Item_cond_xor::val_int() 03583 { 03584 DBUG_ASSERT(fixed == 1); 03585 List_iterator<Item> li(list); 03586 Item *item; 03587 int result=0; 03588 null_value=0; 03589 while ((item=li++)) 03590 { 03591 result^= (item->val_int() != 0); 03592 if (item->null_value) 03593 { 03594 null_value=1; 03595 return 0; 03596 } 03597 } 03598 return (longlong) result; 03599 } 03600 03601 /* 03602 Apply NOT transformation to the item and return a new one. 03603 03604 SYNOPSIS 03605 neg_transformer() 03606 thd thread handler 03607 03608 DESCRIPTION 03609 Transform the item using next rules: 03610 a AND b AND ... -> NOT(a) OR NOT(b) OR ... 03611 a OR b OR ... -> NOT(a) AND NOT(b) AND ... 03612 NOT(a) -> a 03613 a = b -> a != b 03614 a != b -> a = b 03615 a < b -> a >= b 03616 a >= b -> a < b 03617 a > b -> a <= b 03618 a <= b -> a > b 03619 IS NULL(a) -> IS NOT NULL(a) 03620 IS NOT NULL(a) -> IS NULL(a) 03621 03622 RETURN 03623 New item or 03624 NULL if we cannot apply NOT transformation (see Item::neg_transformer()). 03625 */ 03626 03627 Item *Item_func_not::neg_transformer(THD *thd) /* NOT(x) -> x */ 03628 { 03629 return args[0]; 03630 } 03631 03632 03633 Item *Item_bool_rowready_func2::neg_transformer(THD *thd) 03634 { 03635 Item *item= negated_item(); 03636 return item; 03637 } 03638 03639 03640 /* a IS NULL -> a IS NOT NULL */ 03641 Item *Item_func_isnull::neg_transformer(THD *thd) 03642 { 03643 Item *item= new Item_func_isnotnull(args[0]); 03644 return item; 03645 } 03646 03647 03648 /* a IS NOT NULL -> a IS NULL */ 03649 Item *Item_func_isnotnull::neg_transformer(THD *thd) 03650 { 03651 Item *item= new Item_func_isnull(args[0]); 03652 return item; 03653 } 03654 03655 03656 Item *Item_cond_and::neg_transformer(THD *thd) /* NOT(a AND b AND ...) -> */ 03657 /* NOT a OR NOT b OR ... */ 03658 { 03659 neg_arguments(thd); 03660 Item *item= new Item_cond_or(list); 03661 return item; 03662 } 03663 03664 03665 Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */ 03666 /* NOT a AND NOT b AND ... */ 03667 { 03668 neg_arguments(thd); 03669 Item *item= new Item_cond_and(list); 03670 return item; 03671 } 03672 03673 03674 Item *Item_func_nop_all::neg_transformer(THD *thd) 03675 { 03676 /* "NOT (e $cmp$ ANY (SELECT ...)) -> e $rev_cmp$" ALL (SELECT ...) */ 03677 Item_func_not_all *new_item= new Item_func_not_all(args[0]); 03678 Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; 03679 allany->func= allany->func_creator(FALSE); 03680 allany->all= !allany->all; 03681 allany->upper_item= new_item; 03682 return new_item; 03683 } 03684 03685 Item *Item_func_not_all::neg_transformer(THD *thd) 03686 { 03687 /* "NOT (e $cmp$ ALL (SELECT ...)) -> e $rev_cmp$" ANY (SELECT ...) */ 03688 Item_func_nop_all *new_item= new Item_func_nop_all(args[0]); 03689 Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; 03690 allany->all= !allany->all; 03691 allany->func= allany->func_creator(TRUE); 03692 allany->upper_item= new_item; 03693 return new_item; 03694 } 03695 03696 Item *Item_func_eq::negated_item() /* a = b -> a != b */ 03697 { 03698 return new Item_func_ne(args[0], args[1]); 03699 } 03700 03701 03702 Item *Item_func_ne::negated_item() /* a != b -> a = b */ 03703 { 03704 return new Item_func_eq(args[0], args[1]); 03705 } 03706 03707 03708 Item *Item_func_lt::negated_item() /* a < b -> a >= b */ 03709 { 03710 return new Item_func_ge(args[0], args[1]); 03711 } 03712 03713 03714 Item *Item_func_ge::negated_item() /* a >= b -> a < b */ 03715 { 03716 return new Item_func_lt(args[0], args[1]); 03717 } 03718 03719 03720 Item *Item_func_gt::negated_item() /* a > b -> a <= b */ 03721 { 03722 return new Item_func_le(args[0], args[1]); 03723 } 03724 03725 03726 Item *Item_func_le::negated_item() /* a <= b -> a > b */ 03727 { 03728 return new Item_func_gt(args[0], args[1]); 03729 } 03730 03731 // just fake method, should never be called 03732 Item *Item_bool_rowready_func2::negated_item() 03733 { 03734 DBUG_ASSERT(0); 03735 return 0; 03736 } 03737 03738 Item_equal::Item_equal(Item_field *f1, Item_field *f2) 03739 : Item_bool_func(), const_item(0), eval_item(0), cond_false(0) 03740 { 03741 const_item_cache= 0; 03742 fields.push_back(f1); 03743 fields.push_back(f2); 03744 } 03745 03746 Item_equal::Item_equal(Item *c, Item_field *f) 03747 : Item_bool_func(), eval_item(0), cond_false(0) 03748 { 03749 const_item_cache= 0; 03750 fields.push_back(f); 03751 const_item= c; 03752 } 03753 03754 03755 Item_equal::Item_equal(Item_equal *item_equal) 03756 : Item_bool_func(), eval_item(0), cond_false(0) 03757 { 03758 const_item_cache= 0; 03759 List_iterator_fast<Item_field> li(item_equal->fields); 03760 Item_field *item; 03761 while ((item= li++)) 03762 { 03763 fields.push_back(item); 03764 } 03765 const_item= item_equal->const_item; 03766 cond_false= item_equal->cond_false; 03767 } 03768 03769 void Item_equal::add(Item *c) 03770 { 03771 if (cond_false) 03772 return; 03773 if (!const_item) 03774 { 03775 const_item= c; 03776 return; 03777 } 03778 Item_func_eq *func= new Item_func_eq(c, const_item); 03779 func->set_cmp_func(); 03780 func->quick_fix_field(); 03781 if ((cond_false= !func->val_int())) 03782 const_item_cache= 1; 03783 } 03784 03785 void Item_equal::add(Item_field *f) 03786 { 03787 fields.push_back(f); 03788 } 03789 03790 uint Item_equal::members() 03791 { 03792 return fields.elements; 03793 } 03794 03795 03796 /* 03797 Check whether a field is referred in the multiple equality 03798 03799 SYNOPSIS 03800 contains() 03801 field field whose occurrence is to be checked 03802 03803 DESCRIPTION 03804 The function checks whether field is occurred in the Item_equal object 03805 03806 RETURN VALUES 03807 1 if nultiple equality contains a reference to field 03808 0 otherwise 03809 */ 03810 03811 bool Item_equal::contains(Field *field) 03812 { 03813 List_iterator_fast<Item_field> it(fields); 03814 Item_field *item; 03815 while ((item= it++)) 03816 { 03817 if (field->eq(item->field)) 03818 return 1; 03819 } 03820 return 0; 03821 } 03822 03823 03824 /* 03825 Join members of another Item_equal object 03826 03827 SYNOPSIS 03828 merge() 03829 item multiple equality whose members are to be joined 03830 03831 DESCRIPTION 03832 The function actually merges two multiple equalities. 03833 After this operation the Item_equal object additionally contains 03834 the field items of another item of the type Item_equal. 03835 If the optional constant items are not equal the cond_false flag is 03836 set to 1. 03837 03838 RETURN VALUES 03839 none 03840 */ 03841 03842 void Item_equal::merge(Item_equal *item) 03843 { 03844 fields.concat(&item->fields); 03845 Item *c= item->const_item; 03846 if (c) 03847 { 03848 /* 03849 The flag cond_false will be set to 1 after this, if 03850 the multiple equality already contains a constant and its 03851 value is not equal to the value of c. 03852 */ 03853 add(c); 03854 } 03855 cond_false|= item->cond_false; 03856 } 03857 03858 03859 /* 03860 Order field items in multiple equality according to a sorting criteria 03861 03862 SYNOPSIS 03863 sort() 03864 cmp function to compare field item 03865 arg context extra parameter for the cmp function 03866 03867 DESCRIPTION 03868 The function perform ordering of the field items in the Item_equal 03869 object according to the criteria determined by the cmp callback parameter. 03870 If cmp(item_field1,item_field2,arg)<0 than item_field1 must be 03871 placed after item_fiel2. 03872 03873 IMPLEMENTATION 03874 The function sorts field items by the exchange sort algorithm. 03875 The list of field items is looked through and whenever two neighboring 03876 members follow in a wrong order they are swapped. This is performed 03877 again and again until we get all members in a right order. 03878 03879 RETURN VALUES 03880 None 03881 */ 03882 03883 void Item_equal::sort(Item_field_cmpfunc cmp, void *arg) 03884 { 03885 bool swap; 03886 List_iterator<Item_field> it(fields); 03887 do 03888 { 03889 Item_field *item1= it++; 03890 Item_field **ref1= it.ref(); 03891 Item_field *item2; 03892 03893 swap= FALSE; 03894 while ((item2= it++)) 03895 { 03896 Item_field **ref2= it.ref(); 03897 if (cmp(item1, item2, arg) < 0) 03898 { 03899 Item_field *item= *ref1; 03900 *ref1= *ref2; 03901 *ref2= item; 03902 swap= TRUE; 03903 } 03904 else 03905 { 03906 item1= item2; 03907 ref1= ref2; 03908 } 03909 } 03910 it.rewind(); 03911 } while (swap); 03912 } 03913 03914 03915 /* 03916 Check appearance of new constant items in the multiple equality object 03917 03918 SYNOPSIS 03919 update_const() 03920 03921 DESCRIPTION 03922 The function checks appearance of new constant items among 03923 the members of multiple equalities. Each new constant item is 03924 compared with the designated constant item if there is any in the 03925 multiple equality. If there is none the first new constant item 03926 becomes designated. 03927 03928 RETURN VALUES 03929 none 03930 */ 03931 03932 void Item_equal::update_const() 03933 { 03934 List_iterator<Item_field> it(fields); 03935 Item *item; 03936 while ((item= it++)) 03937 { 03938 if (item->const_item()) 03939 { 03940 it.remove(); 03941 add(item); 03942 } 03943 } 03944 } 03945 03946 bool Item_equal::fix_fields(THD *thd, Item **ref) 03947 { 03948 List_iterator_fast<Item_field> li(fields); 03949 Item *item; 03950 not_null_tables_cache= used_tables_cache= 0; 03951 const_item_cache= 0; 03952 while ((item= li++)) 03953 { 03954 table_map tmp_table_map; 03955 used_tables_cache|= item->used_tables(); 03956 tmp_table_map= item->not_null_tables(); 03957 not_null_tables_cache|= tmp_table_map; 03958 if (item->maybe_null) 03959 maybe_null=1; 03960 } 03961 fix_length_and_dec(); 03962 fixed= 1; 03963 return 0; 03964 } 03965 03966 void Item_equal::update_used_tables() 03967 { 03968 List_iterator_fast<Item_field> li(fields); 03969 Item *item; 03970 not_null_tables_cache= used_tables_cache= 0; 03971 if ((const_item_cache= cond_false)) 03972 return; 03973 while ((item=li++)) 03974 { 03975 item->update_used_tables(); 03976 used_tables_cache|= item->used_tables(); 03977 const_item_cache&= item->const_item(); 03978 } 03979 } 03980 03981 longlong Item_equal::val_int() 03982 { 03983 Item_field *item_field; 03984 if (cond_false) 03985 return 0; 03986 List_iterator_fast<Item_field> it(fields); 03987 Item *item= const_item ? const_item : it++; 03988 if ((null_value= item->null_value)) 03989 return 0; 03990 eval_item->store_value(item); 03991 while ((item_field= it++)) 03992 { 03993 /* Skip fields of non-const tables. They haven't been read yet */ 03994 if (item_field->field->table->const_table) 03995 { 03996 if ((null_value= item_field->null_value) || eval_item->cmp(item_field)) 03997 return 0; 03998 } 03999 } 04000 return 1; 04001 } 04002 04003 void Item_equal::fix_length_and_dec() 04004 { 04005 Item *item= const_item ? const_item : get_first(); 04006 eval_item= cmp_item::get_comparator(item->result_type(), 04007 item->collation.collation); 04008 if (item->result_type() == STRING_RESULT) 04009 eval_item->cmp_charset= cmp_collation.collation; 04010 } 04011 04012 bool Item_equal::walk(Item_processor processor, bool walk_subquery, byte *arg) 04013 { 04014 List_iterator_fast<Item_field> it(fields); 04015 Item *item; 04016 while ((item= it++)) 04017 { 04018 if (item->walk(processor, walk_subquery, arg)) 04019 return 1; 04020 } 04021 return Item_func::walk(processor, walk_subquery, arg); 04022 } 04023 04024 Item *Item_equal::transform(Item_transformer transformer, byte *arg) 04025 { 04026 List_iterator<Item_field> it(fields); 04027 Item *item; 04028 while ((item= it++)) 04029 { 04030 Item *new_item= item->transform(transformer, arg); 04031 if (!new_item) 04032 return 0; 04033 if (new_item != item) 04034 it.replace((Item_field *) new_item); 04035 } 04036 return Item_func::transform(transformer, arg); 04037 } 04038 04039 void Item_equal::print(String *str) 04040 { 04041 str->append(func_name()); 04042 str->append('('); 04043 List_iterator_fast<Item_field> it(fields); 04044 Item *item; 04045 if (const_item) 04046 const_item->print(str); 04047 else 04048 { 04049 item= it++; 04050 item->print(str); 04051 } 04052 while ((item= it++)) 04053 { 04054 str->append(','); 04055 str->append(' '); 04056 item->print(str); 04057 } 04058 str->append(')'); 04059 } 04060
1.4.7

