17
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
#ifndef DRIZZLED_ITEM_SUBSELECT_H
21
#define DRIZZLED_ITEM_SUBSELECT_H
20
23
/* subselect Item */
22
#ifdef USE_PRAGMA_INTERFACE
23
#pragma interface /* gcc class implementation */
27
class st_select_lex_unit;
26
#include <drizzled/comp_creator.h>
27
#include <drizzled/item/ref.h>
28
#include <drizzled/item/field.h>
31
class Select_Lex_Unit;
29
33
class select_result_interceptor;
30
34
class subselect_engine;
31
35
class subselect_hash_sj_engine;
32
36
class Item_bool_func2;
38
class Item_in_optimizer;
39
class Item_func_not_all;
40
class Tmp_Table_Param;
35
43
/* base class for subselects */
39
47
bool value_assigned; /* value already assigned to subselect */
41
49
/* thread handler, will be assigned in fix_fields only */
43
51
/* substitution instead of subselect in case of optimization */
44
52
Item *substitution;
45
53
/* unit of subquery */
47
st_select_lex_unit *unit;
55
Select_Lex_Unit *unit;
49
57
/* engine that perform execution of subselect (single select or union) */
50
58
subselect_engine *engine;
70
78
/* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */
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.
86
virtual void init (st_select_lex *select_lex,
94
virtual void init (Select_Lex *select_lex,
87
95
select_result_interceptor *result);
101
109
update_null_value();
102
110
return null_value;
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);
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
142
st_select_lex* get_select_lex();
150
Select_Lex* get_select_lex();
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*);
160
168
Item_cache *value, **row;
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) {}
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.
199
st_select_lex* invalidate_and_restore_select_lex();
207
Select_Lex* invalidate_and_restore_select_lex();
201
209
friend class select_singlerow_subselect;
210
218
bool was_values; // Set if we have found at least one row
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);
216
224
bool any_value() { return was_values; }
226
234
bool value; /* value of this item (boolean: exists/not-exists) */
229
Item_exists_subselect(st_select_lex *select_lex);
237
Item_exists_subselect(Select_Lex *select_lex);
230
238
Item_exists_subselect(): Item_subselect() {}
232
240
subs_type substype() { return EXISTS_SUBS; }
255
263
"left_expr IN (SELECT ...)".
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.
290
298
/* Used to trigger on/off conditions that were pushed down to subselect */
291
299
bool *pushed_cond_guards;
293
301
/* Priority of this predicate in the convert-to-semi-join-nest process. */
294
302
int sj_convert_priority;
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.
314
322
return pushed_cond_guards ? pushed_cond_guards + i : NULL;
316
void set_cond_guard_var(int i, bool v)
324
void set_cond_guard_var(int i, bool v)
318
326
if ( pushed_cond_guards)
319
327
pushed_cond_guards[i]= v;
323
331
Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
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),
332
340
subs_type substype() { return IN_SUBS; }
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,
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();
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);
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);
381
389
// only ALL subquery has upper not
382
390
subs_type substype() { return all?ALL_SUBS:ANY_SUBS; }
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 */
413
421
virtual void cleanup()= 0;
416
Also sets "thd" for subselect_engine::result.
424
Also sets "session" for subselect_engine::result.
417
425
Should be called before prepare().
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;
432
440
stored somewhere by the exec() method itself.
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
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 */
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);
498
506
class subselect_union_engine: public subselect_engine
500
st_select_lex_unit *unit; /* corresponding unit structure */
508
Select_Lex_Unit *unit; /* corresponding unit structure */
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);
527
535
lookup in a unique index.
529
537
This engine is used to resolve subqueries in forms
531
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
539
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
535
543
(oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
536
FROM tbl WHERE subqwhere)
544
FROM tbl WHERE subqwhere)
538
546
i.e. the subquery is a single table SELECT without GROUP BY, aggregate
552
560
bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */
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)
568
set_session(session_arg);
582
590
/* FALSE for 'ref', TRUE for 'ref-or-null'. */
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
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.
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
598
606
(oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
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.
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.
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)
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;
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)