From ae90c20278270d75bc43be0817d173916e44095b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 15 Jun 2006 14:03:17 -0400 Subject: [PATCH] BUG#19309: Crash if double procedural alter mysql-test/r/partition.result: New test case mysql-test/t/partition.test: New test case sql/sql_table.cc: Added new routine to make copy of create_info struct. This struct is manipulated during alter table and create table but needs to remain the same for repeated execution in stored procedures or prepared statements. --- mysql-test/r/partition.result | 8 +++++++ mysql-test/t/partition.test | 14 +++++++++++++ sql/sql_table.cc | 39 +++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 025d9f46412..d8cb474fefc 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,5 +1,13 @@ drop table if exists t1; create table t1 (a int) +partition by list (a) +(partition p0 values in (1)); +create procedure pz() +alter table t1 engine = myisam; +call pz(); +call pz(); +drop table t1; +create table t1 (a int) engine = csv partition by list (a) (partition p0 values in (null)); diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index a7f2e1c0b3e..6658064c094 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -9,6 +9,20 @@ drop table if exists t1; --enable_warnings +# +# Bug 19309 Partitions: Crash if double procedural alter +# +create table t1 (a int) +partition by list (a) +(partition p0 values in (1)); + +create procedure pz() +alter table t1 engine = myisam; + +call pz(); +call pz(); +drop table t1; + # # Bug 19307: CSV engine crashes # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4bc84521f2a..55afd7a5a04 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3001,6 +3001,31 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field) } +/* + 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 @@ -3030,7 +3055,7 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field) bool mysql_create_table_internal(THD *thd, const char *db, const char *table_name, - HA_CREATE_INFO *create_info, + HA_CREATE_INFO *lex_create_info, List &fields, List &keys,bool internal_tmp_table, uint select_field_count) @@ -3040,10 +3065,15 @@ bool mysql_create_table_internal(THD *thd, 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"); + if (!(create_info= copy_create_info(lex_create_info))) + { + DBUG_RETURN(TRUE); + } /* Check for duplicate fields and check type of table to create */ if (!fields.elements) { @@ -4889,7 +4919,7 @@ static uint compare_tables(TABLE *table, List *create_list, */ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, - HA_CREATE_INFO *create_info, + HA_CREATE_INFO *lex_create_info, TABLE_LIST *table_list, List &fields, List &keys, uint order_num, ORDER *order, @@ -4907,6 +4937,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ulonglong next_insert_id; uint db_create_options, used_fields; handlerton *old_db_type, *new_db_type; + HA_CREATE_INFO *create_info; uint need_copy_table= 0; bool no_table_reopen= FALSE, varchar= FALSE; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -4932,6 +4963,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, LINT_INIT(index_drop_buffer); 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;