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

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

into  vajra.(none):/opt/local/work/mysql-5.1-runtime


mysql-test/include/mix1.inc:
  Auto merged
mysql-test/r/innodb_mysql.result:
  Auto merged
mysql-test/r/ps_1general.result:
  Auto merged
mysql-test/t/disabled.def:
  Auto merged
mysql-test/t/ps_1general.test:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/ha_ndbcluster_binlog.cc:
  Auto merged
sql/item.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_cache.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_partition.cc:
  Auto merged
sql/sql_prepare.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/table.h:
  Auto merged
sql/sql_insert.cc:
  SCCS merged
This commit is contained in:
unknown
2007-05-15 17:54:11 +04:00
47 changed files with 2635 additions and 699 deletions

View File

@ -3193,7 +3193,7 @@ static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info)
Create a table
SYNOPSIS
mysql_create_table_internal()
mysql_create_table_no_lock()
thd Thread object
db Database
table_name Table name
@ -3210,6 +3210,11 @@ static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info)
DESCRIPTION
If one creates a temporary table, this is automatically opened
Note that this function assumes that caller already have taken
name-lock on table being created or used some other way to ensure
that concurrent operations won't intervene. mysql_create_table()
is a wrapper that can be used for this.
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
@ -3220,7 +3225,7 @@ static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info)
TRUE error
*/
bool mysql_create_table_internal(THD *thd,
bool mysql_create_table_no_lock(THD *thd,
const char *db, const char *table_name,
HA_CREATE_INFO *lex_create_info,
List<create_field> &fields,
@ -3236,7 +3241,7 @@ bool mysql_create_table_internal(THD *thd,
HA_CREATE_INFO *create_info;
handler *file;
bool error= TRUE;
DBUG_ENTER("mysql_create_table_internal");
DBUG_ENTER("mysql_create_table_no_lock");
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
db, table_name, internal_tmp_table));
@ -3588,7 +3593,7 @@ warn:
/*
Database locking aware wrapper for mysql_create_table_internal(),
Database and name-locking aware wrapper for mysql_create_table_no_lock(),
*/
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
@ -3598,6 +3603,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
uint select_field_count,
bool use_copy_create_info)
{
TABLE *name_lock= 0;
bool result;
DBUG_ENTER("mysql_create_table");
@ -3618,11 +3624,44 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name,
creating_table++;
pthread_mutex_unlock(&LOCK_lock_db);
result= mysql_create_table_internal(thd, db, table_name, create_info,
fields, keys, internal_tmp_table,
select_field_count,
use_copy_create_info);
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
{
result= TRUE;
goto unlock;
}
if (!name_lock)
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
table_name);
create_info->table_existed= 1;
result= FALSE;
}
else
{
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
result= TRUE;
}
goto unlock;
}
}
result= mysql_create_table_no_lock(thd, db, table_name, create_info,
fields, keys, internal_tmp_table,
select_field_count,
use_copy_create_info);
unlock:
if (name_lock)
{
pthread_mutex_lock(&LOCK_open);
unlink_open_table(thd, name_lock, FALSE);
pthread_mutex_unlock(&LOCK_open);
}
pthread_mutex_lock(&LOCK_lock_db);
if (!--creating_table && creating_database)
pthread_cond_signal(&COND_refresh);
@ -3825,7 +3864,7 @@ void close_cached_table(THD *thd, TABLE *table)
thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
unlink_open_table(thd, table, TRUE);
/* When lock on LOCK_open is freed other threads can continue */
broadcast_refresh();
@ -3901,7 +3940,7 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
to finish the restore in the handler later on
*/
pthread_mutex_lock(&LOCK_open);
if (reopen_name_locked_table(thd, table))
if (reopen_name_locked_table(thd, table, TRUE))
{
unlock_table_name(thd, table);
pthread_mutex_unlock(&LOCK_open);
@ -4033,7 +4072,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
to finish the repair in the handler later on.
*/
pthread_mutex_lock(&LOCK_open);
if (reopen_name_locked_table(thd, table_list))
if (reopen_name_locked_table(thd, table_list, TRUE))
{
unlock_table_name(thd, table_list);
pthread_mutex_unlock(&LOCK_open);
@ -4639,7 +4678,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
HA_CREATE_INFO *lex_create_info,
Table_ident *table_ident)
{
TABLE *tmp_table;
TABLE *tmp_table, *name_lock= 0;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
char src_table_name_buff[FN_REFLEN], src_db_name_buff[FN_REFLEN];
uint dst_path_length;
@ -4648,14 +4687,14 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
char *src_db;
char *src_table= table_ident->table.str;
int err;
bool res= TRUE, unlock_dst_table= FALSE;
bool res= TRUE;
enum legacy_db_type not_used;
HA_CREATE_INFO *create_info;
#ifdef WITH_PARTITION_STORAGE_ENGINE
char tmp_path[FN_REFLEN];
#endif
char ts_name[FN_LEN];
TABLE_LIST src_tables_list, dst_tables_list;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
if (!(create_info= copy_create_info(lex_create_info)))
@ -4763,6 +4802,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
}
else
{
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
goto err;
if (!name_lock)
goto table_exists;
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
db, table_name, reg_ext, 0);
if (!access(dst_path, F_OK))
@ -4850,28 +4893,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
char buf[2048];
String query(buf, sizeof(buf), system_charset_info);
query.length(0); // Have to zero it since constructor doesn't
uint counter;
/*
Here we open the destination table. This is needed for
store_create_info() to work. The table will be closed
by close_thread_tables() at the end of the statement.
Here we open the destination table, on which we already have
name-lock. This is needed for store_create_info() to work.
The table will be closed by unlink_open_table() at the end
of this function.
*/
if (open_tables(thd, &table, &counter, 0))
table->table= name_lock;
VOID(pthread_mutex_lock(&LOCK_open));
if (reopen_name_locked_table(thd, table, FALSE))
{
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
bzero((gptr)&dst_tables_list, sizeof(dst_tables_list));
dst_tables_list.db= table->db;
dst_tables_list.table_name= table->table_name;
/*
lock destination table name, to make sure that nobody
can drop/alter the table while we execute store_create_info()
*/
if (lock_and_wait_for_table_name(thd, &dst_tables_list))
goto err;
else
unlock_dst_table= TRUE;
}
VOID(pthread_mutex_unlock(&LOCK_open));
IF_DBUG(int result=) store_create_info(thd, table, &query,
create_info);
@ -4906,10 +4942,10 @@ table_exists:
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
err:
if (unlock_dst_table)
if (name_lock)
{
pthread_mutex_lock(&LOCK_open);
unlock_table_name(thd, &dst_tables_list);
unlink_open_table(thd, name_lock, FALSE);
pthread_mutex_unlock(&LOCK_open);
}
DBUG_RETURN(res);
@ -5356,7 +5392,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
uint order_num, ORDER *order, bool ignore,
ALTER_INFO *alter_info, bool do_send_ok)
{
TABLE *table,*new_table=0;
TABLE *table, *new_table= 0, *name_lock= 0;
int error= 0;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
@ -5493,6 +5529,18 @@ view_err:
DBUG_RETURN(TRUE);
table->use_all_columns();
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
List<create_field> create_list; // Add new fields here
List<Key> key_list; // Add new keys here
List_iterator<create_field> find_it(create_list);
List_iterator<Key> key_it(keys);
List_iterator<create_field> field_it(create_list);
List<key_part_spec> key_parts;
KEY *key_info=table->key_info;
/* Check that we are not trying to rename to an existing table */
if (new_name)
{
@ -5529,13 +5577,21 @@ view_err:
}
else
{
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
DBUG_RETURN(TRUE);
if (!name_lock)
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(TRUE);
}
build_table_filename(new_name_buff, sizeof(new_name_buff),
new_db, new_name_buff, reg_ext, 0);
if (!access(new_name_buff, F_OK))
{
/* Table will be closed in do_command() */
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(TRUE);
goto err;
}
}
}
@ -5570,12 +5626,10 @@ view_err:
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (prep_alter_part_table(thd, table, alter_info, create_info, old_db_type,
&partition_changed, &fast_alter_partition))
{
DBUG_RETURN(TRUE);
}
goto err;
#endif
if (check_engine(thd, new_name, create_info))
DBUG_RETURN(TRUE);
goto err;
new_db_type= create_info->db_type;
if (create_info->row_type == ROW_TYPE_NOT_USED)
create_info->row_type= table->s->row_type;
@ -5588,7 +5642,7 @@ view_err:
{
DBUG_PRINT("info", ("doesn't support alter"));
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
DBUG_RETURN(TRUE);
goto err;
}
thd->proc_info="setup";
@ -5647,7 +5701,19 @@ view_err:
if (!error && (new_name != table_name || new_db != db))
{
thd->proc_info="rename";
/* Then do a 'simple' rename of the table */
/*
Then do a 'simple' rename of the table. First we need to close all
instances of 'source' table.
*/
close_cached_table(thd, table);
/*
Then, we want check once again that target table does not exist.
Actually the order of these two steps does not matter since
earlier we took name-lock on the target table, so we do them
in this particular order only to be consistent with 5.0, in which
we don't take this name-lock and where this order really matters.
TODO: Investigate if we need this access() check at all.
*/
if (!access(new_name_buff,F_OK))
{
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
@ -5656,8 +5722,6 @@ view_err:
else
{
*fn_ext(new_name)=0;
table->s->version= 0; // Force removal of table def
close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
error= -1;
else if (Table_triggers_list::change_table_name(thd, db, table_name,
@ -5689,6 +5753,8 @@ view_err:
table->file->print_error(error, MYF(0));
error= -1;
}
if (name_lock)
unlink_open_table(thd, name_lock, FALSE);
VOID(pthread_mutex_unlock(&LOCK_open));
table_list->table= NULL; // For query cache
query_cache_invalidate3(thd, table_list, 0);
@ -5725,11 +5791,6 @@ view_err:
create_info->tablespace= tablespace;
}
restore_record(table, s->default_values); // Empty record for DEFAULT
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<create_field> def_it(fields);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
List<create_field> create_list; // Add new fields here
List<Key> key_list; // Add new keys here
create_field *def;
/*
@ -5800,7 +5861,7 @@ view_err:
if (def->sql_type == MYSQL_TYPE_BLOB)
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
DBUG_RETURN(TRUE);
goto err;
}
if ((def->def=alter->def)) // Use new default
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
@ -5811,13 +5872,12 @@ view_err:
}
}
def_it.rewind();
List_iterator<create_field> find_it(create_list);
while ((def=def_it++)) // Add new columns
{
if (def->change && ! def->field)
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name);
DBUG_RETURN(TRUE);
goto err;
}
if (!def->after)
create_list.push_back(def);
@ -5835,7 +5895,7 @@ view_err:
if (!find)
{
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name);
DBUG_RETURN(TRUE);
goto err;
}
find_it.after(def); // Put element after this
}
@ -5844,13 +5904,13 @@ view_err:
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
alter_info->alter_list.head()->name, table_name);
DBUG_RETURN(TRUE);
goto err;
}
if (!create_list.elements)
{
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
MYF(0));
DBUG_RETURN(TRUE);
goto err;
}
/*
@ -5858,11 +5918,6 @@ view_err:
for which some fields exists.
*/
List_iterator<Key> key_it(keys);
List_iterator<create_field> field_it(create_list);
List<key_part_spec> key_parts;
KEY *key_info=table->key_info;
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
{
char *key_name= key_info->name;
@ -5966,7 +6021,7 @@ view_err:
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
DBUG_RETURN(TRUE);
goto err;
}
}
}
@ -6208,6 +6263,7 @@ view_err:
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (fast_alter_partition)
{
DBUG_ASSERT(!name_lock);
DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info,
create_info, table_list,
&create_list, &key_list,
@ -6268,11 +6324,12 @@ view_err:
We don't log the statement, it will be logged later.
*/
tmp_disable_binlog(thd);
error= mysql_create_table(thd, new_db, tmp_name,
create_info,create_list,key_list,1,0,0);
error= mysql_create_table_no_lock(thd, new_db, tmp_name,
create_info, create_list,
key_list, 1, 0, 0);
reenable_binlog(thd);
if (error)
DBUG_RETURN(error);
goto err;
/* Open the table if we need to copy the data. */
if (need_copy_table)
@ -6533,17 +6590,6 @@ view_err:
current_pid, thd->thread_id);
if (lower_case_table_names)
my_casedn_str(files_charset_info, old_name);
if (new_name != table_name || new_db != db)
{
if (!access(new_name_buff,F_OK))
{
error=1;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
}
#if !defined( __WIN__)
if (table->file->has_transactions())
@ -6553,7 +6599,6 @@ view_err:
Win32 and InnoDB can't drop a table that is in use, so we must
close the original table before doing the rename
*/
table->s->version= 0; // Force removal of table def
close_cached_table(thd, table);
table=0; // Marker that table is closed
no_table_reopen= TRUE;
@ -6563,6 +6608,21 @@ view_err:
table->file->extra(HA_EXTRA_FORCE_REOPEN); // Don't use this file anymore
#endif
if (new_name != table_name || new_db != db)
{
/*
Check that there is no table with target name. See the
comment describing code for 'simple' ALTER TABLE ... RENAME.
*/
if (!access(new_name_buff,F_OK))
{
error=1;
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
}
error=0;
save_old_db_type= old_db_type;
@ -6613,7 +6673,6 @@ view_err:
*/
if (table)
{
table->s->version= 0; // Force removal of table def
close_cached_table(thd,table);
}
VOID(pthread_mutex_unlock(&LOCK_open));
@ -6621,6 +6680,7 @@ view_err:
}
if (! need_copy_table)
{
bool needs_unlink= FALSE;
if (! table)
{
if (new_name != table_name || new_db != db)
@ -6631,11 +6691,41 @@ view_err:
table_list->db= new_db;
table_list->db_length= strlen(new_db);
}
VOID(pthread_mutex_unlock(&LOCK_open));
if (! (table= open_ltable(thd, table_list, TL_WRITE_ALLOW_READ)))
else
{
/*
TODO: Creation of name-lock placeholder here is a temporary
work-around. Long term we should change close_cached_table() call
which we invoke before table renaming operation in such way that
it will leave placeholders for table in table cache/THD::open_tables
list. By doing this we will be able easily reopen and relock these
tables later and therefore behave under LOCK TABLES in the same way
on all platforms.
*/
char key[MAX_DBKEY_LENGTH];
uint key_length;
key_length= create_table_def_key(thd, key, table_list, 0);
if (!(name_lock= table_cache_insert_placeholder(thd, key,
key_length)))
{
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
name_lock->next= thd->open_tables;
thd->open_tables= name_lock;
}
table_list->table= name_lock;
if (reopen_name_locked_table(thd, table_list, FALSE))
{
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
VOID(pthread_mutex_lock(&LOCK_open));
}
table= table_list->table;
/*
We can't rely on later close_cached_table() calls to close
this instance of the table since it was not properly locked.
*/
needs_unlink= TRUE;
}
/* Tell the handler that a new frm file is in place. */
if (table->file->create_handler_files(path, NULL, CHF_INDEX_FLAG,
@ -6644,6 +6734,11 @@ view_err:
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
if (needs_unlink)
{
unlink_open_table(thd, table, FALSE);
table= name_lock= 0;
}
}
if (thd->lock || new_name != table_name || no_table_reopen) // True if WIN32
@ -6654,7 +6749,6 @@ view_err:
*/
if (table)
{
table->s->version= 0; // Force removal of table def
close_cached_table(thd,table);
}
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
@ -6680,7 +6774,6 @@ view_err:
{ // This shouldn't happen
if (table)
{
table->s->version= 0; // Force removal of table def
close_cached_table(thd,table); // Remove lock for table
}
VOID(pthread_mutex_unlock(&LOCK_open));
@ -6737,6 +6830,13 @@ view_err:
table_list->table=0; // For query cache
query_cache_invalidate3(thd, table_list, 0);
if (name_lock)
{
pthread_mutex_lock(&LOCK_open);
unlink_open_table(thd, name_lock, FALSE);
pthread_mutex_unlock(&LOCK_open);
}
end_temporary:
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted), (ulong) deleted,
@ -6756,6 +6856,12 @@ err1:
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
err:
if (name_lock)
{
pthread_mutex_lock(&LOCK_open);
unlink_open_table(thd, name_lock, FALSE);
pthread_mutex_unlock(&LOCK_open);
}
DBUG_RETURN(TRUE);
}
/* mysql_alter_table */