summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2005-10-28 00:18:23 +0300
committerunknown <bell@sanja.is.com.ua>2005-10-28 00:18:23 +0300
commit9c6c527c769aaff8cee2fef2b4ae6b4babfcd6fe (patch)
tree921242ccda92f66e2ac8bfc607ba0dcb1f172286 /sql/sql_view.cc
parent9a5dd3b41195301967c6ca90d004fdb5e80ec713 (diff)
downloadmariadb-git-9c6c527c769aaff8cee2fef2b4ae6b4babfcd6fe.tar.gz
support of view underlying tables and SP functions security check added (BUG#9505) (WL#2787)
mysql-test/r/information_schema.result: error message changed mysql-test/r/sp.result: error message changed mysql-test/r/sql_mode.result: fixed test suite mysql-test/r/view.result: error message changed mysql-test/r/view_grant.result: test of underlying view tables check mysql-test/t/sql_mode.test: fixed test suite mysql-test/t/view_grant.test: test of underlying view tables check sql/item.cc: check of underlying tables privilege added sql/item.h: Name the resolution context points to the security context of view (if item belong to the view) sql/item_func.cc: a view error hiding for execution of prepared function belonged to a view fixed checking privileges if stored functions belonds to some view sql/mysql_priv.h: refult of derived table processing functions changed to bool Security_context added as an argument to find_field_in_table() sql/share/errmsg.txt: error message fixed sql/sql_acl.cc: Storing requested privileges of tables added View underlying tables privilege check added sql/sql_base.cc: View underlying tables privilege check added sql/sql_cache.cc: Code cleunup: we should not register underlying tables of view second time sql/sql_delete.cc: ancestor -> merge_underlying_list renaming sql/sql_derived.cc: refult of derived table processing functions changed to bool do not give SELECT_ACL for TEMPTABLE views sql/sql_lex.h: The comment added sql/sql_parse.cc: registration of requested privileges added sql/sql_prepare.cc: registration of requested privileges added sql/sql_update.cc: manipulation of requested privileges for underlying tables made the same as for table which we are updating sql/sql_view.cc: underlying tables of view security check support added sql/table.cc: renaming and fixing view preparation methods, methods for checking underlyoing tables security context added sql/table.h: storege for reuested privileges added
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc115
1 files changed, 90 insertions, 25 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 5db08275735..3844520c4f8 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -721,6 +721,7 @@ loop_out:
}
+
/*
read VIEW .frm and create structures
@@ -737,11 +738,26 @@ loop_out:
my_bool
mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
+ THD *thd= current_thd;
DBUG_ENTER("mysql_make_view");
DBUG_PRINT("info", ("table=%p (%s)", table, table->table_name));
if (table->view)
{
+ /*
+ It's an execution of a PS/SP and the view has already been unfolded
+ into a list of used tables. Now we only need to update the information
+ about granted privileges in the view tables with the actual data
+ stored in MySQL privilege system. We don't need to restore the
+ required privileges (by calling register_want_access) because they has
+ not changed since PREPARE or the previous execution: the only case
+ when this information is changed is execution of UPDATE on a view, but
+ the original want_access is restored in its end.
+ */
+ if (!table->prelocking_placeholder && table->prepare_security(thd))
+ {
+ DBUG_RETURN(1);
+ }
DBUG_PRINT("info",
("VIEW %s.%s is already processed on previous PS/SP execution",
table->view_db.str, table->view_name.str));
@@ -749,7 +765,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
SELECT_LEX *end;
- THD *thd= current_thd;
LEX *old_lex= thd->lex, *lex;
SELECT_LEX *view_select;
int res= 0;
@@ -768,7 +783,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (!table->timestamp.str)
table->timestamp.str= table->timestamp_buffer;
/* prepare default values for old format */
- table->view_suid= 1;
+ table->view_suid= TRUE;
table->definer.user.str= table->definer.host.str= 0;
table->definer.user.length= table->definer.host.length= 0;
@@ -879,6 +894,10 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
goto err;
}
+
+ if (!(table->view_tables=
+ (List<TABLE_LIST>*) new(thd->mem_root) List<TABLE_LIST>))
+ goto err;
/*
mark to avoid temporary table using and put view reference and find
last view table
@@ -889,6 +908,22 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
{
tbl->skip_temporary= 1;
tbl->belong_to_view= top_view;
+ tbl->referencing_view= table;
+ /*
+ First we fill want_privilege with SELECT_ACL (this is needed for the
+ tables which belongs to view subqueries and temporary table views,
+ then for the merged view underlying tables we will set wanted
+ privileges of top_view
+ */
+ tbl->grant.want_privilege= SELECT_ACL;
+ /*
+ After unfolding the view we lose the list of tables referenced in it
+ (we will have only a list of underlying tables in case of MERGE
+ algorithm, which does not include the tables referenced from
+ subqueries used in view definition).
+ Let's build a list of all tables referenced in the view.
+ */
+ table->view_tables->push_back(tbl);
}
/*
@@ -914,16 +949,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
/*
- 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.
- */
- if (!lex->select_lex.next_select())
- for (tbl= lex->select_lex.get_table_list(); 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
further processing.
@@ -931,7 +956,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (table->prelocking_placeholder)
goto ok2;
- old_lex->derived_tables|= DERIVED_VIEW;
+ old_lex->derived_tables|= (DERIVED_VIEW | lex->derived_tables);
/* move SQL_NO_CACHE & Co to whole query */
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
@@ -940,6 +965,37 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (view_select->options & OPTION_TO_QUERY_CACHE)
old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ if (table->view_suid)
+ {
+ /*
+ Prepare a security context to check underlying objects of the view
+ */
+ Security_context *save_security_ctx= thd->security_ctx;
+ if (!(table->view_sctx= (Security_context *)
+ thd->stmt_arena->alloc(sizeof(Security_context))))
+ goto err;
+ /* Assign the context to the tables referenced in the view */
+ for (tbl= view_tables; tbl; tbl= tbl->next_global)
+ tbl->security_ctx= table->view_sctx;
+ /* assign security context to SELECT name resolution contexts of view */
+ for(SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ sl->context.security_ctx= table->view_sctx;
+ }
+
+ /*
+ Setup an error processor to hide error messages issued by stored
+ routines referenced in the view
+ */
+ for (SELECT_LEX *sl= lex->all_selects_list;
+ sl;
+ sl= sl->next_select_in_list())
+ {
+ sl->context.error_processor= &view_error_processor;
+ sl->context.error_processor_data= (void *)table;
+ }
+
/*
check MERGE algorithm ability
- algorithm is not explicit TEMPORARY TABLE
@@ -961,24 +1017,28 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
table->updatable= (table->updatable_view != 0);
table->effective_with_check=
old_lex->get_effective_with_check(table);
+ table->merge_underlying_list= view_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;
+ tbl->grant.want_privilege= top_view->grant.orig_want_privilege;
+ }
/* prepare view context */
- lex->select_lex.context.resolve_in_table_list_only(table->ancestor=
- view_tables);
+ lex->select_lex.context.resolve_in_table_list_only(view_tables);
lex->select_lex.context.outer_context= 0;
lex->select_lex.context.select_lex= table->select_lex;
lex->select_lex.select_n_having_items+=
table->select_lex->select_n_having_items;
- /* do not check privileges & hide errors for view underlyings */
- for (SELECT_LEX *sl= lex->all_selects_list;
- sl;
- sl= sl->next_select_in_list())
- {
- sl->context.check_privileges= FALSE;
- sl->context.error_processor= &view_error_processor;
- sl->context.error_processor_data= (void *)table;
- }
/*
Tables of the main select of the view should be marked as belonging
to the same select as original view (again we can use LEX::select_lex
@@ -1011,7 +1071,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
}
- /* Store WHERE clause for post-processing in setup_ancestor */
+ /* Store WHERE clause for post-processing in setup_underlying */
table->where= view_select->where;
/*
Add subqueries units to SELECT into which we merging current view.
@@ -1077,6 +1137,11 @@ ok2:
if (!old_lex->time_zone_tables_used && thd->lex->time_zone_tables_used)
old_lex->time_zone_tables_used= thd->lex->time_zone_tables_used;
thd->lex= old_lex;
+ if (!table->prelocking_placeholder && table->prepare_security(thd))
+ {
+ DBUG_RETURN(1);
+ }
+
DBUG_RETURN(0);
err: