1073
Table rows retrieval plan. Range optimizer creates QuickSelectInterface-derived
1074
objects from table read plans.
1076
class TABLE_READ_PLAN
1080
Plan read cost, with or without cost of full row retrieval, depending
1081
on plan creation parameters.
1084
ha_rows records; /* estimate of #rows to be examined */
1087
If true, the scan returns rows in rowid order. This is used only for
1088
scans that can be both ROR and non-ROR.
1093
Create quick select for this plan.
1096
param Parameter from test_quick_select
1097
retrieve_full_rows If true, created quick select will do full record
1099
parent_alloc Memory pool to use, if any.
1102
retrieve_full_rows is ignored by some implementations.
1105
created quick select
1108
virtual optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1109
bool retrieve_full_rows,
1110
MEM_ROOT *parent_alloc=NULL) = 0;
1112
/* Table read plans are allocated on MEM_ROOT and are never deleted */
1113
static void *operator new(size_t size, MEM_ROOT *mem_root)
1114
{ return (void*) alloc_root(mem_root, (uint32_t) size); }
1115
static void operator delete(void *, size_t)
1116
{ TRASH(ptr, size); }
1117
static void operator delete(void *, MEM_ROOT *)
1118
{ /* Never called */ }
1119
virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */
1123
class TRP_ROR_INTERSECT;
1124
class TRP_ROR_UNION;
1125
class TRP_INDEX_MERGE;
1129
Plan for a QuickRangeSelect scan.
1130
TRP_RANGE::make_quick ignores retrieve_full_rows parameter because
1131
QuickRangeSelect doesn't distinguish between 'index only' scans and full
1132
record retrieval scans.
1135
class TRP_RANGE : public TABLE_READ_PLAN
1138
optimizer::SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
1139
uint32_t key_idx; /* key number in Parameter::key */
1141
uint32_t mrr_buf_size;
1143
TRP_RANGE(optimizer::SEL_ARG *key_arg, uint32_t idx_arg, uint32_t mrr_flags_arg)
1147
mrr_flags(mrr_flags_arg)
1149
virtual ~TRP_RANGE() {} /* Remove gcc warning */
1151
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
1153
optimizer::QuickRangeSelect *quick= NULL;
1154
if ((quick= optimizer::get_quick_select(param,
1161
quick->records= records;
1162
quick->read_time= read_cost;
1169
/* Plan for QUICK_ROR_INTERSECT_SELECT scan. */
1171
class TRP_ROR_INTERSECT : public TABLE_READ_PLAN
1174
TRP_ROR_INTERSECT() {} /* Remove gcc warning */
1175
virtual ~TRP_ROR_INTERSECT() {} /* Remove gcc warning */
1176
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1177
bool retrieve_full_rows,
1178
MEM_ROOT *parent_alloc);
1180
/* Array of pointers to ROR range scans used in this intersection */
1181
struct st_ror_scan_info **first_scan;
1182
struct st_ror_scan_info **last_scan; /* End of the above array */
1183
struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */
1184
bool is_covering; /* true if no row retrieval phase is necessary */
1185
double index_scan_costs; /* SUM(cost(index_scan)) */
1190
Plan for QUICK_ROR_UNION_SELECT scan.
1191
QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows
1192
is ignored by make_quick.
1195
class TRP_ROR_UNION : public TABLE_READ_PLAN
1198
TRP_ROR_UNION() {} /* Remove gcc warning */
1199
virtual ~TRP_ROR_UNION() {} /* Remove gcc warning */
1200
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1201
bool retrieve_full_rows,
1202
MEM_ROOT *parent_alloc);
1203
TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
1204
TABLE_READ_PLAN **last_ror; /* end of the above array */
1209
Plan for QuickIndexMergeSelect scan.
1210
QUICK_ROR_INTERSECT_SELECT always retrieves full rows, so retrieve_full_rows
1211
is ignored by make_quick.
1214
class TRP_INDEX_MERGE : public TABLE_READ_PLAN
1217
TRP_INDEX_MERGE() {} /* Remove gcc warning */
1218
virtual ~TRP_INDEX_MERGE() {} /* Remove gcc warning */
1219
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1220
bool retrieve_full_rows,
1221
MEM_ROOT *parent_alloc);
1222
TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
1223
TRP_RANGE **range_scans_end; /* end of the array */
1228
Plan for a QUICK_GROUP_MIN_MAX_SELECT scan.
1231
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
1234
bool have_min, have_max;
1235
KEY_PART_INFO *min_max_arg_part;
1236
uint32_t group_prefix_len;
1237
uint32_t used_key_parts;
1238
uint32_t group_key_parts;
1241
uint32_t key_infix_len;
1242
unsigned char key_infix[MAX_KEY_LENGTH];
1243
SEL_TREE *range_tree; /* Represents all range predicates in the query. */
1244
optimizer::SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
1245
uint32_t param_idx; /* Index of used key in param->key. */
1246
/* Number of records selected by the ranges in index_tree. */
1248
ha_rows quick_prefix_records;
1250
TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
1251
KEY_PART_INFO *min_max_arg_part_arg,
1252
uint32_t group_prefix_len_arg, uint32_t used_key_parts_arg,
1253
uint32_t group_key_parts_arg, KEY *index_info_arg,
1254
uint32_t index_arg, uint32_t key_infix_len_arg,
1255
unsigned char *key_infix_arg,
1256
SEL_TREE *tree_arg, optimizer::SEL_ARG *index_tree_arg,
1257
uint32_t param_idx_arg, ha_rows quick_prefix_records_arg)
1259
have_min(have_min_arg),
1260
have_max(have_max_arg),
1261
min_max_arg_part(min_max_arg_part_arg),
1262
group_prefix_len(group_prefix_len_arg),
1263
used_key_parts(used_key_parts_arg),
1264
group_key_parts(group_key_parts_arg),
1265
index_info(index_info_arg),
1267
key_infix_len(key_infix_len_arg),
1268
range_tree(tree_arg),
1269
index_tree(index_tree_arg),
1270
param_idx(param_idx_arg),
1271
quick_prefix_records(quick_prefix_records_arg)
1274
memcpy(this->key_infix, key_infix_arg, key_infix_len);
1276
virtual ~TRP_GROUP_MIN_MAX() {} /* Remove gcc warning */
1278
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1279
bool retrieve_full_rows,
1280
MEM_ROOT *parent_alloc);
1285
785
Fill param->needed_fields with bitmap of fields used in the query.
7104
Construct new quick select for group queries with min/max.
7107
QUICK_GROUP_MIN_MAX_SELECT::QUICK_GROUP_MIN_MAX_SELECT()
7108
table The table being accessed
7109
join Descriptor of the current query
7110
have_min true if the query selects a MIN function
7111
have_max true if the query selects a MAX function
7112
min_max_arg_part The only argument field of all MIN/MAX functions
7113
group_prefix_len Length of all key parts in the group prefix
7114
prefix_key_parts All key parts in the group prefix
7115
index_info The index chosen for data access
7116
use_index The id of index_info
7117
read_cost Cost of this access method
7118
records Number of records returned
7119
key_infix_len Length of the key infix appended to the group prefix
7120
key_infix Infix of constants from equality predicates
7121
parent_alloc Memory pool for this and quick_prefix_select data
7126
optimizer::QUICK_GROUP_MIN_MAX_SELECT::
7127
QUICK_GROUP_MIN_MAX_SELECT(Table *table,
7131
KEY_PART_INFO *min_max_arg_part_arg,
7132
uint32_t group_prefix_len_arg,
7133
uint32_t group_key_parts_arg,
7134
uint32_t used_key_parts_arg,
7135
KEY *index_info_arg,
7137
double read_cost_arg,
7138
ha_rows records_arg,
7139
uint32_t key_infix_len_arg,
7140
unsigned char *key_infix_arg,
7141
MEM_ROOT *parent_alloc)
7144
index_info(index_info_arg),
7145
group_prefix_len(group_prefix_len_arg),
7146
group_key_parts(group_key_parts_arg),
7147
have_min(have_min_arg),
7148
have_max(have_max_arg),
7149
seen_first_key(false),
7150
min_max_arg_part(min_max_arg_part_arg),
7151
key_infix(key_infix_arg),
7152
key_infix_len(key_infix_len_arg),
7153
min_functions_it(NULL),
7154
max_functions_it(NULL)
7157
cursor= head->cursor;
7159
record= head->record[0];
7160
tmp_record= head->record[1];
7161
read_time= read_cost_arg;
7162
records= records_arg;
7163
used_key_parts= used_key_parts_arg;
7164
real_key_parts= used_key_parts_arg;
7165
real_prefix_len= group_prefix_len + key_infix_len;
7167
min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
7170
We can't have parent_alloc set as the init function can't handle this case
7173
assert(! parent_alloc);
7176
init_sql_alloc(&alloc, join->session->variables.range_alloc_block_size, 0);
7177
join->session->mem_root= &alloc;
7180
memset(&alloc, 0, sizeof(MEM_ROOT)); // ensure that it's not used
7185
Do post-constructor initialization.
7188
QUICK_GROUP_MIN_MAX_SELECT::init()
7191
The method performs initialization that cannot be done in the constructor
7192
such as memory allocations that may fail. It allocates memory for the
7193
group prefix and inifix buffers, and for the lists of MIN/MAX item to be
7194
updated during execution.
7200
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::init()
7202
if (group_prefix) /* Already initialized. */
7205
if (! (last_prefix= (unsigned char*) alloc_root(&alloc, group_prefix_len)))
7208
We may use group_prefix to store keys with all select fields, so allocate
7209
enough space for it.
7211
if (! (group_prefix= (unsigned char*) alloc_root(&alloc,
7212
real_prefix_len + min_max_arg_len)))
7215
if (key_infix_len > 0)
7218
The memory location pointed to by key_infix will be deleted soon, so
7219
allocate a new buffer and copy the key_infix into it.
7221
unsigned char *tmp_key_infix= (unsigned char*) alloc_root(&alloc, key_infix_len);
7222
if (! tmp_key_infix)
7224
memcpy(tmp_key_infix, this->key_infix, key_infix_len);
7225
this->key_infix= tmp_key_infix;
7228
if (min_max_arg_part)
7230
if (my_init_dynamic_array(&min_max_ranges, sizeof(optimizer::QuickRange*), 16, 16))
7235
if (! (min_functions= new List<Item_sum>))
7239
min_functions= NULL;
7242
if (! (max_functions= new List<Item_sum>))
7246
max_functions= NULL;
7248
Item_sum *min_max_item= NULL;
7249
Item_sum **func_ptr= join->sum_funcs;
7250
while ((min_max_item= *(func_ptr++)))
7252
if (have_min && (min_max_item->sum_func() == Item_sum::MIN_FUNC))
7253
min_functions->push_back(min_max_item);
7254
else if (have_max && (min_max_item->sum_func() == Item_sum::MAX_FUNC))
7255
max_functions->push_back(min_max_item);
7260
if (! (min_functions_it= new List_iterator<Item_sum>(*min_functions)))
7266
if (! (max_functions_it= new List_iterator<Item_sum>(*max_functions)))
7271
min_max_ranges.elements= 0;
7277
optimizer::QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
7279
if (cursor->inited != Cursor::NONE)
7281
cursor->ha_index_end();
7283
if (min_max_arg_part)
7285
delete_dynamic(&min_max_ranges);
7287
free_root(&alloc,MYF(0));
7288
delete min_functions_it;
7289
delete max_functions_it;
7290
delete quick_prefix_select;
7295
Eventually create and add a new quick range object.
7298
QUICK_GROUP_MIN_MAX_SELECT::add_range()
7299
sel_range Range object from which a
7302
Construct a new QuickRange object from a SEL_ARG object, and
7303
add it to the array min_max_ranges. If sel_arg is an infinite
7304
range, e.g. (x < 5 or x > 4), then skip it and do not construct
7311
bool optimizer::QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
7313
optimizer::QuickRange *range= NULL;
7314
uint32_t range_flag= sel_range->min_flag | sel_range->max_flag;
7316
/* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
7317
if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
7320
if (! (sel_range->min_flag & NO_MIN_RANGE) &&
7321
! (sel_range->max_flag & NO_MAX_RANGE))
7323
if (sel_range->maybe_null &&
7324
sel_range->min_value[0] && sel_range->max_value[0])
7325
range_flag|= NULL_RANGE; /* IS NULL condition */
7326
else if (memcmp(sel_range->min_value, sel_range->max_value,
7327
min_max_arg_len) == 0)
7328
range_flag|= EQ_RANGE; /* equality condition */
7330
range= new optimizer::QuickRange(sel_range->min_value,
7332
make_keypart_map(sel_range->part),
7333
sel_range->max_value,
7335
make_keypart_map(sel_range->part),
7339
if (insert_dynamic(&min_max_ranges, (unsigned char*)&range))
7346
Opens the ranges if there are more conditions in quick_prefix_select than
7347
the ones used for jumping through the prefixes.
7350
QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges()
7353
quick_prefix_select is made over the conditions on the whole key.
7354
It defines a number of ranges of length x.
7355
However when jumping through the prefixes we use only the the first
7356
few most significant keyparts in the range key. However if there
7357
are more keyparts to follow the ones we are using we must make the
7358
condition on the key inclusive (because x < "ab" means
7359
x[0] < 'a' OR (x[0] == 'a' AND x[1] < 'b').
7360
To achive the above we must turn off the NEAR_MIN/NEAR_MAX
7362
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges()
7364
if (quick_prefix_select &&
7365
group_prefix_len < quick_prefix_select->max_used_key_length)
7367
DYNAMIC_ARRAY *arr= NULL;
7370
for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++)
7372
optimizer::QuickRange *range= NULL;
7374
get_dynamic(arr, (unsigned char*)&range, inx);
7375
range->flag &= ~(NEAR_MIN | NEAR_MAX);
7382
Determine the total number and length of the keys that will be used for
7386
QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
7389
The total length of the keys used for index lookup depends on whether
7390
there are any predicates referencing the min/max argument, and/or if
7391
the min/max argument field can be NULL.
7392
This function does an optimistic analysis whether the search key might
7393
be extended by a constant for the min/max keypart. It is 'optimistic'
7394
because during actual execution it may happen that a particular range
7395
is skipped, and then a shorter key will be used. However this is data
7396
dependent and can't be easily estimated here.
7401
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
7403
max_used_key_length= real_prefix_len;
7404
if (min_max_ranges.elements > 0)
7406
optimizer::QuickRange *cur_range= NULL;
7408
{ /* Check if the right-most range has a lower boundary. */
7409
get_dynamic(&min_max_ranges,
7410
(unsigned char*) &cur_range,
7411
min_max_ranges.elements - 1);
7412
if (! (cur_range->flag & NO_MIN_RANGE))
7414
max_used_key_length+= min_max_arg_len;
7420
{ /* Check if the left-most range has an upper boundary. */
7421
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, 0);
7422
if (! (cur_range->flag & NO_MAX_RANGE))
7424
max_used_key_length+= min_max_arg_len;
7430
else if (have_min && min_max_arg_part &&
7431
min_max_arg_part->field->real_maybe_null())
7434
If a MIN/MAX argument value is NULL, we can quickly determine
7435
that we're in the beginning of the next group, because NULLs
7436
are always < any other value. This allows us to quickly
7437
determine the end of the current group and jump to the next
7438
group (see next_min()) and thus effectively increases the
7441
max_used_key_length+= min_max_arg_len;
7448
Initialize a quick group min/max select for key retrieval.
7451
QUICK_GROUP_MIN_MAX_SELECT::reset()
7454
Initialize the index chosen for access and find and store the prefix
7455
of the last group. The method is expensive since it performs disk access.
7461
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::reset(void)
7465
cursor->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
7466
if ((result= cursor->ha_index_init(index,1)))
7468
if (quick_prefix_select && quick_prefix_select->reset())
7470
result= cursor->index_last(record);
7471
if (result == HA_ERR_END_OF_FILE)
7473
/* Save the prefix of the last group. */
7474
key_copy(last_prefix, record, index_info, group_prefix_len);
7482
Get the next key containing the MIN and/or MAX key for the next group.
7485
QUICK_GROUP_MIN_MAX_SELECT::get_next()
7488
The method finds the next subsequent group of records that satisfies the
7489
query conditions and finds the keys that contain the MIN/MAX values for
7490
the key part referenced by the MIN/MAX function(s). Once a group and its
7491
MIN/MAX values are found, store these values in the Item_sum objects for
7492
the MIN/MAX functions. The rest of the values in the result row are stored
7493
in the Item_field::result_field of each select field. If the query does
7494
not contain MIN and/or MAX functions, then the function only finds the
7495
group prefix, which is a query answer itself.
7498
If both MIN and MAX are computed, then we use the fact that if there is
7499
no MIN key, there can't be a MAX key as well, so we can skip looking
7500
for a MAX key in this case.
7504
HA_ERR_END_OF_FILE if returned all keys
7505
other if some error occurred
7507
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::get_next()
7512
int is_last_prefix= 0;
7515
Loop until a group is found that satisfies all query conditions or the last
7520
result= next_prefix();
7522
Check if this is the last group prefix. Notice that at this point
7523
this->record contains the current prefix in record format.
7527
is_last_prefix= key_cmp(index_info->key_part, last_prefix,
7529
assert(is_last_prefix <= 0);
7533
if (result == HA_ERR_KEY_NOT_FOUND)
7540
min_res= next_min();
7542
update_min_result();
7544
/* If there is no MIN in the group, there is no MAX either. */
7545
if ((have_max && !have_min) ||
7546
(have_max && have_min && (min_res == 0)))
7548
max_res= next_max();
7550
update_max_result();
7551
/* If a MIN was found, a MAX must have been found as well. */
7552
assert(((have_max && !have_min) ||
7553
(have_max && have_min && (max_res == 0))));
7556
If this is just a GROUP BY or DISTINCT without MIN or MAX and there
7557
are equality predicates for the key parts after the group, find the
7558
first sub-group with the extended prefix.
7560
if (! have_min && ! have_max && key_infix_len > 0)
7561
result= cursor->index_read_map(record,
7563
make_prev_keypart_map(real_key_parts),
7566
result= have_min ? min_res : have_max ? max_res : result;
7567
} while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7568
is_last_prefix != 0);
7573
Partially mimic the behavior of end_select_send. Copy the
7574
field data from Item_field::field into Item_field::result_field
7575
of each non-aggregated field (the group fields, and optionally
7576
other fields in non-ANSI SQL mode).
7578
copy_fields(&join->tmp_table_param);
7580
else if (result == HA_ERR_KEY_NOT_FOUND)
7581
result= HA_ERR_END_OF_FILE;
7588
Retrieve the minimal key in the next group.
7591
QUICK_GROUP_MIN_MAX_SELECT::next_min()
7594
Find the minimal key within this group such that the key satisfies the query
7595
conditions and NULL semantics. The found key is loaded into this->record.
7598
Depending on the values of min_max_ranges.elements, key_infix_len, and
7599
whether there is a NULL in the MIN field, this function may directly
7600
return without any data access. In this case we use the key loaded into
7601
this->record by the call to this->next_prefix() just before this call.
7605
HA_ERR_KEY_NOT_FOUND if no MIN key was found that fulfills all conditions.
7606
HA_ERR_END_OF_FILE - "" -
7607
other if some error occurred
7609
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_min()
7613
/* Find the MIN key using the eventually extended group prefix. */
7614
if (min_max_ranges.elements > 0)
7616
if ((result= next_min_in_range()))
7621
/* Apply the constant equality conditions to the non-group select fields */
7622
if (key_infix_len > 0)
7624
if ((result= cursor->index_read_map(record,
7626
make_prev_keypart_map(real_key_parts),
7627
HA_READ_KEY_EXACT)))
7632
If the min/max argument field is NULL, skip subsequent rows in the same
7633
group with NULL in it. Notice that:
7634
- if the first row in a group doesn't have a NULL in the field, no row
7635
in the same group has (because NULL < any other value),
7636
- min_max_arg_part->field->ptr points to some place in 'record'.
7638
if (min_max_arg_part && min_max_arg_part->field->is_null())
7640
/* Find the first subsequent record without NULL in the MIN/MAX field. */
7641
key_copy(tmp_record, record, index_info, 0);
7642
result= cursor->index_read_map(record,
7644
make_keypart_map(real_key_parts),
7647
Check if the new record belongs to the current group by comparing its
7648
prefix with the group's prefix. If it is from the next group, then the
7649
whole group has NULLs in the MIN/MAX field, so use the first record in
7650
the group as a result.
7652
It is possible to reuse this new record as the result candidate for the
7653
next call to next_min(), and to save one lookup in the next call. For
7654
this add a new member 'this->next_group_prefix'.
7658
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7659
key_restore(record, tmp_record, index_info, 0);
7661
else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
7662
result= 0; /* There is a result in any case. */
7667
If the MIN attribute is non-nullable, this->record already contains the
7668
MIN key in the group, so just return.
7675
Retrieve the maximal key in the next group.
7678
QUICK_GROUP_MIN_MAX_SELECT::next_max()
7681
Lookup the maximal key of the group, and store it into this->record.
7685
HA_ERR_KEY_NOT_FOUND if no MAX key was found that fulfills all conditions.
7686
HA_ERR_END_OF_FILE - "" -
7687
other if some error occurred
7689
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_max()
7693
/* Get the last key in the (possibly extended) group. */
7694
if (min_max_ranges.elements > 0)
7695
result= next_max_in_range();
7697
result= cursor->index_read_map(record,
7699
make_prev_keypart_map(real_key_parts),
7700
HA_READ_PREFIX_LAST);
7706
Determine the prefix of the next group.
7709
QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
7712
Determine the prefix of the next group that satisfies the query conditions.
7713
If there is a range condition referencing the group attributes, use a
7714
QuickRangeSelect object to retrieve the *first* key that satisfies the
7715
condition. If there is a key infix of constants, append this infix
7716
immediately after the group attributes. The possibly extended prefix is
7717
stored in this->group_prefix. The first key of the found group is stored in
7718
this->record, on which relies this->next_min().
7722
HA_ERR_KEY_NOT_FOUND if there is no key with the formed prefix
7723
HA_ERR_END_OF_FILE if there are no more keys
7724
other if some error occurred
7726
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
7730
if (quick_prefix_select)
7732
unsigned char *cur_prefix= seen_first_key ? group_prefix : NULL;
7733
if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
7734
make_prev_keypart_map(group_key_parts),
7737
seen_first_key= true;
7741
if (! seen_first_key)
7743
result= cursor->index_first(record);
7746
seen_first_key= true;
7750
/* Load the first key in this group into record. */
7751
result= cursor->index_read_map(record,
7753
make_prev_keypart_map(group_key_parts),
7760
/* Save the prefix of this group for subsequent calls. */
7761
key_copy(group_prefix, record, index_info, group_prefix_len);
7762
/* Append key_infix to group_prefix. */
7763
if (key_infix_len > 0)
7764
memcpy(group_prefix + group_prefix_len,
7773
Find the minimal key in a group that satisfies some range conditions for the
7774
min/max argument field.
7777
QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
7780
Given the sequence of ranges min_max_ranges, find the minimal key that is
7781
in the left-most possible range. If there is no such key, then the current
7782
group does not have a MIN key that satisfies the WHERE clause. If a key is
7783
found, its value is stored in this->record.
7787
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
7789
HA_ERR_END_OF_FILE - "" -
7792
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
7794
ha_rkey_function find_flag;
7795
key_part_map keypart_map;
7796
optimizer::QuickRange *cur_range= NULL;
7797
bool found_null= false;
7798
int result= HA_ERR_KEY_NOT_FOUND;
7799
basic_string<unsigned char> max_key;
7801
max_key.reserve(real_prefix_len + min_max_arg_len);
7803
assert(min_max_ranges.elements > 0);
7805
for (uint32_t range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
7806
{ /* Search from the left-most range to the right. */
7807
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx);
7810
If the current value for the min/max argument is bigger than the right
7811
boundary of cur_range, there is no need to check this range.
7813
if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
7814
(key_cmp(min_max_arg_part,
7815
(const unsigned char*) cur_range->max_key,
7816
min_max_arg_len) == 1))
7819
if (cur_range->flag & NO_MIN_RANGE)
7821
keypart_map= make_prev_keypart_map(real_key_parts);
7822
find_flag= HA_READ_KEY_EXACT;
7826
/* Extend the search key with the lower boundary for this range. */
7827
memcpy(group_prefix + real_prefix_len,
7829
cur_range->min_length);
7830
keypart_map= make_keypart_map(real_key_parts);
7831
find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
7832
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
7833
HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
7836
result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
7839
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7840
(cur_range->flag & (EQ_RANGE | NULL_RANGE)))
7841
continue; /* Check the next range. */
7844
In all other cases (HA_ERR_*, HA_READ_KEY_EXACT with NO_MIN_RANGE,
7845
HA_READ_AFTER_KEY, HA_READ_KEY_OR_NEXT) if the lookup failed for this
7846
range, it can't succeed for any other subsequent range.
7851
/* A key was found. */
7852
if (cur_range->flag & EQ_RANGE)
7853
break; /* No need to perform the checks below for equal keys. */
7855
if (cur_range->flag & NULL_RANGE)
7858
Remember this key, and continue looking for a non-NULL key that
7859
satisfies some other condition.
7861
memcpy(tmp_record, record, head->s->rec_buff_length);
7866
/* Check if record belongs to the current group. */
7867
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7869
result= HA_ERR_KEY_NOT_FOUND;
7873
/* If there is an upper limit, check if the found key is in the range. */
7874
if (! (cur_range->flag & NO_MAX_RANGE) )
7876
/* Compose the MAX key for the range. */
7878
max_key.append(group_prefix, real_prefix_len);
7879
max_key.append(cur_range->max_key, cur_range->max_length);
7880
/* Compare the found key with max_key. */
7881
int cmp_res= key_cmp(index_info->key_part,
7883
real_prefix_len + min_max_arg_len);
7884
if (! (((cur_range->flag & NEAR_MAX) && (cmp_res == -1)) ||
7887
result= HA_ERR_KEY_NOT_FOUND;
7891
/* If we got to this point, the current key qualifies as MIN. */
7892
assert(result == 0);
7896
If there was a key with NULL in the MIN/MAX field, and there was no other
7897
key without NULL from the same group that satisfies some other condition,
7898
then use the key with the NULL.
7900
if (found_null && result)
7902
memcpy(record, tmp_record, head->s->rec_buff_length);
7910
Find the maximal key in a group that satisfies some range conditions for the
7911
min/max argument field.
7914
QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
7917
Given the sequence of ranges min_max_ranges, find the maximal key that is
7918
in the right-most possible range. If there is no such key, then the current
7919
group does not have a MAX key that satisfies the WHERE clause. If a key is
7920
found, its value is stored in this->record.
7924
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
7926
HA_ERR_END_OF_FILE - "" -
7929
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
7931
ha_rkey_function find_flag;
7932
key_part_map keypart_map;
7933
optimizer::QuickRange *cur_range= NULL;
7935
basic_string<unsigned char> min_key;
7936
min_key.reserve(real_prefix_len + min_max_arg_len);
7938
assert(min_max_ranges.elements > 0);
7940
for (uint32_t range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
7941
{ /* Search from the right-most range to the left. */
7942
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx - 1);
7945
If the current value for the min/max argument is smaller than the left
7946
boundary of cur_range, there is no need to check this range.
7948
if (range_idx != min_max_ranges.elements &&
7949
! (cur_range->flag & NO_MIN_RANGE) &&
7950
(key_cmp(min_max_arg_part,
7951
(const unsigned char*) cur_range->min_key,
7952
min_max_arg_len) == -1))
7955
if (cur_range->flag & NO_MAX_RANGE)
7957
keypart_map= make_prev_keypart_map(real_key_parts);
7958
find_flag= HA_READ_PREFIX_LAST;
7962
/* Extend the search key with the upper boundary for this range. */
7963
memcpy(group_prefix + real_prefix_len,
7965
cur_range->max_length);
7966
keypart_map= make_keypart_map(real_key_parts);
7967
find_flag= (cur_range->flag & EQ_RANGE) ?
7968
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
7969
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
7972
result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
7976
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7977
(cur_range->flag & EQ_RANGE))
7978
continue; /* Check the next range. */
7981
In no key was found with this upper bound, there certainly are no keys
7982
in the ranges to the left.
7986
/* A key was found. */
7987
if (cur_range->flag & EQ_RANGE)
7988
return 0; /* No need to perform the checks below for equal keys. */
7990
/* Check if record belongs to the current group. */
7991
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7992
continue; // Row not found
7994
/* If there is a lower limit, check if the found key is in the range. */
7995
if (! (cur_range->flag & NO_MIN_RANGE) )
7997
/* Compose the MIN key for the range. */
7999
min_key.append(group_prefix, real_prefix_len);
8000
min_key.append(cur_range->min_key, cur_range->min_length);
8002
/* Compare the found key with min_key. */
8003
int cmp_res= key_cmp(index_info->key_part,
8005
real_prefix_len + min_max_arg_len);
8006
if (! (((cur_range->flag & NEAR_MIN) && (cmp_res == 1)) ||
8010
/* If we got to this point, the current key qualifies as MAX. */
8013
return HA_ERR_KEY_NOT_FOUND;
8018
Update all MIN function results with the newly found value.
8021
QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
8024
The method iterates through all MIN functions and updates the result value
8025
of each function by calling Item_sum::reset(), which in turn picks the new
8026
result value from this->head->record[0], previously updated by
8027
next_min(). The updated value is stored in a member variable of each of the
8028
Item_sum objects, depending on the value type.
8031
The update must be done separately for MIN and MAX, immediately after
8032
next_min() was called and before next_max() is called, because both MIN and
8033
MAX take their result value from the same buffer this->head->record[0]
8034
(i.e. this->record).
8039
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
8041
Item_sum *min_func= NULL;
8043
min_functions_it->rewind();
8044
while ((min_func= (*min_functions_it)++))
8050
Update all MAX function results with the newly found value.
8053
QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
8056
The method iterates through all MAX functions and updates the result value
8057
of each function by calling Item_sum::reset(), which in turn picks the new
8058
result value from this->head->record[0], previously updated by
8059
next_max(). The updated value is stored in a member variable of each of the
8060
Item_sum objects, depending on the value type.
8063
The update must be done separately for MIN and MAX, immediately after
8064
next_max() was called, because both MIN and MAX take their result value
8065
from the same buffer this->head->record[0] (i.e. this->record).
8070
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
8072
Item_sum *max_func= NULL;
8074
max_functions_it->rewind();
8075
while ((max_func= (*max_functions_it)++))
8081
Append comma-separated list of keys this quick select uses to key_names;
8082
append comma-separated list of corresponding used lengths to used_lengths.
8085
QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths()
8086
key_names [out] Names of used indexes
8087
used_lengths [out] Corresponding lengths of the index names
8090
This method is used by select_describe to extract the names of the
8091
indexes used by a quick select.
8094
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
8095
String *used_lengths)
8099
key_names->append(index_info->name);
8100
length= int64_t2str(max_used_key_length, buf, 10) - buf;
8101
used_lengths->append(buf, length);
6346
optimizer::QuickSelectInterface *optimizer::TRP_RANGE::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
6348
optimizer::QuickRangeSelect *quick= NULL;
6349
if ((quick= optimizer::get_quick_select(param,
6356
quick->records= records;
6357
quick->read_time= read_cost;
8104
6363
static void print_sel_tree(optimizer::Parameter *param, SEL_TREE *tree, key_map *tree_map, const char *)