mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 11:31:51 +01:00
Merge dfischer@bk-internal.mysql.com:/home/bk/mysql-5.0-build
into kahlann.erinye.com:/home/df/mysql/build/mysql-5.0-build
This commit is contained in:
commit
9885afeef4
23 changed files with 809 additions and 266 deletions
|
@ -2516,9 +2516,9 @@ linked_client_targets="linked_libmysql_sources"
|
|||
|
||||
if test "$THREAD_SAFE_CLIENT" = "no"
|
||||
then
|
||||
sql_client_dirs="strings regex mysys extra libmysql client"
|
||||
sql_client_dirs="strings regex mysys dbug extra libmysql client"
|
||||
else
|
||||
sql_client_dirs="strings regex mysys extra libmysql libmysql_r client"
|
||||
sql_client_dirs="strings regex mysys dbug extra libmysql libmysql_r client"
|
||||
linked_client_targets="$linked_client_targets linked_libmysql_r_sources"
|
||||
AC_CONFIG_FILES(libmysql_r/Makefile)
|
||||
AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe])
|
||||
|
|
|
@ -592,8 +592,8 @@ static uint copy_decode_table(uint16 *to_pos, uint offset,
|
|||
uint16 *decode_table)
|
||||
{
|
||||
uint prev_offset;
|
||||
prev_offset= offset;
|
||||
DBUG_ENTER("copy_decode_table");
|
||||
prev_offset= offset;
|
||||
|
||||
/* Descent on the left side. */
|
||||
if (!(*decode_table & IS_CHAR))
|
||||
|
|
|
@ -87,11 +87,27 @@ x y z
|
|||
rollback;
|
||||
commit;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' for update;
|
||||
x y z
|
||||
# # #
|
||||
# # #
|
||||
begin;
|
||||
select * from t1 where x = 2 for update;
|
||||
x y z
|
||||
2 two 2
|
||||
select * from t1 where x = 1 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
rollback;
|
||||
commit;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x for update;
|
||||
x y z
|
||||
1 one 1
|
||||
3 three 3
|
||||
begin;
|
||||
select * from t1 where x = 2 for update;
|
||||
x y z
|
||||
2 two 2
|
||||
select * from t1 where x = 1 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
rollback;
|
||||
|
@ -124,6 +140,22 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
|||
rollback;
|
||||
commit;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' lock in share mode;
|
||||
x y z
|
||||
# # #
|
||||
# # #
|
||||
begin;
|
||||
select * from t1 where y = 'one' lock in share mode;
|
||||
x y z
|
||||
1 one 1
|
||||
select * from t1 where x = 2 for update;
|
||||
x y z
|
||||
2 two 2
|
||||
select * from t1 where x = 1 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
rollback;
|
||||
commit;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
|
||||
x y z
|
||||
1 one 1
|
||||
|
@ -132,6 +164,9 @@ begin;
|
|||
select * from t1 where y = 'one' lock in share mode;
|
||||
x y z
|
||||
1 one 1
|
||||
select * from t1 where x = 2 for update;
|
||||
x y z
|
||||
2 two 2
|
||||
select * from t1 where x = 1 for update;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
rollback;
|
||||
|
|
|
@ -1055,6 +1055,65 @@ 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` varchar(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` varchar(4) NOT NULL default ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop database mysqltest;
|
||||
deallocate prepare stmt1;
|
||||
deallocate prepare stmt2;
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
End of 4.1 tests.
|
||||
create table t1 (a varchar(20));
|
||||
insert into t1 values ('foo');
|
||||
|
@ -1536,4 +1595,54 @@ a
|
|||
2
|
||||
DEALLOCATE PREPARE stmt;
|
||||
DROP TABLE t1,t2;
|
||||
drop table if exists t1;
|
||||
create table t1 (s1 char(20));
|
||||
prepare stmt from "alter table t1 modify s1 int";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
drop table if exists t1;
|
||||
create table t1 (a int, b int);
|
||||
prepare s_6895 from "alter table t1 drop column b";
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
drop table t1;
|
||||
create table t1 (a int, b int);
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
drop table t1;
|
||||
create table t1 (a int, b int);
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
deallocate prepare s_6895;
|
||||
drop table t1;
|
||||
create table t1 (i int primary key auto_increment) comment='comment for table t1';
|
||||
create table t2 (i int, j int, k int);
|
||||
prepare stmt from "alter table t1 auto_increment=100";
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`i` int(11) NOT NULL auto_increment,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 COMMENT='comment for table t1'
|
||||
flush tables;
|
||||
select * from t2;
|
||||
i j k
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`i` int(11) NOT NULL auto_increment,
|
||||
PRIMARY KEY (`i`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 COMMENT='comment for table t1'
|
||||
deallocate prepare stmt;
|
||||
drop table t1, t2;
|
||||
End of 5.0 tests.
|
||||
|
|
|
@ -3611,3 +3611,9 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
1 SIMPLE t2 range si,ai si 5 NULL 2 Using where
|
||||
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
|
||||
DROP TABLE t1,t2,t3;
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a int);
|
||||
INSERT into t1 values (1), (2), (3);
|
||||
SELECT * FROM t1 LIMIT 2, -1;
|
||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1' at line 1
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -5626,6 +5626,23 @@ Called B
|
|||
Called B
|
||||
drop procedure proc_21462_a|
|
||||
drop procedure proc_21462_b|
|
||||
drop table if exists t3|
|
||||
drop procedure if exists proc_bug19733|
|
||||
create table t3 (s1 int)|
|
||||
create procedure proc_bug19733()
|
||||
begin
|
||||
declare v int default 0;
|
||||
while v < 100 do
|
||||
create index i on t3 (s1);
|
||||
drop index i on t3;
|
||||
set v = v + 1;
|
||||
end while;
|
||||
end|
|
||||
call proc_bug19733()|
|
||||
call proc_bug19733()|
|
||||
call proc_bug19733()|
|
||||
drop procedure proc_bug19733|
|
||||
drop table t3|
|
||||
End of 5.0 tests
|
||||
DROP TABLE IF EXISTS bug23760|
|
||||
DROP TABLE IF EXISTS bug23760_log|
|
||||
|
|
|
@ -102,16 +102,36 @@ connection con1;
|
|||
commit;
|
||||
|
||||
# table scan
|
||||
#
|
||||
# Note that there are two distinct execution paths in which we unlock
|
||||
# non-matching rows inspected during table scan - one that is used in
|
||||
# case of filesort and one that used in rest of cases. Below we cover
|
||||
# the latter (Bug #20390 "SELECT FOR UPDATE does not release locks of
|
||||
# untouched rows in full table scans").
|
||||
connection con1;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x for update;
|
||||
# We can't use "order by x" here as it will cause filesort
|
||||
--replace_column 1 # 2 # 3 #
|
||||
select * from t1 where y = 'one' or y = 'three' for update;
|
||||
|
||||
connection con2;
|
||||
begin;
|
||||
# Have to check with pk access here since scans take locks on
|
||||
# all rows and then release them in chunks
|
||||
# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
|
||||
#select * from t1 where x = 2 for update;
|
||||
select * from t1 where x = 2 for update;
|
||||
--error 1205
|
||||
select * from t1 where x = 1 for update;
|
||||
rollback;
|
||||
|
||||
connection con1;
|
||||
commit;
|
||||
|
||||
# And now the test for case with filesort
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x for update;
|
||||
connection con2;
|
||||
begin;
|
||||
select * from t1 where x = 2 for update;
|
||||
--error 1205
|
||||
select * from t1 where x = 1 for update;
|
||||
rollback;
|
||||
|
@ -157,15 +177,32 @@ commit;
|
|||
# table scan
|
||||
connection con1;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
|
||||
# We can't use "order by x" here as it will cause filesort
|
||||
--replace_column 1 # 2 # 3 #
|
||||
select * from t1 where y = 'one' or y = 'three' lock in share mode;
|
||||
|
||||
connection con2;
|
||||
begin;
|
||||
select * from t1 where y = 'one' lock in share mode;
|
||||
# Have to check with pk access here since scans take locks on
|
||||
# all rows and then release them in chunks
|
||||
# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
|
||||
#select * from t1 where x = 2 for update;
|
||||
select * from t1 where x = 2 for update;
|
||||
--error 1205
|
||||
select * from t1 where x = 1 for update;
|
||||
rollback;
|
||||
|
||||
connection con1;
|
||||
commit;
|
||||
|
||||
# And the same test for case with filesort
|
||||
connection con1;
|
||||
begin;
|
||||
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
|
||||
|
||||
connection con2;
|
||||
begin;
|
||||
select * from t1 where y = 'one' lock in share mode;
|
||||
select * from t1 where x = 2 for update;
|
||||
--error 1205
|
||||
select * from t1 where x = 1 for update;
|
||||
rollback;
|
||||
|
|
|
@ -1106,11 +1106,95 @@ 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
|
||||
#
|
||||
# Protect ourselves from data left in tmp/ by a previos possibly failed
|
||||
# test
|
||||
--system rm -f $MYSQLTEST_VARDIR/tmp/t1.*
|
||||
--disable_query_log
|
||||
eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'";
|
||||
--enable_query_log
|
||||
execute stmt;
|
||||
#
|
||||
# DATA DIRECTORY option does not always work: if the operating
|
||||
# system does not support symlinks, have_symlinks option is automatically
|
||||
# disabled.
|
||||
# In this case DATA DIRECTORY is silently ignored when
|
||||
# creating a table, and is not output by SHOW CREATE TABLE.
|
||||
#
|
||||
--disable_result_log
|
||||
show create table t1;
|
||||
--enable_result_log
|
||||
drop table t1;
|
||||
execute stmt;
|
||||
--disable_result_log
|
||||
show create table t1;
|
||||
--enable_result_log
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
--echo End of 4.1 tests.
|
||||
|
||||
|
||||
|
||||
############################# 5.0 tests start ################################
|
||||
#
|
||||
#
|
||||
|
@ -1585,5 +1669,76 @@ EXECUTE stmt USING @arg;
|
|||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug#4968 "Stored procedure crash if cursor opened on altered table"
|
||||
# The bug is not repeatable any more after the fix for
|
||||
# Bug#15217 "Bug #15217 Using a SP cursor on a table created with PREPARE
|
||||
# fails with weird error", however ALTER TABLE is not re-execution friendly
|
||||
# and that caused a valgrind warning. Check that the warning is gone.
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (s1 char(20));
|
||||
prepare stmt from "alter table t1 modify s1 int";
|
||||
execute stmt;
|
||||
execute stmt;
|
||||
drop table t1;
|
||||
deallocate prepare stmt;
|
||||
|
||||
#
|
||||
# Bug#6895 "Prepared Statements: ALTER TABLE DROP COLUMN does nothing"
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create table t1 (a int, b int);
|
||||
prepare s_6895 from "alter table t1 drop column b";
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
drop table t1;
|
||||
create table t1 (a int, b int);
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
drop table t1;
|
||||
create table t1 (a int, b int);
|
||||
execute s_6895;
|
||||
show columns from t1;
|
||||
deallocate prepare s_6895;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
|
||||
#
|
||||
# 5.0 part of the test.
|
||||
#
|
||||
|
||||
# ALTER TABLE
|
||||
create table t1 (i int primary key auto_increment) comment='comment for table t1';
|
||||
create table t2 (i int, j int, k int);
|
||||
prepare stmt from "alter table t1 auto_increment=100";
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
# Let us trash table-cache's memory
|
||||
flush tables;
|
||||
select * from t2;
|
||||
execute stmt;
|
||||
show create table t1;
|
||||
deallocate prepare stmt;
|
||||
drop table t1, t2;
|
||||
# 5.1 part of the test.
|
||||
# CREATE DATABASE
|
||||
#set @old_character_set_server= @@character_set_server;
|
||||
#set @@character_set_server= latin1;
|
||||
#prepare stmt from "create database mysqltest";
|
||||
#execute stmt;
|
||||
#show create database mysqltest;
|
||||
#drop database mysqltest;
|
||||
#set @@character_set_server= utf8;
|
||||
#execute stmt;
|
||||
#show create database mysqltest;
|
||||
#drop database mysqltest;
|
||||
#deallocate prepare stmt;
|
||||
#set @@character_set_server= @old_character_set_server;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
|
|
@ -3092,3 +3092,23 @@ SELECT t3.a FROM t1,t2,t3
|
|||
t3.c IN ('bb','ee');
|
||||
|
||||
DROP TABLE t1,t2,t3;
|
||||
|
||||
#
|
||||
# Bug#6298: LIMIT #, -1 no longer works to set start with no end limit
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1(a int);
|
||||
INSERT into t1 values (1), (2), (3);
|
||||
|
||||
# LIMIT N, -1 was accepted by accident in 4.0, but was not intended.
|
||||
# This test verifies that this illegal construct is now properly detected.
|
||||
|
||||
--error ER_PARSE_ERROR
|
||||
SELECT * FROM t1 LIMIT 2, -1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
|
|
|
@ -6587,6 +6587,34 @@ call proc_21462_b(1)|
|
|||
drop procedure proc_21462_a|
|
||||
drop procedure proc_21462_b|
|
||||
|
||||
|
||||
#
|
||||
# Bug#19733 "Repeated alter, or repeated create/drop, fails"
|
||||
# Check that CREATE/DROP INDEX is re-execution friendly.
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t3|
|
||||
drop procedure if exists proc_bug19733|
|
||||
--enable_warnings
|
||||
create table t3 (s1 int)|
|
||||
|
||||
create procedure proc_bug19733()
|
||||
begin
|
||||
declare v int default 0;
|
||||
while v < 100 do
|
||||
create index i on t3 (s1);
|
||||
drop index i on t3;
|
||||
set v = v + 1;
|
||||
end while;
|
||||
end|
|
||||
|
||||
call proc_bug19733()|
|
||||
call proc_bug19733()|
|
||||
call proc_bug19733()|
|
||||
|
||||
drop procedure proc_bug19733|
|
||||
drop table t3|
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
|
||||
|
|
|
@ -6111,7 +6111,7 @@ ndb_get_table_statistics(ha_ndbcluster* file, bool report_error, Ndb* ndb,
|
|||
retry:
|
||||
if(report_error)
|
||||
{
|
||||
if (file)
|
||||
if (file && pTrans)
|
||||
{
|
||||
reterr= file->ndb_err(pTrans);
|
||||
}
|
||||
|
|
|
@ -773,17 +773,15 @@ int prepare_create_field(create_field *sql_field,
|
|||
uint table_flags);
|
||||
bool 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);
|
||||
|
||||
bool 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,
|
||||
uint order_num, ORDER *order, bool ignore,
|
||||
ALTER_INFO *alter_info, bool do_send_ok);
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order, bool ignore);
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
|
||||
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Table_ident *src_table);
|
||||
|
@ -792,9 +790,6 @@ bool mysql_rename_table(enum db_type base,
|
|||
const char * old_name,
|
||||
const char *new_db,
|
||||
const char * new_name);
|
||||
bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
|
||||
bool mysql_drop_index(THD *thd, TABLE_LIST *table_list,
|
||||
ALTER_INFO *alter_info);
|
||||
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||
Item **conds, uint order_num, ORDER *order);
|
||||
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
|
@ -896,7 +891,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_LIST *table_list, int fd);
|
||||
bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
|
||||
bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
|
||||
bool 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);
|
||||
|
|
|
@ -5466,6 +5466,11 @@ log and this option does nothing anymore.",
|
|||
0, 0, 0, 0, 0},
|
||||
{"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.",
|
||||
(gptr*) &my_use_symdir, (gptr*) &my_use_symdir, 0, GET_BOOL, NO_ARG,
|
||||
/*
|
||||
The system call realpath() produces warnings under valgrind and
|
||||
purify. These are not suppressed: instead we disable symlinks
|
||||
option if compiled with valgrind support.
|
||||
*/
|
||||
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
|
||||
{"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
|
|
|
@ -1839,21 +1839,22 @@ class select_insert :public select_result_interceptor {
|
|||
class select_create: public select_insert {
|
||||
ORDER *group;
|
||||
TABLE_LIST *create_table;
|
||||
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 (TABLE_LIST *table,
|
||||
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, NULL, &select_fields, 0, 0, duplic, ignore), create_table(table),
|
||||
extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par),
|
||||
select_create(TABLE_LIST *table,
|
||||
HA_CREATE_INFO *create_info_arg,
|
||||
Alter_info *alter_info_arg,
|
||||
List<Item> &select_fields,
|
||||
enum_duplicates duplic, bool ignore)
|
||||
:select_insert(NULL, NULL, &select_fields, 0, 0, duplic, ignore),
|
||||
create_table(table),
|
||||
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);
|
||||
void send_error(uint errcode,const char *err);
|
||||
|
|
|
@ -2616,11 +2616,11 @@ bool select_insert::send_eof()
|
|||
temporary table flag)
|
||||
create_table in Pointer to TABLE_LIST object providing database
|
||||
and name for table to be created or to be open
|
||||
extra_fields in/out Initial list of fields for table to be created
|
||||
keys in List of keys for table to be created
|
||||
alter_info in/out Initial list of columns and indexes for the table
|
||||
to be created
|
||||
items in List of items which should be used to produce rest
|
||||
of fields for the table (corresponding fields will
|
||||
be added to the end of 'extra_fields' list)
|
||||
be added to the end of alter_info->create_list)
|
||||
lock out Pointer to the MYSQL_LOCK object for table created
|
||||
(open) will be returned in this parameter. Since
|
||||
this table is not included in THD::lock caller is
|
||||
|
@ -2642,8 +2642,8 @@ bool select_insert::send_eof()
|
|||
|
||||
static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||
TABLE_LIST *create_table,
|
||||
List<create_field> *extra_fields,
|
||||
List<Key> *keys, List<Item> *items,
|
||||
Alter_info *alter_info,
|
||||
List<Item> *items,
|
||||
MYSQL_LOCK **lock)
|
||||
{
|
||||
TABLE tmp_table; // Used during 'create_field()'
|
||||
|
@ -2682,7 +2682,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||
DBUG_RETURN(0);
|
||||
if (item->maybe_null)
|
||||
cr_field->flags &= ~NOT_NULL_FLAG;
|
||||
extra_fields->push_back(cr_field);
|
||||
alter_info->create_list.push_back(cr_field);
|
||||
}
|
||||
/*
|
||||
create and lock table
|
||||
|
@ -2703,8 +2703,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||
{
|
||||
tmp_disable_binlog(thd);
|
||||
if (!mysql_create_table(thd, create_table->db, create_table->table_name,
|
||||
create_info, *extra_fields, *keys, 0,
|
||||
select_field_count))
|
||||
create_info, alter_info, 0, select_field_count))
|
||||
{
|
||||
/*
|
||||
If we are here in prelocked mode we either create temporary table
|
||||
|
@ -2760,7 +2759,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
|
||||
unit= u;
|
||||
table= create_table_from_items(thd, create_info, create_table,
|
||||
extra_fields, keys, &values, &lock);
|
||||
alter_info, &values, &lock);
|
||||
if (!table)
|
||||
DBUG_RETURN(-1); // abort() deletes table
|
||||
|
||||
|
|
|
@ -1054,6 +1054,17 @@ int MYSQLlex(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)
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
Skip comment in the end of statement.
|
||||
|
||||
|
|
|
@ -686,18 +686,58 @@ typedef class st_select_lex SELECT_LEX;
|
|||
#define ALTER_CONVERT 1024
|
||||
#define ALTER_FORCE 2048
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{}
|
||||
|
||||
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;
|
||||
}
|
||||
/**
|
||||
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
|
||||
};
|
||||
|
||||
struct st_sp_chistics
|
||||
{
|
||||
|
@ -883,8 +923,6 @@ typedef struct st_lex : public Query_tables_list
|
|||
List<String> interval_list;
|
||||
List<LEX_USER> users_list;
|
||||
List<LEX_COLUMN> columns;
|
||||
List<Key> key_list;
|
||||
List<create_field> create_list;
|
||||
List<Item> *insert_list,field_list,value_list,update_list;
|
||||
List<List_item> many_values;
|
||||
List<set_var_base> var_list;
|
||||
|
@ -977,7 +1015,7 @@ typedef struct st_lex : public Query_tables_list
|
|||
bool safe_to_cache_query;
|
||||
bool subqueries, ignore;
|
||||
st_parsing_options parsing_options;
|
||||
ALTER_INFO alter_info;
|
||||
Alter_info alter_info;
|
||||
/* Prepared statements SQL syntax:*/
|
||||
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
||||
/*
|
||||
|
|
|
@ -61,21 +61,24 @@ 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)
|
||||
:next(next_par),info(info_par)
|
||||
{}
|
||||
{}
|
||||
list_node() /* For end_of_list */
|
||||
{
|
||||
info=0;
|
||||
next= this;
|
||||
}
|
||||
friend class base_list;
|
||||
friend class base_list_iterator;
|
||||
{
|
||||
info= 0;
|
||||
next= this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -91,12 +94,57 @@ 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= 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)
|
||||
{
|
||||
|
@ -347,6 +395,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_back(T *a, MEM_ROOT *mem_root)
|
||||
{ return base_list::push_back(a, mem_root); }
|
||||
|
|
232
sql/sql_parse.cc
232
sql/sql_parse.cc
|
@ -2894,17 +2894,35 @@ mysql_execute_command(THD *thd)
|
|||
// Skip first table, which is the table we are creating
|
||||
TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
|
||||
TABLE_LIST *select_tables= lex->query_tables;
|
||||
/*
|
||||
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 end_with_restore_list;
|
||||
}
|
||||
|
||||
if ((res= create_table_precheck(thd, select_tables, create_table)))
|
||||
goto end_with_restore_list;
|
||||
|
||||
create_info.alias= create_table->alias;
|
||||
|
||||
#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->table_name) ||
|
||||
append_file_to_dir(thd, &lex->create_info.index_file_name,
|
||||
append_file_to_dir(thd, &create_info.index_file_name,
|
||||
create_table->table_name))
|
||||
goto end_with_restore_list;
|
||||
#endif
|
||||
|
@ -2912,14 +2930,14 @@ mysql_execute_command(THD *thd)
|
|||
If we are using SET CHARSET without DEFAULT, add an implicit
|
||||
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
|
||||
|
@ -2953,7 +2971,7 @@ mysql_execute_command(THD *thd)
|
|||
Is table which we are changing used somewhere in other parts
|
||||
of query
|
||||
*/
|
||||
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
||||
if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
||||
{
|
||||
TABLE_LIST *duplicate;
|
||||
if ((duplicate= unique_table(thd, create_table, select_tables)))
|
||||
|
@ -2964,10 +2982,10 @@ mysql_execute_command(THD *thd)
|
|||
}
|
||||
}
|
||||
/* If we create merge table, we have to test tables in merge, too */
|
||||
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
|
||||
if (create_info.used_fields & HA_CREATE_USED_UNION)
|
||||
{
|
||||
TABLE_LIST *tab;
|
||||
for (tab= (TABLE_LIST*) lex->create_info.merge_list.first;
|
||||
for (tab= (TABLE_LIST*) create_info.merge_list.first;
|
||||
tab;
|
||||
tab= tab->next_local)
|
||||
{
|
||||
|
@ -2980,14 +2998,16 @@ mysql_execute_command(THD *thd)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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,
|
||||
&lex->create_info,
|
||||
lex->create_list,
|
||||
lex->key_list,
|
||||
select_lex->item_list,
|
||||
lex->duplicates,
|
||||
lex->ignore)))
|
||||
&create_info,
|
||||
&alter_info,
|
||||
select_lex->item_list,
|
||||
lex->duplicates,
|
||||
lex->ignore)))
|
||||
{
|
||||
/*
|
||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
||||
|
@ -2996,23 +3016,19 @@ mysql_execute_command(THD *thd)
|
|||
res= handle_select(thd, lex, result, 0);
|
||||
delete result;
|
||||
}
|
||||
/* 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,
|
||||
(Table_ident *)lex->name);
|
||||
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->table_name, &lex->create_info,
|
||||
lex->create_list,
|
||||
lex->key_list, 0, 0);
|
||||
create_table->table_name, &create_info,
|
||||
&alter_info, 0, 0);
|
||||
}
|
||||
if (!res)
|
||||
send_ok(thd);
|
||||
|
@ -3024,16 +3040,49 @@ end_with_restore_list:
|
|||
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;
|
||||
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if (check_one_table_access(thd, INDEX_ACL, all_tables))
|
||||
if (check_one_table_access(thd, INDEX_ACL, first_table))
|
||||
goto error; /* purecov: inspected */
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
if (end_active_trans(thd))
|
||||
goto error;
|
||||
else
|
||||
res = mysql_create_index(thd, first_table, lex->key_list);
|
||||
break;
|
||||
/*
|
||||
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.row_type= ROW_TYPE_NOT_USED;
|
||||
create_info.default_table_charset= thd->variables.collation_database;
|
||||
|
||||
res= mysql_alter_table(thd, first_table->db, first_table->table_name,
|
||||
&create_info, first_table, &alter_info,
|
||||
0, (ORDER*) 0, 0);
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_REPLICATION
|
||||
case SQLCOM_SLAVE_START:
|
||||
{
|
||||
|
@ -3074,6 +3123,17 @@ end_with_restore_list:
|
|||
DBUG_ASSERT(first_table == all_tables && first_table != 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))
|
||||
{
|
||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
|
||||
|
@ -3088,7 +3148,7 @@ end_with_restore_list:
|
|||
is_schema_db(select_lex->db))||
|
||||
check_merge_table_access(thd, first_table->db,
|
||||
(TABLE_LIST *)
|
||||
lex->create_info.merge_list.first))
|
||||
create_info.merge_list.first))
|
||||
goto error; /* purecov: inspected */
|
||||
if (grant_option)
|
||||
{
|
||||
|
@ -3107,13 +3167,13 @@ end_with_restore_list:
|
|||
}
|
||||
}
|
||||
/* 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))
|
||||
goto error;
|
||||
|
@ -3127,13 +3187,13 @@ end_with_restore_list:
|
|||
}
|
||||
|
||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||
&lex->create_info,
|
||||
first_table, lex->create_list,
|
||||
lex->key_list,
|
||||
select_lex->order_list.elements,
|
||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||
&create_info,
|
||||
first_table,
|
||||
&alter_info,
|
||||
select_lex->order_list.elements,
|
||||
(ORDER *) select_lex->order_list.first,
|
||||
lex->ignore, &lex->alter_info, 1);
|
||||
lex->ignore);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -3286,7 +3346,7 @@ end_with_restore_list:
|
|||
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, first_table, 1) :
|
||||
mysql_recreate_table(thd, first_table) :
|
||||
mysql_optimize_table(thd, first_table, &lex->check_opt);
|
||||
/* ! we write after unlocking the table */
|
||||
if (!res && !lex->no_write_to_binlog)
|
||||
|
@ -3602,15 +3662,6 @@ end_with_restore_list:
|
|||
lex->drop_temporary);
|
||||
}
|
||||
break;
|
||||
case SQLCOM_DROP_INDEX:
|
||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||
if (check_one_table_access(thd, INDEX_ACL, all_tables))
|
||||
goto error; /* purecov: inspected */
|
||||
if (end_active_trans(thd))
|
||||
goto error;
|
||||
else
|
||||
res = mysql_drop_index(thd, first_table, &lex->alter_info);
|
||||
break;
|
||||
case SQLCOM_SHOW_PROCESSLIST:
|
||||
if (!thd->security_ctx->priv_user[0] &&
|
||||
check_global_access(thd,PROCESS_ACL))
|
||||
|
@ -3739,6 +3790,12 @@ end_with_restore_list:
|
|||
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;
|
||||
|
@ -3766,10 +3823,11 @@ end_with_restore_list:
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
|
||||
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:
|
||||
|
@ -4456,7 +4514,7 @@ create_sp_error:
|
|||
goto error;
|
||||
}
|
||||
|
||||
my_bool nsok= thd->net.no_send_ok;
|
||||
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||
thd->net.no_send_ok= TRUE;
|
||||
if (sp->m_flags & sp_head::MULTI_RESULTS)
|
||||
{
|
||||
|
@ -4467,7 +4525,7 @@ create_sp_error:
|
|||
back
|
||||
*/
|
||||
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
|
||||
thd->net.no_send_ok= nsok;
|
||||
thd->net.no_send_ok= save_no_send_ok;
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
|
@ -4483,7 +4541,7 @@ create_sp_error:
|
|||
if (check_routine_access(thd, EXECUTE_ACL,
|
||||
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
|
||||
{
|
||||
thd->net.no_send_ok= nsok;
|
||||
thd->net.no_send_ok= save_no_send_ok;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
|
@ -4508,7 +4566,7 @@ create_sp_error:
|
|||
|
||||
thd->variables.select_limit= select_limit;
|
||||
|
||||
thd->net.no_send_ok= nsok;
|
||||
thd->net.no_send_ok= save_no_send_ok;
|
||||
thd->server_status&= ~bits_to_be_cleared;
|
||||
|
||||
if (!res)
|
||||
|
@ -5917,15 +5975,17 @@ 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->col_list));
|
||||
lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
|
||||
HA_KEY_ALG_UNDEF, 0,
|
||||
lex->col_list));
|
||||
lex->col_list.empty();
|
||||
}
|
||||
|
||||
|
@ -5988,7 +6048,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
|
|||
interval_list, cs, uint_geom_type))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
lex->create_list.push_back(new_field);
|
||||
lex->alter_info.create_list.push_back(new_field);
|
||||
lex->last_field=new_field;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -7016,55 +7076,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.
|
||||
*/
|
||||
|
||||
bool 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;
|
||||
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->table_name,
|
||||
&create_info, table_list,
|
||||
fields, keys, 0, (ORDER*)0,
|
||||
0, &alter_info, 1));
|
||||
}
|
||||
|
||||
|
||||
bool 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;
|
||||
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name,
|
||||
&create_info, table_list,
|
||||
fields, keys, 0, (ORDER*)0,
|
||||
0, alter_info, 1));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Multi update query pre-check
|
||||
|
||||
|
@ -7363,7 +7374,6 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
|||
|
||||
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||
CREATE_TMP_ACL : CREATE_ACL);
|
||||
lex->create_info.alias= create_table->alias;
|
||||
if (check_access(thd, want_priv, create_table->db,
|
||||
&create_table->grant.privilege, 0, 0,
|
||||
test(create_table->schema_table)) ||
|
||||
|
|
|
@ -10434,6 +10434,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
|||
*/
|
||||
join->examined_rows++;
|
||||
join->thd->row_count++;
|
||||
join_tab->read_record.file->unlock_row();
|
||||
}
|
||||
return NESTED_LOOP_OK;
|
||||
}
|
||||
|
|
|
@ -460,7 +460,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
}
|
||||
|
||||
bool mysqld_show_create_db(THD *thd, char *dbname,
|
||||
HA_CREATE_INFO *create_info)
|
||||
const HA_CREATE_INFO *create_info)
|
||||
{
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
char buff[2048];
|
||||
|
|
170
sql/sql_table.cc
170
sql/sql_table.cc
|
@ -645,8 +645,7 @@ int prepare_create_field(create_field *sql_field,
|
|||
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.
|
||||
|
@ -660,8 +659,8 @@ int prepare_create_field(create_field *sql_field,
|
|||
*/
|
||||
|
||||
static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
List<create_field> *fields,
|
||||
List<Key> *keys, bool tmp_table,
|
||||
Alter_info *alter_info,
|
||||
bool tmp_table,
|
||||
uint *db_options,
|
||||
handler *file, KEY **key_info_buffer,
|
||||
uint *key_count, int select_field_count)
|
||||
|
@ -675,11 +674,12 @@ static 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(*fields),it2(*fields);
|
||||
List_iterator<create_field> it(alter_info->create_list);
|
||||
List_iterator<create_field> it2(alter_info->create_list);
|
||||
uint total_uneven_bit_length= 0;
|
||||
DBUG_ENTER("mysql_prepare_table");
|
||||
|
||||
select_field_pos= fields->elements - select_field_count;
|
||||
select_field_pos= alter_info->create_list.elements - select_field_count;
|
||||
null_fields=blob_columns=0;
|
||||
create_info->varchar= 0;
|
||||
max_key_length= file->max_key_length();
|
||||
|
@ -1004,7 +1004,8 @@ static 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;
|
||||
|
@ -1563,14 +1564,13 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
|
|||
|
||||
SYNOPSIS
|
||||
mysql_create_table()
|
||||
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
|
||||
internal_tmp_table Set to 1 if this is an internal temporary table
|
||||
(From ALTER TABLE)
|
||||
thd Thread object
|
||||
db Database
|
||||
table_name Table name
|
||||
create_info [in/out] Create information (like MAX_ROWS)
|
||||
alter_info [in/out] List of columns and indexes to create
|
||||
internal_tmp_table Set to 1 if this is an internal temporary table
|
||||
(From ALTER TABLE)
|
||||
|
||||
DESCRIPTION
|
||||
If one creates a temporary table, this is automatically opened
|
||||
|
@ -1580,6 +1580,11 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
|
|||
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
|
||||
FALSE OK
|
||||
TRUE error
|
||||
|
@ -1587,8 +1592,8 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
|
|||
|
||||
bool 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 internal_tmp_table,
|
||||
Alter_info *alter_info,
|
||||
bool internal_tmp_table,
|
||||
uint select_field_count)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
|
@ -1600,7 +1605,7 @@ bool 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_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
|
||||
MYF(0));
|
||||
|
@ -1644,10 +1649,10 @@ bool 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, internal_tmp_table, &db_options, file,
|
||||
&key_info_buffer, &key_count,
|
||||
select_field_count))
|
||||
if (mysql_prepare_table(thd, create_info, alter_info, internal_tmp_table,
|
||||
&db_options, file,
|
||||
&key_info_buffer, &key_count,
|
||||
select_field_count))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* Check if table exists */
|
||||
|
@ -1737,8 +1742,8 @@ bool 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_count,
|
||||
key_info_buffer))
|
||||
create_info, alter_info->create_list,
|
||||
key_count, key_info_buffer))
|
||||
goto end;
|
||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||
{
|
||||
|
@ -2323,9 +2328,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||
(table->table->file->ha_check_for_upgrade(check_opt) ==
|
||||
HA_ADMIN_NEEDS_ALTER))
|
||||
{
|
||||
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||
close_thread_tables(thd);
|
||||
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);
|
||||
goto send_result;
|
||||
}
|
||||
|
@ -2404,6 +2412,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,
|
||||
|
@ -2414,7 +2423,9 @@ send_result_message:
|
|||
*save_next_global= table->next_global;
|
||||
table->next_local= table->next_global= 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
|
||||
|
@ -2984,14 +2995,20 @@ 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.
|
||||
*/
|
||||
|
||||
bool 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,
|
||||
uint order_num, ORDER *order, bool ignore,
|
||||
ALTER_INFO *alter_info, bool do_send_ok)
|
||||
Alter_info *alter_info,
|
||||
uint order_num, ORDER *order, bool ignore)
|
||||
{
|
||||
TABLE *table,*new_table=0;
|
||||
int error;
|
||||
|
@ -3212,8 +3229,7 @@ view_err:
|
|||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
if (do_send_ok)
|
||||
send_ok(thd);
|
||||
send_ok(thd);
|
||||
}
|
||||
else if (error > 0)
|
||||
{
|
||||
|
@ -3240,10 +3256,9 @@ view_err:
|
|||
|
||||
restore_record(table, s->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;
|
||||
|
||||
/*
|
||||
|
@ -3291,13 +3306,13 @@ view_err:
|
|||
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++))
|
||||
|
@ -3321,7 +3336,7 @@ view_err:
|
|||
}
|
||||
}
|
||||
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)
|
||||
|
@ -3330,9 +3345,9 @@ view_err:
|
|||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
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;
|
||||
|
@ -3356,7 +3371,7 @@ view_err:
|
|||
alter_info->alter_list.head()->name, table_name);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if (!create_list.elements)
|
||||
if (!new_info.create_list.elements)
|
||||
{
|
||||
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
|
||||
MYF(0));
|
||||
|
@ -3368,8 +3383,8 @@ view_err:
|
|||
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;
|
||||
|
@ -3441,24 +3456,37 @@ view_err:
|
|||
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_info->algorithm,
|
||||
test(key_info->flags & HA_GENERATED_KEY),
|
||||
key_parts));
|
||||
{
|
||||
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);
|
||||
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))
|
||||
{
|
||||
|
@ -3593,7 +3621,7 @@ view_err:
|
|||
{
|
||||
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);
|
||||
|
@ -3634,9 +3662,9 @@ view_err:
|
|||
{
|
||||
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||
new_table->next_number_field=new_table->found_next_number_field;
|
||||
error=copy_data_between_tables(table, new_table, create_list, ignore,
|
||||
order_num, order, &copied, &deleted,
|
||||
alter_info->keys_onoff);
|
||||
error= copy_data_between_tables(table, new_table, new_info.create_list,
|
||||
ignore, order_num, order,
|
||||
&copied, &deleted, alter_info->keys_onoff);
|
||||
}
|
||||
else if (!new_table)
|
||||
{
|
||||
|
@ -3860,8 +3888,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(FALSE);
|
||||
|
||||
|
@ -4060,31 +4087,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().
|
||||
*/
|
||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
||||
bool do_send_ok)
|
||||
bool 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();
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
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_NOT_USED;
|
||||
create_info.default_table_charset=default_charset_info;
|
||||
/* Force alter table to recreate table */
|
||||
lex->alter_info.flags= ALTER_CHANGE_COLUMN;
|
||||
alter_info.flags= ALTER_CHANGE_COLUMN;
|
||||
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
|
||||
table_list, lex->create_list,
|
||||
lex->key_list, 0, (ORDER *) 0,
|
||||
0, &lex->alter_info, do_send_ok));
|
||||
table_list, &alter_info,
|
||||
0, (ORDER *) 0, 0));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1352,8 +1352,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));
|
||||
|
@ -1371,16 +1370,17 @@ 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.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
|
||||
|
@ -2920,29 +2920,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,
|
||||
$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,
|
||||
HA_KEY_ALG_UNDEF, 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->alter_info.key_list.push_back(key);
|
||||
key= new Key(Key::MULTIPLE, key_name,
|
||||
HA_KEY_ALG_UNDEF, 1,
|
||||
lex->col_list);
|
||||
lex->alter_info.key_list.push_back(key);
|
||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||
}
|
||||
| constraint opt_check_constraint
|
||||
|
@ -3484,8 +3489,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=
|
||||
|
@ -3495,8 +3498,7 @@ alter:
|
|||
lex->create_info.db_type= DB_TYPE_DEFAULT;
|
||||
lex->create_info.default_table_charset= NULL;
|
||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.flags= 0;
|
||||
lex->alter_info.reset();
|
||||
}
|
||||
alter_list
|
||||
{}
|
||||
|
@ -6254,7 +6256,8 @@ drop:
|
|||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command= SQLCOM_DROP_INDEX;
|
||||
lex->alter_info.drop_list.empty();
|
||||
lex->alter_info.reset();
|
||||
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,
|
||||
|
|
Loading…
Add table
Reference in a new issue