~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item_subselect.h

  • Committer: Monty
  • Date: 2008-10-02 05:41:33 UTC
  • mfrom: (398.1.10 codestyle)
  • Revision ID: mordred@scylla.inaugust.com-20081002054133-tyxv5bmqpazfaqqi
Merged up to 408 of stdint-includes-fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#ifndef DRIZZLED_ITEM_SUBSELECT_H
21
 
#define DRIZZLED_ITEM_SUBSELECT_H
22
 
 
23
20
/* subselect Item */
24
21
 
25
 
 
26
 
#include <drizzled/comp_creator.h>
27
 
#include <drizzled/item/ref.h>
28
 
#include <drizzled/item/field.h>
29
 
#include <drizzled/item/bin_string.h>
30
 
#include <drizzled/util/test.h>
31
 
 
32
 
namespace drizzled
33
 
{
34
 
 
35
 
class Select_Lex;
36
 
class Select_Lex_Unit;
37
 
class Join;
 
22
#ifdef USE_PRAGMA_INTERFACE
 
23
#pragma interface                       /* gcc class implementation */
 
24
#endif
 
25
 
 
26
class st_select_lex;
 
27
class st_select_lex_unit;
 
28
class JOIN;
38
29
class select_result_interceptor;
39
30
class subselect_engine;
40
31
class subselect_hash_sj_engine;
41
32
class Item_bool_func2;
42
33
class Cached_item;
43
 
class Item_in_optimizer;
44
 
class Item_func_not_all;
45
 
class Tmp_Table_Param;
46
 
 
47
34
 
48
35
/* base class for subselects */
49
36
 
52
39
  bool value_assigned; /* value already assigned to subselect */
53
40
public:
54
41
  /* thread handler, will be assigned in fix_fields only */
55
 
  Session *session;
 
42
  THD *thd;
56
43
  /* substitution instead of subselect in case of optimization */
57
44
  Item *substitution;
58
45
  /* unit of subquery */
59
 
  Select_Lex_Unit *unit;
 
46
public:
 
47
  st_select_lex_unit *unit;
60
48
protected:
61
49
  /* engine that perform execution of subselect (single select or union) */
62
50
  subselect_engine *engine;
65
53
  /* cache of used external tables */
66
54
  table_map used_tables_cache;
67
55
  /* allowed number of columns (1 for single value subqueries) */
68
 
  uint32_t max_columns;
 
56
  uint max_columns;
69
57
  /* where subquery is placed */
70
58
  enum_parsing_place parsing_place;
71
59
  /* work with 'substitution' */
80
68
  bool changed;
81
69
 
82
70
  /* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */
83
 
  bool is_correlated;
 
71
  bool is_correlated; 
84
72
 
85
73
  enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
86
74
  enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
95
83
    pointer in constructor initialization list, but we need to pass a pointer
96
84
    to subselect Item class to select_result_interceptor's constructor.
97
85
  */
98
 
  virtual void init (Select_Lex *select_lex,
 
86
  virtual void init (st_select_lex *select_lex,
99
87
                     select_result_interceptor *result);
100
88
 
101
89
  ~Item_subselect();
104
92
  {
105
93
    null_value= 1;
106
94
  }
107
 
  virtual trans_res select_transformer(Join *join);
 
95
  virtual trans_res select_transformer(JOIN *join);
108
96
  bool assigned() { return value_assigned; }
109
97
  void assigned(bool a) { value_assigned= a; }
110
98
  enum Type type() const;
113
101
    update_null_value();
114
102
    return null_value;
115
103
  }
116
 
  bool fix_fields(Session *session, Item **ref);
 
104
  bool fix_fields(THD *thd, Item **ref);
117
105
  virtual bool exec();
118
106
  virtual void fix_length_and_dec();
119
107
  table_map used_tables() const;
121
109
  bool const_item() const;
122
110
  inline table_map get_used_tables_cache() { return used_tables_cache; }
123
111
  inline bool get_const_item_cache() { return const_item_cache; }
124
 
  Item *get_tmp_table_item(Session *session);
 
112
  Item *get_tmp_table_item(THD *thd);
125
113
  void update_used_tables();
126
114
  virtual void print(String *str, enum_query_type query_type);
127
115
  virtual bool have_guarded_conds() { return false; }
145
133
  */
146
134
  virtual void reset_value_registration() {}
147
135
  enum_parsing_place place() { return parsing_place; }
148
 
  bool walk(Item_processor processor, bool walk_subquery, unsigned char *arg);
 
136
  bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
149
137
 
150
138
  /**
151
 
    Get the Select_Lex structure associated with this Item.
152
 
    @return the Select_Lex structure associated with this Item
 
139
    Get the SELECT_LEX structure associated with this Item.
 
140
    @return the SELECT_LEX structure associated with this Item
153
141
  */
154
 
  Select_Lex* get_select_lex();
 
142
  st_select_lex* get_select_lex();
155
143
 
156
144
  friend class select_result_interceptor;
157
145
  friend class Item_in_optimizer;
158
 
  friend bool Item_field::fix_fields(Session *, Item **);
159
 
  friend int  Item_field::fix_outer_field(Session *, Field **, Item **);
160
 
  friend bool Item_ref::fix_fields(Session *, Item **);
161
 
  friend void mark_select_range_as_dependent(Session*,
162
 
                                             Select_Lex*, Select_Lex*,
 
146
  friend bool Item_field::fix_fields(THD *, Item **);
 
147
  friend int  Item_field::fix_outer_field(THD *, Field **, Item **);
 
148
  friend bool Item_ref::fix_fields(THD *, Item **);
 
149
  friend void mark_select_range_as_dependent(THD*,
 
150
                                             st_select_lex*, st_select_lex*,
163
151
                                             Field*, Item*, Item_ident*);
164
152
};
165
153
 
171
159
protected:
172
160
  Item_cache *value, **row;
173
161
public:
174
 
  Item_singlerow_subselect(Select_Lex *select_lex);
 
162
  Item_singlerow_subselect(st_select_lex *select_lex);
175
163
  Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
176
164
 
177
165
  void cleanup();
178
166
  subs_type substype() { return SINGLEROW_SUBS; }
179
167
 
180
168
  void reset();
181
 
  trans_res select_transformer(Join *join);
182
 
  void store(uint32_t i, Item* item);
 
169
  trans_res select_transformer(JOIN *join);
 
170
  void store(uint i, Item* item);
183
171
  double val_real();
184
172
  int64_t val_int ();
185
173
  String *val_str (String *);
186
 
  type::Decimal *val_decimal(type::Decimal *);
 
174
  my_decimal *val_decimal(my_decimal *);
187
175
  bool val_bool();
188
176
  enum Item_result result_type() const;
189
177
  enum_field_types field_type() const;
190
178
  void fix_length_and_dec();
191
179
 
192
 
  uint32_t cols();
193
 
  Item* element_index(uint32_t i) { return reinterpret_cast<Item*>(row[i]); }
194
 
  Item** addr(uint32_t i) { return (Item**)row + i; }
195
 
  bool check_cols(uint32_t c);
 
180
  uint cols();
 
181
  Item* element_index(uint i) { return my_reinterpret_cast(Item*)(row[i]); }
 
182
  Item** addr(uint i) { return (Item**)row + i; }
 
183
  bool check_cols(uint c);
196
184
  bool null_inside();
197
185
  void bring_value();
198
186
 
202
190
    The only caller of this method is handle_sql2003_note184_exception(),
203
191
    see the code there for more details.
204
192
    Note that this method breaks the object internal integrity, by
205
 
    removing it's association with the corresponding Select_Lex,
 
193
    removing it's association with the corresponding SELECT_LEX,
206
194
    making this object orphan from the parse tree.
207
195
    No other method, beside the destructor, should be called on this
208
196
    object, as it is now invalid.
209
 
    @return the Select_Lex structure that was given in the constructor.
 
197
    @return the SELECT_LEX structure that was given in the constructor.
210
198
  */
211
 
  Select_Lex* invalidate_and_restore_select_lex();
 
199
  st_select_lex* invalidate_and_restore_select_lex();
212
200
 
213
201
  friend class select_singlerow_subselect;
214
202
};
215
203
 
216
204
/* used in static ALL/ANY optimization */
 
205
class select_max_min_finder_subselect;
217
206
class Item_maxmin_subselect :public Item_singlerow_subselect
218
207
{
219
208
protected:
220
209
  bool max;
221
210
  bool was_values;  // Set if we have found at least one row
222
211
public:
223
 
  Item_maxmin_subselect(Session *session, Item_subselect *parent,
224
 
                        Select_Lex *select_lex, bool max);
 
212
  Item_maxmin_subselect(THD *thd, Item_subselect *parent,
 
213
                        st_select_lex *select_lex, bool max);
225
214
  virtual void print(String *str, enum_query_type query_type);
226
215
  void cleanup();
227
216
  bool any_value() { return was_values; }
237
226
  bool value; /* value of this item (boolean: exists/not-exists) */
238
227
 
239
228
public:
240
 
  Item_exists_subselect(Select_Lex *select_lex);
 
229
  Item_exists_subselect(st_select_lex *select_lex);
241
230
  Item_exists_subselect(): Item_subselect() {}
242
231
 
243
232
  subs_type substype() { return EXISTS_SUBS; }
244
 
  void reset()
 
233
  void reset() 
245
234
  {
246
235
    value= 0;
247
236
  }
250
239
  int64_t val_int();
251
240
  double val_real();
252
241
  String *val_str(String*);
253
 
  type::Decimal *val_decimal(type::Decimal *);
 
242
  my_decimal *val_decimal(my_decimal *);
254
243
  bool val_bool();
255
244
  void fix_length_and_dec();
256
245
  virtual void print(String *str, enum_query_type query_type);
266
255
  "left_expr IN (SELECT ...)".
267
256
 
268
257
  @detail
269
 
  This class has:
 
258
  This class has: 
270
259
   - A "subquery execution engine" (as a subclass of Item_subselect) that allows
271
260
     it to evaluate subqueries. (and this class participates in execution by
272
261
     having was_null variable where part of execution result is stored.
300
289
public:
301
290
  /* Used to trigger on/off conditions that were pushed down to subselect */
302
291
  bool *pushed_cond_guards;
303
 
 
 
292
  
304
293
  /* Priority of this predicate in the convert-to-semi-join-nest process. */
305
294
  int sj_convert_priority;
306
295
 
307
 
  /*
 
296
  /* 
308
297
    Location of the subquery predicate. It is either
309
298
     - pointer to join nest if the subquery predicate is in the ON expression
310
299
     - (TableList*)1 if the predicate is in the WHERE.
324
313
  {
325
314
    return pushed_cond_guards ? pushed_cond_guards + i : NULL;
326
315
  }
327
 
  void set_cond_guard_var(int i, bool v)
328
 
  {
 
316
  void set_cond_guard_var(int i, bool v) 
 
317
  { 
329
318
    if ( pushed_cond_guards)
330
319
      pushed_cond_guards[i]= v;
331
320
  }
333
322
 
334
323
  Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
335
324
 
336
 
  Item_in_subselect(Item * left_expr, Select_Lex *select_lex);
 
325
  Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
337
326
  Item_in_subselect()
338
 
    :
339
 
      Item_exists_subselect(),
340
 
      left_expr(NULL),
341
 
      left_expr_cache(NULL),
342
 
      first_execution(true),
343
 
      optimizer(NULL),
344
 
      abort_on_null(false),
345
 
      pushed_cond_guards(NULL),
346
 
      sj_convert_priority(0),
347
 
      expr_join_nest(NULL),
348
 
      exec_method(NOT_TRANSFORMED),
349
 
      upper_item(NULL)
 
327
    :Item_exists_subselect(), left_expr_cache(0), first_execution(true),
 
328
    optimizer(0), abort_on_null(0), pushed_cond_guards(NULL),
 
329
    exec_method(NOT_TRANSFORMED), upper_item(0)
350
330
  {}
351
331
  void cleanup();
352
332
  subs_type substype() { return IN_SUBS; }
353
 
  void reset()
 
333
  void reset() 
354
334
  {
355
335
    value= 0;
356
336
    null_value= 0;
357
337
    was_null= 0;
358
338
  }
359
 
  trans_res select_transformer(Join *join);
360
 
  trans_res select_in_like_transformer(Join *join, const Comp_creator *func);
361
 
  trans_res single_value_transformer(Join *join, const Comp_creator *func);
362
 
  trans_res row_value_transformer(Join * join);
363
 
  trans_res single_value_in_to_exists_transformer(Join * join,
364
 
                                                  const Comp_creator *func);
365
 
  trans_res row_value_in_to_exists_transformer(Join * join);
 
339
  trans_res select_transformer(JOIN *join);
 
340
  trans_res select_in_like_transformer(JOIN *join, Comp_creator *func);
 
341
  trans_res single_value_transformer(JOIN *join, Comp_creator *func);
 
342
  trans_res row_value_transformer(JOIN * join);
 
343
  trans_res single_value_in_to_exists_transformer(JOIN * join,
 
344
                                                  Comp_creator *func);
 
345
  trans_res row_value_in_to_exists_transformer(JOIN * join);
366
346
  virtual bool exec();
367
347
  int64_t val_int();
368
348
  double val_real();
369
349
  String *val_str(String*);
370
 
  type::Decimal *val_decimal(type::Decimal *);
 
350
  my_decimal *val_decimal(my_decimal *);
371
351
  void update_null_value () { (void) val_bool(); }
372
352
  bool val_bool();
373
353
  void top_level_item() { abort_on_null=1; }
374
354
  inline bool is_top_level_item() { return abort_on_null; }
375
 
  bool test_limit(Select_Lex_Unit *unit);
 
355
  bool test_limit(st_select_lex_unit *unit);
376
356
  virtual void print(String *str, enum_query_type query_type);
377
 
  bool fix_fields(Session *session, Item **ref);
 
357
  bool fix_fields(THD *thd, Item **ref);
378
358
  bool setup_engine();
379
359
  bool init_left_expr_cache();
380
 
  bool is_expensive_processor(unsigned char *arg);
 
360
  bool is_expensive_processor(uchar *arg);
381
361
 
382
362
  friend class Item_ref_null_helper;
383
363
  friend class Item_is_not_null_test;
396
376
  bool all;
397
377
 
398
378
  Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc,
399
 
                        Select_Lex *select_lex, bool all);
 
379
                        st_select_lex *select_lex, bool all);
400
380
 
401
381
  // only ALL subquery has upper not
402
382
  subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
403
 
  trans_res select_transformer(Join *join);
 
383
  trans_res select_transformer(JOIN *join);
404
384
  virtual void print(String *str, enum_query_type query_type);
405
385
};
406
386
 
407
387
 
408
 
class subselect_engine: public memory::SqlAlloc
 
388
class subselect_engine: public Sql_alloc
409
389
{
410
390
protected:
411
391
  select_result_interceptor *result; /* results storage class */
412
 
  Session *session; /* pointer to current Session */
 
392
  THD *thd; /* pointer to current THD */
413
393
  Item_subselect *item; /* item, that use this engine */
414
394
  enum Item_result res_type; /* type of results */
415
395
  enum_field_types res_field_type; /* column type of the results */
421
401
                         INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE};
422
402
 
423
403
  subselect_engine(Item_subselect *si, select_result_interceptor *res)
424
 
    :session(NULL)
 
404
    :thd(0)
425
405
  {
426
406
    result= res;
427
407
    item= si;
429
409
    res_field_type= DRIZZLE_TYPE_VARCHAR;
430
410
    maybe_null= 0;
431
411
  }
432
 
  virtual ~subselect_engine() {} // to satisfy compiler
 
412
  virtual ~subselect_engine() {}; // to satisfy compiler
433
413
  virtual void cleanup()= 0;
434
414
 
435
415
  /*
436
 
    Also sets "session" for subselect_engine::result.
 
416
    Also sets "thd" for subselect_engine::result.
437
417
    Should be called before prepare().
438
418
  */
439
 
  void set_session(Session *session_arg);
440
 
  Session * get_session() { return session; }
 
419
  void set_thd(THD *thd_arg);
 
420
  THD * get_thd() { return thd; }
441
421
  virtual int prepare()= 0;
442
422
  virtual void fix_length_and_dec(Item_cache** row)= 0;
443
423
  /*
452
432
      stored somewhere by the exec() method itself.
453
433
 
454
434
      A required side effect: If at least one pushed-down predicate is
455
 
      disabled, subselect_engine->no_rows() must return correct result after
 
435
      disabled, subselect_engine->no_rows() must return correct result after 
456
436
      the exec() call.
457
437
 
458
438
    RETURN
461
441
          caller should call exec() again for the new engine.
462
442
  */
463
443
  virtual int exec()= 0;
464
 
  virtual uint32_t cols()= 0; /* return number of columns in select */
465
 
  virtual bool uncacheable()= 0; /* query is uncacheable */
466
 
  virtual bool uncacheable(uint32_t bit_pos)= 0; /* query is uncacheable */
 
444
  virtual uint cols()= 0; /* return number of columns in select */
 
445
  virtual uint8_t uncacheable()= 0; /* query is uncacheable */
467
446
  enum Item_result type() { return res_type; }
468
447
  enum_field_types field_type() { return res_field_type; }
469
448
  virtual void exclude()= 0;
470
 
  virtual bool may_be_null() { return maybe_null; }
 
449
  virtual bool may_be_null() { return maybe_null; };
471
450
  virtual table_map upper_select_const_tables()= 0;
472
451
  static table_map calc_const_tables(TableList *);
473
452
  virtual void print(String *str, enum_query_type query_type)= 0;
489
468
  bool prepared; /* simple subselect is prepared */
490
469
  bool optimized; /* simple subselect is optimized */
491
470
  bool executed; /* simple subselect is executed */
492
 
  Select_Lex *select_lex; /* corresponding select_lex */
493
 
  Join * join; /* corresponding JOIN structure */
 
471
  st_select_lex *select_lex; /* corresponding select_lex */
 
472
  JOIN * join; /* corresponding JOIN structure */
494
473
public:
495
 
  subselect_single_select_engine(Select_Lex *select,
 
474
  subselect_single_select_engine(st_select_lex *select,
496
475
                                 select_result_interceptor *result,
497
476
                                 Item_subselect *item);
498
477
  void cleanup();
499
478
  int prepare();
500
479
  void fix_length_and_dec(Item_cache** row);
501
480
  int exec();
502
 
  uint32_t cols();
503
 
  bool uncacheable();
504
 
  bool uncacheable(uint32_t bit_pos);
 
481
  uint cols();
 
482
  uint8_t uncacheable();
505
483
  void exclude();
506
484
  table_map upper_select_const_tables();
507
485
  virtual void print (String *str, enum_query_type query_type);
511
489
  bool is_executed() const { return executed; }
512
490
  bool no_rows();
513
491
  virtual enum_engine_type engine_type() { return SINGLE_SELECT_ENGINE; }
514
 
  bool save_join_if_explain();
515
492
 
516
493
  friend class subselect_hash_sj_engine;
517
494
  friend class Item_in_subselect;
520
497
 
521
498
class subselect_union_engine: public subselect_engine
522
499
{
523
 
  Select_Lex_Unit *unit;  /* corresponding unit structure */
 
500
  st_select_lex_unit *unit;  /* corresponding unit structure */
524
501
public:
525
 
  subselect_union_engine(Select_Lex_Unit *u,
 
502
  subselect_union_engine(st_select_lex_unit *u,
526
503
                         select_result_interceptor *result,
527
504
                         Item_subselect *item);
528
505
  void cleanup();
529
506
  int prepare();
530
507
  void fix_length_and_dec(Item_cache** row);
531
508
  int exec();
532
 
  uint32_t cols();
533
 
  bool uncacheable();
534
 
  bool uncacheable(uint32_t bit_pos);
 
509
  uint cols();
 
510
  uint8_t uncacheable();
535
511
  void exclude();
536
512
  table_map upper_select_const_tables();
537
513
  virtual void print (String *str, enum_query_type query_type);
543
519
};
544
520
 
545
521
 
546
 
class JoinTable;
 
522
struct st_join_table;
547
523
 
548
524
 
549
525
/*
551
527
  lookup in a unique index.
552
528
 
553
529
  This engine is used to resolve subqueries in forms
554
 
 
555
 
    outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
556
 
 
 
530
  
 
531
    outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where) 
 
532
    
557
533
  or, tuple-based:
558
 
 
 
534
  
559
535
    (oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
560
 
                      FROM tbl WHERE subqwhere)
561
 
 
 
536
                      FROM tbl WHERE subqwhere) 
 
537
  
562
538
  i.e. the subquery is a single table SELECT without GROUP BY, aggregate
563
539
  functions, etc.
564
540
*/
566
542
class subselect_uniquesubquery_engine: public subselect_engine
567
543
{
568
544
protected:
569
 
  JoinTable *tab;
 
545
  st_join_table *tab;
570
546
  Item *cond; /* The WHERE condition of subselect */
571
 
  /*
 
547
  /* 
572
548
    TRUE<=> last execution produced empty set. Valid only when left
573
549
    expression is NULL.
574
550
  */
576
552
  bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */
577
553
public:
578
554
 
579
 
  // constructor can assign Session because it will be called after Join::prepare
580
 
  subselect_uniquesubquery_engine(Session *session_arg, JoinTable *tab_arg,
 
555
  // constructor can assign THD because it will be called after JOIN::prepare
 
556
  subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
581
557
                                  Item_subselect *subs, Item *where)
582
558
    :subselect_engine(subs, 0), tab(tab_arg), cond(where)
583
559
  {
584
 
    set_session(session_arg);
 
560
    set_thd(thd_arg);
585
561
  }
586
562
  void cleanup();
587
563
  int prepare();
588
564
  void fix_length_and_dec(Item_cache** row);
589
565
  int exec();
590
 
  uint32_t cols() { return 1; }
591
 
  bool uncacheable() { return true; }
592
 
  bool uncacheable(uint32_t) { return true; }
 
566
  uint cols() { return 1; }
 
567
  uint8_t uncacheable() { return UNCACHEABLE_DEPENDENT; }
593
568
  void exclude();
594
569
  table_map upper_select_const_tables() { return 0; }
595
570
  virtual void print (String *str, enum_query_type query_type);
606
581
{
607
582
  /* FALSE for 'ref', TRUE for 'ref-or-null'. */
608
583
  bool check_null;
609
 
  /*
 
584
  /* 
610
585
    The "having" clause. This clause (further reffered to as "artificial
611
 
    having") was inserted by subquery transformation code. It contains
612
 
    Item(s) that have a side-effect: they record whether the subquery has
 
586
    having") was inserted by subquery transformation code. It contains 
 
587
    Item(s) that have a side-effect: they record whether the subquery has 
613
588
    produced a row with NULL certain components. We need to use it for cases
614
589
    like
615
590
      (oe1, oe2) IN (SELECT t.key, t.no_key FROM t1)
616
591
    where we do index lookup on t.key=oe1 but need also to check if there
617
592
    was a row such that t.no_key IS NULL.
618
 
 
 
593
    
619
594
    NOTE: This is currently here and not in the uniquesubquery_engine. Ideally
620
595
    it should have been in uniquesubquery_engine in order to allow execution of
621
596
    subqueries like
622
 
 
 
597
    
623
598
      (oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
624
599
 
625
600
    We could use uniquesubquery_engine for the first component and let
632
607
    The above example subquery is handled as a full-blown SELECT with eq_ref
633
608
    access to one table.
634
609
 
635
 
    Due to this limitation, the "artificial having" currently needs to be
 
610
    Due to this limitation, the "artificial having" currently needs to be 
636
611
    checked by only in indexsubquery_engine.
637
612
  */
638
613
  Item *having;
639
614
public:
640
615
 
641
 
  // constructor can assign Session because it will be called after Join::prepare
642
 
  subselect_indexsubquery_engine(Session *session_arg, JoinTable *tab_arg,
 
616
  // constructor can assign THD because it will be called after JOIN::prepare
 
617
  subselect_indexsubquery_engine(THD *thd_arg, st_join_table *tab_arg,
643
618
                                 Item_subselect *subs, Item *where,
644
619
                                 Item *having_arg, bool chk_null)
645
 
    :subselect_uniquesubquery_engine(session_arg, tab_arg, subs, where),
 
620
    :subselect_uniquesubquery_engine(thd_arg, tab_arg, subs, where),
646
621
     check_null(chk_null),
647
622
     having(having_arg)
648
623
  {}
686
661
    QEP to execute the subquery and materialize its result into a
687
662
    temporary table. Created during the first call to exec().
688
663
  */
689
 
  Join *materialize_join;
 
664
  JOIN *materialize_join;
690
665
  /* Temp table context of the outer select's JOIN. */
691
 
  Tmp_Table_Param *tmp_param;
 
666
  TMP_TABLE_PARAM *tmp_param;
692
667
 
693
668
public:
694
 
  subselect_hash_sj_engine(Session *session_in, Item_subselect *in_predicate,
 
669
  subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
695
670
                               subselect_single_select_engine *old_engine)
696
 
    :subselect_uniquesubquery_engine(session_in, NULL, in_predicate, NULL),
 
671
    :subselect_uniquesubquery_engine(thd, NULL, in_predicate, NULL),
697
672
    is_materialized(false), materialize_engine(old_engine),
698
673
    materialize_join(NULL), tmp_param(NULL)
699
674
  {}
705
680
  int prepare() { return 0; }
706
681
  int exec();
707
682
  virtual void print (String *str, enum_query_type query_type);
708
 
  uint32_t cols()
 
683
  uint cols()
709
684
  {
710
685
    return materialize_engine->cols();
711
686
  }
712
687
  virtual enum_engine_type engine_type() { return HASH_SJ_ENGINE; }
713
688
};
714
 
 
715
 
} /* namespace drizzled */
716
 
 
717
 
#endif /* DRIZZLED_ITEM_SUBSELECT_H */