1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

Merge zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-forcollapseandmerge

into  zippy.cornsilk.net:/home/cmiller/work/mysql/mysql-5.1-maint
This commit is contained in:
cmiller@zippy.cornsilk.net
2007-12-14 13:42:09 -05:00
668 changed files with 32614 additions and 19210 deletions

View File

@@ -1521,6 +1521,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
built_query.append("DROP TABLE ");
}
mysql_ha_rm_tables(thd, tables, FALSE);
pthread_mutex_lock(&LOCK_open);
/*
@@ -1562,7 +1564,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
handlerton *table_type;
enum legacy_db_type frm_db_type;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, 1);
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: 0x%lx s: 0x%lx",
table->db, table->table_name, (long) table->table,
table->table ? (long) table->table->s : (long) -1));
error= drop_temporary_table(thd, table);
@@ -1572,13 +1576,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
tmp_table_deleted= 1;
continue;
case -1:
// table already in use
/*
XXX: This branch should never be taken outside of SF, trigger or
prelocked mode.
DBUG_ASSERT(thd->in_sub_stmt);
*/
DBUG_ASSERT(thd->in_sub_stmt);
error= 1;
goto err_with_placeholders;
default:
@@ -1690,6 +1688,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
wrong_tables.append(',');
wrong_tables.append(String(table->table_name,system_charset_info));
}
DBUG_PRINT("table", ("table: 0x%lx s: 0x%lx", (long) table->table,
table->table ? (long) table->table->s : (long) -1));
}
/*
It's safe to unlock LOCK_open: we have an exclusive lock
@@ -1798,7 +1798,8 @@ bool quick_rm_table(handlerton *base,const char *db,
/*
Sort keys in the following order:
- PRIMARY KEY
- UNIQUE keyws where all column are NOT NULL
- UNIQUE keys where all column are NOT NULL
- UNIQUE keys that don't contain partial segments
- Other UNIQUE keys
- Normal keys
- Fulltext keys
@@ -1809,26 +1810,31 @@ bool quick_rm_table(handlerton *base,const char *db,
static int sort_keys(KEY *a, KEY *b)
{
if (a->flags & HA_NOSAME)
ulong a_flags= a->flags, b_flags= b->flags;
if (a_flags & HA_NOSAME)
{
if (!(b->flags & HA_NOSAME))
if (!(b_flags & HA_NOSAME))
return -1;
if ((a->flags ^ b->flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY))
{
/* Sort NOT NULL keys before other keys */
return (a->flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1;
}
if (a->name == primary_key_name)
return -1;
if (b->name == primary_key_name)
return 1;
/* Sort keys don't containing partial segments before others */
if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
}
else if (b->flags & HA_NOSAME)
else if (b_flags & HA_NOSAME)
return 1; // Prefer b
if ((a->flags ^ b->flags) & HA_FULLTEXT)
if ((a_flags ^ b_flags) & HA_FULLTEXT)
{
return (a->flags & HA_FULLTEXT) ? 1 : -1;
return (a_flags & HA_FULLTEXT) ? 1 : -1;
}
/*
Prefer original key order. usable_key_parts contains here
@@ -2892,6 +2898,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
else
key_info->flags|= HA_PACK_KEY;
}
/* Check if the key segment is partial, set the key flag accordingly */
if (length != sql_field->key_length)
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
key_length+=length;
key_part_info++;
@@ -2947,8 +2957,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE);
}
/* Sort keys in optimized order */
qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
(qsort_cmp) sort_keys);
my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
(qsort_cmp) sort_keys);
create_info->null_bits= null_fields;
DBUG_RETURN(FALSE);
@@ -3705,14 +3715,16 @@ mysql_rename_table(handlerton *base, const char *old_db,
Win32 clients must also have a WRITE LOCK on the table !
*/
static void wait_while_table_is_used(THD *thd,TABLE *table,
enum ha_extra_function function)
void wait_while_table_is_used(THD *thd, TABLE *table,
enum ha_extra_function function)
{
DBUG_ENTER("wait_while_table_is_used");
DBUG_PRINT("enter", ("table: '%s' share: 0x%lx db_stat: %u version: %lu",
table->s->table_name.str, (ulong) table->s,
table->db_stat, table->s->version));
safe_mutex_assert_owner(&LOCK_open);
VOID(table->file->extra(function));
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */
@@ -3836,6 +3848,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
DBUG_RETURN(send_check_errmsg(thd, table, "restore",
"Failed to open partially restored table"));
}
/* A MERGE table must not come here. */
DBUG_ASSERT(!table->table || !table->table->child_l);
pthread_mutex_unlock(&LOCK_open);
DBUG_RETURN(0);
}
@@ -3878,6 +3892,10 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
table= &tmp_table;
pthread_mutex_unlock(&LOCK_open);
}
/* A MERGE table must not come here. */
DBUG_ASSERT(!table->child_l);
/*
REPAIR TABLE ... USE_FRM for temporary tables makes little sense.
*/
@@ -4025,13 +4043,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
mysql_ha_rm_tables(thd, tables, FALSE);
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
char* db = table->db;
bool fatal_error=0;
DBUG_PRINT("admin", ("table: '%s'.'%s'", table->db, table->table_name));
DBUG_PRINT("admin", ("extra_open_options: %u", extra_open_options));
strxmov(table_name, db, ".", table->table_name, NullS);
thd->open_options|= extra_open_options;
table->lock_type= lock_type;
@@ -4062,16 +4083,24 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->next_local= save_next_local;
thd->open_options&= ~extra_open_options;
}
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
if (prepare_func)
{
DBUG_PRINT("admin", ("calling prepare_func"));
switch ((*prepare_func)(thd, table, check_opt)) {
case 1: // error, message written to net
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
DBUG_PRINT("admin", ("simple error, admin next table"));
continue;
case -1: // error, message could be written to net
/* purecov: begin inspected */
DBUG_PRINT("admin", ("severe error, stop"));
goto err;
/* purecov: end */
default: // should be 0 otherwise
DBUG_PRINT("admin", ("prepare_func succeeded"));
;
}
}
@@ -4086,6 +4115,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
*/
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
if (!thd->warn_list.elements)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
@@ -4100,14 +4130,17 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (table->view)
{
DBUG_PRINT("admin", ("calling view_operator_func"));
result_code= (*view_operator_func)(thd, table);
goto send_result;
}
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
/* purecov: begin inspected */
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
uint length;
DBUG_PRINT("admin", ("sending error message"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -4122,11 +4155,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (protocol->write())
goto err;
continue;
/* purecov: end */
}
/* Close all instances of the table to allow repair to rename files */
if (lock_type == TL_WRITE && table->table->s->version)
{
DBUG_PRINT("admin", ("removing table from cache"));
pthread_mutex_lock(&LOCK_open);
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
"Waiting to get writelock");
@@ -4146,6 +4181,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (table->table->s->crashed && operator_func == &handler::ha_check)
{
/* purecov: begin inspected */
DBUG_PRINT("admin", ("sending crashed warning"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -4154,6 +4191,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
system_charset_info);
if (protocol->write())
goto err;
/* purecov: end */
}
if (operator_func == &handler::ha_repair &&
@@ -4164,6 +4202,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
HA_ADMIN_NEEDS_ALTER))
{
my_bool save_no_send_ok= thd->net.no_send_ok;
DBUG_PRINT("admin", ("recreating table"));
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
@@ -4176,7 +4215,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
result_code = (table->table->file->*operator_func)(thd, check_opt);
DBUG_PRINT("admin", ("operator_func returned: %d", result_code));
send_result:
@@ -5766,8 +5807,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
build_table_filename(reg_path, sizeof(reg_path), db, table_name, reg_ext, 0);
build_table_filename(path, sizeof(path), db, table_name, "", 0);
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
mysql_ha_rm_tables(thd, table_list, FALSE);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
@@ -5834,10 +5874,25 @@ view_err:
start_waiting_global_read_lock(thd);
DBUG_RETURN(error);
}
if (!(table=open_ltable(thd, table_list, TL_WRITE_ALLOW_READ, 0)))
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
DBUG_RETURN(TRUE);
table->use_all_columns();
/*
Prohibit changing of the UNION list of a non-temporary MERGE table
under LOCK tables. It would be quite difficult to reuse a shrinked
set of tables from the old table or to open a new TABLE object for
an extended list and verify that they belong to locked tables.
*/
if (thd->locked_tables &&
(create_info->used_fields & HA_CREATE_USED_UNION) &&
(table->s->tmp_table == NO_TMP_TABLE))
{
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
DBUG_RETURN(TRUE);
}
/* Check that we are not trying to rename to an existing table */
if (new_name)
{
@@ -6305,6 +6360,7 @@ view_err:
goto err;
/* Open the table if we need to copy the data. */
DBUG_PRINT("info", ("need_copy_table: %u", need_copy_table));
if (need_copy_table != ALTER_TABLE_METADATA_ONLY)
{
if (table->s->tmp_table)
@@ -6328,6 +6384,10 @@ view_err:
}
if (!new_table)
goto err1;
/*
Note: In case of MERGE table, we do not attach children. We do not
copy data for MERGE tables. Only the children have data.
*/
}
/* Copy the data if necessary. */
@@ -6335,6 +6395,10 @@ view_err:
thd->cuted_fields=0L;
thd_proc_info(thd, "copy to tmp table");
copied=deleted=0;
/*
We do not copy data for MERGE tables. Only the children have data.
MERGE tables have HA_NO_COPY_ON_ALTER set.
*/
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
{
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
@@ -6472,7 +6536,10 @@ view_err:
if (new_table)
{
/* Close the intermediate table that will be the new table */
/*
Close the intermediate table that will be the new table.
Note that MERGE tables do not have their children attached here.
*/
intern_close_table(new_table);
my_free(new_table,MYF(0));
}
@@ -6565,6 +6632,7 @@ view_err:
/*
Now we have to inform handler that new .FRM file is in place.
To do this we need to obtain a handler object for it.
NO need to tamper with MERGE tables. The real open is done later.
*/
TABLE *t_table;
if (new_name != table_name || new_db != db)
@@ -6632,7 +6700,7 @@ view_err:
/*
For the alter table to be properly flushed to the logs, we
have to open the new table. If not, we get a problem on server
shutdown.
shutdown. But we do not need to attach MERGE children.
*/
char path[FN_REFLEN];
TABLE *t_table;
@@ -6821,23 +6889,35 @@ copy_data_between_tables(TABLE *from,TABLE *to,
if (order)
{
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
bzero((char*) &tables,sizeof(tables));
tables.table= from;
tables.alias= tables.table_name= from->s->table_name.str;
tables.db= from->s->db.str;
error=1;
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
{
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff),
"ORDER BY ignored as there is a user-defined clustered index"
" in the table '%-.192s'", from->s->table_name.str);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
warn_buff);
}
else
{
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
bzero((char *) &tables, sizeof(tables));
tables.table= from;
tables.alias= tables.table_name= from->s->table_name.str;
tables.db= from->s->db.str;
error= 1;
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, 1,
&examined_rows)) ==
HA_POS_ERROR)
goto err;
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
(from->sort.found_records= filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
1, &examined_rows)) ==
HA_POS_ERROR)
goto err;
}
};
/* Tell handler that we have values for all columns in the to table */
@@ -6962,6 +7042,12 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
Alter_info alter_info;
DBUG_ENTER("mysql_recreate_table");
DBUG_ASSERT(!table_list->next_global);
/*
table_list->table has been closed and freed. Do not reference
uninitialized data. open_tables() could fail.
*/
table_list->table= NULL;
bzero((char*) &create_info, sizeof(create_info));
create_info.db_type= 0;
@@ -6993,6 +7079,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
/* Open one table after the other to keep lock time as short as possible. */
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
@@ -7000,7 +7087,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
strxmov(table_name, table->db ,".", table->table_name, NullS);
t= table->table= open_ltable(thd, table, TL_READ, 0);
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend();