~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join.h

  • Committer: Monty Taylor
  • Date: 2008-12-06 22:41:03 UTC
  • mto: (656.1.7 devel)
  • mto: This revision was merged to the branch mainline in revision 665.
  • Revision ID: monty@inaugust.com-20081206224103-jdouqwt9hb0f01y1
Moved non-working tests into broken suite for easier running of working tests.

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