summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <kroki/tomash@moonlight.intranet>2006-08-29 14:32:59 +0400
committerunknown <kroki/tomash@moonlight.intranet>2006-08-29 14:32:59 +0400
commit7a5a2544bf1e1b1abb910968340ad4b9d6162065 (patch)
tree08149ed0035aec059071efbf2dfc47ffb90e0393
parent3c8150b79bf5302879897e0d1ebd594798bb419e (diff)
downloadmariadb-git-7a5a2544bf1e1b1abb910968340ad4b9d6162065.tar.gz
BUG#17591: Updatable view not possible with trigger or stored function
When a view was used inside a trigger or a function, lock type for tables used in a view was always set to READ (thus making the view non-updatable), even if we were trying to update the view. The solution is to set lock type properly. mysql-test/r/view.result: Add result for bug#17591: Updatable view not possible with trigger or stored function. mysql-test/t/view.test: Add test case for bug#17591: Updatable view not possible with trigger or stored function. sql/sql_view.cc: Move the code that sets requested lock type before the point where we exit from mysql_make_view() when we process a placeholder for prelocked table.
-rw-r--r--mysql-test/r/view.result28
-rw-r--r--mysql-test/t/view.test49
-rw-r--r--sql/sql_view.cc52
3 files changed, 105 insertions, 24 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 534065a33b6..d506eb69048 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -2849,4 +2849,30 @@ SHOW TABLES;
Tables_in_test
t1
DROP TABLE t1;
-DROP VIEW IF EXISTS v1;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP VIEW IF EXISTS v1, v2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (i INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+INSERT INTO v1 VALUES (0);
+RETURN 0;
+END |
+SELECT f1();
+f1()
+0
+CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1;
+CREATE FUNCTION f2() RETURNS INT
+BEGIN
+INSERT INTO v2 VALUES (0);
+RETURN 0;
+END |
+SELECT f2();
+ERROR HY000: The target table v2 of the INSERT is not updatable
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP VIEW v1, v2;
+DROP TABLE t1;
+End of 5.0 tests.
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 5cb85ca6c9b..9360ccc1521 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -2715,6 +2715,53 @@ DROP VIEW t1,v1;
SHOW TABLES;
DROP TABLE t1;
+
+
+#
+# BUG#17591: Updatable view not possible with trigger or stored
+# function
+#
+# During prelocking phase we didn't update lock type of view tables,
+# hence READ lock was always requested.
+#
--disable_warnings
-DROP VIEW IF EXISTS v1;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP VIEW IF EXISTS v1, v2;
+DROP TABLE IF EXISTS t1;
--enable_warnings
+
+CREATE TABLE t1 (i INT);
+
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS INT
+BEGIN
+ INSERT INTO v1 VALUES (0);
+ RETURN 0;
+END |
+delimiter ;|
+
+SELECT f1();
+
+CREATE ALGORITHM=TEMPTABLE VIEW v2 AS SELECT * FROM t1;
+
+delimiter |;
+CREATE FUNCTION f2() RETURNS INT
+BEGIN
+ INSERT INTO v2 VALUES (0);
+ RETURN 0;
+END |
+delimiter ;|
+
+--error ER_NON_UPDATABLE_TABLE
+SELECT f2();
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP VIEW v1, v2;
+DROP TABLE t1;
+
+
+--echo End of 5.0 tests.
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 637d2cc3684..361e86fb048 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1052,6 +1052,31 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
table->next_global= view_tables;
}
+ bool view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
+ lex->can_be_merged());
+ TABLE_LIST *view_main_select_tables;
+ if (view_is_mergeable)
+ {
+ /*
+ Currently 'view_main_select_tables' differs from 'view_tables'
+ only then view has CONVERT_TZ() function in its select list.
+ This may change in future, for example if we enable merging of
+ views with subqueries in select list.
+ */
+ view_main_select_tables=
+ (TABLE_LIST*)lex->select_lex.table_list.first;
+
+ /*
+ Let us set proper lock type for tables of the view's main
+ select since we may want to perform update or insert on
+ view. This won't work for view containing union. But this is
+ ok since we don't allow insert and update on such views
+ anyway.
+ */
+ for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
+ tbl->lock_type= table->lock_type;
+ }
+
/*
If we are opening this view as part of implicit LOCK TABLES, then
this view serves as simple placeholder and we should not continue
@@ -1106,43 +1131,26 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
- VIEW SELECT allow merging
- VIEW used in subquery or command support MERGE algorithm
*/
- if (table->algorithm != VIEW_ALGORITHM_TMPTABLE &&
- lex->can_be_merged() &&
+ if (view_is_mergeable &&
(table->select_lex->master_unit() != &old_lex->unit ||
old_lex->can_use_merged()) &&
!old_lex->can_not_use_merged())
{
- List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
- /*
- Currently 'view_main_select_tables' differs from 'view_tables'
- only then view has CONVERT_TZ() function in its select list.
- This may change in future, for example if we enable merging
- of views with subqueries in select list.
- */
- TABLE_LIST *view_main_select_tables=
- (TABLE_LIST*)lex->select_lex.table_list.first;
/* lex should contain at least one table */
DBUG_ASSERT(view_main_select_tables != 0);
+ List_iterator_fast<TABLE_LIST> ti(view_select->top_join_list);
+
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
DBUG_PRINT("info", ("algorithm: MERGE"));
table->updatable= (table->updatable_view != 0);
table->effective_with_check=
old_lex->get_effective_with_check(table);
table->merge_underlying_list= view_main_select_tables;
- /*
- Let us set proper lock type for tables of the view's main select
- since we may want to perform update or insert on view. This won't
- work for view containing union. But this is ok since we don't
- allow insert and update on such views anyway.
- Also we fill correct wanted privileges.
- */
- for (tbl= table->merge_underlying_list; tbl; tbl= tbl->next_local)
- {
- tbl->lock_type= table->lock_type;
+ /* Fill correct wanted privileges. */
+ for (tbl= view_main_select_tables; tbl; tbl= tbl->next_local)
tbl->grant.want_privilege= top_view->grant.orig_want_privilege;
- }
/* prepare view context */
lex->select_lex.context.resolve_in_table_list_only(view_main_select_tables);