diff options
author | unknown <bell@sanja.is.com.ua> | 2004-07-23 09:25:08 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2004-07-23 09:25:08 +0300 |
commit | 8b30e4a7f588ba1b14ceeda73d23c991ac522aa1 (patch) | |
tree | 92c67af83d58a219cbccc4da3f50af08c32235d2 | |
parent | 24241c8c7a4025524e391e2c59e8658227dcc83d (diff) | |
parent | 1b98202be7544b34f79b99cbf22e4b29090e4f9f (diff) | |
download | mariadb-git-8b30e4a7f588ba1b14ceeda73d23c991ac522aa1.tar.gz |
merge
sql/sql_base.cc:
Auto merged
-rw-r--r-- | mysql-test/r/view.result | 15 | ||||
-rw-r--r-- | mysql-test/t/view.test | 11 | ||||
-rw-r--r-- | sql/item.h | 11 | ||||
-rw-r--r-- | sql/sql_base.cc | 20 | ||||
-rw-r--r-- | sql/sql_insert.cc | 9 | ||||
-rw-r--r-- | sql/sql_lex.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 42 | ||||
-rw-r--r-- | sql/table.cc | 5 |
9 files changed, 100 insertions, 16 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index cc7bbfd2e0c..d42c2a24df5 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -999,3 +999,18 @@ select b from v1 use index (some_index) where b=1; ERROR 42000: Key column 'some_index' doesn't exist in table drop view v1; drop table t1; +create table t1 (col1 char(5),col2 char(5)); +create view v1 (col1,col2) as select col1,col2 from t1; +insert into v1 values('s1','p1'),('s1','p2'),('s1','p3'),('s1','p4'),('s2','p1'),('s3','p2'),('s4','p4'); +select distinct first.col2 from t1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1); +col2 +p1 +p2 +p4 +select distinct first.col2 from v1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1); +col2 +p1 +p2 +p4 +drop view v1; +drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6a14c2d573e..f9ff64e2e5b 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -932,3 +932,14 @@ create view v1 as select a, sum(b) from t1 group by a; select b from v1 use index (some_index) where b=1; drop view v1; drop table t1; + +# +# using VIEW fields several times in query resolved via temporary tables +# +create table t1 (col1 char(5),col2 char(5)); +create view v1 (col1,col2) as select col1,col2 from t1; +insert into v1 values('s1','p1'),('s1','p2'),('s1','p3'),('s1','p4'),('s2','p1'),('s3','p2'),('s4','p4'); +select distinct first.col2 from t1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1); +select distinct first.col2 from v1 first where first.col2 in (select second.col2 from t1 second where second.col1<>first.col1); +drop view v1; +drop table t1; diff --git a/sql/item.h b/sql/item.h index 583b17ca1df..afa439dff32 100644 --- a/sql/item.h +++ b/sql/item.h @@ -887,15 +887,15 @@ public: Item *orig_item; /* things in 'cleanup()' */ Item_ref(Item **hook, Item *original,const char *db_par, const char *table_name_par, const char *field_name_par) - :Item_ident(db_par,table_name_par,field_name_par),ref(0), hook_ptr(hook), - orig_item(original) {} - Item_ref(Item **item, Item **hook, + :Item_ident(db_par, table_name_par, field_name_par), result_field(0), + ref(0), hook_ptr(hook), orig_item(original) {} + Item_ref(Item **item, Item **hook, const char *table_name_par, const char *field_name_par) - :Item_ident(NullS,table_name_par,field_name_par), + :Item_ident(NullS, table_name_par, field_name_par), result_field(0), ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {} // Constructor need to process subselect with temporary tables (see Item) Item_ref(THD *thd, Item_ref *item, Item **hook) - :Item_ident(thd, item), ref(item->ref), + :Item_ident(thd, item), result_field(item->result_field), ref(item->ref), hook_ptr(hook), orig_item(hook ? *hook : 0) {} enum Type type() const { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const @@ -940,6 +940,7 @@ public: return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); } void set_result_field(Field *field) { result_field= field; } + Field *get_tmp_table_field() { return result_field; } bool is_result_field() { return 1; } void save_in_result_field(bool no_conversions) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ec50a30c953..6ff50b32f50 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1955,7 +1955,6 @@ Field *find_field_in_table(THD *thd, TABLE_LIST *table_list, { if (strcmp(trans[i]->name, name) == 0) { - *ref= trans[i]; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (check_grants_view && check_grant_column(thd, &table_list->grant, @@ -1964,6 +1963,21 @@ Field *find_field_in_table(THD *thd, TABLE_LIST *table_list, name, length)) return WRONG_GRANT; #endif + if (thd->lex->current_select->no_wrap_view_item) + *ref= trans[i]; + else + { + Item_arena *arena= thd->current_arena, backup; + if (arena) + thd->set_n_backup_item_arena(arena, &backup); + *ref= new Item_ref(trans + i, 0, table_list->view_name.str, + name); + if (arena) + thd->restore_backup_item_arena(arena, &backup); + /* as far as Item_ref have defined refernce it do not need tables */ + if (*ref) + (*ref)->fix_fields(thd, 0, ref); + } return (Field*) view_ref_found; } } @@ -2441,6 +2455,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, { reg2 Item *item; List_iterator<Item> it(fields); + SELECT_LEX *select_lex= thd->lex->current_select; DBUG_ENTER("setup_fields"); thd->set_query_id=set_query_id; @@ -2452,7 +2467,10 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, { if (!item->fixed && item->fix_fields(thd, tables, it.ref()) || (item= *(it.ref()))->check_cols(1)) + { + select_lex->no_wrap_view_item= 0; DBUG_RETURN(-1); /* purecov: inspected */ + } if (ref) *(ref++)= item; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a9a7d9b4d5a..b43c4d31b34 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -76,6 +76,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields, else { // Part field list TABLE_LIST *save_next= table_list->next_local; + int res; if (fields.elements != values.elements) { my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW, @@ -86,12 +87,14 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields, table_list->next_local= 0; thd->dupp_field=0; - if (setup_fields(thd, 0, table_list, fields, 1, 0, 0)) + thd->lex->select_lex.no_wrap_view_item= 1; + res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); + thd->lex->select_lex.no_wrap_view_item= 0; + table_list->next_local= save_next; + if (res) { - table_list->next_local= save_next; return -1; } - table_list->next_local= save_next; if (check_unique && thd->dupp_field) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index aa1c44b8e73..c4390ce0f9a 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1005,6 +1005,7 @@ void st_select_lex::init_query() first_execution= 1; first_cond_optimization= 1; parsing_place= SELECT_LEX_NODE::NO_MATTER; + no_wrap_view_item= 0; } void st_select_lex::init_select() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5bf6e49abb0..d25381072a5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -478,6 +478,8 @@ public: bool subquery_in_having; bool first_execution; /* first execution in SP or PS */ bool first_cond_optimization; + /* do not wrap view fields with Item_ref */ + bool no_wrap_view_item; /* SELECT for SELECT command st_select_lex. Used to privent scaning diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7d49c422194..61fb4b97200 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -53,6 +53,7 @@ static bool compare_record(TABLE *table, ulong query_id) SYNOPSIS check_fields() + thd thread handler items Items for check RETURN @@ -60,9 +61,9 @@ static bool compare_record(TABLE *table, ulong query_id) FALSE Items are OK */ -static bool check_fields(List<Item> &items) +static bool check_fields(THD *thd, List<Item> &items) { - List_iterator_fast<Item> it(items); + List_iterator<Item> it(items); Item *item; while ((item= it++)) { @@ -72,6 +73,13 @@ static bool check_fields(List<Item> &items) my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); return TRUE; } + /* + we make temporary copy of Item_field, to avoid influence of changing + result_field on Item_ref which refer on this field + */ + Item_field *field= new Item_field(thd, (Item_field *)item); + it.replace(field); + ((Item_field *)item)->register_item_tree_changing(it.ref()); } return FALSE; } @@ -139,9 +147,14 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; #endif - if (setup_fields(thd, 0, table_list, fields, 1, 0, 0)) - DBUG_RETURN(-1); /* purecov: inspected */ - if (check_fields(fields)) + { + thd->lex->select_lex.no_wrap_view_item= 1; + int res= setup_fields(thd, 0, table_list, fields, 1, 0, 0); + thd->lex->select_lex.no_wrap_view_item= 0; + if (res) + DBUG_RETURN(-1); /* purecov: inspected */ + } + if (table_list->view && check_fields(thd, fields)) { DBUG_RETURN(-1); } @@ -521,6 +534,8 @@ int mysql_multi_update_prepare(THD *thd) List<Item> *fields= &lex->select_lex.item_list; TABLE_LIST *tl; table_map tables_for_update= 0, readonly_tables= 0; + int res; + bool update_view= 0; DBUG_ENTER("mysql_multi_update_prepare"); /* Ensure that we have update privilege for all tables and columns in the @@ -545,9 +560,22 @@ int mysql_multi_update_prepare(THD *thd) time. */ if (setup_tables(thd, table_list, &lex->select_lex.where) || - setup_fields(thd, 0, table_list, *fields, 1, 0, 0)) + (thd->lex->select_lex.no_wrap_view_item= 1, + res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0), + thd->lex->select_lex.no_wrap_view_item= 0, + res)) DBUG_RETURN(-1); - if (check_fields(*fields)) + + for (tl= table_list; tl ; tl= tl->next_local) + { + if (tl->view) + { + update_view= 1; + break; + } + } + + if (update_view && check_fields(thd, *fields)) { DBUG_RETURN(-1); } diff --git a/sql/table.cc b/sql/table.cc index 0dc3c77e6a5..097dc8aabf6 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1505,6 +1505,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) List_iterator_fast<Item> it(select->item_list); uint i= 0; bool save_set_query_id= thd->set_query_id; + bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; DBUG_ENTER("st_table_list::setup_ancestor"); if (ancestor->ancestor && @@ -1542,6 +1543,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) /* prevent look up in SELECTs tree */ thd->lex->current_select= &thd->lex->select_lex; + thd->lex->select_lex.no_wrap_view_item= 1; + /* Resolve all view items against ancestor table. @@ -1596,6 +1599,7 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds) } ok: + thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->current_select= current_select_save; thd->set_query_id= save_set_query_id; DBUG_RETURN(0); @@ -1607,6 +1611,7 @@ err: thd->clear_error(); my_error(ER_VIEW_INVALID, MYF(0), view_db.str, view_name.str); } + thd->lex->select_lex.no_wrap_view_item= save_wrapper; thd->lex->current_select= current_select_save; thd->set_query_id= save_set_query_id; DBUG_RETURN(1); |