My Project
|
00001 #ifndef ITEM_SUBSELECT_INCLUDED 00002 #define ITEM_SUBSELECT_INCLUDED 00003 00004 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; version 2 of the License. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software Foundation, 00017 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 00018 00019 /* subselect Item */ 00020 00021 class st_select_lex; 00022 class st_select_lex_unit; 00023 class JOIN; 00024 class select_result_interceptor; 00025 class subselect_engine; 00026 class subselect_hash_sj_engine; 00027 class Item_bool_func2; 00028 class Cached_item; 00029 class Comp_creator; 00030 00031 typedef class st_select_lex SELECT_LEX; 00032 00037 typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); 00038 00039 /* base class for subselects */ 00040 00041 class Item_subselect :public Item_result_field 00042 { 00043 private: 00044 bool value_assigned; /* value already assigned to subselect */ 00051 bool traced_before; 00052 public: 00053 /* 00054 Used inside Item_subselect::fix_fields() according to this scenario: 00055 > Item_subselect::fix_fields 00056 > engine->prepare 00057 > child_join->prepare 00058 (Here we realize we need to do the rewrite and set 00059 substitution= some new Item, eg. Item_in_optimizer ) 00060 < child_join->prepare 00061 < engine->prepare 00062 *ref= substitution; 00063 < Item_subselect::fix_fields 00064 */ 00065 Item *substitution; 00066 public: 00067 /* unit of subquery */ 00068 st_select_lex_unit *unit; 00073 int in_cond_of_tab; 00074 00076 const subselect_engine *get_engine_for_explain() const { return engine; } 00077 00078 protected: 00079 /* engine that perform execution of subselect (single select or union) */ 00080 subselect_engine *engine; 00081 /* old engine if engine was changed */ 00082 subselect_engine *old_engine; 00083 /* cache of used external tables */ 00084 table_map used_tables_cache; 00085 /* allowed number of columns (1 for single value subqueries) */ 00086 uint max_columns; 00087 /* where subquery is placed */ 00088 enum_parsing_place parsing_place; 00089 /* work with 'substitution' */ 00090 bool have_to_be_excluded; 00091 /* cache of constant state */ 00092 bool const_item_cache; 00093 00094 public: 00095 /* changed engine indicator */ 00096 bool engine_changed; 00097 /* subquery is transformed */ 00098 bool changed; 00099 00100 enum trans_res {RES_OK, RES_REDUCE, RES_ERROR}; 00101 enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS, 00102 EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS}; 00103 00104 Item_subselect(); 00105 00106 virtual subs_type substype() { return UNKNOWN_SUBS; } 00107 00108 /* 00109 We need this method, because some compilers do not allow 'this' 00110 pointer in constructor initialization list, but we need to pass a pointer 00111 to subselect Item class to select_result_interceptor's constructor. 00112 */ 00113 virtual void init (st_select_lex *select_lex, 00114 select_result_interceptor *result); 00115 00116 ~Item_subselect(); 00117 virtual void cleanup(); 00118 virtual void reset() 00119 { 00120 null_value= 1; 00121 } 00122 virtual trans_res select_transformer(JOIN *join); 00123 bool assigned() const { return value_assigned; } 00124 void assigned(bool a) { value_assigned= a; } 00125 enum Type type() const; 00126 bool is_null() 00127 { 00128 update_null_value(); 00129 return null_value; 00130 } 00131 bool fix_fields(THD *thd, Item **ref); 00132 void fix_after_pullout(st_select_lex *parent_select, 00133 st_select_lex *removed_select); 00134 virtual bool exec(); 00135 virtual void fix_length_and_dec(); 00136 table_map used_tables() const; 00137 table_map not_null_tables() const { return 0; } 00138 bool const_item() const; 00139 inline table_map get_used_tables_cache() { return used_tables_cache; } 00140 inline bool get_const_item_cache() { return const_item_cache; } 00141 Item *get_tmp_table_item(THD *thd); 00142 void update_used_tables(); 00143 virtual void print(String *str, enum_query_type query_type); 00144 virtual bool have_guarded_conds() { return FALSE; } 00145 bool change_engine(subselect_engine *eng) 00146 { 00147 old_engine= engine; 00148 engine= eng; 00149 engine_changed= 1; 00150 return eng == 0; 00151 } 00152 00153 /* 00154 True if this subquery has been already evaluated. Implemented only for 00155 single select and union subqueries only. 00156 */ 00157 bool is_evaluated() const; 00158 bool is_uncacheable() const; 00159 00160 /* 00161 Used by max/min subquery to initialize value presence registration 00162 mechanism. Engine call this method before rexecution query. 00163 */ 00164 virtual void reset_value_registration() {} 00165 enum_parsing_place place() { return parsing_place; } 00166 bool walk_join_condition(List<TABLE_LIST> *tables, Item_processor processor, 00167 bool walk_subquery, uchar *argument); 00168 bool walk_body(Item_processor processor, bool walk_subquery, uchar *arg); 00169 bool walk(Item_processor processor, bool walk_subquery, uchar *arg); 00170 virtual bool explain_subquery_checker(uchar **arg); 00171 bool inform_item_in_cond_of_tab(uchar *join_tab_index); 00172 virtual bool clean_up_after_removal(uchar *arg); 00173 00174 const char *func_name() const { DBUG_ASSERT(0); return "subselect"; } 00175 00176 friend class select_result_interceptor; 00177 friend class Item_in_optimizer; 00178 friend bool Item_field::fix_fields(THD *, Item **); 00179 friend int Item_field::fix_outer_field(THD *, Field **, Item **); 00180 friend bool Item_ref::fix_fields(THD *, Item **); 00181 friend void Item_ident::fix_after_pullout(st_select_lex *parent_select, 00182 st_select_lex *removed_selec); 00183 friend void mark_select_range_as_dependent(THD*, 00184 st_select_lex*, st_select_lex*, 00185 Field*, Item*, Item_ident*); 00186 }; 00187 00188 /* single value subselect */ 00189 00190 class Item_cache; 00191 class Item_singlerow_subselect :public Item_subselect 00192 { 00193 protected: 00194 Item_cache *value, **row; 00195 bool no_rows; 00196 public: 00197 Item_singlerow_subselect(st_select_lex *select_lex); 00198 Item_singlerow_subselect() : 00199 Item_subselect(), value(0), row (0), no_rows(false) {} 00200 00201 virtual void cleanup(); 00202 subs_type substype() { return SINGLEROW_SUBS; } 00203 00204 virtual void reset(); 00205 trans_res select_transformer(JOIN *join); 00206 void store(uint i, Item* item); 00207 double val_real(); 00208 longlong val_int (); 00209 String *val_str (String *); 00210 my_decimal *val_decimal(my_decimal *); 00211 bool get_date(MYSQL_TIME *ltime, uint fuzzydate); 00212 bool get_time(MYSQL_TIME *ltime); 00213 bool val_bool(); 00214 enum Item_result result_type() const; 00215 enum_field_types field_type() const; 00216 void fix_length_and_dec(); 00217 00218 /* 00219 Mark the subquery as having no rows. 00220 If there are aggregate functions (in the outer query), 00221 we need to generate a NULL row. @c return_zero_rows(). 00222 */ 00223 virtual void no_rows_in_result(); 00224 00225 uint cols(); 00226 Item* element_index(uint i) { return reinterpret_cast<Item*>(row[i]); } 00227 Item** addr(uint i) { return (Item**)row + i; } 00228 bool check_cols(uint c); 00229 bool null_inside(); 00230 void bring_value(); 00231 00244 st_select_lex* invalidate_and_restore_select_lex(); 00245 00246 friend class select_singlerow_subselect; 00247 }; 00248 00249 /* used in static ALL/ANY optimization */ 00250 class select_max_min_finder_subselect; 00251 class Item_maxmin_subselect :public Item_singlerow_subselect 00252 { 00253 protected: 00254 bool max; 00255 bool was_values; // Set if we have found at least one row 00256 public: 00257 Item_maxmin_subselect(THD *thd, Item_subselect *parent, 00258 st_select_lex *select_lex, bool max, bool ignore_nulls); 00259 virtual void print(String *str, enum_query_type query_type); 00260 virtual void cleanup(); 00261 bool any_value() { return was_values; } 00262 void register_value() { was_values= TRUE; } 00263 void reset_value_registration() { was_values= FALSE; } 00264 }; 00265 00266 /* exists subselect */ 00267 00268 class Item_exists_subselect :public Item_subselect 00269 { 00270 protected: 00271 bool value; /* value of this item (boolean: exists/not-exists) */ 00272 00273 public: 00278 enum enum_exec_method { 00279 EXEC_UNSPECIFIED, 00280 EXEC_SEMI_JOIN, 00281 00282 EXEC_EXISTS, 00289 EXEC_EXISTS_OR_MAT, 00291 EXEC_MATERIALIZATION 00292 }; 00293 enum_exec_method exec_method; 00295 int sj_convert_priority; 00297 bool sj_chosen; 00308 TABLE_LIST *embedding_join_nest; 00309 00310 Item_exists_subselect(st_select_lex *select_lex); 00311 Item_exists_subselect() 00312 :Item_subselect(), value(false), exec_method(EXEC_UNSPECIFIED), 00313 sj_convert_priority(0), sj_chosen(false), embedding_join_nest(NULL) 00314 {} 00315 virtual trans_res select_transformer(JOIN *join) 00316 { 00317 exec_method= EXEC_EXISTS; 00318 return RES_OK; 00319 } 00320 subs_type substype() { return EXISTS_SUBS; } 00321 virtual void reset() 00322 { 00323 value= 0; 00324 } 00325 00326 enum Item_result result_type() const { return INT_RESULT;} 00327 longlong val_int(); 00328 double val_real(); 00329 String *val_str(String*); 00330 my_decimal *val_decimal(my_decimal *); 00331 bool val_bool(); 00332 bool get_date(MYSQL_TIME *ltime, uint fuzzydate) 00333 { 00334 return get_date_from_int(ltime, fuzzydate); 00335 } 00336 bool get_time(MYSQL_TIME *ltime) 00337 { 00338 return get_time_from_int(ltime); 00339 } 00340 void fix_length_and_dec(); 00341 virtual void print(String *str, enum_query_type query_type); 00342 00343 friend class select_exists_subselect; 00344 friend class subselect_indexsubquery_engine; 00345 }; 00346 00347 00363 class Item_in_subselect :public Item_exists_subselect 00364 { 00365 public: 00366 Item *left_expr; 00367 protected: 00368 /* 00369 Cache of the left operand of the subquery predicate. Allocated in the 00370 runtime memory root, for each execution, thus need not be freed. 00371 */ 00372 List<Cached_item> *left_expr_cache; 00373 bool left_expr_cache_filled; 00374 00375 bool need_expr_cache; 00376 00377 /* 00378 expr & optimizer used in subselect rewriting to store Item for 00379 all JOIN in UNION 00380 */ 00381 Item *expr; 00382 Item_in_optimizer *optimizer; 00383 bool was_null; 00384 bool abort_on_null; 00385 private: 00391 struct In2exists_info: public Sql_alloc 00392 { 00397 bool added_to_where; 00402 bool originally_dependent; 00403 } *in2exists_info; 00404 00405 Item *remove_in2exists_conds(Item* conds); 00406 00407 public: 00408 /* Used to trigger on/off conditions that were pushed down to subselect */ 00409 bool *pushed_cond_guards; 00410 00411 Item_func_not_all *upper_item; // point on NOT/NOP before ALL/SOME subquery 00412 00413 /* 00414 Location of the subquery predicate. It is either 00415 - pointer to join nest if the subquery predicate is in the ON expression 00416 - (TABLE_LIST*)1 if the predicate is in the WHERE. 00417 */ 00418 TABLE_LIST *expr_join_nest; 00419 00420 bool in2exists_added_to_where() const 00421 { return in2exists_info && in2exists_info->added_to_where; } 00422 00424 bool originally_dependent() const 00425 { return in2exists_info->originally_dependent; } 00426 00427 bool *get_cond_guard(int i) 00428 { 00429 return pushed_cond_guards ? pushed_cond_guards + i : NULL; 00430 } 00431 void set_cond_guard_var(int i, bool v) 00432 { 00433 if ( pushed_cond_guards) 00434 pushed_cond_guards[i]= v; 00435 } 00436 bool have_guarded_conds() { return MY_TEST(pushed_cond_guards); } 00437 00438 Item_in_subselect(Item * left_expr, st_select_lex *select_lex); 00439 Item_in_subselect() 00440 :Item_exists_subselect(), left_expr(NULL), left_expr_cache(NULL), 00441 left_expr_cache_filled(false), need_expr_cache(TRUE), expr(NULL), 00442 optimizer(NULL), was_null(FALSE), abort_on_null(FALSE), 00443 in2exists_info(NULL), pushed_cond_guards(NULL), upper_item(NULL) 00444 {} 00445 virtual void cleanup(); 00446 subs_type substype() { return IN_SUBS; } 00447 virtual void reset() 00448 { 00449 value= 0; 00450 null_value= 0; 00451 was_null= 0; 00452 } 00453 trans_res select_transformer(JOIN *join); 00454 trans_res select_in_like_transformer(JOIN *join, Comp_creator *func); 00455 trans_res single_value_transformer(JOIN *join, Comp_creator *func); 00456 trans_res row_value_transformer(JOIN * join); 00457 trans_res single_value_in_to_exists_transformer(JOIN * join, 00458 Comp_creator *func); 00459 trans_res row_value_in_to_exists_transformer(JOIN * join); 00460 bool walk(Item_processor processor, bool walk_subquery, uchar *arg); 00461 virtual bool exec(); 00462 longlong val_int(); 00463 double val_real(); 00464 String *val_str(String*); 00465 my_decimal *val_decimal(my_decimal *); 00466 void update_null_value () { (void) val_bool(); } 00467 bool val_bool(); 00468 void top_level_item() { abort_on_null=1; } 00469 inline bool is_top_level_item() { return abort_on_null; } 00470 bool test_limit(st_select_lex_unit *unit); 00471 virtual void print(String *str, enum_query_type query_type); 00472 bool fix_fields(THD *thd, Item **ref); 00473 void fix_after_pullout(st_select_lex *parent_select, 00474 st_select_lex *removed_select); 00475 bool init_left_expr_cache(); 00476 00481 bool finalize_exists_transform(SELECT_LEX *select_lex); 00486 bool finalize_materialization_transform(JOIN *join); 00487 00488 friend class Item_ref_null_helper; 00489 friend class Item_is_not_null_test; 00490 friend class Item_in_optimizer; 00491 friend class subselect_indexsubquery_engine; 00492 friend class subselect_hash_sj_engine; 00493 }; 00494 00495 00496 /* ALL/ANY/SOME subselect */ 00497 class Item_allany_subselect :public Item_in_subselect 00498 { 00499 public: 00500 chooser_compare_func_creator func_creator; 00501 Comp_creator *func; 00502 bool all; 00503 00504 Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc, 00505 st_select_lex *select_lex, bool all); 00506 00507 // only ALL subquery has upper not 00508 subs_type substype() { return all?ALL_SUBS:ANY_SUBS; } 00509 trans_res select_transformer(JOIN *join); 00510 virtual void print(String *str, enum_query_type query_type); 00511 }; 00512 00513 00514 class subselect_engine: public Sql_alloc 00515 { 00516 protected: 00517 select_result_interceptor *result; /* results storage class */ 00518 Item_subselect *item; /* item, that use this engine */ 00519 enum Item_result res_type; /* type of results */ 00520 enum_field_types res_field_type; /* column type of the results */ 00521 bool maybe_null; /* may be null (first item in select) */ 00522 public: 00523 00524 enum enum_engine_type {ABSTRACT_ENGINE, SINGLE_SELECT_ENGINE, 00525 UNION_ENGINE, UNIQUESUBQUERY_ENGINE, 00526 INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE}; 00527 00528 subselect_engine(Item_subselect *si, select_result_interceptor *res) 00529 :result(res), item(si), res_type(STRING_RESULT), 00530 res_field_type(MYSQL_TYPE_VAR_STRING), maybe_null(false) 00531 {} 00532 virtual ~subselect_engine() {}; // to satisfy compiler 00536 virtual void cleanup()= 0; 00537 00539 void set_thd_for_result(); 00540 virtual bool prepare()= 0; 00541 virtual void fix_length_and_dec(Item_cache** row)= 0; 00542 /* 00543 Execute the engine 00544 00545 SYNOPSIS 00546 exec() 00547 00548 DESCRIPTION 00549 Execute the engine. The result of execution is subquery value that is 00550 either captured by previously set up select_result-based 'sink' or 00551 stored somewhere by the exec() method itself. 00552 00553 RETURN 00554 0 - OK 00555 1 - Either an execution error, or the engine was "changed", and the 00556 caller should call exec() again for the new engine. 00557 */ 00558 virtual bool exec()= 0; 00559 virtual uint cols() const = 0; /* return number of columns in select */ 00560 virtual uint8 uncacheable() const = 0; /* query is uncacheable */ 00561 virtual enum Item_result type() const { return res_type; } 00562 virtual enum_field_types field_type() const { return res_field_type; } 00563 virtual void exclude()= 0; 00564 virtual bool may_be_null() const { return maybe_null; }; 00565 virtual table_map upper_select_const_tables() const = 0; 00566 static table_map calc_const_tables(TABLE_LIST *); 00567 virtual void print(String *str, enum_query_type query_type)= 0; 00568 virtual bool change_result(Item_subselect *si, 00569 select_result_interceptor *result)= 0; 00570 virtual bool no_tables() const = 0; 00571 virtual bool is_executed() const { return FALSE; } 00572 virtual enum_engine_type engine_type() const { return ABSTRACT_ENGINE; } 00573 #ifndef DBUG_OFF 00574 00578 const Item_subselect *get_item() const { return item; } 00579 #endif 00580 00581 protected: 00582 void set_row(List<Item> &item_list, Item_cache **row); 00583 }; 00584 00585 00586 class subselect_single_select_engine: public subselect_engine 00587 { 00588 private: 00589 bool prepared; /* simple subselect is prepared */ 00590 bool executed; /* simple subselect is executed */ 00591 bool optimize_error; 00592 st_select_lex *select_lex; /* corresponding select_lex */ 00593 JOIN * join; /* corresponding JOIN structure */ 00594 public: 00595 subselect_single_select_engine(st_select_lex *select, 00596 select_result_interceptor *result, 00597 Item_subselect *item); 00598 virtual void cleanup(); 00599 virtual bool prepare(); 00600 virtual void fix_length_and_dec(Item_cache** row); 00601 virtual bool exec(); 00602 virtual uint cols() const; 00603 virtual uint8 uncacheable() const; 00604 virtual void exclude(); 00605 virtual table_map upper_select_const_tables() const; 00606 virtual void print (String *str, enum_query_type query_type); 00607 virtual bool change_result(Item_subselect *si, 00608 select_result_interceptor *result); 00609 virtual bool no_tables() const; 00610 virtual bool may_be_null() const; 00611 virtual bool is_executed() const { return executed; } 00612 virtual enum_engine_type engine_type() const { return SINGLE_SELECT_ENGINE; } 00613 00614 friend class subselect_hash_sj_engine; 00615 friend class Item_in_subselect; 00616 }; 00617 00618 00619 class subselect_union_engine: public subselect_engine 00620 { 00621 public: 00622 subselect_union_engine(st_select_lex_unit *u, 00623 select_result_interceptor *result, 00624 Item_subselect *item); 00625 virtual void cleanup(); 00626 virtual bool prepare(); 00627 virtual void fix_length_and_dec(Item_cache** row); 00628 virtual bool exec(); 00629 virtual uint cols() const; 00630 virtual uint8 uncacheable() const; 00631 virtual void exclude(); 00632 virtual table_map upper_select_const_tables() const; 00633 virtual void print (String *str, enum_query_type query_type); 00634 virtual bool change_result(Item_subselect *si, 00635 select_result_interceptor *result); 00636 virtual bool no_tables() const; 00637 virtual bool is_executed() const; 00638 virtual enum_engine_type engine_type() const { return UNION_ENGINE; } 00639 00640 private: 00641 st_select_lex_unit *unit; /* corresponding unit structure */ 00642 }; 00643 00644 00645 struct st_join_table; 00646 00647 00664 class subselect_indexsubquery_engine : public subselect_engine 00665 { 00666 protected: 00667 st_join_table *tab; 00668 Item *cond; /* The WHERE condition of subselect */ 00669 private: 00670 /* FALSE for 'ref', TRUE for 'ref-or-null'. */ 00671 bool check_null; 00672 /* 00673 The "having" clause. This clause (further referred to as "artificial 00674 having") was inserted by subquery transformation code. It contains 00675 Item(s) that have a side-effect: they record whether the subquery has 00676 produced a row with NULL certain components. We need to use it for cases 00677 like 00678 (oe1, oe2) IN (SELECT t.key, t.no_key FROM t1) 00679 where we do index lookup on t.key=oe1 but need also to check if there 00680 was a row such that t.no_key IS NULL. 00681 */ 00682 Item *having; 00687 bool unique; 00688 public: 00689 00690 // constructor can assign THD because it will be called after JOIN::prepare 00691 subselect_indexsubquery_engine(THD *thd_arg, st_join_table *tab_arg, 00692 Item_subselect *subs, Item *where, 00693 Item *having_arg, bool chk_null, 00694 bool unique_arg) 00695 :subselect_engine(subs, 0), tab(tab_arg), cond(where), 00696 check_null(chk_null), having(having_arg), unique(unique_arg) 00697 {}; 00698 virtual bool exec(); 00699 virtual void print (String *str, enum_query_type query_type); 00700 virtual enum_engine_type engine_type() const 00701 { return unique ? UNIQUESUBQUERY_ENGINE : INDEXSUBQUERY_ENGINE; } 00702 virtual void cleanup() {} 00703 virtual bool prepare(); 00704 virtual void fix_length_and_dec(Item_cache** row); 00705 virtual uint cols() const { return 1; } 00706 virtual uint8 uncacheable() const { return UNCACHEABLE_DEPENDENT; } 00707 virtual void exclude(); 00708 virtual table_map upper_select_const_tables() const { return 0; } 00709 virtual bool change_result(Item_subselect *si, 00710 select_result_interceptor *result); 00711 virtual bool no_tables() const; 00712 bool scan_table(); 00713 void copy_ref_key(bool *require_scan, bool *convert_error); 00714 }; 00715 00716 /* 00717 This function is actually defined in sql_parse.cc, but it depends on 00718 chooser_compare_func_creator defined in this file. 00719 */ 00720 Item * all_any_subquery_creator(Item *left_expr, 00721 chooser_compare_func_creator cmp, 00722 bool all, 00723 SELECT_LEX *select_lex); 00724 00725 00726 inline bool Item_subselect::is_evaluated() const 00727 { 00728 return engine->is_executed(); 00729 } 00730 00731 00732 inline bool Item_subselect::is_uncacheable() const 00733 { 00734 return engine->uncacheable(); 00735 } 00736 00737 00744 class subselect_hash_sj_engine: public subselect_indexsubquery_engine 00745 { 00746 private: 00747 /* TRUE if the subquery was materialized into a temp table. */ 00748 bool is_materialized; 00754 enum nulls_exist 00755 { 00757 NEX_IRRELEVANT_OR_FALSE= 0, 00759 NEX_UNKNOWN= 1, 00761 NEX_TRUE= 2 00762 }; 00763 enum nulls_exist mat_table_has_nulls; 00764 /* 00765 The old engine already chosen at parse time and stored in permanent memory. 00766 Through this member we can re-create and re-prepare the join object 00767 used to materialize the subquery for each execution of a prepared 00768 statement. We also reuse the functionality of 00769 subselect_single_select_engine::[prepare | cols]. 00770 */ 00771 subselect_single_select_engine *materialize_engine; 00772 /* Temp table context of the outer select's JOIN. */ 00773 TMP_TABLE_PARAM *tmp_param; 00774 00775 public: 00776 subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate, 00777 subselect_single_select_engine *old_engine) 00778 :subselect_indexsubquery_engine(thd, NULL, in_predicate, NULL, 00779 NULL, false, true), 00780 is_materialized(false), materialize_engine(old_engine), tmp_param(NULL) 00781 {} 00782 ~subselect_hash_sj_engine(); 00783 00784 bool setup(List<Item> *tmp_columns); 00785 virtual void cleanup(); 00786 virtual bool prepare() 00787 { 00788 return materialize_engine->prepare(); 00789 } 00790 virtual bool exec(); 00791 virtual void print (String *str, enum_query_type query_type); 00792 virtual uint cols() const 00793 { 00794 return materialize_engine->cols(); 00795 } 00796 virtual enum_engine_type engine_type() const { return HASH_SJ_ENGINE; } 00797 00798 const st_join_table *get_join_tab() const { return tab; } 00799 Item *get_cond_for_explain() const { return cond; } 00800 }; 00801 #endif /* ITEM_SUBSELECT_INCLUDED */