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:
169
sql/sql_table.cc
169
sql/sql_table.cc
@ -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);
|
||||
|
Reference in New Issue
Block a user