1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
20
#ifndef DRIZZLED_ITEM_SUBSELECT_H
21
#define DRIZZLED_ITEM_SUBSELECT_H
1
/* Copyright (C) 2000 MySQL AB
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.
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.
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 */
23
16
/* 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;
18
#ifdef USE_PRAGMA_INTERFACE
19
#pragma interface /* gcc class implementation */
23
class st_select_lex_unit;
38
25
class select_result_interceptor;
39
26
class subselect_engine;
40
27
class subselect_hash_sj_engine;
41
28
class Item_bool_func2;
43
class Item_in_optimizer;
44
class Item_func_not_all;
45
class Tmp_Table_Param;
48
31
/* base class for subselects */
50
33
class Item_subselect :public Item_result_field
52
bool value_assigned; /* value already assigned to subselect */
35
my_bool value_assigned; /* value already assigned to subselect */
54
37
/* thread handler, will be assigned in fix_fields only */
56
39
/* substitution instead of subselect in case of optimization */
57
40
Item *substitution;
58
41
/* unit of subquery */
59
Select_Lex_Unit *unit;
43
st_select_lex_unit *unit;
61
45
/* engine that perform execution of subselect (single select or union) */
62
46
subselect_engine *engine;
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)
130
114
old_engine= engine;
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);
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
154
Select_Lex* get_select_lex();
138
st_select_lex* get_select_lex();
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*);
172
156
Item_cache *value, **row;
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) {}
178
162
subs_type substype() { return SINGLEROW_SUBS; }
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();
185
169
String *val_str (String *);
186
170
my_decimal *val_decimal(my_decimal *);
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.
211
Select_Lex* invalidate_and_restore_select_lex();
195
st_select_lex* invalidate_and_restore_select_lex();
213
197
friend class select_singlerow_subselect;
222
206
bool was_values; // Set if we have found at least one row
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);
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; }
233
217
/* exists subselect */
238
222
bool value; /* value of this item (boolean: exists/not-exists) */
241
Item_exists_subselect(Select_Lex *select_lex);
225
Item_exists_subselect(st_select_lex *select_lex);
242
226
Item_exists_subselect(): Item_subselect() {}
244
228
subs_type substype() { return EXISTS_SUBS; }
250
234
enum Item_result result_type() const { return INT_RESULT;}
252
236
double val_real();
253
237
String *val_str(String*);
254
238
my_decimal *val_decimal(my_decimal *);
302
286
/* Used to trigger on/off conditions that were pushed down to subselect */
303
287
bool *pushed_cond_guards;
305
289
/* Priority of this predicate in the convert-to-semi-join-nest process. */
306
290
int sj_convert_priority;
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.
313
TableList *expr_join_nest;
297
TABLE_LIST *expr_join_nest;
315
299
/* The method chosen to execute the IN predicate. */
316
300
enum enum_exec_method {
335
319
Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery
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()
340
Item_exists_subselect(),
342
left_expr_cache(NULL),
343
first_execution(true),
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),
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)
353
328
subs_type substype() { return IN_SUBS; }
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,
341
trans_res row_value_in_to_exists_transformer(JOIN * join);
367
342
virtual bool exec();
369
344
double val_real();
370
345
String *val_str(String*);
371
346
my_decimal *val_decimal(my_decimal *);
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);
383
358
friend class Item_ref_null_helper;
384
359
friend class Item_is_not_null_test;
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);
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);
409
class subselect_engine: public memory::SqlAlloc
384
class subselect_engine: public Sql_alloc
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};
424
399
subselect_engine(Item_subselect *si, select_result_interceptor *res)
429
404
res_type= STRING_RESULT;
430
res_field_type= DRIZZLE_TYPE_VARCHAR;
405
res_field_type= MYSQL_TYPE_VAR_STRING;
433
virtual ~subselect_engine() {} // to satisfy compiler
408
virtual ~subselect_engine() {}; // to satisfy compiler
434
409
virtual void cleanup()= 0;
437
Also sets "session" for subselect_engine::result.
412
Also sets "thd" for subselect_engine::result.
438
413
Should be called before prepare().
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;
462
437
caller should call exec() again for the new engine.
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; }
488
462
class subselect_single_select_engine: public subselect_engine
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 */
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);
501
475
void fix_length_and_dec(Item_cache** row);
505
bool uncacheable(uint32_t bit_pos);
507
480
table_map upper_select_const_tables();
508
481
virtual void print (String *str, enum_query_type query_type);
521
494
class subselect_union_engine: public subselect_engine
523
Select_Lex_Unit *unit; /* corresponding unit structure */
496
st_select_lex_unit *unit; /* corresponding unit structure */
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);
530
503
void fix_length_and_dec(Item_cache** row);
534
bool uncacheable(uint32_t bit_pos);
536
508
table_map upper_select_const_tables();
537
509
virtual void print (String *str, enum_query_type query_type);
551
523
lookup in a unique index.
553
525
This engine is used to resolve subqueries in forms
555
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
527
outer_expr IN (SELECT tbl.unique_key FROM tbl WHERE subq_where)
559
531
(oe1, .. oeN) IN (SELECT uniq_key_part1, ... uniq_key_partK
560
FROM tbl WHERE subqwhere)
532
FROM tbl WHERE subqwhere)
562
534
i.e. the subquery is a single table SELECT without GROUP BY, aggregate
576
548
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,
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)
584
set_session(session_arg);
588
560
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; }
562
uint cols() { return 1; }
563
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
594
565
table_map upper_select_const_tables() { return 0; }
595
566
virtual void print (String *str, enum_query_type query_type);
607
578
/* FALSE for 'ref', TRUE for 'ref-or-null'. */
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
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.
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
623
594
(oe1, oe2) IN (SELECT primary_key, non_key_maybe_null_field FROM tbl)
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.
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.
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)
686
657
QEP to execute the subquery and materialize its result into a
687
658
temporary table. Created during the first call to exec().
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;
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)
700
671
~subselect_hash_sj_engine();