summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
authorunknown <davi@mysql.com/endora.local>2008-02-21 14:58:29 -0300
committerunknown <davi@mysql.com/endora.local>2008-02-21 14:58:29 -0300
commit315665cf67dd4e56922955b051eff2c384f2298e (patch)
tree09d15a0c10b54a7ad010fa850101c4816d4e0d16 /sql/sql_view.cc
parentfa08b280857fde69a70c68bd07797624a52ef262 (diff)
downloadmariadb-git-315665cf67dd4e56922955b051eff2c384f2298e.tar.gz
Bug#32890 Crash after repeated create and drop of tables and views
The problem is that CREATE VIEW statements inside prepared statements weren't being expanded during the prepare phase, which leads to objects not being allocated in the appropriate memory arenas. The solution is to perform the validation of CREATE VIEW statements during the prepare phase of a prepared statement. The validation during the prepare phase assures that transformations of the parsed tree will use the permanent arena of the prepared statement. mysql-test/r/ps.result: Add test case result for Bug#32890 mysql-test/t/ps.test: Add test case for Bug#32890 sql/item.h: Restore original field name if name is auto generated. sql/sql_prepare.cc: Validate and prepare a CREATE VIEW statement for execution. sql/sql_view.cc: Move privileges check to it's own function. sql/sql_view.h: Export function which check privileges of a CREATE VIEW statement.
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc213
1 files changed, 126 insertions, 87 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 48ab5b3af9e..4c8e6e80c41 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -227,104 +227,31 @@ fill_defined_view_parts (THD *thd, TABLE_LIST *view)
return FALSE;
}
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
/**
- @brief Creating/altering VIEW procedure
+ @brief CREATE VIEW privileges pre-check.
@param thd thread handler
+ @param tables tables used in the view
@param views views to create
@param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
- @note This function handles both create and alter view commands.
-
@retval FALSE Operation was a success.
@retval TRUE An error occured.
*/
-bool mysql_create_view(THD *thd, TABLE_LIST *views,
- enum_view_create_mode mode)
+bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
+ enum_view_create_mode mode)
{
LEX *lex= thd->lex;
- bool link_to_local;
/* first table in list is target VIEW name => cut off it */
- TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
- TABLE_LIST *tables= lex->query_tables;
TABLE_LIST *tbl;
SELECT_LEX *select_lex= &lex->select_lex;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
SELECT_LEX *sl;
-#endif
- SELECT_LEX_UNIT *unit= &lex->unit;
- bool res= FALSE;
- DBUG_ENTER("mysql_create_view");
-
- /* This is ensured in the parser. */
- DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
- !lex->param_list.elements && !lex->derived_tables);
-
- if (mode != VIEW_CREATE_NEW)
- {
- if (mode == VIEW_ALTER &&
- fill_defined_view_parts(thd, view))
- {
- res= TRUE;
- goto err;
- }
- sp_cache_invalidate();
- }
+ bool res= TRUE;
+ DBUG_ENTER("create_view_precheck");
- if (!lex->definer)
- {
- /*
- DEFINER-clause is missing; we have to create default definer in
- persistent arena to be PS/SP friendly.
- If this is an ALTER VIEW then the current user should be set as
- the definer.
- */
- Query_arena original_arena;
- Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
-
- if (!(lex->definer= create_default_definer(thd)))
- res= TRUE;
-
- if (ps_arena)
- thd->restore_active_arena(ps_arena, &original_arena);
-
- if (res)
- goto err;
- }
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- /*
- check definer of view:
- - same as current user
- - current user has SUPER_ACL
- */
- if (lex->definer &&
- (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 ||
- my_strcasecmp(system_charset_info,
- lex->definer->host.str,
- thd->security_ctx->priv_host) != 0))
- {
- if (!(thd->security_ctx->master_access & SUPER_ACL))
- {
- my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
- res= TRUE;
- goto err;
- }
- else
- {
- if (!is_acl_user(lex->definer->host.str,
- lex->definer->user.str))
- {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_NO_SUCH_USER,
- ER(ER_NO_SUCH_USER),
- lex->definer->user.str,
- lex->definer->host.str);
- }
- }
- }
/*
Privilege check for view creation:
- user has CREATE VIEW privilege on view table
@@ -346,10 +273,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
(check_access(thd, DROP_ACL, view->db, &view->grant.privilege,
0, 0, is_schema_db(view->db)) ||
grant_option && check_grant(thd, DROP_ACL, view, 0, 1, 0))))
- {
- res= TRUE;
goto err;
- }
+
for (sl= select_lex; sl; sl= sl->next_select())
{
for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
@@ -363,7 +288,6 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
"ANY", thd->security_ctx->priv_user,
thd->security_ctx->priv_host, tbl->table_name);
- res= TRUE;
goto err;
}
/*
@@ -399,10 +323,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
if (check_access(thd, SELECT_ACL, tbl->db,
&tbl->grant.privilege, 0, 0, test(tbl->schema_table)) ||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
- {
- res= TRUE;
goto err;
- }
}
}
}
@@ -426,8 +347,126 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
}
}
}
+
+ res= FALSE;
+
+err:
+ DBUG_RETURN(res || thd->net.report_error);
+}
+
+#else
+
+bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
+ enum_view_create_mode mode)
+{
+ return FALSE;
+}
+
+#endif
+
+
+/**
+ @brief Creating/altering VIEW procedure
+
+ @param thd thread handler
+ @param views views to create
+ @param mode VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
+
+ @note This function handles both create and alter view commands.
+
+ @retval FALSE Operation was a success.
+ @retval TRUE An error occured.
+*/
+
+bool mysql_create_view(THD *thd, TABLE_LIST *views,
+ enum_view_create_mode mode)
+{
+ LEX *lex= thd->lex;
+ bool link_to_local;
+ /* first table in list is target VIEW name => cut off it */
+ TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
+ TABLE_LIST *tables= lex->query_tables;
+ TABLE_LIST *tbl;
+ SELECT_LEX *select_lex= &lex->select_lex;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ SELECT_LEX *sl;
+#endif
+ SELECT_LEX_UNIT *unit= &lex->unit;
+ bool res= FALSE;
+ DBUG_ENTER("mysql_create_view");
+
+ /* This is ensured in the parser. */
+ DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
+ !lex->param_list.elements && !lex->derived_tables);
+
+ if (mode != VIEW_CREATE_NEW)
+ {
+ if (mode == VIEW_ALTER &&
+ fill_defined_view_parts(thd, view))
+ {
+ res= TRUE;
+ goto err;
+ }
+ sp_cache_invalidate();
+ }
+
+ if (!lex->definer)
+ {
+ /*
+ DEFINER-clause is missing; we have to create default definer in
+ persistent arena to be PS/SP friendly.
+ If this is an ALTER VIEW then the current user should be set as
+ the definer.
+ */
+ Query_arena original_arena;
+ Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena);
+
+ if (!(lex->definer= create_default_definer(thd)))
+ res= TRUE;
+
+ if (ps_arena)
+ thd->restore_active_arena(ps_arena, &original_arena);
+
+ if (res)
+ goto err;
+ }
+
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ /*
+ check definer of view:
+ - same as current user
+ - current user has SUPER_ACL
+ */
+ if (lex->definer &&
+ (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 ||
+ my_strcasecmp(system_charset_info,
+ lex->definer->host.str,
+ thd->security_ctx->priv_host) != 0))
+ {
+ if (!(thd->security_ctx->master_access & SUPER_ACL))
+ {
+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
+ res= TRUE;
+ goto err;
+ }
+ else
+ {
+ if (!is_acl_user(lex->definer->host.str,
+ lex->definer->user.str))
+ {
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_NO_SUCH_USER,
+ ER(ER_NO_SUCH_USER),
+ lex->definer->user.str,
+ lex->definer->host.str);
+ }
+ }
+ }
#endif
+ if ((res= create_view_precheck(thd, tables, view, mode)))
+ goto err;
+
if (open_and_lock_tables(thd, tables))
{
res= TRUE;