2006-12-31 01:02:27 +01:00
|
|
|
/* Copyright (C) 2000-2001, 2003, 2005 MySQL AB
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
|
2005-05-26 12:09:14 +02:00
|
|
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
2000-07-31 21:29:14 +02:00
|
|
|
#pragma implementation // gcc: Class implementation
|
|
|
|
#endif
|
|
|
|
|
2005-06-05 19:38:52 +02:00
|
|
|
#include "mysql_priv.h"
|
|
|
|
|
2001-08-02 05:29:50 +02:00
|
|
|
list_node end_of_list;
|
2003-06-10 20:42:29 +02:00
|
|
|
|
|
|
|
void free_list(I_List <i_string_pair> *list)
|
|
|
|
{
|
|
|
|
i_string_pair *tmp;
|
|
|
|
while ((tmp= list->get()))
|
|
|
|
delete tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void free_list(I_List <i_string> *list)
|
|
|
|
{
|
|
|
|
i_string *tmp;
|
|
|
|
while ((tmp= list->get()))
|
|
|
|
delete tmp;
|
|
|
|
}
|
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.
2007-05-28 13:30:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
base_list::base_list(const base_list &rhs, MEM_ROOT *mem_root)
|
|
|
|
{
|
|
|
|
if (rhs.elements)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
It's okay to allocate an array of nodes at once: we never
|
|
|
|
call a destructor for list_node objects anyway.
|
|
|
|
*/
|
|
|
|
first= (list_node*) alloc_root(mem_root,
|
|
|
|
sizeof(list_node) * rhs.elements);
|
|
|
|
if (first)
|
|
|
|
{
|
|
|
|
elements= rhs.elements;
|
|
|
|
list_node *dst= first;
|
|
|
|
list_node *src= rhs.first;
|
|
|
|
for (; dst < first + elements - 1; dst++, src= src->next)
|
|
|
|
{
|
|
|
|
dst->info= src->info;
|
|
|
|
dst->next= dst + 1;
|
|
|
|
}
|
|
|
|
/* Copy the last node */
|
|
|
|
dst->info= src->info;
|
|
|
|
dst->next= &end_of_list;
|
|
|
|
/* Setup 'last' member */
|
|
|
|
last= &dst->next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
elements= 0;
|
|
|
|
first= &end_of_list;
|
|
|
|
last= &first;
|
|
|
|
}
|