Below is the list of changes that have just been committed into a local
4.1 repository of kostja. When kostja 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-01-15 13:03:21+03:00, kostja@stripped +5 -0
Merge bk-internal.mysql.com:/home/bk/mysql-4.1-runtime
into bodhi.local:/opt/local/work/mysql-4.1-4968-to-push
MERGE: 1.2542.22.1
sql/mysql_priv.h@stripped, 2007-01-15 12:58:02+03:00, kostja@stripped +0 -0
Auto merged
MERGE: 1.384.1.1
sql/sql_class.h@stripped, 2007-01-15 12:58:02+03:00, kostja@stripped +0 -0
Auto merged
MERGE: 1.291.1.1
sql/sql_insert.cc@stripped, 2007-01-15 12:58:02+03:00, kostja@stripped +0 -0
Auto merged
MERGE: 1.173.1.1
sql/sql_parse.cc@stripped, 2007-01-15 13:03:18+03:00, kostja@stripped +0 -0
Manual merge.
MERGE: 1.489.1.1
sql/sql_table.cc@stripped, 2007-01-15 13:03:18+03:00, kostja@stripped +2 -3
Manual merge.
MERGE: 1.309.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: kostja
# Host: bodhi.local
# Root: /opt/local/work/mysql-4.1-4968-to-push/RESYNC
--- 1.385/sql/mysql_priv.h 2007-01-15 13:03:27 +03:00
+++ 1.386/sql/mysql_priv.h 2007-01-15 13:03:27 +03:00
@@ -856,6 +856,7 @@ bool open_log(MYSQL_LOG *log, const char
/* mysqld.cc */
extern void yyerror(const char*);
+my_bool mysql_rm_tmp_tables(void);
/* item_func.cc */
extern bool check_reserved_words(LEX_STRING *name);
--- 1.292/sql/sql_class.h 2007-01-15 13:03:27 +03:00
+++ 1.293/sql/sql_class.h 2007-01-15 13:03:27 +03:00
@@ -1293,20 +1293,21 @@ class select_create: public select_inser
ORDER *group;
const char *db;
const char *name;
- List<create_field> *extra_fields;
- List<Key> *keys;
HA_CREATE_INFO *create_info;
+ Alter_info *alter_info;
MYSQL_LOCK *lock;
Field **field;
public:
select_create(const char *db_name, const char *table_name,
- HA_CREATE_INFO *create_info_par,
- List<create_field> &fields_par,
- List<Key> &keys_par,
- List<Item> &select_fields,enum_duplicates duplic, bool ignore)
- :select_insert (NULL, &select_fields, duplic, ignore), db(db_name),
- name(table_name), extra_fields(&fields_par),keys(&keys_par),
- create_info(create_info_par), lock(0)
+ HA_CREATE_INFO *create_info_arg,
+ Alter_info *alter_info_arg,
+ List<Item> &select_fields,
+ enum_duplicates duplic, bool ignore)
+ :select_insert(NULL, &select_fields, duplic, ignore),
+ db(db_name), name(table_name),
+ create_info(create_info_arg),
+ alter_info(alter_info_arg),
+ lock(0)
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
void store_values(List<Item> &values);
--- 1.174/sql/sql_insert.cc 2007-01-15 13:03:27 +03:00
+++ 1.175/sql/sql_insert.cc 2007-01-15 13:03:27 +03:00
@@ -1805,7 +1805,7 @@ select_create::prepare(List<Item> &value
unit= u;
table= create_table_from_items(thd, create_info, db, name,
- extra_fields, keys, &values, &lock);
+ alter_info, &values, &lock);
if (!table)
DBUG_RETURN(-1); // abort() deletes table
--- 1.490/sql/sql_parse.cc 2007-01-15 13:03:27 +03:00
+++ 1.491/sql/sql_parse.cc 2007-01-15 13:03:27 +03:00
@@ -2478,6 +2478,22 @@ mysql_execute_command(THD *thd)
}
/* Skip first table, which is the table we are creating */
TABLE_LIST *create_table, *create_table_local;
+ /*
+ Code below (especially in mysql_create_table() and select_create
+ methods) may modify HA_CREATE_INFO structure in LEX, so we have to
+ use a copy of this structure to make execution prepared statement-
+ safe. A shallow copy is enough as this code won't modify any memory
+ referenced from this structure.
+ */
+ HA_CREATE_INFO create_info(lex->create_info);
+ Alter_info alter_info(lex->alter_info, thd->mem_root);
+
+ if (thd->is_fatal_error)
+ {
+ /* out of memory when creating a copy of alter_info */
+ res= 1;
+ goto unsent_create_error;
+ }
tables= lex->unlink_first_table(tables, &create_table,
&create_table_local);
@@ -2485,12 +2501,12 @@ mysql_execute_command(THD *thd)
goto unsent_create_error;
#ifndef HAVE_READLINK
- lex->create_info.data_file_name=lex->create_info.index_file_name=0;
+ create_info.data_file_name= create_info.index_file_name= NULL;
#else
/* Fix names if symlinked tables */
- if (append_file_to_dir(thd, &lex->create_info.data_file_name,
+ if (append_file_to_dir(thd, &create_info.data_file_name,
create_table->real_name) ||
- append_file_to_dir(thd,&lex->create_info.index_file_name,
+ append_file_to_dir(thd, &create_info.index_file_name,
create_table->real_name))
{
res=-1;
@@ -2501,14 +2517,14 @@ mysql_execute_command(THD *thd)
If we are using SET CHARSET without DEFAULT, add an implicite
DEFAULT to not confuse old users. (This may change).
*/
- if ((lex->create_info.used_fields &
+ if ((create_info.used_fields &
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
HA_CREATE_USED_CHARSET)
{
- lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
- lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
- lex->create_info.default_table_charset= lex->create_info.table_charset;
- lex->create_info.table_charset= 0;
+ create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
+ create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
+ create_info.default_table_charset= create_info.table_charset;
+ create_info.table_charset= 0;
}
/*
The create-select command will open and read-lock the select table
@@ -2542,11 +2558,14 @@ mysql_execute_command(THD *thd)
if (!(res=open_and_lock_tables(thd,tables)))
{
res= -1; // If error
+ /*
+ select_create is currently not re-execution friendly and
+ needs to be created for every execution of a PS/SP.
+ */
if ((result=new select_create(create_table->db,
create_table->real_name,
- &lex->create_info,
- lex->create_list,
- lex->key_list,
+ &create_info,
+ &alter_info,
select_lex->item_list, lex->duplicates,
lex->ignore)))
{
@@ -2558,22 +2577,18 @@ mysql_execute_command(THD *thd)
res=handle_select(thd, lex, result);
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
}
- //reset for PS
- lex->create_list.empty();
- lex->key_list.empty();
}
}
else // regular create
{
if (lex->name)
- res= mysql_create_like_table(thd, create_table, &lex->create_info,
+ res= mysql_create_like_table(thd, create_table, &create_info,
(Table_ident *)lex->name);
else
{
- res= mysql_create_table(thd,create_table->db,
- create_table->real_name, &lex->create_info,
- lex->create_list,
- lex->key_list,0,0);
+ res= mysql_create_table(thd, create_table->db,
+ create_table->real_name, &create_info,
+ &alter_info, 0, 0);
}
if (!res)
send_ok(thd);
@@ -2591,15 +2606,48 @@ unsent_create_error:
break;
}
case SQLCOM_CREATE_INDEX:
+ /* Fall through */
+ case SQLCOM_DROP_INDEX:
+ /*
+ CREATE INDEX and DROP INDEX are implemented by calling ALTER
+ TABLE with proper arguments. This isn't very fast but it
+ should work for most cases.
+
+ In the future ALTER TABLE will notice that only added
+ indexes and create these one by one for the existing table
+ without having to do a full rebuild.
+
+ One should normally create all indexes with CREATE TABLE or
+ ALTER TABLE.
+ */
+ {
+ Alter_info alter_info(lex->alter_info, thd->mem_root);
+ HA_CREATE_INFO create_info;
+
+ if (thd->is_fatal_error) /* out of memory creating a copy of alter_info*/
+ goto error;
+
if (check_one_table_access(thd, INDEX_ACL, tables))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_create_index(thd, tables, lex->key_list);
- break;
+ goto error;
+ /*
+ Currently CREATE INDEX or DROP INDEX cause a full table rebuild
+ and thus classify as slow administrative statements just like
+ ALTER TABLE.
+ */
+ thd->enable_slow_log= opt_log_slow_admin_statements;
+ bzero((char*) &create_info, sizeof(create_info));
+ create_info.db_type= DB_TYPE_DEFAULT;
+ create_info.default_table_charset= thd->variables.collation_database;
+
+ res= mysql_alter_table(thd, tables->db, tables->real_name,
+ &create_info, tables, &alter_info,
+ 0, (ORDER*)0, DUP_ERROR, 0);
+ break;
+ }
#ifdef HAVE_REPLICATION
case SQLCOM_SLAVE_START:
{
@@ -2642,6 +2690,17 @@ unsent_create_error:
#else
{
ulong priv=0;
+ /*
+ Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
+ so we have to use a copy of this structure to make execution
+ prepared statement- safe. A shallow copy is enough as no memory
+ referenced from this structure will be modified.
+ */
+ HA_CREATE_INFO create_info(lex->create_info);
+ Alter_info alter_info(lex->alter_info, thd->mem_root);
+
+ if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
+ goto error;
if (lex->name && (!lex->name[0] || strlen(lex->name) >
NAME_LEN))
{
net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
@@ -2655,7 +2714,7 @@ unsent_create_error:
default database if the new name is not explicitly qualified
by a database. (Bug #11493)
*/
- if (lex->alter_info.flags & ALTER_RENAME)
+ if (alter_info.flags & ALTER_RENAME)
{
if (! thd->db)
{
@@ -2671,7 +2730,7 @@ unsent_create_error:
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
check_merge_table_access(thd, tables->db,
(TABLE_LIST *)
- lex->create_info.merge_list.first))
+ create_info.merge_list.first))
goto error; /* purecov: inspected */
if (grant_option)
{
@@ -2690,26 +2749,26 @@ unsent_create_error:
}
}
/* Don't yet allow changing of symlinks with ALTER TABLE */
- if (lex->create_info.data_file_name)
+ if (create_info.data_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"DATA DIRECTORY option ignored");
- if (lex->create_info.index_file_name)
+ if (create_info.index_file_name)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
"INDEX DIRECTORY option ignored");
- lex->create_info.data_file_name=lex->create_info.index_file_name=0;
+ create_info.data_file_name= create_info.index_file_name= NULL;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
res= -1;
else
{
thd->enable_slow_log= opt_log_slow_admin_statements;
- res= mysql_alter_table(thd, select_lex->db, lex->name,
- &lex->create_info,
- tables, lex->create_list,
- lex->key_list,
- select_lex->order_list.elements,
+ res= mysql_alter_table(thd, select_lex->db, lex->name,
+ &create_info,
+ tables,
+ &alter_info,
+ select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
- lex->duplicates, lex->ignore, &lex->alter_info);
+ lex->duplicates, lex->ignore);
}
break;
}
@@ -2846,7 +2905,7 @@ unsent_create_error:
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
- mysql_recreate_table(thd, tables, 1) :
+ mysql_recreate_table(thd, tables) :
mysql_optimize_table(thd, tables, &lex->check_opt);
/* ! we write after unlocking the table */
if (!res && !lex->no_write_to_binlog)
@@ -3123,14 +3182,6 @@ unsent_create_error:
res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
}
break;
- case SQLCOM_DROP_INDEX:
- if (check_one_table_access(thd, INDEX_ACL, tables))
- goto error; /* purecov: inspected */
- if (end_active_trans(thd))
- res= -1;
- else
- res = mysql_drop_index(thd, tables, &lex->alter_info);
- break;
case SQLCOM_SHOW_DATABASES:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
@@ -3363,6 +3414,12 @@ purposes internal to the MySQL server",
break;
case SQLCOM_CREATE_DB:
{
+ /*
+ As mysql_create_db() may modify HA_CREATE_INFO structure passed to
+ it, we need to use a copy of LEX::create_info to make execution
+ prepared statement- safe.
+ */
+ HA_CREATE_INFO create_info(lex->create_info);
if (end_active_trans(thd))
{
res= -1;
@@ -3393,7 +3450,7 @@ purposes internal to the MySQL server",
if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
break;
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
- &lex->create_info, 0);
+ &create_info, 0);
break;
}
case SQLCOM_DROP_DB:
@@ -4443,15 +4500,17 @@ bool add_field_to_list(THD *thd, char *f
if (type_modifier & PRI_KEY_FLAG)
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
- 0, lex->col_list));
+ lex->alter_info.key_list.push_back(new Key(Key::PRIMARY, NullS,
+ HA_KEY_ALG_UNDEF, 0,
+ lex->col_list));
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
lex->col_list.push_back(new key_part_spec(field_name,0));
- lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
- lex->col_list));
+ lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
+ HA_KEY_ALG_UNDEF, 0,
+ lex->col_list));
lex->col_list.empty();
}
@@ -4778,7 +4837,7 @@ bool add_field_to_list(THD *thd, char *f
new_field->sql_type,
new_field->length);
new_field->char_length= new_field->length;
- lex->create_list.push_back(new_field);
+ lex->alter_info.create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
}
@@ -5455,57 +5514,6 @@ Item * all_any_subquery_creator(Item *le
return it->upper_item= new Item_func_not_all(it); /* ALL */
return it->upper_item= new Item_func_nop_all(it); /* ANY/SOME */
-}
-
-
-/*
- CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
- the proper arguments. This isn't very fast but it should work for most
- cases.
-
- In the future ALTER TABLE will notice that only added indexes
- and create these one by one for the existing table without having to do
- a full rebuild.
-
- One should normally create all indexes with CREATE TABLE or ALTER TABLE.
-*/
-
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
-{
- List<create_field> fields;
- ALTER_INFO alter_info;
- alter_info.flags= ALTER_ADD_INDEX;
- alter_info.is_simple= 0;
- HA_CREATE_INFO create_info;
- DBUG_ENTER("mysql_create_index");
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- create_info.row_type= ROW_TYPE_NOT_USED;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
- &create_info, table_list,
- fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, &alter_info));
-}
-
-
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
-{
- List<create_field> fields;
- List<Key> keys;
- HA_CREATE_INFO create_info;
- DBUG_ENTER("mysql_drop_index");
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- create_info.row_type= ROW_TYPE_NOT_USED;
- alter_info->clear();
- alter_info->flags= ALTER_DROP_INDEX;
- alter_info->is_simple= 0;
- DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
- &create_info, table_list,
- fields, keys, 0, (ORDER*)0,
- DUP_ERROR, 0, alter_info));
}
--- 1.311/sql/sql_table.cc 2007-01-15 13:03:27 +03:00
+++ 1.312/sql/sql_table.cc 2007-01-15 13:03:27 +03:00
@@ -456,8 +456,7 @@ void calculate_interval_lengths(CHARSET_
mysql_prepare_table()
thd Thread object
create_info Create information (like MAX_ROWS)
- fields List of fields to create
- keys List of keys to create
+ alter_info List of columns and indexes to create
DESCRIPTION
Prepares the table and key structures for table creation.
@@ -468,8 +467,8 @@ void calculate_interval_lengths(CHARSET_
*/
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys, bool tmp_table, uint &db_options,
+ Alter_info *alter_info,
+ bool tmp_table, uint &db_options,
handler *file, KEY *&key_info_buffer,
uint *key_count, int select_field_count)
{
@@ -482,10 +481,11 @@ int mysql_prepare_table(THD *thd, HA_CRE
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
+ List_iterator<create_field> it(alter_info->create_list);
+ List_iterator<create_field> it2(alter_info->create_list);
DBUG_ENTER("mysql_prepare_table");
- List_iterator<create_field> it(fields),it2(fields);
- select_field_pos=fields.elements - select_field_count;
+ select_field_pos= alter_info->create_list.elements - select_field_count;
null_fields=blob_columns=0;
for (field_no=0; (sql_field=it++) ; field_no++)
@@ -883,7 +883,8 @@ int mysql_prepare_table(THD *thd, HA_CRE
/* Create keys */
- List_iterator<Key> key_iterator(keys), key_iterator2(keys);
+ List_iterator<Key> key_iterator(alter_info->key_list);
+ List_iterator<Key> key_iterator2(alter_info->key_list);
uint key_parts=0, fk_key_count=0;
bool primary_key=0,unique_key=0;
Key *key, *key2;
@@ -1333,23 +1334,27 @@ int mysql_prepare_table(THD *thd, HA_CRE
SYNOPSIS
mysql_create_table()
- thd Thread object
- db Database
- table_name Table name
- create_info Create information (like MAX_ROWS)
- fields List of fields to create
- keys List of keys to create
- tmp_table Set to 1 if this is an internal temporary table
- (From ALTER TABLE)
+ thd Thread object
+ db Database
+ table_name Table name
+ create_info [in/out] Create information (like MAX_ROWS)
+ alter_info [in/out] List of columns and indexes to create
+ tmp_table Set to 1 if this is an internal temporary table
+ (From ALTER TABLE)
DESCRIPTION
- If one creates a temporary table, this is automaticly opened
+ If one creates a temporary table, this is automatically opened
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,
and must be zero for standard create of table.
+ Note that structures passed as 'create_info' and 'alter_info' parameters
+ may be modified by this function. It is responsibility of the caller to
+ make a copy of create_info in order to provide correct execution in
+ prepared statements/stored routines.
+
RETURN VALUES
0 ok
-1 error
@@ -1357,8 +1362,8 @@ int mysql_prepare_table(THD *thd, HA_CRE
int mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys,bool tmp_table,
+ Alter_info *alter_info,
+ bool tmp_table,
uint select_field_count)
{
char path[FN_REFLEN];
@@ -1371,7 +1376,7 @@ int mysql_create_table(THD *thd,const ch
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
- if (!fields.elements)
+ if (!alter_info->create_list.elements)
{
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
DBUG_RETURN(-1);
@@ -1423,10 +1428,10 @@ int mysql_create_table(THD *thd,const ch
create_info->default_table_charset= db_info.default_table_charset;
}
- if (mysql_prepare_table(thd, create_info, fields,
- keys, tmp_table, db_options, file,
- key_info_buffer, &key_count,
- select_field_count))
+ if (mysql_prepare_table(thd, create_info, alter_info, tmp_table,
+ db_options, file,
+ key_info_buffer, &key_count,
+ select_field_count))
DBUG_RETURN(-1);
/* Check if table exists */
@@ -1503,8 +1508,8 @@ int mysql_create_table(THD *thd,const ch
create_info->table_options=db_options;
if (rea_create_table(thd, path, db, table_name,
- create_info, fields, key_count,
- key_info_buffer))
+ create_info, alter_info->create_list,
+ key_count, key_info_buffer))
goto end;
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
{
@@ -1592,8 +1597,7 @@ make_unique_key_name(const char *field_n
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
const char *db, const char *name,
- List<create_field> *extra_fields,
- List<Key> *keys,
+ Alter_info *alter_info,
List<Item> *items,
MYSQL_LOCK **lock)
{
@@ -1627,7 +1631,7 @@ TABLE *create_table_from_items(THD *thd,
((Item_field *)item)->field :
(Field*) 0))))
DBUG_RETURN(0);
- extra_fields->push_back(cr_field);
+ alter_info->create_list.push_back(cr_field);
}
/* create and lock table */
/* QQ: create and open should be done atomic ! */
@@ -1641,8 +1645,8 @@ TABLE *create_table_from_items(THD *thd,
open_table().
*/
tmp_disable_binlog(thd);
- if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
- *keys,0,select_field_count))
+ if (!mysql_create_table(thd, db, name, create_info, alter_info,
+ 0, select_field_count))
{
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
@@ -2146,6 +2150,7 @@ send_result_message:
case HA_ADMIN_TRY_ALTER:
{
+ my_bool save_no_send_ok= thd->net.no_send_ok;
/*
This is currently used only by InnoDB. ha_innobase::optimize() answers
"try with alter", so here we close the table, do an ALTER TABLE,
@@ -2155,7 +2160,9 @@ send_result_message:
TABLE_LIST *save_next= table->next;
table->next= 0;
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table, 0);
+ thd->net.no_send_ok= TRUE;
+ result_code= mysql_recreate_table(thd, table);
+ thd->net.no_send_ok= save_no_send_ok;
reenable_binlog(thd);
close_thread_tables(thd);
if (!result_code) // recreation went ok
@@ -2635,206 +2642,6 @@ err:
}
-#ifdef NOT_USED
-/*
- CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
- the proper arguments. This isn't very fast but it should work for most
- cases.
- One should normally create all indexes with CREATE TABLE or ALTER TABLE.
-*/
-
-int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
-{
- List<create_field> fields;
- List<Alter_drop> drop;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- int rc;
- uint idx;
- uint db_options;
- uint key_count;
- TABLE *table;
- Field **f_ptr;
- KEY *key_info_buffer;
- char path[FN_REFLEN+1];
- DBUG_ENTER("mysql_create_index");
-
- /*
- Try to use online generation of index.
- This requires that all indexes can be created online.
- Otherwise, the old alter table procedure is executed.
-
- Open the table to have access to the correct table handler.
- */
- if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
-
- /*
- The add_index method takes an array of KEY structs for the new indexes.
- Preparing a new table structure generates this array.
- It needs a list with all fields of the table, which does not need to
- be correct in every respect. The field names are important.
- */
- for (f_ptr= table->field; *f_ptr; f_ptr++)
- {
- create_field *c_fld= new create_field(*f_ptr, *f_ptr);
- c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
- fields.push_back(c_fld);
- }
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- db_options= 0;
- if (mysql_prepare_table(thd, &create_info, fields,
- keys, /*tmp_table*/ 0, db_options, table->file,
- key_info_buffer, key_count,
- /*select_field_count*/ 0))
- DBUG_RETURN(-1);
-
- /*
- Check if all keys can be generated with the add_index method.
- If anyone cannot, then take the old way.
- */
- for (idx=0; idx< key_count; idx++)
- {
- DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
- if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
- (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
- break ;
- }
- if ((idx < key_count)|| !key_count)
- {
- /* Re-initialize the create_info, which was changed by prepare table. */
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
- /* Cleanup the fields list. We do not want to create existing fields. */
- fields.delete_elements();
- if (real_alter_table(thd, table_list->db, table_list->real_name,
- &create_info, table_list, table,
- fields, keys, drop, alter, 0, (ORDER*)0,
- ALTER_ADD_INDEX, DUP_ERROR))
- /* Don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(-1);
- }
- else
- {
- if (table->file->add_index(table, key_info_buffer, key_count)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->real_name,
- reg_ext) == 0 ||
- mysql_create_frm(thd, path, &create_info,
- fields, key_count, key_info_buffer, table->file))
- /* don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(-1);
- }
- /* don't need to free((gptr) key_info_buffer);*/
- DBUG_RETURN(0);
-}
-
-
-int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
- List<Alter_drop> &drop)
-{
- List<create_field> fields;
- List<Key> keys;
- List<Alter_column> alter;
- HA_CREATE_INFO create_info;
- uint idx;
- uint db_options;
- uint key_count;
- uint *key_numbers;
- TABLE *table;
- Field **f_ptr;
- KEY *key_info;
- KEY *key_info_buffer;
- char path[FN_REFLEN];
- DBUG_ENTER("mysql_drop_index");
-
- /*
- Try to use online generation of index.
- This requires that all indexes can be created online.
- Otherwise, the old alter table procedure is executed.
-
- Open the table to have access to the correct table handler.
- */
- if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
-
- /*
- The drop_index method takes an array of key numbers.
- It cannot get more entries than keys in the table.
- */
- key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
- key_count= 0;
-
- /*
- Get the number of each key and check if it can be created online.
- */
- List_iterator<Alter_drop> drop_it(drop);
- Alter_drop *drop_key;
- while ((drop_key= drop_it++))
- {
- /* Find the key in the table. */
- key_info=table->key_info;
- for (idx=0; idx< table->keys; idx++, key_info++)
- {
- if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
- break;
- }
- if (idx>= table->keys)
- {
- my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
- /*
- Check if the key can be generated with the add_index method.
- If anyone cannot, then take the old way.
- */
- DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
- if (!(table->file->index_ddl_flags(table->key_info+idx)&
- (HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
- break ;
- key_numbers[key_count++]= idx;
- }
-
- bzero((char*) &create_info,sizeof(create_info));
- create_info.db_type=DB_TYPE_DEFAULT;
- create_info.default_table_charset= thd->variables.collation_database;
-
- if ((drop_key)|| (drop.elements<= 0))
- {
- if (real_alter_table(thd, table_list->db, table_list->real_name,
- &create_info, table_list, table,
- fields, keys, drop, alter, 0, (ORDER*)0,
- ALTER_DROP_INDEX, DUP_ERROR))
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
- else
- {
- db_options= 0;
- if (table->file->drop_index(table, key_numbers, key_count)||
- mysql_prepare_table(thd, &create_info, fields,
- keys, /*tmp_table*/ 0, db_options, table->file,
- key_info_buffer, key_count,
- /*select_field_count*/ 0)||
- build_table_path(path, sizeof(path), table_list->db,
- (lower_case_table_names == 2) ?
- table_list->alias : table_list->real_name,
- reg_ext) == 0 ||
- mysql_create_frm(thd, path, &create_info,
- fields, key_count, key_info_buffer, table->file))
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(-1);
- }
-
- /*don't need to free((gptr) key_numbers);*/
- DBUG_RETURN(0);
-}
-#endif /* NOT_USED */
/*
@@ -2887,15 +2694,21 @@ bool alter_table_manage_keys(TABLE *tabl
/*
Alter table
+
+
+ NOTE
+ The structures passed as 'create_info' and 'alter_info' parameters may
+ be modified by this function. It is responsibility of the caller to make
+ a copy of create_info in order to provide correct execution in prepared
+ statements/stored routines.
*/
int mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
- List<create_field> &fields, List<Key> &keys,
+ Alter_info *alter_info,
uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates, bool ignore,
- ALTER_INFO *alter_info, bool do_send_ok)
+ enum enum_duplicates handle_duplicates, bool ignore)
{
TABLE *table,*new_table;
int error;
@@ -3064,8 +2877,7 @@ int mysql_alter_table(THD *thd,char *new
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
- if (do_send_ok)
- send_ok(thd);
+ send_ok(thd);
}
else if (error > 0)
{
@@ -3091,10 +2903,9 @@ int mysql_alter_table(THD *thd,char *new
restore_record(table,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<create_field> def_it(alter_info->create_list);
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
+ Alter_info new_info; // Add new columns and indexes here
create_field *def;
/*
@@ -3140,13 +2951,13 @@ int mysql_alter_table(THD *thd,char *new
def->field=field;
if (!def->after)
{
- create_list.push_back(def);
+ new_info.create_list.push_back(def);
def_it.remove();
}
}
else
{ // Use old field value
- create_list.push_back(def=new create_field(field,field));
+ new_info.create_list.push_back(def= new create_field(field, field));
alter_it.rewind(); // Change default if ALTER
Alter_column *alter;
while ((alter=alter_it++))
@@ -3167,7 +2978,7 @@ int mysql_alter_table(THD *thd,char *new
}
}
def_it.rewind();
- List_iterator<create_field> find_it(create_list);
+ List_iterator<create_field> find_it(new_info.create_list);
while ((def=def_it++)) // Add new columns
{
if (def->change && ! def->field)
@@ -3176,9 +2987,9 @@ int mysql_alter_table(THD *thd,char *new
DBUG_RETURN(-1);
}
if (!def->after)
- create_list.push_back(def);
+ new_info.create_list.push_back(def);
else if (def->after == first_keyword)
- create_list.push_front(def);
+ new_info.create_list.push_front(def);
else
{
create_field *find;
@@ -3202,7 +3013,7 @@ int mysql_alter_table(THD *thd,char *new
table_name);
DBUG_RETURN(-1);
}
- if (!create_list.elements)
+ if (!new_info.create_list.elements)
{
my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
DBUG_RETURN(-1);
@@ -3213,8 +3024,8 @@ int mysql_alter_table(THD *thd,char *new
for which some fields exists.
*/
- List_iterator<Key> key_it(keys);
- List_iterator<create_field> field_it(create_list);
+ List_iterator<Key> key_it(alter_info->key_list);
+ List_iterator<create_field> field_it(new_info.create_list);
List<key_part_spec> key_parts;
KEY *key_info=table->key_info;
@@ -3272,24 +3083,37 @@ int mysql_alter_table(THD *thd,char *new
key_part_length));
}
if (key_parts.elements)
- key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
- (key_info->flags & HA_NOSAME ?
- (!my_strcasecmp(system_charset_info,
- key_name, primary_key_name) ?
- Key::PRIMARY : Key::UNIQUE) :
- (key_info->flags & HA_FULLTEXT ?
- Key::FULLTEXT : Key::MULTIPLE)),
- key_name,
- key_info->algorithm,
- test(key_info->flags & HA_GENERATED_KEY),
- key_parts));
+ {
+ Key *key;
+ enum Key::Keytype key_type;
+
+ if (key_info->flags & HA_SPATIAL)
+ key_type= Key::SPATIAL;
+ else if (key_info->flags & HA_NOSAME)
+ {
+ if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
+ key_type= Key::PRIMARY;
+ else
+ key_type= Key::UNIQUE;
+ }
+ else if (key_info->flags & HA_FULLTEXT)
+ key_type= Key::FULLTEXT;
+ else
+ key_type= Key::MULTIPLE;
+
+ key= new Key(key_type, key_name,
+ key_info->algorithm,
+ test(key_info->flags & HA_GENERATED_KEY),
+ key_parts);
+ new_info.key_list.push_back(key);
+ }
}
{
Key *key;
while ((key=key_it++)) // Add new keys
{
if (key->type != Key::FOREIGN_KEY)
- key_list.push_back(key);
+ new_info.key_list.push_back(key);
if (key->name &&
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
@@ -3393,7 +3217,7 @@ int mysql_alter_table(THD *thd,char *new
/* 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);
+ create_info, &new_info, 1, 0);
reenable_binlog(thd);
if (error)
DBUG_RETURN(error);
@@ -3422,10 +3246,10 @@ int mysql_alter_table(THD *thd,char *new
next_insert_id=thd->next_insert_id; // Remember for loggin
copied=deleted=0;
if (!new_table->is_view)
- error=copy_data_between_tables(table,new_table,create_list,
- handle_duplicates, ignore,
- order_num, order, &copied, &deleted,
- alter_info->keys_onoff);
+ error= copy_data_between_tables(table, new_table, new_info.create_list,
+ handle_duplicates, ignore,
+ order_num, order, &copied, &deleted,
+ alter_info->keys_onoff);
/*
No need to have call to alter_table_manage_keys() in the else because
in 4.1 we always copy data, except for views. In 5.0 it could happen
@@ -3637,8 +3461,7 @@ end_temporary:
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
(ulong) (copied + deleted), (ulong) deleted,
(ulong) thd->cuted_fields);
- if (do_send_ok)
- send_ok(thd,copied+deleted,0L,tmp_name);
+ send_ok(thd, copied + deleted, 0L, tmp_name);
thd->some_tables_deleted=0;
DBUG_RETURN(0);
@@ -3828,30 +3651,26 @@ copy_data_between_tables(TABLE *from,TAB
mysql_recreate_table()
thd Thread handler
tables Tables to recreate
- do_send_ok If we should send_ok() or leave it to caller
RETURN
Like mysql_alter_table().
*/
-int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
- bool do_send_ok)
+int mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
{
- DBUG_ENTER("mysql_recreate_table");
LEX *lex= thd->lex;
HA_CREATE_INFO create_info;
- lex->create_list.empty();
- lex->key_list.empty();
- lex->col_list.empty();
- lex->alter_info.reset();
- lex->alter_info.is_simple= 0; // Force full recreate
+ Alter_info alter_info;
+
+ DBUG_ENTER("mysql_recreate_table");
+
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.row_type=ROW_TYPE_DEFAULT;
create_info.default_table_charset=default_charset_info;
+ alter_info.is_simple= 0; // Force full recreate
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
- table_list, lex->create_list,
- lex->key_list, 0, (ORDER *) 0,
- DUP_ERROR, 0, &lex->alter_info, do_send_ok));
+ table_list, &alter_info,
+ 0, (ORDER *) 0, DUP_ERROR, 0));
}
| Thread |
|---|
| • bk commit into 4.1 tree (kostja:1.2597) | konstantin | 15 Jan |