~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/subselect.h

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
20
23
/* subselect Item */
21
24
 
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;
 
25
 
 
26
#include <drizzled/comp_creator.h>
 
27
#include <drizzled/item/ref.h>
 
28
#include <drizzled/item/field.h>
 
29
 
 
30
class Select_Lex;
 
31
class Select_Lex_Unit;
28
32
class JOIN;
29
33
class select_result_interceptor;
30
34
class subselect_engine;
31
35
class subselect_hash_sj_engine;
32
36
class Item_bool_func2;
33
37
class Cached_item;
 
38
class Item_in_optimizer;
 
39
class Item_func_not_all;
 
40
class Tmp_Table_Param;
 
41
 
34
42
 
35
43
/* base class for subselects */
36
44
 
39
47
  bool value_assigned; /* value already assigned to subselect */
40
48
public:
41
49
  /* thread handler, will be assigned in fix_fields only */
42
 
  THD *thd;
 
50
  Session *session;
43
51
  /* substitution instead of subselect in case of optimization */
44
52
  Item *substitution;
45
53
  /* unit of subquery */
46
54
public:
47
 
  st_select_lex_unit *unit;
 
55
  Select_Lex_Unit *unit;
48
56
protected:
49
57
  /* engine that perform execution of subselect (single select or union) */
50
58
  subselect_engine *engine;
68
76
  bool changed;
69
77
 
70
78
  /* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */
71
 
  bool is_correlated; 
 
79
  bool is_correlated;
72
80
 
73
81
  enum trans_res {RES_OK, RES_REDUCE, RES_ERROR};
74
82
  enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS,
83
91
    pointer in constructor initialization list, but we need to pass a pointer
84
92
    to subselect Item class to select_result_interceptor's constructor.
85
93
  */
86
 
  virtual void init (st_select_lex *select_lex,
 
94
  virtual void init (Select_Lex *select_lex,
87
95
                     select_result_interceptor *result);
88
96
 
89
97
  ~Item_subselect();
101
109
    update_null_value();
102
110
    return null_value;
103
111
  }
104
 
  bool fix_fields(THD *thd, Item **ref);
 
112
  bool fix_fields(Session *session, Item **ref);
105
113
  virtual bool exec();
106
114
  virtual void fix_length_and_dec();
107
115
  table_map used_tables() const;
109
117
  bool const_item() const;
110
118
  inline table_map get_used_tables_cache() { return used_tables_cache; }
111
119
  inline bool get_const_item_cache() { return const_item_cache; }
112
 
  Item *get_tmp_table_item(THD *thd);
 
120
  Item *get_tmp_table_item(Session *session);
113
121
  void update_used_tables();
114
122
  virtual void print(String *str, enum_query_type query_type);
115
123
  virtual bool have_guarded_conds() { return false; }
136
144
  bool walk(Item_processor processor, bool walk_subquery, unsigned char *arg);
137
145
 
138
146
  /**
139
 
    Get the SELECT_LEX structure associated with this Item.
140
 
    @return the SELECT_LEX structure associated with this Item
 
147
    Get the Select_Lex structure associated with this Item.
 
148
    @return the Select_Lex structure associated with this Item
141
149
  */
142
 
  st_select_lex* get_select_lex();
 
150
  Select_Lex* get_select_lex();
143
151
 
144
152
  friend class select_result_interceptor;
145
153
  friend class Item_in_optimizer;
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*,
 
154
  friend bool Item_field::fix_fields(Session *, Item **);
 
155
  friend int  Item_field::fix_outer_field(Session *, Field **, Item **);
 
156
  friend bool Item_ref::fix_fields(Session *, Item **);
 
157
  friend void mark_select_range_as_dependent(Session*,
 
158
                                             Select_Lex*, Select_Lex*,
151
159
                                             Field*, Item*, Item_ident*);
152
160
};
153
161
 
159
167
protected:
160
168
  Item_cache *value, **row;
161
169
public:
162
 
  Item_singlerow_subselect(st_select_lex *select_lex);
 
170
  Item_singlerow_subselect(Select_Lex *select_lex);
163
171
  Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {}
164
172
 
165
173
  void cleanup();
190
198
    The only caller of this method is handle_sql2003_note184_exception(),
191
199
    see the code there for more details.
192
200
    Note that this method breaks the object internal integrity, by
193
 
    removing it's association with the corresponding SELECT_LEX,
 
201
    removing it's association with the corresponding Select_Lex,
194
202
    making this object orphan from the parse tree.
195
203
    No other method, beside the destructor, should be called on this
196
204
    object, as it is now invalid.
197
 
    @return the SELECT_LEX structure that was given in the constructor.
 
205
    @return the Select_Lex structure that was given in the constructor.
198
206
  */
199
 
  st_select_lex* invalidate_and_restore_select_lex();
 
207
  Select_Lex* invalidate_and_restore_select_lex();
200
208
 
201
209
  friend class select_singlerow_subselect;
202
210
};
209
217
  bool max;
210
218
  bool was_values;  // Set if we have found at least one row
211
219
public:
212
 
  Item_maxmin_subselect(THD *thd, Item_subselect *parent,
213
 
                        st_select_lex *select_lex, bool max);
 
220
  Item_maxmin_subselect(Session *session, Item_subselect *parent,
 
221
                        Select_Lex *select_lex, bool max);
214
222
  virtual void print(String *str, enum_query_type query_type);
215
223
  void cleanup();
216
224
  bool any_value() { return was_values; }
226
234
  bool value; /* value of this item (boolean: exists/not-exists) */
227
235
 
228
236
public:
229
 
  Item_exists_subselect(st_select_lex *select_lex);
 
237
  Item_exists_subselect(Select_Lex *select_lex);
230
238
  Item_exists_subselect(): Item_subselect() {}
231
239
 
232
240
  subs_type substype() { return EXISTS_SUBS; }
233
 
  void reset() 
 
241
  void reset()
234
242
  {
235
243
    value= 0;
236
244
  }
255
263
  "left_expr IN (SELECT ...)".
256
264
 
257
265
  @detail
258
 
  This class has: 
 
266
  This class has:
259
267
   - A "subquery execution engine" (as a subclass of Item_subselect) that allows
260
268
     it to evaluate subqueries. (and this class participates in execution by
261
269
     having was_null variable where part of execution result is stored.
289
297
public:
290
298
  /* Used to trigger on/off conditions that were pushed down to subselect */
291
299
  bool *pushed_cond_guards;
292
 
  
 
300
 
293
301
  /* Priority of this predicate in the convert-to-semi-join-nest process. */
294
302
  int sj_convert_priority;
295
303
 
296
 
  /* 
 
304
  /*
297
305
    Location of the subquery predicate. It is either
298
306
     - pointer to join nest if the subquery predicate is in the ON expression
299
307
     - (TableList*)1 if the predicate is in the WHERE.
313
321
  {
314
322
    return pushed_cond_guards ? pushed_cond_guards + i : NULL;
315
323
  }
316
 
  void set_cond_guard_var(int i, bool v) 
317
 
  { 
 
324
  void set_cond_guard_var(int i, bool v)
 
325
  {
318
326
    if ( pushed_cond_guards)
319
327
      pushed_cond_guards[i]= v;
320
328
  }
322
330
 
323
331
  Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
324
332
 
325
 
  Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
 
333
  Item_in_subselect(Item * left_expr, Select_Lex *select_lex);
326
334
  Item_in_subselect()
327
335
    :Item_exists_subselect(), left_expr_cache(0), first_execution(true),
328
336
    optimizer(0), abort_on_null(0), pushed_cond_guards(NULL),
330
338
  {}
331
339
  void cleanup();
332
340
  subs_type substype() { return IN_SUBS; }
333
 
  void reset() 
 
341
  void reset()
334
342
  {
335
343
    value= 0;
336
344
    null_value= 0;
337
345
    was_null= 0;
338
346
  }
339
347
  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);
 
348
  trans_res select_in_like_transformer(JOIN *join, const Comp_creator *func);
 
349
  trans_res single_value_transformer(JOIN *join, const Comp_creator *func);
342
350
  trans_res row_value_transformer(JOIN * join);
343
351
  trans_res single_value_in_to_exists_transformer(JOIN * join,
344
 
                                                  Comp_creator *func);
 
352
                                                  const Comp_creator *func);
345
353
  trans_res row_value_in_to_exists_transformer(JOIN * join);
346
354
  virtual bool exec();
347
355
  int64_t val_int();
352
360
  bool val_bool();
353
361
  void top_level_item() { abort_on_null=1; }
354
362
  inline bool is_top_level_item() { return abort_on_null; }
355
 
  bool test_limit(st_select_lex_unit *unit);
 
363
  bool test_limit(Select_Lex_Unit *unit);
356
364
  virtual void print(String *str, enum_query_type query_type);
357
 
  bool fix_fields(THD *thd, Item **ref);
 
365
  bool fix_fields(Session *session, Item **ref);
358
366
  bool setup_engine();
359
367
  bool init_left_expr_cache();
360
368
  bool is_expensive_processor(unsigned char *arg);
376
384
  bool all;
377
385
 
378
386
  Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc,
379
 
                        st_select_lex *select_lex, bool all);
 
387
                        Select_Lex *select_lex, bool all);
380
388
 
381
389
  // only ALL subquery has upper not
382
390
  subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
389
397
{
390
398
protected:
391
399
  select_result_interceptor *result; /* results storage class */
392
 
  THD *thd; /* pointer to current THD */
 
400
  Session *session; /* pointer to current Session */
393
401
  Item_subselect *item; /* item, that use this engine */
394
402
  enum Item_result res_type; /* type of results */
395
403
  enum_field_types res_field_type; /* column type of the results */
401
409
                         INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE};
402
410
 
403
411
  subselect_engine(Item_subselect *si, select_result_interceptor *res)
404
 
    :thd(0)
 
412
    :session(0)
405
413
  {
406
414
    result= res;
407
415
    item= si;
413
421
  virtual void cleanup()= 0;
414
422
 
415
423
  /*
416
 
    Also sets "thd" for subselect_engine::result.
 
424
    Also sets "session" for subselect_engine::result.
417
425
    Should be called before prepare().
418
426
  */
419
 
  void set_thd(THD *thd_arg);
420
 
  THD * get_thd() { return thd; }
 
427
  void set_session(Session *session_arg);
 
428
  Session * get_session() { return session; }
421
429
  virtual int prepare()= 0;
422
430
  virtual void fix_length_and_dec(Item_cache** row)= 0;
423
431
  /*
432
440
      stored somewhere by the exec() method itself.
433
441
 
434
442
      A required side effect: If at least one pushed-down predicate is
435
 
      disabled, subselect_engine->no_rows() must return correct result after 
 
443
      disabled, subselect_engine->no_rows() must return correct result after
436
444
      the exec() call.
437
445
 
438
446
    RETURN
468
476
  bool prepared; /* simple subselect is prepared */
469
477
  bool optimized; /* simple subselect is optimized */
470
478
  bool executed; /* simple subselect is executed */
471
 
  st_select_lex *select_lex; /* corresponding select_lex */
 
479
  Select_Lex *select_lex; /* corresponding select_lex */
472
480
  JOIN * join; /* corresponding JOIN structure */
473
481
public:
474
 
  subselect_single_select_engine(st_select_lex *select,
 
482
  subselect_single_select_engine(Select_Lex *select,
475
483
                                 select_result_interceptor *result,
476
484
                                 Item_subselect *item);
477
485
  void cleanup();
497
505
 
498
506
class subselect_union_engine: public subselect_engine
499
507
{
500
 
  st_select_lex_unit *unit;  /* corresponding unit structure */
 
508
  Select_Lex_Unit *unit;  /* corresponding unit structure */
501
509
public:
502
 
  subselect_union_engine(st_select_lex_unit *u,
 
510
  subselect_union_engine(Select_Lex_Unit *u,
503
511
                         select_result_interceptor *result,
504
512
                         Item_subselect *item);
505
513
  void cleanup();
519
527
};
520
528
 
521
529
 
522
 
struct st_join_table;
 
530
class JoinTable;
523
531
 
524
532
 
525
533
/*
527
535
  lookup in a unique index.
528
536
 
529
537
  This engine is used to resolve subqueries in forms
530
 
  
531
 
    outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where) 
532
 
    
 
538
 
 
539
    outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
 
540
 
533
541
  or, tuple-based:
534
 
  
 
542
 
535
543
    (oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
536
 
                      FROM tbl WHERE subqwhere) 
537
 
  
 
544
                      FROM tbl WHERE subqwhere)
 
545
 
538
546
  i.e. the subquery is a single table SELECT without GROUP BY, aggregate
539
547
  functions, etc.
540
548
*/
542
550
class subselect_uniquesubquery_engine: public subselect_engine
543
551
{
544
552
protected:
545
 
  st_join_table *tab;
 
553
  JoinTable *tab;
546
554
  Item *cond; /* The WHERE condition of subselect */
547
 
  /* 
 
555
  /*
548
556
    TRUE<=> last execution produced empty set. Valid only when left
549
557
    expression is NULL.
550
558
  */
552
560
  bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */
553
561
public:
554
562
 
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,
 
563
  // constructor can assign Session because it will be called after JOIN::prepare
 
564
  subselect_uniquesubquery_engine(Session *session_arg, JoinTable *tab_arg,
557
565
                                  Item_subselect *subs, Item *where)
558
566
    :subselect_engine(subs, 0), tab(tab_arg), cond(where)
559
567
  {
560
 
    set_thd(thd_arg);
 
568
    set_session(session_arg);
561
569
  }
562
570
  void cleanup();
563
571
  int prepare();
581
589
{
582
590
  /* FALSE for 'ref', TRUE for 'ref-or-null'. */
583
591
  bool check_null;
584
 
  /* 
 
592
  /*
585
593
    The "having" clause. This clause (further reffered to as "artificial
586
 
    having") was inserted by subquery transformation code. It contains 
587
 
    Item(s) that have a side-effect: they record whether the subquery has 
 
594
    having") was inserted by subquery transformation code. It contains
 
595
    Item(s) that have a side-effect: they record whether the subquery has
588
596
    produced a row with NULL certain components. We need to use it for cases
589
597
    like
590
598
      (oe1, oe2) IN (SELECT t.key, t.no_key FROM t1)
591
599
    where we do index lookup on t.key=oe1 but need also to check if there
592
600
    was a row such that t.no_key IS NULL.
593
 
    
 
601
 
594
602
    NOTE: This is currently here and not in the uniquesubquery_engine. Ideally
595
603
    it should have been in uniquesubquery_engine in order to allow execution of
596
604
    subqueries like
597
 
    
 
605
 
598
606
      (oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
599
607
 
600
608
    We could use uniquesubquery_engine for the first component and let
607
615
    The above example subquery is handled as a full-blown SELECT with eq_ref
608
616
    access to one table.
609
617
 
610
 
    Due to this limitation, the "artificial having" currently needs to be 
 
618
    Due to this limitation, the "artificial having" currently needs to be
611
619
    checked by only in indexsubquery_engine.
612
620
  */
613
621
  Item *having;
614
622
public:
615
623
 
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,
 
624
  // constructor can assign Session because it will be called after JOIN::prepare
 
625
  subselect_indexsubquery_engine(Session *session_arg, JoinTable *tab_arg,
618
626
                                 Item_subselect *subs, Item *where,
619
627
                                 Item *having_arg, bool chk_null)
620
 
    :subselect_uniquesubquery_engine(thd_arg, tab_arg, subs, where),
 
628
    :subselect_uniquesubquery_engine(session_arg, tab_arg, subs, where),
621
629
     check_null(chk_null),
622
630
     having(having_arg)
623
631
  {}
663
671
  */
664
672
  JOIN *materialize_join;
665
673
  /* Temp table context of the outer select's JOIN. */
666
 
  TMP_TABLE_PARAM *tmp_param;
 
674
  Tmp_Table_Param *tmp_param;
667
675
 
668
676
public:
669
 
  subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
 
677
  subselect_hash_sj_engine(Session *session_in, Item_subselect *in_predicate,
670
678
                               subselect_single_select_engine *old_engine)
671
 
    :subselect_uniquesubquery_engine(thd, NULL, in_predicate, NULL),
 
679
    :subselect_uniquesubquery_engine(session_in, NULL, in_predicate, NULL),
672
680
    is_materialized(false), materialize_engine(old_engine),
673
681
    materialize_join(NULL), tmp_param(NULL)
674
682
  {}
686
694
  }
687
695
  virtual enum_engine_type engine_type() { return HASH_SJ_ENGINE; }
688
696
};
 
697
 
 
698
#endif /* DRIZZLED_ITEM_SUBSELECT_H */