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>
31
#include "drizzled/sql_select.h"
37
class JOIN :public memory::SqlAlloc
39
JOIN(const JOIN &rhs); /**< not implemented */
40
JOIN& operator=(const JOIN &rhs); /**< not implemented */
43
* Contains a partial query execution plan which is extended during
44
* cost-based optimization.
46
optimizer::Position positions[MAX_TABLES+1];
49
* Contains the optimal query execution plan after cost-based optimization
52
optimizer::Position best_positions[MAX_TABLES+1];
57
JoinTable **map2table; /**< mapping between table indexes and JoinTables */
58
JoinTable *join_tab_save; /**< saved join_tab for subquery reexecution */
63
The table which has an index that allows to produce the requried ordering.
64
A special value of 0x1 means that the ordering will be produced by
65
passing 1st non-const table to filesort(). NULL means no such table exists.
69
uint32_t tables; /**< Number of tables in the join */
70
uint32_t outer_tables; /**< Number of tables that are not inside semijoin */
71
uint32_t const_tables;
72
uint32_t send_group_parts;
81
true when we want to resume nested loop iterations when
82
fetching data from a cursor
84
bool resume_nested_loop;
86
true <=> optimizer must not mark any table as a constant table.
87
This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..):
88
when we optimize the select that reads the results of the union from a
89
temporary table, we must not mark the temp. table as constant because
90
the number of rows in it may vary from one subquery execution to another.
93
bool select_distinct; /**< Set if SELECT DISTINCT */
95
If we have the GROUP BY statement in the query,
96
but the group_list was emptied by optimizer, this
98
It happens when fields in the GROUP BY are from
101
bool group_optimized_away;
104
simple_xxxxx is set if order_st/GROUP BY doesn't include any references
105
to other tables than the first non-constant table in the JOIN.
106
It's also set if order_st/GROUP BY is empty.
111
Is set only in case if we have a GROUP BY clause
112
and no ORDER BY after constant elimination of 'order'.
115
/** Is set if we have a GROUP BY and we have ORDER BY on a constant. */
116
bool skip_sort_order;
117
bool union_part; /**< this subselect is part of union */
118
bool optimized; /**< flag to avoid double optimization in EXPLAIN */
120
bool hidden_group_fields;
122
table_map const_table_map;
123
table_map found_const_table_map;
124
table_map outer_join;
126
ha_rows send_records;
127
ha_rows found_records;
128
ha_rows examined_rows;
130
ha_rows select_limit;
132
Used to fetch no more than given amount of rows per one
133
fetch operation of server side cursor.
134
The value is checked in end_send and end_send_group in fashion, similar
136
- fetch_limit= HA_POS_ERROR if there is no cursor.
137
- when we open a cursor, we set fetch_limit to 0,
138
- on each fetch iteration we add num_rows to fetch to fetch_limit
144
List<Item> &fields_list; /**< hold field list passed to mysql_select */
145
List<TableList> *join_list; /**< list of joined tables in reverse order */
146
/** unit structure (with global parameters) for this select */
147
Select_Lex_Unit *unit;
148
/** select that processed */
149
Select_Lex *select_lex;
150
optimizer::SqlSelect *select; /**< created in optimization phase */
153
Bitmap of nested joins embedding the position at the end of the current
154
partial join (valid only during join optimizer run).
156
std::bitset<64> cur_embedding_map;
159
* The cost for the final query execution plan chosen after optimization
160
* has completed. The QEP is stored in the best_positions variable.
163
List<Cached_item> group_fields;
164
List<Cached_item> group_fields_cache;
166
/** used to store 2 possible tmp table of SELECT */
167
Table *exec_tmp_table1;
168
Table *exec_tmp_table2;
169
Item_sum **sum_funcs;
170
Item_sum ***sum_funcs_end;
171
/** second copy of sumfuncs (for queries with 2 temporary tables */
172
Item_sum **sum_funcs2;
173
Item_sum ***sum_funcs_end2;
175
Item *tmp_having; /**< To store having when processed temporary table */
176
Item *having_history; /**< Store having for explain */
177
uint64_t select_options;
178
select_result *result;
179
Tmp_Table_Param tmp_table_param;
182
JOIN *tmp_join; /**< copy of this JOIN to be used with temporary tables */
183
ROLLUP rollup; /**< Used with rollup */
184
DYNAMIC_ARRAY keyuse;
185
Item::cond_result cond_value;
186
Item::cond_result having_value;
187
List<Item> all_fields; /**< to store all fields that used in query */
188
/** Above list changed to use temporary table */
189
List<Item> tmp_all_fields1;
190
List<Item> tmp_all_fields2;
191
List<Item> tmp_all_fields3;
192
/** Part, shared with list above, emulate following list */
193
List<Item> tmp_fields_list1;
194
List<Item> tmp_fields_list2;
195
List<Item> tmp_fields_list3;
199
order_st *group_list; /**< hold parameters of mysql_select */
200
COND *conds; // ---"---
201
Item *conds_history; /**< store WHERE for explain */
202
TableList *tables_list; /**< hold 'tables' parameter of mysql_select */
203
COND_EQUAL *cond_equal;
204
JoinTable *return_tab; /**< used only for outer joins */
205
Item **ref_pointer_array; /**< used pointer reference for this select */
206
/** Copy of above to be used with different lists */
211
Item **current_ref_pointer_array;
212
uint32_t ref_pointer_array_size; ///< size of above in bytes
213
const char *zero_result_cause; ///< not 0 if exec must return zero result
216
storage for caching buffers allocated during query execution.
217
These buffers allocations need to be cached as the thread memory pool is
218
cleared only at the end of the execution of the whole query and not caching
219
allocations that occur in repetition at execution time will result in
220
excessive memory usage.
222
SORT_FIELD *sortorder; // make_unireg_sortorder()
223
Table **table_reexec; // make_simple_join()
224
JoinTable *join_tab_reexec; // make_simple_join()
225
/* end of allocation caching storage */
228
JOIN(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)
303
select_distinct= test(select_options & SELECT_DISTINCT);
304
if (&fields_list != &fields_arg) /* only copy if not same*/
305
fields_list= fields_arg;
306
memset(&keyuse, 0, sizeof(keyuse));
307
tmp_table_param.init();
308
tmp_table_param.end_write_records= HA_POS_ERROR;
309
rollup.state= ROLLUP::STATE_NONE;
313
* This method is currently only used when a subselect EXPLAIN is performed.
314
* I pulled out the init() method and have simply reset the values to what
315
* was previously in the init() method. See the note about the hack in
318
inline void reset(Session *session_arg,
319
List<Item> &fields_arg,
320
uint64_t select_options_arg,
321
select_result *result_arg)
334
sort_and_group= false;
338
no_field_update= false;
340
resume_nested_loop= false;
341
no_const_tables= false;
342
select_distinct= false;
343
group_optimized_away= false;
347
skip_sort_order= false;
351
hidden_group_fields= false;
353
found_const_table_map= 0;
360
fetch_limit= HA_POS_ERROR;
361
session= session_arg;
362
fields_list= fields_arg;
367
exec_tmp_table1= NULL;
368
exec_tmp_table2= NULL;
373
having_history= NULL;
374
select_options= select_options_arg;
376
lock= session_arg->lock;
378
all_fields= fields_arg;
382
ref_pointer_array= NULL;
387
ref_pointer_array_size= 0;
388
zero_result_cause= NULL;
391
join_tab_reexec= NULL;
392
select_distinct= test(select_options & SELECT_DISTINCT);
393
if (&fields_list != &fields_arg) /* only copy if not same*/
394
fields_list= fields_arg;
395
memset(&keyuse, 0, sizeof(keyuse));
396
tmp_table_param.init();
397
tmp_table_param.end_write_records= HA_POS_ERROR;
398
rollup.state= ROLLUP::STATE_NONE;
401
int prepare(Item ***rref_pointer_array,
410
Select_Lex_Unit *unit);
416
bool alloc_func_list();
417
bool setup_subquery_materialization();
418
bool make_sum_func_list(List<Item> &all_fields,
419
List<Item> &send_fields,
420
bool before_group_by,
421
bool recompute= false);
423
inline void set_items_ref_array(Item **ptr)
425
memcpy(ref_pointer_array, ptr, ref_pointer_array_size);
426
current_ref_pointer_array= ptr;
428
inline void init_items_ref_array()
430
items0= ref_pointer_array + all_fields.elements;
431
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
432
current_ref_pointer_array= items0;
436
bool rollup_make_fields(List<Item> &all_fields,
439
int rollup_send_data(uint32_t idx);
440
int rollup_write_data(uint32_t idx, Table *table);
441
void remove_subq_pushed_predicates(Item **where);
443
Release memory and, if possible, the open tables held by this execution
444
plan (and nested plans). It's used to release some tables before
445
the end of execution in order to increase concurrency and reduce
449
/** Cleanup this JOIN, possibly for reuse */
450
void cleanup(bool full);
452
bool save_join_tab();
453
bool init_save_join_tab();
454
bool send_row_on_empty_set()
456
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
459
bool change_result(select_result *result);
460
bool is_top_level_join() const
462
return (unit == &session->lex->unit && (unit->fake_select_lex == 0 ||
463
select_lex == unit->fake_select_lex));
467
* Copy the partial query plan into the optimal query plan.
469
* @param[in] size the size of the plan which is to be copied
471
void copyPartialPlanIntoOptimalPlan(uint32_t size)
473
memcpy(best_positions, positions,
474
sizeof(optimizer::Position) * size);
477
void cache_const_exprs();
480
* @param[in] index the index of the position to retrieve
481
* @return a reference to the specified position in the optimal
484
optimizer::Position &getPosFromOptimalPlan(uint32_t index)
486
return best_positions[index];
490
* @param[in] index the index of the position to retrieve
491
* @return a reference to the specified position in the partial
494
optimizer::Position &getPosFromPartialPlan(uint32_t index)
496
return positions[index];
500
* @param[in] index the index of the position to set
501
* @param[in] in_pos the value to set the position to
503
void setPosInPartialPlan(uint32_t index, optimizer::Position &in_pos)
505
positions[index]= in_pos;
509
* @return a pointer to the first position in the partial query plan
511
optimizer::Position *getFirstPosInPartialPlan()
517
* @param[in] index the index of the operator to retrieve from the partial
519
* @return a pointer to the position in the partial query plan
521
optimizer::Position *getSpecificPosInPartialPlan(int32_t index)
523
return positions + index;
528
enum_nested_loop_state evaluate_join_record(JOIN *join, JoinTable *join_tab, int error);
529
enum_nested_loop_state evaluate_null_complemented_join_record(JOIN *join, JoinTable *join_tab);
530
enum_nested_loop_state flush_cached_records(JOIN *join, JoinTable *join_tab, bool skip_last);
531
enum_nested_loop_state end_send(JOIN *join, JoinTable *join_tab, bool end_of_records);
532
enum_nested_loop_state end_write(JOIN *join, JoinTable *join_tab, bool end_of_records);
533
enum_nested_loop_state end_update(JOIN *join, JoinTable *join_tab, bool end_of_records);
534
enum_nested_loop_state end_unique_update(JOIN *join, JoinTable *join_tab, bool end_of_records);
536
} /* namespace drizzled */
538
#endif /* DRIZZLED_JOIN_H */