118
118
#define double2rows(x) ((ha_rows)(x))
120
static int sel_cmp(Field *f,unsigned char *a,unsigned char *b,uint8_t a_flag,uint8_t b_flag);
120
static int sel_cmp(Field *f,uchar *a,uchar *b,uint8_t a_flag,uint8_t b_flag);
122
static unsigned char is_null_string[2]= {1,0};
122
static uchar is_null_string[2]= {1,0};
124
124
class RANGE_OPT_PARAM;
329
329
SEL_ARG(SEL_ARG &);
330
SEL_ARG(Field *,const unsigned char *, const unsigned char *);
331
SEL_ARG(Field *field, uint8_t part, unsigned char *min_value, unsigned char *max_value,
330
SEL_ARG(Field *,const uchar *, const uchar *);
331
SEL_ARG(Field *field, uint8_t part, uchar *min_value, uchar *max_value,
332
332
uint8_t min_flag, uint8_t max_flag, uint8_t maybe_flag);
333
333
SEL_ARG(enum Type type_arg)
334
334
:min_flag(0),elements(1),use_count(1),left(0),right(0),next_key_part(0),
438
438
min_flag=arg->max_flag & NEAR_MAX ? 0 : NEAR_MIN;
440
440
/* returns a number of keypart values (0 or 1) appended to the key buffer */
441
int store_min(uint32_t length, unsigned char **min_key,uint32_t min_key_flag)
441
int store_min(uint length, uchar **min_key,uint min_key_flag)
443
443
/* "(kp1 > c1) AND (kp2 OP c2) AND ..." -> (kp1 > c1) */
444
444
if ((!(min_flag & NO_MIN_RANGE) &&
459
459
/* returns a number of keypart values (0 or 1) appended to the key buffer */
460
int store_max(uint32_t length, unsigned char **max_key, uint32_t max_key_flag)
460
int store_max(uint length, uchar **max_key, uint max_key_flag)
462
462
if (!(max_flag & NO_MAX_RANGE) &&
463
463
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
478
478
/* returns a number of keypart values appended to the key buffer */
479
int store_min_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
479
int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
481
481
SEL_ARG *key_tree= first();
482
uint32_t res= key_tree->store_min(key[key_tree->part].store_length,
482
uint res= key_tree->store_min(key[key_tree->part].store_length,
483
483
range_key, *range_key_flag);
484
484
*range_key_flag|= key_tree->min_flag;
495
495
/* returns a number of keypart values appended to the key buffer */
496
int store_max_key(KEY_PART *key, unsigned char **range_key, uint32_t *range_key_flag)
496
int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
498
498
SEL_ARG *key_tree= last();
499
uint32_t res=key_tree->store_max(key[key_tree->part].store_length,
499
uint res=key_tree->store_max(key[key_tree->part].store_length,
500
500
range_key, *range_key_flag);
501
501
(*range_key_flag)|= key_tree->max_flag;
502
502
if (key_tree->next_key_part &&
630
630
/* The members below are filled/used only after get_mm_tree is done */
631
631
key_map ror_scans_map; /* bitmask of ROR scan-able elements in keys */
632
uint32_t n_ror_scans; /* number of set bits in ror_scans_map */
632
uint n_ror_scans; /* number of set bits in ror_scans_map */
634
634
struct st_ror_scan_info **ror_scans; /* list of ROR key scans */
635
635
struct st_ror_scan_info **ror_scans_end; /* last ROR scan */
682
682
KEY_PART *key[MAX_KEY]; /* First key parts of keys used in the query */
683
683
int64_t baseflag;
684
uint32_t max_key_part;
685
685
/* Number of ranges in the last checked tree->key */
686
uint32_t range_count;
687
unsigned char min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
687
uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
688
688
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
689
689
bool quick; // Don't calulate possible keys
691
uint32_t fields_bitmap_size;
691
uint fields_bitmap_size;
692
692
MY_BITMAP needed_fields; /* bitmask of fields needed by the query */
693
693
MY_BITMAP tmp_covered_fields;
695
695
key_map *needed_reg; /* ptr to SQL_SELECT::needed_reg */
697
uint32_t *imerge_cost_buff; /* buffer for index_merge cost estimates */
698
uint32_t imerge_cost_buff_size; /* size of the buffer */
697
uint *imerge_cost_buff; /* buffer for index_merge cost estimates */
698
uint imerge_cost_buff_size; /* size of the buffer */
700
700
/* true if last checked tree->key can be used for ROR-scan */
701
701
bool is_ror_scan;
702
702
/* Number of ranges in the last checked tree->key */
706
706
class TABLE_READ_PLAN;
720
720
Item_func::Functype type,Item *value);
721
721
static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond);
723
static bool is_key_scan_ror(PARAM *param, uint32_t keynr, uint8_t nparts);
724
static ha_rows check_quick_select(PARAM *param, uint32_t idx, bool index_only,
723
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8_t nparts);
724
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
725
725
SEL_ARG *tree, bool update_tbl_stats,
726
uint32_t *mrr_flags, uint32_t *bufsize,
726
uint *mrr_flags, uint *bufsize,
727
727
COST_VECT *cost);
728
728
//bool update_tbl_stats);
729
/*static ha_rows check_quick_keys(PARAM *param,uint32_t index,SEL_ARG *key_tree,
730
unsigned char *min_key, uint32_t min_key_flag, int,
731
unsigned char *max_key, uint32_t max_key_flag, int);
729
/*static ha_rows check_quick_keys(PARAM *param,uint index,SEL_ARG *key_tree,
730
uchar *min_key, uint min_key_flag, int,
731
uchar *max_key, uint max_key_flag, int);
734
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint32_t index,
735
SEL_ARG *key_tree, uint32_t mrr_flags,
736
uint32_t mrr_buf_size, MEM_ROOT *alloc);
734
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
735
SEL_ARG *key_tree, uint mrr_flags,
736
uint mrr_buf_size, MEM_ROOT *alloc);
737
737
static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
738
738
bool index_read_must_be_used,
739
739
bool update_tbl_stats,
755
755
static void print_sel_tree(PARAM *param, SEL_TREE *tree, key_map *tree_map,
756
756
const char *msg);
757
static void print_ror_scans_arr(Table *table, const char *msg,
757
static void print_ror_scans_arr(TABLE *table, const char *msg,
758
758
struct st_ror_scan_info **start,
759
759
struct st_ror_scan_info **end);
763
763
static SEL_ARG *sel_add(SEL_ARG *key1,SEL_ARG *key2);
764
764
static SEL_ARG *key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2);
765
765
static SEL_ARG *key_and(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
766
uint32_t clone_flag);
767
767
static bool get_range(SEL_ARG **e1,SEL_ARG **e2,SEL_ARG *root1);
768
768
bool get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
769
SEL_ARG *key_tree, unsigned char *min_key,uint32_t min_key_flag,
770
unsigned char *max_key,uint32_t max_key_flag);
769
SEL_ARG *key_tree, uchar *min_key,uint min_key_flag,
770
uchar *max_key,uint max_key_flag);
771
771
static bool eq_tree(SEL_ARG* a,SEL_ARG *b);
773
773
static SEL_ARG null_element(SEL_ARG::IMPOSSIBLE);
774
static bool null_part_in_key(KEY_PART *key_part, const unsigned char *key,
774
static bool null_part_in_key(KEY_PART *key_part, const uchar *key,
776
776
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2, RANGE_OPT_PARAM* param);
828
828
if (trees_next == trees_end)
830
830
const int realloc_ratio= 2; /* Double size for next round */
831
uint32_t old_elements= (trees_end - trees);
832
uint32_t old_size= sizeof(SEL_TREE**) * old_elements;
833
uint32_t new_size= old_size * realloc_ratio;
831
uint old_elements= (trees_end - trees);
832
uint old_size= sizeof(SEL_TREE**) * old_elements;
833
uint new_size= old_size * realloc_ratio;
834
834
SEL_TREE **new_trees;
835
835
if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size)))
999
999
1 = Got some error (out of memory?)
1002
SQL_SELECT *make_select(Table *head, table_map const_tables,
1002
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
1003
1003
table_map read_tables, COND *conds,
1004
1004
bool allow_null_cond,
1063
1063
used_key_parts(0)
1066
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, Table *table, uint32_t key_nr,
1066
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
1067
1067
bool no_alloc, MEM_ROOT *parent_alloc,
1068
1068
bool *create_error)
1069
1069
:free_file(0),cur_range(NULL),last_range(0),dont_free(0)
1145
1145
delete_dynamic(&ranges); /* ranges are allocated in alloc */
1146
1146
free_root(&alloc,MYF(0));
1147
free((char*) column_bitmap.bitmap);
1147
my_free((char*) column_bitmap.bitmap, MYF(MY_ALLOW_ZERO_PTR));
1149
1149
head->column_bitmaps_set(save_read_set, save_write_set);
1150
x_free(mrr_buf_desc);
1156
1155
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
1158
1157
:pk_quick_select(NULL), thd(thd_param)
1160
1159
index= MAX_KEY;
1217
1216
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1219
1218
memset(&alloc, 0, sizeof(MEM_ROOT));
1220
last_rowid= (unsigned char*) alloc_root(parent_alloc? parent_alloc : &alloc,
1219
last_rowid= (uchar*) alloc_root(parent_alloc? parent_alloc : &alloc,
1221
1220
head->file->ref_length);
1493
1492
val2 Second merged select
1496
int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, unsigned char *val1, unsigned char *val2)
1495
int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, uchar *val1, uchar *val2)
1498
1497
QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg;
1499
1498
return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid,
1602
1601
use_count=0; elements=1;
1605
SEL_ARG::SEL_ARG(Field *f,const unsigned char *min_value_arg,
1606
const unsigned char *max_value_arg)
1604
SEL_ARG::SEL_ARG(Field *f,const uchar *min_value_arg,
1605
const uchar *max_value_arg)
1607
1606
:min_flag(0), max_flag(0), maybe_flag(0), maybe_null(f->real_maybe_null()),
1608
elements(1), use_count(1), field(f), min_value((unsigned char*) min_value_arg),
1609
max_value((unsigned char*) max_value_arg), next(0),prev(0),
1607
elements(1), use_count(1), field(f), min_value((uchar*) min_value_arg),
1608
max_value((uchar*) max_value_arg), next(0),prev(0),
1610
1609
next_key_part(0),color(BLACK),type(KEY_RANGE)
1612
1611
left=right= &null_element;
1615
1614
SEL_ARG::SEL_ARG(Field *field_,uint8_t part_,
1616
unsigned char *min_value_, unsigned char *max_value_,
1615
uchar *min_value_, uchar *max_value_,
1617
1616
uint8_t min_flag_,uint8_t max_flag_,uint8_t maybe_flag_)
1618
1617
:min_flag(min_flag_),max_flag(max_flag_),maybe_flag(maybe_flag_),
1619
1618
part(part_),maybe_null(field_->real_maybe_null()), elements(1),use_count(1),
1691
1690
Returns -2 or 2 if the ranges where 'joined' like < 2 and >= 2
1694
static int sel_cmp(Field *field, unsigned char *a, unsigned char *b, uint8_t a_flag,
1693
static int sel_cmp(Field *field, uchar *a, uchar *b, uint8_t a_flag,
1695
1694
uint8_t b_flag)
1778
1777
MAX_KEY if no such index was found.
1781
uint32_t get_index_for_order(Table *table, order_st *order, ha_rows limit)
1780
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit)
1784
uint32_t match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
1783
uint match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
1787
1786
for (ord= order; ord; ord= ord->next)
1910
1909
SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
1911
uint32_t key_idx; /* key number in PARAM::key */
1913
uint32_t mrr_buf_size;
1910
uint key_idx; /* key number in PARAM::key */
1915
TRP_RANGE(SEL_ARG *key_arg, uint32_t idx_arg, uint32_t mrr_flags_arg)
1914
TRP_RANGE(SEL_ARG *key_arg, uint idx_arg, uint mrr_flags_arg)
1916
1915
: key(key_arg), key_idx(idx_arg), mrr_flags(mrr_flags_arg)
1918
1917
virtual ~TRP_RANGE() {} /* Remove gcc warning */
1998
1997
bool have_min, have_max;
1999
1998
KEY_PART_INFO *min_max_arg_part;
2000
uint32_t group_prefix_len;
2001
uint32_t used_key_parts;
2002
uint32_t group_key_parts;
1999
uint group_prefix_len;
2000
uint used_key_parts;
2001
uint group_key_parts;
2003
2002
KEY *index_info;
2005
uint32_t key_infix_len;
2006
unsigned char key_infix[MAX_KEY_LENGTH];
2005
uchar key_infix[MAX_KEY_LENGTH];
2007
2006
SEL_TREE *range_tree; /* Represents all range predicates in the query. */
2008
2007
SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
2009
uint32_t param_idx; /* Index of used key in param->key. */
2008
uint param_idx; /* Index of used key in param->key. */
2010
2009
/* Number of records selected by the ranges in index_tree. */
2012
2011
ha_rows quick_prefix_records;
2014
2013
TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
2015
2014
KEY_PART_INFO *min_max_arg_part_arg,
2016
uint32_t group_prefix_len_arg, uint32_t used_key_parts_arg,
2017
uint32_t group_key_parts_arg, KEY *index_info_arg,
2018
uint32_t index_arg, uint32_t key_infix_len_arg,
2019
unsigned char *key_infix_arg,
2015
uint group_prefix_len_arg, uint used_key_parts_arg,
2016
uint group_key_parts_arg, KEY *index_info_arg,
2017
uint index_arg, uint key_infix_len_arg,
2018
uchar *key_infix_arg,
2020
2019
SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
2021
uint32_t param_idx_arg, ha_rows quick_prefix_records_arg)
2020
uint param_idx_arg, ha_rows quick_prefix_records_arg)
2022
2021
: have_min(have_min_arg), have_max(have_max_arg),
2023
2022
min_max_arg_part(min_max_arg_part_arg),
2024
2023
group_prefix_len(group_prefix_len_arg), used_key_parts(used_key_parts_arg),
2054
2053
static int fill_used_fields_bitmap(PARAM *param)
2056
Table *table= param->table;
2055
TABLE *table= param->table;
2057
2056
my_bitmap_map *tmp;
2059
2058
param->tmp_covered_fields.bitmap= 0;
2060
2059
param->fields_bitmap_size= table->s->column_bitmap_size;
2061
2060
if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
2227
2226
param.key[param.keys]=key_parts;
2228
2227
key_part_info= key_info->key_part;
2229
for (uint32_t part=0 ; part < key_info->key_parts ;
2228
for (uint part=0 ; part < key_info->key_parts ;
2230
2229
part++, key_parts++, key_part_info++)
2232
2231
key_parts->key= param.keys;
2247
2246
/* Calculate cost of full index read for the shortest covering index */
2248
2247
if (!head->covering_keys.is_clear_all())
2250
int key_for_use= head->find_shortest_key(&head->covering_keys);
2249
int key_for_use= find_shortest_key(head, &head->covering_keys);
2251
2250
double key_read_time=
2252
2251
param.table->file->index_only_read_time(key_for_use,
2253
2252
rows2double(records)) +
2286
2285
group_trp= get_best_group_min_max(¶m, tree);
2289
param.table->quick_condition_rows= cmin(group_trp->records,
2288
param.table->quick_condition_rows= min(group_trp->records,
2290
2289
head->file->stats.records);
2291
2290
if (group_trp->read_cost < best_read_time)
2471
2470
bool pk_is_clustered= param->table->file->primary_key_is_clustered();
2472
2471
bool all_scans_ror_able= true;
2473
2472
bool all_scans_rors= true;
2474
uint32_t unique_calc_buff_size;
2473
uint unique_calc_buff_size;
2475
2474
TABLE_READ_PLAN **roru_read_plans;
2476
2475
TABLE_READ_PLAN **cur_roru_plan;
2477
2476
double roru_index_costs;
2578
2577
imerge_trp->read_cost= imerge_cost;
2579
2578
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
2580
imerge_trp->records= cmin(imerge_trp->records,
2579
imerge_trp->records= min(imerge_trp->records,
2581
2580
param->table->file->stats.records);
2582
2581
imerge_trp->range_scans= range_scans;
2583
2582
imerge_trp->range_scans_end= range_scans + n_child_scans;
2690
2689
typedef struct st_ror_scan_info
2692
uint32_t idx; /* # of used key in param->keys */
2693
uint32_t keynr; /* # of used key in table */
2691
uint idx; /* # of used key in param->keys */
2692
uint keynr; /* # of used key in table */
2694
2693
ha_rows records; /* estimate of # records this scan will return */
2696
2695
/* Set of intervals over key fields that will be used for row retrieval. */
2987
2986
double selectivity_mult= 1.0;
2988
2987
KEY_PART_INFO *key_part= info->param->table->key_info[scan->keynr].key_part;
2989
unsigned char key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
2990
unsigned char *key_ptr= key_val;
2988
uchar key_val[MAX_KEY_LENGTH+MAX_FIELD_WIDTH]; /* key values tuple */
2989
uchar *key_ptr= key_val;
2991
2990
SEL_ARG *sel_arg, *tuple_arg= NULL;
2992
2991
key_part_map keypart_map= 0;
2993
2992
bool cur_covered;
3529
3528
bool update_tbl_stats,
3530
3529
double read_time)
3533
3532
SEL_ARG **key,**end, **key_to_read= NULL;
3534
3533
ha_rows best_records= 0;
3535
uint32_t best_mrr_flags= 0, best_buf_size= 0;
3534
uint best_mrr_flags= 0, best_buf_size= 0;
3536
3535
TRP_RANGE* read_plan= NULL;
3538
3537
Note that there may be trees that have type SEL_TREE::KEY but contain no
3549
3548
ha_rows found_records;
3550
3549
COST_VECT cost;
3551
3550
double found_read_time;
3552
uint32_t mrr_flags, buf_size;
3553
uint32_t keynr= param->real_keynr[idx];
3551
uint mrr_flags, buf_size;
3552
uint keynr= param->real_keynr[idx];
3554
3553
if ((*key)->type == SEL_ARG::MAYBE_KEY ||
3555
3554
(*key)->maybe_flag)
3556
3555
param->needed_reg->set_bit(keynr);
4310
4309
get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field,
4311
4310
KEY_PART *key_part, Item_func::Functype type,Item *value)
4313
uint32_t maybe_null=(uint) field->real_maybe_null();
4312
uint maybe_null=(uint) field->real_maybe_null();
4314
4313
bool optimize_range;
4315
4314
SEL_ARG *tree= 0;
4316
4315
MEM_ROOT *alloc= param->mem_root;
4318
4317
ulong orig_sql_mode;
4377
4376
bool like_error;
4378
4377
char buff1[MAX_FIELD_WIDTH];
4379
unsigned char *min_str,*max_str;
4378
uchar *min_str,*max_str;
4380
4379
String tmp(buff1,sizeof(buff1),value->collation.collation),*res;
4381
4380
size_t length, offset, min_length, max_length;
4382
uint32_t field_length= field->pack_length()+maybe_null;
4381
uint field_length= field->pack_length()+maybe_null;
4384
4383
if (!optimize_range)
4545
4544
field->table->in_use->variables.sql_mode= orig_sql_mode;
4546
str= (unsigned char*) alloc_root(alloc, key_part->store_length+1);
4545
str= (uchar*) alloc_root(alloc, key_part->store_length+1);
4549
4548
if (maybe_null)
4550
*str= (unsigned char) field->is_real_null(); // Set to 1 if null
4549
*str= (uchar) field->is_real_null(); // Set to 1 if null
4551
4550
field->get_key_image(str+maybe_null, key_part->length,
4552
4551
key_part->image_type);
4553
4552
if (!(tree= new (alloc) SEL_ARG(field, str, str)))
4913
4912
/* one tree is index merge tree and another is range tree */
4914
4913
if (tree1->merges.is_empty())
4915
std::swap(tree1, tree2);
4914
swap_variables(SEL_TREE*, tree1, tree2);
4917
4916
if (param->remove_jump_scans && remove_nonrange_trees(param, tree2))
4918
4917
return(new SEL_TREE(SEL_TREE::ALWAYS));
5014
5013
key2->type != SEL_ARG::MAYBE_KEY) ||
5015
5014
key1->type == SEL_ARG::MAYBE_KEY)
5016
5015
{ // Put simple key in key2
5017
std::swap(key1, key2);
5016
swap_variables(SEL_ARG *, key1, key2);
5018
5017
clone_flag=swap_clone_flag(clone_flag);
5876
5875
Pointers in min and max keys. They point to right-after-end of key
5877
5876
images. The 0-th entry has these pointing to key tuple start.
5879
unsigned char *min_key, *max_key;
5878
uchar *min_key, *max_key;
5882
5881
Flags, for {keypart0, keypart1, ... this_keypart} subtuple.
5883
5882
min_key_flag may have NULL_RANGE set.
5885
uint32_t min_key_flag, max_key_flag;
5884
uint min_key_flag, max_key_flag;
5887
5886
/* Number of key parts */
5888
uint32_t min_key_parts, max_key_parts;
5887
uint min_key_parts, max_key_parts;
5889
5888
SEL_ARG *key_tree;
5890
5889
} RANGE_SEQ_ENTRY;
5896
5895
typedef struct st_sel_arg_range_seq
5898
uint32_t keyno; /* index of used tree in SEL_TREE structure */
5899
uint32_t real_keyno; /* Number of the index in tables */
5897
uint keyno; /* index of used tree in SEL_TREE structure */
5898
uint real_keyno; /* Number of the index in tables */
5901
5900
SEL_ARG *start; /* Root node of the traversed SEL_ARG* graph */
5923
5922
range_seq_t sel_arg_range_seq_init(void *init_param,
5924
uint32_t n_ranges __attribute__((unused)),
5925
uint32_t flags __attribute__((unused)))
5923
uint n_ranges __attribute__((unused)),
5924
uint flags __attribute__((unused)))
5927
5926
SEL_ARG_RANGE_SEQ *seq= (SEL_ARG_RANGE_SEQ*)init_param;
5928
5927
seq->at_start= true;
6047
6046
RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
6048
uint32_t min_key_length= cur->min_key - seq->param->min_key;
6049
uint32_t max_key_length= cur->max_key - seq->param->max_key;
6050
uint32_t len= cur->min_key - cur[-1].min_key;
6047
uint min_key_length= cur->min_key - seq->param->min_key;
6048
uint max_key_length= cur->max_key - seq->param->max_key;
6049
uint len= cur->min_key - cur[-1].min_key;
6051
6050
if (!(min_key_length == max_key_length &&
6052
6051
!memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
6053
6052
!key_tree->min_flag && !key_tree->max_flag))
6164
ha_rows check_quick_select(PARAM *param, uint32_t idx, bool index_only,
6163
ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
6165
6164
SEL_ARG *tree, bool update_tbl_stats,
6166
uint32_t *mrr_flags, uint32_t *bufsize, COST_VECT *cost)
6165
uint *mrr_flags, uint *bufsize, COST_VECT *cost)
6168
6167
SEL_ARG_RANGE_SEQ seq;
6169
6168
RANGE_SEQ_IF seq_if = {sel_arg_range_seq_init, sel_arg_range_seq_next};
6170
6169
handler *file= param->table->file;
6172
uint32_t keynr= param->real_keynr[idx];
6171
uint keynr= param->real_keynr[idx];
6174
6173
/* Handle cases when we don't have a valid non-empty list of range */
6215
6214
param->table->quick_key_parts[keynr]=param->max_key_part+1;
6216
6215
param->table->quick_n_ranges[keynr]= param->range_count;
6217
6216
param->table->quick_condition_rows=
6218
cmin(param->table->quick_condition_rows, rows);
6217
min(param->table->quick_condition_rows, rows);
6221
6220
/* Figure out if the key scan is ROR (returns rows in ROWID order) or not */
6277
6276
false Otherwise
6280
static bool is_key_scan_ror(PARAM *param, uint32_t keynr, uint8_t nparts)
6279
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8_t nparts)
6282
6281
KEY *table_key= param->table->key_info + keynr;
6283
6282
KEY_PART_INFO *key_part= table_key->key_part + nparts;
6284
6283
KEY_PART_INFO *key_part_end= (table_key->key_part +
6285
6284
table_key->key_parts);
6288
6287
for (KEY_PART_INFO *kp= table_key->key_part; kp < key_part; kp++)
6341
6340
QUICK_RANGE_SELECT *
6342
get_quick_select(PARAM *param,uint32_t idx,SEL_ARG *key_tree, uint32_t mrr_flags,
6343
uint32_t mrr_buf_size, MEM_ROOT *parent_alloc)
6341
get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree, uint mrr_flags,
6342
uint mrr_buf_size, MEM_ROOT *parent_alloc)
6345
6344
QUICK_RANGE_SELECT *quick;
6346
6345
bool create_err= false;
6380
6379
get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
6381
SEL_ARG *key_tree, unsigned char *min_key,uint32_t min_key_flag,
6382
unsigned char *max_key, uint32_t max_key_flag)
6380
SEL_ARG *key_tree, uchar *min_key,uint min_key_flag,
6381
uchar *max_key, uint max_key_flag)
6384
6383
QUICK_RANGE *range;
6386
6385
int min_part= key_tree->part-1, // # of keypart values in min_key buffer
6387
6386
max_part= key_tree->part-1; // # of keypart values in max_key buffer
6392
6391
min_key,min_key_flag, max_key, max_key_flag))
6395
unsigned char *tmp_min_key=min_key,*tmp_max_key=max_key;
6394
uchar *tmp_min_key=min_key,*tmp_max_key=max_key;
6396
6395
min_part+= key_tree->store_min(key[key_tree->part].store_length,
6397
6396
&tmp_min_key,min_key_flag);
6398
6397
max_part+= key_tree->store_max(key[key_tree->part].store_length,
6413
6412
goto end; // Ugly, but efficient
6416
uint32_t tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
6415
uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
6417
6416
if (!tmp_min_flag)
6418
6417
min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
6419
6418
&tmp_min_flag);
6477
6476
set_if_bigger(quick->max_used_key_length, range->min_length);
6478
6477
set_if_bigger(quick->max_used_key_length, range->max_length);
6479
6478
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
6480
if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
6479
if (insert_dynamic(&quick->ranges, (uchar*) &range))
6523
6522
false Otherwise
6526
static bool null_part_in_key(KEY_PART *key_part, const unsigned char *key, uint32_t length)
6525
static bool null_part_in_key(KEY_PART *key_part, const uchar *key, uint length)
6528
for (const unsigned char *end=key+length ;
6527
for (const uchar *end=key+length ;
6530
6529
key+= key_part++->store_length)
6600
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, Table *table,
6599
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
6601
6600
TABLE_REF *ref, ha_rows records)
6603
6602
MEM_ROOT *old_root, *alloc;
7041
7040
range_seq_t quick_range_seq_init(void *init_param,
7042
uint32_t n_ranges __attribute__((unused)),
7043
uint32_t flags __attribute__((unused)))
7041
uint n_ranges __attribute__((unused)),
7042
uint flags __attribute__((unused)))
7045
7044
QUICK_RANGE_SELECT *quick= (QUICK_RANGE_SELECT*)init_param;
7046
7045
quick->qr_traversal_ctx.first= (QUICK_RANGE**)quick->ranges.buffer;
7116
7115
Reference to range_flag associated with range number #idx
7119
uint16_t &mrr_persistent_flag_storage(range_seq_t seq, uint32_t idx)
7118
uint16_t &mrr_persistent_flag_storage(range_seq_t seq, uint idx)
7121
7120
QUICK_RANGE_SEQ_CTX *ctx= (QUICK_RANGE_SEQ_CTX*)seq;
7122
7121
return ctx->first[idx]->flag;
7222
7221
other if some error occurred
7225
int QUICK_RANGE_SELECT::get_next_prefix(uint32_t prefix_length,
7224
int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length,
7226
7225
key_part_map keypart_map,
7227
unsigned char *cur_prefix)
7250
7249
last_range= *(cur_range++);
7252
start_key.key= (const unsigned char*) last_range->min_key;
7253
start_key.length= cmin(last_range->min_length, (uint16_t)prefix_length);
7251
start_key.key= (const uchar*) last_range->min_key;
7252
start_key.length= min(last_range->min_length, prefix_length);
7254
7253
start_key.keypart_map= last_range->min_keypart_map & keypart_map;
7255
7254
start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
7256
7255
(last_range->flag & EQ_RANGE) ?
7257
7256
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
7258
end_key.key= (const unsigned char*) last_range->max_key;
7259
end_key.length= cmin(last_range->max_length, (uint16_t)prefix_length);
7257
end_key.key= (const uchar*) last_range->max_key;
7258
end_key.length= min(last_range->max_length, prefix_length);
7260
7259
end_key.keypart_map= last_range->max_keypart_map & keypart_map;
7262
7261
We use READ_AFTER_KEY here because if we are reading on a key
7332
7331
QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q,
7333
uint32_t used_key_parts_arg __attribute__((unused)),
7332
uint used_key_parts_arg __attribute__((unused)),
7334
7333
bool *create_err __attribute__((unused)))
7335
7334
:QUICK_RANGE_SELECT(*q), rev_it(rev_ranges)
7445
7444
return 0; /* key can't be to large */
7447
7446
KEY_PART *key_part=key_parts;
7448
uint32_t store_length;
7450
for (unsigned char *key=range_arg->max_key, *end=key+range_arg->max_length;
7449
for (uchar *key=range_arg->max_key, *end=key+range_arg->max_length;
7452
7451
key+= store_length, key_part++)
7680
7679
* Implementation of QUICK_GROUP_MIN_MAX_SELECT
7681
7680
*******************************************************************************/
7683
static inline uint32_t get_field_keypart(KEY *index, Field *field);
7684
static inline SEL_ARG * get_index_range_tree(uint32_t index, SEL_TREE* range_tree,
7685
PARAM *param, uint32_t *param_idx);
7682
static inline uint get_field_keypart(KEY *index, Field *field);
7683
static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
7684
PARAM *param, uint *param_idx);
7686
7685
static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
7687
7686
KEY_PART_INFO *first_non_group_part,
7688
7687
KEY_PART_INFO *min_max_arg_part,
7689
7688
KEY_PART_INFO *last_part, THD *thd,
7690
unsigned char *key_infix, uint32_t *key_infix_len,
7689
uchar *key_infix, uint *key_infix_len,
7691
7690
KEY_PART_INFO **first_non_infix_part);
7693
7692
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
7694
7693
Field::imagetype image_type);
7697
cost_group_min_max(Table* table, KEY *index_info, uint32_t used_key_parts,
7698
uint32_t group_key_parts, SEL_TREE *range_tree,
7696
cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
7697
uint group_key_parts, SEL_TREE *range_tree,
7699
7698
SEL_ARG *index_tree, ha_rows quick_prefix_records,
7700
7699
bool have_min, bool have_max,
7701
7700
double *read_cost, ha_rows *records);
7835
7834
THD *thd= param->thd;
7836
7835
JOIN *join= thd->lex->current_select->join;
7837
Table *table= param->table;
7836
TABLE *table= param->table;
7838
7837
bool have_min= false; /* true if there is a MIN function. */
7839
7838
bool have_max= false; /* true if there is a MAX function. */
7840
7839
Item_field *min_max_arg_item= NULL; // The argument of all MIN/MAX functions
7841
7840
KEY_PART_INFO *min_max_arg_part= NULL; /* The corresponding keypart. */
7842
uint32_t group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
7841
uint group_prefix_len= 0; /* Length (in bytes) of the key prefix. */
7843
7842
KEY *index_info= NULL; /* The index chosen for data access. */
7844
uint32_t index= 0; /* The id of the chosen index. */
7845
uint32_t group_key_parts= 0; // Number of index key parts in the group prefix.
7846
uint32_t used_key_parts= 0; /* Number of index key parts used for access. */
7847
unsigned char key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
7848
uint32_t key_infix_len= 0; /* Length of key_infix. */
7843
uint index= 0; /* The id of the chosen index. */
7844
uint group_key_parts= 0; // Number of index key parts in the group prefix.
7845
uint used_key_parts= 0; /* Number of index key parts used for access. */
7846
uchar key_infix[MAX_KEY_LENGTH]; /* Constants from equality predicates.*/
7847
uint key_infix_len= 0; /* Length of key_infix. */
7849
7848
TRP_GROUP_MIN_MAX *read_plan= NULL; /* The eventually constructed TRP. */
7850
uint32_t key_part_nr;
7851
order_st *tmp_group;
7853
7852
Item_field *item_field;
7926
7925
KEY_PART_INFO *last_part= NULL;
7927
7926
KEY_PART_INFO *first_non_group_part= NULL;
7928
7927
KEY_PART_INFO *first_non_infix_part= NULL;
7929
uint32_t key_infix_parts= 0;
7930
uint32_t cur_group_key_parts= 0;
7931
uint32_t cur_group_prefix_len= 0;
7928
uint key_infix_parts= 0;
7929
uint cur_group_key_parts= 0;
7930
uint cur_group_prefix_len= 0;
7932
7931
/* Cost-related variables for the best index so far. */
7933
7932
double best_read_cost= DBL_MAX;
7934
7933
ha_rows best_records= 0;
7935
7934
SEL_ARG *best_index_tree= NULL;
7936
7935
ha_rows best_quick_prefix_records= 0;
7937
uint32_t best_param_idx= 0;
7936
uint best_param_idx= 0;
7938
7937
double cur_read_cost= DBL_MAX;
7939
7938
ha_rows cur_records;
7940
7939
SEL_ARG *cur_index_tree= NULL;
7941
7940
ha_rows cur_quick_prefix_records= 0;
7942
uint32_t cur_param_idx=MAX_KEY;
7941
uint cur_param_idx=MAX_KEY;
7943
7942
key_map cur_used_key_parts;
7944
uint32_t pk= param->table->s->primary_key;
7943
uint pk= param->table->s->primary_key;
7946
for (uint32_t cur_index= 0 ; cur_index_info != cur_index_info_end ;
7945
for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
7947
7946
cur_index_info++, cur_index++)
7949
7948
/* Check (B1) - if current index is covering. */
8008
8007
Check (GA2) if this is a DISTINCT query.
8009
If GA2, then Store a new order_st object in group_fields_array at the
8010
position of the key part of item_field->field. Thus we get the order_st
8008
If GA2, then Store a new ORDER object in group_fields_array at the
8009
position of the key part of item_field->field. Thus we get the ORDER
8011
8010
objects for each field ordered as the corresponding key parts.
8012
Later group_fields_array of order_st objects is used to convert the query
8011
Later group_fields_array of ORDER objects is used to convert the query
8013
8012
to a GROUP query.
8015
8014
else if (join->select_distinct)
8017
8016
select_items_it.rewind();
8018
8017
cur_used_key_parts.clear_all();
8019
uint32_t max_key_part= 0;
8018
uint max_key_part= 0;
8020
8019
while ((item= select_items_it++))
8022
8021
item_field= (Item_field*) item; /* (SA5) already checked above. */
8034
8033
cur_group_prefix_len+= cur_part->store_length;
8035
8034
cur_used_key_parts.set_bit(key_part_nr);
8036
8035
++cur_group_key_parts;
8037
max_key_part= cmax(max_key_part,key_part_nr);
8036
max_key_part= max(max_key_part,key_part_nr);
8040
8039
Check that used key parts forms a prefix of the index.
8287
8286
Item_func *pred= (Item_func*) cond;
8288
8287
Item **arguments= pred->arguments();
8290
for (uint32_t arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
8289
for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
8292
8291
cur_arg= arguments[arg_idx]->real_item();
8293
8292
if (cur_arg->type() == Item::FIELD_ITEM)
8395
8394
KEY_PART_INFO *min_max_arg_part,
8396
8395
KEY_PART_INFO *last_part,
8397
8396
THD *thd __attribute__((unused)),
8398
unsigned char *key_infix, uint32_t *key_infix_len,
8397
uchar *key_infix, uint *key_infix_len,
8399
8398
KEY_PART_INFO **first_non_infix_part)
8401
8400
SEL_ARG *cur_range;
8436
8435
(cur_range->min_flag & NEAR_MIN) || (cur_range->max_flag & NEAR_MAX))
8439
uint32_t field_length= cur_part->store_length;
8438
uint field_length= cur_part->store_length;
8440
8439
if ((cur_range->maybe_null &&
8441
8440
cur_range->min_value[0] && cur_range->max_value[0]) ||
8442
8441
!memcmp(cur_range->min_value, cur_range->max_value, field_length))
8511
8510
Pointer to the SEL_ARG subtree that corresponds to index.
8514
SEL_ARG * get_index_range_tree(uint32_t index, SEL_TREE* range_tree, PARAM *param,
8515
uint32_t *param_idx)
8513
SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree, PARAM *param,
8517
uint32_t idx= 0; /* Index nr in param->key_parts */
8516
uint idx= 0; /* Index nr in param->key_parts */
8518
8517
while (idx < param->keys)
8520
8519
if (index == param->real_keynr[idx])
8589
void cost_group_min_max(Table* table, KEY *index_info, uint32_t used_key_parts,
8590
uint32_t group_key_parts, SEL_TREE *range_tree,
8588
void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
8589
uint group_key_parts, SEL_TREE *range_tree,
8591
8590
SEL_ARG *index_tree __attribute__((unused)),
8592
8591
ha_rows quick_prefix_records,
8593
8592
bool have_min, bool have_max,
8594
8593
double *read_cost, ha_rows *records)
8596
8595
ha_rows table_records;
8597
uint32_t num_groups;
8598
uint32_t num_blocks;
8599
uint32_t keys_per_block;
8600
uint32_t keys_per_group;
8601
uint32_t keys_per_subgroup; /* Average number of keys in sub-groups */
8598
uint keys_per_block;
8599
uint keys_per_group;
8600
uint keys_per_subgroup; /* Average number of keys in sub-groups */
8602
8601
/* formed by a key infix. */
8603
8602
double p_overlap; /* Probability that a sub-group overlaps two blocks. */
8604
8603
double quick_prefix_selectivity;
8640
8639
double blocks_per_group= (double) num_blocks / (double) num_groups;
8641
8640
p_overlap= (blocks_per_group * (keys_per_subgroup - 1)) / keys_per_group;
8642
p_overlap= cmin(p_overlap, 1.0);
8641
p_overlap= min(p_overlap, 1.0);
8644
io_cost= (double) cmin(num_groups * (1 + p_overlap), (double)num_blocks);
8643
io_cost= (double) min(num_groups * (1 + p_overlap), num_blocks);
8647
8646
io_cost= (keys_per_group > keys_per_block) ?
8785
8784
QUICK_GROUP_MIN_MAX_SELECT::
8786
QUICK_GROUP_MIN_MAX_SELECT(Table *table, JOIN *join_arg, bool have_min_arg,
8785
QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
8787
8786
bool have_max_arg,
8788
8787
KEY_PART_INFO *min_max_arg_part_arg,
8789
uint32_t group_prefix_len_arg, uint32_t group_key_parts_arg,
8790
uint32_t used_key_parts_arg, KEY *index_info_arg,
8791
uint32_t use_index, double read_cost_arg,
8792
ha_rows records_arg, uint32_t key_infix_len_arg,
8793
unsigned char *key_infix_arg, MEM_ROOT *parent_alloc)
8788
uint group_prefix_len_arg, uint group_key_parts_arg,
8789
uint used_key_parts_arg, KEY *index_info_arg,
8790
uint use_index, double read_cost_arg,
8791
ha_rows records_arg, uint key_infix_len_arg,
8792
uchar *key_infix_arg, MEM_ROOT *parent_alloc)
8794
8793
:join(join_arg), index_info(index_info_arg),
8795
8794
group_prefix_len(group_prefix_len_arg),
8796
8795
group_key_parts(group_key_parts_arg), have_min(have_min_arg),
8849
8848
if (group_prefix) /* Already initialized. */
8852
if (!(last_prefix= (unsigned char*) alloc_root(&alloc, group_prefix_len)))
8851
if (!(last_prefix= (uchar*) alloc_root(&alloc, group_prefix_len)))
8855
8854
We may use group_prefix to store keys with all select fields, so allocate
8856
8855
enough space for it.
8858
if (!(group_prefix= (unsigned char*) alloc_root(&alloc,
8857
if (!(group_prefix= (uchar*) alloc_root(&alloc,
8859
8858
real_prefix_len + min_max_arg_len)))
8865
8864
The memory location pointed to by key_infix will be deleted soon, so
8866
8865
allocate a new buffer and copy the key_infix into it.
8868
unsigned char *tmp_key_infix= (unsigned char*) alloc_root(&alloc, key_infix_len);
8867
uchar *tmp_key_infix= (uchar*) alloc_root(&alloc, key_infix_len);
8869
8868
if (!tmp_key_infix)
8871
8870
memcpy(tmp_key_infix, this->key_infix, key_infix_len);
8956
8955
bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
8958
8957
QUICK_RANGE *range;
8959
uint32_t range_flag= sel_range->min_flag | sel_range->max_flag;
8958
uint range_flag= sel_range->min_flag | sel_range->max_flag;
8961
8960
/* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
8962
8961
if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
9008
9007
group_prefix_len < quick_prefix_select->max_used_key_length)
9010
9009
DYNAMIC_ARRAY *arr;
9013
9012
for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++)
9015
9014
QUICK_RANGE *range;
9017
get_dynamic(arr, (unsigned char*)&range, inx);
9016
get_dynamic(arr, (uchar*)&range, inx);
9018
9017
range->flag &= ~(NEAR_MIN | NEAR_MAX);
9050
9049
QUICK_RANGE *cur_range;
9052
9051
{ /* Check if the right-most range has a lower boundary. */
9053
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range,
9052
get_dynamic(&min_max_ranges, (uchar*)&cur_range,
9054
9053
min_max_ranges.elements - 1);
9055
9054
if (!(cur_range->flag & NO_MIN_RANGE))
9063
9062
{ /* Check if the left-most range has an upper boundary. */
9064
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, 0);
9063
get_dynamic(&min_max_ranges, (uchar*)&cur_range, 0);
9065
9064
if (!(cur_range->flag & NO_MAX_RANGE))
9067
9066
max_used_key_length+= min_max_arg_len;
9441
9440
assert(min_max_ranges.elements > 0);
9443
for (uint32_t range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
9442
for (uint range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
9444
9443
{ /* Search from the left-most range to the right. */
9445
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx);
9444
get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx);
9448
9447
If the current value for the min/max argument is bigger than the right
9449
9448
boundary of cur_range, there is no need to check this range.
9451
9450
if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
9452
(key_cmp(min_max_arg_part, (const unsigned char*) cur_range->max_key,
9451
(key_cmp(min_max_arg_part, (const uchar*) cur_range->max_key,
9453
9452
min_max_arg_len) == 1))
9510
9509
if ( !(cur_range->flag & NO_MAX_RANGE) )
9512
9511
/* Compose the MAX key for the range. */
9513
unsigned char *max_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
9512
uchar *max_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len);
9514
9513
memcpy(max_key, group_prefix, real_prefix_len);
9515
9514
memcpy(max_key + real_prefix_len, cur_range->max_key,
9516
9515
cur_range->max_length);
9572
9571
assert(min_max_ranges.elements > 0);
9574
for (uint32_t range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
9573
for (uint range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
9575
9574
{ /* Search from the right-most range to the left. */
9576
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx - 1);
9575
get_dynamic(&min_max_ranges, (uchar*)&cur_range, range_idx - 1);
9579
9578
If the current value for the min/max argument is smaller than the left
9582
9581
if (range_idx != min_max_ranges.elements &&
9583
9582
!(cur_range->flag & NO_MIN_RANGE) &&
9584
(key_cmp(min_max_arg_part, (const unsigned char*) cur_range->min_key,
9583
(key_cmp(min_max_arg_part, (const uchar*) cur_range->min_key,
9585
9584
min_max_arg_len) == -1))
9627
9626
if ( !(cur_range->flag & NO_MIN_RANGE) )
9629
9628
/* Compose the MIN key for the range. */
9630
unsigned char *min_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
9629
uchar *min_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len);
9631
9630
memcpy(min_key, group_prefix, real_prefix_len);
9632
9631
memcpy(min_key + real_prefix_len, cur_range->min_key,
9633
9632
cur_range->min_length);
9766
static void print_ror_scans_arr(Table *table,
9765
static void print_ror_scans_arr(TABLE *table,
9767
9766
const char *msg __attribute__((unused)),
9768
9767
struct st_ror_scan_info **start,
9769
9768
struct st_ror_scan_info **end)