112
112
#include <boost/dynamic_bitset.hpp>
114
#include "drizzled/check_stack_overrun.h"
115
#include "drizzled/error.h"
116
#include "drizzled/field/num.h"
117
#include "drizzled/internal/iocache.h"
118
#include "drizzled/internal/my_sys.h"
119
#include "drizzled/item/cmpfunc.h"
120
#include "drizzled/optimizer/cost_vector.h"
121
#include "drizzled/optimizer/quick_group_min_max_select.h"
122
#include "drizzled/optimizer/quick_index_merge_select.h"
123
#include "drizzled/optimizer/quick_range.h"
124
#include "drizzled/optimizer/quick_range_select.h"
125
#include "drizzled/optimizer/quick_ror_intersect_select.h"
126
#include "drizzled/optimizer/quick_ror_union_select.h"
127
#include "drizzled/optimizer/range.h"
128
#include "drizzled/optimizer/range_param.h"
129
#include "drizzled/optimizer/sel_arg.h"
130
#include "drizzled/optimizer/sel_imerge.h"
131
#include "drizzled/optimizer/sel_tree.h"
132
#include "drizzled/optimizer/sum.h"
133
#include "drizzled/optimizer/table_read_plan.h"
134
#include "drizzled/plugin/storage_engine.h"
135
#include "drizzled/records.h"
136
#include "drizzled/sql_base.h"
137
#include "drizzled/sql_select.h"
138
#include "drizzled/table_reference.h"
140
#include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
114
#include <drizzled/check_stack_overrun.h>
115
#include <drizzled/error.h>
116
#include <drizzled/field/num.h>
117
#include <drizzled/internal/iocache.h>
118
#include <drizzled/internal/my_sys.h>
119
#include <drizzled/item/cmpfunc.h>
120
#include <drizzled/optimizer/cost_vector.h>
121
#include <drizzled/optimizer/quick_group_min_max_select.h>
122
#include <drizzled/optimizer/quick_index_merge_select.h>
123
#include <drizzled/optimizer/quick_range.h>
124
#include <drizzled/optimizer/quick_range_select.h>
125
#include <drizzled/optimizer/quick_ror_intersect_select.h>
126
#include <drizzled/optimizer/quick_ror_union_select.h>
127
#include <drizzled/optimizer/range.h>
128
#include <drizzled/optimizer/range_param.h>
129
#include <drizzled/optimizer/sel_arg.h>
130
#include <drizzled/optimizer/sel_imerge.h>
131
#include <drizzled/optimizer/sel_tree.h>
132
#include <drizzled/optimizer/sum.h>
133
#include <drizzled/optimizer/table_read_plan.h>
134
#include <drizzled/plugin/storage_engine.h>
135
#include <drizzled/records.h>
136
#include <drizzled/sql_base.h>
137
#include <drizzled/sql_select.h>
138
#include <drizzled/table_reference.h>
139
#include <drizzled/session.h>
140
#include <drizzled/key.h>
141
#include <drizzled/unique.h>
142
#include <drizzled/temporal.h> /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */
143
#include <drizzled/sql_lex.h>
144
#include <drizzled/system_variables.h>
142
146
using namespace std;
146
150
#define HA_END_SPACE_KEY 0
288
292
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree);
290
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
291
optimizer::SEL_TREE *tree1,
294
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
295
optimizer::SEL_TREE *tree1,
292
296
optimizer::SEL_TREE *tree2);
294
298
static optimizer::SEL_ARG *sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
691
686
param.force_default_mrr= ordered_output;
693
688
session->no_errors=1; // Don't warn about NULL
694
memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
695
if (!(param.key_parts= (KEY_PART*) alloc.alloc_root( sizeof(KEY_PART) * head->getShare()->key_parts)) ||
696
fill_used_fields_bitmap(¶m))
689
alloc.init(session->variables.range_alloc_block_size);
690
param.key_parts= new (alloc) KEY_PART[head->getShare()->key_parts];
691
if (fill_used_fields_bitmap(¶m))
698
693
session->no_errors=0;
699
694
alloc.free_root(MYF(0)); // Return memory & allocator
976
966
ha_rows roru_total_records;
977
967
double roru_intersect_part= 1.0;
979
if (! (range_scans= (optimizer::RangeReadPlan**)param->mem_root->alloc_root(sizeof(optimizer::RangeReadPlan*)* n_child_scans)))
969
range_scans= new (*param->mem_root) optimizer::RangeReadPlan*[n_child_scans];
985
972
Collect best 'range' scan for each of disjuncts, and, while doing so,
986
973
analyze possibility of ROR scans. Also calculate some values needed by
987
974
other parts of the code.
989
for (ptree= imerge->trees, cur_child= range_scans;
990
ptree != imerge->trees_next;
991
ptree++, cur_child++)
976
for (ptree= imerge->trees, cur_child= range_scans; ptree != imerge->trees_next; ptree++, cur_child++)
993
978
if (!(*cur_child= get_key_scans_params(session, param, *ptree, true, false, read_time)))
1073
1054
param->session->variables.sortbuff_size);
1074
1055
if (imerge_cost < read_time)
1076
if ((imerge_trp= new (param->mem_root) optimizer::IndexMergeReadPlan))
1078
imerge_trp->read_cost= imerge_cost;
1079
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1080
imerge_trp->records= min(imerge_trp->records,
1081
param->table->cursor->stats.records);
1082
imerge_trp->range_scans= range_scans;
1083
imerge_trp->range_scans_end= range_scans + n_child_scans;
1084
read_time= imerge_cost;
1057
imerge_trp= new (*param->mem_root) optimizer::IndexMergeReadPlan;
1058
imerge_trp->read_cost= imerge_cost;
1059
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1060
imerge_trp->records= min(imerge_trp->records, param->table->cursor->stats.records);
1061
imerge_trp->range_scans= range_scans;
1062
imerge_trp->range_scans_end= range_scans + n_child_scans;
1063
read_time= imerge_cost;
1088
1066
build_ror_index_merge:
1089
if (!all_scans_ror_able || param->session->lex->sql_command == SQLCOM_DELETE)
1067
if (!all_scans_ror_able || param->session->lex().sql_command == SQLCOM_DELETE)
1090
1068
return(imerge_trp);
1092
1070
/* Ok, it is possible to build a ROR-union, try it. */
1094
if (! (roru_read_plans=
1095
(optimizer::TableReadPlan **) param->mem_root->alloc_root(sizeof(optimizer::TableReadPlan*) * n_child_scans)))
1072
roru_read_plans= new (*param->mem_root) optimizer::TableReadPlan*[n_child_scans];
1099
1073
skip_to_ror_scan:
1100
1074
roru_index_costs= 0.0;
1101
1075
roru_total_records= 0;
1161
1135
double roru_total_cost;
1163
1137
optimizer::CostVector sweep_cost;
1164
Join *join= param->session->lex->select_lex.join;
1138
Join *join= param->session->lex().select_lex.join;
1165
1139
bool is_interrupted= test(join && join->tables == 1);
1166
1140
get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
1168
1142
roru_total_cost= roru_index_costs +
1169
rows2double(roru_total_records)*log((double)n_child_scans) /
1143
static_cast<double>(roru_total_records)*log((double)n_child_scans) /
1170
1144
(TIME_FOR_COMPARE_ROWID * M_LN2) +
1171
1145
sweep_cost.total_cost();
1704
1671
cost total_cost.
1706
1673
/* Add priority queue use cost. */
1707
total_cost += rows2double(records)*
1674
total_cost += static_cast<double>(records) *
1708
1675
log((double)(ror_scan_mark - tree->ror_scans)) /
1709
1676
(TIME_FOR_COMPARE_ROWID * M_LN2);
1711
1678
if (total_cost > read_time)
1714
optimizer::RorIntersectReadPlan *trp= NULL;
1715
if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1681
optimizer::RorIntersectReadPlan* trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
1720
1683
uint32_t best_num= (ror_scan_mark - tree->ror_scans);
1721
if (!(trp->first_scan= (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)* best_num)))
1684
trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
1723
1685
memcpy(trp->first_scan, tree->ror_scans, best_num*sizeof(optimizer::RorScanInfo*));
1724
1686
trp->last_scan= trp->first_scan + best_num;
1725
1687
trp->is_covering= true;
1911
1867
optimizer::RorIntersectReadPlan *trp= NULL;
1912
1868
if (min_cost < read_time && (cpk_scan_used || best_num > 1))
1914
if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1917
if (! (trp->first_scan=
1918
(optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)*best_num)))
1870
trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
1871
trp->first_scan= new (*param->mem_root) optimizer::RorScanInfo*[best_num];
1920
1872
memcpy(trp->first_scan, intersect_scans, best_num*sizeof(optimizer::RorScanInfo*));
1921
1873
trp->last_scan= trp->first_scan + best_num;
1922
1874
trp->is_covering= intersect_best.is_covering;
2022
1974
if (key_to_read)
2024
1976
idx= key_to_read - tree->keys;
2025
if ((read_plan= new (param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx,
2028
read_plan->records= best_records;
2029
read_plan->is_ror= tree->ror_scans_map.test(idx);
2030
read_plan->read_cost= read_time;
2031
read_plan->mrr_buf_size= best_buf_size;
1977
read_plan= new (*param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx, best_mrr_flags);
1978
read_plan->records= best_records;
1979
read_plan->is_ror= tree->ror_scans_map.test(idx);
1980
read_plan->read_cost= read_time;
1981
read_plan->mrr_buf_size= best_buf_size;
2039
1987
optimizer::QuickSelectInterface *optimizer::IndexMergeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2041
optimizer::QuickIndexMergeSelect *quick_imerge;
2042
optimizer::QuickRangeSelect *quick= NULL;
2043
1989
/* index_merge always retrieves full rows, ignore retrieve_full_rows */
2044
if (! (quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table)))
1990
optimizer::QuickIndexMergeSelect* quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table);
2049
1991
quick_imerge->records= records;
2050
1992
quick_imerge->read_time= read_cost;
2051
for (optimizer::RangeReadPlan **range_scan= range_scans;
2052
range_scan != range_scans_end;
1993
for (optimizer::RangeReadPlan **range_scan= range_scans; range_scan != range_scans_end; range_scan++)
2055
if (! (quick= (optimizer::QuickRangeSelect*)
2056
((*range_scan)->make_quick(param, false, &quick_imerge->alloc))) ||
2057
quick_imerge->push_quick_back(quick))
1995
optimizer::QuickRangeSelect* quick= (optimizer::QuickRangeSelect*)((*range_scan)->make_quick(param, false, &quick_imerge->alloc));
2060
1999
delete quick_imerge;
2002
quick_imerge->push_quick_back(quick);
2064
2004
return quick_imerge;
2118
2058
optimizer::QuickSelectInterface *optimizer::RorUnionReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2120
optimizer::QuickRorUnionSelect *quick_roru= NULL;
2121
optimizer::TableReadPlan **scan= NULL;
2122
optimizer::QuickSelectInterface *quick= NULL;
2124
2061
It is impossible to construct a ROR-union that will not retrieve full
2125
2062
rows, ignore retrieve_full_rows parameter.
2127
if ((quick_roru= new optimizer::QuickRorUnionSelect(param->session, param->table)))
2064
optimizer::QuickRorUnionSelect* quick_roru= new optimizer::QuickRorUnionSelect(param->session, param->table);
2065
for (optimizer::TableReadPlan** scan= first_ror; scan != last_ror; scan++)
2129
for (scan= first_ror; scan != last_ror; scan++)
2131
if (! (quick= (*scan)->make_quick(param, false, &quick_roru->alloc)) ||
2132
quick_roru->push_quick_back(quick))
2137
quick_roru->records= records;
2138
quick_roru->read_time= read_cost;
2067
optimizer::QuickSelectInterface* quick= (*scan)->make_quick(param, false, &quick_roru->alloc);
2070
quick_roru->push_quick_back(quick);
2072
quick_roru->records= records;
2073
quick_roru->read_time= read_cost;
2140
2074
return quick_roru;
2220
tree= get_ne_mm_tree(param,
2154
tree= get_ne_mm_tree(param,
2223
2157
cond_func->arguments()[1],
2224
cond_func->arguments()[2],
2158
cond_func->arguments()[2],
2229
tree= get_mm_parts(param,
2163
tree= get_mm_parts(param,
2232
2166
Item_func::GE_FUNC,
2233
2167
cond_func->arguments()[1],
2237
tree= tree_and(param,
2171
tree= tree_and(param,
2239
2173
get_mm_parts(param, cond_func, field,
2240
2174
Item_func::LE_FUNC,
2241
2175
cond_func->arguments()[2],
2751
2683
if (field->eq(key_part->field))
2753
2685
optimizer::SEL_ARG *sel_arg=0;
2754
if (!tree && !(tree=new optimizer::SEL_TREE()))
2687
tree= new optimizer::SEL_TREE;
2756
2688
if (!value || !(value->used_tables() & ~param->read_tables))
2758
sel_arg= get_mm_leaf(param,cond_func,
2759
key_part->field,key_part,type,value);
2690
sel_arg= get_mm_leaf(param,cond_func, key_part->field,key_part,type,value);
2762
2693
if (sel_arg->type == optimizer::SEL_ARG::IMPOSSIBLE)
3129
3059
Any predicate except "<=>"(null-safe equality operator) involving NULL as a
3130
3060
constant is always FALSE
3131
3061
Put IMPOSSIBLE Tree(null_element) here.
3133
3063
if (type != Item_func::EQUAL_FUNC && field->is_real_null())
3135
3065
tree= &optimizer::null_element;
3139
str= (unsigned char*) alloc->alloc_root(key_part->store_length+1);
3069
str= alloc->alloc(key_part->store_length+1);
3142
3070
if (maybe_null)
3143
*str= (unsigned char) field->is_real_null(); // Set to 1 if null
3071
*str= field->is_real_null(); // Set to 1 if null
3144
3072
field->get_key_image(str+maybe_null, key_part->length);
3145
if (! (tree= new (alloc) optimizer::SEL_ARG(field, str, str)))
3146
goto end; // out of memory
3073
tree= new (alloc) optimizer::SEL_ARG(field, str, str);
3149
3076
Check if we are comparing an UNSIGNED integer with a negative constant.
4008
3933
quick->mrr_flags= mrr_flags;
4009
3934
quick->mrr_buf_size= mrr_buf_size;
4012
quick->key_parts=(KEY_PART*)
4013
parent_alloc->memdup_root( (char*) param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4017
quick->key_parts=(KEY_PART*)
4018
quick->alloc.memdup_root((char*) param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
3935
quick->key_parts= parent_alloc
3936
? (KEY_PART*)parent_alloc->memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts)
3937
: (KEY_PART*)quick->alloc.memdup(param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4153
4071
/* Get range for retrieving rows in QUICK_SELECT::get_next */
4154
if (! (range= new optimizer::QuickRange(param->min_key,
4072
range= new optimizer::QuickRange(param->min_key,
4155
4073
(uint32_t) (tmp_min_key - param->min_key),
4156
4074
min_part >=0 ? make_keypart_map(min_part) : 0,
4157
4075
param->max_key,
4158
4076
(uint32_t) (tmp_max_key - param->max_key),
4159
4077
max_part >=0 ? make_keypart_map(max_part) : 0,
4162
return 1; // out of memory
4165
4080
set_if_bigger(quick->max_used_key_length, (uint32_t)range->min_length);
4166
4081
set_if_bigger(quick->max_used_key_length, (uint32_t)range->max_length);
4167
4082
set_if_bigger(quick->used_key_parts, (uint32_t) key_tree->part+1);
4168
if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
4083
quick->ranges.push_back(&range);
4174
4086
if (key_tree->right != &optimizer::null_element)
4268
4180
quick->records= records;
4270
if ((cp_buffer_from_ref(session, ref) && session->is_fatal_error) ||
4271
!(range= new(alloc) optimizer::QuickRange()))
4182
if (cp_buffer_from_ref(session, ref) && session->is_fatal_error)
4272
4183
goto err; // out of memory
4184
range= new (*alloc) optimizer::QuickRange;
4274
4186
range->min_key= range->max_key= ref->key_buff;
4275
4187
range->min_length= range->max_length= ref->key_length;
4276
4188
range->min_keypart_map= range->max_keypart_map=
4277
4189
make_prev_keypart_map(ref->key_parts);
4278
range->flag= ((ref->key_length == key_info->key_length &&
4279
(key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
4282
if (!(quick->key_parts=key_part=(KEY_PART *)
4283
quick->alloc.alloc_root(sizeof(KEY_PART)*ref->key_parts)))
4190
range->flag= (ref->key_length == key_info->key_length && (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0;
4192
quick->key_parts=key_part= new (quick->alloc) KEY_PART[ref->key_parts];
4286
4194
for (part=0 ; part < ref->key_parts ;part++,key_part++)
4306
4213
optimizer::QuickRange *null_range= NULL;
4308
4215
*ref->null_ref_key= 1; // Set null byte then create a range
4309
if (!(null_range= new (alloc)
4216
null_range= new (alloc)
4310
4217
optimizer::QuickRange(ref->key_buff, ref->key_length,
4311
4218
make_prev_keypart_map(ref->key_parts),
4312
4219
ref->key_buff, ref->key_length,
4313
make_prev_keypart_map(ref->key_parts), EQ_RANGE)))
4220
make_prev_keypart_map(ref->key_parts), EQ_RANGE);
4315
4221
*ref->null_ref_key= 0; // Clear null byte
4316
if (insert_dynamic(&quick->ranges,(unsigned char*)&null_range))
4222
quick->ranges.push_back(&null_range);
4320
4225
/* Call multi_range_read_info() to get the MRR flags and buffer size */
4321
4226
quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
4322
4227
(table->key_read ? HA_MRR_INDEX_ONLY : 0);
4323
if (session->lex->sql_command != SQLCOM_SELECT)
4228
if (session->lex().sql_command != SQLCOM_SELECT)
4324
4229
quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
4326
4231
quick->mrr_buf_size= session->variables.read_rnd_buff_size;
4327
if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records,
4328
&quick->mrr_buf_size,
4329
&quick->mrr_flags, &cost))
4232
if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records, &quick->mrr_buf_size, &quick->mrr_flags, &cost))
5469
5366
optimizer::QuickSelectInterface *
5470
5367
optimizer::GroupMinMaxReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5472
optimizer::QuickGroupMinMaxSelect *quick= NULL;
5474
quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5475
param->session->lex->current_select->join,
5369
optimizer::QuickGroupMinMaxSelect *quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5370
param->session->lex().current_select->join,
5478
5373
min_max_arg_part,
5558
5448
optimizer::QuickSelectInterface *optimizer::RangeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5560
optimizer::QuickRangeSelect *quick= NULL;
5561
if ((quick= optimizer::get_quick_select(param,
5450
optimizer::QuickRangeSelect *quick= optimizer::get_quick_select(param, key_idx, key, mrr_flags, mrr_buf_size, parent_alloc);
5568
5453
quick->records= records;
5569
5454
quick->read_time= read_cost;