1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Merge MySQL 5.1.41 into MariaDB trunk, including a number of after-merge fixes.

Also merge charset patch.
This commit is contained in:
unknown
2009-11-30 22:37:27 +01:00
570 changed files with 21041 additions and 5483 deletions

View File

@ -583,6 +583,126 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
}
/**
An Internal_error_handler that suppresses errors regarding views'
underlying tables that occur during privilege checking within SHOW CREATE
VIEW commands. This happens in the cases when
- A view's underlying table (e.g. referenced in its SELECT list) does not
exist. There should not be an error as no attempt was made to access it
per se.
- Access is denied for some table, column, function or stored procedure
such as mentioned above. This error gets raised automatically, since we
can't untangle its access checking from that of the view itself.
*/
class Show_create_error_handler : public Internal_error_handler {
TABLE_LIST *m_top_view;
bool m_handling;
Security_context *m_sctx;
char m_view_access_denied_message[MYSQL_ERRMSG_SIZE];
char *m_view_access_denied_message_ptr;
public:
/**
Creates a new Show_create_error_handler for the particular security
context and view.
@thd Thread context, used for security context information if needed.
@top_view The view. We do not verify at this point that top_view is in
fact a view since, alas, these things do not stay constant.
*/
explicit Show_create_error_handler(THD *thd, TABLE_LIST *top_view) :
m_top_view(top_view), m_handling(FALSE),
m_view_access_denied_message_ptr(NULL)
{
m_sctx = test(m_top_view->security_ctx) ?
m_top_view->security_ctx : thd->security_ctx;
}
/**
Lazy instantiation of 'view access denied' message. The purpose of the
Show_create_error_handler is to hide details of underlying tables for
which we have no privileges behind ER_VIEW_INVALID messages. But this
obviously does not apply if we lack privileges on the view itself.
Unfortunately the information about for which table privilege checking
failed is not available at this point. The only way for us to check is by
reconstructing the actual error message and see if it's the same.
*/
char* get_view_access_denied_message()
{
if (!m_view_access_denied_message_ptr)
{
m_view_access_denied_message_ptr= m_view_access_denied_message;
my_snprintf(m_view_access_denied_message, MYSQL_ERRMSG_SIZE,
ER(ER_TABLEACCESS_DENIED_ERROR), "SHOW VIEW",
m_sctx->priv_user,
m_sctx->host_or_ip, m_top_view->get_table_name());
}
return m_view_access_denied_message_ptr;
}
bool handle_error(uint sql_errno, const char *message,
MYSQL_ERROR::enum_warning_level level, THD *thd) {
/*
The handler does not handle the errors raised by itself.
At this point we know if top_view is really a view.
*/
if (m_handling || !m_top_view->view)
return FALSE;
m_handling= TRUE;
bool is_handled;
switch (sql_errno)
{
case ER_TABLEACCESS_DENIED_ERROR:
if (!strcmp(get_view_access_denied_message(), message))
{
/* Access to top view is not granted, don't interfere. */
is_handled= FALSE;
break;
}
case ER_COLUMNACCESS_DENIED_ERROR:
case ER_VIEW_NO_EXPLAIN: /* Error was anonymized, ignore all the same. */
case ER_PROCACCESS_DENIED_ERROR:
is_handled= TRUE;
break;
case ER_NO_SUCH_TABLE:
/* Established behavior: warn if underlying tables are missing. */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_INVALID,
ER(ER_VIEW_INVALID),
m_top_view->get_db_name(),
m_top_view->get_table_name());
is_handled= TRUE;
break;
case ER_SP_DOES_NOT_EXIST:
/* Established behavior: warn if underlying functions are missing. */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_INVALID,
ER(ER_VIEW_INVALID),
m_top_view->get_db_name(),
m_top_view->get_table_name());
is_handled= TRUE;
break;
default:
is_handled= FALSE;
}
m_handling= FALSE;
return is_handled;
}
};
bool
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
@ -596,26 +716,13 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
/* We want to preserve the tree for views. */
thd->lex->view_prepare_mode= TRUE;
/* Only one table for now, but VIEW can involve several tables */
if (open_normal_and_derived_tables(thd, table_list, 0))
{
if (!table_list->view ||
(thd->is_error() && thd->main_da.sql_errno() != ER_VIEW_INVALID))
Show_create_error_handler view_error_suppressor(thd, table_list);
thd->push_internal_handler(&view_error_suppressor);
bool error= open_normal_and_derived_tables(thd, table_list, 0);
thd->pop_internal_handler();
if (error && thd->main_da.is_error())
DBUG_RETURN(TRUE);
/*
Clear all messages with 'error' level status and
issue a warning with 'warning' level status in
case of invalid view and last error is ER_VIEW_INVALID
*/
mysql_reset_errors(thd, true);
thd->clear_error();
push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_VIEW_INVALID,
ER(ER_VIEW_INVALID),
table_list->view_db.str,
table_list->view_name.str);
}
/* TODO: add environment variables show when it become possible */
@ -1773,15 +1880,10 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
thd_info->query=0;
/* Lock THD mutex that protects its data when looking at it. */
pthread_mutex_lock(&tmp->LOCK_thd_data);
if (tmp->query)
if (tmp->query())
{
/*
query_length is always set to 0 when we set query = NULL; see
the comment in sql_class.h why this prevents crashes in possible
races with query_length
*/
uint length= min(max_query_length, tmp->query_length);
thd_info->query=(char*) thd->strmake(tmp->query,length);
uint length= min(max_query_length, tmp->query_length());
thd_info->query= (char*) thd->strmake(tmp->query(),length);
}
pthread_mutex_unlock(&tmp->LOCK_thd_data);
thread_infos.append(thd_info);
@ -1894,7 +1996,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
tmp->mysys_var->current_cond ?
"Waiting on cond" : NullS);
#else
val= (char *) "Writing to net";
val= (char *) (tmp->proc_info ? tmp->proc_info : NullS);
#endif
if (val)
{
@ -1906,11 +2008,11 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond)
pthread_mutex_unlock(&mysys_var->mutex);
/* INFO */
if (tmp->query)
if (tmp->query())
{
table->field[7]->store(tmp->query,
table->field[7]->store(tmp->query(),
min(PROCESS_LIST_INFO_WIDTH,
tmp->query_length), cs);
tmp->query_length()), cs);
table->field[7]->set_notnull();
}