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 drizzled::memory::SqlAlloc
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
drizzled::optimizer::SqlSelect *select; /**< created in optimization phase */
149
Bitmap of nested joins embedding the position at the end of the current
150
partial join (valid only during join optimizer run).
152
std::bitset<64> cur_embedding_map;
155
* The cost for the final query execution plan chosen after optimization
156
* has completed. The QEP is stored in the best_positions variable.
159
List<Cached_item> group_fields;
160
List<Cached_item> group_fields_cache;
162
/** used to store 2 possible tmp table of SELECT */
163
Table *exec_tmp_table1;
164
Table *exec_tmp_table2;
165
Item_sum **sum_funcs;
166
Item_sum ***sum_funcs_end;
167
/** second copy of sumfuncs (for queries with 2 temporary tables */
168
Item_sum **sum_funcs2;
169
Item_sum ***sum_funcs_end2;
171
Item *tmp_having; /**< To store having when processed temporary table */
172
Item *having_history; /**< Store having for explain */
173
uint64_t select_options;
174
select_result *result;
175
Tmp_Table_Param tmp_table_param;
178
JOIN *tmp_join; /**< copy of this JOIN to be used with temporary tables */
179
ROLLUP rollup; /**< Used with rollup */
180
DYNAMIC_ARRAY keyuse;
181
Item::cond_result cond_value;
182
Item::cond_result having_value;
183
List<Item> all_fields; /**< to store all fields that used in query */
184
/** Above list changed to use temporary table */
185
List<Item> tmp_all_fields1;
186
List<Item> tmp_all_fields2;
187
List<Item> tmp_all_fields3;
188
/** Part, shared with list above, emulate following list */
189
List<Item> tmp_fields_list1;
190
List<Item> tmp_fields_list2;
191
List<Item> tmp_fields_list3;
195
order_st *group_list; /**< hold parameters of mysql_select */
196
COND *conds; // ---"---
197
Item *conds_history; /**< store WHERE for explain */
198
TableList *tables_list; /**< hold 'tables' parameter of mysql_select */
199
COND_EQUAL *cond_equal;
200
JoinTable *return_tab; /**< used only for outer joins */
201
Item **ref_pointer_array; /**< used pointer reference for this select */
202
/** Copy of above to be used with different lists */
207
Item **current_ref_pointer_array;
208
uint32_t ref_pointer_array_size; ///< size of above in bytes
209
const char *zero_result_cause; ///< not 0 if exec must return zero result
212
storage for caching buffers allocated during query execution.
213
These buffers allocations need to be cached as the thread memory pool is
214
cleared only at the end of the execution of the whole query and not caching
215
allocations that occur in repetition at execution time will result in
216
excessive memory usage.
218
SORT_FIELD *sortorder; // make_unireg_sortorder()
219
Table **table_reexec; // make_simple_join()
220
JoinTable *join_tab_reexec; // make_simple_join()
221
/* end of allocation caching storage */
224
JOIN(Session *session_arg,
225
List<Item> &fields_arg,
226
uint64_t select_options_arg,
227
select_result *result_arg)
240
sort_and_group(false),
244
no_field_update(false),
246
resume_nested_loop(false),
247
no_const_tables(false),
248
select_distinct(false),
249
group_optimized_away(false),
253
skip_sort_order(false),
257
hidden_group_fields(false),
259
found_const_table_map(0),
266
fetch_limit(HA_POS_ERROR),
267
session(session_arg),
268
fields_list(fields_arg),
273
exec_tmp_table1(NULL),
274
exec_tmp_table2(NULL),
279
having_history(NULL),
280
select_options(select_options_arg),
282
lock(session_arg->lock),
284
all_fields(fields_arg),
288
ref_pointer_array(NULL),
293
ref_pointer_array_size(0),
294
zero_result_cause(NULL),
297
join_tab_reexec(NULL)
299
select_distinct= test(select_options & SELECT_DISTINCT);
300
if (&fields_list != &fields_arg) /* only copy if not same*/
301
fields_list= fields_arg;
302
memset(&keyuse, 0, sizeof(keyuse));
303
tmp_table_param.init();
304
tmp_table_param.end_write_records= HA_POS_ERROR;
305
rollup.state= ROLLUP::STATE_NONE;
309
* This method is currently only used when a subselect EXPLAIN is performed.
310
* I pulled out the init() method and have simply reset the values to what
311
* was previously in the init() method. See the note about the hack in
314
inline void reset(Session *session_arg,
315
List<Item> &fields_arg,
316
uint64_t select_options_arg,
317
select_result *result_arg)
330
sort_and_group= false;
334
no_field_update= false;
336
resume_nested_loop= false;
337
no_const_tables= false;
338
select_distinct= false;
339
group_optimized_away= false;
343
skip_sort_order= false;
347
hidden_group_fields= false;
349
found_const_table_map= 0;
356
fetch_limit= HA_POS_ERROR;
357
session= session_arg;
358
fields_list= fields_arg;
363
exec_tmp_table1= NULL;
364
exec_tmp_table2= NULL;
369
having_history= NULL;
370
select_options= select_options_arg;
372
lock= session_arg->lock;
374
all_fields= fields_arg;
378
ref_pointer_array= NULL;
383
ref_pointer_array_size= 0;
384
zero_result_cause= NULL;
387
join_tab_reexec= NULL;
388
select_distinct= test(select_options & SELECT_DISTINCT);
389
if (&fields_list != &fields_arg) /* only copy if not same*/
390
fields_list= fields_arg;
391
memset(&keyuse, 0, sizeof(keyuse));
392
tmp_table_param.init();
393
tmp_table_param.end_write_records= HA_POS_ERROR;
394
rollup.state= ROLLUP::STATE_NONE;
397
int prepare(Item ***rref_pointer_array,
406
Select_Lex_Unit *unit);
412
bool alloc_func_list();
413
bool setup_subquery_materialization();
414
bool make_sum_func_list(List<Item> &all_fields,
415
List<Item> &send_fields,
416
bool before_group_by,
417
bool recompute= false);
419
inline void set_items_ref_array(Item **ptr)
421
memcpy(ref_pointer_array, ptr, ref_pointer_array_size);
422
current_ref_pointer_array= ptr;
424
inline void init_items_ref_array()
426
items0= ref_pointer_array + all_fields.elements;
427
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
428
current_ref_pointer_array= items0;
432
bool rollup_make_fields(List<Item> &all_fields,
435
int rollup_send_data(uint32_t idx);
436
int rollup_write_data(uint32_t idx, Table *table);
437
void remove_subq_pushed_predicates(Item **where);
439
Release memory and, if possible, the open tables held by this execution
440
plan (and nested plans). It's used to release some tables before
441
the end of execution in order to increase concurrency and reduce
445
/** Cleanup this JOIN, possibly for reuse */
446
void cleanup(bool full);
448
bool save_join_tab();
449
bool init_save_join_tab();
450
bool send_row_on_empty_set()
452
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
455
bool change_result(select_result *result);
456
bool is_top_level_join() const
458
return (unit == &session->lex->unit && (unit->fake_select_lex == 0 ||
459
select_lex == unit->fake_select_lex));
463
* Copy the partial query plan into the optimal query plan.
465
* @param[in] size the size of the plan which is to be copied
467
void copyPartialPlanIntoOptimalPlan(uint32_t size)
469
memcpy(best_positions, positions,
470
sizeof(drizzled::optimizer::Position) * size);
473
void cache_const_exprs();
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 */