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"
|
if test "$THREAD_SAFE_CLIENT" = "no"
|
||||||
then
|
then
|
||||||
sql_client_dirs="strings regex mysys extra libmysql client"
|
sql_client_dirs="strings regex mysys dbug extra libmysql client"
|
||||||
else
|
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"
|
linked_client_targets="$linked_client_targets linked_libmysql_r_sources"
|
||||||
AC_CONFIG_FILES(libmysql_r/Makefile)
|
AC_CONFIG_FILES(libmysql_r/Makefile)
|
||||||
AC_DEFINE([THREAD_SAFE_CLIENT], [1], [Should be client be thread safe])
|
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)
|
uint16 *decode_table)
|
||||||
{
|
{
|
||||||
uint prev_offset;
|
uint prev_offset;
|
||||||
prev_offset= offset;
|
|
||||||
DBUG_ENTER("copy_decode_table");
|
DBUG_ENTER("copy_decode_table");
|
||||||
|
prev_offset= offset;
|
||||||
|
|
||||||
/* Descent on the left side. */
|
/* Descent on the left side. */
|
||||||
if (!(*decode_table & IS_CHAR))
|
if (!(*decode_table & IS_CHAR))
|
||||||
|
|
|
@ -87,11 +87,27 @@ x y z
|
||||||
rollback;
|
rollback;
|
||||||
commit;
|
commit;
|
||||||
begin;
|
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;
|
select * from t1 where y = 'one' or y = 'three' order by x for update;
|
||||||
x y z
|
x y z
|
||||||
1 one 1
|
1 one 1
|
||||||
3 three 3
|
3 three 3
|
||||||
begin;
|
begin;
|
||||||
|
select * from t1 where x = 2 for update;
|
||||||
|
x y z
|
||||||
|
2 two 2
|
||||||
select * from t1 where x = 1 for update;
|
select * from t1 where x = 1 for update;
|
||||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
rollback;
|
rollback;
|
||||||
|
@ -124,6 +140,22 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
rollback;
|
rollback;
|
||||||
commit;
|
commit;
|
||||||
begin;
|
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;
|
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
|
||||||
x y z
|
x y z
|
||||||
1 one 1
|
1 one 1
|
||||||
|
@ -132,6 +164,9 @@ begin;
|
||||||
select * from t1 where y = 'one' lock in share mode;
|
select * from t1 where y = 'one' lock in share mode;
|
||||||
x y z
|
x y z
|
||||||
1 one 1
|
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;
|
select * from t1 where x = 1 for update;
|
||||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
rollback;
|
rollback;
|
||||||
|
|
|
@ -1055,6 +1055,65 @@ EXECUTE stmt USING @a;
|
||||||
0 0
|
0 0
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
DROP TABLE IF EXISTS t1, t2;
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
PREPARE st_19182
|
||||||
|
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
j int(11) YES MUL NULL
|
||||||
|
i int(11) YES MUL NULL
|
||||||
|
DROP TABLE t2;
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
Field Type Null Key Default Extra
|
||||||
|
j int(11) YES MUL NULL
|
||||||
|
i int(11) YES MUL NULL
|
||||||
|
DEALLOCATE PREPARE st_19182;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
drop database if exists mysqltest;
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
create database mysqltest character set utf8;
|
||||||
|
prepare stmt1 from "create table mysqltest.t1 (c char(10))";
|
||||||
|
prepare stmt2 from "create table mysqltest.t2 select 'test'";
|
||||||
|
execute stmt1;
|
||||||
|
execute stmt2;
|
||||||
|
show create table mysqltest.t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`c` char(10) default NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8
|
||||||
|
show create table mysqltest.t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`test` 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.
|
End of 4.1 tests.
|
||||||
create table t1 (a varchar(20));
|
create table t1 (a varchar(20));
|
||||||
insert into t1 values ('foo');
|
insert into t1 values ('foo');
|
||||||
|
@ -1536,4 +1595,54 @@ a
|
||||||
2
|
2
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1,t2;
|
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.
|
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 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
|
1 SIMPLE t3 eq_ref PRIMARY,ci PRIMARY 4 test.t2.a 1 Using where
|
||||||
DROP TABLE t1,t2,t3;
|
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
|
Called B
|
||||||
drop procedure proc_21462_a|
|
drop procedure proc_21462_a|
|
||||||
drop procedure proc_21462_b|
|
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
|
End of 5.0 tests
|
||||||
DROP TABLE IF EXISTS bug23760|
|
DROP TABLE IF EXISTS bug23760|
|
||||||
DROP TABLE IF EXISTS bug23760_log|
|
DROP TABLE IF EXISTS bug23760_log|
|
||||||
|
|
|
@ -102,16 +102,36 @@ connection con1;
|
||||||
commit;
|
commit;
|
||||||
|
|
||||||
# table scan
|
# 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;
|
connection con1;
|
||||||
begin;
|
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;
|
connection con2;
|
||||||
begin;
|
begin;
|
||||||
# Have to check with pk access here since scans take locks on
|
# Have to check with pk access here since scans take locks on
|
||||||
# all rows and then release them in chunks
|
# 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
|
--error 1205
|
||||||
select * from t1 where x = 1 for update;
|
select * from t1 where x = 1 for update;
|
||||||
rollback;
|
rollback;
|
||||||
|
@ -157,15 +177,32 @@ commit;
|
||||||
# table scan
|
# table scan
|
||||||
connection con1;
|
connection con1;
|
||||||
begin;
|
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;
|
connection con2;
|
||||||
begin;
|
begin;
|
||||||
select * from t1 where y = 'one' lock in share mode;
|
select * from t1 where y = 'one' lock in share mode;
|
||||||
# Have to check with pk access here since scans take locks on
|
# Have to check with pk access here since scans take locks on
|
||||||
# all rows and then release them in chunks
|
# 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
|
--error 1205
|
||||||
select * from t1 where x = 1 for update;
|
select * from t1 where x = 1 for update;
|
||||||
rollback;
|
rollback;
|
||||||
|
|
|
@ -1106,11 +1106,95 @@ EXECUTE stmt USING @a;
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#19182: CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work
|
||||||
|
# from stored procedure.
|
||||||
|
#
|
||||||
|
# The cause of a bug was that cached LEX::create_list was modified,
|
||||||
|
# and then together with LEX::key_list was reset.
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
DROP TABLE IF EXISTS t1, t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
|
||||||
|
PREPARE st_19182
|
||||||
|
FROM "CREATE TABLE t2 (i INT, j INT, KEY (i), KEY(j)) SELECT i FROM t1";
|
||||||
|
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
|
||||||
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
# Check that on second execution we don't loose 'j' column and the keys
|
||||||
|
# on 'i' and 'j' columns.
|
||||||
|
EXECUTE st_19182;
|
||||||
|
DESC t2;
|
||||||
|
|
||||||
|
DEALLOCATE PREPARE st_19182;
|
||||||
|
DROP TABLE t2, t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
|
||||||
|
#
|
||||||
|
# Code which implemented CREATE/ALTER TABLE and CREATE DATABASE
|
||||||
|
# statement modified HA_CREATE_INFO structure in LEX, making these
|
||||||
|
# statements PS/SP-unsafe (their re-execution might have resulted
|
||||||
|
# in incorrect results).
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists mysqltest;
|
||||||
|
drop table if exists t1, t2;
|
||||||
|
--enable_warnings
|
||||||
|
# CREATE TABLE and CREATE TABLE ... SELECT
|
||||||
|
create database mysqltest character set utf8;
|
||||||
|
prepare stmt1 from "create table mysqltest.t1 (c char(10))";
|
||||||
|
prepare stmt2 from "create table mysqltest.t2 select 'test'";
|
||||||
|
execute stmt1;
|
||||||
|
execute stmt2;
|
||||||
|
show create table mysqltest.t1;
|
||||||
|
show create table mysqltest.t2;
|
||||||
|
drop table mysqltest.t1;
|
||||||
|
drop table mysqltest.t2;
|
||||||
|
alter database mysqltest character set latin1;
|
||||||
|
execute stmt1;
|
||||||
|
execute stmt2;
|
||||||
|
show create table mysqltest.t1;
|
||||||
|
show create table mysqltest.t2;
|
||||||
|
drop database mysqltest;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
deallocate prepare stmt2;
|
||||||
|
#
|
||||||
|
# CREATE TABLE with DATA DIRECTORY option
|
||||||
|
#
|
||||||
|
# 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.
|
--echo End of 4.1 tests.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
############################# 5.0 tests start ################################
|
############################# 5.0 tests start ################################
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -1585,5 +1669,76 @@ EXECUTE stmt USING @arg;
|
||||||
DEALLOCATE PREPARE stmt;
|
DEALLOCATE PREPARE stmt;
|
||||||
|
|
||||||
DROP TABLE t1,t2;
|
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.
|
--echo End of 5.0 tests.
|
||||||
|
|
|
@ -3092,3 +3092,23 @@ SELECT t3.a FROM t1,t2,t3
|
||||||
t3.c IN ('bb','ee');
|
t3.c IN ('bb','ee');
|
||||||
|
|
||||||
DROP TABLE t1,t2,t3;
|
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_a|
|
||||||
drop procedure proc_21462_b|
|
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
|
--echo End of 5.0 tests
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6111,7 +6111,7 @@ ndb_get_table_statistics(ha_ndbcluster* file, bool report_error, Ndb* ndb,
|
||||||
retry:
|
retry:
|
||||||
if(report_error)
|
if(report_error)
|
||||||
{
|
{
|
||||||
if (file)
|
if (file && pTrans)
|
||||||
{
|
{
|
||||||
reterr= file->ndb_err(pTrans);
|
reterr= file->ndb_err(pTrans);
|
||||||
}
|
}
|
||||||
|
|
|
@ -773,17 +773,15 @@ int prepare_create_field(create_field *sql_field,
|
||||||
uint table_flags);
|
uint table_flags);
|
||||||
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields, List<Key> &keys,
|
Alter_info *alter_info,
|
||||||
bool tmp_table, uint select_field_count);
|
bool tmp_table, uint select_field_count);
|
||||||
|
|
||||||
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
List<create_field> &fields,
|
Alter_info *alter_info,
|
||||||
List<Key> &keys,
|
uint order_num, ORDER *order, bool ignore);
|
||||||
uint order_num, ORDER *order, bool ignore,
|
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list);
|
||||||
ALTER_INFO *alter_info, bool do_send_ok);
|
|
||||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
|
||||||
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
Table_ident *src_table);
|
Table_ident *src_table);
|
||||||
|
@ -792,9 +790,6 @@ bool mysql_rename_table(enum db_type base,
|
||||||
const char * old_name,
|
const char * old_name,
|
||||||
const char *new_db,
|
const char *new_db,
|
||||||
const char * new_name);
|
const char * new_name);
|
||||||
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,
|
bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
||||||
Item **conds, uint order_num, ORDER *order);
|
Item **conds, uint order_num, ORDER *order);
|
||||||
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
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);
|
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);
|
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(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);
|
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
|
||||||
int mysqld_show_status(THD *thd);
|
int mysqld_show_status(THD *thd);
|
||||||
|
|
|
@ -5466,6 +5466,11 @@ log and this option does nothing anymore.",
|
||||||
0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0},
|
||||||
{"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.",
|
{"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,
|
(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},
|
IF_PURIFY(0,1), 0, 0, 0, 0, 0},
|
||||||
{"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
{"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
||||||
0, 0, 0, 0, 0, 0},
|
0, 0, 0, 0, 0, 0},
|
||||||
|
|
|
@ -1839,21 +1839,22 @@ class select_insert :public select_result_interceptor {
|
||||||
class select_create: public select_insert {
|
class select_create: public select_insert {
|
||||||
ORDER *group;
|
ORDER *group;
|
||||||
TABLE_LIST *create_table;
|
TABLE_LIST *create_table;
|
||||||
List<create_field> *extra_fields;
|
|
||||||
List<Key> *keys;
|
|
||||||
HA_CREATE_INFO *create_info;
|
HA_CREATE_INFO *create_info;
|
||||||
|
Alter_info *alter_info;
|
||||||
MYSQL_LOCK *lock;
|
MYSQL_LOCK *lock;
|
||||||
Field **field;
|
Field **field;
|
||||||
public:
|
public:
|
||||||
select_create (TABLE_LIST *table,
|
select_create(TABLE_LIST *table,
|
||||||
HA_CREATE_INFO *create_info_par,
|
HA_CREATE_INFO *create_info_arg,
|
||||||
List<create_field> &fields_par,
|
Alter_info *alter_info_arg,
|
||||||
List<Key> &keys_par,
|
List<Item> &select_fields,
|
||||||
List<Item> &select_fields,enum_duplicates duplic, bool ignore)
|
enum_duplicates duplic, bool ignore)
|
||||||
:select_insert (NULL, NULL, &select_fields, 0, 0, duplic, ignore), create_table(table),
|
:select_insert(NULL, NULL, &select_fields, 0, 0, duplic, ignore),
|
||||||
extra_fields(&fields_par),keys(&keys_par), create_info(create_info_par),
|
create_table(table),
|
||||||
|
create_info(create_info_arg),
|
||||||
|
alter_info(alter_info_arg),
|
||||||
lock(0)
|
lock(0)
|
||||||
{}
|
{}
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
void store_values(List<Item> &values);
|
void store_values(List<Item> &values);
|
||||||
void send_error(uint errcode,const char *err);
|
void send_error(uint errcode,const char *err);
|
||||||
|
|
|
@ -2616,11 +2616,11 @@ bool select_insert::send_eof()
|
||||||
temporary table flag)
|
temporary table flag)
|
||||||
create_table in Pointer to TABLE_LIST object providing database
|
create_table in Pointer to TABLE_LIST object providing database
|
||||||
and name for table to be created or to be open
|
and name for table to be created or to be open
|
||||||
extra_fields in/out Initial list of fields for table to be created
|
alter_info in/out Initial list of columns and indexes for the table
|
||||||
keys in List of keys for table to be created
|
to be created
|
||||||
items in List of items which should be used to produce rest
|
items in List of items which should be used to produce rest
|
||||||
of fields for the table (corresponding fields will
|
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
|
lock out Pointer to the MYSQL_LOCK object for table created
|
||||||
(open) will be returned in this parameter. Since
|
(open) will be returned in this parameter. Since
|
||||||
this table is not included in THD::lock caller is
|
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,
|
static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *create_table,
|
TABLE_LIST *create_table,
|
||||||
List<create_field> *extra_fields,
|
Alter_info *alter_info,
|
||||||
List<Key> *keys, List<Item> *items,
|
List<Item> *items,
|
||||||
MYSQL_LOCK **lock)
|
MYSQL_LOCK **lock)
|
||||||
{
|
{
|
||||||
TABLE tmp_table; // Used during 'create_field()'
|
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);
|
DBUG_RETURN(0);
|
||||||
if (item->maybe_null)
|
if (item->maybe_null)
|
||||||
cr_field->flags &= ~NOT_NULL_FLAG;
|
cr_field->flags &= ~NOT_NULL_FLAG;
|
||||||
extra_fields->push_back(cr_field);
|
alter_info->create_list.push_back(cr_field);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
create and lock table
|
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);
|
tmp_disable_binlog(thd);
|
||||||
if (!mysql_create_table(thd, create_table->db, create_table->table_name,
|
if (!mysql_create_table(thd, create_table->db, create_table->table_name,
|
||||||
create_info, *extra_fields, *keys, 0,
|
create_info, alter_info, 0, select_field_count))
|
||||||
select_field_count))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we are here in prelocked mode we either create temporary table
|
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;
|
unit= u;
|
||||||
table= create_table_from_items(thd, create_info, create_table,
|
table= create_table_from_items(thd, create_info, create_table,
|
||||||
extra_fields, keys, &values, &lock);
|
alter_info, &values, &lock);
|
||||||
if (!table)
|
if (!table)
|
||||||
DBUG_RETURN(-1); // abort() deletes table
|
DBUG_RETURN(-1); // abort() deletes table
|
||||||
|
|
||||||
|
|
|
@ -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.
|
Skip comment in the end of statement.
|
||||||
|
|
||||||
|
|
|
@ -686,18 +686,58 @@ typedef class st_select_lex SELECT_LEX;
|
||||||
#define ALTER_CONVERT 1024
|
#define ALTER_CONVERT 1024
|
||||||
#define ALTER_FORCE 2048
|
#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_drop> drop_list;
|
||||||
List<Alter_column> alter_list;
|
List<Alter_column> alter_list;
|
||||||
|
List<Key> key_list;
|
||||||
|
List<create_field> create_list;
|
||||||
uint flags;
|
uint flags;
|
||||||
enum enum_enable_or_disable keys_onoff;
|
enum enum_enable_or_disable keys_onoff;
|
||||||
enum tablespace_op_type tablespace_op;
|
enum tablespace_op_type tablespace_op;
|
||||||
|
|
||||||
st_alter_info(){clear();}
|
Alter_info() :
|
||||||
void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
|
flags(0),
|
||||||
void reset(){drop_list.empty();alter_list.empty();clear();}
|
keys_onoff(LEAVE_AS_IS),
|
||||||
} ALTER_INFO;
|
tablespace_op(NO_TABLESPACE_OP)
|
||||||
|
{}
|
||||||
|
|
||||||
|
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
|
struct st_sp_chistics
|
||||||
{
|
{
|
||||||
|
@ -883,8 +923,6 @@ typedef struct st_lex : public Query_tables_list
|
||||||
List<String> interval_list;
|
List<String> interval_list;
|
||||||
List<LEX_USER> users_list;
|
List<LEX_USER> users_list;
|
||||||
List<LEX_COLUMN> columns;
|
List<LEX_COLUMN> columns;
|
||||||
List<Key> key_list;
|
|
||||||
List<create_field> create_list;
|
|
||||||
List<Item> *insert_list,field_list,value_list,update_list;
|
List<Item> *insert_list,field_list,value_list,update_list;
|
||||||
List<List_item> many_values;
|
List<List_item> many_values;
|
||||||
List<set_var_base> var_list;
|
List<set_var_base> var_list;
|
||||||
|
@ -977,7 +1015,7 @@ typedef struct st_lex : public Query_tables_list
|
||||||
bool safe_to_cache_query;
|
bool safe_to_cache_query;
|
||||||
bool subqueries, ignore;
|
bool subqueries, ignore;
|
||||||
st_parsing_options parsing_options;
|
st_parsing_options parsing_options;
|
||||||
ALTER_INFO alter_info;
|
Alter_info alter_info;
|
||||||
/* Prepared statements SQL syntax:*/
|
/* Prepared statements SQL syntax:*/
|
||||||
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -61,21 +61,24 @@ public:
|
||||||
pointer.
|
pointer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class list_node :public Sql_alloc
|
|
||||||
|
/**
|
||||||
|
list_node - a node of a single-linked list.
|
||||||
|
@note We never call a destructor for instances of this class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct list_node :public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
list_node *next;
|
list_node *next;
|
||||||
void *info;
|
void *info;
|
||||||
list_node(void *info_par,list_node *next_par)
|
list_node(void *info_par,list_node *next_par)
|
||||||
:next(next_par),info(info_par)
|
:next(next_par),info(info_par)
|
||||||
{}
|
{}
|
||||||
list_node() /* For end_of_list */
|
list_node() /* For end_of_list */
|
||||||
{
|
{
|
||||||
info=0;
|
info= 0;
|
||||||
next= this;
|
next= this;
|
||||||
}
|
}
|
||||||
friend class base_list;
|
|
||||||
friend class base_list_iterator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,12 +94,57 @@ public:
|
||||||
|
|
||||||
inline void empty() { elements=0; first= &end_of_list; last=&first;}
|
inline void empty() { elements=0; first= &end_of_list; last=&first;}
|
||||||
inline base_list() { empty(); }
|
inline base_list() { empty(); }
|
||||||
|
/**
|
||||||
|
This is a shallow copy constructor that implicitly passes the ownership
|
||||||
|
from the source list to the new instance. The old instance is not
|
||||||
|
updated, so both objects end up sharing the same nodes. If one of
|
||||||
|
the instances then adds or removes a node, the other becomes out of
|
||||||
|
sync ('last' pointer), while still operational. Some old code uses and
|
||||||
|
relies on this behaviour. This logic is quite tricky: please do not use
|
||||||
|
it in any new code.
|
||||||
|
*/
|
||||||
inline base_list(const base_list &tmp) :Sql_alloc()
|
inline base_list(const base_list &tmp) :Sql_alloc()
|
||||||
{
|
{
|
||||||
elements= tmp.elements;
|
elements= tmp.elements;
|
||||||
first= tmp.first;
|
first= tmp.first;
|
||||||
last= elements ? tmp.last : &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 base_list(bool error) { }
|
||||||
inline bool push_back(void *info)
|
inline bool push_back(void *info)
|
||||||
{
|
{
|
||||||
|
@ -347,6 +395,8 @@ template <class T> class List :public base_list
|
||||||
public:
|
public:
|
||||||
inline List() :base_list() {}
|
inline List() :base_list() {}
|
||||||
inline List(const List<T> &tmp) :base_list(tmp) {}
|
inline List(const List<T> &tmp) :base_list(tmp) {}
|
||||||
|
inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
|
||||||
|
base_list(tmp, mem_root) {}
|
||||||
inline bool push_back(T *a) { return base_list::push_back(a); }
|
inline bool push_back(T *a) { return base_list::push_back(a); }
|
||||||
inline bool push_back(T *a, MEM_ROOT *mem_root)
|
inline bool push_back(T *a, MEM_ROOT *mem_root)
|
||||||
{ return base_list::push_back(a, 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
|
// Skip first table, which is the table we are creating
|
||||||
TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
|
TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local);
|
||||||
TABLE_LIST *select_tables= lex->query_tables;
|
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)))
|
if ((res= create_table_precheck(thd, select_tables, create_table)))
|
||||||
goto end_with_restore_list;
|
goto end_with_restore_list;
|
||||||
|
|
||||||
|
create_info.alias= create_table->alias;
|
||||||
|
|
||||||
#ifndef HAVE_READLINK
|
#ifndef HAVE_READLINK
|
||||||
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
|
create_info.data_file_name= create_info.index_file_name= NULL;
|
||||||
#else
|
#else
|
||||||
/* Fix names if symlinked tables */
|
/* Fix names if symlinked tables */
|
||||||
if (append_file_to_dir(thd, &lex->create_info.data_file_name,
|
if (append_file_to_dir(thd, &create_info.data_file_name,
|
||||||
create_table->table_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))
|
create_table->table_name))
|
||||||
goto end_with_restore_list;
|
goto end_with_restore_list;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2912,14 +2930,14 @@ mysql_execute_command(THD *thd)
|
||||||
If we are using SET CHARSET without DEFAULT, add an implicit
|
If we are using SET CHARSET without DEFAULT, add an implicit
|
||||||
DEFAULT to not confuse old users. (This may change).
|
DEFAULT to not confuse old users. (This may change).
|
||||||
*/
|
*/
|
||||||
if ((lex->create_info.used_fields &
|
if ((create_info.used_fields &
|
||||||
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
|
(HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
|
||||||
HA_CREATE_USED_CHARSET)
|
HA_CREATE_USED_CHARSET)
|
||||||
{
|
{
|
||||||
lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
|
||||||
lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
|
||||||
lex->create_info.default_table_charset= lex->create_info.table_charset;
|
create_info.default_table_charset= create_info.table_charset;
|
||||||
lex->create_info.table_charset= 0;
|
create_info.table_charset= 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
The create-select command will open and read-lock the select table
|
The create-select command will open and read-lock the select table
|
||||||
|
@ -2953,7 +2971,7 @@ mysql_execute_command(THD *thd)
|
||||||
Is table which we are changing used somewhere in other parts
|
Is table which we are changing used somewhere in other parts
|
||||||
of query
|
of query
|
||||||
*/
|
*/
|
||||||
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
|
||||||
{
|
{
|
||||||
TABLE_LIST *duplicate;
|
TABLE_LIST *duplicate;
|
||||||
if ((duplicate= unique_table(thd, create_table, select_tables)))
|
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 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;
|
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= tab->next_local)
|
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,
|
if ((result= new select_create(create_table,
|
||||||
&lex->create_info,
|
&create_info,
|
||||||
lex->create_list,
|
&alter_info,
|
||||||
lex->key_list,
|
select_lex->item_list,
|
||||||
select_lex->item_list,
|
lex->duplicates,
|
||||||
lex->duplicates,
|
lex->ignore)))
|
||||||
lex->ignore)))
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
CREATE from SELECT give its SELECT_LEX for SELECT,
|
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);
|
res= handle_select(thd, lex, result, 0);
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
/* reset for PS */
|
|
||||||
lex->create_list.empty();
|
|
||||||
lex->key_list.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* regular create */
|
/* regular create */
|
||||||
if (lex->name)
|
if (lex->name)
|
||||||
res= mysql_create_like_table(thd, create_table, &lex->create_info,
|
res= mysql_create_like_table(thd, create_table, &create_info,
|
||||||
(Table_ident *)lex->name);
|
(Table_ident *)lex->name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res= mysql_create_table(thd, create_table->db,
|
res= mysql_create_table(thd, create_table->db,
|
||||||
create_table->table_name, &lex->create_info,
|
create_table->table_name, &create_info,
|
||||||
lex->create_list,
|
&alter_info, 0, 0);
|
||||||
lex->key_list, 0, 0);
|
|
||||||
}
|
}
|
||||||
if (!res)
|
if (!res)
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
@ -3024,16 +3040,49 @@ end_with_restore_list:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_CREATE_INDEX:
|
case SQLCOM_CREATE_INDEX:
|
||||||
|
/* Fall through */
|
||||||
|
case SQLCOM_DROP_INDEX:
|
||||||
|
/*
|
||||||
|
CREATE INDEX and DROP INDEX are implemented by calling ALTER
|
||||||
|
TABLE with proper arguments. This isn't very fast but it
|
||||||
|
should work for most cases.
|
||||||
|
|
||||||
|
In the future ALTER TABLE will notice that only added
|
||||||
|
indexes and create these one by one for the existing table
|
||||||
|
without having to do a full rebuild.
|
||||||
|
|
||||||
|
One should normally create all indexes with CREATE TABLE or
|
||||||
|
ALTER TABLE.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
HA_CREATE_INFO create_info;
|
||||||
|
|
||||||
|
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info*/
|
||||||
|
goto error;
|
||||||
|
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
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 */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
else
|
/*
|
||||||
res = mysql_create_index(thd, first_table, lex->key_list);
|
Currently CREATE INDEX or DROP INDEX cause a full table rebuild
|
||||||
break;
|
and thus classify as slow administrative statements just like
|
||||||
|
ALTER TABLE.
|
||||||
|
*/
|
||||||
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
|
|
||||||
|
bzero((char*) &create_info, sizeof(create_info));
|
||||||
|
create_info.db_type= DB_TYPE_DEFAULT;
|
||||||
|
create_info.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
|
#ifdef HAVE_REPLICATION
|
||||||
case SQLCOM_SLAVE_START:
|
case SQLCOM_SLAVE_START:
|
||||||
{
|
{
|
||||||
|
@ -3074,6 +3123,17 @@ end_with_restore_list:
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
{
|
{
|
||||||
ulong priv=0;
|
ulong priv=0;
|
||||||
|
/*
|
||||||
|
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
|
||||||
|
so we have to use a copy of this structure to make execution
|
||||||
|
prepared statement- safe. A shallow copy is enough as no memory
|
||||||
|
referenced from this structure will be modified.
|
||||||
|
*/
|
||||||
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
|
Alter_info alter_info(lex->alter_info, thd->mem_root);
|
||||||
|
|
||||||
|
if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
|
||||||
|
goto error;
|
||||||
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
|
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
|
my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
|
||||||
|
@ -3088,7 +3148,7 @@ end_with_restore_list:
|
||||||
is_schema_db(select_lex->db))||
|
is_schema_db(select_lex->db))||
|
||||||
check_merge_table_access(thd, first_table->db,
|
check_merge_table_access(thd, first_table->db,
|
||||||
(TABLE_LIST *)
|
(TABLE_LIST *)
|
||||||
lex->create_info.merge_list.first))
|
create_info.merge_list.first))
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
if (grant_option)
|
if (grant_option)
|
||||||
{
|
{
|
||||||
|
@ -3107,13 +3167,13 @@ end_with_restore_list:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Don't yet allow changing of symlinks with ALTER TABLE */
|
/* Don't yet allow changing of symlinks with ALTER TABLE */
|
||||||
if (lex->create_info.data_file_name)
|
if (create_info.data_file_name)
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||||
"DATA DIRECTORY option ignored");
|
"DATA DIRECTORY option ignored");
|
||||||
if (lex->create_info.index_file_name)
|
if (create_info.index_file_name)
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
|
||||||
"INDEX DIRECTORY option ignored");
|
"INDEX DIRECTORY option ignored");
|
||||||
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
|
create_info.data_file_name= create_info.index_file_name= NULL;
|
||||||
/* ALTER TABLE ends previous transaction */
|
/* ALTER TABLE ends previous transaction */
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -3127,13 +3187,13 @@ end_with_restore_list:
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
res= mysql_alter_table(thd, select_lex->db, lex->name,
|
||||||
&lex->create_info,
|
&create_info,
|
||||||
first_table, lex->create_list,
|
first_table,
|
||||||
lex->key_list,
|
&alter_info,
|
||||||
select_lex->order_list.elements,
|
select_lex->order_list.elements,
|
||||||
(ORDER *) select_lex->order_list.first,
|
(ORDER *) select_lex->order_list.first,
|
||||||
lex->ignore, &lex->alter_info, 1);
|
lex->ignore);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3286,7 +3346,7 @@ end_with_restore_list:
|
||||||
goto error; /* purecov: inspected */
|
goto error; /* purecov: inspected */
|
||||||
thd->enable_slow_log= opt_log_slow_admin_statements;
|
thd->enable_slow_log= opt_log_slow_admin_statements;
|
||||||
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
|
||||||
mysql_recreate_table(thd, first_table, 1) :
|
mysql_recreate_table(thd, first_table) :
|
||||||
mysql_optimize_table(thd, first_table, &lex->check_opt);
|
mysql_optimize_table(thd, first_table, &lex->check_opt);
|
||||||
/* ! we write after unlocking the table */
|
/* ! we write after unlocking the table */
|
||||||
if (!res && !lex->no_write_to_binlog)
|
if (!res && !lex->no_write_to_binlog)
|
||||||
|
@ -3602,15 +3662,6 @@ end_with_restore_list:
|
||||||
lex->drop_temporary);
|
lex->drop_temporary);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case SQLCOM_SHOW_PROCESSLIST:
|
||||||
if (!thd->security_ctx->priv_user[0] &&
|
if (!thd->security_ctx->priv_user[0] &&
|
||||||
check_global_access(thd,PROCESS_ACL))
|
check_global_access(thd,PROCESS_ACL))
|
||||||
|
@ -3739,6 +3790,12 @@ end_with_restore_list:
|
||||||
break;
|
break;
|
||||||
case SQLCOM_CREATE_DB:
|
case SQLCOM_CREATE_DB:
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
As mysql_create_db() may modify HA_CREATE_INFO structure passed to
|
||||||
|
it, we need to use a copy of LEX::create_info to make execution
|
||||||
|
prepared statement- safe.
|
||||||
|
*/
|
||||||
|
HA_CREATE_INFO create_info(lex->create_info);
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
{
|
{
|
||||||
res= -1;
|
res= -1;
|
||||||
|
@ -3766,10 +3823,11 @@ end_with_restore_list:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
|
if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name)))
|
||||||
break;
|
break;
|
||||||
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
|
res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name),
|
||||||
&lex->create_info, 0);
|
&create_info, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_DROP_DB:
|
case SQLCOM_DROP_DB:
|
||||||
|
@ -4456,7 +4514,7 @@ create_sp_error:
|
||||||
goto 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;
|
thd->net.no_send_ok= TRUE;
|
||||||
if (sp->m_flags & sp_head::MULTI_RESULTS)
|
if (sp->m_flags & sp_head::MULTI_RESULTS)
|
||||||
{
|
{
|
||||||
|
@ -4467,7 +4525,7 @@ create_sp_error:
|
||||||
back
|
back
|
||||||
*/
|
*/
|
||||||
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -4483,7 +4541,7 @@ create_sp_error:
|
||||||
if (check_routine_access(thd, EXECUTE_ACL,
|
if (check_routine_access(thd, EXECUTE_ACL,
|
||||||
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -4508,7 +4566,7 @@ create_sp_error:
|
||||||
|
|
||||||
thd->variables.select_limit= select_limit;
|
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;
|
thd->server_status&= ~bits_to_be_cleared;
|
||||||
|
|
||||||
if (!res)
|
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)
|
if (type_modifier & PRI_KEY_FLAG)
|
||||||
{
|
{
|
||||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||||
lex->key_list.push_back(new Key(Key::PRIMARY, NullS, HA_KEY_ALG_UNDEF,
|
lex->alter_info.key_list.push_back(new Key(Key::PRIMARY, NullS,
|
||||||
0, lex->col_list));
|
HA_KEY_ALG_UNDEF, 0,
|
||||||
|
lex->col_list));
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
}
|
}
|
||||||
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
||||||
{
|
{
|
||||||
lex->col_list.push_back(new key_part_spec(field_name,0));
|
lex->col_list.push_back(new key_part_spec(field_name,0));
|
||||||
lex->key_list.push_back(new Key(Key::UNIQUE, NullS, HA_KEY_ALG_UNDEF, 0,
|
lex->alter_info.key_list.push_back(new Key(Key::UNIQUE, NullS,
|
||||||
lex->col_list));
|
HA_KEY_ALG_UNDEF, 0,
|
||||||
|
lex->col_list));
|
||||||
lex->col_list.empty();
|
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))
|
interval_list, cs, uint_geom_type))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
lex->create_list.push_back(new_field);
|
lex->alter_info.create_list.push_back(new_field);
|
||||||
lex->last_field=new_field;
|
lex->last_field=new_field;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -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
|
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) ?
|
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||||
CREATE_TMP_ACL : CREATE_ACL);
|
CREATE_TMP_ACL : CREATE_ACL);
|
||||||
lex->create_info.alias= create_table->alias;
|
|
||||||
if (check_access(thd, want_priv, create_table->db,
|
if (check_access(thd, want_priv, create_table->db,
|
||||||
&create_table->grant.privilege, 0, 0,
|
&create_table->grant.privilege, 0, 0,
|
||||||
test(create_table->schema_table)) ||
|
test(create_table->schema_table)) ||
|
||||||
|
|
|
@ -10434,6 +10434,7 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
|
||||||
*/
|
*/
|
||||||
join->examined_rows++;
|
join->examined_rows++;
|
||||||
join->thd->row_count++;
|
join->thd->row_count++;
|
||||||
|
join_tab->read_record.file->unlock_row();
|
||||||
}
|
}
|
||||||
return NESTED_LOOP_OK;
|
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,
|
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;
|
Security_context *sctx= thd->security_ctx;
|
||||||
char buff[2048];
|
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()
|
mysql_prepare_table()
|
||||||
thd Thread object
|
thd Thread object
|
||||||
create_info Create information (like MAX_ROWS)
|
create_info Create information (like MAX_ROWS)
|
||||||
fields List of fields to create
|
alter_info List of columns and indexes to create
|
||||||
keys List of keys to create
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Prepares the table and key structures for table creation.
|
Prepares the table and key structures for table creation.
|
||||||
|
@ -660,8 +659,8 @@ int prepare_create_field(create_field *sql_field,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
List<create_field> *fields,
|
Alter_info *alter_info,
|
||||||
List<Key> *keys, bool tmp_table,
|
bool tmp_table,
|
||||||
uint *db_options,
|
uint *db_options,
|
||||||
handler *file, KEY **key_info_buffer,
|
handler *file, KEY **key_info_buffer,
|
||||||
uint *key_count, int select_field_count)
|
uint *key_count, int select_field_count)
|
||||||
|
@ -675,11 +674,12 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
int timestamps= 0, timestamps_with_niladic= 0;
|
int timestamps= 0, timestamps_with_niladic= 0;
|
||||||
int field_no,dup_no;
|
int field_no,dup_no;
|
||||||
int select_field_pos,auto_increment=0;
|
int select_field_pos,auto_increment=0;
|
||||||
List_iterator<create_field> it(*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;
|
uint total_uneven_bit_length= 0;
|
||||||
DBUG_ENTER("mysql_prepare_table");
|
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;
|
null_fields=blob_columns=0;
|
||||||
create_info->varchar= 0;
|
create_info->varchar= 0;
|
||||||
max_key_length= file->max_key_length();
|
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 */
|
/* Create keys */
|
||||||
|
|
||||||
List_iterator<Key> key_iterator(*keys), key_iterator2(*keys);
|
List_iterator<Key> key_iterator(alter_info->key_list);
|
||||||
|
List_iterator<Key> key_iterator2(alter_info->key_list);
|
||||||
uint key_parts=0, fk_key_count=0;
|
uint key_parts=0, fk_key_count=0;
|
||||||
bool primary_key=0,unique_key=0;
|
bool primary_key=0,unique_key=0;
|
||||||
Key *key, *key2;
|
Key *key, *key2;
|
||||||
|
@ -1563,14 +1564,13 @@ void sp_prepare_create_field(THD *thd, create_field *sql_field)
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
mysql_create_table()
|
mysql_create_table()
|
||||||
thd Thread object
|
thd Thread object
|
||||||
db Database
|
db Database
|
||||||
table_name Table name
|
table_name Table name
|
||||||
create_info Create information (like MAX_ROWS)
|
create_info [in/out] Create information (like MAX_ROWS)
|
||||||
fields List of fields to create
|
alter_info [in/out] List of columns and indexes to create
|
||||||
keys List of keys to create
|
internal_tmp_table Set to 1 if this is an internal temporary table
|
||||||
internal_tmp_table Set to 1 if this is an internal temporary table
|
(From ALTER TABLE)
|
||||||
(From ALTER TABLE)
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
If one creates a temporary table, this is automatically opened
|
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,
|
select_field_count is also used for CREATE ... SELECT,
|
||||||
and must be zero for standard create of table.
|
and must be zero for standard create of table.
|
||||||
|
|
||||||
|
Note that structures passed as 'create_info' and 'alter_info' parameters
|
||||||
|
may be modified by this function. It is responsibility of the caller to
|
||||||
|
make a copy of create_info in order to provide correct execution in
|
||||||
|
prepared statements/stored routines.
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE error
|
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,
|
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &fields,
|
Alter_info *alter_info,
|
||||||
List<Key> &keys,bool internal_tmp_table,
|
bool internal_tmp_table,
|
||||||
uint select_field_count)
|
uint select_field_count)
|
||||||
{
|
{
|
||||||
char path[FN_REFLEN];
|
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");
|
DBUG_ENTER("mysql_create_table");
|
||||||
|
|
||||||
/* Check for duplicate fields and check type of table to create */
|
/* Check for duplicate fields and check type of table to create */
|
||||||
if (!fields.elements)
|
if (!alter_info->create_list.elements)
|
||||||
{
|
{
|
||||||
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
|
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
|
||||||
MYF(0));
|
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;
|
create_info->default_table_charset= db_info.default_table_charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mysql_prepare_table(thd, create_info, &fields,
|
if (mysql_prepare_table(thd, create_info, alter_info, internal_tmp_table,
|
||||||
&keys, internal_tmp_table, &db_options, file,
|
&db_options, file,
|
||||||
&key_info_buffer, &key_count,
|
&key_info_buffer, &key_count,
|
||||||
select_field_count))
|
select_field_count))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* Check if table exists */
|
/* 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;
|
create_info->table_options=db_options;
|
||||||
|
|
||||||
if (rea_create_table(thd, path, db, table_name,
|
if (rea_create_table(thd, path, db, table_name,
|
||||||
create_info, fields, key_count,
|
create_info, alter_info->create_list,
|
||||||
key_info_buffer))
|
key_count, key_info_buffer))
|
||||||
goto end;
|
goto end;
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
{
|
{
|
||||||
|
@ -2323,9 +2328,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||||
(table->table->file->ha_check_for_upgrade(check_opt) ==
|
(table->table->file->ha_check_for_upgrade(check_opt) ==
|
||||||
HA_ADMIN_NEEDS_ALTER))
|
HA_ADMIN_NEEDS_ALTER))
|
||||||
{
|
{
|
||||||
|
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||||
result_code= mysql_recreate_table(thd, table, 0);
|
thd->net.no_send_ok= TRUE;
|
||||||
|
result_code= mysql_recreate_table(thd, table);
|
||||||
|
thd->net.no_send_ok= save_no_send_ok;
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
goto send_result;
|
goto send_result;
|
||||||
}
|
}
|
||||||
|
@ -2404,6 +2412,7 @@ send_result_message:
|
||||||
|
|
||||||
case HA_ADMIN_TRY_ALTER:
|
case HA_ADMIN_TRY_ALTER:
|
||||||
{
|
{
|
||||||
|
my_bool save_no_send_ok= thd->net.no_send_ok;
|
||||||
/*
|
/*
|
||||||
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
||||||
"try with alter", so here we close the table, do an ALTER TABLE,
|
"try with alter", so here we close the table, do an ALTER TABLE,
|
||||||
|
@ -2414,7 +2423,9 @@ send_result_message:
|
||||||
*save_next_global= table->next_global;
|
*save_next_global= table->next_global;
|
||||||
table->next_local= table->next_global= 0;
|
table->next_local= table->next_global= 0;
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||||
result_code= mysql_recreate_table(thd, table, 0);
|
thd->net.no_send_ok= TRUE;
|
||||||
|
result_code= mysql_recreate_table(thd, table);
|
||||||
|
thd->net.no_send_ok= save_no_send_ok;
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
if (!result_code) // recreation went ok
|
if (!result_code) // recreation went ok
|
||||||
|
@ -2984,14 +2995,20 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Alter table
|
Alter table
|
||||||
|
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
The structures passed as 'create_info' and 'alter_info' parameters may
|
||||||
|
be modified by this function. It is responsibility of the caller to make
|
||||||
|
a copy of create_info in order to provide correct execution in prepared
|
||||||
|
statements/stored routines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
List<create_field> &fields, List<Key> &keys,
|
Alter_info *alter_info,
|
||||||
uint order_num, ORDER *order, bool ignore,
|
uint order_num, ORDER *order, bool ignore)
|
||||||
ALTER_INFO *alter_info, bool do_send_ok)
|
|
||||||
{
|
{
|
||||||
TABLE *table,*new_table=0;
|
TABLE *table,*new_table=0;
|
||||||
int error;
|
int error;
|
||||||
|
@ -3212,8 +3229,7 @@ view_err:
|
||||||
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
if (do_send_ok)
|
send_ok(thd);
|
||||||
send_ok(thd);
|
|
||||||
}
|
}
|
||||||
else if (error > 0)
|
else if (error > 0)
|
||||||
{
|
{
|
||||||
|
@ -3240,10 +3256,9 @@ view_err:
|
||||||
|
|
||||||
restore_record(table, s->default_values); // Empty record for DEFAULT
|
restore_record(table, s->default_values); // Empty record for DEFAULT
|
||||||
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
||||||
List_iterator<create_field> def_it(fields);
|
List_iterator<create_field> def_it(alter_info->create_list);
|
||||||
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
||||||
List<create_field> create_list; // Add new fields here
|
Alter_info new_info; // Add new columns and indexes here
|
||||||
List<Key> key_list; // Add new keys here
|
|
||||||
create_field *def;
|
create_field *def;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3291,13 +3306,13 @@ view_err:
|
||||||
def->field=field;
|
def->field=field;
|
||||||
if (!def->after)
|
if (!def->after)
|
||||||
{
|
{
|
||||||
create_list.push_back(def);
|
new_info.create_list.push_back(def);
|
||||||
def_it.remove();
|
def_it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Use old field value
|
{ // Use old field value
|
||||||
create_list.push_back(def=new create_field(field,field));
|
new_info.create_list.push_back(def= new create_field(field, field));
|
||||||
alter_it.rewind(); // Change default if ALTER
|
alter_it.rewind(); // Change default if ALTER
|
||||||
Alter_column *alter;
|
Alter_column *alter;
|
||||||
while ((alter=alter_it++))
|
while ((alter=alter_it++))
|
||||||
|
@ -3321,7 +3336,7 @@ view_err:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def_it.rewind();
|
def_it.rewind();
|
||||||
List_iterator<create_field> find_it(create_list);
|
List_iterator<create_field> find_it(new_info.create_list);
|
||||||
while ((def=def_it++)) // Add new columns
|
while ((def=def_it++)) // Add new columns
|
||||||
{
|
{
|
||||||
if (def->change && ! def->field)
|
if (def->change && ! def->field)
|
||||||
|
@ -3330,9 +3345,9 @@ view_err:
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
if (!def->after)
|
if (!def->after)
|
||||||
create_list.push_back(def);
|
new_info.create_list.push_back(def);
|
||||||
else if (def->after == first_keyword)
|
else if (def->after == first_keyword)
|
||||||
create_list.push_front(def);
|
new_info.create_list.push_front(def);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
create_field *find;
|
create_field *find;
|
||||||
|
@ -3356,7 +3371,7 @@ view_err:
|
||||||
alter_info->alter_list.head()->name, table_name);
|
alter_info->alter_list.head()->name, table_name);
|
||||||
DBUG_RETURN(TRUE);
|
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),
|
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
|
||||||
MYF(0));
|
MYF(0));
|
||||||
|
@ -3368,8 +3383,8 @@ view_err:
|
||||||
for which some fields exists.
|
for which some fields exists.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
List_iterator<Key> key_it(keys);
|
List_iterator<Key> key_it(alter_info->key_list);
|
||||||
List_iterator<create_field> field_it(create_list);
|
List_iterator<create_field> field_it(new_info.create_list);
|
||||||
List<key_part_spec> key_parts;
|
List<key_part_spec> key_parts;
|
||||||
|
|
||||||
KEY *key_info=table->key_info;
|
KEY *key_info=table->key_info;
|
||||||
|
@ -3441,24 +3456,37 @@ view_err:
|
||||||
key_part_length));
|
key_part_length));
|
||||||
}
|
}
|
||||||
if (key_parts.elements)
|
if (key_parts.elements)
|
||||||
key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL :
|
{
|
||||||
(key_info->flags & HA_NOSAME ?
|
Key *key;
|
||||||
(!my_strcasecmp(system_charset_info,
|
enum Key::Keytype key_type;
|
||||||
key_name, primary_key_name) ?
|
|
||||||
Key::PRIMARY : Key::UNIQUE) :
|
if (key_info->flags & HA_SPATIAL)
|
||||||
(key_info->flags & HA_FULLTEXT ?
|
key_type= Key::SPATIAL;
|
||||||
Key::FULLTEXT : Key::MULTIPLE)),
|
else if (key_info->flags & HA_NOSAME)
|
||||||
key_name,
|
{
|
||||||
key_info->algorithm,
|
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
|
||||||
test(key_info->flags & HA_GENERATED_KEY),
|
key_type= Key::PRIMARY;
|
||||||
key_parts));
|
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;
|
Key *key;
|
||||||
while ((key=key_it++)) // Add new keys
|
while ((key=key_it++)) // Add new keys
|
||||||
{
|
{
|
||||||
if (key->type != Key::FOREIGN_KEY)
|
if (key->type != Key::FOREIGN_KEY)
|
||||||
key_list.push_back(key);
|
new_info.key_list.push_back(key);
|
||||||
if (key->name &&
|
if (key->name &&
|
||||||
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
|
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
|
||||||
{
|
{
|
||||||
|
@ -3593,7 +3621,7 @@ view_err:
|
||||||
{
|
{
|
||||||
tmp_disable_binlog(thd);
|
tmp_disable_binlog(thd);
|
||||||
error= mysql_create_table(thd, new_db, tmp_name,
|
error= mysql_create_table(thd, new_db, tmp_name,
|
||||||
create_info,create_list,key_list,1,0);
|
create_info, &new_info, 1, 0);
|
||||||
reenable_binlog(thd);
|
reenable_binlog(thd);
|
||||||
if (error)
|
if (error)
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
@ -3634,9 +3662,9 @@ view_err:
|
||||||
{
|
{
|
||||||
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
|
||||||
new_table->next_number_field=new_table->found_next_number_field;
|
new_table->next_number_field=new_table->found_next_number_field;
|
||||||
error=copy_data_between_tables(table, new_table, create_list, ignore,
|
error= copy_data_between_tables(table, new_table, new_info.create_list,
|
||||||
order_num, order, &copied, &deleted,
|
ignore, order_num, order,
|
||||||
alter_info->keys_onoff);
|
&copied, &deleted, alter_info->keys_onoff);
|
||||||
}
|
}
|
||||||
else if (!new_table)
|
else if (!new_table)
|
||||||
{
|
{
|
||||||
|
@ -3860,8 +3888,7 @@ end_temporary:
|
||||||
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
|
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
|
||||||
(ulong) (copied + deleted), (ulong) deleted,
|
(ulong) (copied + deleted), (ulong) deleted,
|
||||||
(ulong) thd->cuted_fields);
|
(ulong) thd->cuted_fields);
|
||||||
if (do_send_ok)
|
send_ok(thd, copied + deleted, 0L, tmp_name);
|
||||||
send_ok(thd,copied+deleted,0L,tmp_name);
|
|
||||||
thd->some_tables_deleted=0;
|
thd->some_tables_deleted=0;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
@ -4060,31 +4087,26 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
||||||
mysql_recreate_table()
|
mysql_recreate_table()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
tables Tables to recreate
|
tables Tables to recreate
|
||||||
do_send_ok If we should send_ok() or leave it to caller
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
Like mysql_alter_table().
|
Like mysql_alter_table().
|
||||||
*/
|
*/
|
||||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
|
||||||
bool do_send_ok)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_recreate_table");
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
HA_CREATE_INFO create_info;
|
HA_CREATE_INFO create_info;
|
||||||
lex->create_list.empty();
|
Alter_info alter_info;
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
DBUG_ENTER("mysql_recreate_table");
|
||||||
lex->alter_info.reset();
|
|
||||||
bzero((char*) &create_info,sizeof(create_info));
|
bzero((char*) &create_info, sizeof(create_info));
|
||||||
create_info.db_type=DB_TYPE_DEFAULT;
|
create_info.db_type=DB_TYPE_DEFAULT;
|
||||||
create_info.row_type=ROW_TYPE_NOT_USED;
|
create_info.row_type=ROW_TYPE_NOT_USED;
|
||||||
create_info.default_table_charset=default_charset_info;
|
create_info.default_table_charset=default_charset_info;
|
||||||
/* Force alter table to recreate table */
|
/* 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,
|
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
|
||||||
table_list, lex->create_list,
|
table_list, &alter_info,
|
||||||
lex->key_list, 0, (ORDER *) 0,
|
0, (ORDER *) 0, 0));
|
||||||
0, &lex->alter_info, do_send_ok));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1352,8 +1352,7 @@ create:
|
||||||
TL_READ_NO_INSERT:
|
TL_READ_NO_INSERT:
|
||||||
TL_READ)))
|
TL_READ)))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
lex->alter_info.reset();
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->change=NullS;
|
lex->change=NullS;
|
||||||
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
||||||
|
@ -1371,16 +1370,17 @@ create:
|
||||||
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
|
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
|
||||||
TL_OPTION_UPDATING))
|
TL_OPTION_UPDATING))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
lex->alter_info.reset();
|
||||||
lex->key_list.empty();
|
lex->alter_info.flags= ALTER_ADD_INDEX;
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->change=NullS;
|
lex->change=NullS;
|
||||||
}
|
}
|
||||||
'(' key_list ')'
|
'(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
|
Key *key= new Key($2, $4.str, $5, 0, lex->col_list);
|
||||||
|
|
||||||
lex->key_list.push_back(new Key($2,$4.str, $5, 0, lex->col_list));
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
}
|
}
|
||||||
| CREATE DATABASE opt_if_not_exists ident
|
| CREATE DATABASE opt_if_not_exists ident
|
||||||
|
@ -2920,29 +2920,34 @@ key_def:
|
||||||
key_type opt_ident key_alg '(' key_list ')'
|
key_type opt_ident key_alg '(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->key_list.push_back(new Key($1,$2, $3, 0, lex->col_list));
|
Key *key= new Key($1, $2, $3, 0, lex->col_list);
|
||||||
|
lex->alter_info.key_list.push_back(key);
|
||||||
|
|
||||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
|
| opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')'
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
const char *key_name= $3 ? $3:$1;
|
const char *key_name= $3 ? $3:$1;
|
||||||
lex->key_list.push_back(new Key($2, key_name, $4, 0,
|
Key *key= new Key($2, key_name, $4, 0, lex->col_list);
|
||||||
lex->col_list));
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list.empty(); /* Alloced by sql_alloc */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
|
| opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->key_list.push_back(new foreign_key($4 ? $4:$1, lex->col_list,
|
const char *key_name= $4 ? $4 : $1;
|
||||||
$8,
|
Key *key= new foreign_key(key_name, lex->col_list,
|
||||||
lex->ref_list,
|
$8,
|
||||||
lex->fk_delete_opt,
|
lex->ref_list,
|
||||||
lex->fk_update_opt,
|
lex->fk_delete_opt,
|
||||||
lex->fk_match_option));
|
lex->fk_update_opt,
|
||||||
lex->key_list.push_back(new Key(Key::MULTIPLE, $4 ? $4 : $1,
|
lex->fk_match_option);
|
||||||
HA_KEY_ALG_UNDEF, 1,
|
lex->alter_info.key_list.push_back(key);
|
||||||
lex->col_list));
|
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 */
|
lex->col_list.empty(); /* Alloced by sql_alloc */
|
||||||
}
|
}
|
||||||
| constraint opt_check_constraint
|
| constraint opt_check_constraint
|
||||||
|
@ -3484,8 +3489,6 @@ alter:
|
||||||
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
|
if (!lex->select_lex.add_table_to_list(thd, $4, NULL,
|
||||||
TL_OPTION_UPDATING))
|
TL_OPTION_UPDATING))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
lex->create_list.empty();
|
|
||||||
lex->key_list.empty();
|
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->select_lex.init_order();
|
lex->select_lex.init_order();
|
||||||
lex->select_lex.db=
|
lex->select_lex.db=
|
||||||
|
@ -3495,8 +3498,7 @@ alter:
|
||||||
lex->create_info.db_type= DB_TYPE_DEFAULT;
|
lex->create_info.db_type= DB_TYPE_DEFAULT;
|
||||||
lex->create_info.default_table_charset= NULL;
|
lex->create_info.default_table_charset= NULL;
|
||||||
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
lex->create_info.row_type= ROW_TYPE_NOT_USED;
|
||||||
lex->alter_info.reset();
|
lex->alter_info.reset();
|
||||||
lex->alter_info.flags= 0;
|
|
||||||
}
|
}
|
||||||
alter_list
|
alter_list
|
||||||
{}
|
{}
|
||||||
|
@ -6254,7 +6256,8 @@ drop:
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->sql_command= SQLCOM_DROP_INDEX;
|
lex->sql_command= SQLCOM_DROP_INDEX;
|
||||||
lex->alter_info.drop_list.empty();
|
lex->alter_info.reset();
|
||||||
|
lex->alter_info.flags= ALTER_DROP_INDEX;
|
||||||
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
|
||||||
$3.str));
|
$3.str));
|
||||||
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
|
if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL,
|
||||||
|
|
Loading…
Add table
Reference in a new issue