1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008-2009 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
* Defines the JOIN class
27
#ifndef DRIZZLED_JOIN_H
28
#define DRIZZLED_JOIN_H
30
#include <drizzled/optimizer/position.h>
33
class JOIN :public Sql_alloc
35
JOIN(const JOIN &rhs); /**< not implemented */
36
JOIN& operator=(const JOIN &rhs); /**< not implemented */
39
* Contains a partial query execution plan which is extended during
40
* cost-based optimization.
42
drizzled::optimizer::Position positions[MAX_TABLES+1];
45
* Contains the optimal query execution plan after cost-based optimization
48
drizzled::optimizer::Position best_positions[MAX_TABLES+1];
53
JoinTable **map2table; /**< mapping between table indexes and JoinTables */
54
JoinTable *join_tab_save; /**< saved join_tab for subquery reexecution */
59
The table which has an index that allows to produce the requried ordering.
60
A special value of 0x1 means that the ordering will be produced by
61
passing 1st non-const table to filesort(). NULL means no such table exists.
65
uint32_t tables; /**< Number of tables in the join */
66
uint32_t outer_tables; /**< Number of tables that are not inside semijoin */
67
uint32_t const_tables;
68
uint32_t send_group_parts;
77
true when we want to resume nested loop iterations when
78
fetching data from a cursor
80
bool resume_nested_loop;
82
true <=> optimizer must not mark any table as a constant table.
83
This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..):
84
when we optimize the select that reads the results of the union from a
85
temporary table, we must not mark the temp. table as constant because
86
the number of rows in it may vary from one subquery execution to another.
89
bool select_distinct; /**< Set if SELECT DISTINCT */
91
If we have the GROUP BY statement in the query,
92
but the group_list was emptied by optimizer, this
94
It happens when fields in the GROUP BY are from
97
bool group_optimized_away;
100
simple_xxxxx is set if order_st/GROUP BY doesn't include any references
101
to other tables than the first non-constant table in the JOIN.
102
It's also set if order_st/GROUP BY is empty.
107
Is set only in case if we have a GROUP BY clause
108
and no order_st BY after constant elimination of 'order'.
111
/** Is set if we have a GROUP BY and we have order_st BY on a constant. */
112
bool skip_sort_order;
113
bool union_part; /**< this subselect is part of union */
114
bool optimized; /**< flag to avoid double optimization in EXPLAIN */
116
bool hidden_group_fields;
118
table_map const_table_map;
119
table_map found_const_table_map;
120
table_map outer_join;
122
ha_rows send_records;
123
ha_rows found_records;
124
ha_rows examined_rows;
126
ha_rows select_limit;
128
Used to fetch no more than given amount of rows per one
129
fetch operation of server side cursor.
130
The value is checked in end_send and end_send_group in fashion, similar
132
- fetch_limit= HA_POS_ERROR if there is no cursor.
133
- when we open a cursor, we set fetch_limit to 0,
134
- on each fetch iteration we add num_rows to fetch to fetch_limit
140
List<Item> &fields_list; /**< hold field list passed to mysql_select */
141
List<TableList> *join_list; /**< list of joined tables in reverse order */
142
/** unit structure (with global parameters) for this select */
143
Select_Lex_Unit *unit;
144
/** select that processed */
145
Select_Lex *select_lex;
146
SQL_SELECT *select; /**< created in optimisation phase */
147
Array<Item_in_subselect> sj_subselects;
150
Bitmap of nested joins embedding the position at the end of the current
151
partial join (valid only during join optimizer run).
153
std::bitset<64> cur_embedding_map;
156
* The cost for the final query execution plan chosen after optimization
157
* has completed. The QEP is stored in the best_positions variable.
160
List<Cached_item> group_fields;
161
List<Cached_item> group_fields_cache;
163
/** used to store 2 possible tmp table of SELECT */
164
Table *exec_tmp_table1;
165
Table *exec_tmp_table2;
166
Item_sum **sum_funcs;
167
Item_sum ***sum_funcs_end;
168
/** second copy of sumfuncs (for queries with 2 temporary tables */
169
Item_sum **sum_funcs2;
170
Item_sum ***sum_funcs_end2;
172
Item *tmp_having; /**< To store having when processed temporary table */
173
Item *having_history; /**< Store having for explain */
174
uint64_t select_options;
175
select_result *result;
176
Tmp_Table_Param tmp_table_param;
179
JOIN *tmp_join; /**< copy of this JOIN to be used with temporary tables */
180
ROLLUP rollup; /**< Used with rollup */
181
DYNAMIC_ARRAY keyuse;
182
Item::cond_result cond_value;
183
Item::cond_result having_value;
184
List<Item> all_fields; /**< to store all fields that used in query */
185
/** Above list changed to use temporary table */
186
List<Item> tmp_all_fields1;
187
List<Item> tmp_all_fields2;
188
List<Item> tmp_all_fields3;
189
/** Part, shared with list above, emulate following list */
190
List<Item> tmp_fields_list1;
191
List<Item> tmp_fields_list2;
192
List<Item> tmp_fields_list3;
196
order_st *group_list; /**< hold parameters of mysql_select */
197
COND *conds; // ---"---
198
Item *conds_history; /**< store WHERE for explain */
199
TableList *tables_list; /**< hold 'tables' parameter of mysql_select */
200
COND_EQUAL *cond_equal;
201
JoinTable *return_tab; /**< used only for outer joins */
202
Item **ref_pointer_array; /**< used pointer reference for this select */
203
/** Copy of above to be used with different lists */
208
Item **current_ref_pointer_array;
209
uint32_t ref_pointer_array_size; ///< size of above in bytes
210
const char *zero_result_cause; ///< not 0 if exec must return zero result
213
storage for caching buffers allocated during query execution.
214
These buffers allocations need to be cached as the thread memory pool is
215
cleared only at the end of the execution of the whole query and not caching
216
allocations that occur in repetition at execution time will result in
217
excessive memory usage.
219
SORT_FIELD *sortorder; // make_unireg_sortorder()
220
Table **table_reexec; // make_simple_join()
221
JoinTable *join_tab_reexec; // make_simple_join()
222
/* end of allocation caching storage */
225
JOIN(Session *session_arg,
226
List<Item> &fields_arg,
227
uint64_t select_options_arg,
228
select_result *result_arg)
241
sort_and_group(false),
245
no_field_update(false),
247
resume_nested_loop(false),
248
no_const_tables(false),
249
select_distinct(false),
250
group_optimized_away(false),
254
skip_sort_order(false),
258
hidden_group_fields(false),
260
found_const_table_map(0),
267
fetch_limit(HA_POS_ERROR),
268
session(session_arg),
269
fields_list(fields_arg),
274
sj_subselects(session_arg->mem_root, 4),
275
exec_tmp_table1(NULL),
276
exec_tmp_table2(NULL),
281
having_history(NULL),
282
select_options(select_options_arg),
284
lock(session_arg->lock),
286
all_fields(fields_arg),
290
ref_pointer_array(NULL),
295
ref_pointer_array_size(0),
296
zero_result_cause(NULL),
299
join_tab_reexec(NULL)
301
select_distinct= test(select_options & SELECT_DISTINCT);
302
if (&fields_list != &fields_arg) /* only copy if not same*/
303
fields_list= fields_arg;
304
memset(&keyuse, 0, sizeof(keyuse));
305
tmp_table_param.init();
306
tmp_table_param.end_write_records= HA_POS_ERROR;
307
rollup.state= ROLLUP::STATE_NONE;
311
* This method is currently only used when a subselect EXPLAIN is performed.
312
* I pulled out the init() method and have simply reset the values to what
313
* was previously in the init() method. See the note about the hack in
316
inline void reset(Session *session_arg,
317
List<Item> &fields_arg,
318
uint64_t select_options_arg,
319
select_result *result_arg)
332
sort_and_group= false;
336
no_field_update= false;
338
resume_nested_loop= false;
339
no_const_tables= false;
340
select_distinct= false;
341
group_optimized_away= false;
345
skip_sort_order= false;
349
hidden_group_fields= false;
351
found_const_table_map= 0;
358
fetch_limit= HA_POS_ERROR;
359
session= session_arg;
360
fields_list= fields_arg;
365
exec_tmp_table1= NULL;
366
exec_tmp_table2= NULL;
371
having_history= NULL;
372
select_options= select_options_arg;
374
lock= session_arg->lock;
376
all_fields= fields_arg;
380
ref_pointer_array= NULL;
385
ref_pointer_array_size= 0;
386
zero_result_cause= NULL;
389
join_tab_reexec= NULL;
390
select_distinct= test(select_options & SELECT_DISTINCT);
391
if (&fields_list != &fields_arg) /* only copy if not same*/
392
fields_list= fields_arg;
393
memset(&keyuse, 0, sizeof(keyuse));
394
tmp_table_param.init();
395
tmp_table_param.end_write_records= HA_POS_ERROR;
396
rollup.state= ROLLUP::STATE_NONE;
399
int prepare(Item ***rref_pointer_array,
408
Select_Lex_Unit *unit);
414
bool alloc_func_list();
415
bool setup_subquery_materialization();
416
bool make_sum_func_list(List<Item> &all_fields,
417
List<Item> &send_fields,
418
bool before_group_by,
419
bool recompute= false);
421
inline void set_items_ref_array(Item **ptr)
423
memcpy(ref_pointer_array, ptr, ref_pointer_array_size);
424
current_ref_pointer_array= ptr;
426
inline void init_items_ref_array()
428
items0= ref_pointer_array + all_fields.elements;
429
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
430
current_ref_pointer_array= items0;
434
bool rollup_make_fields(List<Item> &all_fields,
437
int rollup_send_data(uint32_t idx);
438
int rollup_write_data(uint32_t idx, Table *table);
439
void remove_subq_pushed_predicates(Item **where);
441
Release memory and, if possible, the open tables held by this execution
442
plan (and nested plans). It's used to release some tables before
443
the end of execution in order to increase concurrency and reduce
447
/** Cleanup this JOIN, possibly for reuse */
448
void cleanup(bool full);
450
bool save_join_tab();
451
bool init_save_join_tab();
452
bool send_row_on_empty_set()
454
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
457
bool change_result(select_result *result);
458
bool is_top_level_join() const
460
return (unit == &session->lex->unit && (unit->fake_select_lex == 0 ||
461
select_lex == unit->fake_select_lex));
465
* Copy the partial query plan into the optimal query plan.
467
* @param[in] size the size of the plan which is to be copied
469
void copyPartialPlanIntoOptimalPlan(uint32_t size)
471
memcpy(best_positions, positions,
472
sizeof(drizzled::optimizer::Position) * size);
476
* @param[in] index the index of the position to retrieve
477
* @return a reference to the specified position in the optimal
480
drizzled::optimizer::Position &getPosFromOptimalPlan(uint32_t index)
482
return best_positions[index];
486
* @param[in] index the index of the position to retrieve
487
* @return a reference to the specified position in the partial
490
drizzled::optimizer::Position &getPosFromPartialPlan(uint32_t index)
492
return positions[index];
496
* @param[in] index the index of the position to set
497
* @param[in] in_pos the value to set the position to
499
void setPosInPartialPlan(uint32_t index, drizzled::optimizer::Position &in_pos)
501
positions[index]= in_pos;
505
* @return a pointer to the first position in the partial query plan
507
drizzled::optimizer::Position *getFirstPosInPartialPlan()
513
* @param[in] index the index of the operator to retrieve from the partial
515
* @return a pointer to the position in the partial query plan
517
drizzled::optimizer::Position *getSpecificPosInPartialPlan(int32_t index)
519
return positions + index;
524
enum_nested_loop_state evaluate_join_record(JOIN *join, JoinTable *join_tab, int error);
525
enum_nested_loop_state evaluate_null_complemented_join_record(JOIN *join, JoinTable *join_tab);
526
enum_nested_loop_state flush_cached_records(JOIN *join, JoinTable *join_tab, bool skip_last);
527
enum_nested_loop_state end_send(JOIN *join, JoinTable *join_tab, bool end_of_records);
528
enum_nested_loop_state end_write(JOIN *join, JoinTable *join_tab, bool end_of_records);
529
enum_nested_loop_state end_update(JOIN *join, JoinTable *join_tab, bool end_of_records);
530
enum_nested_loop_state end_unique_update(JOIN *join, JoinTable *join_tab, bool end_of_records);
532
#endif /* DRIZZLED_JOIN_H */