~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join.h

  • Committer: Daniel Nichter
  • Date: 2011-10-23 16:01:37 UTC
  • mto: This revision was merged to the branch mainline in revision 2448.
  • Revision ID: daniel@percona.com-20111023160137-7ac3blgz8z4tf8za
Add Administration Getting Started and Logging.  Capitalize SQL clause keywords.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008-2009 Sun Microsystems, Inc.
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 */
 
20
 
 
21
/**
 
22
 * @file
 
23
 *
 
24
 * Defines the Join class
 
25
 */
 
26
 
 
27
#pragma once
 
28
 
 
29
#include <drizzled/dynamic_array.h>
 
30
#include <drizzled/optimizer/position.h>
 
31
#include <drizzled/sql_select.h>
 
32
#include <drizzled/tmp_table_param.h>
 
33
#include <bitset>
 
34
 
 
35
namespace drizzled {
 
36
 
 
37
class Join : public memory::SqlAlloc, boost::noncopyable
 
38
{
 
39
  /**
 
40
   * Contains a partial query execution plan which is extended during
 
41
   * cost-based optimization.
 
42
   */
 
43
  optimizer::Position positions[MAX_TABLES+1];
 
44
 
 
45
  /**
 
46
   * Contains the optimal query execution plan after cost-based optimization
 
47
   * has taken place. 
 
48
   */
 
49
  optimizer::Position best_positions[MAX_TABLES+1];
 
50
 
 
51
public:
 
52
  JoinTable *join_tab;
 
53
  JoinTable **best_ref;
 
54
  JoinTable **map2table;    /**< mapping between table indexes and JoinTables */
 
55
  JoinTable *join_tab_save; /**< saved join_tab for subquery reexecution */
 
56
 
 
57
  Table **table;
 
58
  Table **all_tables;
 
59
  /**
 
60
    The table which has an index that allows to produce the requried ordering.
 
61
    A special value of 0x1 means that the ordering will be produced by
 
62
    passing 1st non-const table to filesort(). NULL means no such table exists.
 
63
  */
 
64
  Table *sort_by_table;
 
65
 
 
66
  uint32_t tables;        /**< Number of tables in the join */
 
67
  uint32_t outer_tables;  /**< Number of tables that are not inside semijoin */
 
68
  uint32_t const_tables;
 
69
  uint32_t send_group_parts;
 
70
 
 
71
  bool sort_and_group;
 
72
  bool first_record;
 
73
  bool full_join;
 
74
  bool group;
 
75
  bool no_field_update;
 
76
  bool do_send_rows;
 
77
  /**
 
78
    true when we want to resume nested loop iterations when
 
79
    fetching data from a cursor
 
80
  */
 
81
  bool resume_nested_loop;
 
82
  /**
 
83
    true <=> optimizer must not mark any table as a constant table.
 
84
    This is needed for subqueries in form "a IN (SELECT .. UNION SELECT ..):
 
85
    when we optimize the select that reads the results of the union from a
 
86
    temporary table, we must not mark the temp. table as constant because
 
87
    the number of rows in it may vary from one subquery execution to another.
 
88
  */
 
89
  bool no_const_tables;
 
90
  bool select_distinct;                         /**< Set if SELECT DISTINCT */
 
91
  /**
 
92
    If we have the GROUP BY statement in the query,
 
93
    but the group_list was emptied by optimizer, this
 
94
    flag is true.
 
95
    It happens when fields in the GROUP BY are from
 
96
    constant table
 
97
  */
 
98
  bool group_optimized_away;
 
99
 
 
100
  /*
 
101
    simple_xxxxx is set if order_st/GROUP BY doesn't include any references
 
102
    to other tables than the first non-constant table in the Join.
 
103
    It's also set if order_st/GROUP BY is empty.
 
104
  */
 
105
  bool simple_order;
 
106
  bool simple_group;
 
107
  /**
 
108
    Is set only in case if we have a GROUP BY clause
 
109
    and no ORDER BY after constant elimination of 'order'.
 
110
  */
 
111
  bool no_order;
 
112
  /** Is set if we have a GROUP BY and we have ORDER BY on a constant. */
 
113
  bool skip_sort_order;
 
114
  bool union_part; /**< this subselect is part of union */
 
115
  bool optimized; /**< flag to avoid double optimization in EXPLAIN */
 
116
  bool need_tmp;
 
117
  bool hidden_group_fields;
 
118
 
 
119
  table_map const_table_map;
 
120
  table_map found_const_table_map;
 
121
  table_map outer_join;
 
122
 
 
123
  ha_rows send_records;
 
124
  ha_rows found_records;
 
125
  ha_rows examined_rows;
 
126
  ha_rows row_limit;
 
127
  ha_rows select_limit;
 
128
  /**
 
129
    Used to fetch no more than given amount of rows per one
 
130
    fetch operation of server side cursor.
 
131
    The value is checked in end_send and end_send_group in fashion, similar
 
132
    to offset_limit_cnt:
 
133
      - fetch_limit= HA_POS_ERROR if there is no cursor.
 
134
      - when we open a cursor, we set fetch_limit to 0,
 
135
      - on each fetch iteration we add num_rows to fetch to fetch_limit
 
136
  */
 
137
  ha_rows fetch_limit;
 
138
 
 
139
  Session       *session;
 
140
  List<Item> *fields;
 
141
  List<Item> &fields_list; /**< hold field list passed to select_query */
 
142
  List<TableList> *join_list; /**< list of joined tables in reverse order */
 
143
  /** unit structure (with global parameters) for this select */
 
144
  Select_Lex_Unit *unit;
 
145
  /** select that processed */
 
146
  Select_Lex *select_lex;
 
147
  optimizer::SqlSelect *select; /**< created in optimization phase */
 
148
 
 
149
  /**
 
150
    Bitmap of nested joins embedding the position at the end of the current
 
151
    partial join (valid only during join optimizer run).
 
152
  */
 
153
  std::bitset<64> cur_embedding_map;
 
154
 
 
155
  /**
 
156
   * The cost for the final query execution plan chosen after optimization
 
157
   * has completed. The QEP is stored in the best_positions variable.
 
158
   */
 
159
  double best_read;
 
160
  List<Cached_item> group_fields;
 
161
  List<Cached_item> group_fields_cache;
 
162
  Table *tmp_table;
 
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;
 
171
  Item *having;
 
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;
 
177
  DrizzleLock *lock;
 
178
 
 
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;
 
193
  int error;
 
194
 
 
195
  Order *order;
 
196
  Order *group_list; /**< hold parameters of select_query */
 
197
  COND *conds;                            // ---"---
 
198
  Item *conds_history; /**< store WHERE for explain */
 
199
  TableList *tables_list; /**< hold 'tables' parameter of select_query */
 
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 */
 
204
  Item **items0;
 
205
  Item **items1;
 
206
  Item **items2;
 
207
  Item **items3;
 
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
 
211
 
 
212
  /*
 
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.
 
218
  */
 
219
  SortField *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 */
 
223
 
 
224
  /** Constructors */
 
225
  Join(Session *session_arg, 
 
226
       List<Item> &fields_arg, 
 
227
       uint64_t select_options_arg,
 
228
       select_result *result_arg);
 
229
 
 
230
  /** 
 
231
   * This method is currently only used when a subselect EXPLAIN is performed.
 
232
   * I pulled out the init() method and have simply reset the values to what
 
233
   * was previously in the init() method.  See the note about the hack in 
 
234
   * sql_union.cc...
 
235
   */
 
236
  void reset(Session *session_arg, 
 
237
             List<Item> &fields_arg, 
 
238
             uint64_t select_options_arg,
 
239
             select_result *result_arg);
 
240
 
 
241
  int prepare(Item ***rref_pointer_array, 
 
242
              TableList *tables,
 
243
              uint32_t wind_num,
 
244
              COND *conds,
 
245
              uint32_t og_num,
 
246
              Order *order,
 
247
              Order *group,
 
248
              Item *having,
 
249
              Select_Lex *select,
 
250
              Select_Lex_Unit *unit);
 
251
 
 
252
  int optimize();
 
253
  int reinit();
 
254
  void exec();
 
255
  int destroy();
 
256
  void restore_tmp();
 
257
  bool alloc_func_list();
 
258
  bool setup_subquery_materialization();
 
259
  bool make_sum_func_list(List<Item> &all_fields, 
 
260
                          List<Item> &send_fields,
 
261
                                          bool before_group_by,
 
262
                          bool recompute= false);
 
263
 
 
264
  inline void set_items_ref_array(Item **ptr)
 
265
  {
 
266
    memcpy(ref_pointer_array, ptr, ref_pointer_array_size);
 
267
    current_ref_pointer_array= ptr;
 
268
  }
 
269
  inline void init_items_ref_array()
 
270
  {
 
271
    items0= ref_pointer_array + all_fields.size();
 
272
    memcpy(items0, ref_pointer_array, ref_pointer_array_size);
 
273
    current_ref_pointer_array= items0;
 
274
  }
 
275
 
 
276
  bool rollup_init();
 
277
  bool rollup_make_fields(List<Item> &all_fields, 
 
278
                          List<Item> &fields,
 
279
                                          Item_sum ***func);
 
280
  int rollup_send_data(uint32_t idx);
 
281
  int rollup_write_data(uint32_t idx, Table *table);
 
282
  void remove_subq_pushed_predicates(Item **where);
 
283
  /**
 
284
    Release memory and, if possible, the open tables held by this execution
 
285
    plan (and nested plans). It's used to release some tables before
 
286
    the end of execution in order to increase concurrency and reduce
 
287
    memory consumption.
 
288
  */
 
289
  void join_free();
 
290
  /** Cleanup this Join, possibly for reuse */
 
291
  void cleanup(bool full);
 
292
  void clear();
 
293
  void save_join_tab();
 
294
  void init_save_join_tab();
 
295
  bool send_row_on_empty_set()
 
296
  {
 
297
    return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
 
298
            !group_list);
 
299
  }
 
300
  bool change_result(select_result *result);
 
301
  bool is_top_level_join() const;
 
302
 
 
303
  /**
 
304
   * Copy the partial query plan into the optimal query plan.
 
305
   *
 
306
   * @param[in] size the size of the plan which is to be copied
 
307
   */
 
308
  void copyPartialPlanIntoOptimalPlan(uint32_t size)
 
309
  {
 
310
    memcpy(best_positions, positions, 
 
311
           sizeof(optimizer::Position) * size);
 
312
  }
 
313
 
 
314
  void cache_const_exprs();
 
315
 
 
316
  /**
 
317
   * @param[in] index the index of the position to retrieve
 
318
   * @return a reference to the specified position in the optimal
 
319
   *         query plan
 
320
   */
 
321
  optimizer::Position &getPosFromOptimalPlan(uint32_t index)
 
322
  {
 
323
    return best_positions[index];
 
324
  }
 
325
 
 
326
  /**
 
327
   * @param[in] index the index of the position to retrieve
 
328
   * @return a reference to the specified position in the partial
 
329
   *         query plan
 
330
   */
 
331
  optimizer::Position &getPosFromPartialPlan(uint32_t index)
 
332
  {
 
333
    return positions[index];
 
334
  }
 
335
 
 
336
  /**
 
337
   * @param[in] index the index of the position to set
 
338
   * @param[in] in_pos the value to set the position to
 
339
   */
 
340
  void setPosInPartialPlan(uint32_t index, optimizer::Position &in_pos)
 
341
  {
 
342
    positions[index]= in_pos;
 
343
  }
 
344
 
 
345
  /**
 
346
   * @return a pointer to the first position in the partial query plan
 
347
   */
 
348
  optimizer::Position *getFirstPosInPartialPlan()
 
349
  {
 
350
    return positions;
 
351
  }
 
352
 
 
353
  /**
 
354
   * @param[in] index the index of the operator to retrieve from the partial
 
355
   *                  query plan
 
356
   * @return a pointer to the position in the partial query plan
 
357
   */
 
358
  optimizer::Position *getSpecificPosInPartialPlan(int32_t index)
 
359
  {
 
360
    return positions + index;
 
361
  }
 
362
 
 
363
};
 
364
 
 
365
enum_nested_loop_state evaluate_join_record(Join *join, JoinTable *join_tab, int error);
 
366
enum_nested_loop_state evaluate_null_complemented_join_record(Join *join, JoinTable *join_tab);
 
367
enum_nested_loop_state flush_cached_records(Join *join, JoinTable *join_tab, bool skip_last);
 
368
enum_nested_loop_state end_send(Join *join, JoinTable *join_tab, bool end_of_records);
 
369
enum_nested_loop_state end_write(Join *join, JoinTable *join_tab, bool end_of_records);
 
370
enum_nested_loop_state end_update(Join *join, JoinTable *join_tab, bool end_of_records);
 
371
enum_nested_loop_state end_unique_update(Join *join, JoinTable *join_tab, bool end_of_records);
 
372
 
 
373
} /* namespace drizzled */
 
374