diff options
Diffstat (limited to 'sql/item_subselect.h')
-rw-r--r-- | sql/item_subselect.h | 120 |
1 files changed, 81 insertions, 39 deletions
diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 0484ce6c9bf..8c2e74c1ee0 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -71,6 +71,13 @@ protected: bool inside_first_fix_fields; bool done_first_fix_fields; + /* + Set to TRUE if at optimization or execution time we determine that this + item's value is a constant. We need this member because it is not possible + to substitute 'this' with a constant item. + */ + bool forced_const; + public: /* A reference from inside subquery predicate to somewhere outside of it */ class Ref_to_outside : public Sql_alloc @@ -112,13 +119,18 @@ public: /* TRUE <=> The underlying SELECT is correlated w.r.t some ancestor select */ bool is_correlated; - enum trans_res {RES_OK, RES_REDUCE, RES_ERROR}; enum subs_type {UNKNOWN_SUBS, SINGLEROW_SUBS, EXISTS_SUBS, IN_SUBS, ALL_SUBS, ANY_SUBS}; Item_subselect(); virtual subs_type substype() { return UNKNOWN_SUBS; } + bool is_in_predicate() + { + return (substype() == Item_subselect::IN_SUBS || + substype() == Item_subselect::ALL_SUBS || + substype() == Item_subselect::ANY_SUBS); + } /* We need this method, because some compilers do not allow 'this' @@ -135,7 +147,7 @@ public: eliminated= FALSE; null_value= 1; } - virtual trans_res select_transformer(JOIN *join); + virtual bool select_transformer(JOIN *join); bool assigned() { return value_assigned; } void assigned(bool a) { value_assigned= a; } enum Type type() const; @@ -149,12 +161,21 @@ public: void fix_after_pullout(st_select_lex *new_parent, Item **ref); void recalc_used_tables(st_select_lex *new_parent, bool after_pullout); virtual bool exec(); + /* + If subquery optimization or execution determines that the subquery has + an empty result, mark the subquery predicate as a constant value. + */ + void make_const() + { + used_tables_cache= 0; + const_item_cache= 0; + forced_const= TRUE; + } virtual void fix_length_and_dec(); table_map used_tables() const; table_map not_null_tables() const { return 0; } bool const_item() const; inline table_map get_used_tables_cache() { return used_tables_cache; } - inline bool get_const_item_cache() { return const_item_cache; } Item *get_tmp_table_item(THD *thd); void update_used_tables(); virtual void print(String *str, enum_query_type query_type); @@ -172,6 +193,7 @@ public: */ bool is_evaluated() const; bool is_uncacheable() const; + bool is_expensive() { return TRUE; } /* Used by max/min subquery to initialize value presence registration @@ -181,11 +203,23 @@ public: enum_parsing_place place() { return parsing_place; } bool walk(Item_processor processor, bool walk_subquery, uchar *arg); bool mark_as_eliminated_processor(uchar *arg); + bool eliminate_subselect_processor(uchar *arg); + bool set_fake_select_as_master_processor(uchar *arg); bool enumerate_field_refs_processor(uchar *arg); bool check_vcol_func_processor(uchar *int_arg) { return trace_unsupported_by_check_vcol_func_processor("subselect"); } + /** + Callback to test if an IN predicate is expensive. + + @notes + The return value affects the behavior of make_cond_for_table(). + + @retval TRUE if the predicate is expensive + @retval FALSE otherwise + */ + bool is_expensive_processor(uchar *arg) { return TRUE; } Item *safe_charset_converter(CHARSET_INFO *tocs); /** @@ -224,7 +258,7 @@ public: subs_type substype() { return SINGLEROW_SUBS; } void reset(); - trans_res select_transformer(JOIN *join); + bool select_transformer(JOIN *join); void store(uint i, Item* item); double val_real(); longlong val_int (); @@ -313,6 +347,18 @@ public: }; +/* + Possible methods to execute an IN predicate. These are set by the optimizer + based on user-set optimizer switches, semantic analysis and cost comparison. +*/ +#define SUBS_NOT_TRANSFORMED 0 /* No execution method was chosen for this IN. */ +#define SUBS_SEMI_JOIN 1 /* IN was converted to semi-join. */ +#define SUBS_IN_TO_EXISTS 2 /* IN was converted to correlated EXISTS. */ +#define SUBS_MATERIALIZATION 4 /* Execute IN via subquery materialization. */ +/* Partial matching substrategies of MATERIALIZATION. */ +#define SUBS_PARTIAL_MATCH_ROWID_MERGE 8 +#define SUBS_PARTIAL_MATCH_TABLE_SCAN 16 + /** Representation of IN subquery predicates of the form "left_expr IN (SELECT ...)". @@ -330,8 +376,6 @@ public: class Item_in_subselect :public Item_exists_subselect { -public: - Item *left_expr; protected: /* Cache of the left operand of the subquery predicate. Allocated in the @@ -339,12 +383,6 @@ protected: */ List<Cached_item> *left_expr_cache; bool first_execution; - /* - Set to TRUE if at query execution time we determine that this item's - value is a constant during this execution. We need this member because - it is not possible to substitute 'this' with a constant item. - */ - bool is_constant; /* expr & optimizer used in subselect rewriting to store Item for @@ -354,10 +392,24 @@ protected: Item_in_optimizer *optimizer; bool was_null; bool abort_on_null; -public: /* Used to trigger on/off conditions that were pushed down to subselect */ bool *pushed_cond_guards; - + Comp_creator *func; + +protected: + bool init_cond_guards(); + bool select_in_like_transformer(JOIN *join); + bool single_value_transformer(JOIN *join); + bool row_value_transformer(JOIN * join); + bool fix_having(Item *having, st_select_lex *select_lex); + bool create_single_in_to_exists_cond(JOIN * join, + Item **where_item, + Item **having_item); + bool create_row_in_to_exists_cond(JOIN * join, + Item **where_item, + Item **having_item); +public: + Item *left_expr; /* Priority of this predicate in the convert-to-semi-join-nest process. */ int sj_convert_priority; /* @@ -388,14 +440,8 @@ public: */ bool sjm_scan_allowed; - /* The method chosen to execute the IN predicate. */ - enum enum_exec_method { - NOT_TRANSFORMED, /* No execution method was chosen for this IN. */ - SEMI_JOIN, /* IN was converted to semi-join nest and should be removed. */ - IN_TO_EXISTS, /* IN was converted to correlated EXISTS. */ - MATERIALIZATION /* IN will be executed via subquery materialization. */ - }; - enum_exec_method exec_method; + /* A bitmap of possible execution strategies for an IN predicate. */ + uchar in_strategy; bool *get_cond_guard(int i) { @@ -413,9 +459,10 @@ public: Item_in_subselect(Item * left_expr, st_select_lex *select_lex); Item_in_subselect() :Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE), - is_constant(FALSE), optimizer(0), abort_on_null(0), - pushed_cond_guards(NULL), exec_method(NOT_TRANSFORMED), upper_item(0) - {} + optimizer(0), abort_on_null(0), + pushed_cond_guards(NULL), func(NULL), in_strategy(0), + upper_item(0) + {} void cleanup(); subs_type substype() { return IN_SUBS; } void reset() @@ -425,13 +472,10 @@ public: null_value= 0; was_null= 0; } - trans_res select_transformer(JOIN *join); - trans_res select_in_like_transformer(JOIN *join, Comp_creator *func); - trans_res single_value_transformer(JOIN *join, Comp_creator *func); - trans_res row_value_transformer(JOIN * join); - trans_res single_value_in_to_exists_transformer(JOIN * join, - Comp_creator *func); - trans_res row_value_in_to_exists_transformer(JOIN * join); + bool select_transformer(JOIN *join); + bool create_in_to_exists_cond(JOIN *join_arg); + bool inject_in_to_exists_cond(JOIN *join_arg); + virtual bool exec(); longlong val_int(); double val_real(); @@ -446,11 +490,10 @@ public: bool fix_fields(THD *thd, Item **ref); void fix_after_pullout(st_select_lex *new_parent, Item **ref); void update_used_tables(); - bool setup_engine(); + bool setup_mat_engine(); bool init_left_expr_cache(); /* Inform 'this' that it was computed, and contains a valid result. */ void set_first_execution() { if (first_execution) first_execution= FALSE; } - bool is_expensive_processor(uchar *arg); bool expr_cache_is_needed(THD *thd); /* @@ -472,7 +515,6 @@ class Item_allany_subselect :public Item_in_subselect { public: chooser_compare_func_creator func_creator; - Comp_creator *func; bool all; Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc, @@ -480,7 +522,8 @@ public: // only ALL subquery has upper not subs_type substype() { return all?ALL_SUBS:ANY_SUBS; } - trans_res select_transformer(JOIN *join); + bool select_transformer(JOIN *join); + void create_comp_func(bool invert) { func= func_creator(invert); } virtual void print(String *str, enum_query_type query_type); }; @@ -818,10 +861,9 @@ public: {} ~subselect_hash_sj_engine(); - bool init_permanent(List<Item> *tmp_columns); - bool init_runtime(); + bool init(List<Item> *tmp_columns); void cleanup(); - int prepare() { return 0; } /* Override virtual function in base class. */ + int prepare(); int exec(); virtual void print(String *str, enum_query_type query_type); uint cols() |