mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
5.1 version of a fix and test cases for bugs:
Bug#4968 ""Stored procedure crash if cursor opened on altered table" Bug#6895 "Prepared Statements: ALTER TABLE DROP COLUMN does nothing" Bug#19182 "CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work from stored procedure." Bug#19733 "Repeated alter, or repeated create/drop, fails" Bug#22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server" Bug#24879 "Prepared Statements: CREATE TABLE (UTF8 KEY) produces a growing key length" (this bug is not fixed in 5.0) 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 prior to 5.0.25). In 5.1 the problem occured only for CREATE DATABASE, CREATE TABLE SELECT and CREATE TABLE with INDEX/DATA DIRECTOY options). The problem of bugs 4968, 19733, 19282 and 6895 was that functions mysql_prepare_table, mysql_create_table and mysql_alter_table are not re-execution friendly: during their operation they modify contents of LEX (members create_info, alter_info, key_list, create_list), thus making the LEX unusable for the next execution. In particular, these functions removed processed columns and keys from create_list, key_list and drop_list. Search the code in sql_table.cc for drop_it.remove() and similar patterns to find evidence. The fix is to supply to these functions a usable copy of each of the above structures at every re-execution of an SQL statement. To simplify memory management, LEX::key_list and LEX::create_list were added to LEX::alter_info, a fresh copy of which is created for every execution. The problem of crashing bug 22060 stemmed from the fact that the above metnioned functions were not only modifying HA_CREATE_INFO structure in LEX, but also were changing it to point to areas in volatile memory of the execution memory root. The patch solves this problem by creating and using an on-stack copy of HA_CREATE_INFO in mysql_execute_command. Additionally, this patch splits the part of mysql_alter_table that analizes and rewrites information from the parser into a separate function - mysql_prepare_alter_table, in analogy with mysql_prepare_table, which is renamed to mysql_prepare_create_table.
This commit is contained in:
@ -830,26 +830,60 @@ inline bool st_select_lex_unit::is_union ()
|
||||
#define ALTER_REMOVE_PARTITIONING (1L << 25)
|
||||
#define ALTER_FOREIGN_KEY (1L << 26)
|
||||
|
||||
typedef struct st_alter_info
|
||||
/**
|
||||
@brief Parsing data for CREATE or ALTER TABLE.
|
||||
|
||||
This structure contains a list of columns or indexes to be created,
|
||||
altered or dropped.
|
||||
*/
|
||||
|
||||
class Alter_info
|
||||
{
|
||||
public:
|
||||
List<Alter_drop> drop_list;
|
||||
List<Alter_column> alter_list;
|
||||
List<Key> key_list;
|
||||
List<create_field> create_list;
|
||||
uint flags;
|
||||
enum enum_enable_or_disable keys_onoff;
|
||||
enum tablespace_op_type tablespace_op;
|
||||
List<char> partition_names;
|
||||
uint no_parts;
|
||||
|
||||
st_alter_info(){clear();}
|
||||
void clear()
|
||||
Alter_info() :
|
||||
flags(0),
|
||||
keys_onoff(LEAVE_AS_IS),
|
||||
tablespace_op(NO_TABLESPACE_OP),
|
||||
no_parts(0)
|
||||
{}
|
||||
|
||||
void reset()
|
||||
{
|
||||
drop_list.empty();
|
||||
alter_list.empty();
|
||||
key_list.empty();
|
||||
create_list.empty();
|
||||
flags= 0;
|
||||
keys_onoff= LEAVE_AS_IS;
|
||||
tablespace_op= NO_TABLESPACE_OP;
|
||||
no_parts= 0;
|
||||
partition_names.empty();
|
||||
}
|
||||
void reset(){drop_list.empty();alter_list.empty();clear();}
|
||||
} ALTER_INFO;
|
||||
/**
|
||||
Construct a copy of this object to be used for mysql_alter_table
|
||||
and mysql_create_table. Historically, these two functions modify
|
||||
their Alter_info arguments. This behaviour breaks re-execution of
|
||||
prepared statements and stored procedures and is compensated by
|
||||
always supplying a copy of Alter_info to these functions.
|
||||
|
||||
@return You need to use check the error in THD for out
|
||||
of memory condition after calling this function.
|
||||
*/
|
||||
Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root);
|
||||
private:
|
||||
Alter_info &operator=(const Alter_info &rhs); // not implemented
|
||||
Alter_info(const Alter_info &rhs); // not implemented
|
||||
};
|
||||
|
||||
struct st_sp_chistics
|
||||
{
|
||||
@ -1103,8 +1137,6 @@ typedef struct st_lex : public Query_tables_list
|
||||
List<String> interval_list;
|
||||
List<LEX_USER> users_list;
|
||||
List<LEX_COLUMN> columns;
|
||||
List<Key> key_list;
|
||||
List<create_field> create_list;
|
||||
List<Item> *insert_list,field_list,value_list,update_list;
|
||||
List<List_item> many_values;
|
||||
List<set_var_base> var_list;
|
||||
@ -1202,7 +1234,7 @@ typedef struct st_lex : public Query_tables_list
|
||||
bool safe_to_cache_query;
|
||||
bool subqueries, ignore;
|
||||
st_parsing_options parsing_options;
|
||||
ALTER_INFO alter_info;
|
||||
Alter_info alter_info;
|
||||
/* Prepared statements SQL syntax:*/
|
||||
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
||||
/*
|
||||
@ -1361,6 +1393,7 @@ typedef struct st_lex : public Query_tables_list
|
||||
void restore_backup_query_tables_list(Query_tables_list *backup);
|
||||
|
||||
bool table_or_sp_used();
|
||||
bool is_partition_management() const;
|
||||
} LEX;
|
||||
|
||||
struct st_lex_local: public st_lex
|
||||
|
Reference in New Issue
Block a user