diff options
author | bell@sanja.is.com.ua <> | 2004-10-07 22:54:31 +0300 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2004-10-07 22:54:31 +0300 |
commit | 78997a2acd2267f33eeed79864a1d2e5ea724262 (patch) | |
tree | 7e5963f2f643caf651ba3048f7031c2303905b6e | |
parent | d73ba9660d3e44c1f9bb17529ddb343849a35889 (diff) | |
download | mariadb-git-78997a2acd2267f33eeed79864a1d2e5ea724262.tar.gz |
allow merging views with subqueries in WHERE clause (BUG#5504)
-rw-r--r-- | mysql-test/r/view.result | 39 | ||||
-rw-r--r-- | mysql-test/t/view.test | 30 | ||||
-rw-r--r-- | sql/item_subselect.h | 1 | ||||
-rw-r--r-- | sql/sql_lex.cc | 30 | ||||
-rw-r--r-- | sql/sql_view.cc | 22 |
5 files changed, 110 insertions, 12 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ae621d6a35a..344bce2a204 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1457,3 +1457,42 @@ View Create View v1 CREATE ALGORITHM=TEMPTABLE VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` from `test`.`t1` drop view v1; drop table t1; +create table t1 (s1 int); +create table t2 (s1 int); +create view v2 as select * from t2 where s1 in (select s1 from t1); +insert into v2 values (5); +insert into t1 values (5); +select * from v2; +s1 +5 +update v2 set s1 = 0; +select * from v2; +s1 +select * from t2; +s1 +0 +alter view v2 as select * from t2 where s1 in (select s1 from t1) with check option; +insert into v2 values (5); +update v2 set s1 = 1; +ERROR HY000: CHECK OPTION failed 'test.v2' +insert into t1 values (1); +update v2 set s1 = 1; +select * from v2; +s1 +1 +select * from t2; +s1 +0 +1 +prepare stmt1 from "select * from v2;"; +execute stmt1; +s1 +1 +insert into t1 values (0); +execute stmt1; +s1 +0 +1 +deallocate prepare stmt1; +drop view v2; +drop table t1, t2; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index ea7578bfa8d..cfad7e34d0d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1421,3 +1421,33 @@ alter algorithm=temptable view v1 as select * from t1; show create view v1; drop view v1; drop table t1; + +# +# updating view with subquery in the WHERE clause +# +create table t1 (s1 int); +create table t2 (s1 int); +create view v2 as select * from t2 where s1 in (select s1 from t1); +insert into v2 values (5); +insert into t1 values (5); +select * from v2; +update v2 set s1 = 0; +select * from v2; +select * from t2; +# check it with check option +alter view v2 as select * from t2 where s1 in (select s1 from t1) with check option; +insert into v2 values (5); +-- error 1369 +update v2 set s1 = 1; +insert into t1 values (1); +update v2 set s1 = 1; +select * from v2; +select * from t2; +# scheck how VIEWs with subqueries work with prepared statements +prepare stmt1 from "select * from v2;"; +execute stmt1; +insert into t1 values (0); +execute stmt1; +deallocate prepare stmt1; +drop view v2; +drop table t1, t2; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 4ef680cea19..4a325c4b224 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -109,6 +109,7 @@ public: engine_changed= 1; return eng == 0; } + enum_parsing_place place() { return parsing_place; } friend class select_subselect; friend class Item_in_optimizer; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 586075b2f69..59dc1a7ee8b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1543,8 +1543,9 @@ void st_select_lex::print_limit(THD *thd, String *str) st_lex::can_be_merged() DESCRIPTION - We can apply merge algorithm if it is single SELECT view (we do not - count SELECTs of underlying views) and we have not grpouping, ordering, + We can apply merge algorithm if it is single SELECT view with + subqueries only in WHERE clause (we do not count SELECTs of underlying + views, and second level subqueries) and we have not grpouping, ordering, HAVING clause, aggregate functions, DISTINCT clause, LIMIT clause and several underlying tables. @@ -1558,14 +1559,23 @@ bool st_lex::can_be_merged() // TODO: do not forget implement case when select_lex.table_list.elements==0 /* find non VIEW subqueries/unions */ - uint selects= 0; - for (SELECT_LEX *sl= all_selects_list; - sl && selects <= 1; - sl= sl->next_select_in_list()) - if (sl->parent_lex == this) - selects++; - - return (selects <= 1 && + bool selects_allow_merge= select_lex.next_select() == 0; + if (selects_allow_merge) + { + for (SELECT_LEX_UNIT *unit= select_lex.first_inner_unit(); + unit; + unit= unit->next_unit()) + { + if (unit->first_select()->parent_lex == this && + (unit->item == 0 || unit->item->place() != IN_WHERE)) + { + selects_allow_merge= 0; + break; + } + } + } + + return (selects_allow_merge && select_lex.order_list.elements == 0 && select_lex.group_list.elements == 0 && select_lex.having == 0 && diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 6bb84bac02f..4cdbfe9728b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -754,6 +754,20 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) table->where= lex->select_lex.where; /* + Add subqueries units to SELECT in which we merging current view. + + NOTE: we do not support UNION here, so we take only one select + */ + for (SELECT_LEX_UNIT *unit= lex->select_lex.first_inner_unit(); + unit; + unit= unit->next_unit()) + { + SELECT_LEX_NODE *save_slave= unit->slave; + unit->include_down(table->select_lex); + unit->slave= save_slave; // fix include_down initialisation + } + + /* This SELECT_LEX will be linked in global SELECT_LEX list to make it processed by mysql_handle_derived(), but it will not be included to SELECT_LEX tree, because it @@ -923,8 +937,12 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) uint i, elements_in_view; DBUG_ENTER("check_key_in_view"); - if (!view->view || - thd->lex->unit.global_parameters->select_limit == HA_POS_ERROR) + /* + we do not support updatable UNIONs in VIW, so we can check just limit of + LEX::select_lex + */ + if (!view->view || thd->lex->sql_command == SQLCOM_INSERT || + thd->lex->select_lex.select_limit == HA_POS_ERROR) DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */ table= view->table; trans= view->field_translation; |