Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-05-11 21:55:55+04:00, dlenev@stripped +4 -0
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into mockturtle.local:/home/dlenev/src/mysql-5.0-cts-3
MERGE: 1.2471.1.1
sql/mysql_priv.h@stripped, 2007-05-11 21:55:50+04:00, dlenev@stripped +0 -0
Auto merged
MERGE: 1.448.1.1
sql/sql_insert.cc@stripped, 2007-05-11 21:55:50+04:00, dlenev@stripped +0 -0
Auto merged
MERGE: 1.230.1.1
sql/sql_prepare.cc@stripped, 2007-05-11 21:55:50+04:00, dlenev@stripped +0 -0
Auto merged
MERGE: 1.199.1.1
sql/sql_yacc.yy@stripped, 2007-05-11 21:55:51+04:00, dlenev@stripped +0 -0
Auto merged
MERGE: 1.516.1.1
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: dlenev
# Host: mockturtle.local
# Root: /home/dlenev/src/mysql-5.0-cts-3/RESYNC
--- 1.449/sql/mysql_priv.h 2007-05-11 21:56:02 +04:00
+++ 1.450/sql/mysql_priv.h 2007-05-11 21:56:02 +04:00
@@ -676,6 +676,8 @@ struct Query_cache_query_flags
#define query_cache_invalidate_by_MyISAM_filename_ref NULL
#endif /*HAVE_QUERY_CACHE*/
+uint build_table_path(char *buff, size_t bufflen, const char *db,
+ const char *table, const char *ext);
bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
@@ -858,12 +860,14 @@ bool mysql_create_or_drop_trigger(THD *t
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);
-bool reopen_name_locked_table(THD* thd, TABLE_LIST* table);
+bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in);
+TABLE *table_cache_insert_placeholder(THD *thd, const char *key,
+ uint key_length);
+bool table_cache_has_open_placeholder(THD *thd, const char *db,
+ const char *table_name);
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);
-void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
- bool send_refresh);
bool close_data_tables(THD *thd,const char *db, const char *table_name);
bool wait_for_tables(THD *thd);
bool table_is_used(TABLE *table, bool wait_for_name_lock);
@@ -1019,6 +1023,8 @@ void add_join_natural(TABLE_LIST *a,TABL
SELECT_LEX *lex);
bool add_proc_to_list(THD *thd, Item *item);
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
+void drop_open_table(THD *thd, TABLE *table, const char *db_name,
+ const char *table_name);
void update_non_unique_table_error(TABLE_LIST *update,
const char *operation,
TABLE_LIST *duplicate);
@@ -1271,7 +1277,7 @@ extern double log_01[32];
extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
extern ulonglong thd_startup_options;
-extern ulong refresh_version,flush_version, thread_id;
+extern ulong flush_version, thread_id;
extern ulong binlog_cache_use, binlog_cache_disk_use;
extern ulong aborted_threads,aborted_connects;
extern ulong delayed_insert_timeout;
@@ -1445,7 +1451,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK 0x0001
#define MYSQL_LOCK_IGNORE_FLUSH 0x0002
#define MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN 0x0004
-#define MYSQL_OPEN_IGNORE_LOCKED_TABLES 0x0008
+#define MYSQL_OPEN_TEMPORARY_ONLY 0x0008
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
--- 1.232/sql/sql_insert.cc 2007-05-11 21:56:02 +04:00
+++ 1.233/sql/sql_insert.cc 2007-05-11 21:56:02 +04:00
@@ -2255,7 +2255,7 @@ bool Delayed_insert::handle_inserts(void
thd.proc_info="insert";
max_rows= delayed_insert_limit;
- if (thd.killed || table->s->version != refresh_version)
+ if (thd.killed || table->needs_reopen_or_name_lock())
{
thd.killed= THD::KILL_CONNECTION;
max_rows= ~(ulong)0; // Do as much as possible
@@ -2867,8 +2867,8 @@ bool select_insert::send_eof()
***************************************************************************/
/*
- Create table from lists of fields and items (or open existing table
- with same name).
+ Create table from lists of fields and items (or just return TABLE
+ object for pre-opened existing table).
SYNOPSIS
create_table_from_items()
@@ -2883,18 +2883,24 @@ bool select_insert::send_eof()
of fields for the table (corresponding fields will
be added to the end of alter_info->create_list)
lock out Pointer to the MYSQL_LOCK object for table created
- (open) will be returned in this parameter. Since
- this table is not included in THD::lock caller is
- responsible for explicitly unlocking this table.
+ (or open temporary table) will be returned in this
+ parameter. Since this table is not included in
+ THD::lock caller is responsible for explicitly
+ unlocking this table.
NOTES
- If 'create_info->options' bitmask has HA_LEX_CREATE_IF_NOT_EXISTS
- flag and table with name provided already exists then this function will
- simply open existing table.
- Also note that create, open and lock sequence in this function is not
- atomic and thus contains gap for deadlock and can cause other troubles.
- Since this function contains some logic specific to CREATE TABLE ... SELECT
- it should be changed before it can be used in other contexts.
+ This function behaves differently for base and temporary tables:
+ - For base table we assume that either table exists and was pre-opened
+ and locked at open_and_lock_tables() stage (and in this case we just
+ emit error or warning and return pre-opened TABLE object) or special
+ placeholder was put in table cache that guarantees that this table
+ won't be created or opened until the placeholder will be removed
+ (so there is an exclusive lock on this table).
+ - We don't pre-open existing temporary table, instead we either open
+ or create and then open table in this function.
+
+ Since this function contains some logic specific to CREATE TABLE ...
+ SELECT it should be changed before it can be used in other contexts.
RETURN VALUES
non-zero Pointer to TABLE object for table created or opened
@@ -2917,6 +2923,25 @@ static TABLE *create_table_from_items(TH
bool not_used;
DBUG_ENTER("create_table_from_items");
+ DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
+
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
+ create_table->table->db_stat)
+ {
+ /* Table already exists and was open at open_and_lock_tables() stage. */
+ if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
+ {
+ create_info->table_existed= 1; // Mark that table existed
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
+ create_table->table_name);
+ DBUG_RETURN(create_table->table);
+ }
+
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
+ DBUG_RETURN(0);
+ }
+
tmp_table.alias= 0;
tmp_table.timestamp_field= 0;
tmp_table.s= &tmp_table.share_not_to_be_used;
@@ -2945,8 +2970,15 @@ static TABLE *create_table_from_items(TH
cr_field->flags &= ~NOT_NULL_FLAG;
alter_info->create_list.push_back(cr_field);
}
+
+ DBUG_EXECUTE_IF("sleep_create_select_before_create", my_sleep(6000000););
+
/*
- create and lock table
+ Create and lock table.
+
+ Note that we either creating (or opening existing) temporary table or
+ creating base table on which name we have exclusive lock. So code below
+ should not cause deadlocks or races.
We don't log the statement, it will be logged later.
@@ -2956,59 +2988,70 @@ static TABLE *create_table_from_items(TH
don't want to delete from it) 2) it would be written before the CREATE
TABLE, which is a wrong order. So we keep binary logging disabled when we
open_table().
- NOTE: By locking table which we just have created (or for which we just have
- have found that it already exists) separately from other tables used by the
- statement we create potential window for deadlock.
- TODO: create and open should be done atomic !
*/
{
tmp_disable_binlog(thd);
if (!mysql_create_table(thd, create_table->db, create_table->table_name,
create_info, alter_info, 0, select_field_count))
{
- /*
- If we are here in prelocked mode we either create temporary table
- or prelocked mode is caused by the SELECT part of this statement.
- */
- DBUG_ASSERT(!thd->prelocked_mode ||
- create_info->options & HA_LEX_CREATE_TMP_TABLE ||
- thd->lex->requires_prelocking());
- /*
- NOTE: We don't want to ignore set of locked tables here if we are
- under explicit LOCK TABLES since it will open gap for deadlock
- too wide (and also is not backward compatible).
- */
- if (! (table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
- (MYSQL_LOCK_IGNORE_FLUSH |
- ((thd->prelocked_mode == PRELOCKED) ?
- MYSQL_OPEN_IGNORE_LOCKED_TABLES:0)))))
- quick_rm_table(create_info->db_type, create_table->db,
- table_case_name(create_info, create_table->table_name));
+ if (create_info->table_existed &&
+ !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ /*
+ This means that someone created table underneath server
+ or it was created via different mysqld front-end to the
+ cluster. We don't have much options but throw an error.
+ */
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
+ DBUG_RETURN(0);
+ }
+
+ DBUG_EXECUTE_IF("sleep_create_select_before_open", my_sleep(6000000););
+
+ if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (reopen_name_locked_table(thd, create_table, FALSE))
+ {
+ quick_rm_table(create_info->db_type, create_table->db,
+ table_case_name(create_info,
+ create_table->table_name));
+ }
+ else
+ table= create_table->table;
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
+ else
+ {
+ if (!(table= open_table(thd, create_table, thd->mem_root, (bool*) 0,
+ MYSQL_OPEN_TEMPORARY_ONLY)) &&
+ !create_info->table_existed)
+ {
+ /*
+ This shouldn't happen as creation of temporary table should make
+ it preparable for open. But let us do close_temporary_table() here
+ just in case.
+ */
+ close_temporary_table(thd, create_table->db, create_table->table_name);
+ }
+ }
}
reenable_binlog(thd);
if (!table) // open failed
DBUG_RETURN(0);
}
- /*
- FIXME: What happens if trigger manages to be created while we are
- obtaining this lock ? May be it is sensible just to disable
- trigger execution in this case ? Or will MYSQL_LOCK_IGNORE_FLUSH
- save us from that ?
- */
+ DBUG_EXECUTE_IF("sleep_create_select_before_lock", my_sleep(6000000););
+
table->reginfo.lock_type=TL_WRITE;
if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
MYSQL_LOCK_IGNORE_FLUSH, ¬_used)))
{
- VOID(pthread_mutex_lock(&LOCK_open));
- hash_delete(&open_cache,(byte*) table);
- VOID(pthread_mutex_unlock(&LOCK_open));
- quick_rm_table(create_info->db_type, create_table->db,
- table_case_name(create_info, create_table->table_name));
+ if (!create_info->table_existed)
+ drop_open_table(thd, table, create_table->db, create_table->table_name);
DBUG_RETURN(0);
}
- table->file->extra(HA_EXTRA_WRITE_CACHE);
DBUG_RETURN(table);
}
@@ -3059,8 +3102,10 @@ select_create::prepare(List<Item> &value
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
- DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
- table_list));
+ if (check_that_all_fields_are_given_values(thd, table, table_list))
+ DBUG_RETURN(1);
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ DBUG_RETURN(0);
}
@@ -3092,31 +3137,18 @@ bool select_create::send_eof()
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
- VOID(pthread_mutex_lock(&LOCK_open));
- mysql_unlock_tables(thd, lock);
- /*
- TODO:
- Check if we can remove the following two rows.
- We should be able to just keep the table in the table cache.
- */
- if (!table->s->tmp_table)
+ if (lock)
{
- ulong version= table->s->version;
- hash_delete(&open_cache,(byte*) table);
- /* Tell threads waiting for refresh that something has happened */
- if (version != refresh_version)
- broadcast_refresh();
+ mysql_unlock_tables(thd, lock);
+ lock= 0;
}
- lock=0;
- table=0;
- VOID(pthread_mutex_unlock(&LOCK_open));
}
return tmp;
}
+
void select_create::abort()
{
- VOID(pthread_mutex_lock(&LOCK_open));
if (lock)
{
mysql_unlock_tables(thd, lock);
@@ -3126,22 +3158,10 @@ void select_create::abort()
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
- enum db_type table_type=table->s->db_type;
- if (!table->s->tmp_table)
- {
- ulong version= table->s->version;
- hash_delete(&open_cache,(byte*) table);
- if (!create_info->table_existed)
- quick_rm_table(table_type, create_table->db, create_table->table_name);
- /* Tell threads waiting for refresh that something has happened */
- if (version != refresh_version)
- broadcast_refresh();
- }
- else if (!create_info->table_existed)
- close_temporary_table(thd, create_table->db, create_table->table_name);
+ if (!create_info->table_existed)
+ drop_open_table(thd, table, create_table->db, create_table->table_name);
table=0;
}
- VOID(pthread_mutex_unlock(&LOCK_open));
}
--- 1.517/sql/sql_yacc.yy 2007-05-11 21:56:02 +04:00
+++ 1.518/sql/sql_yacc.yy 2007-05-11 21:56:02 +04:00
@@ -1474,9 +1474,7 @@ create:
lex->sql_command= SQLCOM_CREATE_TABLE;
if (!lex->select_lex.add_table_to_list(thd, $5, NULL,
TL_OPTION_UPDATING,
- (using_update_log ?
- TL_READ_NO_INSERT:
- TL_READ)))
+ TL_WRITE))
MYSQL_YYABORT;
lex->alter_info.reset();
lex->col_list.empty();
--- 1.200/sql/sql_prepare.cc 2007-05-11 21:56:02 +04:00
+++ 1.201/sql/sql_prepare.cc 2007-05-11 21:56:02 +04:00
@@ -1491,8 +1491,21 @@ static bool mysql_test_create_table(Prep
if (select_lex->item_list.elements)
{
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
+ {
+ lex->link_first_table_back(create_table, link_to_local);
+ create_table->create= TRUE;
+ }
+
+ if (open_and_lock_tables(stmt->thd, lex->query_tables))
+ DBUG_RETURN(TRUE);
+
+ if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
+ create_table= lex->unlink_first_table(&link_to_local);
+
select_lex->context.resolve_in_select_list= TRUE;
- res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0);
+
+ res= select_like_stmt_test(stmt, 0, 0);
}
/* put tables back for PS rexecuting */
| Thread |
|---|
| • bk commit into 5.0 tree (dlenev:1.2478) | dlenev | 11 May |