My Project
item_subselect.h
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines