mirror of
https://github.com/MariaDB/server.git
synced 2025-12-04 17:23:46 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-4.1-runtime
into bodhi.local:/opt/local/work/mysql-4.1-4968-to-push sql/mysql_priv.h: Auto merged sql/sql_class.h: Auto merged sql/sql_insert.cc: Auto merged sql/sql_parse.cc: Manual merge. sql/sql_table.cc: Manual merge.
This commit is contained in:
@@ -1035,4 +1035,71 @@ EXECUTE stmt USING @a;
|
|||||||
0 0
|
0 0
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
DROP TABLE IF EXISTS t1, t2;
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
PREPARE st_19182
|
||||||
|
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
j int(11) YES MUL NULL
|
||||||
|
i int(11) YES MUL NULL
|
||||||
|
DROP TABLE t2;
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
j int(11) YES MUL NULL
|
||||||
|
i int(11) YES MUL NULL
|
||||||
|
DEALLOCATE PREPARE st_19182;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
drop database if exists mysqltest;
|
||||||
|
drop table if exists 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` char(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` char(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;
|
||||||
End of 4.1 tests.
|
End of 4.1 tests.
|
||||||
|
|||||||
@@ -1068,5 +1068,77 @@ EXECUTE stmt USING @a;
|
|||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#19182: CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work
|
||||||
|
# from stored procedure.
|
||||||
|
#
|
||||||
|
# The cause of a bug was that cached LEX::create_list was modified,
|
||||||
|
# and then together with LEX::key_list was reset.
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1, t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
|
||||||
|
PREPARE st_19182
|
||||||
|
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||||
|
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
|
||||||
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
# Check that on second execution we don't loose 'j' column and the keys
|
||||||
|
# on 'i' and 'j' columns.
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
|
||||||
|
DEALLOCATE PREPARE st_19182;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# 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;
|
||||||
|
#
|
||||||
--echo End of 4.1 tests.
|
--echo End of 4.1 tests.
|
||||||
|
|||||||
@@ -563,25 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
uint &key_count, int select_field_count);
|
uint &key_count, int select_field_count);
|
||||||
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields, List<Key> &keys,
|
Alter_info *alter_info,
|
||||||
bool tmp_table, uint select_field_count);
|
bool tmp_table, uint select_field_count);
|
||||||
|
|
||||||
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
const char *db, const char *name,
|
const char *db, const char *name,
|
||||||
List<create_field> *extra_fields,
|
Alter_info *alter_info,
|
||||||
List<Key> *keys,
|
|
||||||
List<Item> *items,
|
List<Item> *items,
|
||||||
MYSQL_LOCK **lock);
|
MYSQL_LOCK **lock);
|
||||||
int mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
int mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
List<create_field> &fields,
|
Alter_info *alter_info,
|
||||||
List<Key> &keys,
|
|
||||||
uint order_num, ORDER *order,
|
uint order_num, ORDER *order,
|
||||||
enum enum_duplicates handle_duplicates,
|
enum enum_duplicates handle_duplicates,
|
||||||
bool ignore,
|
bool ignore);
|
||||||
ALTER_INFO *alter_info, bool do_send_ok=1);
|
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
|
||||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
|
||||||
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
int mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
Table_ident *src_table);
|
Table_ident *src_table);
|
||||||
@@ -590,9 +587,6 @@ bool mysql_rename_table(enum db_type base,
|
|||||||
const char * old_name,
|
const char * old_name,
|
||||||
const char *new_db,
|
const char *new_db,
|
||||||
const char * new_name);
|
const char * new_name);
|
||||||
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
|
|
||||||
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
|
|
||||||
ALTER_INFO *alter_info);
|
|
||||||
int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||||
TABLE_LIST *update_table_list,
|
TABLE_LIST *update_table_list,
|
||||||
Item **conds, uint order_num, ORDER *order);
|
Item **conds, uint order_num, ORDER *order);
|
||||||
@@ -679,7 +673,8 @@ int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
|
|||||||
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
|
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
|
||||||
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
|
int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
|
||||||
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
|
int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
|
||||||
int mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
|
int mysqld_show_create_db(THD *thd, char *dbname,
|
||||||
|
const HA_CREATE_INFO *create);
|
||||||
|
|
||||||
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
|
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
|
||||||
int mysqld_show_status(THD *thd);
|
int mysqld_show_status(THD *thd);
|
||||||
|
|||||||
@@ -1293,20 +1293,21 @@ class select_create: public select_insert {
|
|||||||
ORDER *group;
|
ORDER *group;
|
||||||
const char *db;
|
const char *db;
|
||||||
const char *name;
|
const char *name;
|
||||||
List<create_field> *extra_fields;
|
|
||||||
List<Key> *keys;
|
|
||||||
HA_CREATE_INFO *create_info;
|
HA_CREATE_INFO *create_info;
|
||||||
|
Alter_info *alter_info;
|
||||||
MYSQL_LOCK *lock;
|
MYSQL_LOCK *lock;
|
||||||
Field **field;
|
Field **field;
|
||||||
public:
|
public:
|
||||||
select_create(const char *db_name, const char *table_name,
|
select_create(const char *db_name, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info_par,
|
HA_CREATE_INFO *create_info_arg,
|
||||||
List<create_field> &fields_par,
|
Alter_info *alter_info_arg,
|
||||||
List<Key> &keys_par,
|
List<Item> &select_fields,
|
||||||
List<Item> &select_fields,enum_duplicates duplic, bool ignore)
|
enum_duplicates duplic, bool ignore)
|
||||||
:select_insert (NULL, &select_fields, duplic, ignore), db(db_name),
|
:select_insert(NULL, &select_fields, duplic, ignore),
|
||||||
name(table_name), extra_fields(&fields_par),keys(&keys_par),
|
db(db_name), name(table_name),
|
||||||
create_info(create_info_par), lock(0)
|
create_info(create_info_arg),
|
||||||
|
alter_info(alter_info_arg),
|
||||||
|
lock(0)
|
||||||
{}
|
{}
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
void store_values(List<Item> &values);
|
void store_values(List<Item> &values);
|
||||||
|
|||||||
@@ -1805,7 +1805,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
|
|
||||||
unit= u;
|
unit= u;
|
||||||
table= create_table_from_items(thd, create_info, db, name,
|
table= create_table_from_items(thd, create_info, db, name,
|
||||||
extra_fields, keys, &values, &lock);
|
alter_info, &values, &lock);
|
||||||
if (!table)
|
if (!table)
|
||||||
DBUG_RETURN(-1); // abort() deletes table
|
DBUG_RETURN(-1); // abort() deletes table
|
||||||
|
|
||||||
|
|||||||
@@ -1015,6 +1015,18 @@ int yylex(void *arg, void *yythd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
||||||
|
:drop_list(rhs.drop_list, mem_root),
|
||||||
|
alter_list(rhs.alter_list, mem_root),
|
||||||
|
key_list(rhs.key_list, mem_root),
|
||||||
|
create_list(rhs.create_list, mem_root),
|
||||||
|
flags(rhs.flags),
|
||||||
|
keys_onoff(rhs.keys_onoff),
|
||||||
|
tablespace_op(rhs.tablespace_op),
|
||||||
|
is_simple(rhs.is_simple)
|
||||||
|
{}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
st_select_lex structures initialisations
|
st_select_lex structures initialisations
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -571,19 +571,61 @@ typedef class st_select_lex SELECT_LEX;
|
|||||||
#define ALTER_ORDER 64
|
#define ALTER_ORDER 64
|
||||||
#define ALTER_OPTIONS 128
|
#define ALTER_OPTIONS 128
|
||||||
|
|
||||||
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_drop> drop_list;
|
||||||
List<Alter_column> alter_list;
|
List<Alter_column> alter_list;
|
||||||
|
List<Key> key_list;
|
||||||
|
List<create_field> create_list;
|
||||||
uint flags;
|
uint flags;
|
||||||
enum enum_enable_or_disable keys_onoff;
|
enum enum_enable_or_disable keys_onoff;
|
||||||
enum tablespace_op_type tablespace_op;
|
enum tablespace_op_type tablespace_op;
|
||||||
bool is_simple;
|
bool is_simple;
|
||||||
|
|
||||||
st_alter_info(){clear();}
|
Alter_info() :
|
||||||
void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
|
flags(0),
|
||||||
void reset(){drop_list.empty();alter_list.empty();clear();}
|
keys_onoff(LEAVE_AS_IS),
|
||||||
} ALTER_INFO;
|
tablespace_op(NO_TABLESPACE_OP),
|
||||||
|
is_simple(1)
|
||||||
|
{}
|
||||||
|
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;
|
||||||
|
is_simple= 1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
The constructed copy still shares key Key, Alter_drop, create_field
|
||||||
|
and Alter_column elements of the lists - these structures are not
|
||||||
|
modified and thus are not copied.
|
||||||
|
|
||||||
|
@note You need to use check thd->is_fatal_error 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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* The state of the lex parsing. This is saved in the THD struct */
|
/* The state of the lex parsing. This is saved in the THD struct */
|
||||||
|
|
||||||
@@ -620,8 +662,6 @@ typedef struct st_lex
|
|||||||
List<String> interval_list;
|
List<String> interval_list;
|
||||||
List<LEX_USER> users_list;
|
List<LEX_USER> users_list;
|
||||||
List<LEX_COLUMN> columns;
|
List<LEX_COLUMN> columns;
|
||||||
List<Key> key_list;
|
|
||||||
List<create_field> create_list;
|
|
||||||
List<Item> *insert_list,field_list,value_list,update_list;
|
List<Item> *insert_list,field_list,value_list,update_list;
|
||||||
List<List_item> many_values;
|
List<List_item> many_values;
|
||||||
List<set_var_base> var_list;
|
List<set_var_base> var_list;
|
||||||
@@ -654,7 +694,7 @@ typedef struct st_lex
|
|||||||
bool derived_tables;
|
bool derived_tables;
|
||||||
bool safe_to_cache_query;
|
bool safe_to_cache_query;
|
||||||
bool subqueries, ignore;
|
bool subqueries, ignore;
|
||||||
ALTER_INFO alter_info;
|
Alter_info alter_info;
|
||||||
/* Prepared statements SQL syntax:*/
|
/* Prepared statements SQL syntax:*/
|
||||||
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -66,9 +66,14 @@ public:
|
|||||||
pointer.
|
pointer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class list_node :public Sql_alloc
|
|
||||||
|
/**
|
||||||
|
list_node - a node of a single-linked list.
|
||||||
|
@note We never call a destructor for instances of this class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct list_node :public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
list_node *next;
|
list_node *next;
|
||||||
void *info;
|
void *info;
|
||||||
list_node(void *info_par,list_node *next_par)
|
list_node(void *info_par,list_node *next_par)
|
||||||
@@ -76,11 +81,9 @@ public:
|
|||||||
{}
|
{}
|
||||||
list_node() /* For end_of_list */
|
list_node() /* For end_of_list */
|
||||||
{
|
{
|
||||||
info=0;
|
info= 0;
|
||||||
next= this;
|
next= this;
|
||||||
}
|
}
|
||||||
friend class base_list;
|
|
||||||
friend class base_list_iterator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -96,11 +99,56 @@ public:
|
|||||||
|
|
||||||
inline void empty() { elements=0; first= &end_of_list; last=&first;}
|
inline void empty() { elements=0; first= &end_of_list; last=&first;}
|
||||||
inline base_list() { empty(); }
|
inline base_list() { empty(); }
|
||||||
|
/**
|
||||||
|
This is a shallow copy constructor that implicitly passes the ownership
|
||||||
|
from the source list to the new instance. The old instance is not
|
||||||
|
updated, so both objects end up sharing the same nodes. If one of
|
||||||
|
the instances then adds or removes a node, the other becomes out of
|
||||||
|
sync ('last' pointer), while still operational. Some old code uses and
|
||||||
|
relies on this behaviour. This logic is quite tricky: please do not use
|
||||||
|
it in any new code.
|
||||||
|
*/
|
||||||
inline base_list(const base_list &tmp) :Sql_alloc()
|
inline base_list(const base_list &tmp) :Sql_alloc()
|
||||||
{
|
{
|
||||||
elements=tmp.elements;
|
elements= tmp.elements;
|
||||||
first=tmp.first;
|
first= tmp.first;
|
||||||
last=tmp.last;
|
last= elements ? tmp.last : &first;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
Construct a deep copy of the argument in memory root mem_root.
|
||||||
|
The elements themselves are copied by pointer.
|
||||||
|
*/
|
||||||
|
inline 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;
|
||||||
}
|
}
|
||||||
inline base_list(bool error) { }
|
inline base_list(bool error) { }
|
||||||
inline bool push_back(void *info)
|
inline bool push_back(void *info)
|
||||||
@@ -327,6 +375,8 @@ template <class T> class List :public base_list
|
|||||||
public:
|
public:
|
||||||
inline List() :base_list() {}
|
inline List() :base_list() {}
|
||||||
inline List(const List<T> &tmp) :base_list(tmp) {}
|
inline List(const List<T> &tmp) :base_list(tmp) {}
|
||||||
|
inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
|
||||||
|
base_list(tmp, mem_root) {}
|
||||||
inline bool push_back(T *a) { return base_list::push_back(a); }
|
inline bool push_back(T *a) { return base_list::push_back(a); }
|
||||||
inline bool push_front(T *a) { return base_list::push_front(a); }
|
inline bool push_front(T *a) { return base_list::push_front(a); }
|
||||||
inline T* head() {return (T*) base_list::head(); }
|
inline T* head() {return (T*) base_list::head(); }
|
||||||
|
|||||||
202
sql/sql_parse.cc
202
sql/sql_parse.cc
@@ -2478,6 +2478,22 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
/* Skip first table, which is the table we are creating */
|
/* Skip first table, which is the table we are creating */
|
||||||
TABLE_LIST *create_table, *create_table_local;
|
TABLE_LIST *create_table, *create_table_local;
|
||||||
|
/*
|
||||||
|
Code below (especially in mysql_create_table() and select_create
|
||||||
|
methods) may modify HA_CREATE_INFO structure in LEX, so we have to
|
||||||
|
use a copy of this structure to make execution prepared statement-
|
||||||
|
safe. A shallow copy is enough as this code won't modify any memory
|
||||||
|
referenced from this structure.
|
||||||
|
*/
|
||||||
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
|
||||||
|
if (thd->is_fatal_error)
|
||||||
|
{
|
||||||
|
/* out of memory when creating a copy of alter_info */
|
||||||
|
res= 1;
|
||||||
|
goto unsent_create_error;
|
||||||
|
}
|
||||||
tables= lex->unlink_first_table(tables, &create_table,
|
tables= lex->unlink_first_table(tables, &create_table,
|
||||||
&create_table_local);
|
&create_table_local);
|
||||||
|
|
||||||
@@ -2485,12 +2501,12 @@ mysql_execute_command(THD *thd)
|
|||||||
goto unsent_create_error;
|
goto unsent_create_error;
|
||||||
|
|
||||||
#ifndef HAVE_READLINK
|
#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= NULL;
|
||||||
#else
|
#else
|
||||||
/* Fix names if symlinked tables */
|
/* 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->real_name) ||
|
create_table->real_name) ||
|
||||||
append_file_to_dir(thd,&lex->create_info.index_file_name,
|
append_file_to_dir(thd, &create_info.index_file_name,
|
||||||
create_table->real_name))
|
create_table->real_name))
|
||||||
{
|
{
|
||||||
res=-1;
|
res=-1;
|
||||||
@@ -2501,14 +2517,14 @@ mysql_execute_command(THD *thd)
|
|||||||
If we are using SET CHARSET without DEFAULT, add an implicite
|
If we are using SET CHARSET without DEFAULT, add an implicite
|
||||||
DEFAULT to not confuse old users. (This may change).
|
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_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
|
||||||
HA_CREATE_USED_CHARSET)
|
HA_CREATE_USED_CHARSET)
|
||||||
{
|
{
|
||||||
lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
||||||
lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||||
lex->create_info.default_table_charset= lex->create_info.table_charset;
|
create_info.default_table_charset= create_info.table_charset;
|
||||||
lex->create_info.table_charset= 0;
|
create_info.table_charset= 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
The create-select command will open and read-lock the select table
|
The create-select command will open and read-lock the select table
|
||||||
@@ -2542,11 +2558,14 @@ mysql_execute_command(THD *thd)
|
|||||||
if (!(res=open_and_lock_tables(thd,tables)))
|
if (!(res=open_and_lock_tables(thd,tables)))
|
||||||
{
|
{
|
||||||
res= -1; // If error
|
res= -1; // If error
|
||||||
|
/*
|
||||||
|
select_create is currently not re-execution friendly and
|
||||||
|
needs to be created for every execution of a PS/SP.
|
||||||
|
*/
|
||||||
if ((result=new select_create(create_table->db,
|
if ((result=new select_create(create_table->db,
|
||||||
create_table->real_name,
|
create_table->real_name,
|
||||||
&lex->create_info,
|
&create_info,
|
||||||
lex->create_list,
|
&alter_info,
|
||||||
lex->key_list,
|
|
||||||
select_lex->item_list, lex->duplicates,
|
select_lex->item_list, lex->duplicates,
|
||||||
lex->ignore)))
|
lex->ignore)))
|
||||||
{
|
{
|
||||||
@@ -2558,22 +2577,18 @@ mysql_execute_command(THD *thd)
|
|||||||
res=handle_select(thd, lex, result);
|
res=handle_select(thd, lex, result);
|
||||||
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
select_lex->resolve_mode= SELECT_LEX::NOMATTER_MODE;
|
||||||
}
|
}
|
||||||
//reset for PS
|
|
||||||
lex->create_list.empty();
|
|
||||||
lex->key_list.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // regular create
|
else // regular create
|
||||||
{
|
{
|
||||||
if (lex->name)
|
if (lex->name)
|
||||||
res= mysql_create_like_table(thd, create_table, &lex->create_info,
|
res= mysql_create_like_table(thd, create_table, &create_info,
|
||||||
(Table_ident *)lex->name);
|
(Table_ident *)lex->name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res= mysql_create_table(thd,create_table->db,
|
res= mysql_create_table(thd, create_table->db,
|
||||||
create_table->real_name, &lex->create_info,
|
create_table->real_name, &create_info,
|
||||||
lex->create_list,
|
&alter_info, 0, 0);
|
||||||
lex->key_list,0,0);
|
|
||||||
}
|
}
|
||||||
if (!res)
|
if (!res)
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
@@ -2591,15 +2606,48 @@ unsent_create_error:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_CREATE_INDEX:
|
case SQLCOM_CREATE_INDEX:
|
||||||
|
/* Fall through */
|
||||||
|
case SQLCOM_DROP_INDEX:
|
||||||
|
/*
|
||||||
|
CREATE INDEX and DROP INDEX are implemented by calling ALTER
|
||||||
|
TABLE with proper arguments. This isn't very fast but it
|
||||||
|
should work for most cases.
|
||||||
|
|
||||||
|
In the future ALTER TABLE will notice that only added
|
||||||
|
indexes and create these one by one for the existing table
|
||||||
|
without having to do a full rebuild.
|
||||||
|
|
||||||
|
One should normally create all indexes with CREATE TABLE or
|
||||||
|
ALTER TABLE.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
HA_CREATE_INFO create_info;
|
||||||
|
|
||||||
|
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info*/
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (check_one_table_access(thd, INDEX_ACL, tables))
|
if (check_one_table_access(thd, INDEX_ACL, tables))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
res= -1;
|
goto error;
|
||||||
else
|
/*
|
||||||
res = mysql_create_index(thd, tables, lex->key_list);
|
Currently CREATE INDEX or DROP INDEX cause a full table rebuild
|
||||||
break;
|
and thus classify as slow administrative statements just like
|
||||||
|
ALTER TABLE.
|
||||||
|
*/
|
||||||
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
|
|
||||||
|
bzero((char*) &create_info, sizeof(create_info));
|
||||||
|
create_info.db_type= DB_TYPE_DEFAULT;
|
||||||
|
create_info.default_table_charset= thd->variables.collation_database;
|
||||||
|
|
||||||
|
res= mysql_alter_table(thd, tables->db, tables->real_name,
|
||||||
|
&create_info, tables, &alter_info,
|
||||||
|
0, (ORDER*)0, DUP_ERROR, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
case SQLCOM_SLAVE_START:
|
case SQLCOM_SLAVE_START:
|
||||||
{
|
{
|
||||||
@@ -2642,6 +2690,17 @@ unsent_create_error:
|
|||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
ulong priv=0;
|
ulong priv=0;
|
||||||
|
/*
|
||||||
|
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
|
||||||
|
so we have to use a copy of this structure to make execution
|
||||||
|
prepared statement- safe. A shallow copy is enough as no memory
|
||||||
|
referenced from this structure will be modified.
|
||||||
|
*/
|
||||||
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
|
||||||
|
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
|
||||||
|
goto error;
|
||||||
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
|
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
|
||||||
{
|
{
|
||||||
net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
|
net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
|
||||||
@@ -2655,7 +2714,7 @@ unsent_create_error:
|
|||||||
default database if the new name is not explicitly qualified
|
default database if the new name is not explicitly qualified
|
||||||
by a database. (Bug #11493)
|
by a database. (Bug #11493)
|
||||||
*/
|
*/
|
||||||
if (lex->alter_info.flags & ALTER_RENAME)
|
if (alter_info.flags & ALTER_RENAME)
|
||||||
{
|
{
|
||||||
if (! thd->db)
|
if (! thd->db)
|
||||||
{
|
{
|
||||||
@@ -2671,7 +2730,7 @@ unsent_create_error:
|
|||||||
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
|
check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0)||
|
||||||
check_merge_table_access(thd, tables->db,
|
check_merge_table_access(thd, tables->db,
|
||||||
(TABLE_LIST *)
|
(TABLE_LIST *)
|
||||||
lex->create_info.merge_list.first))
|
create_info.merge_list.first))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
if (grant_option)
|
if (grant_option)
|
||||||
{
|
{
|
||||||
@@ -2690,13 +2749,13 @@ unsent_create_error:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Don't yet allow changing of symlinks with ALTER TABLE */
|
/* 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,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||||
"DATA DIRECTORY option ignored");
|
"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,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||||
"INDEX DIRECTORY option ignored");
|
"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= NULL;
|
||||||
/* ALTER TABLE ends previous transaction */
|
/* ALTER TABLE ends previous transaction */
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
res= -1;
|
res= -1;
|
||||||
@@ -2704,12 +2763,12 @@ unsent_create_error:
|
|||||||
{
|
{
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||||
&lex->create_info,
|
&create_info,
|
||||||
tables, lex->create_list,
|
tables,
|
||||||
lex->key_list,
|
&alter_info,
|
||||||
select_lex->order_list.elements,
|
select_lex->order_list.elements,
|
||||||
(ORDER *) select_lex->order_list.first,
|
(ORDER *) select_lex->order_list.first,
|
||||||
lex->duplicates, lex->ignore, &lex->alter_info);
|
lex->duplicates, lex->ignore);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2846,7 +2905,7 @@ unsent_create_error:
|
|||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
||||||
mysql_recreate_table(thd, tables, 1) :
|
mysql_recreate_table(thd, tables) :
|
||||||
mysql_optimize_table(thd, tables, &lex->check_opt);
|
mysql_optimize_table(thd, tables, &lex->check_opt);
|
||||||
/* ! we write after unlocking the table */
|
/* ! we write after unlocking the table */
|
||||||
if (!res && !lex->no_write_to_binlog)
|
if (!res && !lex->no_write_to_binlog)
|
||||||
@@ -3123,14 +3182,6 @@ unsent_create_error:
|
|||||||
res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
|
res= mysql_rm_table(thd,tables,lex->drop_if_exists, lex->drop_temporary);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQLCOM_DROP_INDEX:
|
|
||||||
if (check_one_table_access(thd, INDEX_ACL, tables))
|
|
||||||
goto error; /* purecov: inspected */
|
|
||||||
if (end_active_trans(thd))
|
|
||||||
res= -1;
|
|
||||||
else
|
|
||||||
res = mysql_drop_index(thd, tables, &lex->alter_info);
|
|
||||||
break;
|
|
||||||
case SQLCOM_SHOW_DATABASES:
|
case SQLCOM_SHOW_DATABASES:
|
||||||
#if defined(DONT_ALLOW_SHOW_COMMANDS)
|
#if defined(DONT_ALLOW_SHOW_COMMANDS)
|
||||||
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
|
||||||
@@ -3363,6 +3414,12 @@ purposes internal to the MySQL server", MYF(0));
|
|||||||
break;
|
break;
|
||||||
case SQLCOM_CREATE_DB:
|
case SQLCOM_CREATE_DB:
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
As mysql_create_db() may modify HA_CREATE_INFO structure passed to
|
||||||
|
it, we need to use a copy of LEX::create_info to make execution
|
||||||
|
prepared statement- safe.
|
||||||
|
*/
|
||||||
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
{
|
{
|
||||||
res= -1;
|
res= -1;
|
||||||
@@ -3393,7 +3450,7 @@ purposes internal to the MySQL server", MYF(0));
|
|||||||
if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
|
if (check_access(thd,CREATE_ACL,lex->name,0,1,0))
|
||||||
break;
|
break;
|
||||||
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
|
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
|
||||||
&lex->create_info, 0);
|
&create_info, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_DROP_DB:
|
case SQLCOM_DROP_DB:
|
||||||
@@ -4443,14 +4500,16 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
if (type_modifier & PRI_KEY_FLAG)
|
if (type_modifier & PRI_KEY_FLAG)
|
||||||
{
|
{
|
||||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||||
lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
|
lex->alter_info.key_list.push_back(new Key(Key::PRIMARY, NullS,
|
||||||
0, lex->col_list));
|
HA_KEY_ALG_UNDEF, 0,
|
||||||
|
lex->col_list));
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
}
|
}
|
||||||
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
||||||
{
|
{
|
||||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||||
lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
|
lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
|
||||||
|
HA_KEY_ALG_UNDEF, 0,
|
||||||
lex->col_list));
|
lex->col_list));
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
}
|
}
|
||||||
@@ -4778,7 +4837,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||||||
new_field->sql_type,
|
new_field->sql_type,
|
||||||
new_field->length);
|
new_field->length);
|
||||||
new_field->char_length= new_field->length;
|
new_field->char_length= new_field->length;
|
||||||
lex->create_list.push_back(new_field);
|
lex->alter_info.create_list.push_back(new_field);
|
||||||
lex->last_field=new_field;
|
lex->last_field=new_field;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@@ -5458,57 +5517,6 @@ Item * all_any_subquery_creator(Item *left_expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
|
|
||||||
the proper arguments. This isn't very fast but it should work for most
|
|
||||||
cases.
|
|
||||||
|
|
||||||
In the future ALTER TABLE will notice that only added indexes
|
|
||||||
and create these one by one for the existing table without having to do
|
|
||||||
a full rebuild.
|
|
||||||
|
|
||||||
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
|
|
||||||
{
|
|
||||||
List<create_field> fields;
|
|
||||||
ALTER_INFO alter_info;
|
|
||||||
alter_info.flags= ALTER_ADD_INDEX;
|
|
||||||
alter_info.is_simple= 0;
|
|
||||||
HA_CREATE_INFO create_info;
|
|
||||||
DBUG_ENTER("mysql_create_index");
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
|
||||||
create_info.default_table_charset= thd->variables.collation_database;
|
|
||||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
|
||||||
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
|
|
||||||
&create_info, table_list,
|
|
||||||
fields, keys, 0, (ORDER*)0,
|
|
||||||
DUP_ERROR, 0, &alter_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
|
|
||||||
{
|
|
||||||
List<create_field> fields;
|
|
||||||
List<Key> keys;
|
|
||||||
HA_CREATE_INFO create_info;
|
|
||||||
DBUG_ENTER("mysql_drop_index");
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
|
||||||
create_info.default_table_charset= thd->variables.collation_database;
|
|
||||||
create_info.row_type= ROW_TYPE_NOT_USED;
|
|
||||||
alter_info->clear();
|
|
||||||
alter_info->flags= ALTER_DROP_INDEX;
|
|
||||||
alter_info->is_simple= 0;
|
|
||||||
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
|
|
||||||
&create_info, table_list,
|
|
||||||
fields, keys, 0, (ORDER*)0,
|
|
||||||
DUP_ERROR, 0, alter_info));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Multi update query pre-check
|
Multi update query pre-check
|
||||||
|
|
||||||
|
|||||||
@@ -845,7 +845,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int mysqld_show_create_db(THD *thd, char *dbname,
|
int mysqld_show_create_db(THD *thd, char *dbname,
|
||||||
HA_CREATE_INFO *create_info)
|
const HA_CREATE_INFO *create_info)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
char path[FN_REFLEN];
|
char path[FN_REFLEN];
|
||||||
|
|||||||
349
sql/sql_table.cc
349
sql/sql_table.cc
@@ -456,8 +456,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
|||||||
mysql_prepare_table()
|
mysql_prepare_table()
|
||||||
thd Thread object
|
thd Thread object
|
||||||
create_info Create information (like MAX_ROWS)
|
create_info Create information (like MAX_ROWS)
|
||||||
fields List of fields to create
|
alter_info List of columns and indexes to create
|
||||||
keys List of keys to create
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Prepares the table and key structures for table creation.
|
Prepares the table and key structures for table creation.
|
||||||
@@ -468,8 +467,8 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields,
|
Alter_info *alter_info,
|
||||||
List<Key> &keys, bool tmp_table, uint &db_options,
|
bool tmp_table, uint &db_options,
|
||||||
handler *file, KEY *&key_info_buffer,
|
handler *file, KEY *&key_info_buffer,
|
||||||
uint *key_count, int select_field_count)
|
uint *key_count, int select_field_count)
|
||||||
{
|
{
|
||||||
@@ -482,10 +481,11 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
int timestamps= 0, timestamps_with_niladic= 0;
|
int timestamps= 0, timestamps_with_niladic= 0;
|
||||||
int field_no,dup_no;
|
int field_no,dup_no;
|
||||||
int select_field_pos,auto_increment=0;
|
int select_field_pos,auto_increment=0;
|
||||||
|
List_iterator<create_field> it(alter_info->create_list);
|
||||||
|
List_iterator<create_field> it2(alter_info->create_list);
|
||||||
DBUG_ENTER("mysql_prepare_table");
|
DBUG_ENTER("mysql_prepare_table");
|
||||||
|
|
||||||
List_iterator<create_field> it(fields),it2(fields);
|
select_field_pos= alter_info->create_list.elements - select_field_count;
|
||||||
select_field_pos=fields.elements - select_field_count;
|
|
||||||
null_fields=blob_columns=0;
|
null_fields=blob_columns=0;
|
||||||
|
|
||||||
for (field_no=0; (sql_field=it++) ; field_no++)
|
for (field_no=0; (sql_field=it++) ; field_no++)
|
||||||
@@ -883,7 +883,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
|
|
||||||
/* Create keys */
|
/* Create keys */
|
||||||
|
|
||||||
List_iterator<Key> key_iterator(keys), key_iterator2(keys);
|
List_iterator<Key> key_iterator(alter_info->key_list);
|
||||||
|
List_iterator<Key> key_iterator2(alter_info->key_list);
|
||||||
uint key_parts=0, fk_key_count=0;
|
uint key_parts=0, fk_key_count=0;
|
||||||
bool primary_key=0,unique_key=0;
|
bool primary_key=0,unique_key=0;
|
||||||
Key *key, *key2;
|
Key *key, *key2;
|
||||||
@@ -1336,20 +1337,24 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
thd Thread object
|
thd Thread object
|
||||||
db Database
|
db Database
|
||||||
table_name Table name
|
table_name Table name
|
||||||
create_info Create information (like MAX_ROWS)
|
create_info [in/out] Create information (like MAX_ROWS)
|
||||||
fields List of fields to create
|
alter_info [in/out] List of columns and indexes to create
|
||||||
keys List of keys to create
|
|
||||||
tmp_table Set to 1 if this is an internal temporary table
|
tmp_table Set to 1 if this is an internal temporary table
|
||||||
(From ALTER TABLE)
|
(From ALTER TABLE)
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
If one creates a temporary table, this is automaticly opened
|
If one creates a temporary table, this is automatically opened
|
||||||
|
|
||||||
no_log is needed for the case of CREATE ... SELECT,
|
no_log is needed for the case of CREATE ... SELECT,
|
||||||
as the logging will be done later in sql_insert.cc
|
as the logging will be done later in sql_insert.cc
|
||||||
select_field_count is also used for CREATE ... SELECT,
|
select_field_count is also used for CREATE ... SELECT,
|
||||||
and must be zero for standard create of table.
|
and must be zero for standard create of table.
|
||||||
|
|
||||||
|
Note that structures passed as 'create_info' and 'alter_info' parameters
|
||||||
|
may be modified by this function. It is responsibility of the caller to
|
||||||
|
make a copy of create_info in order to provide correct execution in
|
||||||
|
prepared statements/stored routines.
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
0 ok
|
0 ok
|
||||||
-1 error
|
-1 error
|
||||||
@@ -1357,8 +1362,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
|
|
||||||
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields,
|
Alter_info *alter_info,
|
||||||
List<Key> &keys,bool tmp_table,
|
bool tmp_table,
|
||||||
uint select_field_count)
|
uint select_field_count)
|
||||||
{
|
{
|
||||||
char path[FN_REFLEN];
|
char path[FN_REFLEN];
|
||||||
@@ -1371,7 +1376,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||||||
DBUG_ENTER("mysql_create_table");
|
DBUG_ENTER("mysql_create_table");
|
||||||
|
|
||||||
/* Check for duplicate fields and check type of table to create */
|
/* Check for duplicate fields and check type of table to create */
|
||||||
if (!fields.elements)
|
if (!alter_info->create_list.elements)
|
||||||
{
|
{
|
||||||
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
|
my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@@ -1423,8 +1428,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||||||
create_info->default_table_charset= db_info.default_table_charset;
|
create_info->default_table_charset= db_info.default_table_charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mysql_prepare_table(thd, create_info, fields,
|
if (mysql_prepare_table(thd, create_info, alter_info, tmp_table,
|
||||||
keys, tmp_table, db_options, file,
|
db_options, file,
|
||||||
key_info_buffer, &key_count,
|
key_info_buffer, &key_count,
|
||||||
select_field_count))
|
select_field_count))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@@ -1503,8 +1508,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
|
|||||||
create_info->table_options=db_options;
|
create_info->table_options=db_options;
|
||||||
|
|
||||||
if (rea_create_table(thd, path, db, table_name,
|
if (rea_create_table(thd, path, db, table_name,
|
||||||
create_info, fields, key_count,
|
create_info, alter_info->create_list,
|
||||||
key_info_buffer))
|
key_count, key_info_buffer))
|
||||||
goto end;
|
goto end;
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
{
|
{
|
||||||
@@ -1592,8 +1597,7 @@ make_unique_key_name(const char *field_name,KEY *start,KEY *end)
|
|||||||
|
|
||||||
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
const char *db, const char *name,
|
const char *db, const char *name,
|
||||||
List<create_field> *extra_fields,
|
Alter_info *alter_info,
|
||||||
List<Key> *keys,
|
|
||||||
List<Item> *items,
|
List<Item> *items,
|
||||||
MYSQL_LOCK **lock)
|
MYSQL_LOCK **lock)
|
||||||
{
|
{
|
||||||
@@ -1627,7 +1631,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
((Item_field *)item)->field :
|
((Item_field *)item)->field :
|
||||||
(Field*) 0))))
|
(Field*) 0))))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
extra_fields->push_back(cr_field);
|
alter_info->create_list.push_back(cr_field);
|
||||||
}
|
}
|
||||||
/* create and lock table */
|
/* create and lock table */
|
||||||
/* QQ: create and open should be done atomic ! */
|
/* QQ: create and open should be done atomic ! */
|
||||||
@@ -1641,8 +1645,8 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
open_table().
|
open_table().
|
||||||
*/
|
*/
|
||||||
tmp_disable_binlog(thd);
|
tmp_disable_binlog(thd);
|
||||||
if (!mysql_create_table(thd,db,name,create_info,*extra_fields,
|
if (!mysql_create_table(thd, db, name, create_info, alter_info,
|
||||||
*keys,0,select_field_count))
|
0, select_field_count))
|
||||||
{
|
{
|
||||||
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
|
if (!(table=open_table(thd,db,name,name,(bool*) 0)))
|
||||||
quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
|
quick_rm_table(create_info->db_type,db,table_case_name(create_info,name));
|
||||||
@@ -2146,6 +2150,7 @@ send_result_message:
|
|||||||
|
|
||||||
case HA_ADMIN_TRY_ALTER:
|
case HA_ADMIN_TRY_ALTER:
|
||||||
{
|
{
|
||||||
|
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||||
/*
|
/*
|
||||||
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
||||||
"try with alter", so here we close the table, do an ALTER TABLE,
|
"try with alter", so here we close the table, do an ALTER TABLE,
|
||||||
@@ -2155,7 +2160,9 @@ send_result_message:
|
|||||||
TABLE_LIST *save_next= table->next;
|
TABLE_LIST *save_next= table->next;
|
||||||
table->next= 0;
|
table->next= 0;
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||||
result_code= mysql_recreate_table(thd, table, 0);
|
thd->net.no_send_ok= TRUE;
|
||||||
|
result_code= mysql_recreate_table(thd, table);
|
||||||
|
thd->net.no_send_ok= save_no_send_ok;
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
if (!result_code) // recreation went ok
|
if (!result_code) // recreation went ok
|
||||||
@@ -2635,206 +2642,6 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOT_USED
|
|
||||||
/*
|
|
||||||
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
|
|
||||||
the proper arguments. This isn't very fast but it should work for most
|
|
||||||
cases.
|
|
||||||
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
|
|
||||||
{
|
|
||||||
List<create_field> fields;
|
|
||||||
List<Alter_drop> drop;
|
|
||||||
List<Alter_column> alter;
|
|
||||||
HA_CREATE_INFO create_info;
|
|
||||||
int rc;
|
|
||||||
uint idx;
|
|
||||||
uint db_options;
|
|
||||||
uint key_count;
|
|
||||||
TABLE *table;
|
|
||||||
Field **f_ptr;
|
|
||||||
KEY *key_info_buffer;
|
|
||||||
char path[FN_REFLEN+1];
|
|
||||||
DBUG_ENTER("mysql_create_index");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Try to use online generation of index.
|
|
||||||
This requires that all indexes can be created online.
|
|
||||||
Otherwise, the old alter table procedure is executed.
|
|
||||||
|
|
||||||
Open the table to have access to the correct table handler.
|
|
||||||
*/
|
|
||||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
The add_index method takes an array of KEY structs for the new indexes.
|
|
||||||
Preparing a new table structure generates this array.
|
|
||||||
It needs a list with all fields of the table, which does not need to
|
|
||||||
be correct in every respect. The field names are important.
|
|
||||||
*/
|
|
||||||
for (f_ptr= table->field; *f_ptr; f_ptr++)
|
|
||||||
{
|
|
||||||
create_field *c_fld= new create_field(*f_ptr, *f_ptr);
|
|
||||||
c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
|
|
||||||
fields.push_back(c_fld);
|
|
||||||
}
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
|
||||||
create_info.default_table_charset= thd->variables.collation_database;
|
|
||||||
db_options= 0;
|
|
||||||
if (mysql_prepare_table(thd, &create_info, fields,
|
|
||||||
keys, /*tmp_table*/ 0, db_options, table->file,
|
|
||||||
key_info_buffer, key_count,
|
|
||||||
/*select_field_count*/ 0))
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if all keys can be generated with the add_index method.
|
|
||||||
If anyone cannot, then take the old way.
|
|
||||||
*/
|
|
||||||
for (idx=0; idx< key_count; idx++)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
|
|
||||||
if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
|
|
||||||
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
if ((idx < key_count)|| !key_count)
|
|
||||||
{
|
|
||||||
/* Re-initialize the create_info, which was changed by prepare table. */
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
|
||||||
create_info.default_table_charset= thd->variables.collation_database;
|
|
||||||
/* Cleanup the fields list. We do not want to create existing fields. */
|
|
||||||
fields.delete_elements();
|
|
||||||
if (real_alter_table(thd, table_list->db, table_list->real_name,
|
|
||||||
&create_info, table_list, table,
|
|
||||||
fields, keys, drop, alter, 0, (ORDER*)0,
|
|
||||||
ALTER_ADD_INDEX, DUP_ERROR))
|
|
||||||
/* Don't need to free((gptr) key_info_buffer);*/
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (table->file->add_index(table, key_info_buffer, key_count)||
|
|
||||||
build_table_path(path, sizeof(path), table_list->db,
|
|
||||||
(lower_case_table_names == 2) ?
|
|
||||||
table_list->alias : table_list->real_name,
|
|
||||||
reg_ext) == 0 ||
|
|
||||||
mysql_create_frm(thd, path, &create_info,
|
|
||||||
fields, key_count, key_info_buffer, table->file))
|
|
||||||
/* don't need to free((gptr) key_info_buffer);*/
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
/* don't need to free((gptr) key_info_buffer);*/
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
|
|
||||||
List<Alter_drop> &drop)
|
|
||||||
{
|
|
||||||
List<create_field> fields;
|
|
||||||
List<Key> keys;
|
|
||||||
List<Alter_column> alter;
|
|
||||||
HA_CREATE_INFO create_info;
|
|
||||||
uint idx;
|
|
||||||
uint db_options;
|
|
||||||
uint key_count;
|
|
||||||
uint *key_numbers;
|
|
||||||
TABLE *table;
|
|
||||||
Field **f_ptr;
|
|
||||||
KEY *key_info;
|
|
||||||
KEY *key_info_buffer;
|
|
||||||
char path[FN_REFLEN];
|
|
||||||
DBUG_ENTER("mysql_drop_index");
|
|
||||||
|
|
||||||
/*
|
|
||||||
Try to use online generation of index.
|
|
||||||
This requires that all indexes can be created online.
|
|
||||||
Otherwise, the old alter table procedure is executed.
|
|
||||||
|
|
||||||
Open the table to have access to the correct table handler.
|
|
||||||
*/
|
|
||||||
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
The drop_index method takes an array of key numbers.
|
|
||||||
It cannot get more entries than keys in the table.
|
|
||||||
*/
|
|
||||||
key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
|
|
||||||
key_count= 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Get the number of each key and check if it can be created online.
|
|
||||||
*/
|
|
||||||
List_iterator<Alter_drop> drop_it(drop);
|
|
||||||
Alter_drop *drop_key;
|
|
||||||
while ((drop_key= drop_it++))
|
|
||||||
{
|
|
||||||
/* Find the key in the table. */
|
|
||||||
key_info=table->key_info;
|
|
||||||
for (idx=0; idx< table->keys; idx++, key_info++)
|
|
||||||
{
|
|
||||||
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (idx>= table->keys)
|
|
||||||
{
|
|
||||||
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
|
|
||||||
/*don't need to free((gptr) key_numbers);*/
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
Check if the key can be generated with the add_index method.
|
|
||||||
If anyone cannot, then take the old way.
|
|
||||||
*/
|
|
||||||
DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
|
|
||||||
if (!(table->file->index_ddl_flags(table->key_info+idx)&
|
|
||||||
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
|
|
||||||
break ;
|
|
||||||
key_numbers[key_count++]= idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
|
||||||
create_info.default_table_charset= thd->variables.collation_database;
|
|
||||||
|
|
||||||
if ((drop_key)|| (drop.elements<= 0))
|
|
||||||
{
|
|
||||||
if (real_alter_table(thd, table_list->db, table_list->real_name,
|
|
||||||
&create_info, table_list, table,
|
|
||||||
fields, keys, drop, alter, 0, (ORDER*)0,
|
|
||||||
ALTER_DROP_INDEX, DUP_ERROR))
|
|
||||||
/*don't need to free((gptr) key_numbers);*/
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
db_options= 0;
|
|
||||||
if (table->file->drop_index(table, key_numbers, key_count)||
|
|
||||||
mysql_prepare_table(thd, &create_info, fields,
|
|
||||||
keys, /*tmp_table*/ 0, db_options, table->file,
|
|
||||||
key_info_buffer, key_count,
|
|
||||||
/*select_field_count*/ 0)||
|
|
||||||
build_table_path(path, sizeof(path), table_list->db,
|
|
||||||
(lower_case_table_names == 2) ?
|
|
||||||
table_list->alias : table_list->real_name,
|
|
||||||
reg_ext) == 0 ||
|
|
||||||
mysql_create_frm(thd, path, &create_info,
|
|
||||||
fields, key_count, key_info_buffer, table->file))
|
|
||||||
/*don't need to free((gptr) key_numbers);*/
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*don't need to free((gptr) key_numbers);*/
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
#endif /* NOT_USED */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2887,15 +2694,21 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Alter table
|
Alter table
|
||||||
|
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
The structures passed as 'create_info' and 'alter_info' parameters may
|
||||||
|
be modified by this function. It is responsibility of the caller to make
|
||||||
|
a copy of create_info in order to provide correct execution in prepared
|
||||||
|
statements/stored routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
List<create_field> &fields, List<Key> &keys,
|
Alter_info *alter_info,
|
||||||
uint order_num, ORDER *order,
|
uint order_num, ORDER *order,
|
||||||
enum enum_duplicates handle_duplicates, bool ignore,
|
enum enum_duplicates handle_duplicates, bool ignore)
|
||||||
ALTER_INFO *alter_info, bool do_send_ok)
|
|
||||||
{
|
{
|
||||||
TABLE *table,*new_table;
|
TABLE *table,*new_table;
|
||||||
int error;
|
int error;
|
||||||
@@ -3064,7 +2877,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
if (do_send_ok)
|
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
}
|
}
|
||||||
else if (error > 0)
|
else if (error > 0)
|
||||||
@@ -3091,10 +2903,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
|
|
||||||
restore_record(table,default_values); // Empty record for DEFAULT
|
restore_record(table,default_values); // Empty record for DEFAULT
|
||||||
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
||||||
List_iterator<create_field> def_it(fields);
|
List_iterator<create_field> def_it(alter_info->create_list);
|
||||||
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
||||||
List<create_field> create_list; // Add new fields here
|
Alter_info new_info; // Add new columns and indexes here
|
||||||
List<Key> key_list; // Add new keys here
|
|
||||||
create_field *def;
|
create_field *def;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3140,13 +2951,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
def->field=field;
|
def->field=field;
|
||||||
if (!def->after)
|
if (!def->after)
|
||||||
{
|
{
|
||||||
create_list.push_back(def);
|
new_info.create_list.push_back(def);
|
||||||
def_it.remove();
|
def_it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Use old field value
|
{ // Use old field value
|
||||||
create_list.push_back(def=new create_field(field,field));
|
new_info.create_list.push_back(def= new create_field(field, field));
|
||||||
alter_it.rewind(); // Change default if ALTER
|
alter_it.rewind(); // Change default if ALTER
|
||||||
Alter_column *alter;
|
Alter_column *alter;
|
||||||
while ((alter=alter_it++))
|
while ((alter=alter_it++))
|
||||||
@@ -3167,7 +2978,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
def_it.rewind();
|
def_it.rewind();
|
||||||
List_iterator<create_field> find_it(create_list);
|
List_iterator<create_field> find_it(new_info.create_list);
|
||||||
while ((def=def_it++)) // Add new columns
|
while ((def=def_it++)) // Add new columns
|
||||||
{
|
{
|
||||||
if (def->change && ! def->field)
|
if (def->change && ! def->field)
|
||||||
@@ -3176,9 +2987,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
if (!def->after)
|
if (!def->after)
|
||||||
create_list.push_back(def);
|
new_info.create_list.push_back(def);
|
||||||
else if (def->after == first_keyword)
|
else if (def->after == first_keyword)
|
||||||
create_list.push_front(def);
|
new_info.create_list.push_front(def);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
create_field *find;
|
create_field *find;
|
||||||
@@ -3202,7 +3013,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
table_name);
|
table_name);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
if (!create_list.elements)
|
if (!new_info.create_list.elements)
|
||||||
{
|
{
|
||||||
my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
|
my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@@ -3213,8 +3024,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
for which some fields exists.
|
for which some fields exists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
List_iterator<Key> key_it(keys);
|
List_iterator<Key> key_it(alter_info->key_list);
|
||||||
List_iterator<create_field> field_it(create_list);
|
List_iterator<create_field> field_it(new_info.create_list);
|
||||||
List<key_part_spec> key_parts;
|
List<key_part_spec> key_parts;
|
||||||
|
|
||||||
KEY *key_info=table->key_info;
|
KEY *key_info=table->key_info;
|
||||||
@@ -3272,24 +3083,37 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
key_part_length));
|
key_part_length));
|
||||||
}
|
}
|
||||||
if (key_parts.elements)
|
if (key_parts.elements)
|
||||||
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
|
{
|
||||||
(key_info->flags & HA_NOSAME ?
|
Key *key;
|
||||||
(!my_strcasecmp(system_charset_info,
|
enum Key::Keytype key_type;
|
||||||
key_name, primary_key_name) ?
|
|
||||||
Key::PRIMARY : Key::UNIQUE) :
|
if (key_info->flags & HA_SPATIAL)
|
||||||
(key_info->flags & HA_FULLTEXT ?
|
key_type= Key::SPATIAL;
|
||||||
Key::FULLTEXT : Key::MULTIPLE)),
|
else if (key_info->flags & HA_NOSAME)
|
||||||
key_name,
|
{
|
||||||
|
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
|
||||||
|
key_type= Key::PRIMARY;
|
||||||
|
else
|
||||||
|
key_type= Key::UNIQUE;
|
||||||
|
}
|
||||||
|
else if (key_info->flags & HA_FULLTEXT)
|
||||||
|
key_type= Key::FULLTEXT;
|
||||||
|
else
|
||||||
|
key_type= Key::MULTIPLE;
|
||||||
|
|
||||||
|
key= new Key(key_type, key_name,
|
||||||
key_info->algorithm,
|
key_info->algorithm,
|
||||||
test(key_info->flags & HA_GENERATED_KEY),
|
test(key_info->flags & HA_GENERATED_KEY),
|
||||||
key_parts));
|
key_parts);
|
||||||
|
new_info.key_list.push_back(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
while ((key=key_it++)) // Add new keys
|
while ((key=key_it++)) // Add new keys
|
||||||
{
|
{
|
||||||
if (key->type != Key::FOREIGN_KEY)
|
if (key->type != Key::FOREIGN_KEY)
|
||||||
key_list.push_back(key);
|
new_info.key_list.push_back(key);
|
||||||
if (key->name &&
|
if (key->name &&
|
||||||
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
|
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
|
||||||
{
|
{
|
||||||
@@ -3393,7 +3217,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
/* We don't log the statement, it will be logged later. */
|
/* We don't log the statement, it will be logged later. */
|
||||||
tmp_disable_binlog(thd);
|
tmp_disable_binlog(thd);
|
||||||
error= mysql_create_table(thd, new_db, tmp_name,
|
error= mysql_create_table(thd, new_db, tmp_name,
|
||||||
create_info,create_list,key_list,1,0);
|
create_info, &new_info, 1, 0);
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
if (error)
|
if (error)
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
@@ -3422,7 +3246,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||||||
next_insert_id=thd->next_insert_id; // Remember for loggin
|
next_insert_id=thd->next_insert_id; // Remember for loggin
|
||||||
copied=deleted=0;
|
copied=deleted=0;
|
||||||
if (!new_table->is_view)
|
if (!new_table->is_view)
|
||||||
error=copy_data_between_tables(table,new_table,create_list,
|
error= copy_data_between_tables(table, new_table, new_info.create_list,
|
||||||
handle_duplicates, ignore,
|
handle_duplicates, ignore,
|
||||||
order_num, order, &copied, &deleted,
|
order_num, order, &copied, &deleted,
|
||||||
alter_info->keys_onoff);
|
alter_info->keys_onoff);
|
||||||
@@ -3637,8 +3461,7 @@ end_temporary:
|
|||||||
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
|
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
|
||||||
(ulong) (copied + deleted), (ulong) deleted,
|
(ulong) (copied + deleted), (ulong) deleted,
|
||||||
(ulong) thd->cuted_fields);
|
(ulong) thd->cuted_fields);
|
||||||
if (do_send_ok)
|
send_ok(thd, copied + deleted, 0L, tmp_name);
|
||||||
send_ok(thd,copied+deleted,0L,tmp_name);
|
|
||||||
thd->some_tables_deleted=0;
|
thd->some_tables_deleted=0;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
@@ -3828,30 +3651,26 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||||||
mysql_recreate_table()
|
mysql_recreate_table()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
tables Tables to recreate
|
tables Tables to recreate
|
||||||
do_send_ok If we should send_ok() or leave it to caller
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
Like mysql_alter_table().
|
Like mysql_alter_table().
|
||||||
*/
|
*/
|
||||||
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
int mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
|
||||||
bool do_send_ok)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_recreate_table");
|
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
HA_CREATE_INFO create_info;
|
HA_CREATE_INFO create_info;
|
||||||
lex->create_list.empty();
|
Alter_info alter_info;
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
DBUG_ENTER("mysql_recreate_table");
|
||||||
lex->alter_info.reset();
|
|
||||||
lex->alter_info.is_simple= 0; // Force full recreate
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
bzero((char*) &create_info,sizeof(create_info));
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
create_info.db_type=DB_TYPE_DEFAULT;
|
||||||
create_info.row_type=ROW_TYPE_DEFAULT;
|
create_info.row_type=ROW_TYPE_DEFAULT;
|
||||||
create_info.default_table_charset=default_charset_info;
|
create_info.default_table_charset=default_charset_info;
|
||||||
|
alter_info.is_simple= 0; // Force full recreate
|
||||||
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
|
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
|
||||||
table_list, lex->create_list,
|
table_list, &alter_info,
|
||||||
lex->key_list, 0, (ORDER *) 0,
|
0, (ORDER *) 0, DUP_ERROR, 0));
|
||||||
DUP_ERROR, 0, &lex->alter_info, do_send_ok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1021,8 +1021,7 @@ create:
|
|||||||
TL_READ_NO_INSERT:
|
TL_READ_NO_INSERT:
|
||||||
TL_READ)))
|
TL_READ)))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
lex->alter_info.reset();
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->change=NullS;
|
lex->change=NullS;
|
||||||
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
||||||
@@ -1040,16 +1039,18 @@ create:
|
|||||||
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
|
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
|
||||||
TL_OPTION_UPDATING))
|
TL_OPTION_UPDATING))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
lex->alter_info.reset();
|
||||||
lex->key_list.empty();
|
lex->alter_info.is_simple= 0;
|
||||||
|
lex->alter_info.flags= ALTER_ADD_INDEX;
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->change=NullS;
|
lex->change=NullS;
|
||||||
}
|
}
|
||||||
'(' key_list ')'
|
'(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
Key *key= new Key($2, $4.str, $5, 0, lex->col_list);
|
||||||
|
|
||||||
lex->key_list.push_back(new Key($2,$4.str, $5, 0, lex->col_list));
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
}
|
}
|
||||||
| CREATE DATABASE opt_if_not_exists ident
|
| CREATE DATABASE opt_if_not_exists ident
|
||||||
@@ -1305,29 +1306,34 @@ key_def:
|
|||||||
key_type opt_ident key_alg '(' key_list ')'
|
key_type opt_ident key_alg '(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list));
|
Key *key= new Key($1, $2, $3, 0, lex->col_list);
|
||||||
|
lex->alter_info.key_list.push_back(key);
|
||||||
|
|
||||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
|
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
const char *key_name= $3 ? $3:$1;
|
const char *key_name= $3 ? $3:$1;
|
||||||
lex->key_list.push_back(new Key($2, key_name, $4, 0,
|
Key *key= new Key($2, key_name, $4, 0, lex->col_list);
|
||||||
lex->col_list));
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
|
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->key_list.push_back(new foreign_key($4 ? $4:$1, lex->col_list,
|
const char *key_name= $4 ? $4 : $1;
|
||||||
|
Key *key= new foreign_key(key_name, lex->col_list,
|
||||||
$8,
|
$8,
|
||||||
lex->ref_list,
|
lex->ref_list,
|
||||||
lex->fk_delete_opt,
|
lex->fk_delete_opt,
|
||||||
lex->fk_update_opt,
|
lex->fk_update_opt,
|
||||||
lex->fk_match_option));
|
lex->fk_match_option);
|
||||||
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
|
lex->alter_info.key_list.push_back(key);
|
||||||
|
key= new Key(Key::MULTIPLE, key_name,
|
||||||
HA_KEY_ALG_UNDEF, 1,
|
HA_KEY_ALG_UNDEF, 1,
|
||||||
lex->col_list));
|
lex->col_list);
|
||||||
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| constraint opt_check_constraint
|
| constraint opt_check_constraint
|
||||||
@@ -1850,8 +1856,6 @@ alter:
|
|||||||
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
|
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
|
||||||
TL_OPTION_UPDATING))
|
TL_OPTION_UPDATING))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->select_lex.init_order();
|
lex->select_lex.init_order();
|
||||||
lex->select_lex.db=lex->name=0;
|
lex->select_lex.db=lex->name=0;
|
||||||
@@ -1860,8 +1864,6 @@ alter:
|
|||||||
lex->create_info.default_table_charset= NULL;
|
lex->create_info.default_table_charset= NULL;
|
||||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||||
lex->alter_info.reset();
|
lex->alter_info.reset();
|
||||||
lex->alter_info.is_simple= 1;
|
|
||||||
lex->alter_info.flags= 0;
|
|
||||||
}
|
}
|
||||||
alter_list
|
alter_list
|
||||||
{}
|
{}
|
||||||
@@ -4030,7 +4032,9 @@ drop:
|
|||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command= SQLCOM_DROP_INDEX;
|
lex->sql_command= SQLCOM_DROP_INDEX;
|
||||||
lex->alter_info.drop_list.empty();
|
lex->alter_info.reset();
|
||||||
|
lex->alter_info.is_simple= 0;
|
||||||
|
lex->alter_info.flags= ALTER_DROP_INDEX;
|
||||||
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
||||||
$3.str));
|
$3.str));
|
||||||
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
|
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user