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

Go to the source code of this file.
| #define CLONE_KEY1_MAYBE 1 |
| #define CLONE_KEY2_MAYBE 2 |
Definition at line 82 of file opt_range.cc.
Referenced by get_best_ror_intersect(), and ror_intersect_add().
| #define NOT_IN_IGNORE_THRESHOLD 1000 |
Referenced by get_func_mm_tree().
| #define test_rb_tree | ( | A, | |||
| B | ) | {} |
Definition at line 74 of file opt_range.cc.
Referenced by SEL_ARG::rb_insert(), test_rb_tree(), and SEL_ARG::tree_delete().
| #define test_use_count | ( | A | ) | {} |
Definition at line 75 of file opt_range.cc.
| typedef struct st_ror_scan_info ROR_SCAN_INFO |
Definition at line 5908 of file opt_range.cc.
References SEL_ARG::IMPOSSIBLE, SEL_ARG::increment_use_count(), key1, key2, key_and(), SEL_ARG::MAYBE_KEY, SEL_ARG::next, SEL_ARG::next_key_part, null_element, and SEL_ARG::type.
Referenced by key_and().
05909 { 05910 SEL_ARG *next; 05911 ulong use_count=key1->use_count; 05912 05913 if (key1->elements != 1) 05914 { 05915 key2->use_count+=key1->elements-1; 05916 key2->increment_use_count((int) key1->elements-1); 05917 } 05918 if (key1->type == SEL_ARG::MAYBE_KEY) 05919 { 05920 key1->right= key1->left= &null_element; 05921 key1->next= key1->prev= 0; 05922 } 05923 for (next=key1->first(); next ; next=next->next) 05924 { 05925 if (next->next_key_part) 05926 { 05927 SEL_ARG *tmp=key_and(next->next_key_part,key2,clone_flag); 05928 if (tmp && tmp->type == SEL_ARG::IMPOSSIBLE) 05929 { 05930 key1=key1->tree_delete(next); 05931 continue; 05932 } 05933 next->next_key_part=tmp; 05934 if (use_count) 05935 next->increment_use_count(use_count); 05936 } 05937 else 05938 next->next_key_part=key2; 05939 } 05940 if (!key1) 05941 return &null_element; // Impossible ranges 05942 key1->use_count++; 05943 return key1; 05944 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool check_group_min_max_predicates | ( | COND * | cond, | |
| Item_field * | min_max_arg_item, | |||
| Field::imagetype | image_type | |||
| ) | [static] |
Definition at line 9172 of file opt_range.cc.
References args, Item_func::argument_count(), Item_func::arguments(), Item_func::BETWEEN, bzero, Field::cmp_type(), Item::compare_collation(), cond, Item::COND_ITEM, Item::const_item(), DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, Item_field::eq(), Item_func::EQ_FUNC, Item_func::EQUAL_FUNC, FALSE, Item_field::field, Item::FIELD_ITEM, Item::full_name(), Item::FUNC_ITEM, Item_func::func_name(), Item_func::functype(), Item_func::GE_FUNC, Item_func::GT_FUNC, Item_func::ISNOTNULL_FUNC, Item_func::ISNULL_FUNC, Field::itRAW, Item_func::LE_FUNC, Item_func::LT_FUNC, Item_func::NE_FUNC, Item_field::result_type(), simple_pred(), STRING_RESULT, Item::SUBSELECT_ITEM, TRUE, and Item::type().
Referenced by get_best_group_min_max().
09174 { 09175 DBUG_ENTER("check_group_min_max_predicates"); 09176 DBUG_ASSERT(cond && min_max_arg_item); 09177 09178 Item::Type cond_type= cond->type(); 09179 if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */ 09180 { 09181 DBUG_PRINT("info", ("Analyzing: %s", ((Item_func*) cond)->func_name())); 09182 List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); 09183 Item *and_or_arg; 09184 while ((and_or_arg= li++)) 09185 { 09186 if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, 09187 image_type)) 09188 DBUG_RETURN(FALSE); 09189 } 09190 DBUG_RETURN(TRUE); 09191 } 09192 09193 /* 09194 TODO: 09195 This is a very crude fix to handle sub-selects in the WHERE clause 09196 (Item_subselect objects). With the test below we rule out from the 09197 optimization all queries with subselects in the WHERE clause. What has to 09198 be done, is that here we should analyze whether the subselect references 09199 the MIN/MAX argument field, and disallow the optimization only if this is 09200 so. 09201 */ 09202 if (cond_type == Item::SUBSELECT_ITEM) 09203 DBUG_RETURN(FALSE); 09204 09205 /* We presume that at this point there are no other Items than functions. */ 09206 DBUG_ASSERT(cond_type == Item::FUNC_ITEM); 09207 09208 /* Test if cond references only group-by or non-group fields. */ 09209 Item_func *pred= (Item_func*) cond; 09210 Item **arguments= pred->arguments(); 09211 Item *cur_arg; 09212 DBUG_PRINT("info", ("Analyzing: %s", pred->func_name())); 09213 for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++) 09214 { 09215 cur_arg= arguments[arg_idx]; 09216 DBUG_PRINT("info", ("cur_arg: %s", cur_arg->full_name())); 09217 if (cur_arg->type() == Item::FIELD_ITEM) 09218 { 09219 if (min_max_arg_item->eq(cur_arg, 1)) 09220 { 09221 /* 09222 If pred references the MIN/MAX argument, check whether pred is a range 09223 condition that compares the MIN/MAX argument with a constant. 09224 */ 09225 Item_func::Functype pred_type= pred->functype(); 09226 if (pred_type != Item_func::EQUAL_FUNC && 09227 pred_type != Item_func::LT_FUNC && 09228 pred_type != Item_func::LE_FUNC && 09229 pred_type != Item_func::GT_FUNC && 09230 pred_type != Item_func::GE_FUNC && 09231 pred_type != Item_func::BETWEEN && 09232 pred_type != Item_func::ISNULL_FUNC && 09233 pred_type != Item_func::ISNOTNULL_FUNC && 09234 pred_type != Item_func::EQ_FUNC && 09235 pred_type != Item_func::NE_FUNC) 09236 DBUG_RETURN(FALSE); 09237 09238 /* Check that pred compares min_max_arg_item with a constant. */ 09239 Item *args[3]; 09240 bzero(args, 3 * sizeof(Item*)); 09241 bool inv; 09242 /* Test if this is a comparison of a field and a constant. */ 09243 if (!simple_pred(pred, args, &inv)) 09244 DBUG_RETURN(FALSE); 09245 09246 /* Check for compatible string comparisons - similar to get_mm_leaf. */ 09247 if (args[0] && args[1] && !args[2] && // this is a binary function 09248 min_max_arg_item->result_type() == STRING_RESULT && 09249 /* 09250 Don't use an index when comparing strings of different collations. 09251 */ 09252 ((args[1]->result_type() == STRING_RESULT && 09253 image_type == Field::itRAW && 09254 ((Field_str*) min_max_arg_item->field)->charset() != 09255 pred->compare_collation()) 09256 || 09257 /* 09258 We can't always use indexes when comparing a string index to a 09259 number. 09260 */ 09261 (args[1]->result_type() != STRING_RESULT && 09262 min_max_arg_item->field->cmp_type() != args[1]->result_type()))) 09263 DBUG_RETURN(FALSE); 09264 } 09265 } 09266 else if (cur_arg->type() == Item::FUNC_ITEM) 09267 { 09268 if (!check_group_min_max_predicates(cur_arg, min_max_arg_item, 09269 image_type)) 09270 DBUG_RETURN(FALSE); 09271 } 09272 else if (cur_arg->const_item()) 09273 { 09274 DBUG_RETURN(TRUE); 09275 } 09276 else 09277 DBUG_RETURN(FALSE); 09278 } 09279 09280 DBUG_RETURN(TRUE); 09281 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ha_rows check_quick_keys | ( | PARAM * | param, | |
| uint | index, | |||
| SEL_ARG * | key_tree, | |||
| char * | min_key, | |||
| uint | min_key_flag, | |||
| char * | max_key, | |||
| uint | max_key_flag | |||
| ) | [static] |
Definition at line 6982 of file opt_range.cc.
References FALSE, st_table::field, st_table::file, st_key_range::flag, st_key::flags, GEOM_FLAG, HA_END_SPACE_KEY, HA_NOSAME, HA_POS_ERROR, HA_READ_AFTER_KEY, HA_READ_BEFORE_KEY, HA_READ_KEY_EXACT, is_key_scan_ror(), PARAM::is_ror_scan, st_key_range::key, PARAM::key, st_table::key_info, Field::key_length(), st_key::key_parts, SEL_ARG::KEY_RANGE, SEL_ARG::left, st_key_range::length, st_key_part::length, max, SEL_ARG::max_flag, PARAM::max_key, PARAM::max_key_part, memcmp(), SEL_ARG::min_flag, PARAM::min_key, PARAM::n_ranges, NEAR_MAX, NEAR_MIN, SEL_ARG::next_key_part, null_element, SEL_ARG::part, PARAM::range_count, RANGE_OPT_PARAM::real_keynr, records, handler::records_in_range(), SEL_ARG::right, SEL_ARG::store(), SEL_ARG::store_max_key(), SEL_ARG::store_min_key(), RANGE_OPT_PARAM::table, and SEL_ARG::type.
Referenced by check_quick_select().
06985 { 06986 ha_rows records=0, tmp; 06987 uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length; 06988 char *tmp_min_key, *tmp_max_key; 06989 06990 param->max_key_part=max(param->max_key_part,key_tree->part); 06991 if (key_tree->left != &null_element) 06992 { 06993 /* 06994 There are at least two intervals for current key part, i.e. condition 06995 was converted to something like 06996 (keyXpartY less/equals c1) OR (keyXpartY more/equals c2). 06997 This is not a ROR scan if the key is not Clustered Primary Key. 06998 */ 06999 param->is_ror_scan= FALSE; 07000 records=check_quick_keys(param,idx,key_tree->left,min_key,min_key_flag, 07001 max_key,max_key_flag); 07002 if (records == HA_POS_ERROR) // Impossible 07003 return records; 07004 } 07005 07006 tmp_min_key= min_key; 07007 tmp_max_key= max_key; 07008 key_tree->store(param->key[idx][key_tree->part].store_length, 07009 &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag); 07010 min_key_length= (uint) (tmp_min_key- param->min_key); 07011 max_key_length= (uint) (tmp_max_key- param->max_key); 07012 07013 if (param->is_ror_scan) 07014 { 07015 /* 07016 If the index doesn't cover entire key, mark the scan as non-ROR scan. 07017 Actually we're cutting off some ROR scans here. 07018 */ 07019 uint16 fieldnr= param->table->key_info[param->real_keynr[idx]]. 07020 key_part[key_tree->part].fieldnr - 1; 07021 if (param->table->field[fieldnr]->key_length() != 07022 param->key[idx][key_tree->part].length) 07023 param->is_ror_scan= FALSE; 07024 } 07025 07026 if (key_tree->next_key_part && 07027 key_tree->next_key_part->part == key_tree->part+1 && 07028 key_tree->next_key_part->type == SEL_ARG::KEY_RANGE) 07029 { // const key as prefix 07030 if (min_key_length == max_key_length && 07031 !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) && 07032 !key_tree->min_flag && !key_tree->max_flag) 07033 { 07034 tmp=check_quick_keys(param,idx,key_tree->next_key_part, 07035 tmp_min_key, min_key_flag | key_tree->min_flag, 07036 tmp_max_key, max_key_flag | key_tree->max_flag); 07037 goto end; // Ugly, but efficient 07038 } 07039 else 07040 { 07041 /* The interval for current key part is not c1 <= keyXpartY <= c1 */ 07042 param->is_ror_scan= FALSE; 07043 } 07044 07045 tmp_min_flag=key_tree->min_flag; 07046 tmp_max_flag=key_tree->max_flag; 07047 if (!tmp_min_flag) 07048 key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key, 07049 &tmp_min_flag); 07050 if (!tmp_max_flag) 07051 key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key, 07052 &tmp_max_flag); 07053 min_key_length= (uint) (tmp_min_key- param->min_key); 07054 max_key_length= (uint) (tmp_max_key- param->max_key); 07055 } 07056 else 07057 { 07058 tmp_min_flag=min_key_flag | key_tree->min_flag; 07059 tmp_max_flag=max_key_flag | key_tree->max_flag; 07060 } 07061 07062 keynr=param->real_keynr[idx]; 07063 param->range_count++; 07064 if (!tmp_min_flag && ! tmp_max_flag && 07065 (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && 07066 (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == 07067 HA_NOSAME && 07068 min_key_length == max_key_length && 07069 !memcmp(param->min_key,param->max_key,min_key_length)) 07070 { 07071 tmp=1; // Max one record 07072 param->n_ranges++; 07073 } 07074 else 07075 { 07076 if (param->is_ror_scan) 07077 { 07078 /* 07079 If we get here, the condition on the key was converted to form 07080 "(keyXpart1 = c1) AND ... AND (keyXpart{key_tree->part - 1} = cN) AND 07081 somecond(keyXpart{key_tree->part})" 07082 Check if 07083 somecond is "keyXpart{key_tree->part} = const" and 07084 uncovered "tail" of KeyX parts is either empty or is identical to 07085 first members of clustered primary key. 07086 */ 07087 if (!(min_key_length == max_key_length && 07088 !memcmp(min_key,max_key, (uint) (tmp_max_key - max_key)) && 07089 !key_tree->min_flag && !key_tree->max_flag && 07090 is_key_scan_ror(param, keynr, key_tree->part + 1))) 07091 param->is_ror_scan= FALSE; 07092 } 07093 param->n_ranges++; 07094 07095 if (tmp_min_flag & GEOM_FLAG) 07096 { 07097 key_range min_range; 07098 min_range.key= (byte*) param->min_key; 07099 min_range.length= min_key_length; 07100 /* In this case tmp_min_flag contains the handler-read-function */ 07101 min_range.flag= (ha_rkey_function) (tmp_min_flag ^ GEOM_FLAG); 07102 07103 tmp= param->table->file->records_in_range(keynr, &min_range, 07104 (key_range*) 0); 07105 } 07106 else 07107 { 07108 key_range min_range, max_range; 07109 07110 min_range.key= (byte*) param->min_key; 07111 min_range.length= min_key_length; 07112 min_range.flag= (tmp_min_flag & NEAR_MIN ? HA_READ_AFTER_KEY : 07113 HA_READ_KEY_EXACT); 07114 max_range.key= (byte*) param->max_key; 07115 max_range.length= max_key_length; 07116 max_range.flag= (tmp_max_flag & NEAR_MAX ? 07117 HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY); 07118 tmp=param->table->file->records_in_range(keynr, 07119 (min_key_length ? &min_range : 07120 (key_range*) 0), 07121 (max_key_length ? &max_range : 07122 (key_range*) 0)); 07123 } 07124 } 07125 end: 07126 if (tmp == HA_POS_ERROR) // Impossible range 07127 return tmp; 07128 records+=tmp; 07129 if (key_tree->right != &null_element) 07130 { 07131 /* 07132 There are at least two intervals for current key part, i.e. condition 07133 was converted to something like 07134 (keyXpartY less/equals c1) OR (keyXpartY more/equals c2). 07135 This is not a ROR scan if the key is not Clustered Primary Key. 07136 */ 07137 param->is_ror_scan= FALSE; 07138 tmp=check_quick_keys(param,idx,key_tree->right,min_key,min_key_flag, 07139 max_key,max_key_flag); 07140 if (tmp == HA_POS_ERROR) 07141 return tmp; 07142 records+=tmp; 07143 } 07144 return records; 07145 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static ha_rows check_quick_select | ( | PARAM * | param, | |
| uint | index, | |||
| SEL_ARG * | key_tree, | |||
| bool | update_tbl_stats | |||
| ) | [static] |
Definition at line 6881 of file opt_range.cc.
References st_key::algorithm, check_quick_keys(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, FALSE, st_table::file, HA_KEY_ALG_BTREE, HA_KEY_ALG_UNDEF, HA_KEY_SCAN_NOT_ROR, HA_POS_ERROR, SEL_ARG::IMPOSSIBLE, handler::index_flags(), PARAM::is_ror_scan, key, st_table::key_info, SEL_ARG::KEY_RANGE, PARAM::max_key, PARAM::max_key_part, min, PARAM::min_key, PARAM::n_ranges, SEL_ARG::part, st_table_share::primary_key, handler::primary_key_is_clustered(), st_table::quick_condition_rows, st_table::quick_key_parts, st_table::quick_keys, st_table::quick_n_ranges, st_table::quick_rows, PARAM::range_count, RANGE_OPT_PARAM::real_keynr, records, st_table::s, Bitmap< 64 >::set_bit(), RANGE_OPT_PARAM::table, TRUE, and SEL_ARG::type.
Referenced by get_best_group_min_max(), and get_key_scans_params().
06882 { 06883 ha_rows records; 06884 bool cpk_scan; 06885 uint key; 06886 DBUG_ENTER("check_quick_select"); 06887 06888 param->is_ror_scan= FALSE; 06889 06890 if (!tree) 06891 DBUG_RETURN(HA_POS_ERROR); // Can't use it 06892 param->max_key_part=0; 06893 param->range_count=0; 06894 key= param->real_keynr[idx]; 06895 06896 if (tree->type == SEL_ARG::IMPOSSIBLE) 06897 DBUG_RETURN(0L); // Impossible select. return 06898 if (tree->type != SEL_ARG::KEY_RANGE || tree->part != 0) 06899 DBUG_RETURN(HA_POS_ERROR); // Don't use tree 06900 06901 enum ha_key_alg key_alg= param->table->key_info[key].algorithm; 06902 if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF)) 06903 { 06904 /* Records are not ordered by rowid for other types of indexes. */ 06905 cpk_scan= FALSE; 06906 } 06907 else 06908 { 06909 /* 06910 Clustered PK scan is a special case, check_quick_keys doesn't recognize 06911 CPK scans as ROR scans (while actually any CPK scan is a ROR scan). 06912 */ 06913 cpk_scan= ((param->table->s->primary_key == param->real_keynr[idx]) && 06914 param->table->file->primary_key_is_clustered()); 06915 param->is_ror_scan= !cpk_scan; 06916 } 06917 param->n_ranges= 0; 06918 06919 records=check_quick_keys(param,idx,tree,param->min_key,0,param->max_key,0); 06920 if (records != HA_POS_ERROR) 06921 { 06922 if (update_tbl_stats) 06923 { 06924 param->table->quick_keys.set_bit(key); 06925 param->table->quick_key_parts[key]=param->max_key_part+1; 06926 param->table->quick_n_ranges[key]= param->n_ranges

