My Project
sql_optimizer.h
00001 #ifndef SQL_OPTIMIZER_INCLUDED
00002 #define SQL_OPTIMIZER_INCLUDED
00003 
00004 /* Copyright (c) 2000, 2015, 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
00017    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00018 
00019 
00022 /*
00023    This structure is used to collect info on potentially sargable
00024    predicates in order to check whether they become sargable after
00025    reading const tables.
00026    We form a bitmap of indexes that can be used for sargable predicates.
00027    Only such indexes are involved in range analysis.
00028 */
00029 
00030 #include "opt_explain_format.h"
00031 
00032 typedef struct st_sargable_param
00033 {
00034   Field *field;              /* field against which to check sargability */
00035   Item **arg_value;          /* values of potential keys for lookups     */
00036   uint num_values;           /* number of values in the above array      */
00037 } SARGABLE_PARAM;
00038 
00039 typedef struct st_rollup
00040 {
00041   enum State { STATE_NONE, STATE_INITED, STATE_READY };
00042   State state;
00043   Item_null_array null_items;
00044   Ref_ptr_array *ref_pointer_arrays;
00045   List<Item> *fields;
00046 } ROLLUP;
00047 
00048 class JOIN :public Sql_alloc
00049 {
00050   JOIN(const JOIN &rhs);                        
00051   JOIN& operator=(const JOIN &rhs);             
00052 public:
00053   JOIN_TAB *join_tab,**best_ref;
00054   JOIN_TAB **map2table;    
00055   TABLE    **table;
00056   /*
00057     The table which has an index that allows to produce the requried ordering.
00058     A special value of 0x1 means that the ordering will be produced by
00059     passing 1st non-const table to filesort(). NULL means no such table exists.
00060   */
00061   TABLE    *sort_by_table;
00085   uint     tables;         
00086   uint     primary_tables; 
00087   uint     const_tables;   
00088   uint     tmp_tables;     
00089   uint     send_group_parts;
00096   bool     sort_and_group; 
00097   bool     first_record,full_join, no_field_update;
00098   bool     group;            
00099   bool     do_send_rows;
00100   table_map all_table_map;   
00101   table_map const_table_map; 
00102 
00108   table_map found_const_table_map;
00109   table_map outer_join;      
00110   /* Number of records produced after join + group operation */
00111   ha_rows  send_records;
00112   ha_rows found_records,examined_rows,row_limit;
00113   // m_select_limit is used to decide if we are likely to scan the whole table.
00114   ha_rows m_select_limit;
00124   ha_rows  fetch_limit;
00125 
00130   ha_rows  min_ft_matches;
00131 
00132   /* Finally picked QEP. This is result of join optimization */
00133   POSITION *best_positions;
00134 
00135 /******* Join optimization state members start *******/
00136   
00137   /* Current join optimization state */
00138   POSITION *positions;  
00139 
00140   /* We also maintain a stack of join optimization states in * join->positions[] */
00141 /******* Join optimization state members end *******/
00142 
00143 
00144   Next_select_func first_select;
00150   double   best_read;
00154   ha_rows  best_rowcount;
00155   List<Item> *fields;
00156   List<Cached_item> group_fields, group_fields_cache;
00157   THD      *thd;
00158   Item_sum  **sum_funcs, ***sum_funcs_end;
00160   Item_sum  **sum_funcs2, ***sum_funcs_end2;
00161   ulonglong  select_options;
00162   select_result *result;
00163   TMP_TABLE_PARAM tmp_table_param;
00164   MYSQL_LOCK *lock;
00166   SELECT_LEX_UNIT *unit;
00168   SELECT_LEX *select_lex;
00176   bool no_const_tables; 
00177   
00178   ROLLUP rollup;                                
00179 
00180   bool select_distinct;                         
00181 
00188   bool group_optimized_away;
00189 
00190   /*
00191     simple_xxxxx is set if ORDER/GROUP BY doesn't include any references
00192     to other tables than the first non-constant table in the JOIN.
00193     It's also set if ORDER/GROUP BY is empty.
00194     Used for deciding for or against using a temporary table to compute 
00195     GROUP/ORDER BY.
00196   */
00197   bool simple_order, simple_group;
00198 
00199   /*
00200     ordered_index_usage is set if an ordered index access
00201     should be used instead of a filesort when computing 
00202     ORDER/GROUP BY.
00203   */
00204   enum
00205   {
00206     ordered_index_void,       // No ordered index avail.
00207     ordered_index_group_by,   // Use index for GROUP BY
00208     ordered_index_order_by    // Use index for ORDER BY
00209   } ordered_index_usage;
00210 
00215   bool no_order;
00217   bool          skip_sort_order;
00218 
00219   bool need_tmp;
00220   int hidden_group_field_count;
00221 
00222   Key_use_array keyuse;
00223 
00224   List<Item> all_fields; 
00225 
00226   List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
00228   List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
00229   List<Item> &fields_list; 
00230   List<Item> procedure_fields_list;
00231   int error; 
00232 
00240   class ORDER_with_src
00241   {
00253     struct null {};
00254 
00255   public:
00256     ORDER *order;  //< ORDER expression that we are wrapping with this class
00257     Explain_sort_clause src; //< origin of order list
00258 
00259   private:
00260     int flags; //< bitmap of Explain_sort_property
00261 
00262   public:
00263     ORDER_with_src() { clean(); }
00264 
00265     ORDER_with_src(ORDER *order_arg, Explain_sort_clause src_arg)
00266     : order(order_arg), src(src_arg), flags(order_arg ? ESP_EXISTS : ESP_none)
00267     {}
00268 
00274     ORDER_with_src &operator=(null *) { clean(); return *this; }
00275 
00281     ORDER_with_src(null *) { clean(); }
00282 
00295     operator       ORDER *()       { return order; }
00296     operator const ORDER *() const { return order; }
00297 
00298     ORDER* operator->() const { return order; }
00299  
00300     void clean() { order= NULL; src= ESC_none; flags= ESP_none; }
00301 
00302     void set_flag(Explain_sort_property flag)
00303     {
00304       DBUG_ASSERT(order);
00305       flags|= flag;
00306     }
00307     void reset_flag(Explain_sort_property flag) { flags&= ~flag; }
00308     bool get_flag(Explain_sort_property flag) const {
00309       DBUG_ASSERT(order);
00310       return flags & flag;
00311     }
00312     int get_flags() const { DBUG_ASSERT(order); return flags; }
00313   };
00314 
00318   ORDER_with_src order, group_list;
00319 
00323   Explain_format_flags explain_flags;
00324 
00342   Item       *conds;                      
00343   Item       *having;                     
00344   Item       *having_for_explain;    
00345   TABLE_LIST *tables_list;           
00346   List<TABLE_LIST> *join_list;       
00347   COND_EQUAL *cond_equal;
00348   /*
00349     Join tab to return to. Points to an element of join->join_tab array, or to
00350     join->join_tab[-1].
00351     This is used at execution stage to shortcut join enumeration. Currently
00352     shortcutting is done to handle outer joins or handle semi-joins with
00353     FirstMatch strategy.
00354   */
00355   JOIN_TAB *return_tab;
00356 
00357   /*
00358     Used pointer reference for this select.
00359     select_lex->ref_pointer_array contains five "slices" of the same length:
00360     |========|========|========|========|========|
00361      ref_ptrs items0   items1   items2   items3
00362    */
00363   Ref_ptr_array ref_ptrs;
00364   // Copy of the initial slice above, to be used with different lists
00365   Ref_ptr_array items0, items1, items2, items3;
00366   // Used by rollup, to restore ref_ptrs after overwriting it.
00367   Ref_ptr_array current_ref_ptrs;
00368 
00369   const char *zero_result_cause; 
00370   
00371   bool union_part; 
00372   bool optimized; 
00373 
00380   bool child_subquery_can_materialize;
00386   bool allow_outer_refs;
00387 
00388   // true: No need to run DTORs on pointers.
00389   Mem_root_array<Item_exists_subselect*, true> sj_subselects;
00390 
00391   /* Temporary tables used to weed-out semi-join duplicates */
00392   List<TABLE> sj_tmp_tables;
00393   List<Semijoin_mat_exec> sjm_exec_list;
00394   /* end of allocation caching storage */
00395 
00397   bool set_group_rpa;
00399   bool group_sent;
00400 
00401   JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
00402        select_result *result_arg)
00403     : keyuse(thd_arg->mem_root),
00404       fields_list(fields_arg),
00405       sj_subselects(thd_arg->mem_root)
00406   {
00407     init(thd_arg, fields_arg, select_options_arg, result_arg);
00408   }
00409 
00410   void init(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
00411        select_result *result_arg)
00412   {
00413     join_tab= 0;
00414     tables= 0;
00415     primary_tables= 0;
00416     const_tables= 0;
00417     tmp_tables= 0;
00418     const_table_map= 0;
00419     join_list= 0;
00420     implicit_grouping= FALSE;
00421     sort_and_group= 0;
00422     first_record= 0;
00423     do_send_rows= 1;
00424     send_records= 0;
00425     found_records= 0;
00426     fetch_limit= HA_POS_ERROR;
00427     min_ft_matches= HA_POS_ERROR;
00428     examined_rows= 0;
00429     thd= thd_arg;
00430     sum_funcs= sum_funcs2= 0;
00431     having= having_for_explain= 0;
00432     select_options= select_options_arg;
00433     result= result_arg;
00434     lock= thd_arg->lock;
00435     select_lex= 0; //for safety
00436     select_distinct= MY_TEST(select_options & SELECT_DISTINCT);
00437     no_order= 0;
00438     simple_order= 0;
00439     simple_group= 0;
00440     ordered_index_usage= ordered_index_void;
00441     skip_sort_order= 0;
00442     need_tmp= 0;
00443     hidden_group_field_count= 0; /*safety*/
00444     error= 0;
00445     return_tab= 0;
00446     ref_ptrs.reset();
00447     items0.reset();
00448     items1.reset();
00449     items2.reset();
00450     items3.reset();
00451     zero_result_cause= 0;
00452     optimized= child_subquery_can_materialize= false;
00453     cond_equal= 0;
00454     group_optimized_away= 0;
00455 
00456     all_fields= fields_arg;
00457     if (&fields_list != &fields_arg)      /* Avoid valgrind-warning */
00458       fields_list= fields_arg;
00459     keyuse.clear();
00460     tmp_table_param.init();
00461     tmp_table_param.end_write_records= HA_POS_ERROR;
00462     rollup.state= ROLLUP::STATE_NONE;
00463 
00464     no_const_tables= FALSE;
00465     /* can help debugging (makes smaller test cases): */
00466     DBUG_EXECUTE_IF("no_const_tables",no_const_tables= TRUE;);
00467     first_select= sub_select;
00468     set_group_rpa= false;
00469     group_sent= 0;
00470   }
00471 
00473   bool plan_is_const() const { return const_tables == primary_tables; }
00474 
00479   bool plan_is_single_table() { return primary_tables - const_tables == 1; }
00480 
00481   int prepare(TABLE_LIST *tables, uint wind_num,
00482               Item *conds, uint og_num, ORDER *order, ORDER *group,
00483               Item *having,
00484               SELECT_LEX *select, SELECT_LEX_UNIT *unit);
00485   int optimize();
00486   void reset();
00487   void exec();
00488   bool prepare_result(List<Item> **columns_list);
00489   bool explain();
00490   bool destroy();
00491   void restore_tmp();
00492   bool alloc_func_list();
00493   bool flatten_subqueries();
00494   bool make_sum_func_list(List<Item> &all_fields,
00495                           List<Item> &send_fields,
00496                           bool before_group_by, bool recompute= FALSE);
00497 
00499   Ref_ptr_array ref_ptr_array_slice(size_t slice_num)
00500   {
00501     size_t slice_sz= select_lex->ref_pointer_array.size() / 5U;
00502     DBUG_ASSERT(select_lex->ref_pointer_array.size() % 5 == 0);
00503     DBUG_ASSERT(slice_num < 5U);
00504     return Ref_ptr_array(&select_lex->ref_pointer_array[slice_num * slice_sz],
00505                          slice_sz);
00506   }
00507 
00513   void copy_ref_ptr_array(Ref_ptr_array dst_arr, Ref_ptr_array src_arr)
00514   {
00515     DBUG_ASSERT(dst_arr.size() >= src_arr.size());
00516     void *dest= dst_arr.array();
00517     const void *src= src_arr.array();
00518     memcpy(dest, src, src_arr.size() * src_arr.element_size());
00519   }
00520 
00522   void set_items_ref_array(Ref_ptr_array src_arr)
00523   {
00524     copy_ref_ptr_array(ref_ptrs, src_arr);
00525     current_ref_ptrs= src_arr;
00526   }
00527 
00529   void init_items_ref_array()
00530   {
00531     items0= ref_ptr_array_slice(1);
00532     copy_ref_ptr_array(items0, ref_ptrs);
00533     current_ref_ptrs= items0;
00534   }
00535 
00536   bool rollup_init();
00537   bool rollup_process_const_fields();
00538   bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
00539                           Item_sum ***func);
00540   int rollup_send_data(uint idx);
00541   int rollup_write_data(uint idx, TABLE *table);
00542   void remove_subq_pushed_predicates(Item **where);
00549   void join_free();
00551   void cleanup(bool full);
00552   void clear();
00553   bool save_join_tab();
00554   void restore_join_tab();
00555   bool init_save_join_tab();
00566   bool send_row_on_empty_set() const
00567   {
00568     return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
00569             group_list == NULL && !group_optimized_away &&
00570             select_lex->having_value != Item::COND_FALSE);
00571   }
00572   bool change_result(select_result *result);
00573   bool is_top_level_join() const
00574   {
00575     return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
00576                                         select_lex == unit->fake_select_lex));
00577   }
00578   bool cache_const_exprs();
00579   bool generate_derived_keys();
00580   void drop_unused_derived_keys();
00581   bool get_best_combination();
00582   bool update_equalities_for_sjm();
00583   bool add_sorting_to_table(JOIN_TAB *tab, ORDER_with_src *order);
00584   bool decide_subquery_strategy();
00585   void refine_best_rowcount();
00586 
00587 private:
00593   void send_data();
00594   
00611   bool create_intermediate_table(JOIN_TAB *tab, List<Item> *tmp_table_fields,
00612                                  ORDER_with_src &tmp_table_group,
00613                                  bool save_sum_fields);
00618   bool create_first_intermediate_table();
00625   void optimize_distinct();
00626 
00638   void optimize_fts_query();
00639 
00640 
00644   void optimize_fts_limit_query();
00645 
00657   void replace_item_field(const char* field_name, Item* new_item);
00658 
00659 #ifdef WITH_PARTITION_STORAGE_ENGINE
00660   bool prune_table_partitions(THD *thd);
00661 #endif
00662 
00666   bool implicit_grouping; 
00667 
00668   void set_prefix_tables();
00669   void cleanup_item_list(List<Item> &items) const;
00670 public: // @todo: Make private
00671   void set_semijoin_embedding();
00672 private:
00673   void set_semijoin_info();
00674   bool set_access_methods();
00675   bool setup_materialized_table(JOIN_TAB *tab, uint tableno,
00676                                 const POSITION *inner_pos,
00677                                 POSITION *sjm_pos);
00678   bool add_having_as_tmp_table_cond(uint curr_tmp_table);
00679   bool make_tmp_tables_info();
00680   bool compare_costs_of_subquery_strategies(
00681          Item_exists_subselect::enum_exec_method *method);
00682 
00684   class Prepare_error_tracker
00685   {
00686 public:
00687     Prepare_error_tracker(THD *thd_arg) : thd(thd_arg) {}
00688     ~Prepare_error_tracker()
00689     {
00690       if (unlikely(thd->is_error()))
00691         thd->lex->mark_broken();
00692     }
00693 private:
00694     THD *const thd;
00695   };
00696 
00697 };
00698 
00699 
00700 bool uses_index_fields_only(Item *item, TABLE *tbl, uint keyno, 
00701                             bool other_tbls_ok);
00702 void update_depend_map(JOIN *join);
00703 void reset_nj_counters(List<TABLE_LIST> *join_list);
00704 Item *remove_eq_conds(THD *thd, Item *cond, Item::cond_result *cond_value);
00705 Item *optimize_cond(THD *thd, Item *conds, COND_EQUAL **cond_equal,
00706                     List<TABLE_LIST> *join_list,
00707                     bool build_equalities, Item::cond_result *cond_value);
00708 Item* substitute_for_best_equal_field(Item *cond,
00709                                       COND_EQUAL *cond_equal,
00710                                       void *table_join_idx);
00711 Item *build_equal_items(THD *thd, Item *cond,
00712                         COND_EQUAL *inherited, bool do_inherit,
00713                         List<TABLE_LIST> *join_list,
00714                         COND_EQUAL **cond_equal_ref);
00715 bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
00716 Key_use_array *create_keyuse_for_table(THD *thd, TABLE *table, uint keyparts,
00717                                        Item_field **fields,
00718                                        List<Item> outer_exprs);
00719 Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
00720                             bool *inherited_fl);
00721 Item_field *get_best_field(Item_field *item_field, COND_EQUAL *cond_equal);
00722 Item *
00723 make_cond_for_table(Item *cond, table_map tables, table_map used_table,
00724                     bool exclude_expensive_cond);
00725 
00732 inline bool field_time_cmp_date(const Field *f, const Item *v)
00733 {
00734   return f->is_temporal() && !f->is_temporal_with_date() &&
00735     v->is_temporal_with_date();
00736 }
00737 
00738 #endif /* SQL_OPTIMIZER_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines