26
26
This file contains:
29
A module that accepts a condition, index (or partitioning) description,
30
and builds lists of intervals (in index/partitioning space), such that
31
all possible records that match the condition are contained within the
29
A module that accepts a condition, index (or partitioning) description,
30
and builds lists of intervals (in index/partitioning space), such that
31
all possible records that match the condition are contained within the
33
33
The entry point for the range analysis module is get_mm_tree() function.
35
35
The lists are returned in form of complicated structure of interlinked
36
36
SEL_TREE/SEL_IMERGE/SEL_ARG objects.
37
See quick_range_seq_next, find_used_partitions for examples of how to walk
37
See quick_range_seq_next, find_used_partitions for examples of how to walk
39
39
All direct "users" of this module are located within this file, too.
99
99
See key_copy() and key_restore() for code to move data between index tuple
102
CAUTION: the above description is only sergefp's understanding of the
102
CAUTION: the above description is only sergefp's understanding of the
103
103
subject and may omit some details.
106
106
#include <drizzled/server_includes.h>
107
#include <drizzled/sql_base.h>
107
108
#include <drizzled/sql_select.h>
110
#define test_rb_tree(A,B) {}
111
#define test_use_count(A) {}
109
#include <drizzled/error.h>
110
#include <drizzled/cost_vect.h>
111
#include <drizzled/item/cmpfunc.h>
112
#include <drizzled/field/num.h>
113
#include <drizzled/check_stack_overrun.h>
115
#include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
123
#define HA_END_SPACE_KEY 0
115
126
Convert double value to #rows. Currently this does floor(), and we
116
127
might consider using round() instead.
118
#define double2rows(x) ((ha_rows)(x))
129
static inline ha_rows double2rows(double x)
131
return static_cast<ha_rows>(x);
134
extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
136
handler *file= (handler*)arg;
137
return file->cmp_ref((const unsigned char*)a, (const unsigned char*)b);
120
140
static int sel_cmp(Field *f,unsigned char *a,unsigned char *b,uint8_t a_flag,uint8_t b_flag);
161
181
+-------+ $ $ +--------+
163
183
... $ $ +--------+
165
185
The entire graph is partitioned into "interval lists".
167
187
An interval list is a sequence of ordered disjoint intervals over the same
168
188
key part. SEL_ARG are linked via "next" and "prev" pointers. Additionally,
169
all intervals in the list form an RB-tree, linked via left/right/parent
189
all intervals in the list form an RB-tree, linked via left/right/parent
170
190
pointers. The RB-tree root SEL_ARG object will be further called "root of the
173
In the example pic, there are 4 interval lists:
193
In the example pic, there are 4 interval lists:
174
194
"kp<1 OR kp1=2 OR kp1=3", "kp2=5", "kp3=10 OR kp3=12", "kp3=11 OR kp3=13".
175
195
The vertical lines represent SEL_ARG::next/prev pointers.
177
197
In an interval list, each member X may have SEL_ARG::next_key_part pointer
178
198
pointing to the root of another interval list Y. The pointed interval list
179
199
must cover a key part with greater number (i.e. Y->part > X->part).
181
201
In the example pic, the next_key_part pointers are represented by
182
202
horisontal lines.
208
228
and create QUICK_RANGE_SELECT object that will
209
229
read records within these intervals.
211
4. SPACE COMPLEXITY NOTES
231
4. SPACE COMPLEXITY NOTES
213
233
SEL_ARG graph is a representation of an ordered disjoint sequence of
214
234
intervals over the ordered set of index tuple values.
216
236
For multi-part keys, one can construct a WHERE expression such that its
217
237
list of intervals will be of combinatorial size. Here is an example:
219
(keypart1 IN (1,2, ..., n1)) AND
220
(keypart2 IN (1,2, ..., n2)) AND
239
(keypart1 IN (1,2, ..., n1)) AND
240
(keypart2 IN (1,2, ..., n2)) AND
221
241
(keypart3 IN (1,2, ..., n3))
223
243
For this WHERE clause the list of intervals will have n1*n2*n3 intervals
226
246
(keypart1, keypart2, keypart3) = (k1, k2, k3), where 1 <= k{i} <= n{i}
228
248
SEL_ARG graph structure aims to reduce the amount of required space by
229
249
"sharing" the elementary intervals when possible (the pic at the
230
beginning of this comment has examples of such sharing). The sharing may
250
beginning of this comment has examples of such sharing). The sharing may
231
251
prevent combinatorial blowup:
233
253
There are WHERE clauses that have combinatorial-size interval lists but
234
254
will be represented by a compact SEL_ARG graph.
236
(keypartN IN (1,2, ..., n1)) AND
256
(keypartN IN (1,2, ..., n1)) AND
238
(keypart2 IN (1,2, ..., n2)) AND
258
(keypart2 IN (1,2, ..., n2)) AND
239
259
(keypart1 IN (1,2, ..., n3))
241
261
but not in all cases:
255
275
By induction: Let's take any interval on some keypart in the middle:
259
279
Then let's AND it with this interval 'structure' from preceding and
260
280
following keyparts:
262
282
(kp14=c1 AND kp16=c3) OR keypart14=c2) (*)
264
284
We will obtain this SEL_ARG graph:
266
286
kp14 $ kp15 $ kp16
268
288
+---------+ $ +---------+ $ +---------+
269
289
| kp14=c1 |--$-->| kp15=c0 |--$-->| kp16=c3 |
270
290
+---------+ $ +---------+ $ +---------+
272
+---------+ $ +---------+ $
273
| kp14=c2 |--$-->| kp15=c0 | $
274
+---------+ $ +---------+ $
292
+---------+ $ +---------+ $
293
| kp14=c2 |--$-->| kp15=c0 | $
294
+---------+ $ +---------+ $
277
297
Note that we had to duplicate "kp15=c0" and there was no way to avoid
279
299
The induction step: AND the obtained expression with another "wrapping"
280
300
expression like (*).
281
When the process ends because of the limit on max. number of keyparts
301
When the process ends because of the limit on max. number of keyparts
284
304
WHERE clause length is O(3*#max_keyparts)
970
991
Perform OR operation on index_merge list and key tree.
973
0 OK, result is stored in *im1.
994
false OK, result is stored in im1.
977
int imerge_list_or_tree(RANGE_OPT_PARAM *param,
978
List<SEL_IMERGE> *im1,
998
static bool imerge_list_or_tree(RANGE_OPT_PARAM *param,
999
vector<SEL_IMERGE*> &im1,
982
List_iterator<SEL_IMERGE> it(*im1);
983
while ((imerge= it++))
1002
vector<SEL_IMERGE*>::iterator imerge= im1.begin();
1004
while (imerge != im1.end())
985
if (imerge->or_sel_tree_with_checks(param, tree))
1006
if ((*imerge)->or_sel_tree_with_checks(param, tree))
1007
imerge= im1.erase( imerge );
988
return im1->is_empty();
1087
bool SQL_SELECT::check_quick(Session *session, bool force_quick_range,
1092
return test_quick_select(session, tmp, 0, limit,
1093
force_quick_range, false) < 0;
1097
bool SQL_SELECT::skip_record()
1099
return cond ? cond->val_int() == 0 : 0;
1061
1103
QUICK_SELECT_I::QUICK_SELECT_I()
1062
1104
:max_used_key_length(0),
1063
1105
used_key_parts(0)
1066
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, Table *table, uint32_t key_nr,
1108
QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(Session *session, Table *table, uint32_t key_nr,
1067
1109
bool no_alloc, MEM_ROOT *parent_alloc,
1068
1110
bool *create_error)
1069
1111
:free_file(0),cur_range(NULL),last_range(0),dont_free(0)
1077
1119
key_part_info= head->key_info[index].key_part;
1078
1120
my_init_dynamic_array(&ranges, sizeof(QUICK_RANGE*), 16, 16);
1080
/* 'thd' is not accessible in QUICK_RANGE_SELECT::reset(). */
1081
mrr_buf_size= thd->variables.read_rnd_buff_size;
1122
/* 'session' is not accessible in QUICK_RANGE_SELECT::reset(). */
1123
mrr_buf_size= session->variables.read_rnd_buff_size;
1082
1124
mrr_buf_desc= NULL;
1084
1126
if (!no_alloc && !parent_alloc)
1086
1128
// Allocates everything through the internal memroot
1087
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1088
thd->mem_root= &alloc;
1129
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
1130
session->mem_root= &alloc;
1091
1133
memset(&alloc, 0, sizeof(alloc));
1140
file->ha_external_lock(current_thd, F_UNLCK);
1182
file->ha_external_lock(current_session, F_UNLCK);
1145
1187
delete_dynamic(&ranges); /* ranges are allocated in alloc */
1146
1188
free_root(&alloc,MYF(0));
1147
free((char*) column_bitmap.bitmap);
1149
1190
head->column_bitmaps_set(save_read_set, save_write_set);
1191
assert(mrr_buf_desc == NULL);
1150
1192
if (mrr_buf_desc)
1151
1193
free(mrr_buf_desc);
1156
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
1197
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(Session *session_param,
1158
:pk_quick_select(NULL), thd(thd_param)
1199
:pk_quick_select(NULL), session(session_param)
1160
1201
index= MAX_KEY;
1162
1203
memset(&read_record, 0, sizeof(read_record));
1163
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1204
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
1167
1208
int QUICK_INDEX_MERGE_SELECT::init()
1172
1213
int QUICK_INDEX_MERGE_SELECT::reset()
1206
QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(THD *thd_param,
1247
QUICK_ROR_INTERSECT_SELECT::QUICK_ROR_INTERSECT_SELECT(Session *session_param,
1208
1249
bool retrieve_full_rows,
1209
1250
MEM_ROOT *parent_alloc)
1210
: cpk_quick(NULL), thd(thd_param), need_to_fetch_row(retrieve_full_rows),
1251
: cpk_quick(NULL), session(session_param), need_to_fetch_row(retrieve_full_rows),
1211
1252
scans_inited(false)
1213
1254
index= MAX_KEY;
1215
1256
record= head->record[0];
1216
1257
if (!parent_alloc)
1217
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1258
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
1219
1260
memset(&alloc, 0, sizeof(MEM_ROOT));
1220
1261
last_rowid= (unsigned char*) alloc_root(parent_alloc? parent_alloc : &alloc,
1283
1324
/* already have own 'handler' object. */
1288
if (!(file= head->file->clone(thd->mem_root)))
1328
session= head->in_use;
1329
if (!(file= head->file->clone(session->mem_root)))
1291
1332
Manually set the error flag. Note: there seems to be quite a few
1292
1333
places where a failure could cause the server to "hang" the client by
1293
sending no response to a query. ATM those are not real errors because
1294
the storage engine calls in question happen to never fail with the
1295
existing storage engines.
1334
sending no response to a query. ATM those are not real errors because
1335
the storage engine calls in question happen to never fail with the
1336
existing storage engines.
1297
my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
1338
my_error(ER_OUT_OF_RESOURCES, MYF(0));
1298
1339
/* Caller will free the memory */
1299
goto failure; /* purecov: inspected */
1302
1343
head->column_bitmaps_set(&column_bitmap, &column_bitmap);
1304
if (file->ha_external_lock(thd, F_RDLCK))
1345
if (file->ha_external_lock(session, F_RDLCK))
1307
1348
if (init() || reset())
1309
file->ha_external_lock(thd, F_UNLCK);
1350
file->ha_external_lock(session, F_UNLCK);
1445
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
1492
QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(Session *session_param,
1447
: thd(thd_param), scans_inited(false)
1494
: session(session_param), scans_inited(false)
1449
1496
index= MAX_KEY;
1451
1498
rowid_length= table->file->ref_length;
1452
1499
record= head->record[0];
1453
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
1454
thd_param->mem_root= &alloc;
1500
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
1501
session_param->mem_root= &alloc;
1505
* Function object that is used as the comparison function
1506
* for the priority queue in the QUICK_ROR_UNION_SELECT
1509
class compare_functor
1511
QUICK_ROR_UNION_SELECT *self;
1513
compare_functor(QUICK_ROR_UNION_SELECT *in_arg)
1515
inline bool operator()(const QUICK_SELECT_I *i, const QUICK_SELECT_I *j) const
1517
int val= self->head->file->cmp_ref(i->last_rowid,
1459
1524
Do post-constructor initialization.
1468
1533
int QUICK_ROR_UNION_SELECT::init()
1470
if (init_queue(&queue, quick_selects.elements, 0,
1471
false , QUICK_ROR_UNION_SELECT::queue_cmp,
1474
memset(&queue, 0, sizeof(QUEUE));
1536
new priority_queue<QUICK_SELECT_I *, vector<QUICK_SELECT_I *>, compare_functor >(compare_functor(this));
1478
1537
if (!(cur_rowid= (unsigned char*) alloc_root(&alloc, 2*head->file->ref_length)))
1480
1539
prev_rowid= cur_rowid + head->file->ref_length;
1486
Comparison function to be used QUICK_ROR_UNION_SELECT::queue priority
1490
QUICK_ROR_UNION_SELECT::queue_cmp()
1491
arg Pointer to QUICK_ROR_UNION_SELECT
1492
val1 First merged select
1493
val2 Second merged select
1496
int QUICK_ROR_UNION_SELECT::queue_cmp(void *arg, unsigned char *val1, unsigned char *val2)
1498
QUICK_ROR_UNION_SELECT *self= (QUICK_ROR_UNION_SELECT*)arg;
1499
return self->head->file->cmp_ref(((QUICK_SELECT_I*)val1)->last_rowid,
1500
((QUICK_SELECT_I*)val2)->last_rowid);
1784
1827
uint32_t match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
1787
1830
for (ord= order; ord; ord= ord->next)
1789
1832
return MAX_KEY;
1791
1834
for (idx= 0; idx < table->s->keys; idx++)
1793
if (!(table->keys_in_use_for_query.is_set(idx)))
1836
if (!(table->keys_in_use_for_query.test(idx)))
1795
1838
KEY_PART_INFO *keyinfo= table->key_info[idx].key_part;
1796
1839
uint32_t n_parts= table->key_info[idx].key_parts;
1797
1840
uint32_t partno= 0;
1800
The below check is sufficient considering we now have either BTREE
1801
indexes (records are returned in order for any index prefix) or HASH
1843
The below check is sufficient considering we now have either BTREE
1844
indexes (records are returned in order for any index prefix) or HASH
1802
1845
indexes (records are not returned in order for any index prefix).
1804
1847
if (!(table->file->index_flags(idx, 0, 1) & HA_READ_ORDER))
2056
2095
Table *table= param->table;
2057
2096
my_bitmap_map *tmp;
2059
param->tmp_covered_fields.bitmap= 0;
2098
param->tmp_covered_fields.setBitmap(0);
2060
2099
param->fields_bitmap_size= table->s->column_bitmap_size;
2061
2100
if (!(tmp= (my_bitmap_map*) alloc_root(param->mem_root,
2062
2101
param->fields_bitmap_size)) ||
2063
bitmap_init(¶m->needed_fields, tmp, table->s->fields, false))
2102
param->needed_fields.init(tmp, table->s->fields))
2066
bitmap_copy(¶m->needed_fields, table->read_set);
2105
param->needed_fields= *table->read_set;
2067
2106
bitmap_union(¶m->needed_fields, table->write_set);
2069
2108
pk= param->table->s->primary_key;
2107
2146
quick_condition_rows value is obtained as follows:
2109
2148
It is a minimum of E(#output rows) for all considered table access
2110
2149
methods (range and index_merge accesses over various indexes).
2112
2151
The obtained value is not a true E(#rows that satisfy table condition)
2113
2152
but rather a pessimistic estimate. To obtain a true E(#...) one would
2114
2153
need to combine estimates of various access methods, taking into account
2115
2154
correlations between sets of rows they will return.
2117
2156
For example, if values of tbl.key1 and tbl.key2 are independent (a right
2118
2157
assumption if we have no information about their correlation) then the
2119
2158
correct estimate will be:
2121
E(#rows("tbl.key1 < c1 AND tbl.key2 < c2")) =
2160
E(#rows("tbl.key1 < c1 AND tbl.key2 < c2")) =
2122
2161
= E(#rows(tbl.key1 < c1)) / total_rows(tbl) * E(#rows(tbl.key2 < c2)
2124
which is smaller than
2163
which is smaller than
2126
2165
MIN(E(#rows(tbl.key1 < c1), E(#rows(tbl.key2 < c2)))
2128
2167
which is currently produced.
2131
2170
* Change the value returned in quick_condition_rows from a pessimistic
2132
estimate to true E(#rows that satisfy table condition).
2133
(we can re-use some of E(#rows) calcuation code from index_merge/intersection
2171
estimate to true E(#rows that satisfy table condition).
2172
(we can re-use some of E(#rows) calcuation code from index_merge/intersection
2136
2175
* Check if this function really needs to modify keys_to_use, and change the
2137
2176
code to pass it by reference if it doesn't.
2183
if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, NULL))
2184
return(0); // Fatal error flag is set
2222
if (check_stack_overrun(session, 2*STACK_MIN_SIZE, NULL))
2223
return 0; // Fatal error flag is set
2186
2225
/* set up parameter that is passed to all functions */
2226
param.session= session;
2188
2227
param.baseflag= head->file->ha_table_flags();
2189
param.prev_tables=prev_tables | const_tables;
2190
param.read_tables=read_tables;
2228
param.prev_tables= prev_tables | const_tables;
2229
param.read_tables= read_tables;
2191
2230
param.current_table= head->map;
2192
2231
param.table=head;
2194
2233
param.mem_root= &alloc;
2195
param.old_root= thd->mem_root;
2234
param.old_root= session->mem_root;
2196
2235
param.needed_reg= &needed_reg;
2197
2236
param.imerge_cost_buff_size= 0;
2198
2237
param.using_real_indexes= true;
2199
2238
param.remove_jump_scans= true;
2200
2239
param.force_default_mrr= ordered_output;
2202
thd->no_errors=1; // Don't warn about NULL
2203
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
2241
session->no_errors=1; // Don't warn about NULL
2242
init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
2204
2243
if (!(param.key_parts= (KEY_PART*) alloc_root(&alloc,
2205
2244
sizeof(KEY_PART)*
2206
2245
head->s->key_parts)) ||
2207
2246
fill_used_fields_bitmap(¶m))
2248
session->no_errors=0;
2210
2249
free_root(&alloc,MYF(0)); // Return memory & allocator
2211
return(0); // Can't use range
2250
return 0; // Can't use range
2213
2252
key_parts= param.key_parts;
2214
thd->mem_root= &alloc;
2253
session->mem_root= &alloc;
2217
2256
Make an array with description of all key parts of all table keys.
2221
2260
for (idx=0 ; idx < head->s->keys ; idx++, key_info++)
2223
2262
KEY_PART_INFO *key_part_info;
2224
if (!keys_to_use.is_set(idx))
2263
if (! keys_to_use.test(idx))
2227
2266
param.key[param.keys]=key_parts;
2228
2267
key_part_info= key_info->key_part;
2229
for (uint32_t part=0 ; part < key_info->key_parts ;
2230
part++, key_parts++, key_part_info++)
2268
for (uint32_t part=0;
2269
part < key_info->key_parts;
2270
part++, key_parts++, key_part_info++)
2232
key_parts->key= param.keys;
2233
key_parts->part= part;
2234
key_parts->length= key_part_info->length;
2235
key_parts->store_length= key_part_info->store_length;
2236
key_parts->field= key_part_info->field;
2237
key_parts->null_bit= key_part_info->null_bit;
2238
key_parts->image_type = Field::itRAW;
2272
key_parts->key= param.keys;
2273
key_parts->part= part;
2274
key_parts->length= key_part_info->length;
2275
key_parts->store_length= key_part_info->store_length;
2276
key_parts->field= key_part_info->field;
2277
key_parts->null_bit= key_part_info->null_bit;
2239
2278
/* Only HA_PART_KEY_SEG is used */
2240
key_parts->flag= (uint8_t) key_part_info->key_part_flag;
2279
key_parts->flag= (uint8_t) key_part_info->key_part_flag;
2242
2281
param.real_keynr[param.keys++]=idx;
2347
2386
/* Try creating index_merge/ROR-union scan. */
2349
2387
TABLE_READ_PLAN *best_conj_trp= NULL, *new_conj_trp;
2350
List_iterator_fast<SEL_IMERGE> it(tree->merges);
2351
while ((imerge= it++))
2388
vector<SEL_IMERGE*>::iterator imerge= tree->merges.begin();
2389
while (imerge != tree->merges.end())
2353
new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time);
2391
new_conj_trp= get_best_disjunct_quick(¶m, *imerge, best_read_time);
2354
2392
if (new_conj_trp)
2355
set_if_smaller(param.table->quick_condition_rows,
2393
set_if_smaller(param.table->quick_condition_rows,
2356
2394
new_conj_trp->records);
2357
2396
if (!best_conj_trp || (new_conj_trp && new_conj_trp->read_cost <
2358
2397
best_conj_trp->read_cost))
2359
2398
best_conj_trp= new_conj_trp;
2361
2402
if (best_conj_trp)
2362
2403
best_trp= best_conj_trp;
2366
thd->mem_root= param.old_root;
2407
session->mem_root= param.old_root;
2368
2409
/* If we got a read plan, create a quick select from it. */
2558
2599
unique_calc_buff_size=
2559
2600
Unique::get_cost_calc_buff_size((ulong)non_cpk_scan_records,
2560
2601
param->table->file->ref_length,
2561
param->thd->variables.sortbuff_size);
2602
param->session->variables.sortbuff_size);
2562
2603
if (param->imerge_cost_buff_size < unique_calc_buff_size)
2564
2605
if (!(param->imerge_cost_buff= (uint*)alloc_root(param->mem_root,
2565
2606
unique_calc_buff_size)))
2567
2608
param->imerge_cost_buff_size= unique_calc_buff_size;
2571
Unique::get_use_cost(param->imerge_cost_buff, (uint)non_cpk_scan_records,
2612
Unique::get_use_cost(param->imerge_cost_buff, (uint32_t)non_cpk_scan_records,
2572
2613
param->table->file->ref_length,
2573
param->thd->variables.sortbuff_size);
2614
param->session->variables.sortbuff_size);
2574
2615
if (imerge_cost < read_time)
2576
2617
if ((imerge_trp= new (param->mem_root)TRP_INDEX_MERGE))
2578
2619
imerge_trp->read_cost= imerge_cost;
2579
2620
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
2580
imerge_trp->records= cmin(imerge_trp->records,
2621
imerge_trp->records= min(imerge_trp->records,
2581
2622
param->table->file->stats.records);
2582
2623
imerge_trp->range_scans= range_scans;
2583
2624
imerge_trp->range_scans_end= range_scans + n_child_scans;
2747
2789
if (!(bitmap_buf= (my_bitmap_map*) alloc_root(param->mem_root,
2748
2790
param->fields_bitmap_size)))
2751
if (bitmap_init(&ror_scan->covered_fields, bitmap_buf,
2752
param->table->s->fields, false))
2754
bitmap_clear_all(&ror_scan->covered_fields);
2793
if (ror_scan->covered_fields.init(bitmap_buf,
2794
param->table->s->fields))
2796
ror_scan->covered_fields.clearAll();
2756
2798
KEY_PART_INFO *key_part= param->table->key_info[keynr].key_part;
2757
2799
KEY_PART_INFO *key_part_end= key_part +
2758
2800
param->table->key_info[keynr].key_parts;
2759
2801
for (;key_part != key_part_end; ++key_part)
2761
if (bitmap_is_set(¶m->needed_fields, key_part->fieldnr-1))
2762
bitmap_set_bit(&ror_scan->covered_fields, key_part->fieldnr-1);
2803
if (param->needed_fields.isBitSet(key_part->fieldnr-1))
2804
ror_scan->covered_fields.setBit(key_part->fieldnr-1);
2764
2806
double rows= rows2double(param->table->quick_rows[ror_scan->keynr]);
2765
2807
ror_scan->index_read_cost=
2867
2909
if (!(buf= (my_bitmap_map*) alloc_root(param->mem_root,
2868
2910
param->fields_bitmap_size)))
2870
if (bitmap_init(&info->covered_fields, buf, param->table->s->fields,
2912
if (info->covered_fields.init(buf, param->table->s->fields))
2873
2914
info->is_covering= false;
2874
2915
info->index_scan_costs= 0.0;
2875
2916
info->index_records= 0;
2876
2917
info->out_rows= (double) param->table->file->stats.records;
2877
bitmap_clear_all(&info->covered_fields);
2918
info->covered_fields.clearAll();
2881
void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src)
2922
static void ror_intersect_cpy(ROR_INTERSECT_INFO *dst,
2923
const ROR_INTERSECT_INFO *src)
2883
2925
dst->param= src->param;
2884
memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap,
2885
no_bytes_in_map(&src->covered_fields));
2926
dst->covered_fields= src->covered_fields;
2886
2927
dst->out_rows= src->out_rows;
2887
2928
dst->is_covering= src->is_covering;
2888
2929
dst->index_records= src->index_records;
3408
3448
/*I=set of all covering indexes */
3409
3449
ror_scan_mark= tree->ror_scans;
3411
MY_BITMAP *covered_fields= ¶m->tmp_covered_fields;
3412
if (!covered_fields->bitmap)
3413
covered_fields->bitmap= (my_bitmap_map*)alloc_root(param->mem_root,
3451
MyBitmap *covered_fields= ¶m->tmp_covered_fields;
3452
if (! covered_fields->getBitmap())
3454
my_bitmap_map *tmp_bitmap= (my_bitmap_map*)alloc_root(param->mem_root,
3414
3455
param->fields_bitmap_size);
3415
if (!covered_fields->bitmap ||
3416
bitmap_init(covered_fields, covered_fields->bitmap,
3417
param->table->s->fields, false))
3419
bitmap_clear_all(covered_fields);
3456
covered_fields->setBitmap(tmp_bitmap);
3458
if (! covered_fields->getBitmap() ||
3459
covered_fields->init(covered_fields->getBitmap(),
3460
param->table->s->fields))
3462
covered_fields->clearAll();
3421
3464
double total_cost= 0.0f;
3422
3465
ha_rows records=0;
3841
3880
#define NOT_IN_IGNORE_THRESHOLD 1000
3842
3881
MEM_ROOT *tmp_root= param->mem_root;
3843
param->thd->mem_root= param->old_root;
3882
param->session->mem_root= param->old_root;
3845
3884
Create one Item_type constant object. We'll need it as
3846
3885
get_mm_parts only accepts constant values wrapped in Item_Type
3848
3887
We create the Item on param->mem_root which points to
3849
per-statement mem_root (while thd->mem_root is currently pointing
3888
per-statement mem_root (while session->mem_root is currently pointing
3850
3889
to mem_root local to range optimizer).
3852
3891
Item *value_item= func->array->create_item();
3853
param->thd->mem_root= tmp_root;
3892
param->session->mem_root= tmp_root;
3855
3894
if (func->array->count > NOT_IN_IGNORE_THRESHOLD || !value_item)
3858
3897
/* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
3862
3901
func->array->value_to_item(i, value_item);
3863
3902
tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
4010
4049
Yet a predicate of the form (c BETWEEN f1i AND f2i) is processed
4011
4050
differently. It is considered as a conjuction of two SARGable
4012
4051
predicates (f1i <= c) and (f2i <=c) and the function get_full_func_mm_tree
4013
is called for each of them separately producing trees for
4014
AND j (f1j <=c ) and AND j (f2j <= c)
4052
is called for each of them separately producing trees for
4053
AND j (f1j <=c ) and AND j (f2j <= c)
4015
4054
After this these two trees are united in one conjunctive tree.
4016
4055
It's easy to see that the same tree is obtained for
4017
4056
AND j,k (f1j <=c AND f2k<=c)
4018
which is equivalent to
4057
which is equivalent to
4019
4058
AND j,k (c BETWEEN f1j AND f2k).
4020
4059
The validity of the processing of the predicate (c NOT BETWEEN f1i AND f2i)
4021
4060
which equivalent to (f1i > c OR f2i < c) is not so obvious. Here the
4022
4061
function get_full_func_mm_tree is called for (f1i > c) and (f2i < c)
4023
4062
producing trees for AND j (f1j > c) and AND j (f2j < c). Then this two
4024
trees are united in one OR-tree. The expression
4063
trees are united in one OR-tree. The expression
4025
4064
(AND j (f1j > c) OR AND j (f2j < c)
4026
4065
is equivalent to the expression
4027
AND j,k (f1j > c OR f2k < c)
4028
which is just a translation of
4066
AND j,k (f1j > c OR f2k < c)
4067
which is just a translation of
4029
4068
AND j,k (c NOT BETWEEN f1j AND f2k)
4031
4070
In the cases when one of the items f1, f2 is a constant c1 we do not create
4038
4077
As to IN predicates only ones of the form (f IN (c1,...,cn)),
4039
4078
where f1 is a field and c1,...,cn are constant, are considered as
4040
4079
SARGable. We never try to narrow the index scan using predicates of
4041
the form (c IN (c1,...,f,...,cn)).
4080
the form (c IN (c1,...,f,...,cn)).
4044
4083
Pointer to the tree representing the built conjunction of SEL_TREEs
4047
4086
static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
4048
4087
Item_func *cond_func,
4049
Item_field *field_item, Item *value,
4088
Item_field *field_item, Item *value,
4052
4091
SEL_TREE *tree= 0;
4209
4253
Item_func_in *func=(Item_func_in*) cond_func;
4210
4254
if (func->key_item()->real_item()->type() != Item::FIELD_ITEM)
4212
4256
field_item= (Item_field*) (func->key_item()->real_item());
4213
4257
ftree= get_full_func_mm_tree(param, cond_func, field_item, NULL, inv);
4216
4260
case Item_func::MULT_EQUAL_FUNC:
4218
Item_equal *item_equal= (Item_equal *) cond;
4262
Item_equal *item_equal= (Item_equal *) cond;
4219
4263
if (!(value= item_equal->get_const()))
4221
4265
Item_equal_iterator it(*item_equal);
4222
4266
ref_tables= value->used_tables();
4223
4267
while ((field_item= it++))
4225
4269
Field *field= field_item->field;
4270
field->setWriteSet();
4226
4272
Item_result cmp_type= field->cmp_type();
4227
4273
if (!((ref_tables | field->table->map) & param_comp))
4259
4305
static SEL_TREE *
4260
4306
get_mm_parts(RANGE_OPT_PARAM *param, COND *cond_func, Field *field,
4261
4307
Item_func::Functype type,
4263
Item_result cmp_type __attribute__((unused)))
4308
Item *value, Item_result)
4265
4310
if (field->table != param->table)
4268
4313
KEY_PART *key_part = param->key_parts;
4269
4314
KEY_PART *end = param->key_parts_end;
4270
4315
SEL_TREE *tree=0;
4272
4317
value->used_tables() & ~(param->prev_tables | param->read_tables))
4274
4319
for (; key_part != end ; key_part++)
4276
4321
if (field->eq(key_part->field))
4278
4323
SEL_ARG *sel_arg=0;
4279
4324
if (!tree && !(tree=new SEL_TREE()))
4281
4326
if (!value || !(value->used_tables() & ~param->read_tables))
4283
4328
sel_arg=get_mm_leaf(param,cond_func,
4465
4511
value->result_type() != STRING_RESULT &&
4466
4512
field->cmp_type() != value->result_type())
4468
/* For comparison purposes allow invalid dates like 2000-01-32 */
4469
orig_sql_mode= field->table->in_use->variables.sql_mode;
4470
if (value->real_item()->type() == Item::STRING_ITEM &&
4471
(field->type() == DRIZZLE_TYPE_NEWDATE ||
4472
field->type() == DRIZZLE_TYPE_DATETIME))
4473
field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES;
4474
err= value->save_in_field_no_warnings(field, 1);
4516
* Some notes from Jay...
4518
* OK, so previously, and in MySQL, what the optimizer does here is
4519
* override the sql_mode variable to ignore out-of-range or bad date-
4520
* time values. It does this because the optimizer is populating the
4521
* field variable with the incoming value from the comparison field,
4522
* and the value may exceed the bounds of a proper column type.
4524
* For instance, assume the following:
4526
* CREATE TABLE t1 (ts TIMESTAMP);
4527
* INSERT INTO t1 ('2009-03-04 00:00:00');
4528
* CREATE TABLE t2 (dt1 DATETIME, dt2 DATETIME);
4529
* INSERT INT t2 ('2003-12-31 00:00:00','2999-12-31 00:00:00');
4531
* If we issue this query:
4533
* SELECT * FROM t1, t2 WHERE t1.ts BETWEEN t2.dt1 AND t2.dt2;
4535
* We will come into bounds issues. Field_timestamp::store() will be
4536
* called with a datetime value of "2999-12-31 00:00:00" and will throw
4537
* an error for out-of-bounds. MySQL solves this via a hack with sql_mode
4538
* but Drizzle always throws errors on bad data storage in a Field class.
4540
* Therefore, to get around the problem of the Field class being used for
4541
* "storage" here without actually storing anything...we must check to see
4542
* if the value being stored in a Field_timestamp here is out of range. If
4543
* it is, then we must convert to the highest Timestamp value (or lowest,
4544
* depending on whether the datetime is before or after the epoch.
4546
if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
4549
* The left-side of the range comparison is a timestamp field. Therefore,
4550
* we must check to see if the value in the right-hand side is outside the
4551
* range of the UNIX epoch, and cut to the epoch bounds if it is.
4553
/* Datetime and date columns are Item::FIELD_ITEM ... and have a result type of STRING_RESULT */
4554
if (value->real_item()->type() == Item::FIELD_ITEM
4555
&& value->result_type() == STRING_RESULT)
4557
char buff[drizzled::DateTime::MAX_STRING_LENGTH];
4558
String tmp(buff, sizeof(buff), &my_charset_bin);
4559
String *res= value->val_str(&tmp);
4566
* Create a datetime from the string and compare to fixed timestamp
4567
* instances representing the epoch boundaries.
4569
drizzled::DateTime value_datetime;
4571
if (! value_datetime.from_string(res->c_ptr(), (size_t) res->length()))
4574
drizzled::Timestamp max_timestamp;
4575
drizzled::Timestamp min_timestamp;
4577
(void) max_timestamp.from_time_t((time_t) INT32_MAX);
4578
(void) min_timestamp.from_time_t((time_t) 0);
4580
/* We rely on Temporal class operator overloads to do our comparisons. */
4581
if (value_datetime < min_timestamp)
4584
* Datetime in right-hand side column is before UNIX epoch, so adjust to
4587
char new_value_buff[drizzled::DateTime::MAX_STRING_LENGTH];
4588
int new_value_length;
4589
String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
4591
new_value_length= min_timestamp.to_string(new_value_string.c_ptr(),
4592
drizzled::DateTime::MAX_STRING_LENGTH);
4593
assert((new_value_length+1) < drizzled::DateTime::MAX_STRING_LENGTH);
4594
new_value_string.length(new_value_length);
4595
err= value->save_str_value_in_field(field, &new_value_string);
4597
else if (value_datetime > max_timestamp)
4600
* Datetime in right hand side column is after UNIX epoch, so adjust
4601
* to the higher bound of the epoch.
4603
char new_value_buff[drizzled::DateTime::MAX_STRING_LENGTH];
4604
int new_value_length;
4605
String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
4607
new_value_length= max_timestamp.to_string(new_value_string.c_ptr(),
4608
drizzled::DateTime::MAX_STRING_LENGTH);
4609
assert((new_value_length+1) < drizzled::DateTime::MAX_STRING_LENGTH);
4610
new_value_string.length(new_value_length);
4611
err= value->save_str_value_in_field(field, &new_value_string);
4614
err= value->save_in_field(field, 1);
4617
else /* Not a datetime -> timestamp comparison */
4618
err= value->save_in_field(field, 1);
4620
else /* Not a timestamp comparison */
4621
err= value->save_in_field(field, 1);
4477
4625
if (field->cmp_type() != value->result_type())
4739
4884
using index_merge.
4742
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2,
4887
bool sel_trees_can_be_ored(SEL_TREE *tree1, SEL_TREE *tree2,
4743
4888
RANGE_OPT_PARAM* param)
4745
4890
key_map common_keys= tree1->keys_map;
4746
common_keys.intersect(tree2->keys_map);
4891
common_keys&= tree2->keys_map;
4748
if (common_keys.is_clear_all())
4893
if (common_keys.none())
4751
4896
/* trees have a common key, check if they refer to same key part */
4752
4897
SEL_ARG **key1,**key2;
4753
4898
for (uint32_t key_no=0; key_no < param->keys; key_no++)
4755
if (common_keys.is_set(key_no))
4900
if (common_keys.test(key_no))
4757
4902
key1= tree1->keys + key_no;
4758
4903
key2= tree2->keys + key_no;
4759
4904
if ((*key1)->part == (*key2)->part)
4793
4938
call tree_and(tree1, tree2) -- this joins SEL_ARGs into a usable SEL_ARG
4796
4941
There is an exception though: when we construct index_merge SEL_TREE,
4797
4942
any SEL_ARG* tree that cannot be used to construct quick range select can
4798
4943
be removed, because current range analysis code doesn't provide any way
4799
4944
that tree could be later combined with another tree.
4800
4945
Consider an example: we should not construct
4802
merges = SEL_IMERGE {
4803
SEL_TREE(t.key1part1 = 1),
4947
merges = SEL_IMERGE {
4948
SEL_TREE(t.key1part1 = 1),
4804
4949
SEL_TREE(t.key2part2 = 2) -- (*)
4808
- (*) cannot be used to construct quick range select,
4809
- There is no execution path that would cause (*) to be converted to
4953
- (*) cannot be used to construct quick range select,
4954
- There is no execution path that would cause (*) to be converted to
4810
4955
a tree that could be used.
4812
4957
The latter is easy to verify: first, notice that the only way to convert
4813
4958
(*) into a usable tree is to call tree_and(something, (*)).
4815
4960
Second look at what tree_and/tree_or function would do when passed a
4816
SEL_TREE that has the structure like st1 tree has, and conlcude that
4961
SEL_TREE that has the structure like st1 tree has, and conlcude that
4817
4962
tree_and(something, (*)) will not be called.
4892
5037
return(new SEL_TREE(SEL_TREE::ALWAYS));
4895
/* both trees are "range" trees, produce new index merge structure */
4896
if (!(result= new SEL_TREE()) || !(merge= new SEL_IMERGE()) ||
4897
(result->merges.push_back(merge)) ||
4898
(merge->or_sel_tree(param, tree1)) ||
4899
(merge->or_sel_tree(param, tree2)))
5040
/* both trees are "range" trees, produce new index merge structure. */
5041
result= new SEL_TREE();
5042
SEL_IMERGE *merge= new SEL_IMERGE();
5043
result->merges.push_back(merge);
5045
if( merge->or_sel_tree(param, tree1) || merge->or_sel_tree(param, tree2))
4902
5048
result->type= tree1->type;
4904
else if (!tree1->merges.is_empty() && !tree2->merges.is_empty())
5050
else if ((tree1->merges.empty() == false) && (tree2->merges.empty() == false))
4906
if (imerge_list_or_list(param, &tree1->merges, &tree2->merges))
5052
if (imerge_list_or_list(param, tree1->merges, tree2->merges))
4907
5053
result= new SEL_TREE(SEL_TREE::ALWAYS);
4913
5059
/* one tree is index merge tree and another is range tree */
4914
if (tree1->merges.is_empty())
5060
if (tree1->merges.empty() == true)
4915
5061
std::swap(tree1, tree2);
4917
5063
if (param->remove_jump_scans && remove_nonrange_trees(param, tree2))
4918
5064
return(new SEL_TREE(SEL_TREE::ALWAYS));
4919
5066
/* add tree2 to tree1->merges, checking if it collapses to ALWAYS */
4920
if (imerge_list_or_tree(param, &tree1->merges, tree2))
5067
if (imerge_list_or_tree(param, tree1->merges, tree2))
4921
5068
result= new SEL_TREE(SEL_TREE::ALWAYS);
4930
5077
/* And key trees where key1->part < key2 -> part */
4932
5079
static SEL_ARG *
4933
and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
5080
and_all_keys(RANGE_OPT_PARAM *param, SEL_ARG *key1, SEL_ARG *key2,
4934
5081
uint32_t clone_flag)
5729
5881
return 0; // Found end of tree
5730
5882
if (element->parent != parent)
5732
sql_print_error("Wrong tree: Parent doesn't point at parent");
5884
errmsg_printf(ERRMSG_LVL_ERROR, "Wrong tree: Parent doesn't point at parent");
5735
5887
if (element->color == SEL_ARG::RED &&
5736
5888
(element->left->color == SEL_ARG::RED ||
5737
5889
element->right->color == SEL_ARG::RED))
5739
sql_print_error("Wrong tree: Found two red in a row");
5891
errmsg_printf(ERRMSG_LVL_ERROR, "Wrong tree: Found two red in a row");
5742
5894
if (element->left == element->right && element->left != &null_element)
5743
5895
{ // Dummy test
5744
sql_print_error("Wrong tree: Found right == left");
5896
errmsg_printf(ERRMSG_LVL_ERROR, "Wrong tree: Found right == left");
5747
5899
count_l=test_rb_tree(element->left,element);
5870
6022
****************************************************************************/
5872
6024
/* MRR range sequence, SEL_ARG* implementation: stack entry */
5873
typedef struct st_range_seq_entry
6025
typedef struct st_range_seq_entry
5876
6028
Pointers in min and max keys. They point to right-after-end of key
5877
6029
images. The 0-th entry has these pointing to key tuple start.
5879
6031
unsigned char *min_key, *max_key;
5882
6034
Flags, for {keypart0, keypart1, ... this_keypart} subtuple.
5883
6035
min_key_flag may have NULL_RANGE set.
5885
6037
uint32_t min_key_flag, max_key_flag;
5887
6039
/* Number of key parts */
5888
6040
uint32_t min_key_parts, max_key_parts;
5889
6041
SEL_ARG *key_tree;
6085
6235
/* Ok got a tuple */
6086
6236
RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i];
6088
6238
range->ptr= (char*)(int)(key_tree->part);
6090
6240
range->range_flag= cur->min_key_flag | cur->max_key_flag;
6092
6242
range->start_key.key= seq->param->min_key;
6093
6243
range->start_key.length= cur->min_key - seq->param->min_key;
6094
6244
range->start_key.keypart_map= make_prev_keypart_map(cur->min_key_parts);
6095
range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
6245
range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY :
6096
6246
HA_READ_KEY_EXACT);
6098
6248
range->end_key.key= seq->param->max_key;
6099
6249
range->end_key.length= cur->max_key - seq->param->max_key;
6100
range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
6250
range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
6101
6251
HA_READ_AFTER_KEY);
6102
6252
range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts);
6104
6254
if (!(cur->min_key_flag & ~NULL_RANGE) && !cur->max_key_flag &&
6105
(uint)key_tree->part+1 == seq->param->table->key_info[seq->real_keyno].key_parts &&
6255
(uint32_t)key_tree->part+1 == seq->param->table->key_info[seq->real_keyno].key_parts &&
6106
6256
(seq->param->table->key_info[seq->real_keyno].flags & (HA_NOSAME)) ==
6108
6258
range->start_key.length == range->end_key.length &&
6109
6259
!memcmp(seq->param->min_key,seq->param->max_key,range->start_key.length))
6110
6260
range->range_flag= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
6112
6262
if (seq->param->is_ror_scan)
6190
6340
param->is_ror_scan= true;
6191
6341
if (file->index_flags(keynr, 0, true) & HA_KEY_SCAN_NOT_ROR)
6192
6342
param->is_ror_scan= false;
6194
6344
*mrr_flags= param->force_default_mrr? HA_MRR_USE_DEFAULT_IMPL: 0;
6195
6345
*mrr_flags|= HA_MRR_NO_ASSOCIATION;
6197
6347
bool pk_is_clustered= file->primary_key_is_clustered();
6199
6349
(file->index_flags(keynr, param->max_key_part, 1) & HA_KEYREAD_ONLY) &&
6200
6350
!(pk_is_clustered && keynr == param->table->s->primary_key))
6201
6351
*mrr_flags |= HA_MRR_INDEX_ONLY;
6203
if (current_thd->lex->sql_command != SQLCOM_SELECT)
6353
if (current_session->lex->sql_command != SQLCOM_SELECT)
6204
6354
*mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
6206
*bufsize= param->thd->variables.read_rnd_buff_size;
6356
*bufsize= param->session->variables.read_rnd_buff_size;
6207
6357
rows= file->multi_range_read_info_const(keynr, &seq_if, (void*)&seq, 0,
6208
6358
bufsize, mrr_flags, cost);
6209
6359
if (rows != HA_POS_ERROR)
6211
6361
param->table->quick_rows[keynr]=rows;
6212
6362
if (update_tbl_stats)
6214
param->table->quick_keys.set_bit(keynr);
6364
param->table->quick_keys.set(keynr);
6215
6365
param->table->quick_key_parts[keynr]=param->max_key_part+1;
6216
6366
param->table->quick_n_ranges[keynr]= param->range_count;
6217
6367
param->table->quick_condition_rows=
6218
cmin(param->table->quick_condition_rows, rows);
6368
min(param->table->quick_condition_rows, rows);
6221
6371
/* Figure out if the key scan is ROR (returns rows in ROWID order) or not */
6222
6372
enum ha_key_alg key_alg= param->table->key_info[seq.real_keyno].algorithm;
6223
6373
if ((key_alg != HA_KEY_ALG_BTREE) && (key_alg!= HA_KEY_ALG_UNDEF))
6226
6376
All scans are non-ROR scans for those index types.
6227
TODO: Don't have this logic here, make table engines return
6377
TODO: Don't have this logic here, make table engines return
6228
6378
appropriate flags instead.
6230
6380
param->is_ror_scan= false;
6264
6414
where the index is defined on (key1_1, ..., key1_N [,a_1, ..., a_n])
6266
and the table has a clustered Primary Key defined as
6267
PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k)
6269
i.e. the first key parts of it are identical to uncovered parts ot the
6416
and the table has a clustered Primary Key defined as
6417
PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k)
6419
i.e. the first key parts of it are identical to uncovered parts ot the
6270
6420
key being scanned. This function assumes that the index flags do not
6271
6421
include HA_KEY_SCAN_NOT_ROR flag (that is checked elsewhere).
6467
6617
/* Get range for retrieving rows in QUICK_SELECT::get_next */
6468
6618
if (!(range= new QUICK_RANGE(param->min_key,
6469
(uint) (tmp_min_key - param->min_key),
6619
(uint32_t) (tmp_min_key - param->min_key),
6470
6620
min_part >=0 ? make_keypart_map(min_part) : 0,
6471
6621
param->max_key,
6472
(uint) (tmp_max_key - param->max_key),
6622
(uint32_t) (tmp_max_key - param->max_key),
6473
6623
max_part >=0 ? make_keypart_map(max_part) : 0,
6475
6625
return 1; // out of memory
6477
set_if_bigger(quick->max_used_key_length, range->min_length);
6478
set_if_bigger(quick->max_used_key_length, range->max_length);
6479
set_if_bigger(quick->used_key_parts, (uint) key_tree->part+1);
6627
set_if_bigger(quick->max_used_key_length, (uint32_t)range->min_length);
6628
set_if_bigger(quick->max_used_key_length, (uint32_t)range->max_length);
6629
set_if_bigger(quick->used_key_parts, (uint32_t) key_tree->part+1);
6480
6630
if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
6539
bool QUICK_SELECT_I::is_keys_used(const MY_BITMAP *fields)
6689
bool QUICK_SELECT_I::is_keys_used(const MyBitmap *fields)
6541
6691
return is_key_used(head, index, fields);
6544
bool QUICK_INDEX_MERGE_SELECT::is_keys_used(const MY_BITMAP *fields)
6546
QUICK_RANGE_SELECT *quick;
6547
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
6548
while ((quick= it++))
6550
if (is_key_used(head, quick->index, fields))
6556
bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MY_BITMAP *fields)
6558
QUICK_RANGE_SELECT *quick;
6559
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
6560
while ((quick= it++))
6562
if (is_key_used(head, quick->index, fields))
6568
bool QUICK_ROR_UNION_SELECT::is_keys_used(const MY_BITMAP *fields)
6694
bool QUICK_INDEX_MERGE_SELECT::is_keys_used(const MyBitmap *fields)
6696
QUICK_RANGE_SELECT *quick;
6697
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
6698
while ((quick= it++))
6700
if (is_key_used(head, quick->index, fields))
6706
bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(const MyBitmap *fields)
6708
QUICK_RANGE_SELECT *quick;
6709
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
6710
while ((quick= it++))
6712
if (is_key_used(head, quick->index, fields))
6718
bool QUICK_ROR_UNION_SELECT::is_keys_used(const MyBitmap *fields)
6570
6720
QUICK_SELECT_I *quick;
6571
6721
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
6609
6759
bool create_err= false;
6610
6760
COST_VECT cost;
6612
old_root= thd->mem_root;
6613
/* The following call may change thd->mem_root */
6614
quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0, 0, &create_err);
6762
old_root= session->mem_root;
6763
/* The following call may change session->mem_root */
6764
quick= new QUICK_RANGE_SELECT(session, table, ref->key, 0, 0, &create_err);
6615
6765
/* save mem_root set by QUICK_RANGE_SELECT constructor */
6616
alloc= thd->mem_root;
6766
alloc= session->mem_root;
6618
return back default mem_root (thd->mem_root) changed by
6768
return back default mem_root (session->mem_root) changed by
6619
6769
QUICK_RANGE_SELECT constructor
6621
thd->mem_root= old_root;
6771
session->mem_root= old_root;
6623
6773
if (!quick || create_err)
6624
6774
return 0; /* no ranges found */
6678
6829
/* Call multi_range_read_info() to get the MRR flags and buffer size */
6679
quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
6830
quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
6680
6831
(table->key_read ? HA_MRR_INDEX_ONLY : 0);
6681
if (thd->lex->sql_command != SQLCOM_SELECT)
6832
if (session->lex->sql_command != SQLCOM_SELECT)
6682
6833
quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
6684
quick->mrr_buf_size= thd->variables.read_rnd_buff_size;
6685
if (table->file->multi_range_read_info(quick->index, 1, (uint)records,
6835
quick->mrr_buf_size= session->variables.read_rnd_buff_size;
6836
if (table->file->multi_range_read_info(quick->index, 1, (uint32_t)records,
6686
6837
&quick->mrr_buf_size,
6687
6838
&quick->mrr_flags, &cost))
7100
MRR range sequence interface: array<QUICK_RANGE> impl: utility func for NDB
7103
mrr_persistent_flag_storage()
7104
seq Range sequence being traversed
7108
MRR/NDB implementation needs to store some bits for each range. This
7109
function returns a reference to the "range_flag" associated with the
7112
This function should be removed when we get a proper MRR/NDB
7116
Reference to range_flag associated with range number #idx
7119
uint16_t &mrr_persistent_flag_storage(range_seq_t seq, uint32_t idx)
7121
QUICK_RANGE_SEQ_CTX *ctx= (QUICK_RANGE_SEQ_CTX*)seq;
7122
return ctx->first[idx]->flag;
7127
MRR range sequence interface: array<QUICK_RANGE> impl: utility func for NDB
7130
mrr_get_ptr_by_idx()
7131
seq Range sequence bening traversed
7132
idx Number of the range
7135
An extension of MRR range sequence interface needed by NDB: return the
7136
data associated with the given range.
7138
A proper MRR interface implementer is supposed to store and return
7139
range-associated data. NDB stores number of the range instead. So this
7140
is a helper function that translates range number to range associated
7143
This function does nothing, as currrently there is only one user of the
7144
MRR interface - the quick range select code, and this user doesn't need
7145
to use range-associated data.
7148
Reference to range-associated data
7151
char* &mrr_get_ptr_by_idx(range_seq_t seq __attribute__((unused)),
7152
uint32_t idx __attribute__((unused)))
7160
7250
Get next possible record using quick-struct.
7246
7336
/* Ranges have already been used up before. None is left for read. */
7248
return(HA_ERR_END_OF_FILE);
7338
return HA_ERR_END_OF_FILE;
7250
7340
last_range= *(cur_range++);
7252
7342
start_key.key= (const unsigned char*) last_range->min_key;
7253
start_key.length= cmin(last_range->min_length, (uint16_t)prefix_length);
7343
start_key.length= min(last_range->min_length, (uint16_t)prefix_length);
7254
7344
start_key.keypart_map= last_range->min_keypart_map & keypart_map;
7255
7345
start_key.flag= ((last_range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
7256
7346
(last_range->flag & EQ_RANGE) ?
7257
7347
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
7258
7348
end_key.key= (const unsigned char*) last_range->max_key;
7259
end_key.length= cmin(last_range->max_length, (uint16_t)prefix_length);
7349
end_key.length= min(last_range->max_length, (uint16_t)prefix_length);
7260
7350
end_key.keypart_map= last_range->max_keypart_map & keypart_map;
7262
7352
We use READ_AFTER_KEY here because if we are reading on a key
7686
7774
static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
7687
7775
KEY_PART_INFO *first_non_group_part,
7688
7776
KEY_PART_INFO *min_max_arg_part,
7689
KEY_PART_INFO *last_part, THD *thd,
7777
KEY_PART_INFO *last_part, Session *session,
7690
7778
unsigned char *key_infix, uint32_t *key_infix_len,
7691
7779
KEY_PART_INFO **first_non_infix_part);
7693
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
7694
Field::imagetype image_type);
7780
static bool check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item);
7697
7783
cost_group_min_max(Table* table, KEY *index_info, uint32_t used_key_parts,
8162
8253
COST_VECT dummy_cost;
8163
8254
uint32_t mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
8164
8255
uint32_t mrr_bufsize=0;
8165
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
8166
false /*don't care*/,
8256
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
8257
false /*don't care*/,
8167
8258
cur_index_tree, true,
8168
8259
&mrr_flags, &mrr_bufsize,
8171
cost_group_min_max(table, cur_index_info, used_key_parts,
8262
cost_group_min_max(table, cur_index_info, cur_used_key_parts,
8172
8263
cur_group_key_parts, tree, cur_index_tree,
8173
8264
cur_quick_prefix_records, have_min, have_max,
8174
8265
&cur_read_cost, &cur_records);
8189
8280
best_param_idx= cur_param_idx;
8190
8281
group_key_parts= cur_group_key_parts;
8191
8282
group_prefix_len= cur_group_prefix_len;
8283
key_infix_len= cur_key_infix_len;
8285
memcpy (key_infix, cur_key_infix, sizeof (key_infix));
8286
used_key_parts= cur_used_key_parts;
8195
8290
cur_group_key_parts= 0;
8196
8291
cur_group_prefix_len= 0;
8292
cur_key_infix_len= 0;
8198
8294
if (!index_info) /* No usable index found. */
8201
8297
/* Check (SA3) for the where clause. */
8202
8298
if (join->conds && min_max_arg_item &&
8203
!check_group_min_max_predicates(join->conds, min_max_arg_item, Field::itRAW))
8299
! check_group_min_max_predicates(join->conds, min_max_arg_item))
8206
8302
/* The query passes all tests, so construct a new TRP object. */
8207
8303
read_plan= new (param->mem_root)
8392
get_constant_key_infix(KEY *index_info __attribute__((unused)),
8393
SEL_ARG *index_range_tree,
8482
get_constant_key_infix(KEY *, SEL_ARG *index_range_tree,
8394
8483
KEY_PART_INFO *first_non_group_part,
8395
8484
KEY_PART_INFO *min_max_arg_part,
8396
8485
KEY_PART_INFO *last_part,
8397
THD *thd __attribute__((unused)),
8398
unsigned char *key_infix, uint32_t *key_infix_len,
8486
Session *, unsigned char *key_infix, uint32_t *key_infix_len,
8399
8487
KEY_PART_INFO **first_non_infix_part)
8401
8489
SEL_ARG *cur_range;
8609
8696
keys_per_block= (table->file->stats.block_size / 2 /
8610
8697
(index_info->key_length + table->file->ref_length)
8612
num_blocks= (uint)(table_records / keys_per_block) + 1;
8699
num_blocks= (uint32_t)(table_records / keys_per_block) + 1;
8614
8701
/* Compute the number of keys in a group. */
8615
8702
keys_per_group= index_info->rec_per_key[group_key_parts - 1];
8616
8703
if (keys_per_group == 0) /* If there is no statistics try to guess */
8617
8704
/* each group contains 10% of all records */
8618
keys_per_group= (uint)(table_records / 10) + 1;
8619
num_groups= (uint)(table_records / keys_per_group) + 1;
8705
keys_per_group= (uint32_t)(table_records / 10) + 1;
8706
num_groups= (uint32_t)(table_records / keys_per_group) + 1;
8621
8708
/* Apply the selectivity of the quick select for group prefixes. */
8622
8709
if (range_tree && (quick_prefix_records != HA_POS_ERROR))
8624
8711
quick_prefix_selectivity= (double) quick_prefix_records /
8625
8712
(double) table_records;
8626
num_groups= (uint) rint(num_groups * quick_prefix_selectivity);
8627
set_if_bigger(num_groups, 1);
8713
num_groups= (uint32_t) rint(num_groups * quick_prefix_selectivity);
8714
set_if_bigger(num_groups, 1U);
8630
8717
if (used_key_parts > group_key_parts)
8686
8772
QUICK_SELECT_I *
8687
TRP_GROUP_MIN_MAX::make_quick(PARAM *param,
8688
bool retrieve_full_rows __attribute__((unused)),
8689
MEM_ROOT *parent_alloc)
8773
TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool, MEM_ROOT *parent_alloc)
8691
8775
QUICK_GROUP_MIN_MAX_SELECT *quick;
8693
8777
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
8694
param->thd->lex->current_select->join,
8778
param->session->lex->current_select->join,
8695
8779
have_min, have_max, min_max_arg_part,
8696
8780
group_prefix_len, group_key_parts,
8697
8781
used_key_parts, index_info, index,
8698
8782
read_cost, records, key_infix_len,
8699
8783
key_infix, parent_alloc);
8703
8787
if (quick->init())
8709
8793
if (range_tree)
9510
9596
if ( !(cur_range->flag & NO_MAX_RANGE) )
9512
9598
/* Compose the MAX key for the range. */
9513
unsigned char *max_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
9514
memcpy(max_key, group_prefix, real_prefix_len);
9515
memcpy(max_key + real_prefix_len, cur_range->max_key,
9516
cur_range->max_length);
9600
max_key.append(group_prefix, real_prefix_len);
9601
max_key.append(cur_range->max_key, cur_range->max_length);
9517
9602
/* Compare the found key with max_key. */
9518
int cmp_res= key_cmp(index_info->key_part, max_key,
9603
int cmp_res= key_cmp(index_info->key_part,
9519
9605
real_prefix_len + min_max_arg_len);
9520
if ((!((cur_range->flag & NEAR_MAX) && (cmp_res == -1)) || (cmp_res <= 0)))
9606
if (!(((cur_range->flag & NEAR_MAX) && (cmp_res == -1)) ||
9522
9609
result= HA_ERR_KEY_NOT_FOUND;
9627
9716
if ( !(cur_range->flag & NO_MIN_RANGE) )
9629
9718
/* Compose the MIN key for the range. */
9630
unsigned char *min_key= (unsigned char*) my_alloca(real_prefix_len + min_max_arg_len);
9631
memcpy(min_key, group_prefix, real_prefix_len);
9632
memcpy(min_key + real_prefix_len, cur_range->min_key,
9633
cur_range->min_length);
9720
min_key.append(group_prefix, real_prefix_len);
9721
min_key.append(cur_range->min_key, cur_range->min_length);
9634
9723
/* Compare the found key with min_key. */
9635
int cmp_res= key_cmp(index_info->key_part, min_key,
9724
int cmp_res= key_cmp(index_info->key_part,
9636
9726
real_prefix_len + min_max_arg_len);
9637
if ((!((cur_range->flag & NEAR_MIN) && (cmp_res == 1)) ||
9727
if (!(((cur_range->flag & NEAR_MIN) && (cmp_res == 1)) ||
9638
9728
(cmp_res >= 0)))