1069
Table rows retrieval plan. Range optimizer creates QuickSelectInterface-derived
1070
objects from table read plans.
1072
class TABLE_READ_PLAN
1076
Plan read cost, with or without cost of full row retrieval, depending
1077
on plan creation parameters.
1080
ha_rows records; /* estimate of #rows to be examined */
1083
If true, the scan returns rows in rowid order. This is used only for
1084
scans that can be both ROR and non-ROR.
1089
Create quick select for this plan.
1092
param Parameter from test_quick_select
1093
retrieve_full_rows If true, created quick select will do full record
1095
parent_alloc Memory pool to use, if any.
1098
retrieve_full_rows is ignored by some implementations.
1101
created quick select
1104
virtual optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1105
bool retrieve_full_rows,
1106
MEM_ROOT *parent_alloc=NULL) = 0;
1108
/* Table read plans are allocated on MEM_ROOT and are never deleted */
1109
static void *operator new(size_t size, MEM_ROOT *mem_root)
1110
{ return (void*) alloc_root(mem_root, (uint32_t) size); }
1111
static void operator delete(void *, size_t)
1112
{ TRASH(ptr, size); }
1113
static void operator delete(void *, MEM_ROOT *)
1114
{ /* Never called */ }
1115
virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */
1119
class TRP_ROR_INTERSECT;
1120
class TRP_ROR_UNION;
1121
class TRP_INDEX_MERGE;
1125
Plan for a QuickRangeSelect scan.
1126
TRP_RANGE::make_quick ignores retrieve_full_rows parameter because
1127
QuickRangeSelect doesn't distinguish between 'index only' scans and full
1128
record retrieval scans.
1131
class TRP_RANGE : public TABLE_READ_PLAN
1134
optimizer::SEL_ARG *key; /* set of intervals to be used in "range" method retrieval */
1135
uint32_t key_idx; /* key number in Parameter::key */
1137
uint32_t mrr_buf_size;
1139
TRP_RANGE(optimizer::SEL_ARG *key_arg, uint32_t idx_arg, uint32_t mrr_flags_arg)
1143
mrr_flags(mrr_flags_arg)
1145
virtual ~TRP_RANGE() {} /* Remove gcc warning */
1147
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
1149
optimizer::QuickRangeSelect *quick= NULL;
1150
if ((quick= optimizer::get_quick_select(param,
1157
quick->records= records;
1158
quick->read_time= read_cost;
1165
/* Plan for QUICK_ROR_INTERSECT_SELECT scan. */
1167
class TRP_ROR_INTERSECT : public TABLE_READ_PLAN
1170
TRP_ROR_INTERSECT() {} /* Remove gcc warning */
1171
virtual ~TRP_ROR_INTERSECT() {} /* Remove gcc warning */
1172
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1173
bool retrieve_full_rows,
1174
MEM_ROOT *parent_alloc);
1176
/* Array of pointers to ROR range scans used in this intersection */
1177
struct st_ror_scan_info **first_scan;
1178
struct st_ror_scan_info **last_scan; /* End of the above array */
1179
struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */
1180
bool is_covering; /* true if no row retrieval phase is necessary */
1181
double index_scan_costs; /* SUM(cost(index_scan)) */
1186
Plan for QUICK_ROR_UNION_SELECT scan.
1187
QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows
1188
is ignored by make_quick.
1191
class TRP_ROR_UNION : public TABLE_READ_PLAN
1194
TRP_ROR_UNION() {} /* Remove gcc warning */
1195
virtual ~TRP_ROR_UNION() {} /* Remove gcc warning */
1196
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1197
bool retrieve_full_rows,
1198
MEM_ROOT *parent_alloc);
1199
TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
1200
TABLE_READ_PLAN **last_ror; /* end of the above array */
1205
Plan for QuickIndexMergeSelect scan.
1206
QUICK_ROR_INTERSECT_SELECT always retrieves full rows, so retrieve_full_rows
1207
is ignored by make_quick.
1210
class TRP_INDEX_MERGE : public TABLE_READ_PLAN
1213
TRP_INDEX_MERGE() {} /* Remove gcc warning */
1214
virtual ~TRP_INDEX_MERGE() {} /* Remove gcc warning */
1215
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1216
bool retrieve_full_rows,
1217
MEM_ROOT *parent_alloc);
1218
TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
1219
TRP_RANGE **range_scans_end; /* end of the array */
1224
Plan for a QUICK_GROUP_MIN_MAX_SELECT scan.
1227
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
1230
bool have_min, have_max;
1231
KEY_PART_INFO *min_max_arg_part;
1232
uint32_t group_prefix_len;
1233
uint32_t used_key_parts;
1234
uint32_t group_key_parts;
1237
uint32_t key_infix_len;
1238
unsigned char key_infix[MAX_KEY_LENGTH];
1239
SEL_TREE *range_tree; /* Represents all range predicates in the query. */
1240
optimizer::SEL_ARG *index_tree; /* The SEL_ARG sub-tree corresponding to index_info. */
1241
uint32_t param_idx; /* Index of used key in param->key. */
1242
/* Number of records selected by the ranges in index_tree. */
1244
ha_rows quick_prefix_records;
1246
TRP_GROUP_MIN_MAX(bool have_min_arg, bool have_max_arg,
1247
KEY_PART_INFO *min_max_arg_part_arg,
1248
uint32_t group_prefix_len_arg, uint32_t used_key_parts_arg,
1249
uint32_t group_key_parts_arg, KEY *index_info_arg,
1250
uint32_t index_arg, uint32_t key_infix_len_arg,
1251
unsigned char *key_infix_arg,
1252
SEL_TREE *tree_arg, optimizer::SEL_ARG *index_tree_arg,
1253
uint32_t param_idx_arg, ha_rows quick_prefix_records_arg)
1255
have_min(have_min_arg),
1256
have_max(have_max_arg),
1257
min_max_arg_part(min_max_arg_part_arg),
1258
group_prefix_len(group_prefix_len_arg),
1259
used_key_parts(used_key_parts_arg),
1260
group_key_parts(group_key_parts_arg),
1261
index_info(index_info_arg),
1263
key_infix_len(key_infix_len_arg),
1264
range_tree(tree_arg),
1265
index_tree(index_tree_arg),
1266
param_idx(param_idx_arg),
1267
quick_prefix_records(quick_prefix_records_arg)
1270
memcpy(this->key_infix, key_infix_arg, key_infix_len);
1272
virtual ~TRP_GROUP_MIN_MAX() {} /* Remove gcc warning */
1274
optimizer::QuickSelectInterface *make_quick(optimizer::Parameter *param,
1275
bool retrieve_full_rows,
1276
MEM_ROOT *parent_alloc);
1281
781
Fill param->needed_fields with bitmap of fields used in the query.
7100
Construct new quick select for group queries with min/max.
7103
QUICK_GROUP_MIN_MAX_SELECT::QUICK_GROUP_MIN_MAX_SELECT()
7104
table The table being accessed
7105
join Descriptor of the current query
7106
have_min true if the query selects a MIN function
7107
have_max true if the query selects a MAX function
7108
min_max_arg_part The only argument field of all MIN/MAX functions
7109
group_prefix_len Length of all key parts in the group prefix
7110
prefix_key_parts All key parts in the group prefix
7111
index_info The index chosen for data access
7112
use_index The id of index_info
7113
read_cost Cost of this access method
7114
records Number of records returned
7115
key_infix_len Length of the key infix appended to the group prefix
7116
key_infix Infix of constants from equality predicates
7117
parent_alloc Memory pool for this and quick_prefix_select data
7122
optimizer::QUICK_GROUP_MIN_MAX_SELECT::
7123
QUICK_GROUP_MIN_MAX_SELECT(Table *table,
7127
KEY_PART_INFO *min_max_arg_part_arg,
7128
uint32_t group_prefix_len_arg,
7129
uint32_t group_key_parts_arg,
7130
uint32_t used_key_parts_arg,
7131
KEY *index_info_arg,
7133
double read_cost_arg,
7134
ha_rows records_arg,
7135
uint32_t key_infix_len_arg,
7136
unsigned char *key_infix_arg,
7137
MEM_ROOT *parent_alloc)
7140
index_info(index_info_arg),
7141
group_prefix_len(group_prefix_len_arg),
7142
group_key_parts(group_key_parts_arg),
7143
have_min(have_min_arg),
7144
have_max(have_max_arg),
7145
seen_first_key(false),
7146
min_max_arg_part(min_max_arg_part_arg),
7147
key_infix(key_infix_arg),
7148
key_infix_len(key_infix_len_arg),
7149
min_functions_it(NULL),
7150
max_functions_it(NULL)
7153
cursor= head->cursor;
7155
record= head->record[0];
7156
tmp_record= head->record[1];
7157
read_time= read_cost_arg;
7158
records= records_arg;
7159
used_key_parts= used_key_parts_arg;
7160
real_key_parts= used_key_parts_arg;
7161
real_prefix_len= group_prefix_len + key_infix_len;
7163
min_max_arg_len= min_max_arg_part ? min_max_arg_part->store_length : 0;
7166
We can't have parent_alloc set as the init function can't handle this case
7169
assert(! parent_alloc);
7172
init_sql_alloc(&alloc, join->session->variables.range_alloc_block_size, 0);
7173
join->session->mem_root= &alloc;
7176
memset(&alloc, 0, sizeof(MEM_ROOT)); // ensure that it's not used
7181
Do post-constructor initialization.
7184
QUICK_GROUP_MIN_MAX_SELECT::init()
7187
The method performs initialization that cannot be done in the constructor
7188
such as memory allocations that may fail. It allocates memory for the
7189
group prefix and inifix buffers, and for the lists of MIN/MAX item to be
7190
updated during execution.
7196
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::init()
7198
if (group_prefix) /* Already initialized. */
7201
if (! (last_prefix= (unsigned char*) alloc_root(&alloc, group_prefix_len)))
7204
We may use group_prefix to store keys with all select fields, so allocate
7205
enough space for it.
7207
if (! (group_prefix= (unsigned char*) alloc_root(&alloc,
7208
real_prefix_len + min_max_arg_len)))
7211
if (key_infix_len > 0)
7214
The memory location pointed to by key_infix will be deleted soon, so
7215
allocate a new buffer and copy the key_infix into it.
7217
unsigned char *tmp_key_infix= (unsigned char*) alloc_root(&alloc, key_infix_len);
7218
if (! tmp_key_infix)
7220
memcpy(tmp_key_infix, this->key_infix, key_infix_len);
7221
this->key_infix= tmp_key_infix;
7224
if (min_max_arg_part)
7226
if (my_init_dynamic_array(&min_max_ranges, sizeof(optimizer::QuickRange*), 16, 16))
7231
if (! (min_functions= new List<Item_sum>))
7235
min_functions= NULL;
7238
if (! (max_functions= new List<Item_sum>))
7242
max_functions= NULL;
7244
Item_sum *min_max_item= NULL;
7245
Item_sum **func_ptr= join->sum_funcs;
7246
while ((min_max_item= *(func_ptr++)))
7248
if (have_min && (min_max_item->sum_func() == Item_sum::MIN_FUNC))
7249
min_functions->push_back(min_max_item);
7250
else if (have_max && (min_max_item->sum_func() == Item_sum::MAX_FUNC))
7251
max_functions->push_back(min_max_item);
7256
if (! (min_functions_it= new List_iterator<Item_sum>(*min_functions)))
7262
if (! (max_functions_it= new List_iterator<Item_sum>(*max_functions)))
7267
min_max_ranges.elements= 0;
7273
optimizer::QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
7275
if (cursor->inited != Cursor::NONE)
7277
cursor->ha_index_end();
7279
if (min_max_arg_part)
7281
delete_dynamic(&min_max_ranges);
7283
free_root(&alloc,MYF(0));
7284
delete min_functions_it;
7285
delete max_functions_it;
7286
delete quick_prefix_select;
7291
Eventually create and add a new quick range object.
7294
QUICK_GROUP_MIN_MAX_SELECT::add_range()
7295
sel_range Range object from which a
7298
Construct a new QuickRange object from a SEL_ARG object, and
7299
add it to the array min_max_ranges. If sel_arg is an infinite
7300
range, e.g. (x < 5 or x > 4), then skip it and do not construct
7307
bool optimizer::QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
7309
optimizer::QuickRange *range= NULL;
7310
uint32_t range_flag= sel_range->min_flag | sel_range->max_flag;
7312
/* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
7313
if ((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
7316
if (! (sel_range->min_flag & NO_MIN_RANGE) &&
7317
! (sel_range->max_flag & NO_MAX_RANGE))
7319
if (sel_range->maybe_null &&
7320
sel_range->min_value[0] && sel_range->max_value[0])
7321
range_flag|= NULL_RANGE; /* IS NULL condition */
7322
else if (memcmp(sel_range->min_value, sel_range->max_value,
7323
min_max_arg_len) == 0)
7324
range_flag|= EQ_RANGE; /* equality condition */
7326
range= new optimizer::QuickRange(sel_range->min_value,
7328
make_keypart_map(sel_range->part),
7329
sel_range->max_value,
7331
make_keypart_map(sel_range->part),
7335
if (insert_dynamic(&min_max_ranges, (unsigned char*)&range))
7342
Opens the ranges if there are more conditions in quick_prefix_select than
7343
the ones used for jumping through the prefixes.
7346
QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges()
7349
quick_prefix_select is made over the conditions on the whole key.
7350
It defines a number of ranges of length x.
7351
However when jumping through the prefixes we use only the the first
7352
few most significant keyparts in the range key. However if there
7353
are more keyparts to follow the ones we are using we must make the
7354
condition on the key inclusive (because x < "ab" means
7355
x[0] < 'a' OR (x[0] == 'a' AND x[1] < 'b').
7356
To achive the above we must turn off the NEAR_MIN/NEAR_MAX
7358
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::adjust_prefix_ranges()
7360
if (quick_prefix_select &&
7361
group_prefix_len < quick_prefix_select->max_used_key_length)
7363
DYNAMIC_ARRAY *arr= NULL;
7366
for (inx= 0, arr= &quick_prefix_select->ranges; inx < arr->elements; inx++)
7368
optimizer::QuickRange *range= NULL;
7370
get_dynamic(arr, (unsigned char*)&range, inx);
7371
range->flag &= ~(NEAR_MIN | NEAR_MAX);
7378
Determine the total number and length of the keys that will be used for
7382
QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
7385
The total length of the keys used for index lookup depends on whether
7386
there are any predicates referencing the min/max argument, and/or if
7387
the min/max argument field can be NULL.
7388
This function does an optimistic analysis whether the search key might
7389
be extended by a constant for the min/max keypart. It is 'optimistic'
7390
because during actual execution it may happen that a particular range
7391
is skipped, and then a shorter key will be used. However this is data
7392
dependent and can't be easily estimated here.
7397
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_key_stat()
7399
max_used_key_length= real_prefix_len;
7400
if (min_max_ranges.elements > 0)
7402
optimizer::QuickRange *cur_range= NULL;
7404
{ /* Check if the right-most range has a lower boundary. */
7405
get_dynamic(&min_max_ranges,
7406
(unsigned char*) &cur_range,
7407
min_max_ranges.elements - 1);
7408
if (! (cur_range->flag & NO_MIN_RANGE))
7410
max_used_key_length+= min_max_arg_len;
7416
{ /* Check if the left-most range has an upper boundary. */
7417
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, 0);
7418
if (! (cur_range->flag & NO_MAX_RANGE))
7420
max_used_key_length+= min_max_arg_len;
7426
else if (have_min && min_max_arg_part &&
7427
min_max_arg_part->field->real_maybe_null())
7430
If a MIN/MAX argument value is NULL, we can quickly determine
7431
that we're in the beginning of the next group, because NULLs
7432
are always < any other value. This allows us to quickly
7433
determine the end of the current group and jump to the next
7434
group (see next_min()) and thus effectively increases the
7437
max_used_key_length+= min_max_arg_len;
7444
Initialize a quick group min/max select for key retrieval.
7447
QUICK_GROUP_MIN_MAX_SELECT::reset()
7450
Initialize the index chosen for access and find and store the prefix
7451
of the last group. The method is expensive since it performs disk access.
7457
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::reset(void)
7461
cursor->extra(HA_EXTRA_KEYREAD); /* We need only the key attributes */
7462
if ((result= cursor->ha_index_init(index,1)))
7464
if (quick_prefix_select && quick_prefix_select->reset())
7466
result= cursor->index_last(record);
7467
if (result == HA_ERR_END_OF_FILE)
7469
/* Save the prefix of the last group. */
7470
key_copy(last_prefix, record, index_info, group_prefix_len);
7478
Get the next key containing the MIN and/or MAX key for the next group.
7481
QUICK_GROUP_MIN_MAX_SELECT::get_next()
7484
The method finds the next subsequent group of records that satisfies the
7485
query conditions and finds the keys that contain the MIN/MAX values for
7486
the key part referenced by the MIN/MAX function(s). Once a group and its
7487
MIN/MAX values are found, store these values in the Item_sum objects for
7488
the MIN/MAX functions. The rest of the values in the result row are stored
7489
in the Item_field::result_field of each select field. If the query does
7490
not contain MIN and/or MAX functions, then the function only finds the
7491
group prefix, which is a query answer itself.
7494
If both MIN and MAX are computed, then we use the fact that if there is
7495
no MIN key, there can't be a MAX key as well, so we can skip looking
7496
for a MAX key in this case.
7500
HA_ERR_END_OF_FILE if returned all keys
7501
other if some error occurred
7503
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::get_next()
7508
int is_last_prefix= 0;
7511
Loop until a group is found that satisfies all query conditions or the last
7516
result= next_prefix();
7518
Check if this is the last group prefix. Notice that at this point
7519
this->record contains the current prefix in record format.
7523
is_last_prefix= key_cmp(index_info->key_part, last_prefix,
7525
assert(is_last_prefix <= 0);
7529
if (result == HA_ERR_KEY_NOT_FOUND)
7536
min_res= next_min();
7538
update_min_result();
7540
/* If there is no MIN in the group, there is no MAX either. */
7541
if ((have_max && !have_min) ||
7542
(have_max && have_min && (min_res == 0)))
7544
max_res= next_max();
7546
update_max_result();
7547
/* If a MIN was found, a MAX must have been found as well. */
7548
assert(((have_max && !have_min) ||
7549
(have_max && have_min && (max_res == 0))));
7552
If this is just a GROUP BY or DISTINCT without MIN or MAX and there
7553
are equality predicates for the key parts after the group, find the
7554
first sub-group with the extended prefix.
7556
if (! have_min && ! have_max && key_infix_len > 0)
7557
result= cursor->index_read_map(record,
7559
make_prev_keypart_map(real_key_parts),
7562
result= have_min ? min_res : have_max ? max_res : result;
7563
} while ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7564
is_last_prefix != 0);
7569
Partially mimic the behavior of end_select_send. Copy the
7570
field data from Item_field::field into Item_field::result_field
7571
of each non-aggregated field (the group fields, and optionally
7572
other fields in non-ANSI SQL mode).
7574
copy_fields(&join->tmp_table_param);
7576
else if (result == HA_ERR_KEY_NOT_FOUND)
7577
result= HA_ERR_END_OF_FILE;
7584
Retrieve the minimal key in the next group.
7587
QUICK_GROUP_MIN_MAX_SELECT::next_min()
7590
Find the minimal key within this group such that the key satisfies the query
7591
conditions and NULL semantics. The found key is loaded into this->record.
7594
Depending on the values of min_max_ranges.elements, key_infix_len, and
7595
whether there is a NULL in the MIN field, this function may directly
7596
return without any data access. In this case we use the key loaded into
7597
this->record by the call to this->next_prefix() just before this call.
7601
HA_ERR_KEY_NOT_FOUND if no MIN key was found that fulfills all conditions.
7602
HA_ERR_END_OF_FILE - "" -
7603
other if some error occurred
7605
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_min()
7609
/* Find the MIN key using the eventually extended group prefix. */
7610
if (min_max_ranges.elements > 0)
7612
if ((result= next_min_in_range()))
7617
/* Apply the constant equality conditions to the non-group select fields */
7618
if (key_infix_len > 0)
7620
if ((result= cursor->index_read_map(record,
7622
make_prev_keypart_map(real_key_parts),
7623
HA_READ_KEY_EXACT)))
7628
If the min/max argument field is NULL, skip subsequent rows in the same
7629
group with NULL in it. Notice that:
7630
- if the first row in a group doesn't have a NULL in the field, no row
7631
in the same group has (because NULL < any other value),
7632
- min_max_arg_part->field->ptr points to some place in 'record'.
7634
if (min_max_arg_part && min_max_arg_part->field->is_null())
7636
/* Find the first subsequent record without NULL in the MIN/MAX field. */
7637
key_copy(tmp_record, record, index_info, 0);
7638
result= cursor->index_read_map(record,
7640
make_keypart_map(real_key_parts),
7643
Check if the new record belongs to the current group by comparing its
7644
prefix with the group's prefix. If it is from the next group, then the
7645
whole group has NULLs in the MIN/MAX field, so use the first record in
7646
the group as a result.
7648
It is possible to reuse this new record as the result candidate for the
7649
next call to next_min(), and to save one lookup in the next call. For
7650
this add a new member 'this->next_group_prefix'.
7654
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7655
key_restore(record, tmp_record, index_info, 0);
7657
else if (result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE)
7658
result= 0; /* There is a result in any case. */
7663
If the MIN attribute is non-nullable, this->record already contains the
7664
MIN key in the group, so just return.
7671
Retrieve the maximal key in the next group.
7674
QUICK_GROUP_MIN_MAX_SELECT::next_max()
7677
Lookup the maximal key of the group, and store it into this->record.
7681
HA_ERR_KEY_NOT_FOUND if no MAX key was found that fulfills all conditions.
7682
HA_ERR_END_OF_FILE - "" -
7683
other if some error occurred
7685
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_max()
7689
/* Get the last key in the (possibly extended) group. */
7690
if (min_max_ranges.elements > 0)
7691
result= next_max_in_range();
7693
result= cursor->index_read_map(record,
7695
make_prev_keypart_map(real_key_parts),
7696
HA_READ_PREFIX_LAST);
7702
Determine the prefix of the next group.
7705
QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
7708
Determine the prefix of the next group that satisfies the query conditions.
7709
If there is a range condition referencing the group attributes, use a
7710
QuickRangeSelect object to retrieve the *first* key that satisfies the
7711
condition. If there is a key infix of constants, append this infix
7712
immediately after the group attributes. The possibly extended prefix is
7713
stored in this->group_prefix. The first key of the found group is stored in
7714
this->record, on which relies this->next_min().
7718
HA_ERR_KEY_NOT_FOUND if there is no key with the formed prefix
7719
HA_ERR_END_OF_FILE if there are no more keys
7720
other if some error occurred
7722
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_prefix()
7726
if (quick_prefix_select)
7728
unsigned char *cur_prefix= seen_first_key ? group_prefix : NULL;
7729
if ((result= quick_prefix_select->get_next_prefix(group_prefix_len,
7730
make_prev_keypart_map(group_key_parts),
7733
seen_first_key= true;
7737
if (! seen_first_key)
7739
result= cursor->index_first(record);
7742
seen_first_key= true;
7746
/* Load the first key in this group into record. */
7747
result= cursor->index_read_map(record,
7749
make_prev_keypart_map(group_key_parts),
7756
/* Save the prefix of this group for subsequent calls. */
7757
key_copy(group_prefix, record, index_info, group_prefix_len);
7758
/* Append key_infix to group_prefix. */
7759
if (key_infix_len > 0)
7760
memcpy(group_prefix + group_prefix_len,
7769
Find the minimal key in a group that satisfies some range conditions for the
7770
min/max argument field.
7773
QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
7776
Given the sequence of ranges min_max_ranges, find the minimal key that is
7777
in the left-most possible range. If there is no such key, then the current
7778
group does not have a MIN key that satisfies the WHERE clause. If a key is
7779
found, its value is stored in this->record.
7783
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
7785
HA_ERR_END_OF_FILE - "" -
7788
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
7790
ha_rkey_function find_flag;
7791
key_part_map keypart_map;
7792
optimizer::QuickRange *cur_range= NULL;
7793
bool found_null= false;
7794
int result= HA_ERR_KEY_NOT_FOUND;
7795
basic_string<unsigned char> max_key;
7797
max_key.reserve(real_prefix_len + min_max_arg_len);
7799
assert(min_max_ranges.elements > 0);
7801
for (uint32_t range_idx= 0; range_idx < min_max_ranges.elements; range_idx++)
7802
{ /* Search from the left-most range to the right. */
7803
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx);
7806
If the current value for the min/max argument is bigger than the right
7807
boundary of cur_range, there is no need to check this range.
7809
if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
7810
(key_cmp(min_max_arg_part,
7811
(const unsigned char*) cur_range->max_key,
7812
min_max_arg_len) == 1))
7815
if (cur_range->flag & NO_MIN_RANGE)
7817
keypart_map= make_prev_keypart_map(real_key_parts);
7818
find_flag= HA_READ_KEY_EXACT;
7822
/* Extend the search key with the lower boundary for this range. */
7823
memcpy(group_prefix + real_prefix_len,
7825
cur_range->min_length);
7826
keypart_map= make_keypart_map(real_key_parts);
7827
find_flag= (cur_range->flag & (EQ_RANGE | NULL_RANGE)) ?
7828
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MIN) ?
7829
HA_READ_AFTER_KEY : HA_READ_KEY_OR_NEXT;
7832
result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
7835
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7836
(cur_range->flag & (EQ_RANGE | NULL_RANGE)))
7837
continue; /* Check the next range. */
7840
In all other cases (HA_ERR_*, HA_READ_KEY_EXACT with NO_MIN_RANGE,
7841
HA_READ_AFTER_KEY, HA_READ_KEY_OR_NEXT) if the lookup failed for this
7842
range, it can't succeed for any other subsequent range.
7847
/* A key was found. */
7848
if (cur_range->flag & EQ_RANGE)
7849
break; /* No need to perform the checks below for equal keys. */
7851
if (cur_range->flag & NULL_RANGE)
7854
Remember this key, and continue looking for a non-NULL key that
7855
satisfies some other condition.
7857
memcpy(tmp_record, record, head->s->rec_buff_length);
7862
/* Check if record belongs to the current group. */
7863
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7865
result= HA_ERR_KEY_NOT_FOUND;
7869
/* If there is an upper limit, check if the found key is in the range. */
7870
if (! (cur_range->flag & NO_MAX_RANGE) )
7872
/* Compose the MAX key for the range. */
7874
max_key.append(group_prefix, real_prefix_len);
7875
max_key.append(cur_range->max_key, cur_range->max_length);
7876
/* Compare the found key with max_key. */
7877
int cmp_res= key_cmp(index_info->key_part,
7879
real_prefix_len + min_max_arg_len);
7880
if (! (((cur_range->flag & NEAR_MAX) && (cmp_res == -1)) ||
7883
result= HA_ERR_KEY_NOT_FOUND;
7887
/* If we got to this point, the current key qualifies as MIN. */
7888
assert(result == 0);
7892
If there was a key with NULL in the MIN/MAX field, and there was no other
7893
key without NULL from the same group that satisfies some other condition,
7894
then use the key with the NULL.
7896
if (found_null && result)
7898
memcpy(record, tmp_record, head->s->rec_buff_length);
7906
Find the maximal key in a group that satisfies some range conditions for the
7907
min/max argument field.
7910
QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
7913
Given the sequence of ranges min_max_ranges, find the maximal key that is
7914
in the right-most possible range. If there is no such key, then the current
7915
group does not have a MAX key that satisfies the WHERE clause. If a key is
7916
found, its value is stored in this->record.
7920
HA_ERR_KEY_NOT_FOUND if there is no key with the given prefix in any of
7922
HA_ERR_END_OF_FILE - "" -
7925
int optimizer::QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
7927
ha_rkey_function find_flag;
7928
key_part_map keypart_map;
7929
optimizer::QuickRange *cur_range= NULL;
7931
basic_string<unsigned char> min_key;
7932
min_key.reserve(real_prefix_len + min_max_arg_len);
7934
assert(min_max_ranges.elements > 0);
7936
for (uint32_t range_idx= min_max_ranges.elements; range_idx > 0; range_idx--)
7937
{ /* Search from the right-most range to the left. */
7938
get_dynamic(&min_max_ranges, (unsigned char*)&cur_range, range_idx - 1);
7941
If the current value for the min/max argument is smaller than the left
7942
boundary of cur_range, there is no need to check this range.
7944
if (range_idx != min_max_ranges.elements &&
7945
! (cur_range->flag & NO_MIN_RANGE) &&
7946
(key_cmp(min_max_arg_part,
7947
(const unsigned char*) cur_range->min_key,
7948
min_max_arg_len) == -1))
7951
if (cur_range->flag & NO_MAX_RANGE)
7953
keypart_map= make_prev_keypart_map(real_key_parts);
7954
find_flag= HA_READ_PREFIX_LAST;
7958
/* Extend the search key with the upper boundary for this range. */
7959
memcpy(group_prefix + real_prefix_len,
7961
cur_range->max_length);
7962
keypart_map= make_keypart_map(real_key_parts);
7963
find_flag= (cur_range->flag & EQ_RANGE) ?
7964
HA_READ_KEY_EXACT : (cur_range->flag & NEAR_MAX) ?
7965
HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV;
7968
result= cursor->index_read_map(record, group_prefix, keypart_map, find_flag);
7972
if ((result == HA_ERR_KEY_NOT_FOUND || result == HA_ERR_END_OF_FILE) &&
7973
(cur_range->flag & EQ_RANGE))
7974
continue; /* Check the next range. */
7977
In no key was found with this upper bound, there certainly are no keys
7978
in the ranges to the left.
7982
/* A key was found. */
7983
if (cur_range->flag & EQ_RANGE)
7984
return 0; /* No need to perform the checks below for equal keys. */
7986
/* Check if record belongs to the current group. */
7987
if (key_cmp(index_info->key_part, group_prefix, real_prefix_len))
7988
continue; // Row not found
7990
/* If there is a lower limit, check if the found key is in the range. */
7991
if (! (cur_range->flag & NO_MIN_RANGE) )
7993
/* Compose the MIN key for the range. */
7995
min_key.append(group_prefix, real_prefix_len);
7996
min_key.append(cur_range->min_key, cur_range->min_length);
7998
/* Compare the found key with min_key. */
7999
int cmp_res= key_cmp(index_info->key_part,
8001
real_prefix_len + min_max_arg_len);
8002
if (! (((cur_range->flag & NEAR_MIN) && (cmp_res == 1)) ||
8006
/* If we got to this point, the current key qualifies as MAX. */
8009
return HA_ERR_KEY_NOT_FOUND;
8014
Update all MIN function results with the newly found value.
8017
QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
8020
The method iterates through all MIN functions and updates the result value
8021
of each function by calling Item_sum::reset(), which in turn picks the new
8022
result value from this->head->record[0], previously updated by
8023
next_min(). The updated value is stored in a member variable of each of the
8024
Item_sum objects, depending on the value type.
8027
The update must be done separately for MIN and MAX, immediately after
8028
next_min() was called and before next_max() is called, because both MIN and
8029
MAX take their result value from the same buffer this->head->record[0]
8030
(i.e. this->record).
8035
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_min_result()
8037
Item_sum *min_func= NULL;
8039
min_functions_it->rewind();
8040
while ((min_func= (*min_functions_it)++))
8046
Update all MAX function results with the newly found value.
8049
QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
8052
The method iterates through all MAX functions and updates the result value
8053
of each function by calling Item_sum::reset(), which in turn picks the new
8054
result value from this->head->record[0], previously updated by
8055
next_max(). The updated value is stored in a member variable of each of the
8056
Item_sum objects, depending on the value type.
8059
The update must be done separately for MIN and MAX, immediately after
8060
next_max() was called, because both MIN and MAX take their result value
8061
from the same buffer this->head->record[0] (i.e. this->record).
8066
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::update_max_result()
8068
Item_sum *max_func= NULL;
8070
max_functions_it->rewind();
8071
while ((max_func= (*max_functions_it)++))
8077
Append comma-separated list of keys this quick select uses to key_names;
8078
append comma-separated list of corresponding used lengths to used_lengths.
8081
QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths()
8082
key_names [out] Names of used indexes
8083
used_lengths [out] Corresponding lengths of the index names
8086
This method is used by select_describe to extract the names of the
8087
indexes used by a quick select.
8090
void optimizer::QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
8091
String *used_lengths)
8095
key_names->append(index_info->name);
8096
length= int64_t2str(max_used_key_length, buf, 10) - buf;
8097
used_lengths->append(buf, length);
6342
optimizer::QuickSelectInterface *optimizer::TRP_RANGE::make_quick(optimizer::Parameter *param, bool, MEM_ROOT *parent_alloc)
6344
optimizer::QuickRangeSelect *quick= NULL;
6345
if ((quick= optimizer::get_quick_select(param,
6352
quick->records= records;
6353
quick->read_time= read_cost;
8100
6359
static void print_sel_tree(optimizer::Parameter *param, SEL_TREE *tree, key_map *tree_map, const char *)