1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +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:
kostja@vajra.(none)
2007-05-28 15:30:01 +04:00
parent 7db7a83f94
commit c759487769
17 changed files with 1602 additions and 1064 deletions

View File

@ -141,30 +141,6 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info,
PARTITION_ITERATOR *part_iter);
static void set_up_range_analysis_info(partition_info *part_info);
/*
A routine used by the parser to decide whether we are specifying a full
partitioning or if only partitions to add or to split.
SYNOPSIS
is_partition_management()
lex Reference to the lex object
RETURN VALUE
TRUE Yes, it is part of a management partition command
FALSE No, not a management partition command
DESCRIPTION
This needs to be outside of WITH_PARTITION_STORAGE_ENGINE since it is
used from the sql parser that doesn't have any #ifdef's
*/
my_bool is_partition_management(LEX *lex)
{
return (lex->sql_command == SQLCOM_ALTER_TABLE &&
(lex->alter_info.flags == ALTER_ADD_PARTITION ||
lex->alter_info.flags == ALTER_REORGANIZE_PARTITION));
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
/*
A support function to check if a name is in a list of strings
@ -4125,7 +4101,7 @@ error:
change patterns.
*/
uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
HA_CREATE_INFO *create_info,
handlerton *old_db_type,
bool *partition_changed,
@ -5991,8 +5967,6 @@ void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt,
alter_info ALTER TABLE info
create_info Create info for CREATE TABLE
table_list List of the table involved
create_list The fields in the resulting table
key_list The keys in the resulting table
db Database name of new table
table_name Table name of new table
@ -6006,11 +5980,10 @@ void handle_alter_part_error(ALTER_PARTITION_PARAM_TYPE *lpt,
*/
uint fast_alter_partition_table(THD *thd, TABLE *table,
ALTER_INFO *alter_info,
Alter_info *alter_info,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
List<create_field> *create_list,
List<Key> *key_list, char *db,
char *db,
const char *table_name,
uint fast_alter_partition)
{
@ -6027,8 +6000,6 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->part_info= part_info;
lpt->alter_info= alter_info;
lpt->create_info= create_info;
lpt->create_list= create_list;
lpt->key_list= key_list;
lpt->db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
lpt->db_options|= HA_OPTION_PACK_RECORD;
@ -6106,7 +6077,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
The first approach here was to downgrade locks. Now a different approach
is decided upon. The idea is that the handler will have access to the
ALTER_INFO when store_lock arrives with TL_WRITE_ALLOW_READ. So if the
Alter_info when store_lock arrives with TL_WRITE_ALLOW_READ. So if the
handler knows that this functionality can be handled with a lower lock
level it will set the lock level to TL_WRITE_ALLOW_WRITE immediately.
Thus the need to downgrade the lock disappears.
@ -6379,7 +6350,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
user
*/
DBUG_RETURN(fast_end_partition(thd, lpt->copied, lpt->deleted,
table, table_list, FALSE, lpt,
table, table_list, FALSE, NULL,
written_bin_log));
}
#endif