Below is the list of changes that have just been committed into a local
5.1 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, 2006-10-31 16:22:23+03:00, dlenev@stripped +7 -0
Proposed fix for bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP
crashes server".
Re-execution of CREATE DATABASE, CREATE TABLE and ALTER TABLE
statements in stored routines or as prepared statements caused
incorrect results (and crashes in versions before 5.0.25).
(in 5.1 problem occured only for CREATE DATABASE, CREATE TABLE
SELECT and CREATE TABLE with INDEX/DATA DIRECTOY options).
The problem stemmed from the fact that code implementing these
statements modified HA_CREATE_INFO structure in LEX (e.g. making
it to point to areas in current memory root).
Proposed patch solves this problem by creating and using on-stack
copy of this structure (note that code in 5.1 already created and
used copies this structure in mysql_create_table()/alter_table()
routines but this approach didn't work well for CREATE TABLE
SELECT statement).
Note that this patch does not make CREATE/ALTER TABLE statements
totally safe for re-execution. Their implementation still has some
problems which are to be fixed during work on bugs 4968 and 19182.
mysql-test/r/ps.result@stripped, 2006-10-31 16:22:19+03:00, dlenev@stripped +88 -0
Added test for bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server".
mysql-test/t/ps.test@stripped, 2006-10-31 16:22:19+03:00, dlenev@stripped +71 -0
Added test for bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server".
sql/mysql_priv.h@stripped, 2006-10-31 16:22:20+03:00, dlenev@stripped +2 -3
mysql_create_table() no longer needs use_copy_create_info parameter
since now it is responsibility of caller to create copy of HA_CREATE_INFO
structure if it is necessary to ensure its PS-safety.
Added const qualifier to the 3rd mysqld_show_create_db()'s argument
(HA_CREATE_INFO structure) in order to emphasize that this structure
is not modified in this function.
sql/sql_insert.cc@stripped, 2006-10-31 16:22:20+03:00, dlenev@stripped +1 -1
mysql_create_table() no longer needs use_copy_create_info parameter
since now it is responsibility of caller to create copy of HA_CREATE_INFO
structure if it is necessary to ensure its PS-safety.
sql/sql_parse.cc@stripped, 2006-10-31 16:22:20+03:00, dlenev@stripped +48 -21
Since code which implements CREATE DATABASE, CREATE TABLE and
ALTER TABLE statements (especially in mysql_create_table() and
select_create methods) may modify HA_CREATE_INFO structure in LEX,
we have to create and use copy of this structure to make these
statements prepared statement/stored routine safe. Before this
patch this copying happened inside of mysql_create_table() and
mysql_alter_table() routines but unfortunately such approach
didn't work well for CREATE TABLE SELECT statement (and CREATE
TABLE with DATA/INDEX DIRECTORY option). So now this copying is
done in callers of these routines (i.e. in part of
mysql_execute_command() which is responsible for CREATE/ALTER
TABLE processing).
sql/sql_show.cc@stripped, 2006-10-31 16:22:20+03:00, dlenev@stripped +1 -1
Added const qualifier to the 3rd mysqld_show_create_db()'s argument
(HA_CREATE_INFO structure) in order to emphasize that this structure
is not modified in this function.
sql/sql_table.cc@stripped, 2006-10-31 16:22:20+03:00, dlenev@stripped +44 -64
We no longer create copies of HA_CREATE_INFO structures inside
of mysql_create_table()/create_table_like()/alter_table() functions
as now it is responsibility of caller to create such copies if
PS-safety required. This new approach works better than old one
in cases when we want PS-safety on one hand but also need to use
this structure as out parameter OTOH (for example for CREATE TABLE
SELECT). It also more consistent with general approach that was
chosen to make CREATE/ALTER TABLE PS-safe.
# 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.1-bg22060-3
--- 1.453/sql/mysql_priv.h 2006-10-31 16:22:29 +03:00
+++ 1.454/sql/mysql_priv.h 2006-10-31 16:22:29 +03:00
@@ -916,8 +916,7 @@
bool 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, uint select_field_count,
- bool use_copy_create_info);
+ bool tmp_table, uint select_field_count);
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
@@ -1043,7 +1042,7 @@
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd);
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
-bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
+bool mysqld_show_create_db(THD *thd, char *dbname, const HA_CREATE_INFO *create);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
--- 1.232/sql/sql_insert.cc 2006-10-31 16:22:29 +03:00
+++ 1.233/sql/sql_insert.cc 2006-10-31 16:22:29 +03:00
@@ -2884,7 +2884,7 @@
tmp_disable_binlog(thd);
if (!mysql_create_table(thd, create_table->db, create_table->table_name,
create_info, *extra_fields, *keys, 0,
- select_field_count, 0))
+ select_field_count))
{
/*
If we are here in prelocked mode we either create temporary table
--- 1.585/sql/sql_parse.cc 2006-10-31 16:22:29 +03:00
+++ 1.586/sql/sql_parse.cc 2006-10-31 16:22:29 +03:00
@@ -2884,17 +2884,27 @@
// Skip first table, which is the table we are creating
TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
TABLE_LIST *select_tables= lex->query_tables;
+ HA_CREATE_INFO create_info;
if ((res= create_table_precheck(thd, select_tables, create_table)))
goto end_with_restore_list;
+ /*
+ Code below (especially in mysql_create_table() and select_create
+ methods) may modify HA_CREATE_INFO structure in LEX, so we have to
+ use copy of this structure to make execution prepared statement safe.
+ Shallow copy is enough as this code won't modify memory referenced
+ from this structure.
+ */
+ create_info= lex->create_info;
+
#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= 0;
#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->table_name) ||
- append_file_to_dir(thd, &lex->create_info.index_file_name,
+ append_file_to_dir(thd, &create_info.index_file_name,
create_table->table_name))
goto end_with_restore_list;
#endif
@@ -2902,14 +2912,14 @@
If we are using SET CHARSET without DEFAULT, add an implicit
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
@@ -2954,7 +2964,7 @@
Is table which we are changing used somewhere in other parts
of query
*/
- if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
+ if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
TABLE_LIST *duplicate;
if ((duplicate= unique_table(thd, create_table, select_tables)))
@@ -2965,10 +2975,10 @@
}
}
/* If we create merge table, we have to test tables in merge, too */
- if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
+ if (create_info.used_fields & HA_CREATE_USED_UNION)
{
TABLE_LIST *tab;
- for (tab= (TABLE_LIST*) lex->create_info.merge_list.first;
+ for (tab= (TABLE_LIST*) create_info.merge_list.first;
tab;
tab= tab->next_local)
{
@@ -2983,7 +2993,7 @@
}
if ((result= new select_create(create_table,
- &lex->create_info,
+ &create_info,
lex->create_list,
lex->key_list,
select_lex->item_list,
@@ -3005,18 +3015,18 @@
else
{
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
- if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
thd->options|= OPTION_KEEP_LOG;
/* regular create */
if (lex->like_name)
- res= mysql_create_like_table(thd, create_table, &lex->create_info,
+ res= mysql_create_like_table(thd, create_table, &create_info,
lex->like_name);
else
{
res= mysql_create_table(thd, create_table->db,
- create_table->table_name, &lex->create_info,
+ create_table->table_name, &create_info,
lex->create_list,
- lex->key_list, 0, 0, 1);
+ lex->key_list, 0, 0);
}
if (!res)
send_ok(thd);
@@ -3083,6 +3093,7 @@
{
ulong priv=0;
ulong priv_needed= ALTER_ACL;
+ HA_CREATE_INFO create_info;
/* We also require DROP priv for ALTER TABLE ... DROP PARTITION */
if (lex->alter_info.flags & ALTER_DROP_PARTITION)
priv_needed|= DROP_ACL;
@@ -3119,14 +3130,22 @@
goto error;
}
}
+ /*
+ Code in mysql_alter_table() may modify HA_CREATE_INFO structure
+ in LEX, so we have to use copy of this structure to make execution
+ prepared statement safe.
+ Shallow copy is enough as memory referenced from this structure
+ won't be modified.
+ */
+ create_info= lex->create_info;
/* 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= 0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
goto error;
@@ -3140,7 +3159,7 @@
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
- &lex->create_info,
+ &create_info,
first_table, lex->create_list,
lex->key_list,
select_lex->order_list.elements,
@@ -3726,6 +3745,8 @@
break;
case SQLCOM_CREATE_DB:
{
+ HA_CREATE_INFO create_info;
+
if (end_active_trans(thd))
{
res= -1;
@@ -3755,8 +3776,14 @@
#endif
if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
break;
+ /*
+ As mysql_create_db() may modify HA_CREATE_INFO structure passed to
+ it, we need to use copy of LEX::create_info to make execution prepared
+ statement safe.
+ */
+ create_info= lex->create_info;
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:
--- 1.367/sql/sql_show.cc 2006-10-31 16:22:29 +03:00
+++ 1.368/sql/sql_show.cc 2006-10-31 16:22:30 +03:00
@@ -693,7 +693,7 @@
}
bool mysqld_show_create_db(THD *thd, char *dbname,
- HA_CREATE_INFO *create_info)
+ const HA_CREATE_INFO *create_info)
{
Security_context *sctx= thd->security_ctx;
int length;
--- 1.368/sql/sql_table.cc 2006-10-31 16:22:30 +03:00
+++ 1.369/sql/sql_table.cc 2006-10-31 16:22:30 +03:00
@@ -3136,31 +3136,6 @@
/*
- Copy HA_CREATE_INFO struct
- SYNOPSIS
- copy_create_info()
- lex_create_info The create_info struct setup by parser
- RETURN VALUES
- > 0 A pointer to a copy of the lex_create_info
- 0 Memory allocation error
- DESCRIPTION
- Allocate memory for copy of HA_CREATE_INFO structure from parser
- to ensure we can reuse the parser struct in stored procedures
- and prepared statements.
-*/
-
-static HA_CREATE_INFO *copy_create_info(HA_CREATE_INFO *lex_create_info)
-{
- HA_CREATE_INFO *create_info;
- if (!(create_info= (HA_CREATE_INFO*)sql_alloc(sizeof(HA_CREATE_INFO))))
- mem_alloc_error(sizeof(HA_CREATE_INFO));
- else
- memcpy((void*)create_info, (void*)lex_create_info, sizeof(HA_CREATE_INFO));
- return create_info;
-}
-
-
-/*
Create a table
SYNOPSIS
@@ -3168,15 +3143,12 @@
thd Thread object
db Database
table_name Table name
- lex_create_info Create information (like MAX_ROWS)
+ create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
internal_tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
select_field_count
- use_copy_create_info Should we make a copy of create info (we do this
- when this is called from sql_parse.cc where we
- want to ensure lex object isn't manipulated.
DESCRIPTION
If one creates a temporary table, this is automatically opened
@@ -3186,6 +3158,10 @@
select_field_count is also used for CREATE ... SELECT,
and must be zero for standard create of table.
+ Note that structure passed as 'create_info' parameter may be modified by
+ this function. It is responsibility of caller to make its copies in order
+ to provide correct execution in prepared statements/stored routines.
+
RETURN VALUES
FALSE OK
TRUE error
@@ -3193,34 +3169,22 @@
bool mysql_create_table_internal(THD *thd,
const char *db, const char *table_name,
- HA_CREATE_INFO *lex_create_info,
+ HA_CREATE_INFO *create_info,
List<create_field> &fields,
List<Key> &keys,bool internal_tmp_table,
- uint select_field_count,
- bool use_copy_create_info)
+ uint select_field_count)
{
char path[FN_REFLEN];
uint path_length;
const char *alias;
uint db_options, key_count;
KEY *key_info_buffer;
- HA_CREATE_INFO *create_info;
handler *file;
bool error= TRUE;
DBUG_ENTER("mysql_create_table_internal");
DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d",
db, table_name, internal_tmp_table));
- if (use_copy_create_info)
- {
- if (!(create_info= copy_create_info(lex_create_info)))
- {
- DBUG_RETURN(TRUE);
- }
- }
- else
- create_info= lex_create_info;
-
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
@@ -3562,8 +3526,7 @@
HA_CREATE_INFO *create_info,
List<create_field> &fields,
List<Key> &keys,bool internal_tmp_table,
- uint select_field_count,
- bool use_copy_create_info)
+ uint select_field_count)
{
bool result;
DBUG_ENTER("mysql_create_table");
@@ -3587,8 +3550,7 @@
result= mysql_create_table_internal(thd, db, table_name, create_info,
fields, keys, internal_tmp_table,
- select_field_count,
- use_copy_create_info);
+ select_field_count);
pthread_mutex_lock(&LOCK_lock_db);
if (!--creating_table && creating_database)
@@ -4568,7 +4530,7 @@
*/
bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
- HA_CREATE_INFO *lex_create_info,
+ HA_CREATE_INFO *create_info,
Table_ident *table_ident)
{
TABLE *tmp_table;
@@ -4581,15 +4543,10 @@
int err;
bool res= TRUE;
enum legacy_db_type not_used;
- HA_CREATE_INFO *create_info;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
- if (!(create_info= copy_create_info(lex_create_info)))
- {
- DBUG_RETURN(TRUE);
- }
DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
src_db= table_ident->db.str;
@@ -5132,11 +5089,38 @@
/*
- Alter table
+ Alter table's definition.
+
+ SYNOPSIS
+ mysql_alter_table()
+ thd Thread object
+ new_db New database for table
+ new_name New name for table
+ create_info Create informaton (like MAX_ROWS or COMMENT)
+ table_list Element of table list for table to be altered
+ fields List of fields to be modified or added
+ keys List of keys to be added
+ order_num Number of order list elements
+ order Order list
+ ignore TRUE - if non-fatal errors which occur during
+ copying of data between old and new versions
+ of table must be ignored (for example duplicate
+ key errors). FALSE - otherwise.
+ alter_info Structure which describes alter operation (partially)
+ do_send_ok TRUE - if ok packet should be suppressed
+ FALSE - otherwise
+
+ NOTE
+ Note that structure passed as 'create_info' parameter may be modified by
+ this function. It is responsibility of caller to make its copies in order
+ to provide correct execution in prepared statements/stored routines.
+
+ RETURN VALUE
+ FALSE/TRUE - Success/Failure
*/
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
- HA_CREATE_INFO *lex_create_info,
+ HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
List<create_field> &fields, List<Key> &keys,
uint order_num, ORDER *order, bool ignore,
@@ -5153,7 +5137,6 @@
uint db_create_options, used_fields;
handlerton *old_db_type, *new_db_type;
legacy_db_type table_type;
- HA_CREATE_INFO *create_info;
frm_type_enum frm_type;
uint need_copy_table= 0;
bool no_table_reopen= FALSE, varchar= FALSE;
@@ -5206,9 +5189,9 @@
/* Disable alter of log tables to unsupported engine */
if ((table_kind == GENERAL_LOG || table_kind == SLOW_LOG) &&
- (lex_create_info->used_fields & HA_CREATE_USED_ENGINE) &&
- (!lex_create_info->db_type || /* unknown engine */
- !(lex_create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
+ (create_info->used_fields & HA_CREATE_USED_ENGINE) &&
+ (!create_info->db_type || /* unknown engine */
+ !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
{
my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
DBUG_RETURN(TRUE);
@@ -5216,10 +5199,7 @@
}
thd->proc_info="init";
- if (!(create_info= copy_create_info(lex_create_info)))
- {
- DBUG_RETURN(TRUE);
- }
+
table_name=table_list->table_name;
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
db=table_list->db;
@@ -6020,7 +6000,7 @@
*/
tmp_disable_binlog(thd);
error= mysql_create_table(thd, new_db, tmp_name,
- create_info,create_list,key_list,1,0,0);
+ create_info, create_list, key_list, 1, 0);
reenable_binlog(thd);
if (error)
DBUG_RETURN(error);
--- 1.78/mysql-test/r/ps.result 2006-10-31 16:22:30 +03:00
+++ 1.79/mysql-test/r/ps.result 2006-10-31 16:22:30 +03:00
@@ -2243,3 +2243,91 @@
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
deallocate prepare abc;
+drop database if exists mysqltest;
+drop table if exists t1, t2;
+create table t1 (i int primary key auto_increment) comment='comment for table t1';
+create table t2 (i int, j int, k int);
+prepare stmt from "alter table t1 auto_increment=100";
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`i`)
+) ENGINE=MyISAM AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 COMMENT='comment for table t1'
+flush tables;
+select * from t2;
+i j k
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`i`)
+) ENGINE=MyISAM AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 COMMENT='comment for table t1'
+deallocate prepare stmt;
+drop table t1, t2;
+create database mysqltest character set utf8;
+prepare stmt1 from "create table mysqltest.t1 (c char(10))";
+prepare stmt2 from "create table mysqltest.t2 select 'test'";
+execute stmt1;
+execute stmt2;
+show create table mysqltest.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+show create table mysqltest.t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `test` varchar(4) CHARACTER SET latin1 NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+drop table mysqltest.t1;
+drop table mysqltest.t2;
+alter database mysqltest character set latin1;
+execute stmt1;
+execute stmt2;
+show create table mysqltest.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table mysqltest.t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `test` varchar(4) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop database mysqltest;
+deallocate prepare stmt1;
+deallocate prepare stmt2;
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
+drop table t1;
+execute stmt;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c` char(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQLTEST_VARDIR/tmp/'
+drop table t1;
+deallocate prepare stmt;
+set @old_character_set_server= @@character_set_server;
+set @@character_set_server= latin1;
+prepare stmt from "create database mysqltest";
+execute stmt;
+show create database mysqltest;
+Database Create Database
+mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET latin1 */
+drop database mysqltest;
+set @@character_set_server= utf8;
+execute stmt;
+show create database mysqltest;
+Database Create Database
+mysqltest CREATE DATABASE `mysqltest` /*!40100 DEFAULT CHARACTER SET utf8 */
+drop database mysqltest;
+deallocate prepare stmt;
+set @@character_set_server= @old_character_set_server;
--- 1.75/mysql-test/t/ps.test 2006-10-31 16:22:30 +03:00
+++ 1.76/mysql-test/t/ps.test 2006-10-31 16:22:30 +03:00
@@ -2307,3 +2307,74 @@
drop table if exists t1, t2;
execute abc;
deallocate prepare abc;
+
+
+#
+# Bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
+#
+# Code which implemented CREATE/ALTER TABLE and CREATE DATABASE
+# statement modified HA_CREATE_INFO structure in LEX, making these
+# statements PS/SP-unsafe (their re-execution might have resulted
+# in incorrect results).
+#
+--disable_warnings
+drop database if exists mysqltest;
+drop table if exists t1, t2;
+--enable_warnings
+# ALTER TABLE
+create table t1 (i int primary key auto_increment) comment='comment for table t1';
+create table t2 (i int, j int, k int);
+prepare stmt from "alter table t1 auto_increment=100";
+execute stmt;
+show create table t1;
+# Let us trash table-cache's memory
+flush tables;
+select * from t2;
+execute stmt;
+show create table t1;
+deallocate prepare stmt;
+drop table t1, t2;
+# CREATE TABLE and CREATE TABLE ... SELECT
+create database mysqltest character set utf8;
+prepare stmt1 from "create table mysqltest.t1 (c char(10))";
+prepare stmt2 from "create table mysqltest.t2 select 'test'";
+execute stmt1;
+execute stmt2;
+show create table mysqltest.t1;
+show create table mysqltest.t2;
+drop table mysqltest.t1;
+drop table mysqltest.t2;
+alter database mysqltest character set latin1;
+execute stmt1;
+execute stmt2;
+show create table mysqltest.t1;
+show create table mysqltest.t2;
+drop database mysqltest;
+deallocate prepare stmt1;
+deallocate prepare stmt2;
+# CREATE TABLE with DATA DIRECTORY option
+--disable_query_log
+eval prepare stmt from "create table t1 (c char(10)) data
directory='$MYSQLTEST_VARDIR/tmp'";
+--enable_query_log
+execute stmt;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show create table t1;
+drop table t1;
+execute stmt;
+--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
+show create table t1;
+drop table t1;
+deallocate prepare stmt;
+# CREATE DATABASE
+set @old_character_set_server= @@character_set_server;
+set @@character_set_server= latin1;
+prepare stmt from "create database mysqltest";
+execute stmt;
+show create database mysqltest;
+drop database mysqltest;
+set @@character_set_server= utf8;
+execute stmt;
+show create database mysqltest;
+drop database mysqltest;
+deallocate prepare stmt;
+set @@character_set_server= @old_character_set_server;
| Thread |
|---|
| • bk commit into 5.1 tree (dlenev:1.2321) BUG#22060 | dlenev | 31 Oct |