The world's most popular open source database
#include "mysql_priv.h"#include "sql_select.h"Include dependency graph for opt_sum.cc:

Go to the source code of this file.
Functions | |
| static bool | find_key_for_maxmin (bool max_fl, TABLE_REF *ref, Field *field, COND *cond, uint *range_fl, uint *key_prefix_length) |
| static int | reckey_in_range (bool max_fl, TABLE_REF *ref, Field *field, COND *cond, uint range_fl, uint prefix_len) |
| static int | maxmin_in_range (bool max_fl, Field *field, COND *cond) |
| static ulonglong | get_exact_record_count (TABLE_LIST *tables) |
| int | opt_sum_query (TABLE_LIST *tables, List< Item > &all_fields, COND *conds) |
| bool | simple_pred (Item_func *func_item, Item **args, bool *inv_order) |
| static bool | matching_cond (bool max_fl, TABLE_REF *ref, KEY *keyinfo, KEY_PART_INFO *field_part, COND *cond, key_part_map *key_part_used, uint *range_fl, uint *prefix_len) |
| static bool find_key_for_maxmin | ( | bool | max_fl, | |
| TABLE_REF * | ref, | |||
| Field * | field, | |||
| COND * | cond, | |||
| uint * | range_fl, | |||
| uint * | key_prefix_length | |||
| ) | [static] |
Definition at line 730 of file opt_sum.cc.
References BLOB_FLAG, cond, Field::eq(), handler::extra(), st_key_part_info::field, st_table::field, st_key_part_info::fieldnr, st_table::file, Field::flags, HA_EXTRA_KEYREAD, HA_READ_ORDER, handler::index_flags(), Bitmap< 64 >::is_set(), st_table_ref::key, st_table_ref::key_buff, st_table::key_info, st_table_ref::key_length, Field::key_length(), st_table::key_read, keyinfo, st_table_share::keys, st_table::keys_in_use_for_query, st_key_part_info::length, matching_cond(), NEAR_MIN, NO_MAX_RANGE, NO_MIN_RANGE, st_key_part_info::null_bit, PART_KEY_FLAG, Field::part_of_key, st_table::s, st_key_part_info::store_length, and Field::table.
Referenced by opt_sum_query().
00733 { 00734 if (!(field->flags & PART_KEY_FLAG)) 00735 return 0; // Not key field 00736 00737 TABLE *table= field->table; 00738 uint idx= 0; 00739 00740 KEY *keyinfo,*keyinfo_end; 00741 for (keyinfo= table->key_info, keyinfo_end= keyinfo+table->s->keys ; 00742 keyinfo != keyinfo_end; 00743 keyinfo++,idx++) 00744 { 00745 KEY_PART_INFO *part,*part_end; 00746 key_part_map key_part_to_use= 0; 00747 /* 00748 Perform a check if index is not disabled by ALTER TABLE 00749 or IGNORE INDEX. 00750 */ 00751 if (!table->keys_in_use_for_query.is_set(idx)) 00752 continue; 00753 uint jdx= 0; 00754 *prefix_len= 0; 00755 for (part= keyinfo->key_part, part_end= part+keyinfo->key_parts ; 00756 part != part_end ; 00757 part++, jdx++, key_part_to_use= (key_part_to_use << 1) | 1) 00758 { 00759 if (!(table->file->index_flags(idx, jdx, 0) & HA_READ_ORDER)) 00760 return 0; 00761 00762 /* Check whether the index component is partial */ 00763 Field *part_field= table->field[part->fieldnr-1]; 00764 if ((part_field->flags & BLOB_FLAG) || 00765 part->length < part_field->key_length()) 00766 break; 00767 00768 if (field->eq(part->field)) 00769 { 00770 ref->key= idx; 00771 ref->key_length= 0; 00772 key_part_map key_part_used= 0; 00773 *range_fl= NO_MIN_RANGE | NO_MAX_RANGE; 00774 if (matching_cond(max_fl, ref, keyinfo, part, cond, 00775 &key_part_used, range_fl, prefix_len) && 00776 !(key_part_to_use & ~key_part_used)) 00777 { 00778 if (!max_fl && key_part_used == key_part_to_use && part->null_bit) 00779 { 00780 /* 00781 SELECT MIN(key_part2) FROM t1 WHERE key_part1=const 00782 If key_part2 may be NULL, then we want to find the first row 00783 that is not null 00784 */ 00785 ref->key_buff[ref->key_length]= 1; 00786 ref->key_length+= part->store_length; 00787 *range_fl&= ~NO_MIN_RANGE; 00788 *range_fl|= NEAR_MIN; // > NULL 00789 } 00790 /* 00791 The following test is false when the key in the key tree is 00792 converted (for example to upper case) 00793 */ 00794 if (field->part_of_key.is_set(idx)) 00795 { 00796 table->key_read= 1; 00797 table->file->extra(HA_EXTRA_KEYREAD); 00798 } 00799 return 1; 00800 } 00801 } 00802 } 00803 } 00804 return 0; 00805 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ulonglong get_exact_record_count | ( | TABLE_LIST * | tables | ) | [static] |
Definition at line 73 of file opt_sum.cc.
References count, HA_POS_ERROR, st_table_list::next_leaf, and ULONGLONG_MAX.
Referenced by opt_sum_query().
00074 { 00075 ulonglong count= 1; 00076 for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf) 00077 { 00078 ha_rows tmp= tl->table->file->records(); 00079 if ((tmp == HA_POS_ERROR)) 00080 return ULONGLONG_MAX; 00081 count*= tmp; 00082 } 00083 return count; 00084 }
Here is the caller graph for this function:

| static bool matching_cond | ( | bool | max_fl, | |
| TABLE_REF * | ref, | |||
| KEY * | keyinfo, | |||
| KEY_PART_INFO * | field_part, | |||
| COND * | cond, | |||
| key_part_map * | key_part_used, | |||
| uint * | range_fl, | |||
| uint * | prefix_len | |||
| ) | [static] |
Definition at line 526 of file opt_sum.cc.
References args, Item_func::BETWEEN, CHECK_FIELD_IGNORE, cond, Item::COND_ITEM, Item_func::COND_OR_FUNC, Field::eq(), Item_func::EQ_FUNC, Item_func::EQUAL_FUNC, st_key_part_info::field, Item::FUNC_ITEM, Item_func::GE_FUNC, Field::get_key_image(), Item_func::GT_FUNC, Field::is_null(), Item_func::ISNULL_FUNC, Field::itRAW, st_table_ref::key_buff, st_table_ref::key_length, keyinfo, Item_func::LE_FUNC, st_key_part_info::length, Item_func::LT_FUNC, st_table::map, Item_func::MULT_EQUAL_FUNC, NEAR_MAX, NEAR_MIN, NO_MAX_RANGE, NO_MIN_RANGE, st_key_part_info::null_bit, Field::set_null(), simple_pred(), st_key_part_info::store_length, store_val_in_field(), Field::table, and test.
Referenced by find_key_for_maxmin().
00530 { 00531 if (!cond) 00532 return 1; 00533 Field *field= field_part->field; 00534 if (!(cond->used_tables() & field->table->map)) 00535 { 00536 /* Condition doesn't restrict the used table */ 00537 return 1; 00538 } 00539 if (cond->type() == Item::COND_ITEM) 00540 { 00541 if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC) 00542 return 0; 00543 00544 /* AND */ 00545 List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); 00546 Item *item; 00547 while ((item= li++)) 00548 { 00549 if (!matching_cond(max_fl, ref, keyinfo, field_part, item, 00550 key_part_used, range_fl, prefix_len)) 00551 return 0; 00552 } 00553 return 1; 00554 } 00555 00556 if (cond->type() != Item::FUNC_ITEM) 00557 return 0; // Not operator, can't optimize 00558 00559 bool eq_type= 0; // =, <=> or IS NULL 00560 bool noeq_type= 0; // < or > 00561 bool less_fl= 0; // < or <= 00562 bool is_null= 0; 00563 bool between= 0; 00564 00565 switch (((Item_func*) cond)->functype()) { 00566 case Item_func::ISNULL_FUNC: 00567 is_null= 1; /* fall through */ 00568 case Item_func::EQ_FUNC: 00569 case Item_func::EQUAL_FUNC: 00570 eq_type= 1; 00571 break; 00572 case Item_func::LT_FUNC: 00573 noeq_type= 1; /* fall through */ 00574 case Item_func::LE_FUNC: 00575 less_fl= 1; 00576 break; 00577 case Item_func::GT_FUNC: 00578 noeq_type= 1; /* fall through */ 00579 case Item_func::GE_FUNC: 00580 break; 00581 case Item_func::BETWEEN: 00582 between= 1; 00583 break; 00584 case Item_func::MULT_EQUAL_FUNC: 00585 eq_type= 1; 00586 break; 00587 default: 00588 return 0; // Can't optimize function 00589 } 00590 00591 Item *args[3]; 00592 bool inv; 00593 00594 /* Test if this is a comparison of a field and constant */ 00595 if (!simple_pred((Item_func*) cond, args, &inv)) 00596 return 0; 00597 00598 if (inv && !eq_type) 00599 less_fl= 1-less_fl; // Convert '<' -> '>' (etc) 00600 00601 /* Check if field is part of the tested partial key */ 00602 byte *key_ptr= ref->key_buff; 00603 KEY_PART_INFO *part; 00604 for (part= keyinfo->key_part; 00605 ; 00606 key_ptr+= part++->store_length) 00607 00608 { 00609 if (part > field_part) 00610 return 0; // Field is beyond the tested parts 00611 if (part->field->eq(((Item_field*) args[0])->field)) 00612 break; // Found a part od the key for the field 00613 } 00614 00615 bool is_field_part= part == field_part; 00616 if (!(is_field_part || eq_type)) 00617 return 0; 00618 00619 key_part_map org_key_part_used= *key_part_used; 00620 if (eq_type || between || max_fl == less_fl) 00621 { 00622 uint length= (key_ptr-ref->key_buff)+part->store_length; 00623 if (ref->key_length < length) 00624 /* Ultimately ref->key_length will contain the length of the search key */ 00625 ref->key_length= length; 00626 if (!*prefix_len && part+1 == field_part) 00627 *prefix_len= length; 00628 if (is_field_part && eq_type) 00629 *prefix_len= ref->key_length; 00630 00631 *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part); 00632 } 00633 00634 if (org_key_part_used != *key_part_used || 00635 (is_field_part && 00636 (between || eq_type || max_fl == less_fl) && !cond->val_int())) 00637 { 00638 /* 00639 It's the first predicate for this part or a predicate of the 00640 following form that moves upper/lower bounds for max/min values: 00641 - field BETWEEN const AND const 00642 - field = const 00643 - field {<|<=} const, when searching for MAX 00644 - field {>|>=} const, when searching for MIN 00645 */ 00646 00647 if (is_null) 00648 { 00649 part->field->set_null(); 00650 *key_ptr= (byte) 1; 00651 } 00652 else 00653 { 00654 store_val_in_field(part->field, args[between && max_fl ? 2 : 1], 00655 CHECK_FIELD_IGNORE); 00656 if (part->null_bit) 00657 *key_ptr++= (byte) test(part->field->is_null()); 00658 part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW); 00659 } 00660 if (is_field_part) 00661 { 00662 if (between || eq_type) 00663 *range_fl&= ~(NO_MAX_RANGE | NO_MIN_RANGE); 00664 else 00665 { 00666 *range_fl&= ~(max_fl ? NO_MAX_RANGE : NO_MIN_RANGE); 00667 if (noeq_type) 00668 *range_fl|= (max_fl ? NEAR_MAX : NEAR_MIN); 00669 else 00670 *range_fl&= ~(max_fl ? NEAR_MAX : NEAR_MIN); 00671 } 00672 } 00673 } 00674 else if (eq_type) 00675 { 00676 if (!is_null && !cond->val_int() || 00677 is_null && !test(part->field->is_null())) 00678 return 0; // Impossible test 00679 } 00680 else if (is_field_part) 00681 *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE); 00682 return 1; 00683 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 849 of file opt_sum.cc.
References Item_func::BETWEEN, cond, Item::COND_ITEM, Item::const_item(), DBUG_ASSERT, Item_func::EQ_FUNC, Item_func::EQUAL_FUNC, Item_func::GE_FUNC, Item_func::GT_FUNC, Item_func::LE_FUNC, Item_func::LT_FUNC, st_table::map, and Field::table.
Referenced by reckey_in_range().
00850 { 00851 /* If AND/OR condition */ 00852 if (cond->type() == Item::COND_ITEM) 00853 { 00854 List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); 00855 Item *item; 00856 while ((item= li++)) 00857 { 00858 if (maxmin_in_range(max_fl, field, item)) 00859 return 1; 00860 } 00861 return 0; 00862 } 00863 00864 if (cond->used_tables() != field->table->map) 00865 return 0; 00866 bool less_fl= 0; 00867 switch (((Item_func*) cond)->functype()) { 00868 case Item_func::BETWEEN: 00869 return cond->val_int() == 0; // Return 1 if WHERE is false 00870 case Item_func::LT_FUNC: 00871 case Item_func::LE_FUNC: 00872 less_fl= 1; 00873 case Item_func::GT_FUNC: 00874 case Item_func::GE_FUNC: 00875 { 00876 Item *item= ((Item_func*) cond)->arguments()[1]; 00877 /* In case of 'const op item' we have to swap the operator */ 00878 if (!item->const_item()) 00879 less_fl= 1-less_fl; 00880 /* 00881 We only have to check the expression if we are using an expression like 00882 SELECT MAX(b) FROM t1 WHERE a=const AND b>const 00883 not for 00884 SELECT MAX(b) FROM t1 WHERE a=const AND b<const 00885 */ 00886 if (max_fl != less_fl) 00887 return cond->val_int() == 0; // Return 1 if WHERE is false 00888 return 0; 00889 } 00890 case Item_func::EQ_FUNC: 00891 case Item_func::EQUAL_FUNC: 00892 break; 00893 default: // Keep compiler happy 00894 DBUG_ASSERT(1); // Impossible 00895 break; 00896 } 00897 return 0; 00898 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int opt_sum_query | ( | TABLE_LIST * | tables, | |
| List< Item > & | all_fields, | |||
| COND * | conds | |||
| ) |
Definition at line 108 of file opt_sum.cc.
References args, Item::const_item(), count, Item_sum::COUNT_FUNC, error, handler::extra(), FALSE, Item_field::field, Item::FIELD_ITEM, st_table::file, find_key_for_maxmin(), get_exact_record_count(), HA_ERR_END_OF_FILE, HA_ERR_KEY_NOT_FOUND, HA_EXTRA_NO_KEYREAD, HA_HAS_RECORDS, handler::ha_index_end(), handler::ha_index_init(), HA_READ_AFTER_KEY, HA_READ_BEFORE_KEY, HA_READ_KEY_OR_NEXT, HA_READ_PREFIX_LAST_OR_PREV, HA_STATS_RECORDS_IS_EXACT, HA_STATUS_NO_LOCK, HA_STATUS_VARIABLE, handler::index_first(), handler::index_last(), handler::index_read(), st_table_ref::key, st_table_ref::key_buff, st_table_ref::key_length, st_table::key_read, st_table::map, Item_sum::MAX_FUNC, MAX_KEY_LENGTH, Item_sum::MIN_FUNC, MYF, NEAR_MAX, NEAR_MIN, st_table_list::next_leaf, handler::print_error(), Item::real_item(), reckey_in_range(), st_table::record, Item::SUM_FUNC_ITEM, Field::table, test, TRUE, Item::type(), ULONGLONG_MAX, Item::update_used_tables(), and Item::used_tables().
Referenced by JOIN::optimize().
00109 { 00110 List_iterator_fast<Item> it(all_fields); 00111 int const_result= 1; 00112 bool recalc_const_item= 0; 00113 ulonglong count= 1; 00114 bool is_exact_count= TRUE, maybe_exact_count= TRUE; 00115 table_map removed_tables= 0, outer_tables= 0, used_tables= 0; 00116 table_map where_tables= 0; 00117 Item *item; 00118 int error; 00119 00120 if (conds) 00121 where_tables= conds->used_tables(); 00122 00123 /* 00124 Analyze outer join dependencies, and, if possible, compute the number 00125 of returned rows. 00126 */ 00127 for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf) 00128 { 00129 TABLE_LIST *embedded; 00130 for (embedded= tl ; embedded; embedded= embedded->embedding) 00131 { 00132 if (embedded->on_expr) 00133 break; 00134 } 00135 if (embedded) 00136 /* Don't replace expression on a table that is part of an outer join */ 00137 { 00138 outer_tables|= tl->table->map; 00139 00140 /* 00141 We can't optimise LEFT JOIN in cases where the WHERE condition 00142 restricts the table that is used, like in: 00143 SELECT MAX(t1.a) FROM t1 LEFT JOIN t2 join-condition 00144 WHERE t2.field IS NULL; 00145 */ 00146 if (tl->table->map & where_tables) 00147 return 0; 00148 } 00149 else 00150 used_tables|= tl->table->map; 00151 00152 /* 00153 If the storage manager of 'tl' gives exact row count as part of 00154 statistics (cheap), compute the total number of rows. If there are 00155 no outer table dependencies, this count may be used as the real count. 00156 Schema tables are filled after this function is invoked, so we can't 00157 get row count 00158 */ 00159 if (!(tl->table->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT) || 00160 tl->schema_table) 00161 { 00162 maybe_exact_count&= test(!tl->schema_table && 00163 (tl->table->file->ha_table_flags() & 00164 HA_HAS_RECORDS)); 00165 is_exact_count= FALSE; 00166 count= 1; // ensure count != 0 00167 } 00168 else 00169 { 00170 tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); 00171 count*= tl->table->file->stats.records; 00172 } 00173 } 00174 00175 /* 00176 Iterate through all items in the SELECT clause and replace 00177 COUNT(), MIN() and MAX() with constants (if possible). 00178 */ 00179 00180 while ((item= it++)) 00181 { 00182 if (item->type() == Item::SUM_FUNC_ITEM) 00183 { 00184 Item_sum *item_sum= (((Item_sum*) item)); 00185 switch (item_sum->sum_func()) { 00186 case Item_sum::COUNT_FUNC: 00187 /* 00188 If the expr in COUNT(expr) can never be null we can change this 00189 to the number of rows in the tables if this number is exact and 00190 there are no outer joins. 00191 */ 00192 if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null && 00193 !outer_tables && maybe_exact_count) 00194 { 00195 if (!is_exact_count) 00196 { 00197 if ((count= get_exact_record_count(tables)) == ULONGLONG_MAX) 00198 { 00199 /* Error from handler in counting rows. Don't optimize count() */ 00200 const_result= 0; 00201 continue; 00202 } 00203 is_exact_count= 1; // count is now exact 00204 } 00205 ((Item_sum_count*) item)->make_const((longlong) count); 00206 recalc_const_item= 1; 00207 } 00208 else 00209 const_result= 0; 00210 break; 00211 case Item_sum::MIN_FUNC: 00212 { 00213 /* 00214 If MIN(expr) is the first part of a key or if all previous 00215 parts of the key is found in the COND, then we can use 00216 indexes to find the key. 00217 */ 00218 Item *expr=item_sum->args[0]; 00219 if (expr->real_item()->type() == Item::FIELD_ITEM) 00220 { 00221 byte key_buff[MAX_KEY_LENGTH]; 00222 TABLE_REF ref; 00223 uint range_fl, prefix_len; 00224 00225 ref.key_buff= key_buff; 00226 Item_field *item_field= (Item_field*) (expr->real_item()); 00227 TABLE *table= item_field->field->table; 00228 00229 /* 00230 Look for a partial key that can be used for optimization. 00231 If we succeed, ref.key_length will contain the length of 00232 this key, while prefix_len will contain the length of 00233 the beginning of this key without field used in MIN(). 00234 Type of range for the key part for this field will be 00235 returned in range_fl. 00236 */ 00237 if ((outer_tables & table->map) || 00238 !find_key_for_maxmin(0, &ref, item_field->field, conds, 00239 &range_fl, &prefix_len)) 00240 { 00241 const_result= 0; 00242 break; 00243 } 00244 error= table->file->ha_index_init((uint) ref.key, 1); 00245 00246 if (!ref.key_length) 00247 error= table->file->index_first(table->record[0]); 00248 else 00249 error= table->file->index_read(table->record[0],key_buff, 00250 ref.key_length, 00251 range_fl & NEAR_MIN ? 00252 HA_READ_AFTER_KEY : 00253 HA_READ_KEY_OR_NEXT); 00254 if (!error && reckey_in_range(0, &ref, item_field->field, 00255 conds, range_fl, prefix_len)) 00256 error= HA_ERR_KEY_NOT_FOUND; 00257 if (table->key_read) 00258 { 00259 table->key_read= 0; 00260 table->file->extra(HA_EXTRA_NO_KEYREAD); 00261 } 00262 table->file->ha_index_end(); 00263 if (error) 00264 { 00265 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) 00266 return -1; // No rows matching WHERE 00267 /* HA_ERR_LOCK_DEADLOCK or some other error */ 00268 table->file->print_error(error, MYF(0)); 00269 return(error); 00270 } 00271 removed_tables|= table->map; 00272 } 00273 else if (!expr->const_item() || !is_exact_count) 00274 { 00275 /* 00276 The optimization is not applicable in both cases: 00277 (a) 'expr' is a non-constant expression. Then we can't 00278 replace 'expr' by a constant. 00279 (b) 'expr' is a costant. According to ANSI, MIN/MAX must return 00280 NULL if the query does not return any rows. Thus, if we are not 00281 able to determine if the query returns any rows, we can't apply 00282 the optimization and replace MIN/MAX with a constant. 00283 */ 00284 const_result= 0; 00285 break; 00286 } 00287 if (!count) 00288 { 00289 /* If count == 0, then we know that is_exact_count == TRUE. */ 00290 ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */ 00291 } 00292 else 00293 ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */ 00294 ((Item_sum_min*) item_sum)->make_const(); 00295 recalc_const_item= 1; 00296 break; 00297 } 00298 case Item_sum::MAX_FUNC: 00299 { 00300 /* 00301 If MAX(expr) is the first part of a key or if all previous 00302 parts of the key is found in the COND, then we can use 00303 indexes to find the key. 00304 */ 00305 Item *expr=item_sum->args[0]; 00306 if (expr->real_item()->type() == Item::FIELD_ITEM) 00307 { 00308 byte key_buff[MAX_KEY_LENGTH]; 00309 TABLE_REF ref; 00310 uint range_fl, prefix_len; 00311 00312 ref.key_buff= key_buff; 00313 Item_field *item_field= (Item_field*) (expr->real_item()); 00314 TABLE *table= item_field->field->table; 00315 00316 /* 00317 Look for a partial key that can be used for optimization. 00318 If we succeed, ref.key_length will contain the length of 00319 this key, while prefix_len will contain the length of 00320 the beginning of this key without field used in MAX(). 00321 Type of range for the key part for this field will be 00322 returned in range_fl. 00323 */ 00324 if ((outer_tables & table->map) || 00325 !find_key_for_maxmin(1, &ref, item_field->field, conds, 00326 &range_fl, &prefix_len)) 00327 { 00328 const_result= 0; 00329 break; 00330 } 00331 error= table->file->ha_index_init((uint) ref.key, 1); 00332 00333 if (!ref.key_length) 00334 error= table->file->index_last(table->record[0]); 00335 else 00336 error= table->file->index_read(table->record[0], key_buff, 00337 ref.key_length, 00338 range_fl & NEAR_MAX ? 00339 HA_READ_BEFORE_KEY : 00340 HA_READ_PREFIX_LAST_OR_PREV); 00341 if (!error && reckey_in_range(1, &ref, item_field->field, 00342 conds, range_fl, prefix_len)) 00343 error= HA_ERR_KEY_NOT_FOUND; 00344 if (table->key_read) 00345 { 00346 table->key_read=0; 00347 table->file->extra(HA_EXTRA_NO_KEYREAD); 00348 } 00349 table->file->ha_index_end(); 00350 if (error) 00351 { 00352 if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) 00353 return -1; // No rows matching WHERE 00354 /* HA_ERR_LOCK_DEADLOCK or some other error */ 00355 table->file->print_error(error, MYF(0)); 00356 return(error); 00357 } 00358 removed_tables|= table->map; 00359 } 00360 else if (!expr->const_item() || !is_exact_count) 00361 { 00362 /* 00363 The optimization is not applicable in both cases: 00364 (a) 'expr' is a non-constant expression. Then we can't 00365 replace 'expr' by a constant. 00366 (b) 'expr' is a costant. According to ANSI, MIN/MAX must return 00367 NULL if the query does not return any rows. Thus, if we are not 00368 able to determine if the query returns any rows, we can't apply 00369 the optimization and replace MIN/MAX with a constant. 00370 */ 00371 const_result= 0; 00372 break; 00373 } 00374 if (!count) 00375 { 00376 /* If count != 1, then we know that is_exact_count == TRUE. */ 00377 ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */ 00378 } 00379 else 00380 ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */ 00381 ((Item_sum_max*) item_sum)->make_const(); 00382 recalc_const_item= 1; 00383 break; 00384 } 00385 default: 00386 const_result= 0; 00387 break; 00388 } 00389 } 00390 else if (const_result) 00391 { 00392 if (recalc_const_item) 00393 item->update_used_tables(); 00394 if (!item->const_item()) 00395 const_result= 0; 00396 } 00397 } 00398 /* 00399 If we have a where clause, we can only ignore searching in the 00400 tables if MIN/MAX optimisation replaced all used tables 00401 We do not use replaced values in case of: 00402 SELECT MIN(key) FROM table_1, empty_table 00403 removed_tables is != 0 if we have used MIN() or MAX(). 00404 */ 00405 if (removed_tables && used_tables != removed_tables) 00406 const_result= 0; // We didn't remove all tables 00407 return const_result; 00408 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int reckey_in_range | ( | bool | max_fl, | |
| TABLE_REF * | ref, | |||
| Field * | field, | |||
| COND * | cond, | |||
| uint | range_fl, | |||
| uint | prefix_len | |||
| ) | [static] |
Definition at line 825 of file opt_sum.cc.
References cond, st_table_ref::key, st_table_ref::key_buff, key_cmp_if_same(), maxmin_in_range(), NO_MAX_RANGE, NO_MIN_RANGE, and Field::table.
Referenced by opt_sum_query().
00827 { 00828 if (key_cmp_if_same(field->table, ref->key_buff, ref->key, prefix_len)) 00829 return 1; 00830 if (!cond || (range_fl & (max_fl ? NO_MIN_RANGE : NO_MAX_RANGE))) 00831 return 0; 00832 return maxmin_in_range(max_fl, field, cond); 00833 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 427 of file opt_sum.cc.
References args, Item_func::argument_count(), Item_func::arguments(), Item::const_item(), Item::FIELD_ITEM, and Item::type().
Referenced by check_group_min_max_predicates(), and matching_cond().
00428 { 00429 Item *item; 00430 *inv_order= 0; 00431 switch (func_item->argument_count()) { 00432 case 0: 00433 /* MULT_EQUAL_FUNC */ 00434 { 00435 Item_equal *item_equal= (Item_equal *) func_item; 00436 Item_equal_iterator it(*item_equal); 00437 args[0]= it++; 00438 if (it++) 00439 return 0; 00440 if (!(args[1]= item_equal->get_const())) 00441 return 0; 00442 } 00443 break; 00444 case 1: 00445 /* field IS NULL */ 00446 item= func_item->arguments()[0]; 00447 if (item->type() != Item::FIELD_ITEM) 00448 return 0; 00449 args[0]= item; 00450 break; 00451 case 2: 00452 /* 'field op const' or 'const op field' */ 00453 item= func_item->arguments()[0]; 00454 if (item->type() == Item::FIELD_ITEM) 00455 { 00456 args[0]= item; 00457 item= func_item->arguments()[1]; 00458 if (!item->const_item()) 00459 return 0; 00460 args[1]= item; 00461 } 00462 else if (item->const_item()) 00463 { 00464 args[1]= item; 00465 item= func_item->arguments()[1]; 00466 if (item->

