Commit 920d3792 authored by dlenev@mysql.com's avatar dlenev@mysql.com

Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into  mysql.com:/home/dlenev/src/mysql-5.0-bg12739
parents cb034d23 ea0b89ae
......@@ -757,7 +757,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
bool *refresh, uint flags);
TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table);
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table);
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
bool reopen_table(TABLE *table,bool locked);
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
......
......@@ -976,32 +976,57 @@ void wait_for_refresh(THD *thd)
}
TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
/*
Open table which is already name-locked by this thread.
SYNOPSIS
reopen_name_locked_table()
thd Thread handle
table_list TABLE_LIST object for table to be open, TABLE_LIST::table
member should point to TABLE object which was used for
name-locking.
NOTE
This function assumes that its caller already acquired LOCK_open mutex.
RETURN VALUE
FALSE - Success
TRUE - Error
*/
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("reopen_name_locked_table");
if (thd->killed)
DBUG_RETURN(0);
TABLE *table;
TABLE *table= table_list->table;
TABLE_SHARE *share;
if (!(table = table_list->table))
DBUG_RETURN(0);
char *db= table_list->db;
char *table_name= table_list->table_name;
char key[MAX_DBKEY_LENGTH];
uint key_length;
TABLE orig_table;
DBUG_ENTER("reopen_name_locked_table");
char* db = thd->db ? thd->db : table_list->db;
char* table_name = table_list->table_name;
char key[MAX_DBKEY_LENGTH];
uint key_length;
safe_mutex_assert_owner(&LOCK_open);
if (thd->killed || !table)
DBUG_RETURN(TRUE);
orig_table= *table;
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
pthread_mutex_lock(&LOCK_open);
if (open_unireg_entry(thd, table, db, table_name, table_name, 0,
thd->mem_root) ||
!(table->s->table_cache_key= memdup_root(&table->mem_root, (char*) key,
key_length)))
{
delete table->triggers;
closefrm(table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
intern_close_table(table);
/*
If there was an error during opening of table (for example if it
does not exist) '*table' object can be wiped out. To be able
properly release name-lock in this case we should restore this
object to its original state.
*/
*table= orig_table;
DBUG_RETURN(TRUE);
}
share= table->s;
......@@ -1011,7 +1036,6 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
share->flush_version=0;
table->in_use = thd;
check_unused();
pthread_mutex_unlock(&LOCK_open);
table->next = thd->open_tables;
thd->open_tables = table;
table->tablenr=thd->current_tablenr++;
......@@ -1021,7 +1045,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
table->status=STATUS_NO_RECORD;
table->keys_in_use_for_query= share->keys_in_use;
table->used_keys= share->keys_for_keyread;
DBUG_RETURN(table);
DBUG_RETURN(FALSE);
}
......
......@@ -1950,8 +1950,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
{
char* backup_dir= thd->lex->backup_dir;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char* table_name = table->table_name;
char* db = thd->db ? thd->db : table->db;
char* table_name= table->table_name;
char* db= table->db;
if (fn_format_relative_to_data_home(src_path, table_name, backup_dir,
reg_ext))
......@@ -1987,12 +1987,15 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
Now we should be able to open the partially restored table
to finish the restore in the handler later on
*/
if (!(table->table = reopen_name_locked_table(thd, table)))
pthread_mutex_lock(&LOCK_open);
if (reopen_name_locked_table(thd, table))
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed to open partially restored table"));
}
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
......@@ -2089,12 +2092,16 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
Now we should be able to open the partially repaired table
to finish the repair in the handler later on.
*/
if (!(table_list->table = reopen_name_locked_table(thd, table_list)))
pthread_mutex_lock(&LOCK_open);
if (reopen_name_locked_table(thd, table_list))
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
error= send_check_errmsg(thd, table_list, "repair",
"Failed to open partially repaired table");
goto end;
}
pthread_mutex_unlock(&LOCK_open);
end:
if (table == &tmp_table)
......
......@@ -103,8 +103,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig);
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
{
TABLE *table;
bool result= 0;
bool result= TRUE;
DBUG_ENTER("mysql_create_or_drop_trigger");
/*
......@@ -119,9 +118,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
if (!(table= open_ltable(thd, tables, tables->lock_type)))
DBUG_RETURN(TRUE);
/*
TODO: We should check if user has TRIGGER privilege for table here.
Now we just require SUPER privilege for creating/dropping because
......@@ -131,28 +127,24 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
DBUG_RETURN(TRUE);
/*
We do not allow creation of triggers on temporary tables. We also don't
allow creation of triggers on views but fulfilment of this restriction
is guaranteed by open_ltable(). It is better to have this check here
than do it in Table_triggers_list::create_trigger() and mess with table
cache.
There is no DETERMINISTIC clause for triggers, so can't check it.
But a trigger can in theory be used to do nasty things (if it supported
DROP for example) so we do the check for privileges. For now there is
already a stronger test right above; but when this stronger test will
be removed, the test below will hold.
*/
if (table->s->tmp_table != NO_TMP_TABLE)
if (!trust_routine_creators && mysql_bin_log.is_open() &&
!(thd->security_ctx->master_access & SUPER_ACL))
{
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
}
if (!table->triggers)
/* We do not allow creation of triggers on temporary tables. */
if (create && find_temporary_table(thd, tables->db, tables->table_name))
{
if (!create)
{
my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
DBUG_RETURN(TRUE);
}
if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
DBUG_RETURN(TRUE);
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
DBUG_RETURN(TRUE);
}
/*
......@@ -161,31 +153,41 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
again until we are done. (Acquiring LOCK_open is not enough because
global read lock is held without helding LOCK_open).
*/
if (wait_if_global_read_lock(thd, 0, 0))
if (wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(TRUE);
/*
There is no DETERMINISTIC clause for triggers, so can't check it.
But a trigger can in theory be used to do nasty things (if it supported
DROP for example) so we do the check for privileges. For now there is
already a stronger test above (see start of the function); but when this
stronger test will be removed, the test below will hold.
*/
if (!trust_routine_creators && mysql_bin_log.is_open() &&
!(thd->security_ctx->master_access & SUPER_ACL))
VOID(pthread_mutex_lock(&LOCK_open));
if (lock_table_names(thd, tables))
goto end;
/* We also don't allow creation of triggers on views. */
tables->required_type= FRMTYPE_TABLE;
if (reopen_name_locked_table(thd, tables))
{
my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0));
DBUG_RETURN(TRUE);
unlock_table_name(thd, tables);
goto end;
}
table= tables->table;
if (!table->triggers)
{
if (!create)
{
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
goto end;
}
if (!(table->triggers= new (&table->mem_root) Table_triggers_list(table)))
goto end;
}
VOID(pthread_mutex_lock(&LOCK_open));
result= (create ?
table->triggers->create_trigger(thd, tables):
table->triggers->drop_trigger(thd, tables));
/* It is sensible to invalidate table in any case */
close_cached_table(thd, table);
end:
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment