Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into  bodhi.local:/opt/local/work/mysql-5.0-runtime-merge
This commit is contained in:
kostja@bodhi.local 2006-11-02 01:21:37 +03:00
commit b471ea50f7
46 changed files with 1387 additions and 404 deletions

View File

@ -65,6 +65,8 @@ my_bool hash_check(HASH *hash); /* Only in debug library */
#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
#define hash_inited(H) ((H)->array.buffer != 0)
#define hash_init_opt(A,B,C,D,E,F,G,H) \
(!hash_inited(A) && _hash_init(A,B,C,D,E,F,G, H CALLER_INFO))
#ifdef __cplusplus
}

View File

@ -119,4 +119,13 @@ END|
---------------------------------------------------------------------------
CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
BEGIN
DECLARE div_zero INTEGER;
SELECT 1/0 INTO div_zero;
RETURN div_zero;
END|
---------------------------------------------------------------------------
delimiter ;|

View File

@ -1268,6 +1268,9 @@ sub environment_setup () {
$ENV{'IM_PATH_PID'}= $instance_manager->{path_pid};
$ENV{'IM_PATH_ANGEL_PID'}= $instance_manager->{path_angel_pid};
$ENV{'IM_PORT'}= $instance_manager->{port};
$ENV{'IM_PATH_SOCK'}= $instance_manager->{path_sock};
$ENV{'IM_USERNAME'}= $instance_manager->{admin_login};
$ENV{'IM_PASSWORD'}= $instance_manager->{admin_password};
$ENV{'IM_MYSQLD1_SOCK'}= $instance_manager->{instances}->[0]->{path_sock};
$ENV{'IM_MYSQLD1_PORT'}= $instance_manager->{instances}->[0]->{port};
@ -1276,6 +1279,9 @@ sub environment_setup () {
$ENV{'IM_MYSQLD2_PORT'}= $instance_manager->{instances}->[1]->{port};
$ENV{'IM_MYSQLD2_PATH_PID'}=$instance_manager->{instances}->[1]->{path_pid};
$ENV{'EXE_MYSQL'}= $exe_mysql;
$ENV{MTR_BUILD_THREAD}= 0 unless $ENV{MTR_BUILD_THREAD}; # Set if not set
# We are nice and report a bit about our settings

View File

@ -8,6 +8,7 @@ mysqld2 offline
Killing the process...
Sleeping...
Success: the process was restarted.
Success: server is ready to accept connection on socket.
--------------------------------------------------------------------
-- Test for BUG#12751

View File

@ -295,6 +295,22 @@ b
c
d
drop table t1,t4;
DROP TABLE IF EXISTS t2, t1;
CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB;
CREATE TABLE t2 (
i INT NOT NULL,
FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION
) ENGINE= InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
DELETE IGNORE FROM t1 WHERE i = 1;
Warnings:
Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION)
SELECT * FROM t1, t2;
i i
1 1
DROP TABLE t2, t1;
End of 4.1 tests.
create table t1 (
a varchar(30), b varchar(30), primary key(a), key(b)
) engine=innodb;

View File

@ -956,7 +956,103 @@ GROUP_CONCAT(Track SEPARATOR ', ')
CAD
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
End of 4.1 tests
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (i INT, INDEX(i));
INSERT INTO t1 VALUES (1);
PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(COUNT(i) = 1) COUNT(i)
0 0
SET @a = 1;
EXECUTE stmt USING @a;
(COUNT(i) = 1) COUNT(i)
1 1
SET @a = 0;
EXECUTE stmt USING @a;
(COUNT(i) = 1) COUNT(i)
0 0
PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(AVG(i) = 1) AVG(i)
NULL NULL
SET @a = 1;
EXECUTE stmt USING @a;
(AVG(i) = 1) AVG(i)
1 1.0000
SET @a = 0;
EXECUTE stmt USING @a;
(AVG(i) = 1) AVG(i)
NULL NULL
PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(VARIANCE(i) = 1) VARIANCE(i)
NULL NULL
SET @a = 1;
EXECUTE stmt USING @a;
(VARIANCE(i) = 1) VARIANCE(i)
0 0.0000
SET @a = 0;
EXECUTE stmt USING @a;
(VARIANCE(i) = 1) VARIANCE(i)
NULL NULL
PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(STDDEV(i) = 1) STDDEV(i)
NULL NULL
SET @a = 1;
EXECUTE stmt USING @a;
(STDDEV(i) = 1) STDDEV(i)
0 0.0000
SET @a = 0;
EXECUTE stmt USING @a;
(STDDEV(i) = 1) STDDEV(i)
NULL NULL
PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_OR(i) = 1) BIT_OR(i)
0 0
SET @a = 1;
EXECUTE stmt USING @a;
(BIT_OR(i) = 1) BIT_OR(i)
1 1
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_OR(i) = 1) BIT_OR(i)
0 0
PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_AND(i) = 1) BIT_AND(i)
0 18446744073709551615
SET @a = 1;
EXECUTE stmt USING @a;
(BIT_AND(i) = 1) BIT_AND(i)
1 1
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_AND(i) = 1) BIT_AND(i)
0 18446744073709551615
PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_XOR(i) = 1) BIT_XOR(i)
0 0
SET @a = 1;
EXECUTE stmt USING @a;
(BIT_XOR(i) = 1) BIT_XOR(i)
1 1
SET @a = 0;
EXECUTE stmt USING @a;
(BIT_XOR(i) = 1) BIT_XOR(i)
0 0
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
End of 4.1 tests.
create table t1 (a varchar(20));
insert into t1 values ('foo');
prepare stmt FROM 'SELECT char_length (a) FROM t1';
@ -1379,4 +1475,5 @@ i
1
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
DROP PROCEDURE IF EXISTS p1;
End of 5.0 tests.

View File

@ -1226,3 +1226,27 @@ END;
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 'IF NOT EXISTS bug14702()
BEGIN
END' at line 1
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (i INT);
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
ERROR HY000: View's SELECT contains a 'INTO' clause
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
ERROR HY000: View's SELECT contains a 'INTO' clause
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
ERROR HY000: View's SELECT contains a 'INTO' clause
CREATE PROCEDURE bug20953()
CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1;
ERROR HY000: View's SELECT contains a subquery in the FROM clause
CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
ERROR HY000: View's SELECT contains a variable or parameter
CREATE PROCEDURE bug20953()
BEGIN
DECLARE i INT;
CREATE VIEW v AS SELECT i;
END |
ERROR HY000: View's SELECT contains a variable or parameter
PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
ERROR HY000: View's SELECT contains a variable or parameter
DROP TABLE t1;

View File

@ -4,6 +4,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1;
DROP FUNCTION IF EXISTS sp_vars_check_ret2;
DROP FUNCTION IF EXISTS sp_vars_check_ret3;
DROP FUNCTION IF EXISTS sp_vars_check_ret4;
DROP FUNCTION IF EXISTS sp_vars_div_zero;
SET @@sql_mode = 'ansi';
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
@ -88,6 +89,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
BEGIN
DECLARE div_zero INTEGER;
SELECT 1/0 INTO div_zero;
RETURN div_zero;
END|
---------------------------------------------------------------
Calling the routines, created in ANSI mode.
@ -172,6 +179,9 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
SELECT sp_vars_div_zero();
sp_vars_div_zero()
NULL
SET @@sql_mode = 'traditional';
---------------------------------------------------------------
@ -257,12 +267,16 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
SELECT sp_vars_div_zero();
sp_vars_div_zero()
NULL
DROP PROCEDURE sp_vars_check_dflt;
DROP PROCEDURE sp_vars_check_assignment;
DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
DROP FUNCTION sp_vars_div_zero;
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
DECLARE v1 TINYINT DEFAULT 1e200;
@ -346,6 +360,12 @@ CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
CREATE FUNCTION sp_vars_div_zero() RETURNS INTEGER
BEGIN
DECLARE div_zero INTEGER;
SELECT 1/0 INTO div_zero;
RETURN div_zero;
END|
---------------------------------------------------------------
Calling the routines, created in TRADITIONAL mode.
@ -366,6 +386,8 @@ sp_vars_check_ret4()
154.12
Warnings:
Note 1265 Data truncated for column 'sp_vars_check_ret4()' at row 1
SELECT sp_vars_div_zero();
ERROR 22012: Division by 0
SET @@sql_mode = 'ansi';
DROP PROCEDURE sp_vars_check_dflt;
DROP PROCEDURE sp_vars_check_assignment;
@ -373,6 +395,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
DROP FUNCTION sp_vars_div_zero;
---------------------------------------------------------------
BIT data type tests

View File

@ -5470,5 +5470,161 @@ CAD
CHF
DROP FUNCTION bug21493|
DROP TABLE t3,t4|
drop function if exists func_20028_a|
drop function if exists func_20028_b|
drop function if exists func_20028_c|
drop procedure if exists proc_20028_a|
drop procedure if exists proc_20028_b|
drop procedure if exists proc_20028_c|
drop table if exists table_20028|
create table table_20028 (i int)|
SET @save_sql_mode=@@sql_mode|
SET sql_mode=''|
create function func_20028_a() returns integer
begin
declare temp integer;
select i into temp from table_20028 limit 1;
return ifnull(temp, 0);
end|
create function func_20028_b() returns integer
begin
return func_20028_a();
end|
create function func_20028_c() returns integer
begin
declare div_zero integer;
set SQL_MODE='TRADITIONAL';
select 1/0 into div_zero;
return div_zero;
end|
create procedure proc_20028_a()
begin
declare temp integer;
select i into temp from table_20028 limit 1;
end|
create procedure proc_20028_b()
begin
call proc_20028_a();
end|
create procedure proc_20028_c()
begin
declare div_zero integer;
set SQL_MODE='TRADITIONAL';
select 1/0 into div_zero;
end|
select func_20028_a()|
func_20028_a()
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
select func_20028_b()|
func_20028_b()
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
select func_20028_c()|
ERROR 22012: Division by 0
call proc_20028_a()|
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call proc_20028_b()|
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call proc_20028_c()|
ERROR 22012: Division by 0
SET sql_mode='TRADITIONAL'|
drop function func_20028_a|
drop function func_20028_b|
drop function func_20028_c|
drop procedure proc_20028_a|
drop procedure proc_20028_b|
drop procedure proc_20028_c|
create function func_20028_a() returns integer
begin
declare temp integer;
select i into temp from table_20028 limit 1;
return ifnull(temp, 0);
end|
create function func_20028_b() returns integer
begin
return func_20028_a();
end|
create function func_20028_c() returns integer
begin
declare div_zero integer;
set SQL_MODE='';
select 1/0 into div_zero;
return div_zero;
end|
create procedure proc_20028_a()
begin
declare temp integer;
select i into temp from table_20028 limit 1;
end|
create procedure proc_20028_b()
begin
call proc_20028_a();
end|
create procedure proc_20028_c()
begin
declare div_zero integer;
set SQL_MODE='';
select 1/0 into div_zero;
end|
select func_20028_a()|
func_20028_a()
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
select func_20028_b()|
func_20028_b()
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
select func_20028_c()|
func_20028_c()
NULL
call proc_20028_a()|
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call proc_20028_b()|
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call proc_20028_c()|
SET @@sql_mode=@save_sql_mode|
drop function func_20028_a|
drop function func_20028_b|
drop function func_20028_c|
drop procedure proc_20028_a|
drop procedure proc_20028_b|
drop procedure proc_20028_c|
drop table table_20028|
drop procedure if exists proc_21462_a|
drop procedure if exists proc_21462_b|
create procedure proc_21462_a()
begin
select "Called A";
end|
create procedure proc_21462_b(x int)
begin
select "Called B";
end|
call proc_21462_a|
Called A
Called A
call proc_21462_a()|
Called A
Called A
call proc_21462_a(1)|
ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_a; expected 0, got 1
call proc_21462_b|
ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0
call proc_21462_b()|
ERROR 42000: Incorrect number of arguments for PROCEDURE test.proc_21462_b; expected 1, got 0
call proc_21462_b(1)|
Called B
Called B
drop procedure proc_21462_a|
drop procedure proc_21462_b|
End of 5.0 tests
drop table t1,t2;

View File

@ -1073,10 +1073,11 @@ SELECT @x;
NULL
SET @x=2;
UPDATE t1 SET i1 = @x;
ERROR 22012: Division by 0
Warnings:
Error 1365 Division by 0
SELECT @x;
@x
2
NULL
SET SQL_MODE='';
SET @x=3;
INSERT INTO t1 VALUES (@x);
@ -1085,10 +1086,12 @@ SELECT @x;
NULL
SET @x=4;
UPDATE t1 SET i1 = @x;
ERROR 22012: Division by 0
Warnings:
Error 1365 Division by 0
Error 1365 Division by 0
SELECT @x;
@x
4
NULL
SET @@sql_mode=@save_sql_mode;
DROP TRIGGER t1_ai;
DROP TRIGGER t1_au;
@ -1174,6 +1177,59 @@ ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghi
DROP TABLE t1;
DROP TABLE t2;
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
drop table if exists t4;
SET @save_sql_mode=@@sql_mode;
SET sql_mode='TRADITIONAL'|
create table t1 (id int(10) not null primary key, v int(10) )|
create table t2 (id int(10) not null primary key, v int(10) )|
create table t3 (id int(10) not null primary key, v int(10) )|
create table t4 (c int)|
create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1|
create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1|
insert into t1 values(10, 10)|
set @a:=1/0|
Warnings:
Error 1365 Division by 0
select 1/0 from t1|
1/0
NULL
Warnings:
Error 1365 Division by 0
create trigger t1_bi before insert on t1 for each row set @a:=1/0|
insert into t1 values(20, 20)|
Warnings:
Error 1365 Division by 0
drop trigger t1_bi|
create trigger t1_bi before insert on t1 for each row
begin
insert into t2 values (new.id, new.v);
update t2 set v=v+1 where id= new.id;
replace t3 values (new.id, 0);
update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id;
create temporary table t5 select * from t1;
delete from t5;
insert into t5 select * from t1;
insert into t4 values (0);
set @check= (select count(*) from t5);
update t4 set c= @check;
drop temporary table t5;
set @a:=1/0;
end|
set @check=0, @t4_bi_called=0, @t4_bu_called=0|
insert into t1 values(30, 30)|
Warnings:
Error 1365 Division by 0
select @check, @t4_bi_called, @t4_bu_called|
@check @t4_bi_called @t4_bu_called
2 1 1
SET @@sql_mode=@save_sql_mode;
drop table t1;
drop table t2;
drop table t3;
drop table t4;
drop table if exists t1;
create table t1 (i int, j int key);
insert into t1 values (1,1), (2,2), (3,3);
create trigger t1_bu before update on t1 for each row

View File

@ -12,6 +12,9 @@ create table t1 (a int, b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
ERROR HY000: View's SELECT contains a variable or parameter
create view v1 (c,d) as select a,b from t1
where a = @@global.max_user_connections;
ERROR HY000: View's SELECT contains a variable or parameter
create view v1 (c) as select b+1 from t1;
select c from v1;
c
@ -596,11 +599,6 @@ ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function
drop view v1;
create view v1 (a,a) as select 'a','a';
ERROR 42S21: Duplicate column name 'a'
drop procedure if exists p1;
create procedure p1 () begin declare v int; create view v1 as select v; end;//
call p1();
ERROR HY000: View's SELECT contains a variable or parameter
drop procedure p1;
create table t1 (col1 int,col2 char(22));
insert into t1 values(5,'Hello, world of views');
create view v1 as select * from t1;
@ -886,6 +884,8 @@ ERROR HY000: View's SELECT contains a 'INTO' clause
create table t1 (a int);
create view v1 as select a from t1 procedure analyse();
ERROR HY000: View's SELECT contains a 'PROCEDURE' clause
create view v1 as select 1 from (select 1) as d1;
ERROR HY000: View's SELECT contains a subquery in the FROM clause
drop table t1;
create table t1 (s1 int, primary key (s1));
create view v1 as select * from t1;
@ -2956,6 +2956,20 @@ View Create View
v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`))))))
DROP VIEW v1;
DROP TABLE t1, t2;
DROP FUNCTION IF EXISTS f1;
DROP VIEW IF EXISTS v1;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (1);
CREATE VIEW v1 AS SELECT MAX(i) FROM t1;
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
SET NEW.i = (SELECT * FROM v1) + 1;
INSERT INTO t1 VALUES (1);
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
UPDATE t1 SET i= f1();
DROP FUNCTION f1;
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1(id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, val INT UNSIGNED NOT NULL);
CREATE VIEW v1 AS SELECT id, val FROM t1 WHERE val >= 1 AND val <= 5 WITH CHECK OPTION;
INSERT INTO v1 (val) VALUES (2);
@ -2966,4 +2980,38 @@ UPDATE v1 SET val=6 WHERE id=2;
ERROR HY000: CHECK OPTION failed 'test.v1'
DROP VIEW v1;
DROP TABLE t1;
DROP VIEW IF EXISTS v1, v2;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT);
CREATE VIEW v1 AS SELECT j FROM t1;
CREATE VIEW v2 AS SELECT * FROM t1;
INSERT INTO t1 (j) VALUES (1);
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
1
INSERT INTO v1 (j) VALUES (2);
# LAST_INSERT_ID() should not change.
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
1
INSERT INTO v2 (j) VALUES (3);
# LAST_INSERT_ID() should be updated.
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
3
INSERT INTO v1 (j) SELECT j FROM t1;
# LAST_INSERT_ID() should not change.
SELECT LAST_INSERT_ID();
LAST_INSERT_ID()
3
SELECT * FROM t1;
i j
1 1
2 2
3 3
4 1
5 2
6 3
DROP VIEW v1, v2;
DROP TABLE t1;
End of 5.0 tests.

View File

@ -98,7 +98,7 @@ select ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'withou
select distinct ifnull(group_concat(concat(t1.id, ':', t1.name)), 'shortname') as 'with distinct: cutoff at length of shortname' from t1;
drop table t1;
# check zero rows
# check zero rows (bug#836)
create table t1(id int);
create table t2(id int);
insert into t1 values(0),(1);

View File

@ -17,6 +17,12 @@
###########################################################################
# Wait for IM to start accepting connections.
--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30
###########################################################################
#
# BUG#12751: Instance Manager: client hangs
#

View File

@ -246,6 +246,36 @@ select distinct a1 from t4 where pk_col not in (1,2,3,4);
drop table t1,t4;
#
# BUG#18819: DELETE IGNORE hangs on foreign key parent delete
#
# The bug itself does not relate to InnoDB, but we have to use foreign
# keys to reproduce it.
#
--disable_warnings
DROP TABLE IF EXISTS t2, t1;
--enable_warnings
CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB;
CREATE TABLE t2 (
i INT NOT NULL,
FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION
) ENGINE= InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
DELETE IGNORE FROM t1 WHERE i = 1;
SELECT * FROM t1, t2;
DROP TABLE t2, t1;
--echo End of 4.1 tests.
#
# Bug #6142: a problem with the empty innodb table
# (was part of group_min_max.test)

View File

@ -988,6 +988,7 @@ execute stmt;
drop temporary table t1;
deallocate prepare stmt;
#
# BUG#22085: Crash on the execution of a prepared statement that
# uses an IN subquery with aggregate functions in HAVING
@ -1040,7 +1041,82 @@ EXECUTE STMT USING @id,@id;
DEALLOCATE PREPARE STMT;
DROP TABLE t1;
--echo End of 4.1 tests
#
# BUG#21354: (COUNT(*) = 1) not working in SELECT inside prepared
# statement
#
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (i INT, INDEX(i));
INSERT INTO t1 VALUES (1);
PREPARE stmt FROM "SELECT (COUNT(i) = 1), COUNT(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (AVG(i) = 1), AVG(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (VARIANCE(i) = 1), VARIANCE(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (STDDEV(i) = 1), STDDEV(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (BIT_OR(i) = 1), BIT_OR(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (BIT_AND(i) = 1), BIT_AND(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
PREPARE stmt FROM "SELECT (BIT_XOR(i) = 1), BIT_XOR(i) FROM t1 WHERE i = ?";
SET @a = 0;
EXECUTE stmt USING @a;
SET @a = 1;
EXECUTE stmt USING @a;
SET @a = 0;
EXECUTE stmt USING @a;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo End of 4.1 tests.
############################# 5.0 tests start ################################
#
#
@ -1437,4 +1513,24 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
#
# BUG#21856: Prepared Statments: crash if bad create
#
--disable_warnings
DROP PROCEDURE IF EXISTS p1;
--enable_warnings
let $iterations= 100;
--disable_query_log
--disable_result_log
while ($iterations > 0)
{
--error ER_PARSE_ERROR
PREPARE stmt FROM "CREATE PROCEDURE p1()";
dec $iterations;
}
--enable_query_log
--enable_result_log
--echo End of 5.0 tests.

View File

@ -1767,6 +1767,47 @@ BEGIN
END;
#
# BUG#20953: create proc with a create view that uses local
# vars/params should fail to create
#
# See test case for what syntax is forbidden in a view.
#
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (i INT);
# We do not have to drop this procedure and view because they won't be
# created.
--error ER_VIEW_SELECT_CLAUSE
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO @a;
--error ER_VIEW_SELECT_CLAUSE
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO DUMPFILE "file";
--error ER_VIEW_SELECT_CLAUSE
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 INTO OUTFILE "file";
--error ER_VIEW_SELECT_CLAUSE
CREATE PROCEDURE bug20953()
CREATE VIEW v AS SELECT i FROM t1 PROCEDURE ANALYSE();
--error ER_VIEW_SELECT_DERIVED
CREATE PROCEDURE bug20953() CREATE VIEW v AS SELECT 1 FROM (SELECT 1) AS d1;
--error ER_VIEW_SELECT_VARIABLE
CREATE PROCEDURE bug20953(i INT) CREATE VIEW v AS SELECT i;
delimiter |;
--error ER_VIEW_SELECT_VARIABLE
CREATE PROCEDURE bug20953()
BEGIN
DECLARE i INT;
CREATE VIEW v AS SELECT i;
END |
delimiter ;|
--error ER_VIEW_SELECT_VARIABLE
PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
DROP TABLE t1;
#
# BUG#NNNN: New bug synopsis
#

View File

@ -15,6 +15,7 @@ DROP FUNCTION IF EXISTS sp_vars_check_ret1;
DROP FUNCTION IF EXISTS sp_vars_check_ret2;
DROP FUNCTION IF EXISTS sp_vars_check_ret3;
DROP FUNCTION IF EXISTS sp_vars_check_ret4;
DROP FUNCTION IF EXISTS sp_vars_div_zero;
--enable_warnings
@ -49,6 +50,8 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
SELECT sp_vars_div_zero();
# Check that changing sql_mode after creating a store procedure does not
# matter.
@ -72,6 +75,8 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
SELECT sp_vars_div_zero();
# Create the procedure in TRADITIONAL mode. Check that error will be thrown on
# execution.
@ -81,6 +86,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
DROP FUNCTION sp_vars_div_zero;
--source include/sp-vars.inc
@ -110,6 +116,9 @@ SELECT sp_vars_check_ret3();
SELECT sp_vars_check_ret4();
--error ER_DIVISION_BY_ZERO
SELECT sp_vars_div_zero();
SET @@sql_mode = 'ansi';
#
@ -122,6 +131,7 @@ DROP FUNCTION sp_vars_check_ret1;
DROP FUNCTION sp_vars_check_ret2;
DROP FUNCTION sp_vars_check_ret3;
DROP FUNCTION sp_vars_check_ret4;
DROP FUNCTION sp_vars_div_zero;
###########################################################################
#

View File

@ -6420,6 +6420,170 @@ SELECT bug21493(Member_ID) FROM t3|
DROP FUNCTION bug21493|
DROP TABLE t3,t4|
#
# Bug#20028 Function with select return no data
#
--disable_warnings
drop function if exists func_20028_a|
drop function if exists func_20028_b|
drop function if exists func_20028_c|
drop procedure if exists proc_20028_a|
drop procedure if exists proc_20028_b|
drop procedure if exists proc_20028_c|
drop table if exists table_20028|
--enable_warnings
create table table_20028 (i int)|
SET @save_sql_mode=@@sql_mode|
SET sql_mode=''|
create function func_20028_a() returns integer
begin
declare temp integer;
select i into temp from table_20028 limit 1;
return ifnull(temp, 0);
end|
create function func_20028_b() returns integer
begin
return func_20028_a();
end|
create function func_20028_c() returns integer
begin
declare div_zero integer;
set SQL_MODE='TRADITIONAL';
select 1/0 into div_zero;
return div_zero;
end|
create procedure proc_20028_a()
begin
declare temp integer;
select i into temp from table_20028 limit 1;
end|
create procedure proc_20028_b()
begin
call proc_20028_a();
end|
create procedure proc_20028_c()
begin
declare div_zero integer;
set SQL_MODE='TRADITIONAL';
select 1/0 into div_zero;
end|
select func_20028_a()|
select func_20028_b()|
--error ER_DIVISION_BY_ZERO
select func_20028_c()|
call proc_20028_a()|
call proc_20028_b()|
--error ER_DIVISION_BY_ZERO
call proc_20028_c()|
SET sql_mode='TRADITIONAL'|
drop function func_20028_a|
drop function func_20028_b|
drop function func_20028_c|
drop procedure proc_20028_a|
drop procedure proc_20028_b|
drop procedure proc_20028_c|
create function func_20028_a() returns integer
begin
declare temp integer;
select i into temp from table_20028 limit 1;
return ifnull(temp, 0);
end|
create function func_20028_b() returns integer
begin
return func_20028_a();
end|
create function func_20028_c() returns integer
begin
declare div_zero integer;
set SQL_MODE='';
select 1/0 into div_zero;
return div_zero;
end|
create procedure proc_20028_a()
begin
declare temp integer;
select i into temp from table_20028 limit 1;
end|
create procedure proc_20028_b()
begin
call proc_20028_a();
end|
create procedure proc_20028_c()
begin
declare div_zero integer;
set SQL_MODE='';
select 1/0 into div_zero;
end|
select func_20028_a()|
select func_20028_b()|
select func_20028_c()|
call proc_20028_a()|
call proc_20028_b()|
call proc_20028_c()|
SET @@sql_mode=@save_sql_mode|
drop function func_20028_a|
drop function func_20028_b|
drop function func_20028_c|
drop procedure proc_20028_a|
drop procedure proc_20028_b|
drop procedure proc_20028_c|
drop table table_20028|
#
# Bug#21462 Stored procedures with no arguments require parenthesis
#
--disable_warnings
drop procedure if exists proc_21462_a|
drop procedure if exists proc_21462_b|
--enable_warnings
create procedure proc_21462_a()
begin
select "Called A";
end|
create procedure proc_21462_b(x int)
begin
select "Called B";
end|
call proc_21462_a|
call proc_21462_a()|
-- error ER_SP_WRONG_NO_OF_ARGS
call proc_21462_a(1)|
-- error ER_SP_WRONG_NO_OF_ARGS
call proc_21462_b|
-- error ER_SP_WRONG_NO_OF_ARGS
call proc_21462_b()|
call proc_21462_b(1)|
drop procedure proc_21462_a|
drop procedure proc_21462_b|
--echo End of 5.0 tests

View File

@ -1274,7 +1274,6 @@ INSERT INTO t1 VALUES (@x);
SELECT @x;
SET @x=2;
--error ER_DIVISION_BY_ZERO
UPDATE t1 SET i1 = @x;
SELECT @x;
@ -1285,7 +1284,6 @@ INSERT INTO t1 VALUES (@x);
SELECT @x;
SET @x=4;
--error ER_DIVISION_BY_ZERO
UPDATE t1 SET i1 = @x;
SELECT @x;
@ -1420,6 +1418,67 @@ CREATE DEFINER=some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890
DROP TABLE t1;
DROP TABLE t2;
#
# Bug#20028 Function with select return no data
#
--disable_warnings
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
drop table if exists t4;
--enable_warnings
SET @save_sql_mode=@@sql_mode;
delimiter |;
SET sql_mode='TRADITIONAL'|
create table t1 (id int(10) not null primary key, v int(10) )|
create table t2 (id int(10) not null primary key, v int(10) )|
create table t3 (id int(10) not null primary key, v int(10) )|
create table t4 (c int)|
create trigger t4_bi before insert on t4 for each row set @t4_bi_called:=1|
create trigger t4_bu before update on t4 for each row set @t4_bu_called:=1|
insert into t1 values(10, 10)|
set @a:=1/0|
select 1/0 from t1|
create trigger t1_bi before insert on t1 for each row set @a:=1/0|
insert into t1 values(20, 20)|
drop trigger t1_bi|
create trigger t1_bi before insert on t1 for each row
begin
insert into t2 values (new.id, new.v);
update t2 set v=v+1 where id= new.id;
replace t3 values (new.id, 0);
update t2, t3 set t2.v=new.v, t3.v=new.v where t2.id=t3.id;
create temporary table t5 select * from t1;
delete from t5;
insert into t5 select * from t1;
insert into t4 values (0);
set @check= (select count(*) from t5);
update t4 set c= @check;
drop temporary table t5;
set @a:=1/0;
end|
set @check=0, @t4_bi_called=0, @t4_bu_called=0|
insert into t1 values(30, 30)|
select @check, @t4_bi_called, @t4_bu_called|
delimiter ;|
SET @@sql_mode=@save_sql_mode;
drop table t1;
drop table t2;
drop table t3;
drop table t4;
#
# Bug#20670 "UPDATE using key and invoking trigger that modifies

View File

@ -23,8 +23,11 @@ create table t1 (a int, b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
# view with variable
-- error 1351
-- error ER_VIEW_SELECT_VARIABLE
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
-- error ER_VIEW_SELECT_VARIABLE
create view v1 (c,d) as select a,b from t1
where a = @@global.max_user_connections;
# simple view
create view v1 (c) as select b+1 from t1;
@ -486,19 +489,6 @@ drop view v1;
-- error 1060
create view v1 (a,a) as select 'a','a';
#
# SP variables inside view test
#
--disable_warnings
drop procedure if exists p1;
--enable_warnings
delimiter //;
create procedure p1 () begin declare v int; create view v1 as select v; end;//
delimiter ;//
-- error 1351
call p1();
drop procedure p1;
#
# updatablity should be transitive
#
@ -820,6 +810,8 @@ create view v1 as select 5 into outfile 'ttt';
create table t1 (a int);
-- error 1350
create view v1 as select a from t1 procedure analyse();
-- error ER_VIEW_SELECT_DERIVED
create view v1 as select 1 from (select 1) as d1;
drop table t1;
#
@ -2597,6 +2589,7 @@ SELECT * FROM t2;
DROP VIEW v1;
DROP TABLE t1,t2;
#
# Bug#16110: insert permitted into view col w/o default value
#
@ -2880,6 +2873,40 @@ SHOW CREATE VIEW v1;
DROP VIEW v1;
DROP TABLE t1, t2;
#
# Bug#19111: TRIGGERs selecting from a VIEW on the firing base table
# fail
#
# Allow to select from a view on a table being modified in a trigger
# and stored function, since plain select is allowed there.
#
--disable_warnings
DROP FUNCTION IF EXISTS f1;
DROP VIEW IF EXISTS v1;
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (1);
CREATE VIEW v1 AS SELECT MAX(i) FROM t1;
# Plain 'SET NEW.i = (SELECT MAX(i) FROM t1) + 1' works, so select
# from a view should work too.
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
SET NEW.i = (SELECT * FROM v1) + 1;
INSERT INTO t1 VALUES (1);
# Plain 'RETURN (SELECT MAX(i) FROM t1)' works in INSERT, so select
# from a view should work too.
CREATE FUNCTION f1() RETURNS INT RETURN (SELECT * FROM v1);
UPDATE t1 SET i= f1();
DROP FUNCTION f1;
DROP VIEW v1;
DROP TABLE t1;
#
# Bug #16813 (WITH CHECK OPTION doesn't work with UPDATE)
#
@ -2894,4 +2921,43 @@ UPDATE v1 SET val=6 WHERE id=2;
DROP VIEW v1;
DROP TABLE t1;
#
# BUG#22584: last_insert_id not updated after inserting a record
# through a updatable view
#
# We still do not update LAST_INSERT_ID if AUTO_INCREMENT column is
# not accessible through a view. However, we do not reset the value
# of LAST_INSERT_ID, but keep it unchanged.
#
--disable_warnings
DROP VIEW IF EXISTS v1, v2;
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT);
CREATE VIEW v1 AS SELECT j FROM t1;
CREATE VIEW v2 AS SELECT * FROM t1;
INSERT INTO t1 (j) VALUES (1);
SELECT LAST_INSERT_ID();
INSERT INTO v1 (j) VALUES (2);
--echo # LAST_INSERT_ID() should not change.
SELECT LAST_INSERT_ID();
INSERT INTO v2 (j) VALUES (3);
--echo # LAST_INSERT_ID() should be updated.
SELECT LAST_INSERT_ID();
INSERT INTO v1 (j) SELECT j FROM t1;
--echo # LAST_INSERT_ID() should not change.
SELECT LAST_INSERT_ID();
SELECT * FROM t1;
DROP VIEW v1, v2;
DROP TABLE t1;
--echo End of 5.0 tests.

62
mysql-test/t/wait_for_socket.sh Executable file
View File

@ -0,0 +1,62 @@
#!/bin/sh
###########################################################################
if [ $# -ne 6 ]; then
echo "Usage: wait_for_socket.sh <executable path> <socket path> <username> <password> <db> <timeout>"
exit 0
fi
client_exe="$1"
socket_path="$2"
username="$3"
password="$4"
db="$5"
total_timeout="$6"
###########################################################################
if [ -z "$client_exe" ]; then
echo "Error: invalid path to client executable ($client_exe)."
exit 0;
fi
if [ ! -x "$client_exe" ]; then
echo "Error: client by path '$client_exe' is not available."
exit 0;
fi
if [ -z "$socket_path" ]; then
echo "Error: invalid socket patch."
exit 0
fi
###########################################################################
client_args="--silent --socket=$socket_path "
[ -n "$username" ] && client_args="$client_args --user=$username "
[ -n "$password" ] && client_args="$client_args --password=$password "
[ -n "$db" ] && client_args="$client_args $db"
###########################################################################
cur_attempt=1
while true; do
if ( echo 'quit' | "$client_exe" $client_args >/dev/null 2>&1 ); then
echo "Success: server is ready to accept connection on socket."
exit 0
fi
[ $cur_attempt -ge $total_timeout ] && break
sleep 1
cur_attempt=`expr $cur_attempt + 1`
done
echo "Error: server does not accept connections after $total_timeout seconds."
exit 0

View File

@ -66,11 +66,11 @@ Guardian_thread::~Guardian_thread()
}
void Guardian_thread::request_shutdown(bool stop_instances_arg)
void Guardian_thread::request_shutdown()
{
pthread_mutex_lock(&LOCK_guardian);
/* stop instances or just clean up Guardian repository */
stop_instances(stop_instances_arg);
stop_instances();
shutdown_requested= TRUE;
pthread_mutex_unlock(&LOCK_guardian);
}
@ -118,11 +118,11 @@ void Guardian_thread::process_instance(Instance *instance,
{
/* Pid file not created yet, don't go to STARTED state yet */
}
else
else if (current_node->state != STARTED)
{
/* clear status fields */
log_info("guardian: instance %s is running, set state to STARTED",
instance->options.instance_name);
log_info("guardian: instance '%s' is running, set state to STARTED.",
(const char *) instance->options.instance_name);
current_node->restart_counter= 0;
current_node->crash_moment= 0;
current_node->state= STARTED;
@ -132,8 +132,8 @@ void Guardian_thread::process_instance(Instance *instance,
{
switch (current_node->state) {
case NOT_STARTED:
log_info("guardian: starting instance %s",
instance->options.instance_name);
log_info("guardian: starting instance '%s'...",
(const char *) instance->options.instance_name);
/* NOTE, set state to STARTING _before_ start() is called */
current_node->state= STARTING;
@ -157,8 +157,8 @@ void Guardian_thread::process_instance(Instance *instance,
if (instance->is_crashed())
{
instance->start();
log_info("guardian: starting instance %s",
instance->options.instance_name);
log_info("guardian: starting instance '%s'...",
(const char *) instance->options.instance_name);
}
}
else
@ -175,8 +175,8 @@ void Guardian_thread::process_instance(Instance *instance,
instance->start();
current_node->last_checked= current_time;
current_node->restart_counter++;
log_info("guardian: restarting instance %s",
instance->options.instance_name);
log_info("guardian: restarting instance '%s'...",
(const char *) instance->options.instance_name);
}
}
else
@ -382,12 +382,11 @@ int Guardian_thread::stop_guard(Instance *instance)
SYNOPSYS
stop_instances()
stop_instances_arg whether we should stop instances at shutdown
DESCRIPTION
Loops through the guarded_instances list and prepares them for shutdown.
If stop_instances was requested, we need to issue a stop command and change
the state accordingly. Otherwise we simply delete an entry.
For each instance we issue a stop command and change the state
accordingly.
NOTE
Guardian object should be locked by the calling function.
@ -397,42 +396,29 @@ int Guardian_thread::stop_guard(Instance *instance)
1 - error occured
*/
int Guardian_thread::stop_instances(bool stop_instances_arg)
int Guardian_thread::stop_instances()
{
LIST *node;
node= guarded_instances;
while (node != NULL)
{
if (!stop_instances_arg)
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
/*
If instance is running or was running (and now probably hanging),
request stop.
*/
if (current_node->instance->is_running() ||
(current_node->state == STARTED))
{
/* just forget about an instance */
guarded_instances= list_delete(guarded_instances, node);
/*
This should still work fine, as we have only removed the
node from the list. The pointer to the next one is still valid
*/
node= node->next;
current_node->state= STOPPING;
current_node->last_checked= time(NULL);
}
else
{
GUARD_NODE *current_node= (GUARD_NODE *) node->data;
/*
If instance is running or was running (and now probably hanging),
request stop.
*/
if (current_node->instance->is_running() ||
(current_node->state == STARTED))
{
current_node->state= STOPPING;
current_node->last_checked= time(NULL);
}
else
/* otherwise remove it from the list */
guarded_instances= list_delete(guarded_instances, node);
/* But try to kill it anyway. Just in case */
current_node->instance->kill_instance(SIGTERM);
node= node->next;
}
/* otherwise remove it from the list */
guarded_instances= list_delete(guarded_instances, node);
/* But try to kill it anyway. Just in case */
current_node->instance->kill_instance(SIGTERM);
node= node->next;
}
return 0;
}
@ -440,7 +426,7 @@ int Guardian_thread::stop_instances(bool stop_instances_arg)
void Guardian_thread::lock()
{
pthread_mutex_lock(&LOCK_guardian);
pthread_mutex_lock(&LOCK_guardian);
}

View File

@ -89,7 +89,7 @@ public:
/* Initialize or refresh the list of guarded instances */
int init();
/* Request guardian shutdown. Stop instances if needed */
void request_shutdown(bool stop_instances);
void request_shutdown();
/* Start instance protection */
int guard(Instance *instance, bool nolock= FALSE);
/* Stop instance protection */
@ -104,7 +104,7 @@ public:
private:
/* Prepares Guardian shutdown. Stops instances is needed */
int stop_instances(bool stop_instances_arg);
int stop_instances();
/* check instance state and act accordingly */
void process_instance(Instance *instance, GUARD_NODE *current_node,
LIST **guarded_instances, LIST *elem);

View File

@ -156,8 +156,8 @@ static int start_process(Instance_options *instance_options,
/* exec never returns */
exit(1);
case -1:
log_info("cannot create a new process to start instance %s",
instance_options->instance_name);
log_info("cannot create a new process to start instance '%s'.",
(const char *) instance_options->instance_name);
return 1;
}
return 0;
@ -252,7 +252,8 @@ static void start_and_monitor_instance(Instance_options *old_instance_options,
MAX_INSTANCE_NAME_LEN - 1);
instance_name_len= old_instance_options->instance_name_len;
log_info("starting instance %s", instance_name_buff);
log_info("starting instance '%s'...",
(const char *) instance_name_buff);
if (start_process(old_instance_options, &process_info))
{
@ -286,9 +287,9 @@ void Instance::remove_pid()
int pid;
if ((pid= options.get_pid()) != 0) /* check the pidfile */
if (options.unlink_pidfile()) /* remove stalled pidfile */
log_error("cannot remove pidfile for instance %i, this might be \
log_error("cannot remove pidfile for instance '%s', this might be \
since IM lacks permmissions or hasn't found the pidifle",
options.instance_name);
(const char *) options.instance_name);
}
@ -435,9 +436,9 @@ bool Instance::is_running()
We have successfully connected to the server using fake
username/password. Write a warning to the logfile.
*/
log_info("The Instance Manager was able to log into you server \
with faked compiled-in password while checking server status. \
Looks like something is wrong.");
log_info("The Instance Manager was able to log into you server "
"with faked compiled-in password while checking server status. "
"Looks like something is wrong.");
pthread_mutex_unlock(&LOCK_instance);
return_val= TRUE; /* server is alive */
}
@ -577,10 +578,10 @@ void Instance::kill_instance(int signum)
/* Kill suceeded */
if (signum == SIGKILL) /* really killed instance with SIGKILL */
{
log_error("The instance %s is being stopped forcibly. Normally" \
"it should not happen. Probably the instance has been" \
log_error("The instance '%s' is being stopped forcibly. Normally"
"it should not happen. Probably the instance has been"
"hanging. You should also check your IM setup",
options.instance_name);
(const char *) options.instance_name);
/* After sucessful hard kill the pidfile need to be removed */
options.unlink_pidfile();
}

View File

@ -215,7 +215,9 @@ int Instance_map::flush_instances()
hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
get_instance_key, delete_instance, 0);
rc= load();
guardian->init(); // TODO: check error status.
/* don't init guardian if we failed to load instances */
if (!rc)
guardian->init(); // TODO: check error status.
pthread_mutex_unlock(&LOCK_instance_map);
guardian->unlock();
return rc;

View File

@ -280,7 +280,7 @@ int Listener_thread::create_tcp_socket()
FD_SET(ip_socket, &read_fds);
sockets[num_sockets++]= ip_socket;
log_info("accepting connections on ip socket");
log_info("accepting connections on ip socket (port: %d)", (int) im_port);
return 0;
}
@ -334,7 +334,7 @@ create_unix_socket(struct sockaddr_un &unix_socket_address)
/* make sure that instances won't be listening our sockets */
set_no_inherit(unix_socket);
log_info("accepting connections on unix socket %s",
log_info("accepting connections on unix socket '%s'",
unix_socket_address.sun_path);
sockets[num_sockets++]= unix_socket;
FD_SET(unix_socket, &read_fds);

View File

@ -104,6 +104,19 @@ int my_sigwait(const sigset_t *set, int *sig)
#endif
void stop_all(Guardian_thread *guardian, Thread_registry *registry)
{
/*
Let guardian thread know that it should break it's processing cycle,
once it wakes up.
*/
guardian->request_shutdown();
/* wake guardian */
pthread_cond_signal(&guardian->COND_guardian);
/* stop all threads */
registry->deliver_shutdown();
}
/*
manager - entry point to the main instance manager process: start
listener thread, write pid file and enter into signal handling.
@ -210,7 +223,8 @@ void manager(const Options &options)
log_error("Cannot init instances repository. This might be caused by "
"the wrong config file options. For instance, missing mysqld "
"binary. Aborting.");
return;
stop_all(&guardian_thread, &thread_registry);
goto err;
}
/* create the listener */
@ -227,6 +241,7 @@ void manager(const Options &options)
if (rc)
{
log_error("manager(): set_stacksize_n_create_thread(listener) failed");
stop_all(&guardian_thread, &thread_registry);
goto err;
}
@ -245,6 +260,7 @@ void manager(const Options &options)
if ((status= my_sigwait(&mask, &signo)) != 0)
{
log_error("sigwait() failed");
stop_all(&guardian_thread, &thread_registry);
goto err;
}
@ -266,8 +282,7 @@ void manager(const Options &options)
{
if (!guardian_thread.is_stopped())
{
bool stop_instances= true;
guardian_thread.request_shutdown(stop_instances);
guardian_thread.request_shutdown();
pthread_cond_signal(&guardian_thread.COND_guardian);
}
else

View File

@ -45,10 +45,10 @@ const char *default_password_file_name= QUOTE(DEFAULT_PASSWORD_FILE_NAME);
const char *default_log_file_name= QUOTE(DEFAULT_LOG_FILE_NAME);
const char *Options::config_file= QUOTE(DEFAULT_CONFIG_FILE);
const char *Options::angel_pid_file_name= NULL;
const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
#endif
const char *Options::log_file_name= default_log_file_name;
const char *Options::pid_file_name= QUOTE(DEFAULT_PID_FILE_NAME);
const char *Options::socket_file_name= QUOTE(DEFAULT_SOCKET_FILE_NAME);
const char *Options::password_file_name= default_password_file_name;
const char *Options::default_mysqld_path= QUOTE(DEFAULT_MYSQLD_PATH);
const char *Options::bind_address= 0; /* No default value */
@ -106,11 +106,11 @@ static struct my_option my_long_options[] =
(gptr *) &Options::angel_pid_file_name,
(gptr *) &Options::angel_pid_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif
{ "socket", OPT_SOCKET, "Socket file to use for connection.",
(gptr *) &Options::socket_file_name, (gptr *) &Options::socket_file_name,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
#endif
{ "passwd", 'P', "Prepare entry for passwd file and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },

View File

@ -36,11 +36,11 @@ struct Options
static char run_as_service; /* handle_options doesn't support bool */
static const char *user;
static const char *angel_pid_file_name;
static const char *socket_file_name;
#endif
static bool is_forced_default_file;
static const char *log_file_name;
static const char *pid_file_name;
static const char *socket_file_name;
static const char *password_file_name;
static const char *default_mysqld_path;
/* the option which should be passed to process_default_option_files */

View File

@ -1055,6 +1055,7 @@ longlong Item_sum_count::val_int()
void Item_sum_count::cleanup()
{
DBUG_ENTER("Item_sum_count::cleanup");
count= 0;
Item_sum_int::cleanup();
used_table_cache= ~(table_map) 0;
DBUG_VOID_RETURN;

View File

@ -260,9 +260,30 @@ public:
Item_sum(THD *thd, Item_sum *item);
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
/*
This method is similar to add(), but it is called when the current
aggregation group changes. Thus it performs a combination of
clear() and add().
*/
inline bool reset() { clear(); return add(); };
/*
Prepare this item for evaluation of an aggregate value. This is
called by reset() when a group changes, or, for correlated
subqueries, between subquery executions. E.g. for COUNT(), this
method should set count= 0;
*/
virtual void clear()= 0;
/*
This method is called for the next row in the same group. Its
purpose is to aggregate the new value to the previous values in
the group (i.e. since clear() was called last time). For example,
for COUNT(), do count++.
*/
virtual bool add()=0;
/*
Called when new group is started and results are being saved in
a temporary table. Similar to reset(), but must also store value in
@ -306,7 +327,17 @@ public:
void make_field(Send_field *field);
void print(String *str);
void fix_num_length_and_dec();
void no_rows_in_result() { reset(); }
/*
This function is called by the execution engine to assign 'NO ROWS
FOUND' value to an aggregate item, when the underlying result set
has no rows. Such value, in a general case, may be different from
the default value of the item after 'clear()': e.g. a numeric item
may be initialized to 0 by clear() and to NULL by
no_rows_in_result().
*/
void no_rows_in_result() { clear(); }
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
@ -610,6 +641,11 @@ public:
const char *func_name() const { return "avg("; }
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
void cleanup()
{
count= 0;
Item_sum_sum::cleanup();
}
};
class Item_sum_variance;
@ -689,6 +725,12 @@ public:
Item *copy_or_same(THD* thd);
Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length);
enum Item_result result_type () const { return REAL_RESULT; }
void cleanup()
{
cur_dec= 0;
count= 0;
Item_sum_num::cleanup();
}
};
class Item_sum_std;
@ -819,6 +861,11 @@ public:
void update_field();
void fix_length_and_dec()
{ decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; }
void cleanup()
{
bits= reset_bits;
Item_sum_int::cleanup();
}
};

View File

@ -131,6 +131,8 @@ MY_LOCALE *my_locale_by_name(const char *name);
#define MAX_ACCEPT_RETRY 10 // Test accept this many times
#define MAX_FIELDS_BEFORE_HASH 32
#define USER_VARS_HASH_SIZE 16
#define TABLE_OPEN_CACHE_MIN 64
#define TABLE_OPEN_CACHE_DEFAULT 64
/*
Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper

View File

@ -2641,19 +2641,43 @@ static int init_common_variables(const char *conf_file_name, int argc,
/* connections and databases needs lots of files */
{
uint files, wanted_files;
uint files, wanted_files, max_open_files;
wanted_files= 10+(uint) max(max_connections*5,
max_connections+table_cache_size*2);
set_if_bigger(wanted_files, open_files_limit);
files= my_set_max_open_files(wanted_files);
/* MyISAM requires two file handles per table. */
wanted_files= 10+max_connections+table_cache_size*2;
/*
We are trying to allocate no less than max_connections*5 file
handles (i.e. we are trying to set the limit so that they will
be available). In addition, we allocate no less than how much
was already allocated. However below we report a warning and
recompute values only if we got less file handles than were
explicitly requested. No warning and re-computation occur if we
can't get max_connections*5 but still got no less than was
requested (value of wanted_files).
*/
max_open_files= max(max(wanted_files, max_connections*5),
open_files_limit);
files= my_set_max_open_files(max_open_files);
if (files < wanted_files)
{
if (!open_files_limit)
{
max_connections= (ulong) min((files-10),max_connections);
table_cache_size= (ulong) max((files-10-max_connections)/2,64);
/*
If we have requested too much file handles than we bring
max_connections in supported bounds.
*/
max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
max_connections);
/*
Decrease table_cache_size according to max_connections, but
not below TABLE_OPEN_CACHE_MIN. Outer min() ensures that we
never increase table_cache_size automatically (that could
happen if max_connections is decreased above).
*/
table_cache_size= (ulong) min(max((files-10-max_connections)/2,
TABLE_OPEN_CACHE_MIN),
table_cache_size);
DBUG_PRINT("warning",
("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld",
files, max_connections, table_cache_size));
@ -5943,8 +5967,8 @@ The minimum value for this variable is 4096.",
0, 0, 0, 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
(gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
0, 1, 0},
(gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG,
TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
{"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in "
"seconds to wait for a table level lock before returning an error. Used"
" only if the connection has active cursors.",

View File

@ -107,4 +107,20 @@ public:
bool bad_format_errors);
};
/*
Custom version of standard offsetof() macro which can be used to get
offsets of members in class for non-POD types (according to the current
version of C++ standard offsetof() macro can't be used in such cases and
attempt to do so causes warnings to be emitted, OTOH in many cases it is
still OK to assume that all instances of the class has the same offsets
for the same members).
This is temporary solution which should be removed once File_parser class
and related routines are refactored.
*/
#define my_offsetof(TYPE, MEMBER) \
((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
#endif /* _PARSE_FILE_H_ */

View File

@ -1369,6 +1369,10 @@ static bool add_used_routine(LEX *lex, Query_arena *arena,
const LEX_STRING *key,
TABLE_LIST *belong_to_view)
{
hash_init_opt(&lex->sroutines, system_charset_info,
Query_tables_list::START_SROUTINES_HASH_SIZE,
0, 0, sp_sroutine_key, 0, 0);
if (!hash_search(&lex->sroutines, (byte *)key->str, key->length))
{
Sroutine_hash_entry *rn=

View File

@ -991,8 +991,7 @@ sp_head::execute(THD *thd)
save_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
save_abort_on_warning= thd->abort_on_warning;
thd->abort_on_warning=
(m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES));
thd->abort_on_warning= 0;
/*
It is also more efficient to save/restore current thd->lex once when

View File

@ -806,6 +806,10 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
Also SELECT::exclude_from_table_unique_test used to exclude from check
tables of main SELECT of multi-delete and multi-update
We also skip tables with TABLE_LIST::prelocking_placeholder set,
because we want to allow SELECTs from them, and their modification
will rise the error anyway.
TODO: when we will have table/view change detection we can do this check
only once for PS/SP
@ -852,12 +856,13 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list)
if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) &&
(! (res= mysql_lock_have_duplicate(thd, table, table_list)))) ||
((!res->table || res->table != table->table) &&
res->select_lex && !res->select_lex->exclude_from_table_unique_test))
res->select_lex && !res->select_lex->exclude_from_table_unique_test &&
!res->prelocking_placeholder))
break;
/*
If we found entry of this table or or table of SELECT which already
If we found entry of this table or table of SELECT which already
processed in derived table or top select of multi-update/multi-delete
(exclude_from_table_unique_test).
(exclude_from_table_unique_test) or prelocking placeholder.
*/
table_list= res->next_global;
DBUG_PRINT("info",

View File

@ -322,7 +322,7 @@ cleanup:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
if (error < 0)
if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error))
{
thd->row_count_func= deleted;
send_ok(thd,deleted);

View File

@ -150,7 +150,6 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0;
lex->leaf_tables_insert= 0;
lex->variables_used= 0;
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
@ -1635,9 +1634,18 @@ void Query_tables_list::reset_query_tables_list(bool init)
query_tables_last= &query_tables;
query_tables_own_last= 0;
if (init)
hash_init(&sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0);
{
/*
We delay real initialization of hash (and therefore related
memory allocation) until first insertion into this hash.
*/
hash_clear(&sroutines);
}
else if (sroutines.records)
{
/* Non-zero sroutines.records means that hash was initialized. */
my_hash_reset(&sroutines);
}
sroutines_list.empty();
sroutines_list_own_last= sroutines_list.next;
sroutines_list_own_elements= 0;

View File

@ -743,7 +743,11 @@ public:
0 - indicates that this query does not need prelocking.
*/
TABLE_LIST **query_tables_own_last;
/* Set of stored routines called by statement. */
/*
Set of stored routines called by statement.
(Note that we use lazy-initialization for this hash).
*/
enum { START_SROUTINES_HASH_SIZE= 16 };
HASH sroutines;
/*
List linking elements of 'sroutines' set. Allows you to add new elements
@ -808,6 +812,25 @@ public:
};
/*
st_parsing_options contains the flags for constructions that are
allowed in the current statement.
*/
struct st_parsing_options
{
bool allows_variable;
bool allows_select_into;
bool allows_select_procedure;
bool allows_derived;
st_parsing_options()
: allows_variable(TRUE), allows_select_into(TRUE),
allows_select_procedure(TRUE), allows_derived(TRUE)
{}
};
/* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex : public Query_tables_list
@ -951,7 +974,7 @@ typedef struct st_lex : public Query_tables_list
bool stmt_prepare_mode;
bool safe_to_cache_query;
bool subqueries, ignore;
bool variables_used;
st_parsing_options parsing_options;
ALTER_INFO alter_info;
/* Prepared statements SQL syntax:*/
LEX_STRING prepared_stmt_name; /* Statement name (in all queries) */

View File

@ -3045,11 +3045,6 @@ end_with_restore_list:
case SQLCOM_ALTER_TABLE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#if defined(DONT_ALLOW_SHOW_COMMANDS)
my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
MYF(0)); /* purecov: inspected */
goto error;
#else
{
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
@ -3115,7 +3110,6 @@ end_with_restore_list:
}
break;
}
#endif /*DONT_ALLOW_SHOW_COMMANDS*/
case SQLCOM_RENAME_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@ -3369,8 +3363,16 @@ end_with_restore_list:
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
/*
If we have inserted into a VIEW, and the base table has
AUTO_INCREMENT column, but this column is not accessible through
a view, then we should restore LAST_INSERT_ID to the value it
had before the statement.
*/
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
thd->last_insert_id= thd->current_insert_id;
break;
}
case SQLCOM_REPLACE_SELECT:
@ -3431,8 +3433,15 @@ end_with_restore_list:
select_lex->table_list.first= (byte*) first_table;
}
/*
If we have inserted into a VIEW, and the base table has
AUTO_INCREMENT column, but this column is not accessible through
a view, then we should restore LAST_INSERT_ID to the value it
had before the statement.
*/
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
thd->last_insert_id= thd->current_insert_id;
break;
}
case SQLCOM_TRUNCATE:
@ -5878,14 +5887,19 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
DBUG_ASSERT(thd->net.report_error);
DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error));
query_cache_abort(&thd->net);
lex->unit.cleanup();
/*
The first thing we do after parse error is freeing sp_head to
ensure that we have restored original memroot.
*/
if (thd->lex->sphead)
{
/* Clean up after failed stored procedure/function */
delete thd->lex->sphead;
thd->lex->sphead= NULL;
}
query_cache_abort(&thd->net);
lex->unit.cleanup();
}
thd->proc_info="freeing items";
thd->end_statement();

View File

@ -2773,6 +2773,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
error= MYSQLparse((void *)thd) || thd->is_fatal_error ||
thd->net.report_error || init_param_array(this);
/*
The first thing we do after parse error is freeing sp_head to
ensure that we have restored original memroot.
*/
if (error && lex->sphead)
{
delete lex->sphead;
lex->sphead= NULL;
}
/*
While doing context analysis of the query (in check_prepared_statement)
we allocate a lot of additional memory: for open tables, JOINs, derived
@ -2798,6 +2808,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
if (error == 0)
error= check_prepared_statement(this, name.str != 0);
/* Free sp_head if check_prepared_statement() failed. */
if (error && lex->sphead)
{
delete lex->sphead;

View File

@ -2934,208 +2934,6 @@ err:
}
#ifdef NOT_USED
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int mysql_create_indexes(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
List<Alter_drop> drop;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
int rc;
uint idx;
uint db_options;
uint key_count;
TABLE *table;
Field **f_ptr;
KEY *key_info_buffer;
char path[FN_REFLEN+1];
DBUG_ENTER("mysql_create_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The add_index method takes an array of KEY structs for the new indexes.
Preparing a new table structure generates this array.
It needs a list with all fields of the table, which does not need to
be correct in every respect. The field names are important.
*/
for (f_ptr= table->field; *f_ptr; f_ptr++)
{
create_field *c_fld= new create_field(*f_ptr, *f_ptr);
c_fld->unireg_check= Field::NONE; /*avoid multiple auto_increments*/
fields.push_back(c_fld);
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
db_options= 0;
if (mysql_prepare_table(thd, &create_info, &fields,
&keys, /*tmp_table*/ 0, &db_options, table->file,
&key_info_buffer, key_count,
/*select_field_count*/ 0))
DBUG_RETURN(-1);
/*
Check if all keys can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
for (idx=0; idx< key_count; idx++)
{
DBUG_PRINT("info", ("creating index %s", key_info_buffer[idx].name));
if (!(table->file->index_ddl_flags(key_info_buffer+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
}
if ((idx < key_count)|| !key_count)
{
/* Re-initialize the create_info, which was changed by prepare table. */
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
/* Cleanup the fields list. We do not want to create existing fields. */
fields.delete_elements();
if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_ADD_INDEX, DUP_ERROR))
/* Don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
else
{
if (table->file->add_index(table, key_info_buffer, key_count)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/* don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(-1);
}
/* don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN(0);
}
int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop)
{
List<create_field> fields;
List<Key> keys;
List<Alter_column> alter;
HA_CREATE_INFO create_info;
uint idx;
uint db_options;
uint key_count;
uint *key_numbers;
TABLE *table;
Field **f_ptr;
KEY *key_info;
KEY *key_info_buffer;
char path[FN_REFLEN];
DBUG_ENTER("mysql_drop_index");
/*
Try to use online generation of index.
This requires that all indexes can be created online.
Otherwise, the old alter table procedure is executed.
Open the table to have access to the correct table handler.
*/
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
/*
The drop_index method takes an array of key numbers.
It cannot get more entries than keys in the table.
*/
key_numbers= (uint*) thd->alloc(sizeof(uint*)*table->keys);
key_count= 0;
/*
Get the number of each key and check if it can be created online.
*/
List_iterator<Alter_drop> drop_it(drop);
Alter_drop *drop_key;
while ((drop_key= drop_it++))
{
/* Find the key in the table. */
key_info=table->key_info;
for (idx=0; idx< table->keys; idx++, key_info++)
{
if (!my_strcasecmp(system_charset_info, key_info->name, drop_key->name))
break;
}
if (idx>= table->keys)
{
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop_key->name);
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*
Check if the key can be generated with the add_index method.
If anyone cannot, then take the old way.
*/
DBUG_PRINT("info", ("dropping index %s", table->key_info[idx].name));
if (!(table->file->index_ddl_flags(table->key_info+idx)&
(HA_DDL_ONLINE| HA_DDL_WITH_LOCK)))
break ;
key_numbers[key_count++]= idx;
}
bzero((char*) &create_info,sizeof(create_info));
create_info.db_type=DB_TYPE_DEFAULT;
create_info.default_table_charset= thd->variables.collation_database;
if ((drop_key)|| (drop.elements<= 0))
{
if (real_alter_table(thd, table_list->db, table_list->table_name,
&create_info, table_list, table,
fields, keys, drop, alter, 0, (ORDER*)0,
ALTER_DROP_INDEX, DUP_ERROR))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
else
{
db_options= 0;
if (table->file->drop_index(table, key_numbers, key_count)||
mysql_prepare_table(thd, &create_info, &fields,
&keys, /*tmp_table*/ 0, &db_options, table->file,
&key_info_buffer, key_count,
/*select_field_count*/ 0)||
build_table_path(path, sizeof(path), table_list->db,
(lower_case_table_names == 2) ?
table_list->alias : table_list->table_name,
reg_ext) == 0 ||
mysql_create_frm(thd, path, &create_info,
fields, key_count, key_info_buffer, table->file))
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(-1);
}
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN(0);
}
#endif /* NOT_USED */
/*
Alter table
*/

View File

@ -36,17 +36,17 @@ static File_option triggers_file_parameters[]=
{
{
{(char *) STRING_WITH_LEN("triggers") },
offsetof(class Table_triggers_list, definitions_list),
my_offsetof(class Table_triggers_list, definitions_list),
FILE_OPTIONS_STRLIST
},
{
{(char *) STRING_WITH_LEN("sql_modes") },
offsetof(class Table_triggers_list, definition_modes_list),
my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
},
{
{(char *) STRING_WITH_LEN("definers") },
offsetof(class Table_triggers_list, definers_list),
my_offsetof(class Table_triggers_list, definers_list),
FILE_OPTIONS_STRLIST
},
{ { 0, 0 }, 0, FILE_OPTIONS_STRING }
@ -55,7 +55,7 @@ static File_option triggers_file_parameters[]=
File_option sql_modes_parameters=
{
{(char*) STRING_WITH_LEN("sql_modes") },
offsetof(class Table_triggers_list, definition_modes_list),
my_offsetof(class Table_triggers_list, definition_modes_list),
FILE_OPTIONS_ULLLIST
};

View File

@ -236,25 +236,9 @@ bool mysql_create_view(THD *thd,
bool res= FALSE;
DBUG_ENTER("mysql_create_view");
if (lex->proc_list.first ||
lex->result)
{
my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ?
"INTO" :
"PROCEDURE"));
res= TRUE;
goto err;
}
if (lex->derived_tables ||
lex->variables_used || lex->param_list.elements)
{
int err= (lex->derived_tables ?
ER_VIEW_SELECT_DERIVED :
ER_VIEW_SELECT_VARIABLE);
my_message(err, ER(err), MYF(0));
res= TRUE;
goto err;
}
/* This is ensured in the parser. */
DBUG_ASSERT(!lex->proc_list.first && !lex->result &&
!lex->param_list.elements && !lex->derived_tables);
if (mode != VIEW_CREATE_NEW)
{
@ -582,40 +566,40 @@ static const int num_view_backups= 3;
*/
static File_option view_parameters[]=
{{{(char*) STRING_WITH_LEN("query")},
offsetof(TABLE_LIST, query),
my_offsetof(TABLE_LIST, query),
FILE_OPTIONS_ESTRING},
{{(char*) STRING_WITH_LEN("md5")},
offsetof(TABLE_LIST, md5),
my_offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("updatable")},
offsetof(TABLE_LIST, updatable_view),
my_offsetof(TABLE_LIST, updatable_view),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("algorithm")},
offsetof(TABLE_LIST, algorithm),
my_offsetof(TABLE_LIST, algorithm),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("definer_user")},
offsetof(TABLE_LIST, definer.user),
my_offsetof(TABLE_LIST, definer.user),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("definer_host")},
offsetof(TABLE_LIST, definer.host),
my_offsetof(TABLE_LIST, definer.host),
FILE_OPTIONS_STRING},
{{(char*) STRING_WITH_LEN("suid")},
offsetof(TABLE_LIST, view_suid),
my_offsetof(TABLE_LIST, view_suid),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("with_check_option")},
offsetof(TABLE_LIST, with_check),
my_offsetof(TABLE_LIST, with_check),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("revision")},
offsetof(TABLE_LIST, revision),
my_offsetof(TABLE_LIST, revision),
FILE_OPTIONS_REV},
{{(char*) STRING_WITH_LEN("timestamp")},
offsetof(TABLE_LIST, timestamp),
my_offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
{{(char*)STRING_WITH_LEN("create-version")},
offsetof(TABLE_LIST, file_version),
my_offsetof(TABLE_LIST, file_version),
FILE_OPTIONS_ULONGLONG},
{{(char*) STRING_WITH_LEN("source")},
offsetof(TABLE_LIST, source),
my_offsetof(TABLE_LIST, source),
FILE_OPTIONS_ESTRING},
{{NullS, 0}, 0,
FILE_OPTIONS_STRING}

View File

@ -650,11 +650,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UNIX_TIMESTAMP
%token UNKNOWN_SYM
%token UNLOCK_SYM
%token UNLOCK_SYM
%token UNSIGNED
%token UNTIL_SYM
%token UNTIL_SYM
%token UPDATE_SYM
%token UPDATE_SYM
%token UPGRADE_SYM
%token USAGE
@ -749,7 +746,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
bool_term bool_factor bool_test bool_pri
variable variable_aux bool_term bool_factor bool_test bool_pri
predicate bit_expr bit_term bit_factor value_expr term factor
table_wild simple_expr udf_expr
expr_or_default set_expr_or_default interval_expr
@ -1447,15 +1444,20 @@ call:
lex->value_list.empty();
sp_add_used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE);
}
'(' sp_cparam_list ')' {}
opt_sp_cparam_list {}
;
/* CALL parameters */
sp_cparam_list:
opt_sp_cparam_list:
/* Empty */
| sp_cparams
| '(' opt_sp_cparams ')'
;
opt_sp_cparams:
/* Empty */
| sp_cparams
;
sp_cparams:
sp_cparams ',' expr
{
@ -4325,32 +4327,7 @@ simple_expr:
}
| literal
| param_marker
| '@' ident_or_text SET_VAR expr
{
$$= new Item_func_set_user_var($2,$4);
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
lex->variables_used= 1;
}
| '@' ident_or_text
{
$$= new Item_func_get_user_var($2);
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
lex->variables_used= 1;
}
| '@' '@' opt_var_ident_type ident_or_text opt_component
{
if ($4.str && $5.str && check_reserved_words(&$4))
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (!($$= get_system_var(YYTHD, $3, $4, $5)))
YYABORT;
Lex->variables_used= 1;
}
| variable
| sum_expr
| simple_expr OR_OR_SYM simple_expr
{ $$= new Item_func_concat($1, $3); }
@ -5060,6 +5037,46 @@ sum_expr:
$5->empty();
};
variable:
'@'
{
if (! Lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
YYABORT;
}
}
variable_aux
{
$$= $3;
}
;
variable_aux:
ident_or_text SET_VAR expr
{
$$= new Item_func_set_user_var($1, $3);
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
}
| ident_or_text
{
$$= new Item_func_get_user_var($1);
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
}
| '@' opt_var_ident_type ident_or_text opt_component
{
if ($3.str && $4.str && check_reserved_words(&$3))
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (!($$= get_system_var(YYTHD, $2, $3, $4)))
YYABORT;
}
;
opt_distinct:
/* empty */ { $$ = 0; }
|DISTINCT { $$ = 1; };
@ -5166,7 +5183,7 @@ when_list2:
/* Warning - may return NULL in case of incomplete SELECT */
table_ref:
table_factor { $$=$1; }
| join_table { $$=$1; }
| join_table
{
LEX *lex= Lex;
if (!($$= lex->current_select->nest_last_join(lex->thd)))
@ -5208,7 +5225,7 @@ join_table:
| table_ref normal_join table_ref
ON
{
YYERROR_UNLESS($1 && ($$=$3));
YYERROR_UNLESS($1 && $3);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
@ -5223,7 +5240,7 @@ join_table:
| table_ref STRAIGHT_JOIN table_factor
ON
{
YYERROR_UNLESS($1 && ($$=$3));
YYERROR_UNLESS($1 && $3);
/* Change the current name resolution context to a local context. */
if (push_new_name_resolution_context(YYTHD, $1, $3))
YYABORT;
@ -5490,6 +5507,13 @@ select_derived_init:
SELECT_SYM
{
LEX *lex= Lex;
if (! lex->parsing_options.allows_derived)
{
my_error(ER_VIEW_SELECT_DERIVED, MYF(0));
YYABORT;
}
SELECT_LEX *sel= lex->current_select;
TABLE_LIST *embedding;
if (!sel->embedding || sel->end_nested_join(lex->thd))
@ -5849,6 +5873,13 @@ procedure_clause:
| PROCEDURE ident /* Procedure name */
{
LEX *lex=Lex;
if (! lex->parsing_options.allows_select_procedure)
{
my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE");
YYABORT;
}
if (&lex->select_lex != lex->current_select)
{
my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
@ -5948,28 +5979,40 @@ select_var_ident:
;
into:
INTO OUTFILE TEXT_STRING_filesystem
INTO
{
if (! Lex->parsing_options.allows_select_into)
{
my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO");
YYABORT;
}
}
into_destination
;
into_destination:
OUTFILE TEXT_STRING_filesystem
{
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($3.str, 0)) ||
if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
!(lex->result= new select_export(lex->exchange)))
YYABORT;
}
opt_field_term opt_line_term
| INTO DUMPFILE TEXT_STRING_filesystem
| DUMPFILE TEXT_STRING_filesystem
{
LEX *lex=Lex;
if (!lex->describe)
{
lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($3.str,1)))
if (!(lex->exchange= new sql_exchange($2.str,1)))
YYABORT;
if (!(lex->result= new select_dump(lex->exchange)))
YYABORT;
}
}
| INTO select_var_list_init
| select_var_list_init
{
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
}
@ -7129,8 +7172,13 @@ param_marker:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
Item_param *item= new Item_param((uint) (lex->tok_start -
(uchar *) thd->query));
Item_param *item;
if (! lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
YYABORT;
}
item= new Item_param((uint) (lex->tok_start - (uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@ -7250,6 +7298,12 @@ simple_ident:
if (spc && (spv = spc->find_variable(&$1)))
{
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
YYABORT;
}
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, spv->type,
lex->tok_start_prev -
@ -7259,7 +7313,6 @@ simple_ident:
splocal->m_sp= lex->sphead;
#endif
$$ = (Item*) splocal;
lex->variables_used= 1;
lex->safe_to_cache_query=0;
}
else
@ -9107,6 +9160,24 @@ view_list:
;
view_select:
{
LEX *lex= Lex;
lex->parsing_options.allows_variable= FALSE;
lex->parsing_options.allows_select_into= FALSE;
lex->parsing_options.allows_select_procedure= FALSE;
lex->parsing_options.allows_derived= FALSE;
}
view_select_aux
{
LEX *lex= Lex;
lex->parsing_options.allows_variable= TRUE;
lex->parsing_options.allows_select_into= TRUE;
lex->parsing_options.allows_select_procedure= TRUE;
lex->parsing_options.allows_derived= TRUE;
}
;
view_select_aux:
SELECT_SYM remember_name select_init2
{
THD *thd=YYTHD;