1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merged 5.1 with maria 5.1

This commit is contained in:
Michael Widenius
2008-10-10 18:28:41 +03:00
1924 changed files with 487105 additions and 167345 deletions

View File

@ -4030,6 +4030,13 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
- Run a normal repair using the new index file and the old data file
*/
if (table->s->frm_version != FRM_VER_TRUE_VARCHAR)
{
error= send_check_errmsg(thd, table_list, "repair",
"Failed repairing incompatible .frm file");
goto end;
}
/*
Check if this is a table type that stores index and data separately,
like ISAM or MyISAM. We assume fixed order of engine file name
@ -4196,6 +4203,46 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
table->next_global= save_next_global;
table->next_local= save_next_local;
thd->open_options&= ~extra_open_options;
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->table && table->table->part_info)
{
/*
Set up which partitions that should be processed
if ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION ..
*/
Alter_info *alter_info= &lex->alter_info;
if (alter_info->flags & ALTER_ANALYZE_PARTITION ||
alter_info->flags & ALTER_CHECK_PARTITION ||
alter_info->flags & ALTER_OPTIMIZE_PARTITION ||
alter_info->flags & ALTER_REPAIR_PARTITION)
{
uint no_parts_found;
uint no_parts_opt= alter_info->partition_names.elements;
no_parts_found= set_part_state(alter_info, table->table->part_info,
PART_CHANGED);
if (no_parts_found != no_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
uint length;
DBUG_PRINT("admin", ("sending non existent partition error"));
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
length= my_snprintf(buff, sizeof(buff),
ER(ER_DROP_PARTITION_NON_EXISTENT),
table_name);
protocol->store(buff, length, system_charset_info);
if(protocol->write())
goto err;
my_eof(thd);
goto err;
}
}
}
#endif
}
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
@ -4430,9 +4477,17 @@ send_result_message:
This is currently used only by InnoDB. ha_innobase::optimize() answers
"try with alter", so here we close the table, do an ALTER TABLE,
reopen the table and do ha_innobase::analyze() on it.
We have to end the row, so analyze could return more rows.
*/
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(STRING_WITH_LEN(
"Table does not support optimize, doing recreate + analyze instead"),
system_charset_info);
if (protocol->write())
goto err;
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
TABLE_LIST *save_next_local= table->next_local,
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
@ -4455,6 +4510,10 @@ send_result_message:
((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
result_code= 0; // analyze went ok
}
/* Start a new row for the final status row */
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
if (result_code) // either mysql_recreate_table or analyze failed
{
DBUG_ASSERT(thd->is_error());
@ -4470,7 +4529,8 @@ send_result_message:
/* Hijack the row already in-progress. */
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
protocol->store(err_msg, system_charset_info);
(void)protocol->write();
if (protocol->write())
goto err;
/* Start off another row for HA_ADMIN_FAILED */
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@ -4785,9 +4845,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
DBUG_ENTER("mysql_create_like_table");
/* CREATE TABLE ... LIKE is not allowed for views. */
src_table->required_type= FRMTYPE_TABLE;
/*
By opening source table we guarantee that it exists and no concurrent
DDL operation will mess with it. Later we also take an exclusive
@ -5150,51 +5207,51 @@ compare_tables(TABLE *table,
Field **f_ptr, *field;
uint changes= 0, tmp;
uint key_count;
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
Create_field *new_field;
List_iterator_fast<Create_field> new_field_it, tmp_new_field_it;
Create_field *new_field, *tmp_new_field;
KEY_PART_INFO *key_part;
KEY_PART_INFO *end;
THD *thd= table->in_use;
/*
Remember if the new definition has new VARCHAR column;
create_info->varchar will be reset in mysql_prepare_create_table.
*/
bool varchar= create_info->varchar;
/*
Create a copy of alter_info.
To compare the new and old table definitions, we need to "prepare"
the new definition - transform it from parser output to a format
that describes the final table layout (all column defaults are
initialized, duplicate columns are removed). This is done by
mysql_prepare_create_table. Unfortunately,
mysql_prepare_create_table performs its transformations
"in-place", that is, modifies the argument. Since we would
like to keep compare_tables() idempotent (not altering any
of the arguments) we create a copy of alter_info here and
pass it to mysql_prepare_create_table, then use the result
to evaluate possibility of fast ALTER TABLE, and then
destroy the copy.
*/
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
DBUG_ENTER("compare_tables");
{
THD *thd= table->in_use;
/*
Create a copy of alter_info.
To compare the new and old table definitions, we need to "prepare"
the new definition - transform it from parser output to a format
that describes the final table layout (all column defaults are
initialized, duplicate columns are removed). This is done by
mysql_prepare_create_table. Unfortunately,
mysql_prepare_create_table performs its transformations
"in-place", that is, modifies the argument. Since we would
like to keep compare_tables() idempotent (not altering any
of the arguments) we create a copy of alter_info here and
pass it to mysql_prepare_create_table, then use the result
to evaluate possibility of fast ALTER TABLE, and then
destroy the copy.
*/
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */
/* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info,
(table->s->tmp_table != NO_TMP_TABLE),
&db_options,
table->file, key_info_buffer,
&key_count, 0))
DBUG_RETURN(1);
/* Allocate result buffers. */
if (! (*index_drop_buffer=
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
! (*index_add_buffer=
(uint*) thd->alloc(sizeof(uint) * tmp_alter_info.key_list.elements)))
DBUG_RETURN(1);
}
/* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info,
(table->s->tmp_table != NO_TMP_TABLE),
&db_options,
table->file, key_info_buffer,
&key_count, 0))
DBUG_RETURN(1);
/* Allocate result buffers. */
if (! (*index_drop_buffer=
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
! (*index_add_buffer=
(uint*) thd->alloc(sizeof(uint) * tmp_alter_info.key_list.elements)))
DBUG_RETURN(1);
/*
Some very basic checks. If number of fields changes, or the
handler, we need to run full ALTER TABLE. In the future
@ -5240,18 +5297,27 @@ compare_tables(TABLE *table,
}
/*
Go through fields and check if the original ones are compatible
Use transformed info to evaluate possibility of fast ALTER TABLE
but use the preserved field to persist modifications.
*/
new_field_it.init(alter_info->create_list);
tmp_new_field_it.init(tmp_alter_info.create_list);
/* Go through fields and check if the original ones are compatible
with new table.
*/
for (f_ptr= table->field, new_field= new_field_it++;
(field= *f_ptr); f_ptr++, new_field= new_field_it++)
for (f_ptr= table->field, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++;
(field= *f_ptr);
f_ptr++, new_field= new_field_it++,
tmp_new_field= tmp_new_field_it++)
{
/* Make sure we have at least the default charset in use. */
if (!new_field->charset)
new_field->charset= create_info->default_table_charset;
/* Check that NULL behavior is same for old and new fields */
if ((new_field->flags & NOT_NULL_FLAG) !=
if ((tmp_new_field->flags & NOT_NULL_FLAG) !=
(uint) (field->flags & NOT_NULL_FLAG))
{
*need_copy_table= ALTER_TABLE_DATA_CHANGED;
@ -5259,20 +5325,21 @@ compare_tables(TABLE *table,
}
/* Don't pack rows in old tables if the user has requested this. */
if ((new_field->flags & BLOB_FLAG) ||
new_field->sql_type == MYSQL_TYPE_VARCHAR &&
create_info->row_type != ROW_TYPE_FIXED)
create_info->table_options|= HA_OPTION_PACK_RECORD;
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
(tmp_new_field->flags & BLOB_FLAG) ||
tmp_new_field->sql_type == MYSQL_TYPE_VARCHAR &&
create_info->row_type != ROW_TYPE_FIXED)
create_info->table_options|= HA_OPTION_PACK_RECORD;
/* Check if field was renamed */
field->flags&= ~FIELD_IS_RENAMED;
if (my_strcasecmp(system_charset_info,
field->field_name,
new_field->field_name))
tmp_new_field->field_name))
field->flags|= FIELD_IS_RENAMED;
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
if (!(tmp= field->is_equal(new_field)))
if (!(tmp= field->is_equal(tmp_new_field)))
{
*need_copy_table= ALTER_TABLE_DATA_CHANGED;
DBUG_RETURN(0);
@ -7108,7 +7175,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
errpos= 4;
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);