diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 2d4b3a6c27a..fd61ffb1efc 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3601,6 +3601,12 @@ create view v2 as select 1 a from t2, v1 where c in insert into t1 values (1), (1); insert into t2 values (1), (1); prepare stmt from "select * from v2 where a = 1"; +execute stmt; +a +1 +1 +1 +1 drop view v1, v2; drop table t1, t2; CREATE TABLE t1 (a INT); diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index bf7ba1a5faa..f14ee74b87e 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3574,9 +3574,7 @@ insert into t1 values (1), (1); insert into t2 values (1), (1); prepare stmt from "select * from v2 where a = 1"; -# !!! This command returns a wrong result due to a bug in the code of mwl106 -# !!! Unocomment it when the bug is fixed -# execute stmt; +execute stmt; drop view v1, v2; drop table t1, t2; diff --git a/sql/item.cc b/sql/item.cc index 0660ea4fd41..eb38ee2e30b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -652,7 +652,7 @@ void Item_ident::cleanup() bool Item_ident::remove_dependence_processor(uchar * arg) { DBUG_ENTER("Item_ident::remove_dependence_processor"); - if (depended_from == (st_select_lex *) arg) + if (get_depended_from() == (st_select_lex *) arg) depended_from= 0; context= &((st_select_lex *) arg)->context; DBUG_RETURN(0); @@ -2292,17 +2292,17 @@ table_map Item_field::used_tables() const { if (field->table->const_table) return 0; // const item - return (depended_from ? OUTER_REF_TABLE_BIT : field->table->map); + return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map); } table_map Item_field::all_used_tables() const { - return (depended_from ? OUTER_REF_TABLE_BIT : field->table->map); + return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map); } void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref) { - if (new_parent == depended_from) + if (new_parent == get_depended_from()) depended_from= NULL; Name_resolution_context *ctx= new Name_resolution_context(); ctx->outer_context= NULL; // We don't build a complete name resolver @@ -6299,8 +6299,9 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) { if (depended_from && reference) { - DBUG_ASSERT(context->select_lex != depended_from); - context->select_lex->register_dependency_item(depended_from, reference); + DBUG_ASSERT(context->select_lex != get_depended_from()); + context->select_lex->register_dependency_item(get_depended_from(), + reference); } /* It could be that we're referring to something that's in ancestor selects. @@ -7260,7 +7261,7 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference) void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent, Item **ref) { - if (depended_from == new_parent) + if (get_depended_from() == new_parent) { *ref= outer_ref; (*ref)->fix_after_pullout(new_parent, ref); @@ -7270,7 +7271,7 @@ void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent, Item **ref) void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr) { (*ref)->fix_after_pullout(new_parent, ref); - if (depended_from == new_parent) + if (get_depended_from() == new_parent) depended_from= NULL; } @@ -8860,6 +8861,49 @@ void view_error_processor(THD *thd, void *data) ((TABLE_LIST *)data)->hide_view_error(thd); } + +inline struct st_select_lex *Item_ident::get_depended_from() const +{ + st_select_lex *dep; + if ((dep= depended_from)) + for ( ; dep->merged_into; dep= dep->merged_into); + return dep; +} + + +table_map Item_ref::used_tables() const +{ + return get_depended_from() ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); +} + + +void Item_ref::update_used_tables() +{ + if (!get_depended_from()) + (*ref)->update_used_tables(); +} + + +table_map Item_direct_view_ref::used_tables() const +{ + return get_depended_from() ? + OUTER_REF_TABLE_BIT : + (view->merged ? (*ref)->used_tables() : view->table->map); +} + + +/* + we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE +*/ +table_map Item_ref_null_helper::used_tables() const +{ + return (get_depended_from() ? + OUTER_REF_TABLE_BIT : + (*ref)->used_tables() | RAND_TABLE_BIT); +} + + + /***************************************************************************** ** Instantiate templates *****************************************************************************/ diff --git a/sql/item.h b/sql/item.h index 5527ffd9ca1..68ce9ffdc9e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1637,6 +1637,7 @@ public: Item_ident(TABLE_LIST *view_arg, const char *field_name_arg); const char *full_name() const; void cleanup(); + struct st_select_lex *get_depended_from() const; bool remove_dependence_processor(uchar * arg); virtual void print(String *str, enum_query_type query_type); virtual bool change_context_processor(uchar *cntx) @@ -2524,15 +2525,8 @@ public: Field *get_tmp_table_field() { return result_field ? result_field : (*ref)->get_tmp_table_field(); } Item *get_tmp_table_item(THD *thd); - table_map used_tables() const - { - return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); - } - void update_used_tables() - { - if (!depended_from) - (*ref)->update_used_tables(); - } + inline table_map used_tables() const; + inline void update_used_tables(); bool const_item() const { return (*ref)->const_item(); @@ -2852,12 +2846,7 @@ public: bool subst_argument_checker(uchar **arg); Item *equal_fields_propagator(uchar *arg); Item *replace_equal_field(uchar *arg); - table_map used_tables() const - { - return depended_from ? - OUTER_REF_TABLE_BIT : - (view->merged ? (*ref)->used_tables() : view->table->map); - } + table_map used_tables() const; bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (*ref)->walk(processor, walk_subquery, arg) || @@ -2960,15 +2949,7 @@ public: bool val_bool(); bool get_date(MYSQL_TIME *ltime, uint fuzzydate); virtual void print(String *str, enum_query_type query_type); - /* - we add RAND_TABLE_BIT to prevent moving this item from HAVING to WHERE - */ - table_map used_tables() const - { - return (depended_from ? - OUTER_REF_TABLE_BIT : - (*ref)->used_tables() | RAND_TABLE_BIT); - } + table_map used_tables() const; }; /* diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1a9e12efccc..d2b1522c218 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -426,7 +426,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, Don't save field value if no data has been read yet. Outer constant values are always saved. */ - bool save_field_value= (field_item->depended_from && + bool save_field_value= (field_item->get_depended_from() && (field_item->const_item() || !(field->table->status & STATUS_NO_RECORD))); if (save_field_value) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index bbdcbab8133..18f6e4b21ae 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1669,6 +1669,7 @@ void st_select_lex::init_select() cond_value= having_value= Item::COND_UNDEF; inner_refs_list.empty(); full_group_by_flag= 0; + merged_into= 0; } /* @@ -3393,6 +3394,7 @@ bool SELECT_LEX::merge_subquery(TABLE_LIST *derived, SELECT_LEX *subq_select, /* Walk through child's tables and adjust table map, tablenr, * parent_lex */ subq_select->remap_tables(derived, map, table_no, this); + subq_select->merged_into= this; return FALSE; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e8efae8859f..c0bd522036d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -638,6 +638,8 @@ public: List leaf_tables; List leaf_tables_exec; uint insert_tables; + st_select_lex *merged_into; /* select which this select is merged into */ + /* (not 0 only for views/derived tables) */ const char *type; /* type of select for EXPLAIN */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 2c769e40f72..945ee0f41f0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3903,7 +3903,7 @@ is_local_field (Item *field) { return field->real_item()->type() == Item::FIELD_ITEM && !(field->used_tables() & OUTER_REF_TABLE_BIT) - && !((Item_field *)field->real_item())->depended_from; + && !((Item_field *)field->real_item())->get_depended_from(); } @@ -9586,21 +9586,21 @@ static bool check_simple_equality(Item *left_item, Item *right_item, if (left_item->type() == Item::REF_ITEM && ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) { - if (((Item_ref*)left_item)->depended_from) + if (((Item_ref*)left_item)->get_depended_from()) return FALSE; left_item= left_item->real_item(); } if (right_item->type() == Item::REF_ITEM && ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) { - if (((Item_ref*)right_item)->depended_from) + if (((Item_ref*)right_item)->get_depended_from()) return FALSE; right_item= right_item->real_item(); } if (left_item->type() == Item::FIELD_ITEM && right_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - !((Item_field*)right_item)->depended_from) + !((Item_field*)left_item)->get_depended_from() && + !((Item_field*)right_item)->get_depended_from()) { /* The predicate the form field1=field2 is processed */ @@ -9683,7 +9683,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, Item_field *field_item= 0; Item *orig_field_item= 0; if (left_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && + !((Item_field*)left_item)->get_depended_from() && right_item->const_item()) { orig_field_item= left_item; @@ -9691,7 +9691,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item, const_item= right_item; } else if (right_item->type() == Item::FIELD_ITEM && - !((Item_field*)right_item)->depended_from && + !((Item_field*)right_item)->get_depended_from() && left_item->const_item()) { orig_field_item= right_item;