112
112
#include <boost/dynamic_bitset.hpp>
114
#include "drizzled/sql_base.h"
115
#include "drizzled/sql_select.h"
116
#include "drizzled/error.h"
117
#include "drizzled/optimizer/cost_vector.h"
118
#include "drizzled/item/cmpfunc.h"
119
#include "drizzled/field/num.h"
120
#include "drizzled/check_stack_overrun.h"
121
#include "drizzled/optimizer/sum.h"
122
#include "drizzled/optimizer/range.h"
123
#include "drizzled/optimizer/quick_range.h"
124
#include "drizzled/optimizer/quick_range_select.h"
125
#include "drizzled/optimizer/quick_group_min_max_select.h"
126
#include "drizzled/optimizer/quick_index_merge_select.h"
127
#include "drizzled/optimizer/quick_ror_intersect_select.h"
128
#include "drizzled/optimizer/quick_ror_union_select.h"
129
#include "drizzled/optimizer/table_read_plan.h"
130
#include "drizzled/optimizer/sel_arg.h"
131
#include "drizzled/optimizer/sel_imerge.h"
132
#include "drizzled/optimizer/sel_tree.h"
133
#include "drizzled/optimizer/range_param.h"
134
#include "drizzled/records.h"
135
#include "drizzled/internal/my_sys.h"
136
#include "drizzled/internal/iocache.h"
138
#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>
140
146
using namespace std;
144
150
#define HA_END_SPACE_KEY 0
286
292
optimizer::GroupMinMaxReadPlan *get_best_group_min_max(optimizer::Parameter *param, optimizer::SEL_TREE *tree);
288
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
289
optimizer::SEL_TREE *tree1,
294
static optimizer::SEL_TREE *tree_and(optimizer::RangeParameter *param,
295
optimizer::SEL_TREE *tree1,
290
296
optimizer::SEL_TREE *tree2);
292
298
static optimizer::SEL_ARG *sel_add(optimizer::SEL_ARG *key1, optimizer::SEL_ARG *key2);
689
686
param.force_default_mrr= ordered_output;
691
688
session->no_errors=1; // Don't warn about NULL
692
memory::init_sql_alloc(&alloc, session->variables.range_alloc_block_size, 0);
693
if (!(param.key_parts= (KEY_PART*) alloc.alloc_root( sizeof(KEY_PART) * head->getShare()->key_parts)) ||
694
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))
696
693
session->no_errors=0;
697
694
alloc.free_root(MYF(0)); // Return memory & allocator
974
966
ha_rows roru_total_records;
975
967
double roru_intersect_part= 1.0;
977
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];
983
972
Collect best 'range' scan for each of disjuncts, and, while doing so,
984
973
analyze possibility of ROR scans. Also calculate some values needed by
985
974
other parts of the code.
987
for (ptree= imerge->trees, cur_child= range_scans;
988
ptree != imerge->trees_next;
989
ptree++, cur_child++)
976
for (ptree= imerge->trees, cur_child= range_scans; ptree != imerge->trees_next; ptree++, cur_child++)
991
978
if (!(*cur_child= get_key_scans_params(session, param, *ptree, true, false, read_time)))
1071
1054
param->session->variables.sortbuff_size);
1072
1055
if (imerge_cost < read_time)
1074
if ((imerge_trp= new (param->mem_root) optimizer::IndexMergeReadPlan))
1076
imerge_trp->read_cost= imerge_cost;
1077
imerge_trp->records= non_cpk_scan_records + cpk_scan_records;
1078
imerge_trp->records= min(imerge_trp->records,
1079
param->table->cursor->stats.records);
1080
imerge_trp->range_scans= range_scans;
1081
imerge_trp->range_scans_end= range_scans + n_child_scans;
1082
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;
1086
1066
build_ror_index_merge:
1087
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)
1088
1068
return(imerge_trp);
1090
1070
/* Ok, it is possible to build a ROR-union, try it. */
1092
if (! (roru_read_plans=
1093
(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];
1097
1073
skip_to_ror_scan:
1098
1074
roru_index_costs= 0.0;
1099
1075
roru_total_records= 0;
1159
1135
double roru_total_cost;
1161
1137
optimizer::CostVector sweep_cost;
1162
Join *join= param->session->lex->select_lex.join;
1138
Join *join= param->session->lex().select_lex.join;
1163
1139
bool is_interrupted= test(join && join->tables == 1);
1164
1140
get_sweep_read_cost(param->table, roru_total_records, is_interrupted,
1166
1142
roru_total_cost= roru_index_costs +
1167
rows2double(roru_total_records)*log((double)n_child_scans) /
1143
static_cast<double>(roru_total_records)*log((double)n_child_scans) /
1168
1144
(TIME_FOR_COMPARE_ROWID * M_LN2) +
1169
1145
sweep_cost.total_cost();
1702
1671
cost total_cost.
1704
1673
/* Add priority queue use cost. */
1705
total_cost += rows2double(records)*
1674
total_cost += static_cast<double>(records) *
1706
1675
log((double)(ror_scan_mark - tree->ror_scans)) /
1707
1676
(TIME_FOR_COMPARE_ROWID * M_LN2);
1709
1678
if (total_cost > read_time)
1712
optimizer::RorIntersectReadPlan *trp= NULL;
1713
if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1681
optimizer::RorIntersectReadPlan* trp= new (*param->mem_root) optimizer::RorIntersectReadPlan;
1718
1683
uint32_t best_num= (ror_scan_mark - tree->ror_scans);
1719
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];
1721
1685
memcpy(trp->first_scan, tree->ror_scans, best_num*sizeof(optimizer::RorScanInfo*));
1722
1686
trp->last_scan= trp->first_scan + best_num;
1723
1687
trp->is_covering= true;
1815
1779
uint32_t cpk_no= 0;
1816
1780
bool cpk_scan_used= false;
1818
if (! (tree->ror_scans= (optimizer::RorScanInfo**)param->mem_root->alloc_root(sizeof(optimizer::RorScanInfo*)* param->keys)))
1822
cpk_no= ((param->table->cursor->primary_key_is_clustered()) ?
1823
param->table->getShare()->getPrimaryKey() : MAX_KEY);
1782
tree->ror_scans= new (*param->mem_root) optimizer::RorScanInfo*[param->keys];
1783
cpk_no= ((param->table->cursor->primary_key_is_clustered()) ? param->table->getShare()->getPrimaryKey() : MAX_KEY);
1825
1785
for (idx= 0, cur_ror_scan= tree->ror_scans; idx < param->keys; idx++)
1909
1867
optimizer::RorIntersectReadPlan *trp= NULL;
1910
1868
if (min_cost < read_time && (cpk_scan_used || best_num > 1))
1912
if (! (trp= new (param->mem_root) optimizer::RorIntersectReadPlan))
1915
if (! (trp->first_scan=
1916
(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];
1918
1872
memcpy(trp->first_scan, intersect_scans, best_num*sizeof(optimizer::RorScanInfo*));
1919
1873
trp->last_scan= trp->first_scan + best_num;
1920
1874
trp->is_covering= intersect_best.is_covering;
2020
1974
if (key_to_read)
2022
1976
idx= key_to_read - tree->keys;
2023
if ((read_plan= new (param->mem_root) optimizer::RangeReadPlan(*key_to_read, idx,
2026
read_plan->records= best_records;
2027
read_plan->is_ror= tree->ror_scans_map.test(idx);
2028
read_plan->read_cost= read_time;
2029
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;
2037
1987
optimizer::QuickSelectInterface *optimizer::IndexMergeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2039
optimizer::QuickIndexMergeSelect *quick_imerge;
2040
optimizer::QuickRangeSelect *quick= NULL;
2041
1989
/* index_merge always retrieves full rows, ignore retrieve_full_rows */
2042
if (! (quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table)))
1990
optimizer::QuickIndexMergeSelect* quick_imerge= new optimizer::QuickIndexMergeSelect(param->session, param->table);
2047
1991
quick_imerge->records= records;
2048
1992
quick_imerge->read_time= read_cost;
2049
for (optimizer::RangeReadPlan **range_scan= range_scans;
2050
range_scan != range_scans_end;
1993
for (optimizer::RangeReadPlan **range_scan= range_scans; range_scan != range_scans_end; range_scan++)
2053
if (! (quick= (optimizer::QuickRangeSelect*)
2054
((*range_scan)->make_quick(param, false, &quick_imerge->alloc))) ||
2055
quick_imerge->push_quick_back(quick))
1995
optimizer::QuickRangeSelect* quick= (optimizer::QuickRangeSelect*)((*range_scan)->make_quick(param, false, &quick_imerge->alloc));
2058
1999
delete quick_imerge;
2002
quick_imerge->push_quick_back(quick);
2062
2004
return quick_imerge;
2116
2058
optimizer::QuickSelectInterface *optimizer::RorUnionReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *)
2118
optimizer::QuickRorUnionSelect *quick_roru= NULL;
2119
optimizer::TableReadPlan **scan= NULL;
2120
optimizer::QuickSelectInterface *quick= NULL;
2122
2061
It is impossible to construct a ROR-union that will not retrieve full
2123
2062
rows, ignore retrieve_full_rows parameter.
2125
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++)
2127
for (scan= first_ror; scan != last_ror; scan++)
2129
if (! (quick= (*scan)->make_quick(param, false, &quick_roru->alloc)) ||
2130
quick_roru->push_quick_back(quick))
2135
quick_roru->records= records;
2136
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;
2138
2074
return quick_roru;
2218
tree= get_ne_mm_tree(param,
2154
tree= get_ne_mm_tree(param,
2221
2157
cond_func->arguments()[1],
2222
cond_func->arguments()[2],
2158
cond_func->arguments()[2],
2227
tree= get_mm_parts(param,
2163
tree= get_mm_parts(param,
2230
2166
Item_func::GE_FUNC,
2231
2167
cond_func->arguments()[1],
2235
tree= tree_and(param,
2171
tree= tree_and(param,
2237
2173
get_mm_parts(param, cond_func, field,
2238
2174
Item_func::LE_FUNC,
2239
2175
cond_func->arguments()[2],
2749
2683
if (field->eq(key_part->field))
2751
2685
optimizer::SEL_ARG *sel_arg=0;
2752
if (!tree && !(tree=new optimizer::SEL_TREE()))
2687
tree= new optimizer::SEL_TREE;
2754
2688
if (!value || !(value->used_tables() & ~param->read_tables))
2756
sel_arg= get_mm_leaf(param,cond_func,
2757
key_part->field,key_part,type,value);
2690
sel_arg= get_mm_leaf(param,cond_func, key_part->field,key_part,type,value);
2760
2693
if (sel_arg->type == optimizer::SEL_ARG::IMPOSSIBLE)
3127
3059
Any predicate except "<=>"(null-safe equality operator) involving NULL as a
3128
3060
constant is always FALSE
3129
3061
Put IMPOSSIBLE Tree(null_element) here.
3131
3063
if (type != Item_func::EQUAL_FUNC && field->is_real_null())
3133
3065
tree= &optimizer::null_element;
3137
str= (unsigned char*) alloc->alloc_root(key_part->store_length+1);
3069
str= alloc->alloc(key_part->store_length+1);
3140
3070
if (maybe_null)
3141
*str= (unsigned char) field->is_real_null(); // Set to 1 if null
3071
*str= field->is_real_null(); // Set to 1 if null
3142
3072
field->get_key_image(str+maybe_null, key_part->length);
3143
if (! (tree= new (alloc) optimizer::SEL_ARG(field, str, str)))
3144
goto end; // out of memory
3073
tree= new (alloc) optimizer::SEL_ARG(field, str, str);
3147
3076
Check if we are comparing an UNSIGNED integer with a negative constant.
4003
3933
quick->mrr_flags= mrr_flags;
4004
3934
quick->mrr_buf_size= mrr_buf_size;
4007
quick->key_parts=(KEY_PART*)
4008
parent_alloc->memdup_root( (char*) param->key[idx], sizeof(KEY_PART)* param->table->key_info[param->real_keynr[idx]].key_parts);
4012
quick->key_parts=(KEY_PART*)
4013
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);
4148
4071
/* Get range for retrieving rows in QUICK_SELECT::get_next */
4149
if (! (range= new optimizer::QuickRange(param->min_key,
4072
range= new optimizer::QuickRange(param->min_key,
4150
4073
(uint32_t) (tmp_min_key - param->min_key),
4151
4074
min_part >=0 ? make_keypart_map(min_part) : 0,
4152
4075
param->max_key,
4153
4076
(uint32_t) (tmp_max_key - param->max_key),
4154
4077
max_part >=0 ? make_keypart_map(max_part) : 0,
4157
return 1; // out of memory
4160
4080
set_if_bigger(quick->max_used_key_length, (uint32_t)range->min_length);
4161
4081
set_if_bigger(quick->max_used_key_length, (uint32_t)range->max_length);
4162
4082
set_if_bigger(quick->used_key_parts, (uint32_t) key_tree->part+1);
4163
if (insert_dynamic(&quick->ranges, (unsigned char*) &range))
4083
quick->ranges.push_back(&range);
4169
4086
if (key_tree->right != &optimizer::null_element)
4263
4180
quick->records= records;
4265
if ((cp_buffer_from_ref(session, ref) && session->is_fatal_error) ||
4266
!(range= new(alloc) optimizer::QuickRange()))
4182
if (cp_buffer_from_ref(session, ref) && session->is_fatal_error)
4267
4183
goto err; // out of memory
4184
range= new (*alloc) optimizer::QuickRange;
4269
4186
range->min_key= range->max_key= ref->key_buff;
4270
4187
range->min_length= range->max_length= ref->key_length;
4271
4188
range->min_keypart_map= range->max_keypart_map=
4272
4189
make_prev_keypart_map(ref->key_parts);
4273
range->flag= ((ref->key_length == key_info->key_length &&
4274
(key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0);
4277
if (!(quick->key_parts=key_part=(KEY_PART *)
4278
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];
4281
4194
for (part=0 ; part < ref->key_parts ;part++,key_part++)
4301
4213
optimizer::QuickRange *null_range= NULL;
4303
4215
*ref->null_ref_key= 1; // Set null byte then create a range
4304
if (!(null_range= new (alloc)
4216
null_range= new (alloc)
4305
4217
optimizer::QuickRange(ref->key_buff, ref->key_length,
4306
4218
make_prev_keypart_map(ref->key_parts),
4307
4219
ref->key_buff, ref->key_length,
4308
make_prev_keypart_map(ref->key_parts), EQ_RANGE)))
4220
make_prev_keypart_map(ref->key_parts), EQ_RANGE);
4310
4221
*ref->null_ref_key= 0; // Clear null byte
4311
if (insert_dynamic(&quick->ranges,(unsigned char*)&null_range))
4222
quick->ranges.push_back(&null_range);
4315
4225
/* Call multi_range_read_info() to get the MRR flags and buffer size */
4316
4226
quick->mrr_flags= HA_MRR_NO_ASSOCIATION |
4317
4227
(table->key_read ? HA_MRR_INDEX_ONLY : 0);
4318
if (session->lex->sql_command != SQLCOM_SELECT)
4228
if (session->lex().sql_command != SQLCOM_SELECT)
4319
4229
quick->mrr_flags |= HA_MRR_USE_DEFAULT_IMPL;
4321
4231
quick->mrr_buf_size= session->variables.read_rnd_buff_size;
4322
if (table->cursor->multi_range_read_info(quick->index, 1, (uint32_t)records,
4323
&quick->mrr_buf_size,
4324
&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))
5464
5366
optimizer::QuickSelectInterface *
5465
5367
optimizer::GroupMinMaxReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5467
optimizer::QuickGroupMinMaxSelect *quick= NULL;
5469
quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5470
param->session->lex->current_select->join,
5369
optimizer::QuickGroupMinMaxSelect *quick= new optimizer::QuickGroupMinMaxSelect(param->table,
5370
param->session->lex().current_select->join,
5473
5373
min_max_arg_part,
5553
5448
optimizer::QuickSelectInterface *optimizer::RangeReadPlan::make_quick(optimizer::Parameter *param, bool, memory::Root *parent_alloc)
5555
optimizer::QuickRangeSelect *quick= NULL;
5556
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);
5563
5453
quick->records= records;
5564
5454
quick->read_time= read_cost;