~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/item_subselect.h

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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