24
* Implementation of the Join class
24
* Implementation of the JOIN class
26
26
* @defgroup Query_Optimizer Query Optimizer
35
#include <drizzled/item/cache.h>
36
#include <drizzled/item/cmpfunc.h>
37
#include <drizzled/item/copy_string.h>
38
#include <drizzled/item/uint.h>
39
#include <drizzled/cached_item.h>
40
#include <drizzled/sql_base.h>
41
#include <drizzled/sql_select.h> /* include join.h */
42
#include <drizzled/lock.h>
43
#include <drizzled/nested_join.h>
44
#include <drizzled/join.h>
45
#include <drizzled/join_cache.h>
46
#include <drizzled/show.h>
47
#include <drizzled/field/blob.h>
48
#include <drizzled/optimizer/position.h>
49
#include <drizzled/optimizer/sargable_param.h>
50
#include <drizzled/optimizer/key_use.h>
51
#include <drizzled/optimizer/range.h>
52
#include <drizzled/optimizer/sum.h>
53
#include <drizzled/optimizer/explain_plan.h>
54
#include <drizzled/optimizer/access_method_factory.h>
55
#include <drizzled/optimizer/access_method.h>
56
#include <drizzled/records.h>
57
#include <drizzled/probes.h>
58
#include <drizzled/internal/my_bit.h>
59
#include <drizzled/internal/my_sys.h>
60
#include <drizzled/internal/iocache.h>
61
#include <drizzled/plugin/storage_engine.h>
62
#include <drizzled/session.h>
63
#include <drizzled/select_result.h>
65
#include <drizzled/debug.h>
35
#include "drizzled/item/cache.h"
36
#include "drizzled/item/cmpfunc.h"
37
#include "drizzled/item/copy_string.h"
38
#include "drizzled/item/uint.h"
39
#include "drizzled/cached_item.h"
40
#include "drizzled/sql_base.h"
41
#include "drizzled/sql_select.h" /* include join.h */
42
#include "drizzled/lock.h"
43
#include "drizzled/nested_join.h"
44
#include "drizzled/join.h"
45
#include "drizzled/join_cache.h"
46
#include "drizzled/show.h"
47
#include "drizzled/field/blob.h"
48
#include "drizzled/optimizer/position.h"
49
#include "drizzled/optimizer/sargable_param.h"
50
#include "drizzled/optimizer/key_use.h"
51
#include "drizzled/optimizer/range.h"
52
#include "drizzled/optimizer/sum.h"
53
#include "drizzled/optimizer/explain_plan.h"
54
#include "drizzled/optimizer/access_method_factory.h"
55
#include "drizzled/optimizer/access_method.h"
56
#include "drizzled/records.h"
57
#include "drizzled/probes.h"
58
#include "drizzled/internal/my_bit.h"
59
#include "drizzled/internal/my_sys.h"
60
#include "drizzled/internal/iocache.h"
67
62
#include <algorithm>
73
69
extern plugin::StorageEngine *heap_engine;
70
extern std::bitset<12> test_flags;
75
72
/** Declarations of static functions used in this source file. */
76
static bool make_group_fields(Join *main_join, Join *curr_join);
77
static void calc_group_buffer(Join *join, Order *group);
78
static bool alloc_group_fields(Join *join, Order *group);
79
static uint32_t cache_record_length(Join *join, uint32_t index);
80
static double prev_record_reads(Join *join, uint32_t idx, table_map found_ref);
81
static bool get_best_combination(Join *join);
82
static void set_position(Join *join,
73
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
74
static void calc_group_buffer(JOIN *join,order_st *group);
75
static bool alloc_group_fields(JOIN *join,order_st *group);
76
static uint32_t cache_record_length(JOIN *join, uint32_t index);
77
static double prev_record_reads(JOIN *join, uint32_t idx, table_map found_ref);
78
static bool get_best_combination(JOIN *join);
79
static void set_position(JOIN *join,
85
82
optimizer::KeyUse *key);
86
static bool choose_plan(Join *join,table_map join_tables);
87
static void best_access_path(Join *join, JoinTable *s,
83
static bool choose_plan(JOIN *join,table_map join_tables);
84
static void best_access_path(JOIN *join, JoinTable *s,
89
86
table_map remaining_tables,
91
88
double record_count,
93
static void optimize_straight_join(Join *join, table_map join_tables);
94
static bool greedy_search(Join *join, table_map remaining_tables, uint32_t depth, uint32_t prune_level);
95
static bool best_extension_by_limited_search(Join *join,
90
static void optimize_straight_join(JOIN *join, table_map join_tables);
91
static bool greedy_search(JOIN *join, table_map remaining_tables, uint32_t depth, uint32_t prune_level);
92
static bool best_extension_by_limited_search(JOIN *join,
96
93
table_map remaining_tables,
98
95
double record_count,
101
98
uint32_t prune_level);
102
static uint32_t determine_search_depth(Join* join);
103
static bool make_simple_join(Join *join,Table *tmp_table);
104
static void make_outerjoin_info(Join *join);
105
static bool make_join_select(Join *join, optimizer::SqlSelect *select,COND *item);
106
static bool make_join_readinfo(Join *join);
107
static void update_depend_map(Join *join);
108
static void update_depend_map(Join *join, Order *order);
109
static Order *remove_constants(Join *join,Order *first_order,COND *cond, bool change_list, bool *simple_order);
110
static int return_zero_rows(Join *join,
99
static uint32_t determine_search_depth(JOIN* join);
100
static bool make_simple_join(JOIN *join,Table *tmp_table);
101
static void make_outerjoin_info(JOIN *join);
102
static bool make_join_select(JOIN *join, optimizer::SqlSelect *select,COND *item);
103
static bool make_join_readinfo(JOIN *join);
104
static void update_depend_map(JOIN *join);
105
static void update_depend_map(JOIN *join, order_st *order);
106
static order_st *remove_constants(JOIN *join,order_st *first_order,COND *cond, bool change_list, bool *simple_order);
107
static int return_zero_rows(JOIN *join,
111
108
select_result *res,
112
109
TableList *tables,
113
110
List<Item> &fields,
115
112
uint64_t select_options,
116
113
const char *info,
118
static COND *simplify_joins(Join *join, List<TableList> *join_list, COND *conds, bool top);
119
static int remove_duplicates(Join *join,Table *entry,List<Item> &fields, Item *having);
115
static COND *simplify_joins(JOIN *join, List<TableList> *join_list, COND *conds, bool top);
116
static int remove_duplicates(JOIN *join,Table *entry,List<Item> &fields, Item *having);
120
117
static int setup_without_group(Session *session,
121
118
Item **ref_pointer_array,
122
119
TableList *tables,
124
121
List<Item> &fields,
125
122
List<Item> &all_fields,
129
126
bool *hidden_group_fields);
130
static bool make_join_statistics(Join *join, TableList *leaves, COND *conds, DYNAMIC_ARRAY *keyuse);
127
static bool make_join_statistics(JOIN *join, TableList *leaves, COND *conds, DYNAMIC_ARRAY *keyuse);
131
128
static uint32_t build_bitmap_for_nested_joins(List<TableList> *join_list, uint32_t first_unused);
132
static Table *get_sort_by_table(Order *a, Order *b,TableList *tables);
129
static Table *get_sort_by_table(order_st *a,order_st *b,TableList *tables);
133
130
static void reset_nj_counters(List<TableList> *join_list);
134
static bool test_if_subpart(Order *a,Order *b);
131
static bool test_if_subpart(order_st *a,order_st *b);
135
132
static void restore_prev_nj_state(JoinTable *last);
136
133
static bool add_ref_to_table_cond(Session *session, JoinTable *join_tab);
137
134
static void free_blobs(Field **ptr); /* Rename this method...conflicts with another in global namespace... */
139
Join::Join(Session *session_arg,
140
List<Item> &fields_arg,
141
uint64_t select_options_arg,
142
select_result *result_arg) :
154
sort_and_group(false),
158
no_field_update(false),
160
resume_nested_loop(false),
161
no_const_tables(false),
162
select_distinct(false),
163
group_optimized_away(false),
167
skip_sort_order(false),
171
hidden_group_fields(false),
173
found_const_table_map(0),
180
fetch_limit(HA_POS_ERROR),
181
session(session_arg),
182
fields_list(fields_arg),
187
exec_tmp_table1(NULL),
188
exec_tmp_table2(NULL),
193
having_history(NULL),
194
select_options(select_options_arg),
196
lock(session_arg->lock),
198
all_fields(fields_arg),
202
ref_pointer_array(NULL),
207
ref_pointer_array_size(0),
208
zero_result_cause(NULL),
211
join_tab_reexec(NULL)
213
select_distinct= test(select_options & SELECT_DISTINCT);
214
if (&fields_list != &fields_arg) /* only copy if not same*/
215
fields_list= fields_arg;
216
memset(&keyuse, 0, sizeof(keyuse));
217
tmp_table_param.init();
218
tmp_table_param.end_write_records= HA_POS_ERROR;
219
rollup.setState(Rollup::STATE_NONE);
223
* This method is currently only used when a subselect EXPLAIN is performed.
224
* I pulled out the init() method and have simply reset the values to what
225
* was previously in the init() method. See the note about the hack in
228
void Join::reset(Session *session_arg,
229
List<Item> &fields_arg,
230
uint64_t select_options_arg,
231
select_result *result_arg)
244
sort_and_group= false;
248
no_field_update= false;
250
resume_nested_loop= false;
251
no_const_tables= false;
252
select_distinct= false;
253
group_optimized_away= false;
257
skip_sort_order= false;
261
hidden_group_fields= false;
263
found_const_table_map= 0;
270
fetch_limit= HA_POS_ERROR;
271
session= session_arg;
272
fields_list= fields_arg;
277
exec_tmp_table1= NULL;
278
exec_tmp_table2= NULL;
283
having_history= NULL;
284
select_options= select_options_arg;
286
lock= session_arg->lock;
288
all_fields= fields_arg;
292
ref_pointer_array= NULL;
297
ref_pointer_array_size= 0;
298
zero_result_cause= NULL;
301
join_tab_reexec= NULL;
302
select_distinct= test(select_options & SELECT_DISTINCT);
303
if (&fields_list != &fields_arg) /* only copy if not same*/
304
fields_list= fields_arg;
305
memset(&keyuse, 0, sizeof(keyuse));
306
tmp_table_param.init();
307
tmp_table_param.end_write_records= HA_POS_ERROR;
308
rollup.setState(Rollup::STATE_NONE);
311
bool Join::is_top_level_join() const
313
return (unit == &session->getLex()->unit && (unit->fake_select_lex == 0 ||
314
select_lex == unit->fake_select_lex));
318
137
Prepare of whole select (including sub queries in future).
1269
1103
If this join belongs to an uncacheable subquery save
1270
1104
the original join
1272
if (select_lex->uncacheable.any() &&
1273
! is_top_level_join() &&
1106
if (select_lex->uncacheable && !is_top_level_join() &&
1274
1107
init_save_join_tab())
1284
/* Even with zero matching rows, subqueries in the HAVING clause
1285
may need to be evaluated if there are aggregate functions in the query.
1287
if (setup_subquery_materialization())
1294
1116
Restore values in temporary join.
1296
void Join::restore_tmp()
1118
void JOIN::restore_tmp()
1298
memcpy(tmp_join, this, (size_t) sizeof(Join));
1120
memcpy(tmp_join, this, (size_t) sizeof(JOIN));
1303
1125
unit->offset_limit_cnt= (ha_rows)(select_lex->offset_limit ?
1304
1126
select_lex->offset_limit->val_uint() :
1350
1172
@retval 0 success.
1351
1173
@retval 1 error occurred.
1353
bool Join::init_save_join_tab()
1175
bool JOIN::init_save_join_tab()
1355
if (!(tmp_join= (Join*)session->getMemRoot()->allocate(sizeof(Join))))
1177
if (!(tmp_join= (JOIN*)session->alloc(sizeof(JOIN))))
1358
1179
error= 0; // Ensure that tmp_join.error= 0
1364
bool Join::save_join_tab()
1184
bool JOIN::save_join_tab()
1366
if (! join_tab_save && select_lex->master_unit()->uncacheable.any())
1186
if (!join_tab_save && select_lex->master_unit()->uncacheable)
1368
if (!(join_tab_save= (JoinTable*)session->getMemRoot()->duplicate((unsigned char*) join_tab,
1188
if (!(join_tab_save= (JoinTable*)session->memdup((unsigned char*) join_tab,
1369
1189
sizeof(JoinTable) * tables)))
1971
1787
is called after all rows are sent, but before EOF packet is sent.
1973
1789
For a simple SELECT with no subqueries this function performs a full
1974
cleanup of the Join and calls unlockReadTables to free used base
1790
cleanup of the JOIN and calls mysql_unlock_read_tables to free used base
1977
If a Join is executed for a subquery or if it has a subquery, we can't
1793
If a JOIN is executed for a subquery or if it has a subquery, we can't
1978
1794
do the full cleanup and need to do a partial cleanup only.
1979
- If a Join is not the top level join, we must not unlock the tables
1795
- If a JOIN is not the top level join, we must not unlock the tables
1980
1796
because the outer select may not have been evaluated yet, and we
1981
1797
can't unlock only selected tables of a query.
1982
- Additionally, if this Join corresponds to a correlated subquery, we
1798
- Additionally, if this JOIN corresponds to a correlated subquery, we
1983
1799
should not free quick selects and join buffers because they will be
1984
1800
needed for the next execution of the correlated subquery.
1985
- However, if this is a Join for a [sub]select, which is not
1801
- However, if this is a JOIN for a [sub]select, which is not
1986
1802
a correlated subquery itself, but has subqueries, we can free it
1987
fully and also free Joins of all its subqueries. The exception
1803
fully and also free JOINs of all its subqueries. The exception
1988
1804
is a subquery in SELECT list, e.g: @n
1989
1805
SELECT a, (select cmax(b) from t1) group by c @n
1990
1806
This subquery will not be evaluated at first sweep and its value will
2038
1852
if (can_unlock && lock && session->lock &&
2039
1853
!(select_options & SELECT_NO_UNLOCK) &&
2040
1854
!select_lex->subquery_in_having &&
2041
(select_lex == (session->getLex()->unit.fake_select_lex ?
2042
session->getLex()->unit.fake_select_lex : &session->getLex()->select_lex)))
1855
(select_lex == (session->lex->unit.fake_select_lex ?
1856
session->lex->unit.fake_select_lex : &session->lex->select_lex)))
2045
1859
TODO: unlock tables even if the join isn't top level select in the
2048
session->unlockReadTables(lock); // Don't free join->lock
1862
mysql_unlock_read_tables(session, lock); // Don't free join->lock
2228
2035
((Item_sum *)item)->depended_from() == select_lex))
2229
2036
*func++= (Item_sum*) item;
2231
if (before_group_by && rollup.getState() == Rollup::STATE_INITED)
2038
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
2233
rollup.setState(Rollup::STATE_READY);
2040
rollup.state= ROLLUP::STATE_READY;
2234
2041
if (rollup_make_fields(field_list, send_fields, &func))
2235
return true; // Should never happen
2042
return(true); // Should never happen
2237
else if (rollup.getState() == Rollup::STATE_NONE)
2044
else if (rollup.state == ROLLUP::STATE_NONE)
2239
2046
for (uint32_t i=0 ; i <= send_group_parts ;i++)
2240
2047
sum_funcs_end[i]= func;
2242
else if (rollup.getState() == Rollup::STATE_READY)
2049
else if (rollup.state == ROLLUP::STATE_READY)
2243
2050
return(false); // Don't put end marker
2244
2051
*func=0; // End marker
2248
2055
/** Allocate memory needed for other rollup functions. */
2249
bool Join::rollup_init()
2056
bool JOIN::rollup_init()
2251
2059
Item **ref_array;
2253
2061
tmp_table_param.quick_group= 0; // Can't create groups in tmp table
2254
rollup.setState(Rollup::STATE_INITED);
2062
rollup.state= ROLLUP::STATE_INITED;
2257
2065
Create pointers to the different sum function groups
2260
2068
tmp_table_param.group_parts= send_group_parts;
2262
rollup.setNullItems((Item_null_result**) session->getMemRoot()->allocate((sizeof(Item*) +
2264
sizeof(List<Item>) +
2265
ref_pointer_array_size)
2266
* send_group_parts ));
2267
if (! rollup.getNullItems())
2070
if (!(rollup.null_items= (Item_null_result**) session->alloc((sizeof(Item*) +
2072
sizeof(List<Item>) +
2073
ref_pointer_array_size)
2074
* send_group_parts )))
2272
rollup.setFields((List<Item>*) (rollup.getNullItems() + send_group_parts));
2273
rollup.setRefPointerArrays((Item***) (rollup.getFields() + send_group_parts));
2274
ref_array= (Item**) (rollup.getRefPointerArrays()+send_group_parts);
2077
rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
2078
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
2079
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
2277
2082
Prepare space for field list for the different levels
2278
2083
These will be filled up in rollup_make_fields()
2280
for (uint32_t i= 0 ; i < send_group_parts ; i++)
2085
for (i= 0 ; i < send_group_parts ; i++)
2282
rollup.getNullItems()[i]= new (session->mem_root) Item_null_result();
2283
List<Item> *rollup_fields= &rollup.getFields()[i];
2284
rollup_fields->clear();
2285
rollup.getRefPointerArrays()[i]= ref_array;
2087
rollup.null_items[i]= new (session->mem_root) Item_null_result();
2088
List<Item> *rollup_fields= &rollup.fields[i];
2089
rollup_fields->empty();
2090
rollup.ref_pointer_arrays[i]= ref_array;
2286
2091
ref_array+= all_fields.elements;
2289
for (uint32_t i= 0 ; i < send_group_parts; i++)
2093
for (i= 0 ; i < send_group_parts; i++)
2291
for (uint32_t j= 0 ; j < fields_list.elements ; j++)
2293
rollup.getFields()[i].push_back(rollup.getNullItems()[i]);
2095
for (j=0 ; j < fields_list.elements ; j++)
2096
rollup.fields[i].push_back(rollup.null_items[i]);
2297
List<Item>::iterator it(all_fields.begin());
2098
List_iterator<Item> it(all_fields);
2299
2100
while ((item= it++))
2102
order_st *group_tmp;
2302
2103
bool found_in_group= 0;
2304
2105
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
2498
2299
1 If send_data_failed()
2500
int Join::rollup_send_data(uint32_t idx)
2301
int JOIN::rollup_send_data(uint32_t idx)
2502
for (uint32_t i= send_group_parts ; i-- > idx ; )
2304
for (i= send_group_parts ; i-- > idx ; )
2504
2306
/* Get reference pointers to sum functions in place */
2505
memcpy(ref_pointer_array, rollup.getRefPointerArrays()[i], ref_pointer_array_size);
2307
memcpy(ref_pointer_array, rollup.ref_pointer_arrays[i],
2308
ref_pointer_array_size);
2507
2309
if ((!having || having->val_int()))
2509
if (send_records < unit->select_limit_cnt && do_send_rows && result->send_data(rollup.getFields()[i]))
2311
if (send_records < unit->select_limit_cnt && do_send_rows &&
2312
result->send_data(rollup.fields[i]))
2513
2314
send_records++;
2516
2317
/* Restore ref_pointer_array */
2517
2318
set_items_ref_array(current_ref_pointer_array);
2539
2339
1 if write_data_failed()
2541
int Join::rollup_write_data(uint32_t idx, Table *table_arg)
2341
int JOIN::rollup_write_data(uint32_t idx, Table *table_arg)
2543
for (uint32_t i= send_group_parts ; i-- > idx ; )
2344
for (i= send_group_parts ; i-- > idx ; )
2545
2346
/* Get reference pointers to sum functions in place */
2546
memcpy(ref_pointer_array, rollup.getRefPointerArrays()[i],
2347
memcpy(ref_pointer_array, rollup.ref_pointer_arrays[i],
2547
2348
ref_pointer_array_size);
2548
2349
if ((!having || having->val_int()))
2550
2351
int write_error;
2552
List<Item>::iterator it(rollup.getFields()[i].begin());
2353
List_iterator_fast<Item> it(rollup.fields[i]);
2553
2354
while ((item= it++))
2555
2356
if (item->type() == Item::NULL_ITEM && item->is_result_field())
2556
2357
item->save_in_result_field(1);
2558
2359
copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
2559
if ((write_error= table_arg->cursor->insertRecord(table_arg->getInsertRecord())))
2360
if ((write_error= table_arg->cursor->insertRecord(table_arg->record[0])))
2561
2362
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
2831
2631
return (*join_tab->next_select)(join, join_tab+1, 0);
2834
enum_nested_loop_state flush_cached_records(Join *join, JoinTable *join_tab, bool skip_last)
2634
enum_nested_loop_state flush_cached_records(JOIN *join, JoinTable *join_tab, bool skip_last)
2836
2636
enum_nested_loop_state rc= NESTED_LOOP_OK;
2840
2640
join_tab->table->null_row= 0;
2841
2641
if (!join_tab->cache.records)
2843
2642
return NESTED_LOOP_OK; /* Nothing to do */
2848
(void) join_tab->cache.store_record_in_cache(); // Must save this for later
2644
(void) store_record_in_cache(&join_tab->cache); // Must save this for later
2852
2645
if (join_tab->use_quick == 2)
2854
2647
if (join_tab->select->quick)
3013
2806
if (!end_of_records)
3015
2808
copy_fields(&join->tmp_table_param);
3016
if (copy_funcs(join->tmp_table_param.items_to_copy, join->session))
3017
return NESTED_LOOP_ERROR;
2809
copy_funcs(join->tmp_table_param.items_to_copy);
3018
2810
if (!join->having || join->having->val_int())
3021
2813
join->found_records++;
3022
if ((error=table->cursor->insertRecord(table->getInsertRecord())))
2814
if ((error=table->cursor->insertRecord(table->record[0])))
3024
2816
if (!table->cursor->is_fatal_error(error, HA_CHECK_DUP))
3026
return NESTED_LOOP_OK;
3029
2819
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
3030
2820
return NESTED_LOOP_ERROR; // Table is_full error
3069
2859
if (item->maybe_null)
3070
2860
group->buff[-1]= (char) group->field->is_null();
3072
if (!table->cursor->index_read_map(table->getUpdateRecord(),
2862
if (!table->cursor->index_read_map(table->record[1],
3073
2863
join->tmp_table_param.group_buff,
3075
2865
HA_READ_KEY_EXACT))
3076
2866
{ /* Update old record */
3077
2867
table->restoreRecord();
3078
2868
update_tmptable_sum_func(join->sum_funcs,table);
3079
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
3080
table->getInsertRecord())))
2869
if ((error= table->cursor->updateRecord(table->record[1],
3082
2872
table->print_error(error,MYF(0));
3083
2873
return NESTED_LOOP_ERROR;
3096
2886
group=group->next,key_part++)
3098
2888
if (key_part->null_bit)
3099
memcpy(table->getInsertRecord()+key_part->offset, group->buff, 1);
2889
memcpy(table->record[0]+key_part->offset, group->buff, 1);
3101
2891
init_tmptable_sum_functions(join->sum_funcs);
3102
if (copy_funcs(join->tmp_table_param.items_to_copy, join->session))
3103
return NESTED_LOOP_ERROR;
3104
if ((error=table->cursor->insertRecord(table->getInsertRecord())))
2892
copy_funcs(join->tmp_table_param.items_to_copy);
2893
if ((error=table->cursor->insertRecord(table->record[0])))
3106
2895
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
3107
2896
return NESTED_LOOP_ERROR; // Table is_full error
3138
2926
table->print_error(error,MYF(0));
3139
2927
return NESTED_LOOP_ERROR;
3141
if (table->cursor->rnd_pos(table->getUpdateRecord(),table->cursor->dup_ref))
2929
if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
3143
2931
table->print_error(error,MYF(0));
3144
2932
return NESTED_LOOP_ERROR;
3146
2934
table->restoreRecord();
3147
2935
update_tmptable_sum_func(join->sum_funcs,table);
3148
if ((error= table->cursor->updateRecord(table->getUpdateRecord(),
3149
table->getInsertRecord())))
2936
if ((error= table->cursor->updateRecord(table->record[1],
3151
2939
table->print_error(error,MYF(0));
3152
2940
return NESTED_LOOP_ERROR;
3212
3000
case REAL_RESULT:
3213
3001
key_length+= sizeof(double);
3216
3003
case INT_RESULT:
3217
3004
key_length+= sizeof(int64_t);
3220
3006
case DECIMAL_RESULT:
3221
key_length+= class_decimal_get_binary_size(group_item->max_length -
3007
key_length+= my_decimal_get_binary_size(group_item->max_length -
3222
3008
(group_item->decimals ? 1 : 0),
3223
3009
group_item->decimals);
3226
3011
case STRING_RESULT:
3228
enum enum_field_types type= group_item->field_type();
3013
enum enum_field_types type= group_item->field_type();
3015
As items represented as DATE/TIME fields in the group buffer
3016
have STRING_RESULT result type, we increase the length
3017
by 8 as maximum pack length of such fields.
3019
if (type == DRIZZLE_TYPE_DATE ||
3020
type == DRIZZLE_TYPE_DATETIME ||
3021
type == DRIZZLE_TYPE_TIMESTAMP)
3230
As items represented as DATE/TIME fields in the group buffer
3231
have STRING_RESULT result type, we increase the length
3232
by 8 as maximum pack length of such fields.
3028
Group strings are taken as varstrings and require an length field.
3029
A field is not yet created by create_tmp_field()
3030
and the sizes should match up.
3234
if (field::isDateTime(type))
3241
Group strings are taken as varstrings and require an length field.
3242
A field is not yet created by create_tmp_field()
3243
and the sizes should match up.
3245
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
3032
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
3252
3037
/* This case should never be choosen */
3254
3039
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
3260
3043
if (group_item->maybe_null)
3264
3046
join->tmp_table_param.group_length=key_length+null_parts;
3265
3047
join->tmp_table_param.group_parts=parts;
3266
3048
join->tmp_table_param.group_null_parts=null_parts;
5200
4967
Returns new sort order
5202
static Order *remove_constants(Join *join,Order *first_order, COND *cond, bool change_list, bool *simple_order)
4969
static order_st *remove_constants(JOIN *join,order_st *first_order, COND *cond, bool change_list, bool *simple_order)
5204
4971
if (join->tables == join->const_tables)
5205
4972
return change_list ? 0 : first_order; // No need to sort
5207
Order *order,**prev_ptr;
4974
order_st *order,**prev_ptr;
5208
4975
table_map first_table= join->join_tab[join->const_tables].table->map;
5209
4976
table_map not_const_tables= ~join->const_table_map;
5425
5192
- The new condition, if success
5428
static COND *simplify_joins(Join *join, List<TableList> *join_list, COND *conds, bool top)
5195
static COND *simplify_joins(JOIN *join, List<TableList> *join_list, COND *conds, bool top)
5430
5197
TableList *table;
5431
NestedJoin *nested_join;
5198
nested_join_st *nested_join;
5432
5199
TableList *prev_table= 0;
5433
List<TableList>::iterator li(join_list->begin());
5200
List_iterator<TableList> li(*join_list);
5436
5203
Try to simplify join operations from join_list.
5523
5290
if (table->on_expr)
5525
table->setDepTables(table->getDepTables() | table->on_expr->used_tables());
5526
if (table->getEmbedding())
5292
table->dep_tables|= table->on_expr->used_tables();
5293
if (table->embedding)
5528
table->setDepTables(table->getDepTables() & ~table->getEmbedding()->getNestedJoin()->used_tables);
5295
table->dep_tables&= ~table->embedding->nested_join->used_tables;
5530
5297
Embedding table depends on tables used
5531
5298
in embedded on expressions.
5533
table->getEmbedding()->setOnExprDepTables(table->getEmbedding()->getOnExprDepTables() & table->on_expr->used_tables());
5300
table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
5536
table->setDepTables(table->getDepTables() & ~table->table->map);
5303
table->dep_tables&= ~table->table->map;
5539
5306
if (prev_table)
5541
//If this is straight join, set prev table to be dependent on all tables
5542
//from this nested join, so that correct join order is selected.
5543
if ((test(join->select_options & SELECT_STRAIGHT_JOIN)) ||
5544
prev_table->straight)
5545
prev_table->setDepTables(prev_table->getDepTables() | used_tables);
5308
/* The order of tables is reverse: prev_table follows table */
5309
if (prev_table->straight)
5310
prev_table->dep_tables|= used_tables;
5546
5311
if (prev_table->on_expr)
5548
prev_table->setDepTables(prev_table->getDepTables() | table->getOnExprDepTables());
5549
table_map prev_used_tables= prev_table->getNestedJoin() ?
5550
prev_table->getNestedJoin()->used_tables :
5313
prev_table->dep_tables|= table->on_expr_dep_tables;
5314
table_map prev_used_tables= prev_table->nested_join ?
5315
prev_table->nested_join->used_tables :
5551
5316
prev_table->table->map;
5553
5318
If on expression contains only references to inner tables
5566
5331
Flatten nested joins that can be flattened.
5567
5332
no ON expression and not a semi-join => can be flattened.
5569
li= join_list->begin();
5570
5335
while ((table= li++))
5572
nested_join= table->getNestedJoin();
5337
nested_join= table->nested_join;
5573
5338
if (nested_join && !table->on_expr)
5575
5340
TableList *tbl;
5576
List<TableList>::iterator it(nested_join->join_list.begin());
5341
List_iterator<TableList> it(nested_join->join_list);
5577
5342
while ((tbl= it++))
5579
tbl->setEmbedding(table->getEmbedding());
5580
tbl->setJoinList(table->getJoinList());
5344
tbl->embedding= table->embedding;
5345
tbl->join_list= table->join_list;
5582
5347
li.replace(nested_join->join_list);
5609
5374
join->unit->select_limit_cnt= 1; // Only send first row
5612
Field **first_field=entry->getFields() + entry->getShare()->sizeFields() - field_count;
5377
Field **first_field=entry->field+entry->s->fields - field_count;
5613
5378
offset= (field_count ?
5614
entry->getField(entry->getShare()->sizeFields() - field_count)->offset(entry->getInsertRecord()) : 0);
5615
reclength= entry->getShare()->getRecordLength() - offset;
5379
entry->field[entry->s->fields - field_count]->
5380
offset(entry->record[0]) : 0);
5381
reclength= entry->s->reclength-offset;
5617
5383
entry->free_io_cache(); // Safety
5618
5384
entry->cursor->info(HA_STATUS_VARIABLE);
5619
if (entry->getShare()->db_type() == heap_engine ||
5620
(!entry->getShare()->blob_fields &&
5385
if (entry->s->db_type() == heap_engine ||
5386
(!entry->s->blob_fields &&
5621
5387
((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->cursor->stats.records <
5622
session->variables.sortbuff_size)))
5388
session->variables.sortbuff_size)))
5624
5389
error= remove_dup_with_hash_index(join->session, entry,
5625
field_count, first_field,
5390
field_count, first_field,
5630
error= remove_dup_with_compare(join->session, entry, first_field, offset, having);
5393
error= remove_dup_with_compare(join->session, entry, first_field, offset,
5633
5396
free_blobs(first_field);
5645
5407
List<Item> &fields,
5646
5408
List<Item> &all_fields,
5650
5412
bool *hidden_group_fields)
5653
nesting_map save_allow_sum_func=session->getLex()->allow_sum_func ;
5415
nesting_map save_allow_sum_func=session->lex->allow_sum_func ;
5655
session->getLex()->allow_sum_func&= ~(1 << session->getLex()->current_select->nest_level);
5417
session->lex->allow_sum_func&= ~(1 << session->lex->current_select->nest_level);
5656
5418
res= session->setup_conds(tables, conds);
5658
session->getLex()->allow_sum_func|= 1 << session->getLex()->current_select->nest_level;
5420
session->lex->allow_sum_func|= 1 << session->lex->current_select->nest_level;
5659
5421
res= res || setup_order(session, ref_pointer_array, tables, fields, all_fields,
5661
session->getLex()->allow_sum_func&= ~(1 << session->getLex()->current_select->nest_level);
5423
session->lex->allow_sum_func&= ~(1 << session->lex->current_select->nest_level);
5662
5424
res= res || setup_group(session, ref_pointer_array, tables, fields, all_fields,
5663
5425
group, hidden_group_fields);
5664
session->getLex()->allow_sum_func= save_allow_sum_func;
5426
session->lex->allow_sum_func= save_allow_sum_func;
5757
5518
outer_join|= table->map;
5758
5519
s->embedding_map.reset();
5759
for (;embedding; embedding= embedding->getEmbedding())
5760
s->embedding_map|= embedding->getNestedJoin()->nj_map;
5520
for (;embedding; embedding= embedding->embedding)
5521
s->embedding_map|= embedding->nested_join->nj_map;
5763
if (embedding && !(false && ! embedding->getEmbedding()))
5524
if (embedding && !(false && ! embedding->embedding))
5765
5526
/* s belongs to a nested join, maybe to several embedded joins */
5766
5527
s->embedding_map.reset();
5769
NestedJoin *nested_join= embedding->getNestedJoin();
5530
nested_join_st *nested_join= embedding->nested_join;
5770
5531
s->embedding_map|= nested_join->nj_map;
5771
s->dependent|= embedding->getDepTables();
5772
embedding= embedding->getEmbedding();
5532
s->dependent|= embedding->dep_tables;
5533
embedding= embedding->embedding;
5773
5534
outer_join|= nested_join->used_tables;
5775
5536
while (embedding);
5795
5556
As we use bitmaps to represent the relation the complexity
5796
5557
of the algorithm is O((number of tables)^2).
5798
for (i= 0; i < table_count; i++)
5559
for (i= 0, s= stat ; i < table_count ; i++, s++)
5801
table= stat[i].table;
5803
if (!table->reginfo.join_tab->dependent)
5806
for (j= 0, s= stat; j < table_count; j++, s++)
5561
for (uint32_t j= 0 ; j < table_count ; j++)
5563
table= stat[j].table;
5808
5564
if (s->dependent & table->map)
5810
table_map was_dependent= s->dependent;
5811
5565
s->dependent |= table->reginfo.join_tab->dependent;
5812
if (i > j && s->dependent != was_dependent)
5568
s->table->maybe_null= 1;
5820
5570
/* Catch illegal cross references for outer joins */
5821
5571
for (i= 0, s= stat ; i < table_count ; i++, s++)
5918
5665
if (table->cursor->stats.records <= 1L &&
5919
5666
(table->cursor->getEngine()->check_flag(HTON_BIT_STATS_RECORDS_IS_EXACT)) &&
5920
!table->pos_in_table_list->getEmbedding())
5667
!table->pos_in_table_list->embedding)
5921
5668
{ // system table
5923
5670
s->type= AM_SYSTEM;
5924
5671
join->const_table_map|=table->map;
5925
5672
set_position(join, const_count++, s, (optimizer::KeyUse*) 0);
5926
5673
partial_pos= join->getSpecificPosInPartialPlan(const_count - 1);
5927
if ((tmp= s->joinReadConstTable(partial_pos)))
5674
if ((tmp= join_read_const_table(s, partial_pos)))
5930
5677
return 1; // Fatal error
6245
5989
Nested joins perspective: Remove the last table from the join order.
6247
The algorithm is the reciprocal of check_interleaving_with_nj(), hence
6248
parent join nest nodes are updated only when the last table in its child
6249
node is removed. The ASCII graphic below will clarify.
6251
%A table nesting such as <tt> t1 x [ ( t2 x t3 ) x ( t4 x t5 ) ] </tt>is
6252
represented by the below join nest tree.
6260
t1 x [ (t2 x t3) x (t4 x t5) ]
6263
At the point in time when check_interleaving_with_nj() adds the table t5 to
6264
the query execution plan, QEP, it also directs the node named NJ2 to mark
6265
the table as covered. NJ2 does so by incrementing its @c counter
6266
member. Since all of NJ2's tables are now covered by the QEP, the algorithm
6267
proceeds up the tree to NJ1, incrementing its counter as well. All join
6268
nests are now completely covered by the QEP.
6270
restore_prev_nj_state() does the above in reverse. As seen above, the node
6271
NJ1 contains the nodes t2, t3, and NJ2. Its counter being equal to 3 means
6272
that the plan covers t2, t3, and NJ2, @e and that the sub-plan (t4 x t5)
6273
completely covers NJ2. The removal of t5 from the partial plan will first
6274
decrement NJ2's counter to 1. It will then detect that NJ2 went from being
6275
completely to partially covered, and hence the algorithm must continue
6276
upwards to NJ1 and decrement its counter to 2. %A subsequent removal of t4
6277
will however not influence NJ1 since it did not un-cover the last table in
6281
restore_prev_nj_state()
6282
last join table to remove, it is assumed to be the last in current
6287
5991
Remove the last table from the partial join order and update the nested
6288
joins counters and join->cur_embedding_map. It is ok to call this
6289
function for the first table in join order (for which
5992
joins counters and join->cur_embedding_map. It is ok to call this
5993
function for the first table in join order (for which
6290
5994
check_interleaving_with_nj has not been called)
6292
5996
@param last join table to remove, it is assumed to be the last in current
6293
5997
partial join order.
6296
5999
static void restore_prev_nj_state(JoinTable *last)
6298
TableList *last_emb= last->table->pos_in_table_list->getEmbedding();
6299
Join *join= last->join;
6300
for (;last_emb != NULL; last_emb= last_emb->getEmbedding())
6001
TableList *last_emb= last->table->pos_in_table_list->embedding;
6002
JOIN *join= last->join;
6302
NestedJoin *nest= last_emb->getNestedJoin();
6304
bool was_fully_covered= nest->is_fully_covered();
6306
if (--nest->counter_ == 0)
6307
join->cur_embedding_map&= ~nest->nj_map;
6309
if (!was_fully_covered)
6312
join->cur_embedding_map|= nest->nj_map;
6005
if (last_emb->on_expr)
6007
if (!(--last_emb->nested_join->counter_))
6008
join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
6009
else if (last_emb->nested_join->join_list.elements-1 ==
6010
last_emb->nested_join->counter_)
6011
join->cur_embedding_map|= last_emb->nested_join->nj_map;
6015
last_emb= last_emb->embedding;
6317
6021
Create a condition for a const reference and add this to the
6318
6022
currenct select for the table.