1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
4
* Copyright (C) 2008 Sun Microsystems
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
20
#ifndef DRIZZLED_ITEM_SUBSELECT_H
21
#define DRIZZLED_ITEM_SUBSELECT_H
23
20
/* subselect Item */
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>
36
class Select_Lex_Unit;
22
#ifdef USE_PRAGMA_INTERFACE
23
#pragma interface /* gcc class implementation */
27
class st_select_lex_unit;
38
29
class select_result_interceptor;
39
30
class subselect_engine;
40
31
class subselect_hash_sj_engine;
41
32
class Item_bool_func2;
43
class Item_in_optimizer;
44
class Item_func_not_all;
45
class Tmp_Table_Param;
48
35
/* base class for subselects */
52
39
bool value_assigned; /* value already assigned to subselect */
54
41
/* thread handler, will be assigned in fix_fields only */
56
43
/* substitution instead of subselect in case of optimization */
57
44
Item *substitution;
58
45
/* unit of subquery */
59
Select_Lex_Unit *unit;
47
st_select_lex_unit *unit;
61
49
/* engine that perform execution of subselect (single select or union) */
62
50
subselect_engine *engine;
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.
98
virtual void init (Select_Lex *select_lex,
86
virtual void init (st_select_lex *select_lex,
99
87
select_result_interceptor *result);
101
89
~Item_subselect();
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; }
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);
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
154
Select_Lex* get_select_lex();
142
st_select_lex* get_select_lex();
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*);
172
160
Item_cache *value, **row;
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) {}
178
166
subs_type substype() { return SINGLEROW_SUBS; }
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 *);
188
176
enum Item_result result_type() const;
189
177
enum_field_types field_type() const;
190
178
void fix_length_and_dec();
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);
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();
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.
211
Select_Lex* invalidate_and_restore_select_lex();
199
st_select_lex* invalidate_and_restore_select_lex();
213
201
friend class select_singlerow_subselect;
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
221
210
bool was_values; // Set if we have found at least one row
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);
227
216
bool any_value() { return was_values; }
301
290
/* Used to trigger on/off conditions that were pushed down to subselect */
302
291
bool *pushed_cond_guards;
304
293
/* Priority of this predicate in the convert-to-semi-join-nest process. */
305
294
int sj_convert_priority;
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.
334
323
Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
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()
339
Item_exists_subselect(),
341
left_expr_cache(NULL),
342
first_execution(true),
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),
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)
352
332
subs_type substype() { return IN_SUBS; }
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,
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(); }
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);
382
362
friend class Item_ref_null_helper;
383
363
friend class Item_is_not_null_test;
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);
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);
408
class subselect_engine: public memory::SqlAlloc
388
class subselect_engine: public Sql_alloc
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 */
429
409
res_field_type= DRIZZLE_TYPE_VARCHAR;
432
virtual ~subselect_engine() {} // to satisfy compiler
412
virtual ~subselect_engine() {}; // to satisfy compiler
433
413
virtual void cleanup()= 0;
436
Also sets "session" for subselect_engine::result.
416
Also sets "thd" for subselect_engine::result.
437
417
Should be called before prepare().
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;
461
441
caller should call exec() again for the new engine.
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 */
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);
500
479
void fix_length_and_dec(Item_cache** row);
504
bool uncacheable(uint32_t bit_pos);
482
uint8_t uncacheable();
506
484
table_map upper_select_const_tables();
507
485
virtual void print (String *str, enum_query_type query_type);
521
498
class subselect_union_engine: public subselect_engine
523
Select_Lex_Unit *unit; /* corresponding unit structure */
500
st_select_lex_unit *unit; /* corresponding unit structure */
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);
530
507
void fix_length_and_dec(Item_cache** row);
534
bool uncacheable(uint32_t bit_pos);
510
uint8_t uncacheable();
536
512
table_map upper_select_const_tables();
537
513
virtual void print (String *str, enum_query_type query_type);
551
527
lookup in a unique index.
553
529
This engine is used to resolve subqueries in forms
555
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
531
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
559
535
(oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
560
FROM tbl WHERE subqwhere)
536
FROM tbl WHERE subqwhere)
562
538
i.e. the subquery is a single table SELECT without GROUP BY, aggregate
576
552
bool null_keypart; /* TRUE <=> constructed search tuple has a NULL */
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)
584
set_session(session_arg);
588
564
void fix_length_and_dec(Item_cache** row);
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; }
594
569
table_map upper_select_const_tables() { return 0; }
595
570
virtual void print (String *str, enum_query_type query_type);
607
582
/* FALSE for 'ref', TRUE for 'ref-or-null'. */
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
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.
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
623
598
(oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
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.
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.
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)
686
661
QEP to execute the subquery and materialize its result into a
687
662
temporary table. Created during the first call to exec().
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;
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)
705
680
int prepare() { return 0; }
707
682
virtual void print (String *str, enum_query_type query_type);
710
685
return materialize_engine->cols();
712
687
virtual enum_engine_type engine_type() { return HASH_SJ_ENGINE; }
715
} /* namespace drizzled */
717
#endif /* DRIZZLED_ITEM_SUBSELECT_H */