~drizzle-trunk/drizzle/development

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