Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
d53072d1
Commit
d53072d1
authored
Jan 15, 2007
by
kostja@bodhi.local
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-4.1-runtime
into bodhi.local:/opt/local/work/mysql-4.1-4968-to-push
parents
a7862496
90072e69
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
512 additions
and
444 deletions
+512
-444
mysql-test/r/ps.result
mysql-test/r/ps.result
+67
-0
mysql-test/t/ps.test
mysql-test/t/ps.test
+72
-0
sql/mysql_priv.h
sql/mysql_priv.h
+7
-12
sql/sql_class.h
sql/sql_class.h
+10
-9
sql/sql_insert.cc
sql/sql_insert.cc
+1
-1
sql/sql_lex.cc
sql/sql_lex.cc
+12
-0
sql/sql_lex.h
sql/sql_lex.h
+48
-8
sql/sql_list.h
sql/sql_list.h
+62
-12
sql/sql_parse.cc
sql/sql_parse.cc
+108
-100
sql/sql_show.cc
sql/sql_show.cc
+1
-1
sql/sql_table.cc
sql/sql_table.cc
+97
-278
sql/sql_yacc.yy
sql/sql_yacc.yy
+27
-23
No files found.
mysql-test/r/ps.result
View file @
d53072d1
...
...
@@ -1035,4 +1035,71 @@ EXECUTE stmt USING @a;
0 0
DEALLOCATE PREPARE stmt;
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.
mysql-test/t/ps.test
View file @
d53072d1
...
...
@@ -1068,5 +1068,77 @@ EXECUTE stmt USING @a;
DEALLOCATE
PREPARE
stmt
;
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
.
sql/mysql_priv.h
View file @
d53072d1
...
...
@@ -563,25 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
uint
&
key_count
,
int
select_field_count
);
int
mysql_create_table
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
,
HA_CREATE_INFO
*
create_info
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
Alter_info
*
alter_info
,
bool
tmp_table
,
uint
select_field_count
);
TABLE
*
create_table_from_items
(
THD
*
thd
,
HA_CREATE_INFO
*
create_info
,
const
char
*
db
,
const
char
*
name
,
List
<
create_field
>
*
extra_fields
,
List
<
Key
>
*
keys
,
Alter_info
*
alter_info
,
List
<
Item
>
*
items
,
MYSQL_LOCK
**
lock
);
int
mysql_alter_table
(
THD
*
thd
,
char
*
new_db
,
char
*
new_name
,
HA_CREATE_INFO
*
create_info
,
TABLE_LIST
*
table_list
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
Alter_info
*
alter_info
,
uint
order_num
,
ORDER
*
order
,
enum
enum_duplicates
handle_duplicates
,
bool
ignore
,
ALTER_INFO
*
alter_info
,
bool
do_send_ok
=
1
);
int
mysql_recreate_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
bool
do_send_ok
);
bool
ignore
);
int
mysql_recreate_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
);
int
mysql_create_like_table
(
THD
*
thd
,
TABLE_LIST
*
table
,
HA_CREATE_INFO
*
create_info
,
Table_ident
*
src_table
);
...
...
@@ -590,9 +587,6 @@ bool mysql_rename_table(enum db_type base,
const
char
*
old_name
,
const
char
*
new_db
,
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
,
TABLE_LIST
*
update_table_list
,
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
);
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_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
);
int
mysqld_show_status
(
THD
*
thd
);
...
...
sql/sql_class.h
View file @
d53072d1
...
...
@@ -1293,20 +1293,21 @@ class select_create: public select_insert {
ORDER
*
group
;
const
char
*
db
;
const
char
*
name
;
List
<
create_field
>
*
extra_fields
;
List
<
Key
>
*
keys
;
HA_CREATE_INFO
*
create_info
;
Alter_info
*
alter_info
;
MYSQL_LOCK
*
lock
;
Field
**
field
;
public:
select_create
(
const
char
*
db_name
,
const
char
*
table_name
,
HA_CREATE_INFO
*
create_info_par
,
List
<
create_field
>
&
fields_par
,
List
<
Key
>
&
keys_par
,
List
<
Item
>
&
select_fields
,
enum_duplicates
duplic
,
bool
ignore
)
:
select_insert
(
NULL
,
&
select_fields
,
duplic
,
ignore
),
db
(
db_name
),
name
(
table_name
),
extra_fields
(
&
fields_par
),
keys
(
&
keys_par
),
create_info
(
create_info_par
),
lock
(
0
)
HA_CREATE_INFO
*
create_info_arg
,
Alter_info
*
alter_info_arg
,
List
<
Item
>
&
select_fields
,
enum_duplicates
duplic
,
bool
ignore
)
:
select_insert
(
NULL
,
&
select_fields
,
duplic
,
ignore
),
db
(
db_name
),
name
(
table_name
),
create_info
(
create_info_arg
),
alter_info
(
alter_info_arg
),
lock
(
0
)
{}
int
prepare
(
List
<
Item
>
&
list
,
SELECT_LEX_UNIT
*
u
);
void
store_values
(
List
<
Item
>
&
values
);
...
...
sql/sql_insert.cc
View file @
d53072d1
...
...
@@ -1805,7 +1805,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
unit
=
u
;
table
=
create_table_from_items
(
thd
,
create_info
,
db
,
name
,
extra_fields
,
keys
,
&
values
,
&
lock
);
alter_info
,
&
values
,
&
lock
);
if
(
!
table
)
DBUG_RETURN
(
-
1
);
// abort() deletes table
...
...
sql/sql_lex.cc
View file @
d53072d1
...
...
@@ -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
*/
...
...
sql/sql_lex.h
View file @
d53072d1
...
...
@@ -571,19 +571,61 @@ typedef class st_select_lex SELECT_LEX;
#define ALTER_ORDER 64
#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_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
;
bool
is_simple
;
st_alter_info
(){
clear
();}
void
clear
(){
keys_onoff
=
LEAVE_AS_IS
;
tablespace_op
=
NO_TABLESPACE_OP
;}
void
reset
(){
drop_list
.
empty
();
alter_list
.
empty
();
clear
();}
}
ALTER_INFO
;
Alter_info
()
:
flags
(
0
),
keys_onoff
(
LEAVE_AS_IS
),
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 */
...
...
@@ -620,8 +662,6 @@ typedef struct st_lex
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
;
...
...
@@ -654,7 +694,7 @@ typedef struct st_lex
bool
derived_tables
;
bool
safe_to_cache_query
;
bool
subqueries
,
ignore
;
A
LTER_INFO
alter_info
;
A
lter_info
alter_info
;
/* Prepared statements SQL syntax:*/
LEX_STRING
prepared_stmt_name
;
/* Statement name (in all queries) */
/*
...
...
sql/sql_list.h
View file @
d53072d1
...
...
@@ -66,9 +66,14 @@ public:
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
;
void
*
info
;
list_node
(
void
*
info_par
,
list_node
*
next_par
)
...
...
@@ -76,11 +81,9 @@ public:
{}
list_node
()
/* For end_of_list */
{
info
=
0
;
info
=
0
;
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
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
()
{
elements
=
tmp
.
elements
;
first
=
tmp
.
first
;
last
=
tmp
.
last
;
elements
=
tmp
.
elements
;
first
=
tmp
.
first
;
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
bool
push_back
(
void
*
info
)
...
...
@@ -327,6 +375,8 @@ template <class T> class List :public base_list
public:
inline
List
()
:
base_list
()
{}
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_front
(
T
*
a
)
{
return
base_list
::
push_front
(
a
);
}
inline
T
*
head
()
{
return
(
T
*
)
base_list
::
head
();
}
...
...
sql/sql_parse.cc
View file @
d53072d1
...
...
@@ -2478,6 +2478,22 @@ mysql_execute_command(THD *thd)
}
/* Skip first table, which is the table we are creating */
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
,
&
create_table_local
);
...
...
@@ -2485,12 +2501,12 @@ mysql_execute_command(THD *thd)
goto
unsent_create_error
;
#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
/* 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
)
||
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
))
{
res
=-
1
;
...
...
@@ -2501,14 +2517,14 @@ mysql_execute_command(THD *thd)
If we are using SET CHARSET without DEFAULT, add an implicite
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_CHARSET
)
{
lex
->
create_info
.
used_fields
&=
~
HA_CREATE_USED_CHARSET
;
lex
->
create_info
.
used_fields
|=
HA_CREATE_USED_DEFAULT_CHARSET
;
lex
->
create_info
.
default_table_charset
=
lex
->
create_info
.
table_charset
;
lex
->
create_info
.
table_charset
=
0
;
create_info
.
used_fields
&=
~
HA_CREATE_USED_CHARSET
;
create_info
.
used_fields
|=
HA_CREATE_USED_DEFAULT_CHARSET
;
create_info
.
default_table_charset
=
create_info
.
table_charset
;
create_info
.
table_charset
=
0
;
}
/*
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
)))
{
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
,
create_table
->
real_name
,
&
lex
->
create_info
,
lex
->
create_list
,
lex
->
key_list
,
&
create_info
,
&
alter_info
,
select_lex
->
item_list
,
lex
->
duplicates
,
lex
->
ignore
)))
{
...
...
@@ -2558,22 +2577,18 @@ mysql_execute_command(THD *thd)
res
=
handle_select
(
thd
,
lex
,
result
);
select_lex
->
resolve_mode
=
SELECT_LEX
::
NOMATTER_MODE
;
}
//reset for PS
lex
->
create_list
.
empty
();
lex
->
key_list
.
empty
();
}
}
else
// regular create
{
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
);
else
{
res
=
mysql_create_table
(
thd
,
create_table
->
db
,
create_table
->
real_name
,
&
lex
->
create_info
,
lex
->
create_list
,
lex
->
key_list
,
0
,
0
);
res
=
mysql_create_table
(
thd
,
create_table
->
db
,
create_table
->
real_name
,
&
create_info
,
&
alter_info
,
0
,
0
);
}
if
(
!
res
)
send_ok
(
thd
);
...
...
@@ -2591,15 +2606,48 @@ unsent_create_error:
break
;
}
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
))
goto
error
;
/* purecov: inspected */
thd
->
enable_slow_log
=
opt_log_slow_admin_statements
;
if
(
end_active_trans
(
thd
))
res
=
-
1
;
else
res
=
mysql_create_index
(
thd
,
tables
,
lex
->
key_list
);
break
;
goto
error
;
/*
Currently CREATE INDEX or DROP INDEX cause a full table rebuild
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
case
SQLCOM_SLAVE_START
:
{
...
...
@@ -2642,6 +2690,17 @@ unsent_create_error:
#else
{
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
))
{
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
by a database. (Bug #11493)
*/
if
(
lex
->
alter_info
.
flags
&
ALTER_RENAME
)
if
(
alter_info
.
flags
&
ALTER_RENAME
)
{
if
(
!
thd
->
db
)
{
...
...
@@ -2671,7 +2730,7 @@ unsent_create_error:
check_access
(
thd
,
INSERT_ACL
|
CREATE_ACL
,
select_lex
->
db
,
&
priv
,
0
,
0
)
||
check_merge_table_access
(
thd
,
tables
->
db
,
(
TABLE_LIST
*
)
lex
->
create_info
.
merge_list
.
first
))
create_info
.
merge_list
.
first
))
goto
error
;
/* purecov: inspected */
if
(
grant_option
)
{
...
...
@@ -2690,13 +2749,13 @@ unsent_create_error:
}
}
/* 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
,
"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
,
"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 */
if
(
end_active_trans
(
thd
))
res
=
-
1
;
...
...
@@ -2704,12 +2763,12 @@ unsent_create_error:
{
thd
->
enable_slow_log
=
opt_log_slow_admin_statements
;
res
=
mysql_alter_table
(
thd
,
select_lex
->
db
,
lex
->
name
,
&
lex
->
create_info
,
tables
,
lex
->
create_list
,
lex
->
key_list
,
&
create_info
,
tables
,
&
alter_info
,
select_lex
->
order_list
.
elements
,
(
ORDER
*
)
select_lex
->
order_list
.
first
,
lex
->
duplicates
,
lex
->
ignore
,
&
lex
->
alter_info
);
lex
->
duplicates
,
lex
->
ignore
);
}
break
;
}
...
...
@@ -2846,7 +2905,7 @@ unsent_create_error:
goto
error
;
/* purecov: inspected */
thd
->
enable_slow_log
=
opt_log_slow_admin_statements
;
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
);
/* ! we write after unlocking the table */
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
);
}
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
:
#if defined(DONT_ALLOW_SHOW_COMMANDS)
send_error
(
thd
,
ER_NOT_ALLOWED_COMMAND
);
/* purecov: inspected */
...
...
@@ -3363,6 +3414,12 @@ purposes internal to the MySQL server", MYF(0));
break
;
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
))
{
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
))
break
;
res
=
mysql_create_db
(
thd
,(
lower_case_table_names
==
2
?
alias
:
lex
->
name
),
&
lex
->
create_info
,
0
);
&
create_info
,
0
);
break
;
}
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
)
{
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
,
0
,
lex
->
col_list
));
lex
->
alter_info
.
key_list
.
push_back
(
new
Key
(
Key
::
PRIMARY
,
NullS
,
HA_KEY_ALG_UNDEF
,
0
,
lex
->
col_list
));
lex
->
col_list
.
empty
();
}
if
(
type_modifier
&
(
UNIQUE_FLAG
|
UNIQUE_KEY_FLAG
))
{
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
.
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
->
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
;
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
...
...
sql/sql_show.cc
View file @
d53072d1
...
...
@@ -845,7 +845,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
}
int
mysqld_show_create_db
(
THD
*
thd
,
char
*
dbname
,
HA_CREATE_INFO
*
create_info
)
const
HA_CREATE_INFO
*
create_info
)
{
int
length
;
char
path
[
FN_REFLEN
];
...
...
sql/sql_table.cc
View file @
d53072d1
...
...
@@ -456,8 +456,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
mysql_prepare_table()
thd Thread object
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
alter_info List of columns and indexes to create
DESCRIPTION
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
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
bool
tmp_table
,
uint
&
db_options
,
Alter_info
*
alter_info
,
bool
tmp_table
,
uint
&
db_options
,
handler
*
file
,
KEY
*&
key_info_buffer
,
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
field_no
,
dup_no
;
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"
);
List_iterator
<
create_field
>
it
(
fields
),
it2
(
fields
);
select_field_pos
=
fields
.
elements
-
select_field_count
;
select_field_pos
=
alter_info
->
create_list
.
elements
-
select_field_count
;
null_fields
=
blob_columns
=
0
;
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 */
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
;
bool
primary_key
=
0
,
unique_key
=
0
;
Key
*
key
,
*
key2
;
...
...
@@ -1336,20 +1337,24 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
thd Thread object
db Database
table_name Table name
create_info Create information (like MAX_ROWS)
fields List of fields to create
keys List of keys to create
create_info [in/out] Create information (like MAX_ROWS)
alter_info [in/out] List of columns and indexes to create
tmp_table Set to 1 if this is an internal temporary table
(From ALTER TABLE)
DESCRIPTION
If one creates a temporary table, this is automaticly opened
If one creates a temporary table, this is automatic
al
ly opened
no_log is needed for the case of CREATE ... SELECT,
as the logging will be done later in sql_insert.cc
select_field_count is also used for CREATE ... SELECT,
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
0 ok
-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
,
HA_CREATE_INFO
*
create_info
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
bool
tmp_table
,
Alter_info
*
alter_info
,
bool
tmp_table
,
uint
select_field_count
)
{
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"
);
/* 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
));
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
;
}
if
(
mysql_prepare_table
(
thd
,
create_info
,
fields
,
keys
,
tmp_table
,
db_options
,
file
,
if
(
mysql_prepare_table
(
thd
,
create_info
,
alter_info
,
tmp_table
,
db_options
,
file
,
key_info_buffer
,
&
key_count
,
select_field_count
))
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
;
if
(
rea_create_table
(
thd
,
path
,
db
,
table_name
,
create_info
,
fields
,
key_coun
t
,
key_info_buffer
))
create_info
,
alter_info
->
create_lis
t
,
key_count
,
key_info_buffer
))
goto
end
;
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
,
const
char
*
db
,
const
char
*
name
,
List
<
create_field
>
*
extra_fields
,
List
<
Key
>
*
keys
,
Alter_info
*
alter_info
,
List
<
Item
>
*
items
,
MYSQL_LOCK
**
lock
)
{
...
...
@@ -1627,7 +1631,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
((
Item_field
*
)
item
)
->
field
:
(
Field
*
)
0
))))
DBUG_RETURN
(
0
);
extra_fields
->
push_back
(
cr_field
);
alter_info
->
create_list
.
push_back
(
cr_field
);
}
/* create and lock table */
/* 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().
*/
tmp_disable_binlog
(
thd
);
if
(
!
mysql_create_table
(
thd
,
db
,
name
,
create_info
,
*
extra_fields
,
*
keys
,
0
,
select_field_count
))
if
(
!
mysql_create_table
(
thd
,
db
,
name
,
create_info
,
alter_info
,
0
,
select_field_count
))
{
if
(
!
(
table
=
open_table
(
thd
,
db
,
name
,
name
,(
bool
*
)
0
)))
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
:
{
my_bool
save_no_send_ok
=
thd
->
net
.
no_send_ok
;
/*
This is currently used only by InnoDB. ha_innobase::optimize() answers
"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
->
next
=
0
;
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
);
close_thread_tables
(
thd
);
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
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
,
HA_CREATE_INFO
*
create_info
,
TABLE_LIST
*
table_list
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
Alter_info
*
alter_info
,
uint
order_num
,
ORDER
*
order
,
enum
enum_duplicates
handle_duplicates
,
bool
ignore
,
ALTER_INFO
*
alter_info
,
bool
do_send_ok
)
enum
enum_duplicates
handle_duplicates
,
bool
ignore
)
{
TABLE
*
table
,
*
new_table
;
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
);
mysql_bin_log
.
write
(
&
qinfo
);
}
if
(
do_send_ok
)
send_ok
(
thd
);
}
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
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
<
create_field
>
create_list
;
// Add new fields here
List
<
Key
>
key_list
;
// Add new keys here
Alter_info
new_info
;
// Add new columns and indexes here
create_field
*
def
;
/*
...
...
@@ -3140,13 +2951,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
def
->
field
=
field
;
if
(
!
def
->
after
)
{
create_list
.
push_back
(
def
);
new_info
.
create_list
.
push_back
(
def
);
def_it
.
remove
();
}
}
else
{
// 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_column
*
alter
;
while
((
alter
=
alter_it
++
))
...
...
@@ -3167,7 +2978,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
}
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
{
if
(
def
->
change
&&
!
def
->
field
)
...
...
@@ -3176,9 +2987,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN
(
-
1
);
}
if
(
!
def
->
after
)
create_list
.
push_back
(
def
);
new_info
.
create_list
.
push_back
(
def
);
else
if
(
def
->
after
==
first_keyword
)
create_list
.
push_front
(
def
);
new_info
.
create_list
.
push_front
(
def
);
else
{
create_field
*
find
;
...
...
@@ -3202,7 +3013,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
table_name
);
DBUG_RETURN
(
-
1
);
}
if
(
!
create_list
.
elements
)
if
(
!
new_info
.
create_list
.
elements
)
{
my_error
(
ER_CANT_REMOVE_ALL_FIELDS
,
MYF
(
0
));
DBUG_RETURN
(
-
1
);
...
...
@@ -3213,8 +3024,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
for which some fields exists.
*/
List_iterator
<
Key
>
key_it
(
keys
);
List_iterator
<
create_field
>
field_it
(
create_list
);
List_iterator
<
Key
>
key_it
(
alter_info
->
key_list
);
List_iterator
<
create_field
>
field_it
(
new_info
.
create_list
);
List
<
key_part_spec
>
key_parts
;
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
));
}
if
(
key_parts
.
elements
)
key_list
.
push_back
(
new
Key
(
key_info
->
flags
&
HA_SPATIAL
?
Key
::
SPATIAL
:
(
key_info
->
flags
&
HA_NOSAME
?
(
!
my_strcasecmp
(
system_charset_info
,
key_name
,
primary_key_name
)
?
Key
::
PRIMARY
:
Key
::
UNIQUE
)
:
(
key_info
->
flags
&
HA_FULLTEXT
?
Key
::
FULLTEXT
:
Key
::
MULTIPLE
)),
key_name
,
{
Key
*
key
;
enum
Key
::
Keytype
key_type
;
if
(
key_info
->
flags
&
HA_SPATIAL
)
key_type
=
Key
::
SPATIAL
;
else
if
(
key_info
->
flags
&
HA_NOSAME
)
{
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
,
test
(
key_info
->
flags
&
HA_GENERATED_KEY
),
key_parts
));
key_parts
);
new_info
.
key_list
.
push_back
(
key
);
}
}
{
Key
*
key
;
while
((
key
=
key_it
++
))
// Add new keys
{
if
(
key
->
type
!=
Key
::
FOREIGN_KEY
)
key_list
.
push_back
(
key
);
new_info
.
key_list
.
push_back
(
key
);
if
(
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. */
tmp_disable_binlog
(
thd
);
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
);
if
(
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
copied
=
deleted
=
0
;
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
,
order_num
,
order
,
&
copied
,
&
deleted
,
alter_info
->
keys_onoff
);
...
...
@@ -3637,8 +3461,7 @@ end_temporary:
my_snprintf
(
tmp_name
,
sizeof
(
tmp_name
),
ER
(
ER_INSERT_INFO
),
(
ulong
)
(
copied
+
deleted
),
(
ulong
)
deleted
,
(
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
;
DBUG_RETURN
(
0
);
...
...
@@ -3828,30 +3651,26 @@ copy_data_between_tables(TABLE *from,TABLE *to,
mysql_recreate_table()
thd Thread handler
tables Tables to recreate
do_send_ok If we should send_ok() or leave it to caller
RETURN
Like mysql_alter_table().
*/
int
mysql_recreate_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
bool
do_send_ok
)
int
mysql_recreate_table
(
THD
*
thd
,
TABLE_LIST
*
table_list
)
{
DBUG_ENTER
(
"mysql_recreate_table"
);
LEX
*
lex
=
thd
->
lex
;
HA_CREATE_INFO
create_info
;
lex
->
create_list
.
empty
();
lex
->
key_list
.
empty
();
lex
->
col_list
.
empty
();
lex
->
alter_info
.
reset
();
lex
->
alter_info
.
is_simple
=
0
;
// Force full recreate
Alter_info
alter_info
;
DBUG_ENTER
(
"mysql_recreate_table"
);
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
db_type
=
DB_TYPE_DEFAULT
;
create_info
.
row_type
=
ROW_TYPE_DEFAULT
;
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
,
table_list
,
lex
->
create_list
,
lex
->
key_list
,
0
,
(
ORDER
*
)
0
,
DUP_ERROR
,
0
,
&
lex
->
alter_info
,
do_send_ok
));
table_list
,
&
alter_info
,
0
,
(
ORDER
*
)
0
,
DUP_ERROR
,
0
));
}
...
...
sql/sql_yacc.yy
View file @
d53072d1
...
...
@@ -1021,8 +1021,7 @@ create:
TL_READ_NO_INSERT:
TL_READ)))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
lex->alter_info.reset();
lex->col_list.empty();
lex->change=NullS;
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,
TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
lex->alter_info.reset();
lex->alter_info.is_simple= 0;
lex->alter_info.flags= ALTER_ADD_INDEX;
lex->col_list.empty();
lex->change=NullS;
}
'(' key_list ')'
{
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();
}
| CREATE DATABASE opt_if_not_exists ident
...
...
@@ -1305,29 +1306,34 @@ key_def:
key_type opt_ident key_alg '(' key_list ')'
{
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 */
}
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
{
LEX *lex=Lex;
const char *key_name= $3 ? $3:$1;
lex->key_list.push_back(new Key($2, key_name, $4, 0,
lex->col_list)
);
Key *key= new Key($2, key_name, $4, 0, lex->col_list);
lex->alter_info.key_list.push_back(key
);
lex->col_list.empty(); /* Alloced by sql_alloc */
}
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
{
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,
lex->ref_list,
lex->fk_delete_opt,
lex->fk_update_opt,
lex->fk_match_option));
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
lex->fk_match_option);
lex->alter_info.key_list.push_back(key);
key= new Key(Key::MULTIPLE, key_name,
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 */
}
| constraint opt_check_constraint
...
...
@@ -1850,8 +1856,6 @@ alter:
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
TL_OPTION_UPDATING))
YYABORT;
lex->create_list.empty();
lex->key_list.empty();
lex->col_list.empty();
lex->select_lex.init_order();
lex->select_lex.db=lex->name=0;
...
...
@@ -1860,8 +1864,6 @@ alter:
lex->create_info.default_table_charset= NULL;
lex->create_info.row_type= ROW_TYPE_NOT_USED;
lex->alter_info.reset();
lex->alter_info.is_simple= 1;
lex->alter_info.flags= 0;
}
alter_list
{}
...
...
@@ -4030,7 +4032,9 @@ drop:
{
LEX *lex=Lex;
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,
$3.str));
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment