summaryrefslogtreecommitdiff
path: root/sql/sql_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_view.cc')
-rw-r--r--sql/sql_view.cc79
1 files changed, 51 insertions, 28 deletions
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 622f7b99d33..453cbbc091e 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -224,6 +224,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
{
LEX *lex= thd->lex;
bool link_to_local;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ bool definer_check_is_needed= mode != VIEW_ALTER || lex->definer;
+#endif
/* 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;
@@ -256,8 +259,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
/*
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);
@@ -277,11 +281,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
- same as current user
- current user has SUPER_ACL
*/
- if (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 (definer_check_is_needed &&
+ (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))
{
@@ -492,35 +496,46 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
/*
Compare/check grants on view with grants of underlying tables
*/
+
+ fill_effective_table_privileges(thd, &view->grant, view->db,
+ view->table_name);
+
+ {
+ Item *report_item= NULL;
+ uint final_priv= VIEW_ANY_ACL;
+
for (sl= select_lex; sl; sl= sl->next_select())
{
DBUG_ASSERT(view->db); /* Must be set in the parser */
List_iterator_fast<Item> it(sl->item_list);
Item *item;
- fill_effective_table_privileges(thd, &view->grant, view->db,
- view->table_name);
while ((item= it++))
{
- Item_field *fld;
+ Item_field *fld= item->filed_for_view_update();
uint priv= (get_column_grant(thd, &view->grant, view->db,
view->table_name, item->name) &
VIEW_ANY_ACL);
- if ((fld= item->filed_for_view_update()))
+
+ if (fld && !fld->field->table->s->tmp_table)
{
- /*
- Do we have more privileges on view field then underlying table field?
- */
- if (!fld->field->table->s->tmp_table && (~fld->have_privileges & priv))
+ final_priv&= fld->have_privileges;
+
+ if (~fld->have_privileges & priv)
+ report_item= item;
+ }
+ }
+ }
+
+ if (!final_priv)
{
- /* VIEW column has more privileges */
+ DBUG_ASSERT(report_item);
+
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
"create view", thd->security_ctx->priv_user,
- thd->security_ctx->priv_host, item->name,
+ thd->security_ctx->priv_host, report_item->name,
view->table_name);
res= TRUE;
goto err;
- }
- }
}
}
#endif
@@ -675,7 +690,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
char md5[MD5_BUFF_LENGTH];
bool can_be_merged;
char dir_buff[FN_REFLEN], path_buff[FN_REFLEN];
- const uchar *endp;
+ const char *endp;
LEX_STRING dir, file, path;
DBUG_ENTER("mysql_register_view");
@@ -759,9 +774,9 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view->query.str= (char*)str.ptr();
view->query.length= str.length()-1; // we do not need last \0
view->source.str= thd->query + thd->lex->create_view_select_start;
- endp= (uchar*) view->source.str;
- endp= skip_rear_comments(endp, (uchar*) (thd->query + thd->query_length));
- view->source.length= endp - (uchar*) view->source.str;
+ endp= view->source.str;
+ endp= skip_rear_comments(endp, thd->query + thd->query_length);
+ view->source.length= endp - view->source.str;
view->file_version= 1;
view->calc_md5(md5);
view->md5.str= md5;
@@ -970,7 +985,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
now Lex placed in statement memory
*/
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
- lex_start(thd, (uchar*)table->query.str, table->query.length);
+ lex_start(thd, table->query.str, table->query.length);
view_select= &lex->select_lex;
view_select->select_number= ++thd->select_number;
{
@@ -1004,6 +1019,11 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
CHARSET_INFO *save_cs= thd->variables.character_set_client;
thd->variables.character_set_client= system_charset_info;
res= MYSQLparse((void *)thd);
+
+ if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
+ (old_lex->sql_command == SQLCOM_SHOW_CREATE))
+ lex->sql_command= old_lex->sql_command;
+
thd->variables.character_set_client= save_cs;
thd->variables.sql_mode= save_mode;
}
@@ -1029,7 +1049,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
}
}
else if (!table->prelocking_placeholder &&
- old_lex->sql_command == SQLCOM_SHOW_CREATE &&
+ (old_lex->sql_command == SQLCOM_SHOW_CREATE) &&
!table->belong_to_view)
{
if (check_table_access(thd, SHOW_VIEW_ACL, table, 0))
@@ -1266,13 +1286,18 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
unit->slave= save_slave; // fix include_down initialisation
}
+ /*
+ We can safely ignore the VIEW's ORDER BY if we merge into union
+ branch, as order is not important there.
+ */
+ if (!table->select_lex->master_unit()->is_union())
+ table->select_lex->order_list.push_back(&lex->select_lex.order_list);
/*
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
will not be executed
- */
- table->select_lex->order_list.push_back(&lex->select_lex.order_list);
+ */
goto ok;
}
@@ -1302,8 +1327,6 @@ ok:
(st_select_lex_node**)&old_lex->all_selects_list;
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;
DBUG_ASSERT(lex == thd->lex);
thd->lex= old_lex; // Needed for prepare_security
result= !table->prelocking_placeholder && table->prepare_security(thd);