merge from 5.1 main
This commit is contained in:
commit
b2151faee8
@ -36,6 +36,7 @@
|
|||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "log_event.h"
|
#include "log_event.h"
|
||||||
#include "sql_common.h"
|
#include "sql_common.h"
|
||||||
|
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
|
||||||
|
|
||||||
#define BIN_LOG_HEADER_SIZE 4
|
#define BIN_LOG_HEADER_SIZE 4
|
||||||
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
|
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
|
||||||
@ -1249,10 +1250,7 @@ static void print_version()
|
|||||||
static void usage()
|
static void usage()
|
||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
puts("By Monty and Sasha, for your professional use\n\
|
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000, 2011"));
|
||||||
This software comes with NO WARRANTY: This is free software,\n\
|
|
||||||
and you are welcome to modify and redistribute it under the GPL license.\n");
|
|
||||||
|
|
||||||
printf("\
|
printf("\
|
||||||
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
|
Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
|
||||||
the mysql command line client.\n\n");
|
the mysql command line client.\n\n");
|
||||||
|
@ -38,7 +38,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \
|
|||||||
my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \
|
my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \
|
||||||
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
|
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
|
||||||
my_compare.h my_time.h my_vle.h my_user.h \
|
my_compare.h my_time.h my_vle.h my_user.h \
|
||||||
my_libwrap.h my_stacktrace.h
|
my_libwrap.h my_stacktrace.h welcome_copyright_notice.h
|
||||||
|
|
||||||
EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
|
EXTRA_DIST = mysql.h.pp mysql/plugin.h.pp
|
||||||
|
|
||||||
|
31
include/welcome_copyright_notice.h
Normal file
31
include/welcome_copyright_notice.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#ifndef _welcome_copyright_notice_h_
|
||||||
|
#define _welcome_copyright_notice_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
This define specifies copyright notice which is displayed by every MySQL
|
||||||
|
program on start, or on help screen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ORACLE_WELCOME_COPYRIGHT_NOTICE(years) \
|
||||||
|
"Copyright (c) " years ", Oracle and/or its affiliates. All rights reserved.\n" \
|
||||||
|
"\n" \
|
||||||
|
"Oracle is a registered trademark of Oracle Corporation and/or its\n" \
|
||||||
|
"affiliates. Other names may be trademarks of their respective\n" \
|
||||||
|
"owners.\n"
|
||||||
|
|
||||||
|
#endif /* _welcome_copyright_notice_h_ */
|
@ -176,11 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_mode;
|
|||||||
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
||||||
EXPLAIN EXTENDED SELECT 1 FROM t1
|
EXPLAIN EXTENDED SELECT 1 FROM t1
|
||||||
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
|
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
|
||||||
ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
SHOW WARNINGS;
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||||
Level Code Message
|
2 SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
|
||||||
Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
|
2 SUBQUERY t system NULL NULL NULL NULL 0 0.00 const row not found
|
||||||
Note 1003 select 1 AS `1` from `test`.`t1` where <not>(<exists>(...))
|
Warnings:
|
||||||
|
Note 1003 select 1 AS `1` from `test`.`t1` where 0
|
||||||
SET SESSION sql_mode=@old_sql_mode;
|
SET SESSION sql_mode=@old_sql_mode;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
End of 5.0 tests.
|
End of 5.0 tests.
|
||||||
|
38
mysql-test/r/secure_file_priv_win.result
Normal file
38
mysql-test/r/secure_file_priv_win.result
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
CREATE TABLE t1 (c1 longtext);
|
||||||
|
INSERT INTO t1 values ('a');
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517.tmp';
|
||||||
|
show global variables like 'secure_file_priv';
|
||||||
|
Variable_name Value
|
||||||
|
secure_file_priv MYSQL_TMP_DIR/
|
||||||
|
SELECT load_file('MYSQL_TMP_DIR\\B11764517.tmp') AS x;
|
||||||
|
x
|
||||||
|
a
|
||||||
|
|
||||||
|
SELECT load_file('MYSQL_TMP_DIR/B11764517.tmp') AS x;
|
||||||
|
x
|
||||||
|
a
|
||||||
|
|
||||||
|
SELECT load_file('MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
|
||||||
|
x
|
||||||
|
a
|
||||||
|
|
||||||
|
SELECT load_file('MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
|
||||||
|
x
|
||||||
|
a
|
||||||
|
|
||||||
|
SELECT load_file('MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp') AS x;
|
||||||
|
x
|
||||||
|
NULL
|
||||||
|
LOAD DATA INFILE 'MYSQL_TMP_DIR\\B11764517.tmp' INTO TABLE t1;
|
||||||
|
LOAD DATA INFILE 'MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
|
||||||
|
LOAD DATA INFILE 'MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
|
||||||
|
LOAD DATA INFILE 'MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
|
||||||
|
LOAD DATA INFILE "MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517.tmp" into table t1;
|
||||||
|
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\..a..\\..\\..\\B11764517-2.tmp';
|
||||||
|
ERROR HY000: The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR\\B11764517-2.tmp';
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR/B11764517-3.tmp';
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
|
||||||
|
SELECT * FROM t1 INTO OUTFILE 'MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
|
||||||
|
DROP TABLE t1;
|
@ -567,3 +567,28 @@ DROP USER 'tester';
|
|||||||
DROP USER 'Tester';
|
DROP USER 'Tester';
|
||||||
DROP DATABASE B48872;
|
DROP DATABASE B48872;
|
||||||
End of 5.0 tests.
|
End of 5.0 tests.
|
||||||
|
#
|
||||||
|
# Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
|
||||||
|
# DEFINITION OF ANY ROUTINE.
|
||||||
|
#
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE PROCEDURE db1.p1() SELECT 1;
|
||||||
|
CREATE USER user2@localhost IDENTIFIED BY '';
|
||||||
|
GRANT SELECT(db) ON mysql.proc TO user2@localhost;
|
||||||
|
# Connection con2 as user2
|
||||||
|
# The statement below before disclosed info from body_utf8 column.
|
||||||
|
SHOW CREATE PROCEDURE db1.p1;
|
||||||
|
ERROR 42000: PROCEDURE p1 does not exist
|
||||||
|
# Check that SHOW works with SELECT grant on whole table
|
||||||
|
# Connection default
|
||||||
|
GRANT SELECT ON mysql.proc TO user2@localhost;
|
||||||
|
# Connection con2
|
||||||
|
# This should work
|
||||||
|
SHOW CREATE PROCEDURE db1.p1;
|
||||||
|
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||||
|
p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`()
|
||||||
|
SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci
|
||||||
|
# Connection default
|
||||||
|
DROP USER user2@localhost;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
@ -4435,6 +4435,32 @@ pk int_key
|
|||||||
3 3
|
3 3
|
||||||
7 3
|
7 3
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
#
|
||||||
|
# Bug#12329653
|
||||||
|
# EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a1 int);
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
SELECT @@session.sql_mode INTO @old_sql_mode;
|
||||||
|
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
||||||
|
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
PREPARE stmt FROM
|
||||||
|
'SELECT 1 UNION ALL
|
||||||
|
SELECT 1 FROM t1
|
||||||
|
ORDER BY
|
||||||
|
(SELECT 1 FROM t1 AS t1_0
|
||||||
|
WHERE 1 < SOME (SELECT a1 FROM t1)
|
||||||
|
)' ;
|
||||||
|
EXECUTE stmt ;
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
EXECUTE stmt ;
|
||||||
|
ERROR 21000: Subquery returns more than 1 row
|
||||||
|
SET SESSION sql_mode=@old_sql_mode;
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
DROP TABLE t1;
|
||||||
End of 5.0 tests.
|
End of 5.0 tests.
|
||||||
CREATE TABLE t1 (a INT, b INT);
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
|
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
|
||||||
|
@ -1,3 +1,46 @@
|
|||||||
|
set global innodb_file_per_table=on;
|
||||||
|
set global innodb_file_format='Barracuda';
|
||||||
|
CREATE TABLE t1_purge (
|
||||||
|
A INT,
|
||||||
|
B BLOB, C BLOB, D BLOB, E BLOB,
|
||||||
|
F BLOB, G BLOB, H BLOB,
|
||||||
|
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
|
||||||
|
INDEX (A)
|
||||||
|
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
INSERT INTO t1_purge VALUES (1,
|
||||||
|
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
|
||||||
|
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
|
||||||
|
CREATE TABLE t2_purge (
|
||||||
|
A INT PRIMARY KEY,
|
||||||
|
B BLOB, C BLOB, D BLOB, E BLOB,
|
||||||
|
F BLOB, G BLOB, H BLOB, I BLOB,
|
||||||
|
J BLOB, K BLOB, L BLOB,
|
||||||
|
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
INSERT INTO t2_purge VALUES (1,
|
||||||
|
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
|
||||||
|
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
|
||||||
|
REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
|
||||||
|
CREATE TABLE t3_purge (
|
||||||
|
A INT,
|
||||||
|
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
|
||||||
|
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
|
||||||
|
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
|
||||||
|
INDEX (A)
|
||||||
|
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
INSERT INTO t3_purge SELECT * FROM t1_purge;
|
||||||
|
CREATE TABLE t4_purge (
|
||||||
|
A INT PRIMARY KEY,
|
||||||
|
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
|
||||||
|
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
|
||||||
|
J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
|
||||||
|
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
INSERT INTO t4_purge SELECT * FROM t2_purge;
|
||||||
|
DELETE FROM t1_purge;
|
||||||
|
DELETE FROM t2_purge;
|
||||||
|
DELETE FROM t3_purge;
|
||||||
|
DELETE FROM t4_purge;
|
||||||
|
set global innodb_file_per_table=0;
|
||||||
|
set global innodb_file_format=Antelope;
|
||||||
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
|
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
|
||||||
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
|
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
|
||||||
commit;
|
commit;
|
||||||
@ -979,6 +1022,7 @@ v16 VARCHAR(500), v17 VARCHAR(500), v18 VARCHAR(500)
|
|||||||
CREATE INDEX idx1 ON t1(a,v1);
|
CREATE INDEX idx1 ON t1(a,v1);
|
||||||
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
||||||
UPDATE t1 SET a=1000;
|
UPDATE t1 SET a=1000;
|
||||||
|
DELETE FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
set global innodb_file_per_table=0;
|
set global innodb_file_per_table=0;
|
||||||
set global innodb_file_format=Antelope;
|
set global innodb_file_format=Antelope;
|
||||||
@ -1183,3 +1227,4 @@ a b
|
|||||||
3 a
|
3 a
|
||||||
3 b
|
3 b
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
|
||||||
|
@ -4,6 +4,65 @@ let $MYSQLD_DATADIR= `select @@datadir`;
|
|||||||
|
|
||||||
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
|
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
|
||||||
|
|
||||||
|
let $per_table=`select @@innodb_file_per_table`;
|
||||||
|
let $format=`select @@innodb_file_format`;
|
||||||
|
set global innodb_file_per_table=on;
|
||||||
|
set global innodb_file_format='Barracuda';
|
||||||
|
|
||||||
|
# Test an assertion failure on purge.
|
||||||
|
CREATE TABLE t1_purge (
|
||||||
|
A INT,
|
||||||
|
B BLOB, C BLOB, D BLOB, E BLOB,
|
||||||
|
F BLOB, G BLOB, H BLOB,
|
||||||
|
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
|
||||||
|
INDEX (A)
|
||||||
|
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
INSERT INTO t1_purge VALUES (1,
|
||||||
|
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
|
||||||
|
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766));
|
||||||
|
|
||||||
|
CREATE TABLE t2_purge (
|
||||||
|
A INT PRIMARY KEY,
|
||||||
|
B BLOB, C BLOB, D BLOB, E BLOB,
|
||||||
|
F BLOB, G BLOB, H BLOB, I BLOB,
|
||||||
|
J BLOB, K BLOB, L BLOB,
|
||||||
|
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
INSERT INTO t2_purge VALUES (1,
|
||||||
|
REPEAT('b', 766), REPEAT('c', 766), REPEAT('d', 766), REPEAT('e', 766),
|
||||||
|
REPEAT('f', 766), REPEAT('g', 766), REPEAT('h', 766), REPEAT('i', 766),
|
||||||
|
REPEAT('j', 766), REPEAT('k', 766), REPEAT('l', 766));
|
||||||
|
|
||||||
|
CREATE TABLE t3_purge (
|
||||||
|
A INT,
|
||||||
|
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
|
||||||
|
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800),
|
||||||
|
PRIMARY KEY (B(767), C(767), D(767), E(767), A),
|
||||||
|
INDEX (A)
|
||||||
|
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
INSERT INTO t3_purge SELECT * FROM t1_purge;
|
||||||
|
|
||||||
|
CREATE TABLE t4_purge (
|
||||||
|
A INT PRIMARY KEY,
|
||||||
|
B VARCHAR(800), C VARCHAR(800), D VARCHAR(800), E VARCHAR(800),
|
||||||
|
F VARCHAR(800), G VARCHAR(800), H VARCHAR(800), I VARCHAR(800),
|
||||||
|
J VARCHAR(800), K VARCHAR(800), L VARCHAR(800),
|
||||||
|
INDEX (B(767))) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||||
|
|
||||||
|
INSERT INTO t4_purge SELECT * FROM t2_purge;
|
||||||
|
|
||||||
|
# This would trigger the failure (Bug #12429576)
|
||||||
|
# if purge gets a chance to run before DROP TABLE t1_purge, ....
|
||||||
|
DELETE FROM t1_purge;
|
||||||
|
DELETE FROM t2_purge;
|
||||||
|
DELETE FROM t3_purge;
|
||||||
|
DELETE FROM t4_purge;
|
||||||
|
|
||||||
|
eval set global innodb_file_per_table=$per_table;
|
||||||
|
eval set global innodb_file_format=$format;
|
||||||
|
|
||||||
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
|
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
|
||||||
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
|
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
|
||||||
commit;
|
commit;
|
||||||
@ -360,8 +419,6 @@ disconnect b;
|
|||||||
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
let $per_table=`select @@innodb_file_per_table`;
|
|
||||||
let $format=`select @@innodb_file_format`;
|
|
||||||
set global innodb_file_per_table=on;
|
set global innodb_file_per_table=on;
|
||||||
set global innodb_file_format='Barracuda';
|
set global innodb_file_format='Barracuda';
|
||||||
# Test creating a table that could lead to undo log overflow.
|
# Test creating a table that could lead to undo log overflow.
|
||||||
@ -418,6 +475,9 @@ CREATE TABLE t1(a INT,
|
|||||||
CREATE INDEX idx1 ON t1(a,v1);
|
CREATE INDEX idx1 ON t1(a,v1);
|
||||||
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
INSERT INTO t1 VALUES(9,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r,@r);
|
||||||
UPDATE t1 SET a=1000;
|
UPDATE t1 SET a=1000;
|
||||||
|
DELETE FROM t1;
|
||||||
|
# Let the purge thread clean up this file.
|
||||||
|
-- sleep 10
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
eval set global innodb_file_per_table=$per_table;
|
eval set global innodb_file_per_table=$per_table;
|
||||||
@ -557,6 +617,7 @@ disconnect a;
|
|||||||
disconnect b;
|
disconnect b;
|
||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
|
||||||
|
|
||||||
#
|
#
|
||||||
# restore environment to the state it was before this test execution
|
# restore environment to the state it was before this test execution
|
||||||
|
49
mysql-test/suite/rpl/r/rpl_row_corruption.result
Normal file
49
mysql-test/suite/rpl/r/rpl_row_corruption.result
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
include/master-slave.inc
|
||||||
|
[connection master]
|
||||||
|
CREATE TABLE t1_11753004 (c1 INT);
|
||||||
|
CREATE TABLE t2_11753004 (c1 INT);
|
||||||
|
INSERT INTO t1_11753004 VALUES (1);
|
||||||
|
INSERT INTO t2_11753004 VALUES (2);
|
||||||
|
call mtr.add_suppression(".*Found table map event mapping table id 0 which was already mapped but with different settings.*");
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET @save_debug= @@global.debug;
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
include/start_slave.inc
|
||||||
|
UPDATE t1_11753004, t2_11753004 SET t1_11753004.c1=3, t2_11753004.c1=4 WHERE t1_11753004.c1=1 OR t2_11753004.c1=2;
|
||||||
|
include/wait_for_slave_sql_error.inc [errno=1593 ]
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
include/start_slave.inc
|
||||||
|
include/rpl_reset.inc
|
||||||
|
DROP TABLE t1_11753004, t2_11753004;
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
include/start_slave.inc
|
||||||
|
include/rpl_reset.inc
|
||||||
|
CREATE TABLE t1_11753004 (c1 INT);
|
||||||
|
CREATE TABLE t2_11753004_ign (c1 INT);
|
||||||
|
INSERT INTO t1_11753004 VALUES (1);
|
||||||
|
INSERT INTO t2_11753004_ign VALUES (2);
|
||||||
|
UPDATE t1_11753004, t2_11753004_ign SET t1_11753004.c1=3, t2_11753004_ign.c1=4 WHERE t1_11753004.c1=1 OR t2_11753004_ign.c1=2;
|
||||||
|
CREATE TABLE t1 (c1 INT);
|
||||||
|
CREATE TABLE t2 (c1 INT);
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
BINLOG '
|
||||||
|
SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=
|
||||||
|
'/*!*/;
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
BINLOG '
|
||||||
|
SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE=
|
||||||
|
SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE=
|
||||||
|
SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA==
|
||||||
|
SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA==
|
||||||
|
'/*!*/;
|
||||||
|
ERROR HY000: Fatal error: Found table map event mapping table id 0 which was already mapped but with different settings.
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
DROP TABLE t1_11753004;
|
||||||
|
DROP TABLE t2_11753004_ign;
|
||||||
|
SET GLOBAL debug= @save_debug;
|
||||||
|
include/rpl_end.inc
|
1
mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
Normal file
1
mysql-test/suite/rpl/t/rpl_row_corruption-slave.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--replicate-ignore-table=test.t2_11753004_ign
|
115
mysql-test/suite/rpl/t/rpl_row_corruption.test
Normal file
115
mysql-test/suite/rpl/t/rpl_row_corruption.test
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#
|
||||||
|
--source include/master-slave.inc
|
||||||
|
--source include/have_debug.inc
|
||||||
|
--source include/have_binlog_format_row.inc
|
||||||
|
|
||||||
|
# BUG#11753004: 44360: REPLICATION FAILED
|
||||||
|
|
||||||
|
## assert that we get an error when checking the
|
||||||
|
## identifiers at the slave (instead of a crash or
|
||||||
|
## different table being updated)
|
||||||
|
|
||||||
|
--let $t1= t1_11753004
|
||||||
|
--let $t2= t2_11753004
|
||||||
|
--let $t2_ign= t2_11753004_ign
|
||||||
|
|
||||||
|
## test #1: assert that we get an error raised when multiple
|
||||||
|
## tables in the same RBR statement are mapped with the
|
||||||
|
## same identifier
|
||||||
|
|
||||||
|
--eval CREATE TABLE $t1 (c1 INT)
|
||||||
|
--eval CREATE TABLE $t2 (c1 INT)
|
||||||
|
--eval INSERT INTO $t1 VALUES (1)
|
||||||
|
--eval INSERT INTO $t2 VALUES (2)
|
||||||
|
|
||||||
|
--sync_slave_with_master
|
||||||
|
call mtr.add_suppression(".*Found table map event mapping table id 0 which was already mapped but with different settings.*");
|
||||||
|
|
||||||
|
# stop the slave and inject corruption
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
SET @save_debug= @@global.debug;
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--connection master
|
||||||
|
# both tables get mapped to 0 (in a way, simulating scenario
|
||||||
|
# originated by BUG#56226)
|
||||||
|
--eval UPDATE $t1, $t2 SET $t1.c1=3, $t2.c1=4 WHERE $t1.c1=1 OR $t2.c1=2
|
||||||
|
--connection slave
|
||||||
|
|
||||||
|
# wait for error 1593 (ER_SLAVE_FATAL_ERROR)
|
||||||
|
--let $slave_sql_errno=1593
|
||||||
|
--source include/wait_for_slave_sql_error.inc
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
# clean up
|
||||||
|
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--connection master
|
||||||
|
--source include/rpl_reset.inc
|
||||||
|
--eval DROP TABLE $t1, $t2
|
||||||
|
--sync_slave_with_master
|
||||||
|
|
||||||
|
## test #2: assert that ignored tables that may have been mapped
|
||||||
|
## with the same identifier are skipped, thus no error
|
||||||
|
## is raised.
|
||||||
|
|
||||||
|
--connection slave
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
--source include/start_slave.inc
|
||||||
|
--source include/rpl_reset.inc
|
||||||
|
--connection master
|
||||||
|
--eval CREATE TABLE $t1 (c1 INT)
|
||||||
|
--eval CREATE TABLE $t2_ign (c1 INT)
|
||||||
|
--eval INSERT INTO $t1 VALUES (1)
|
||||||
|
--eval INSERT INTO $t2_ign VALUES (2)
|
||||||
|
--eval UPDATE $t1, $t2_ign SET $t1.c1=3, $t2_ign.c1=4 WHERE $t1.c1=1 OR $t2_ign.c1=2
|
||||||
|
|
||||||
|
# must not raise error as second table is filtered
|
||||||
|
--sync_slave_with_master
|
||||||
|
|
||||||
|
|
||||||
|
## test #3: check that BINLOG statements will also raise an
|
||||||
|
## error if containing table map events mapping different
|
||||||
|
## tables to same table identifier.
|
||||||
|
|
||||||
|
CREATE TABLE t1 (c1 INT);
|
||||||
|
CREATE TABLE t2 (c1 INT);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (1);
|
||||||
|
INSERT INTO t2 VALUES (1);
|
||||||
|
|
||||||
|
# FD event
|
||||||
|
BINLOG '
|
||||||
|
SOgWTg8BAAAAbgAAAHIAAAAAAAQANS42LjMtbTUtZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAABI6BZOEzgNAAgAEgAEBAQEEgAAVgAEGggAAAAICAgCAAAAAAVAYI8=
|
||||||
|
'/*!*/;
|
||||||
|
|
||||||
|
#110708 12:21:44 server id 1 end_log_pos 774 Table_map: `test`.`t1` mapped to number 66
|
||||||
|
# at 774
|
||||||
|
#110708 12:21:44 server id 1 end_log_pos 815 Table_map: `test`.`t2` mapped to number 67
|
||||||
|
# at 815
|
||||||
|
#110708 12:21:44 server id 1 end_log_pos 855 Update_rows: table id 66
|
||||||
|
# at 855
|
||||||
|
#110708 12:21:44 server id 1 end_log_pos 895 Update_rows: table id 67 flags: STMT_END_F
|
||||||
|
SET GLOBAL debug="+d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
--error ER_SLAVE_FATAL_ERROR
|
||||||
|
BINLOG '
|
||||||
|
SOgWThMBAAAAKQAAAAYDAAAAAEIAAAAAAAEABHRlc3QAAnQxAAEDAAE=
|
||||||
|
SOgWThMBAAAAKQAAAC8DAAAAAEMAAAAAAAEABHRlc3QAAnQyAAEDAAE=
|
||||||
|
SOgWThgBAAAAKAAAAFcDAAAAAEIAAAAAAAAAAf///gEAAAD+AwAAAA==
|
||||||
|
SOgWThgBAAAAKAAAAH8DAAAAAEMAAAAAAAEAAf///gEAAAD+BAAAAA==
|
||||||
|
'/*!*/;
|
||||||
|
|
||||||
|
|
||||||
|
# clean up
|
||||||
|
DROP TABLE t1,t2;
|
||||||
|
--connection slave
|
||||||
|
SET GLOBAL debug="-d,inject_tblmap_same_id_maps_diff_table";
|
||||||
|
--connection master
|
||||||
|
--eval DROP TABLE $t1
|
||||||
|
--eval DROP TABLE $t2_ign
|
||||||
|
--sync_slave_with_master
|
||||||
|
SET GLOBAL debug= @save_debug;
|
||||||
|
|
||||||
|
--source include/rpl_end.inc
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Test of different EXPLAIN's
|
# Test of different EXPLAINs
|
||||||
|
|
||||||
--disable_warnings
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT);
|
|||||||
SELECT @@session.sql_mode INTO @old_sql_mode;
|
SELECT @@session.sql_mode INTO @old_sql_mode;
|
||||||
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
||||||
|
|
||||||
# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE.
|
# EXPLAIN EXTENDED (with subselect). used to crash.
|
||||||
--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
|
# This is actually a valid query for this sql_mode,
|
||||||
|
# but it was transformed in such a way that it failed, see
|
||||||
|
# Bug#12329653 - EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
|
||||||
EXPLAIN EXTENDED SELECT 1 FROM t1
|
EXPLAIN EXTENDED SELECT 1 FROM t1
|
||||||
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
|
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
|
||||||
SHOW WARNINGS;
|
|
||||||
|
|
||||||
SET SESSION sql_mode=@old_sql_mode;
|
SET SESSION sql_mode=@old_sql_mode;
|
||||||
|
|
||||||
|
1
mysql-test/t/secure_file_priv_win-master.opt
Normal file
1
mysql-test/t/secure_file_priv_win-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--secure_file_priv=$MYSQL_TMP_DIR
|
79
mysql-test/t/secure_file_priv_win.test
Normal file
79
mysql-test/t/secure_file_priv_win.test
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#
|
||||||
|
# Bug58747 breaks secure_file_priv+not secure yet+still accesses other folders
|
||||||
|
#
|
||||||
|
|
||||||
|
# we do the windows specific relative directory testing
|
||||||
|
|
||||||
|
--source include/windows.inc
|
||||||
|
|
||||||
|
CREATE TABLE t1 (c1 longtext);
|
||||||
|
INSERT INTO t1 values ('a');
|
||||||
|
|
||||||
|
LET $MYSQL_TMP_DIR_UCASE= `SELECT upper('$MYSQL_TMP_DIR')`;
|
||||||
|
LET $MYSQL_TMP_DIR_LCASE= `SELECT lower('$MYSQL_TMP_DIR')`;
|
||||||
|
|
||||||
|
#create the file
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517.tmp';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
show global variables like 'secure_file_priv';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT load_file('$MYSQL_TMP_DIR\\\\B11764517.tmp') AS x;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT load_file('$MYSQL_TMP_DIR/B11764517.tmp') AS x;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
|
||||||
|
eval SELECT load_file('$MYSQL_TMP_DIR_UCASE/B11764517.tmp') AS x;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
|
||||||
|
eval SELECT load_file('$MYSQL_TMP_DIR_LCASE/B11764517.tmp') AS x;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT load_file('$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp') AS x;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval LOAD DATA INFILE '$MYSQL_TMP_DIR\\\\B11764517.tmp' INTO TABLE t1;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval LOAD DATA INFILE '$MYSQL_TMP_DIR/B11764517.tmp' INTO TABLE t1;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
|
||||||
|
eval LOAD DATA INFILE '$MYSQL_TMP_DIR_UCASE/B11764517.tmp' INTO TABLE t1;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
|
||||||
|
eval LOAD DATA INFILE '$MYSQL_TMP_DIR_LCASE/B11764517.tmp' INTO TABLE t1;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
--error ER_OPTION_PREVENTS_STATEMENT
|
||||||
|
eval LOAD DATA INFILE "$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517.tmp" into table t1;
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
--error ER_OPTION_PREVENTS_STATEMENT
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\..a..\\\\..\\\\..\\\\B11764517-2.tmp';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR\\\\B11764517-2.tmp';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR/B11764517-3.tmp';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_UCASE MYSQL_TMP_DIR_UCASE
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_UCASE/B11764517-4.tmp';
|
||||||
|
|
||||||
|
--replace_result $MYSQL_TMP_DIR_LCASE MYSQL_TMP_DIR_LCASE
|
||||||
|
eval SELECT * FROM t1 INTO OUTFILE '$MYSQL_TMP_DIR_LCASE/B11764517-5.tmp';
|
||||||
|
|
||||||
|
--error 0,1
|
||||||
|
--remove_file $MYSQL_TMP_DIR/B11764517.tmp;
|
||||||
|
--error 0,1
|
||||||
|
--remove_file $MYSQL_TMP_DIR/B11764517-2.tmp;
|
||||||
|
--error 0,1
|
||||||
|
--remove_file $MYSQL_TMP_DIR/B11764517-3.tmp;
|
||||||
|
--error 0,1
|
||||||
|
--remove_file $MYSQL_TMP_DIR/B11764517-4.tmp;
|
||||||
|
--error 0,1
|
||||||
|
--remove_file $MYSQL_TMP_DIR/B11764517-5.tmp;
|
||||||
|
DROP TABLE t1;
|
@ -926,6 +926,43 @@ DROP DATABASE B48872;
|
|||||||
|
|
||||||
--echo End of 5.0 tests.
|
--echo End of 5.0 tests.
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE
|
||||||
|
--echo # DEFINITION OF ANY ROUTINE.
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS db1;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE DATABASE db1;
|
||||||
|
CREATE PROCEDURE db1.p1() SELECT 1;
|
||||||
|
CREATE USER user2@localhost IDENTIFIED BY '';
|
||||||
|
GRANT SELECT(db) ON mysql.proc TO user2@localhost;
|
||||||
|
|
||||||
|
--echo # Connection con2 as user2
|
||||||
|
connect (con2, localhost, user2);
|
||||||
|
--echo # The statement below before disclosed info from body_utf8 column.
|
||||||
|
--error ER_SP_DOES_NOT_EXIST
|
||||||
|
SHOW CREATE PROCEDURE db1.p1;
|
||||||
|
|
||||||
|
--echo # Check that SHOW works with SELECT grant on whole table
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
GRANT SELECT ON mysql.proc TO user2@localhost;
|
||||||
|
|
||||||
|
--echo # Connection con2
|
||||||
|
connection con2;
|
||||||
|
--echo # This should work
|
||||||
|
SHOW CREATE PROCEDURE db1.p1;
|
||||||
|
|
||||||
|
--echo # Connection default
|
||||||
|
connection default;
|
||||||
|
disconnect con2;
|
||||||
|
DROP USER user2@localhost;
|
||||||
|
DROP DATABASE db1;
|
||||||
|
|
||||||
|
|
||||||
# Wait till all disconnects are completed
|
# Wait till all disconnects are completed
|
||||||
--source include/wait_until_count_sessions.inc
|
--source include/wait_until_count_sessions.inc
|
||||||
|
|
||||||
|
@ -3393,6 +3393,39 @@ ORDER BY outr.pk;
|
|||||||
|
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug#12329653
|
||||||
|
--echo # EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1(a1 int);
|
||||||
|
INSERT INTO t1 VALUES (1),(2);
|
||||||
|
|
||||||
|
SELECT @@session.sql_mode INTO @old_sql_mode;
|
||||||
|
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
|
||||||
|
|
||||||
|
## First a simpler query, illustrating the transformation
|
||||||
|
## '1 < some (...)' => '1 < max(...)'
|
||||||
|
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
|
||||||
|
|
||||||
|
## The query which made the server crash.
|
||||||
|
PREPARE stmt FROM
|
||||||
|
'SELECT 1 UNION ALL
|
||||||
|
SELECT 1 FROM t1
|
||||||
|
ORDER BY
|
||||||
|
(SELECT 1 FROM t1 AS t1_0
|
||||||
|
WHERE 1 < SOME (SELECT a1 FROM t1)
|
||||||
|
)' ;
|
||||||
|
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
EXECUTE stmt ;
|
||||||
|
--error ER_SUBQUERY_NO_1_ROW
|
||||||
|
EXECUTE stmt ;
|
||||||
|
|
||||||
|
SET SESSION sql_mode=@old_sql_mode;
|
||||||
|
|
||||||
|
DEALLOCATE PREPARE stmt;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo End of 5.0 tests.
|
--echo End of 5.0 tests.
|
||||||
|
|
||||||
|
@ -146,24 +146,23 @@ int my_realpath(char *to, const char *filename, myf MyFlags)
|
|||||||
result= -1;
|
result= -1;
|
||||||
}
|
}
|
||||||
DBUG_RETURN(result);
|
DBUG_RETURN(result);
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
#ifdef _WIN32
|
int ret= GetFullPathName(filename,FN_REFLEN, to, NULL);
|
||||||
int ret= GetFullPathName(filename,FN_REFLEN,
|
|
||||||
to,
|
|
||||||
NULL);
|
|
||||||
if (ret == 0 || ret > FN_REFLEN)
|
if (ret == 0 || ret > FN_REFLEN)
|
||||||
{
|
{
|
||||||
if (ret > FN_REFLEN)
|
my_errno= (ret > FN_REFLEN) ? ENAMETOOLONG : GetLastError();
|
||||||
my_errno= ENAMETOOLONG;
|
|
||||||
else
|
|
||||||
my_errno= EACCES;
|
|
||||||
if (MyFlags & MY_WME)
|
if (MyFlags & MY_WME)
|
||||||
my_error(EE_REALPATH, MYF(0), filename, my_errno);
|
my_error(EE_REALPATH, MYF(0), filename, my_errno);
|
||||||
return -1;
|
/*
|
||||||
|
GetFullPathName didn't work : use my_load_path() which is a poor
|
||||||
|
substitute original name but will at least be able to resolve
|
||||||
|
paths that starts with '.'.
|
||||||
|
*/
|
||||||
|
my_load_path(to, filename, NullS);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
my_load_path(to, filename, NullS);
|
my_load_path(to, filename, NullS);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -4466,14 +4466,14 @@ mark_non_agg_field:
|
|||||||
SELECT_LEX *select_lex= cached_table ?
|
SELECT_LEX *select_lex= cached_table ?
|
||||||
cached_table->select_lex : context->select_lex;
|
cached_table->select_lex : context->select_lex;
|
||||||
if (!thd->lex->in_sum_func)
|
if (!thd->lex->in_sum_func)
|
||||||
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
|
select_lex->set_non_agg_field_used(true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (outer_fixed)
|
if (outer_fixed)
|
||||||
thd->lex->in_sum_func->outer_fields.push_back(this);
|
thd->lex->in_sum_func->outer_fields.push_back(this);
|
||||||
else if (thd->lex->in_sum_func->nest_level !=
|
else if (thd->lex->in_sum_func->nest_level !=
|
||||||
thd->lex->current_select->nest_level)
|
thd->lex->current_select->nest_level)
|
||||||
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
|
select_lex->set_non_agg_field_used(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1016,6 +1016,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
it.replace(item);
|
it.replace(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_EXECUTE("where",
|
||||||
|
print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
|
||||||
|
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(select_lex->non_agg_field_used());
|
||||||
|
select_lex->set_non_agg_field_used(false);
|
||||||
|
}
|
||||||
|
|
||||||
save_allow_sum_func= thd->lex->allow_sum_func;
|
save_allow_sum_func= thd->lex->allow_sum_func;
|
||||||
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
|
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
|
||||||
/*
|
/*
|
||||||
|
@ -247,10 +247,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
in_sum_func->outer_fields.push_back(field);
|
in_sum_func->outer_fields.push_back(field);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sel->full_group_by_flag|= NON_AGG_FIELD_USED;
|
sel->set_non_agg_field_used(true);
|
||||||
}
|
}
|
||||||
if (sel->nest_level > aggr_level &&
|
if (sel->nest_level > aggr_level &&
|
||||||
(sel->full_group_by_flag & SUM_FUNC_USED) &&
|
(sel->agg_func_used()) &&
|
||||||
!sel->group_list.elements)
|
!sel->group_list.elements)
|
||||||
{
|
{
|
||||||
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
|
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
|
||||||
@ -259,7 +259,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
|
aggr_sel->set_agg_func_used(true);
|
||||||
update_used_tables();
|
update_used_tables();
|
||||||
thd->lex->in_sum_func= in_sum_func;
|
thd->lex->in_sum_func= in_sum_func;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
163
sql/log_event.cc
163
sql/log_event.cc
@ -59,6 +59,11 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd);
|
|||||||
|
|
||||||
static const char *HA_ERR(int i)
|
static const char *HA_ERR(int i)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
This function should only be called in case of an error
|
||||||
|
was detected
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(i != 0);
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case HA_ERR_KEY_NOT_FOUND: return "HA_ERR_KEY_NOT_FOUND";
|
case HA_ERR_KEY_NOT_FOUND: return "HA_ERR_KEY_NOT_FOUND";
|
||||||
case HA_ERR_FOUND_DUPP_KEY: return "HA_ERR_FOUND_DUPP_KEY";
|
case HA_ERR_FOUND_DUPP_KEY: return "HA_ERR_FOUND_DUPP_KEY";
|
||||||
@ -111,7 +116,7 @@ static const char *HA_ERR(int i)
|
|||||||
case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
|
case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
|
||||||
case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
|
case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
|
||||||
}
|
}
|
||||||
return 0;
|
return "No Error!";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,7 +137,7 @@ static void inline slave_rows_error_report(enum loglevel level, int ha_error,
|
|||||||
TABLE *table, const char * type,
|
TABLE *table, const char * type,
|
||||||
const char *log_name, ulong pos)
|
const char *log_name, ulong pos)
|
||||||
{
|
{
|
||||||
const char *handler_error= HA_ERR(ha_error);
|
const char *handler_error= (ha_error ? HA_ERR(ha_error) : NULL);
|
||||||
char buff[MAX_SLAVE_ERRMSG], *slider;
|
char buff[MAX_SLAVE_ERRMSG], *slider;
|
||||||
const char *buff_end= buff + sizeof(buff);
|
const char *buff_end= buff + sizeof(buff);
|
||||||
uint len;
|
uint len;
|
||||||
@ -7596,7 +7601,8 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
|
|
||||||
error= do_exec_row(rli);
|
error= do_exec_row(rli);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
if (error)
|
||||||
|
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||||
DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
|
DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
|
||||||
|
|
||||||
table->in_use = old_thd;
|
table->in_use = old_thd;
|
||||||
@ -8222,6 +8228,97 @@ Table_map_log_event::~Table_map_log_event()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
|
||||||
|
|
||||||
|
enum enum_tbl_map_status
|
||||||
|
{
|
||||||
|
/* no duplicate identifier found */
|
||||||
|
OK_TO_PROCESS= 0,
|
||||||
|
|
||||||
|
/* this table map must be filtered out */
|
||||||
|
FILTERED_OUT= 1,
|
||||||
|
|
||||||
|
/* identifier mapping table with different properties */
|
||||||
|
SAME_ID_MAPPING_DIFFERENT_TABLE= 2,
|
||||||
|
|
||||||
|
/* a duplicate identifier was found mapping the same table */
|
||||||
|
SAME_ID_MAPPING_SAME_TABLE= 3
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Checks if this table map event should be processed or not. First
|
||||||
|
it checks the filtering rules, and then looks for duplicate identifiers
|
||||||
|
in the existing list of rli->tables_to_lock.
|
||||||
|
|
||||||
|
It checks that there hasn't been any corruption by verifying that there
|
||||||
|
are no duplicate entries with different properties.
|
||||||
|
|
||||||
|
In some cases, some binary logs could get corrupted, showing several
|
||||||
|
tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
|
||||||
|
early sanity check for such cases and avoid that the server crashes
|
||||||
|
later.
|
||||||
|
|
||||||
|
In some corner cases, the master logs duplicate table map events, i.e.,
|
||||||
|
same id, same database name, same table name (see: BUG#37137). This is
|
||||||
|
different from the above as it's the same table that is mapped again
|
||||||
|
to the same identifier. Thus we cannot just check for same ids and
|
||||||
|
assume that the event is corrupted we need to check every property.
|
||||||
|
|
||||||
|
NOTE: in the event that BUG#37137 ever gets fixed, this extra check
|
||||||
|
will still be valid because we would need to support old binary
|
||||||
|
logs anyway.
|
||||||
|
|
||||||
|
@param rli The relay log info reference.
|
||||||
|
@param table_list A list element containing the table to check against.
|
||||||
|
@return OK_TO_PROCESS
|
||||||
|
if there was no identifier already in rli->tables_to_lock
|
||||||
|
|
||||||
|
FILTERED_OUT
|
||||||
|
if the event is filtered according to the filtering rules
|
||||||
|
|
||||||
|
SAME_ID_MAPPING_DIFFERENT_TABLE
|
||||||
|
if the same identifier already maps a different table in
|
||||||
|
rli->tables_to_lock
|
||||||
|
|
||||||
|
SAME_ID_MAPPING_SAME_TABLE
|
||||||
|
if the same identifier already maps the same table in
|
||||||
|
rli->tables_to_lock.
|
||||||
|
*/
|
||||||
|
static enum_tbl_map_status
|
||||||
|
check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("check_table_map");
|
||||||
|
enum_tbl_map_status res= OK_TO_PROCESS;
|
||||||
|
|
||||||
|
if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
|
||||||
|
(!rpl_filter->db_ok(table_list->db) ||
|
||||||
|
(rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
|
||||||
|
res= FILTERED_OUT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(rli->tables_to_lock);
|
||||||
|
ptr;
|
||||||
|
ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_local))
|
||||||
|
{
|
||||||
|
if (ptr->table_id == table_list->table_id)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (strcmp(ptr->db, table_list->db) ||
|
||||||
|
strcmp(ptr->alias, table_list->table_name) ||
|
||||||
|
ptr->lock_type != TL_WRITE) // the ::do_apply_event always sets TL_WRITE
|
||||||
|
res= SAME_ID_MAPPING_DIFFERENT_TABLE;
|
||||||
|
else
|
||||||
|
res= SAME_ID_MAPPING_SAME_TABLE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
|
||||||
|
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
|
||||||
int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
||||||
{
|
{
|
||||||
RPL_TABLE_LIST *table_list;
|
RPL_TABLE_LIST *table_list;
|
||||||
@ -8248,20 +8345,13 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
table_list->alias= table_list->table_name = tname_mem;
|
table_list->alias= table_list->table_name = tname_mem;
|
||||||
table_list->lock_type= TL_WRITE;
|
table_list->lock_type= TL_WRITE;
|
||||||
table_list->next_global= table_list->next_local= 0;
|
table_list->next_global= table_list->next_local= 0;
|
||||||
table_list->table_id= m_table_id;
|
table_list->table_id= DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id);
|
||||||
table_list->updating= 1;
|
table_list->updating= 1;
|
||||||
strmov(table_list->db, rpl_filter->get_rewrite_db(m_dbnam, &dummy_len));
|
strmov(table_list->db, rpl_filter->get_rewrite_db(m_dbnam, &dummy_len));
|
||||||
strmov(table_list->table_name, m_tblnam);
|
strmov(table_list->table_name, m_tblnam);
|
||||||
|
DBUG_PRINT("debug", ("table: %s is mapped to %u", table_list->table_name, table_list->table_id));
|
||||||
int error= 0;
|
enum_tbl_map_status tblmap_status= check_table_map(rli, table_list);
|
||||||
|
if (tblmap_status == OK_TO_PROCESS)
|
||||||
if (rli->sql_thd->slave_thread /* filtering is for slave only */ &&
|
|
||||||
(!rpl_filter->db_ok(table_list->db) ||
|
|
||||||
(rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
|
|
||||||
{
|
|
||||||
my_free(memory, MYF(MY_WME));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(thd->lex->query_tables != table_list);
|
DBUG_ASSERT(thd->lex->query_tables != table_list);
|
||||||
|
|
||||||
@ -8290,8 +8380,48 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
const_cast<Relay_log_info*>(rli)->tables_to_lock_count++;
|
const_cast<Relay_log_info*>(rli)->tables_to_lock_count++;
|
||||||
/* 'memory' is freed in clear_tables_to_lock */
|
/* 'memory' is freed in clear_tables_to_lock */
|
||||||
}
|
}
|
||||||
|
else // FILTERED_OUT, SAME_ID_MAPPING_*
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If mapped already but with different properties, we raise an
|
||||||
|
error.
|
||||||
|
If mapped already but with same properties we skip the event.
|
||||||
|
If filtered out we skip the event.
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
In all three cases, we need to free the memory previously
|
||||||
|
allocated.
|
||||||
|
*/
|
||||||
|
if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Something bad has happened. We need to stop the slave as strange things
|
||||||
|
could happen if we proceed: slave crash, wrong table being updated, ...
|
||||||
|
As a consequence we push an error in this case.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
my_snprintf(buf, sizeof(buf),
|
||||||
|
"Found table map event mapping table id %u which "
|
||||||
|
"was already mapped but with different settings.",
|
||||||
|
table_list->table_id);
|
||||||
|
|
||||||
|
if (thd->slave_thread)
|
||||||
|
rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
|
||||||
|
ER(ER_SLAVE_FATAL_ERROR), buf);
|
||||||
|
else
|
||||||
|
/*
|
||||||
|
For the cases in which a 'BINLOG' statement is set to
|
||||||
|
execute in a user session
|
||||||
|
*/
|
||||||
|
my_printf_error(ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
|
||||||
|
MYF(0), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_free(memory, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log_event::enum_skip_reason
|
Log_event::enum_skip_reason
|
||||||
@ -9220,7 +9350,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
|
|||||||
restart_rnd_next:
|
restart_rnd_next:
|
||||||
error= table->file->rnd_next(table->record[0]);
|
error= table->file->rnd_next(table->record[0]);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
if (error)
|
||||||
|
DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
|
||||||
switch (error) {
|
switch (error) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -1475,13 +1475,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
|
|||||||
bool allow_null_cond, int *error);
|
bool allow_null_cond, int *error);
|
||||||
extern Item **not_found_item;
|
extern Item **not_found_item;
|
||||||
|
|
||||||
/*
|
|
||||||
A set of constants used for checking non aggregated fields and sum
|
|
||||||
functions mixture in the ONLY_FULL_GROUP_BY_MODE.
|
|
||||||
*/
|
|
||||||
#define NON_AGG_FIELD_USED 1
|
|
||||||
#define SUM_FUNC_USED 2
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This enumeration type is used only by the function find_item_in_list
|
This enumeration type is used only by the function find_item_in_list
|
||||||
to return the info on how an item has been resolved against a list
|
to return the info on how an item has been resolved against a list
|
||||||
|
@ -8973,12 +8973,15 @@ fn_format_relative_to_data_home(char * to, const char *name,
|
|||||||
bool is_secure_file_path(char *path)
|
bool is_secure_file_path(char *path)
|
||||||
{
|
{
|
||||||
char buff1[FN_REFLEN], buff2[FN_REFLEN];
|
char buff1[FN_REFLEN], buff2[FN_REFLEN];
|
||||||
|
size_t opt_secure_file_priv_len;
|
||||||
/*
|
/*
|
||||||
All paths are secure if opt_secure_file_path is 0
|
All paths are secure if opt_secure_file_path is 0
|
||||||
*/
|
*/
|
||||||
if (!opt_secure_file_priv)
|
if (!opt_secure_file_priv)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
opt_secure_file_priv_len= strlen(opt_secure_file_priv);
|
||||||
|
|
||||||
if (strlen(path) >= FN_REFLEN)
|
if (strlen(path) >= FN_REFLEN)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -8996,11 +8999,24 @@ bool is_secure_file_path(char *path)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
convert_dirname(buff2, buff1, NullS);
|
convert_dirname(buff2, buff1, NullS);
|
||||||
if (strncmp(opt_secure_file_priv, buff2, strlen(opt_secure_file_priv)))
|
if (!lower_case_file_system)
|
||||||
return FALSE;
|
{
|
||||||
|
if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (files_charset_info->coll->strnncoll(files_charset_info,
|
||||||
|
(uchar *) buff2, strlen(buff2),
|
||||||
|
(uchar *) opt_secure_file_priv,
|
||||||
|
opt_secure_file_priv_len,
|
||||||
|
TRUE))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int fix_paths(void)
|
static int fix_paths(void)
|
||||||
{
|
{
|
||||||
char buff[FN_REFLEN],*pos;
|
char buff[FN_REFLEN],*pos;
|
||||||
|
@ -2403,7 +2403,8 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access)
|
|||||||
bzero((char*) &tables,sizeof(tables));
|
bzero((char*) &tables,sizeof(tables));
|
||||||
tables.db= (char*) "mysql";
|
tables.db= (char*) "mysql";
|
||||||
tables.table_name= tables.alias= (char*) "proc";
|
tables.table_name= tables.alias= (char*) "proc";
|
||||||
*full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) ||
|
*full_access= ((!check_table_access(thd, SELECT_ACL, &tables, 1, TRUE) &&
|
||||||
|
(tables.grant.privilege & SELECT_ACL) != 0) ||
|
||||||
(!strcmp(sp->m_definer_user.str,
|
(!strcmp(sp->m_definer_user.str,
|
||||||
thd->security_ctx->priv_user) &&
|
thd->security_ctx->priv_user) &&
|
||||||
!strcmp(sp->m_definer_host.str,
|
!strcmp(sp->m_definer_host.str,
|
||||||
|
@ -21,23 +21,10 @@
|
|||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
|
|
||||||
#ifdef HAVE_OPENSSL
|
/** Size of the header fields of an authentication packet. */
|
||||||
/*
|
#define AUTH_PACKET_HEADER_SIZE_PROTO_41 32
|
||||||
Without SSL the handshake consists of one packet. This packet
|
#define AUTH_PACKET_HEADER_SIZE_PROTO_40 5
|
||||||
has both client capabilites and scrambled password.
|
#define AUTH_PACKET_HEADER_SIZE_CONNJ_SSL 4
|
||||||
With SSL the handshake might consist of two packets. If the first
|
|
||||||
packet (client capabilities) has CLIENT_SSL flag set, we have to
|
|
||||||
switch to SSL and read the second packet. The scrambled password
|
|
||||||
is in the second packet and client_capabilites field will be ignored.
|
|
||||||
Maybe it is better to accept flags other than CLIENT_SSL from the
|
|
||||||
second packet?
|
|
||||||
*/
|
|
||||||
#define SSL_HANDSHAKE_SIZE 2
|
|
||||||
#define NORMAL_HANDSHAKE_SIZE 6
|
|
||||||
#define MIN_HANDSHAKE_SIZE 2
|
|
||||||
#else
|
|
||||||
#define MIN_HANDSHAKE_SIZE 6
|
|
||||||
#endif /* HAVE_OPENSSL */
|
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
extern void win_install_sigabrt_handler();
|
extern void win_install_sigabrt_handler();
|
||||||
@ -822,6 +809,14 @@ static int check_connection(THD *thd)
|
|||||||
ulong pkt_len= 0;
|
ulong pkt_len= 0;
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
|
bool packet_has_required_size= false;
|
||||||
|
char *db;
|
||||||
|
size_t db_len;
|
||||||
|
char *passwd;
|
||||||
|
size_t passwd_len;
|
||||||
|
char *user;
|
||||||
|
size_t user_len;
|
||||||
|
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
("New connection received on %s", vio_description(net->vio)));
|
("New connection received on %s", vio_description(net->vio)));
|
||||||
#ifdef SIGNAL_WITH_VIO_CLOSE
|
#ifdef SIGNAL_WITH_VIO_CLOSE
|
||||||
@ -930,8 +925,7 @@ static int check_connection(THD *thd)
|
|||||||
/* At this point we write connection message and read reply */
|
/* At this point we write connection message and read reply */
|
||||||
if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
|
if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
|
||||||
(uchar*) buff, (size_t) (end-buff)) ||
|
(uchar*) buff, (size_t) (end-buff)) ||
|
||||||
(pkt_len= my_net_read(net)) == packet_error ||
|
(pkt_len= my_net_read(net)) == packet_error)
|
||||||
pkt_len < MIN_HANDSHAKE_SIZE)
|
|
||||||
{
|
{
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
inc_host_errors(&thd->remote.sin_addr);
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
||||||
@ -946,22 +940,82 @@ static int check_connection(THD *thd)
|
|||||||
if (thd->packet.alloc(thd->variables.net_buffer_length))
|
if (thd->packet.alloc(thd->variables.net_buffer_length))
|
||||||
return 1; /* The error is set by alloc(). */
|
return 1; /* The error is set by alloc(). */
|
||||||
|
|
||||||
thd->client_capabilities= uint2korr(net->read_pos);
|
uint charset_code= 0;
|
||||||
|
end= (char *)net->read_pos;
|
||||||
|
/*
|
||||||
|
In order to safely scan a head for '\0' string terminators
|
||||||
|
we must keep track of how many bytes remain in the allocated
|
||||||
|
buffer or we might read past the end of the buffer.
|
||||||
|
*/
|
||||||
|
size_t bytes_remaining_in_packet= pkt_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Peek ahead on the client capability packet and determine which version of
|
||||||
|
the protocol should be used.
|
||||||
|
*/
|
||||||
|
if (bytes_remaining_in_packet < 2)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
thd->client_capabilities= uint2korr(end);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Connector/J only sends client capabilities (4 bytes) before starting SSL
|
||||||
|
negotiation so we don't have char_set and other information for client in
|
||||||
|
packet read. In that case, skip reading those information. The below code
|
||||||
|
is patch for this.
|
||||||
|
*/
|
||||||
|
if(bytes_remaining_in_packet == AUTH_PACKET_HEADER_SIZE_CONNJ_SSL &&
|
||||||
|
(thd->client_capabilities & CLIENT_SSL))
|
||||||
|
{
|
||||||
|
thd->client_capabilities= uint4korr(end);
|
||||||
|
thd->max_client_packet_length= global_system_variables.max_allowed_packet;
|
||||||
|
charset_code= default_charset_info->number;
|
||||||
|
end+= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
|
||||||
|
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_CONNJ_SSL;
|
||||||
|
goto skip_to_ssl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
|
||||||
|
packet_has_required_size= bytes_remaining_in_packet >=
|
||||||
|
AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
|
else
|
||||||
|
packet_has_required_size= bytes_remaining_in_packet >=
|
||||||
|
AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
|
||||||
|
if (!packet_has_required_size)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
|
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
|
||||||
{
|
{
|
||||||
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
|
thd->client_capabilities= uint4korr(end);
|
||||||
thd->max_client_packet_length= uint4korr(net->read_pos+4);
|
thd->max_client_packet_length= uint4korr(end + 4);
|
||||||
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
|
charset_code= (uint)(uchar)*(end + 8);
|
||||||
if (thd_init_client_charset(thd, (uint) net->read_pos[8]))
|
/*
|
||||||
return 1;
|
Skip 23 remaining filler bytes which have no particular meaning.
|
||||||
thd->update_charset();
|
*/
|
||||||
end= (char*) net->read_pos+32;
|
end+= AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
|
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thd->max_client_packet_length= uint3korr(net->read_pos+2);
|
thd->client_capabilities= uint2korr(end);
|
||||||
end= (char*) net->read_pos+5;
|
thd->max_client_packet_length= uint3korr(end + 2);
|
||||||
|
end+= AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
bytes_remaining_in_packet-= AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
/**
|
||||||
|
Old clients didn't have their own charset. Instead the assumption
|
||||||
|
was that they used what ever the server used.
|
||||||
|
*/
|
||||||
|
charset_code= default_charset_info->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skip_to_ssl:
|
||||||
|
|
||||||
|
DBUG_PRINT("info", ("client_character_set: %u", charset_code));
|
||||||
|
if (thd_init_client_charset(thd, charset_code))
|
||||||
|
goto error;
|
||||||
|
thd->update_charset();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Disable those bits which are not supported by the server.
|
Disable those bits which are not supported by the server.
|
||||||
This is a precautionary measure, if the client lies. See Bug#27944.
|
This is a precautionary measure, if the client lies. See Bug#27944.
|
||||||
@ -972,43 +1026,64 @@ static int check_connection(THD *thd)
|
|||||||
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
|
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
|
DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
|
||||||
|
|
||||||
|
/*
|
||||||
|
If client requested SSL then we must stop parsing, try to switch to SSL,
|
||||||
|
and wait for the client to send a new handshake packet.
|
||||||
|
The client isn't expected to send any more bytes until SSL is initialized.
|
||||||
|
*/
|
||||||
if (thd->client_capabilities & CLIENT_SSL)
|
if (thd->client_capabilities & CLIENT_SSL)
|
||||||
{
|
{
|
||||||
/* Do the SSL layering. */
|
/* Do the SSL layering. */
|
||||||
if (!ssl_acceptor_fd)
|
if (!ssl_acceptor_fd)
|
||||||
{
|
goto error;
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
DBUG_PRINT("info", ("IO layer change in progress..."));
|
DBUG_PRINT("info", ("IO layer change in progress..."));
|
||||||
if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
|
if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("Failed to accept new SSL connection"));
|
DBUG_PRINT("error", ("Failed to accept new SSL connection"));
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
goto error;
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Reading user information over SSL layer"));
|
DBUG_PRINT("info", ("Reading user information over SSL layer"));
|
||||||
if ((pkt_len= my_net_read(net)) == packet_error ||
|
if ((pkt_len= my_net_read(net)) == packet_error)
|
||||||
pkt_len < NORMAL_HANDSHAKE_SIZE)
|
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
|
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
|
||||||
pkt_len));
|
pkt_len));
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
goto error;
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
A new packet was read and the statistics reflecting the remaining bytes
|
||||||
|
in the packet must be updated.
|
||||||
|
*/
|
||||||
|
bytes_remaining_in_packet= pkt_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
After the SSL handshake is performed the client resends the handshake
|
||||||
|
packet but because of legacy reasons we chose not to parse the packet
|
||||||
|
fields a second time and instead only assert the length of the packet.
|
||||||
|
*/
|
||||||
|
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
|
||||||
|
{
|
||||||
|
|
||||||
|
packet_has_required_size= bytes_remaining_in_packet >=
|
||||||
|
AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
|
end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
|
bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_41;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
packet_has_required_size= bytes_remaining_in_packet >=
|
||||||
|
AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
end= (char *)net->read_pos + AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
bytes_remaining_in_packet -= AUTH_PACKET_HEADER_SIZE_PROTO_40;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packet_has_required_size)
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OPENSSL */
|
#endif /* HAVE_OPENSSL */
|
||||||
|
|
||||||
if (end > (char *)net->read_pos + pkt_len)
|
|
||||||
{
|
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
||||||
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
|
||||||
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
|
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
|
||||||
@ -1028,29 +1103,17 @@ static int check_connection(THD *thd)
|
|||||||
else
|
else
|
||||||
get_string= get_40_protocol_string;
|
get_string= get_40_protocol_string;
|
||||||
|
|
||||||
/*
|
user= get_string(&end, &bytes_remaining_in_packet, &user_len);
|
||||||
In order to safely scan a head for '\0' string terminators
|
|
||||||
we must keep track of how many bytes remain in the allocated
|
|
||||||
buffer or we might read past the end of the buffer.
|
|
||||||
*/
|
|
||||||
size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
|
|
||||||
|
|
||||||
size_t user_len;
|
|
||||||
char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
|
|
||||||
if (user == NULL)
|
if (user == NULL)
|
||||||
{
|
goto error;
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Old clients send a null-terminated string as password; new clients send
|
Old clients send a null-terminated string as password; new clients send
|
||||||
the size (1 byte) + string (not null-terminated). Hence in case of empty
|
the size (1 byte) + string (not null-terminated). Hence in case of empty
|
||||||
password both send '\0'.
|
password both send '\0'.
|
||||||
*/
|
*/
|
||||||
size_t passwd_len= 0;
|
passwd_len= 0;
|
||||||
char *passwd= NULL;
|
passwd= NULL;
|
||||||
|
|
||||||
if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
|
if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
|
||||||
{
|
{
|
||||||
@ -1069,24 +1132,16 @@ static int check_connection(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (passwd == NULL)
|
if (passwd == NULL)
|
||||||
{
|
goto error;
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t db_len= 0;
|
db_len= 0;
|
||||||
char *db= NULL;
|
db= NULL;
|
||||||
|
|
||||||
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
|
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
|
||||||
{
|
{
|
||||||
db= get_string(&end, &bytes_remaining_in_packet, &db_len);
|
db= get_string(&end, &bytes_remaining_in_packet, &db_len);
|
||||||
if (db == NULL)
|
if (db == NULL)
|
||||||
{
|
goto error;
|
||||||
inc_host_errors(&thd->remote.sin_addr);
|
|
||||||
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
|
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
|
||||||
@ -1134,11 +1189,14 @@ static int check_connection(THD *thd)
|
|||||||
user[user_len]= '\0';
|
user[user_len]= '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thd->main_security_ctx.user)
|
|
||||||
x_free(thd->main_security_ctx.user);
|
|
||||||
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
|
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
|
||||||
return 1; /* The error is set by my_strdup(). */
|
return 1; /* The error is set by my_strdup(). */
|
||||||
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
|
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
|
||||||
|
|
||||||
|
error:
|
||||||
|
inc_host_errors(&thd->remote.sin_addr);
|
||||||
|
my_error(ER_HANDSHAKE_ERROR, MYF(0));
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1388,3 +1446,4 @@ end_thread:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* EMBEDDED_LIBRARY */
|
#endif /* EMBEDDED_LIBRARY */
|
||||||
|
|
||||||
|
@ -1623,6 +1623,8 @@ void st_select_lex::init_query()
|
|||||||
nest_level= 0;
|
nest_level= 0;
|
||||||
link_next= 0;
|
link_next= 0;
|
||||||
lock_option= TL_READ_DEFAULT;
|
lock_option= TL_READ_DEFAULT;
|
||||||
|
m_non_agg_field_used= false;
|
||||||
|
m_agg_func_used= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void st_select_lex::init_select()
|
void st_select_lex::init_select()
|
||||||
@ -1653,7 +1655,8 @@ void st_select_lex::init_select()
|
|||||||
non_agg_fields.empty();
|
non_agg_fields.empty();
|
||||||
cond_value= having_value= Item::COND_UNDEF;
|
cond_value= having_value= Item::COND_UNDEF;
|
||||||
inner_refs_list.empty();
|
inner_refs_list.empty();
|
||||||
full_group_by_flag= 0;
|
m_non_agg_field_used= false;
|
||||||
|
m_agg_func_used= false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -715,16 +715,7 @@ public:
|
|||||||
joins on the right.
|
joins on the right.
|
||||||
*/
|
*/
|
||||||
List<String> *prev_join_using;
|
List<String> *prev_join_using;
|
||||||
/*
|
|
||||||
Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate
|
|
||||||
functions and non aggregated fields when GROUP BY list is absent.
|
|
||||||
Bits:
|
|
||||||
0 - non aggregated fields are used in this select,
|
|
||||||
defined as NON_AGG_FIELD_USED.
|
|
||||||
1 - aggregate functions are used in this select,
|
|
||||||
defined as SUM_FUNC_USED.
|
|
||||||
*/
|
|
||||||
uint8 full_group_by_flag;
|
|
||||||
void init_query();
|
void init_query();
|
||||||
void init_select();
|
void init_select();
|
||||||
st_select_lex_unit* master_unit();
|
st_select_lex_unit* master_unit();
|
||||||
@ -832,7 +823,22 @@ public:
|
|||||||
|
|
||||||
void clear_index_hints(void) { index_hints= NULL; }
|
void clear_index_hints(void) { index_hints= NULL; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
|
||||||
|
- Non-aggregated fields are used in this select.
|
||||||
|
- Aggregate functions are used in this select.
|
||||||
|
In MODE_ONLY_FULL_GROUP_BY only one of these may be true.
|
||||||
|
*/
|
||||||
|
bool non_agg_field_used() const { return m_non_agg_field_used; }
|
||||||
|
bool agg_func_used() const { return m_agg_func_used; }
|
||||||
|
|
||||||
|
void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
|
||||||
|
void set_agg_func_used(bool val) { m_agg_func_used= val; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_non_agg_field_used;
|
||||||
|
bool m_agg_func_used;
|
||||||
|
|
||||||
/* current index hint kind. used in filling up index_hints */
|
/* current index hint kind. used in filling up index_hints */
|
||||||
enum index_hint_type current_index_hint_type;
|
enum index_hint_type current_index_hint_type;
|
||||||
index_clause_map current_index_hint_clause;
|
index_clause_map current_index_hint_clause;
|
||||||
|
@ -350,21 +350,21 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
|
|
||||||
#if !defined(__WIN__) && ! defined(__NETWARE__)
|
#if !defined(__WIN__) && ! defined(__NETWARE__)
|
||||||
MY_STAT stat_info;
|
MY_STAT stat_info;
|
||||||
if (!my_stat(name,&stat_info,MYF(MY_WME)))
|
if (!my_stat(name, &stat_info, MYF(MY_WME)))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
// if we are not in slave thread, the file must be:
|
// if we are not in slave thread, the file must be:
|
||||||
if (!thd->slave_thread &&
|
if (!thd->slave_thread &&
|
||||||
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
|
!((stat_info.st_mode & S_IROTH) == S_IROTH && // readable by others
|
||||||
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
|
(stat_info.st_mode & S_IFLNK) != S_IFLNK && // and not a symlink
|
||||||
((stat_info.st_mode & S_IFREG) == S_IFREG ||
|
((stat_info.st_mode & S_IFREG) == S_IFREG || // and a regular file
|
||||||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
|
(stat_info.st_mode & S_IFIFO) == S_IFIFO))) // or FIFO
|
||||||
{
|
{
|
||||||
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
|
my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
|
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
|
||||||
is_fifo = 1;
|
is_fifo= 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
|
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
|
||||||
|
@ -930,9 +930,6 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
|
|||||||
const char *save_where;
|
const char *save_where;
|
||||||
char* db_name;
|
char* db_name;
|
||||||
char db_name_string[FN_REFLEN];
|
char db_name_string[FN_REFLEN];
|
||||||
bool save_use_only_table_context;
|
|
||||||
uint8 saved_full_group_by_flag;
|
|
||||||
nesting_map saved_allow_sum_func;
|
|
||||||
DBUG_ENTER("fix_fields_part_func");
|
DBUG_ENTER("fix_fields_part_func");
|
||||||
|
|
||||||
if (part_info->fixed)
|
if (part_info->fixed)
|
||||||
@ -999,23 +996,26 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
|
|||||||
of interesting side effects, both desirable and undesirable.
|
of interesting side effects, both desirable and undesirable.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
save_use_only_table_context= thd->lex->use_only_table_context;
|
{
|
||||||
thd->lex->use_only_table_context= TRUE;
|
const bool save_use_only_table_context= thd->lex->use_only_table_context;
|
||||||
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
|
thd->lex->use_only_table_context= TRUE;
|
||||||
saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag;
|
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
|
||||||
saved_allow_sum_func= thd->lex->allow_sum_func;
|
const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
|
||||||
thd->lex->allow_sum_func= 0;
|
const bool save_agg_func= thd->lex->current_select->agg_func_used();
|
||||||
|
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
|
||||||
|
thd->lex->allow_sum_func= 0;
|
||||||
|
|
||||||
error= func_expr->fix_fields(thd, (Item**)&func_expr);
|
error= func_expr->fix_fields(thd, (Item**)&func_expr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Restore full_group_by_flag and allow_sum_func,
|
Restore agg_field/agg_func and allow_sum_func,
|
||||||
fix_fields should not affect mysql_select later, see Bug#46923.
|
fix_fields should not affect mysql_select later, see Bug#46923.
|
||||||
*/
|
*/
|
||||||
thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag;
|
thd->lex->current_select->set_non_agg_field_used(save_agg_field);
|
||||||
thd->lex->allow_sum_func= saved_allow_sum_func;
|
thd->lex->current_select->set_agg_func_used(save_agg_func);
|
||||||
|
thd->lex->allow_sum_func= saved_allow_sum_func;
|
||||||
thd->lex->use_only_table_context= save_use_only_table_context;
|
thd->lex->use_only_table_context= save_use_only_table_context;
|
||||||
|
}
|
||||||
|
|
||||||
context->table_list= save_table_list;
|
context->table_list= save_table_list;
|
||||||
context->first_name_resolution_table= save_first_table;
|
context->first_name_resolution_table= save_first_table;
|
||||||
|
@ -426,19 +426,18 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
|||||||
int res;
|
int res;
|
||||||
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
|
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
|
||||||
/*
|
/*
|
||||||
Need to save the value, so we can turn off only the new NON_AGG_FIELD
|
Need to save the value, so we can turn off only any new non_agg_field_used
|
||||||
additions coming from the WHERE
|
additions coming from the WHERE
|
||||||
*/
|
*/
|
||||||
uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
|
const bool saved_non_agg_field_used=
|
||||||
|
thd->lex->current_select->non_agg_field_used();
|
||||||
DBUG_ENTER("setup_without_group");
|
DBUG_ENTER("setup_without_group");
|
||||||
|
|
||||||
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
|
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
|
||||||
res= setup_conds(thd, tables, leaves, conds);
|
res= setup_conds(thd, tables, leaves, conds);
|
||||||
|
|
||||||
/* it's not wrong to have non-aggregated columns in a WHERE */
|
/* it's not wrong to have non-aggregated columns in a WHERE */
|
||||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
|
thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
|
||||||
thd->lex->current_select->full_group_by_flag= saved_flag |
|
|
||||||
(thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
|
|
||||||
|
|
||||||
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
|
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
|
||||||
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||||
@ -644,7 +643,8 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
aggregate functions with implicit grouping (there is no GROUP BY).
|
aggregate functions with implicit grouping (there is no GROUP BY).
|
||||||
*/
|
*/
|
||||||
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
|
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
|
||||||
select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED))
|
select_lex->non_agg_field_used() &&
|
||||||
|
select_lex->agg_func_used())
|
||||||
{
|
{
|
||||||
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
|
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
|
||||||
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
|
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
|
||||||
|
@ -37,6 +37,11 @@
|
|||||||
* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
|
* row/row0row.c, row/row0vers.c, trx/trx0rec.c:
|
||||||
Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
|
Instrumentation for Bug#12612184 Race condition in row_upd_clust_rec()
|
||||||
|
|
||||||
|
2011-05-19 The InnoDB Team
|
||||||
|
|
||||||
|
* row/row0row.c:
|
||||||
|
Fix Bug#12429576 Assertion failure on purge of column prefix index
|
||||||
|
|
||||||
2011-04-07 The InnoDB Team
|
2011-04-07 The InnoDB Team
|
||||||
|
|
||||||
* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
|
* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
|
||||||
|
@ -148,24 +148,27 @@ row_build_index_entry(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (dfield_is_ext(dfield)) {
|
} else if (dfield_is_ext(dfield)) {
|
||||||
/* This table should be in Antelope format
|
/* This table is either in Antelope format
|
||||||
(ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT).
|
(ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT)
|
||||||
In that format, the maximum column prefix
|
or a purge record where the ordered part of
|
||||||
|
the field is not external.
|
||||||
|
In Antelope, the maximum column prefix
|
||||||
index length is 767 bytes, and the clustered
|
index length is 767 bytes, and the clustered
|
||||||
index record contains a 768-byte prefix of
|
index record contains a 768-byte prefix of
|
||||||
each off-page column. */
|
each off-page column. */
|
||||||
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||||
len -= BTR_EXTERN_FIELD_REF_SIZE;
|
len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||||
ut_a(ind_field->prefix_len <= len
|
dfield_set_len(dfield, len);
|
||||||
|| dict_index_is_clust(index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a column prefix index, take only the prefix. */
|
/* If a column prefix index, take only the prefix. */
|
||||||
ut_ad(ind_field->prefix_len);
|
if (ind_field->prefix_len) {
|
||||||
len = dtype_get_at_most_n_mbchars(
|
len = dtype_get_at_most_n_mbchars(
|
||||||
col->prtype, col->mbminlen, col->mbmaxlen,
|
col->prtype, col->mbminlen, col->mbmaxlen,
|
||||||
ind_field->prefix_len, len, dfield_get_data(dfield));
|
ind_field->prefix_len, len,
|
||||||
dfield_set_len(dfield, len);
|
dfield_get_data(dfield));
|
||||||
|
dfield_set_len(dfield, len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(dtuple_check_typed(entry));
|
ut_ad(dtuple_check_typed(entry));
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
-- Copyright (c) 2005 MySQL AB
|
|
||||||
-- Use is subject to license terms.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
CREATE DATABASE IF NOT EXISTS BANK default charset=latin1 default collate=latin1_bin;
|
|
||||||
USE BANK;
|
|
||||||
DROP TABLE IF EXISTS GL;
|
|
||||||
CREATE TABLE GL ( TIME BIGINT UNSIGNED NOT NULL,
|
|
||||||
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
|
|
||||||
BALANCE INT UNSIGNED NOT NULL,
|
|
||||||
DEPOSIT_COUNT INT UNSIGNED NOT NULL,
|
|
||||||
DEPOSIT_SUM INT UNSIGNED NOT NULL,
|
|
||||||
WITHDRAWAL_COUNT INT UNSIGNED NOT NULL,
|
|
||||||
WITHDRAWAL_SUM INT UNSIGNED NOT NULL,
|
|
||||||
PURGED INT UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY USING HASH (TIME,ACCOUNT_TYPE))
|
|
||||||
ENGINE = NDB;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS ACCOUNT;
|
|
||||||
CREATE TABLE ACCOUNT ( ACCOUNT_ID INT UNSIGNED NOT NULL,
|
|
||||||
OWNER INT UNSIGNED NOT NULL,
|
|
||||||
BALANCE INT UNSIGNED NOT NULL,
|
|
||||||
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY USING HASH (ACCOUNT_ID))
|
|
||||||
ENGINE = NDB;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS TRANSACTION;
|
|
||||||
CREATE TABLE TRANSACTION ( TRANSACTION_ID BIGINT UNSIGNED NOT NULL,
|
|
||||||
ACCOUNT INT UNSIGNED NOT NULL,
|
|
||||||
ACCOUNT_TYPE INT UNSIGNED NOT NULL,
|
|
||||||
OTHER_ACCOUNT INT UNSIGNED NOT NULL,
|
|
||||||
TRANSACTION_TYPE INT UNSIGNED NOT NULL,
|
|
||||||
TIME BIGINT UNSIGNED NOT NULL,
|
|
||||||
AMOUNT INT UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY USING HASH (TRANSACTION_ID,ACCOUNT))
|
|
||||||
ENGINE = NDB;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS SYSTEM_VALUES;
|
|
||||||
CREATE TABLE SYSTEM_VALUES ( SYSTEM_VALUES_ID INT UNSIGNED NOT NULL,
|
|
||||||
VALUE BIGINT UNSIGNED NOT NULL,
|
|
||||||
PRIMARY KEY USING HASH (SYSTEM_VALUES_ID))
|
|
||||||
ENGINE = NDB;
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS ACCOUNT_TYPE;
|
|
||||||
CREATE TABLE ACCOUNT_TYPE ( ACCOUNT_TYPE_ID INT UNSIGNED NOT NULL,
|
|
||||||
DESCRIPTION CHAR(64) NOT NULL,
|
|
||||||
PRIMARY KEY USING HASH (ACCOUNT_TYPE_ID))
|
|
||||||
ENGINE = NDB;
|
|
@ -1,25 +0,0 @@
|
|||||||
-- Copyright (c) 2005 MySQL AB
|
|
||||||
-- Use is subject to license terms.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
create database if not exists TEST_DB;
|
|
||||||
use TEST_DB;
|
|
||||||
drop table if exists T1;
|
|
||||||
create table T1 (KOL1 int unsigned not null,
|
|
||||||
KOL2 int unsigned not null,
|
|
||||||
KOL3 int unsigned not null,
|
|
||||||
KOL4 int unsigned not null,
|
|
||||||
KOL5 int unsigned not null,
|
|
||||||
primary key using hash(KOL1)) engine=ndb;
|
|
@ -1,196 +0,0 @@
|
|||||||
# Copyright (C) 2005 MySQL AB
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Library General Public
|
|
||||||
# License as published by the Free Software Foundation; version 2
|
|
||||||
# of the License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# Library General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Library General Public
|
|
||||||
# License along with this library; if not, write to the Free
|
|
||||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
||||||
# MA 02111-1307, USA
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use IO::Socket;
|
|
||||||
use DBI;
|
|
||||||
|
|
||||||
# mgm info
|
|
||||||
my $mgmhost = "localhost";
|
|
||||||
my $mgmport = 38101;
|
|
||||||
|
|
||||||
# location of ndb_x_fs
|
|
||||||
my $datadir = "c2";
|
|
||||||
my @schemafiles = <$datadir/ndb_*_fs/D[12]/DBDICT/P0.SchemaLog>;
|
|
||||||
@schemafiles or die "no schemafiles in $datadir";
|
|
||||||
|
|
||||||
my $dsn;
|
|
||||||
$dsn = "dbi:mysql:test:localhost;port=38100";
|
|
||||||
|
|
||||||
# this works better for me
|
|
||||||
my $cnf = $ENV{MYSQL_HOME} . "/var/my.cnf";
|
|
||||||
$dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$cnf";
|
|
||||||
|
|
||||||
my $dbh;
|
|
||||||
$dbh = DBI->connect($dsn, 'root', undef, { RaiseError => 0, PrintError => 0 });
|
|
||||||
$dbh or die $DBI::errstr;
|
|
||||||
|
|
||||||
# mgm commands
|
|
||||||
|
|
||||||
my $mgm = undef;
|
|
||||||
|
|
||||||
sub mgmconnect {
|
|
||||||
$mgm = IO::Socket::INET->new(
|
|
||||||
Proto => "tcp",
|
|
||||||
PeerHost => $mgmhost,
|
|
||||||
PeerPort => $mgmport);
|
|
||||||
$mgm or die "connect to mgm failed: $!";
|
|
||||||
$mgm->autoflush(1);
|
|
||||||
};
|
|
||||||
|
|
||||||
mgmconnect();
|
|
||||||
warn "connected to mgm $mgmhost $mgmport\n";
|
|
||||||
|
|
||||||
my $nodeinfo = {};
|
|
||||||
|
|
||||||
sub getnodeinfo {
|
|
||||||
$nodeinfo = {};
|
|
||||||
$mgm->print("get status\n");
|
|
||||||
$mgm->print("\n");
|
|
||||||
while (defined($_ = $mgm->getline)) {
|
|
||||||
/^node\s+status/ && last;
|
|
||||||
}
|
|
||||||
while (defined($_ = $mgm->getline)) {
|
|
||||||
/^\s*$/ && last;
|
|
||||||
/^node\.(\d+)\.(\w+):\s*(\S+)/ && ($nodeinfo->{$1}{$2} = $3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getnodeinfo();
|
|
||||||
|
|
||||||
my @dbnode = ();
|
|
||||||
for my $n (keys %$nodeinfo) {
|
|
||||||
my $p = $nodeinfo->{$n};
|
|
||||||
($p->{type} eq 'NDB') && push(@dbnode, $n);
|
|
||||||
}
|
|
||||||
@dbnode = sort { $a <=> $b } @dbnode;
|
|
||||||
@dbnode or die "mgm error, found no db nodes";
|
|
||||||
warn "db nodes: @dbnode\n";
|
|
||||||
|
|
||||||
sub restartnode {
|
|
||||||
my($n, $initialstart) = @_;
|
|
||||||
warn "restart node $n initialstart=$initialstart\n";
|
|
||||||
$mgm->print("restart node\n");
|
|
||||||
$mgm->print("node: $n\n");
|
|
||||||
$mgm->print("initialstart: $initialstart\n");
|
|
||||||
$mgm->print("\n");
|
|
||||||
while (1) {
|
|
||||||
sleep 5;
|
|
||||||
getnodeinfo();
|
|
||||||
my $status = $nodeinfo->{$n}{status};
|
|
||||||
my $sp = $nodeinfo->{$n}{startphase};
|
|
||||||
warn "node $n status: $status sp: $sp\n";
|
|
||||||
last if $status eq 'STARTED';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub restartall {
|
|
||||||
warn "restart all\n";
|
|
||||||
$mgm->print("restart all\n");
|
|
||||||
$mgm->print("\n");
|
|
||||||
while (1) {
|
|
||||||
sleep 5;
|
|
||||||
getnodeinfo();
|
|
||||||
my $ok = 1;
|
|
||||||
for my $n (@dbnode) {
|
|
||||||
my $status = $nodeinfo->{$n}{status};
|
|
||||||
my $sp = $nodeinfo->{$n}{startphase};
|
|
||||||
warn "node $n status: $status sp: $sp\n";
|
|
||||||
$ok = 0 if $status ne 'STARTED';
|
|
||||||
}
|
|
||||||
last if $ok;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# the sql stuff
|
|
||||||
|
|
||||||
my $maxtab = 300;
|
|
||||||
my @tab = ();
|
|
||||||
|
|
||||||
sub create {
|
|
||||||
my($n) = @_;
|
|
||||||
my $sql = "create table t$n (a int primary key, b varchar(20), key (b)) engine=ndb";
|
|
||||||
warn "create t$n\n";
|
|
||||||
$dbh->do($sql) or die "$sql\n$DBI::errstr";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub drop {
|
|
||||||
my($n) = @_;
|
|
||||||
my $sql = "drop table t$n";
|
|
||||||
warn "drop t$n\n";
|
|
||||||
$dbh->do($sql) or die "$sql\n$DBI::errstr";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub dropall {
|
|
||||||
for my $n (0..($maxtab-1)) {
|
|
||||||
my $sql = "drop table if exists t$n";
|
|
||||||
$dbh->do($sql) or die "$sql\n$DBI::errstr";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub createdrop {
|
|
||||||
my $n = int(rand($maxtab));
|
|
||||||
if (! $tab[$n]) {
|
|
||||||
create($n);
|
|
||||||
$tab[$n] = 1;
|
|
||||||
} else {
|
|
||||||
drop($n);
|
|
||||||
$tab[$n] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub checkschemafiles {
|
|
||||||
system("printSchemaFile -ce @schemafiles");
|
|
||||||
$? == 0 or die "schemafiles check failed";
|
|
||||||
}
|
|
||||||
|
|
||||||
sub randomrestart {
|
|
||||||
my($k) = @_;
|
|
||||||
my $s = int(rand(500));
|
|
||||||
if ($s < 2) {
|
|
||||||
my $i = $k % scalar(@dbnode);
|
|
||||||
my $n = $dbnode[$i];
|
|
||||||
my $initialstart = ($s < 1 ? 0 : 1);
|
|
||||||
restartnode($n, $initialstart);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ($s < 3) {
|
|
||||||
restartall();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# deterministic
|
|
||||||
srand(1);
|
|
||||||
|
|
||||||
warn "drop any old tables\n";
|
|
||||||
dropall();
|
|
||||||
|
|
||||||
my $loop = 1000000;
|
|
||||||
for my $k (0..($loop-1)) {
|
|
||||||
warn "$k\n";
|
|
||||||
createdrop();
|
|
||||||
checkschemafiles();
|
|
||||||
if (randomrestart($k)) {
|
|
||||||
checkschemafiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$dbh->disconnect or die $DBI::errstr;
|
|
||||||
|
|
||||||
# vim: set sw=2:
|
|
@ -1,235 +0,0 @@
|
|||||||
# Copyright (C) 2005 MySQL AB
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Library General Public
|
|
||||||
# License as published by the Free Software Foundation; version 2
|
|
||||||
# of the License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# Library General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Library General Public
|
|
||||||
# License along with this library; if not, write to the Free
|
|
||||||
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
||||||
# MA 02111-1307, USA
|
|
||||||
|
|
||||||
#
|
|
||||||
# test range scan bounds
|
|
||||||
# give option --all to test all cases
|
|
||||||
# set MYSQL_HOME to installation top
|
|
||||||
#
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use integer;
|
|
||||||
use Getopt::Long;
|
|
||||||
use DBI;
|
|
||||||
|
|
||||||
my $opt_all = 0;
|
|
||||||
my $opt_cnt = 5;
|
|
||||||
my $opt_verbose = 0;
|
|
||||||
GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt, "verbose" => \$opt_verbose)
|
|
||||||
or die "options are: --all --cnt=N --verbose";
|
|
||||||
|
|
||||||
my $mysql_home = $ENV{MYSQL_HOME};
|
|
||||||
defined($mysql_home) or die "no MYSQL_HOME";
|
|
||||||
my $dsn = "dbi:mysql:database=test;host=localhost;mysql_read_default_file=$mysql_home/var/my.cnf";
|
|
||||||
my $opts = { RaiseError => 0, PrintError => 0, AutoCommit => 1, };
|
|
||||||
|
|
||||||
my $dbh;
|
|
||||||
my $sth;
|
|
||||||
my $sql;
|
|
||||||
|
|
||||||
$dbh = DBI->connect($dsn, "root", undef, $opts) or die $DBI::errstr;
|
|
||||||
|
|
||||||
my $table = 't';
|
|
||||||
|
|
||||||
$sql = "drop table if exists $table";
|
|
||||||
$dbh->do($sql) or die $DBI::errstr;
|
|
||||||
|
|
||||||
sub cut ($$$) {
|
|
||||||
my($op, $key, $val) = @_;
|
|
||||||
$op = '==' if $op eq '=';
|
|
||||||
my(@w) = @$val;
|
|
||||||
eval "\@w = grep(\$_ $op $key, \@w)";
|
|
||||||
$@ and die $@;
|
|
||||||
return [ @w ];
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mkdummy ($) {
|
|
||||||
my ($val) = @_;
|
|
||||||
return {
|
|
||||||
'dummy' => 1,
|
|
||||||
'exp' => '9 = 9',
|
|
||||||
'res' => $val,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mkone ($$$$) {
|
|
||||||
my($col, $op, $key, $val) = @_;
|
|
||||||
my $res = cut($op, $key, $val);
|
|
||||||
return {
|
|
||||||
'exp' => "$col $op $key",
|
|
||||||
'res' => $res,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mktwo ($$$$$$) {
|
|
||||||
my($col, $op1, $key1, $op2, $key2, $val) = @_;
|
|
||||||
my $res = cut($op2, $key2, cut($op1, $key1, $val));
|
|
||||||
return {
|
|
||||||
'exp' => "$col $op1 $key1 and $col $op2 $key2",
|
|
||||||
'res' => $res,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sub mkall ($$$$) {
|
|
||||||
my($col, $key1, $key2, $val) = @_;
|
|
||||||
my @a = ();
|
|
||||||
my $p = mkdummy($val);
|
|
||||||
push(@a, $p) if $opt_all;
|
|
||||||
my @ops = qw(< <= = >= >);
|
|
||||||
for my $op (@ops) {
|
|
||||||
my $p = mkone($col, $op, $key1, $val);
|
|
||||||
push(@a, $p) if $opt_all || @{$p->{res}} != 0;
|
|
||||||
}
|
|
||||||
my @ops1 = $opt_all ? @ops : qw(= >= >);
|
|
||||||
my @ops2 = $opt_all ? @ops : qw(<= <);
|
|
||||||
for my $op1 (@ops1) {
|
|
||||||
for my $op2 (@ops2) {
|
|
||||||
my $p = mktwo($col, $op1, $key1, $op2, $key2, $val);
|
|
||||||
push(@a, $p) if $opt_all || @{$p->{res}} != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn scalar(@a)." cases\n" if $opt_verbose;
|
|
||||||
return \@a;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $casecnt = 0;
|
|
||||||
|
|
||||||
sub verify ($$$) {
|
|
||||||
my($sql, $ord, $res) = @_;
|
|
||||||
warn "$sql\n" if $opt_verbose;
|
|
||||||
$sth = $dbh->prepare($sql) or die "prepare: $sql: $DBI::errstr";
|
|
||||||
$sth->execute() or die "execute: $sql: $DBI::errstr";
|
|
||||||
#
|
|
||||||
# BUG: execute can return success on error so check again
|
|
||||||
#
|
|
||||||
$sth->err and die "execute: $sql: $DBI::errstr";
|
|
||||||
my @out = ();
|
|
||||||
for my $b (@{$res->[0]}) {
|
|
||||||
for my $c (@{$res->[1]}) {
|
|
||||||
for my $d (@{$res->[2]}) {
|
|
||||||
push(@out, [$b, $c, $d]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($ord) {
|
|
||||||
@out = sort {
|
|
||||||
$ord * ($a->[0] - $b->[0]) ||
|
|
||||||
$ord * ($a->[1] - $b->[1]) ||
|
|
||||||
$ord * ($a->[2] - $b->[2]) ||
|
|
||||||
0
|
|
||||||
} @out;
|
|
||||||
}
|
|
||||||
my $cnt = scalar @out;
|
|
||||||
my $n = 0;
|
|
||||||
while (1) {
|
|
||||||
my $row = $sth->fetchrow_arrayref;
|
|
||||||
$row || last;
|
|
||||||
@$row == 3 or die "bad row: $sql: @$row";
|
|
||||||
for my $v (@$row) {
|
|
||||||
$v =~ s/^\s+|\s+$//g;
|
|
||||||
$v =~ /^\d+$/ or die "bad value: $sql: $v";
|
|
||||||
}
|
|
||||||
if ($ord) {
|
|
||||||
my $out = $out[$n];
|
|
||||||
$row->[0] == $out->[0] &&
|
|
||||||
$row->[1] == $out->[1] &&
|
|
||||||
$row->[2] == $out->[2] or
|
|
||||||
die "$sql: row $n: got row @$row != @$out";
|
|
||||||
}
|
|
||||||
$n++;
|
|
||||||
}
|
|
||||||
$sth->err and die "fetch: $sql: $DBI::errstr";
|
|
||||||
$n == $cnt or die "verify: $sql: got row count $n != $cnt";
|
|
||||||
$casecnt++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for my $nn ("bcd", "") {
|
|
||||||
my %nn;
|
|
||||||
for my $x (qw(b c d)) {
|
|
||||||
$nn{$x} = $nn =~ /$x/ ? "not null" : "null";
|
|
||||||
}
|
|
||||||
warn "create table\n";
|
|
||||||
$sql = <<EOF;
|
|
||||||
create table $table (
|
|
||||||
a int primary key,
|
|
||||||
b int $nn{b},
|
|
||||||
c int $nn{c},
|
|
||||||
d int $nn{d},
|
|
||||||
index (b, c, d)
|
|
||||||
) engine=ndb
|
|
||||||
EOF
|
|
||||||
$dbh->do($sql) or die $DBI::errstr;
|
|
||||||
warn "insert\n";
|
|
||||||
$sql = "insert into $table values(?, ?, ?, ?)";
|
|
||||||
$sth = $dbh->prepare($sql) or die $DBI::errstr;
|
|
||||||
my @val = (0..($opt_cnt-1));
|
|
||||||
my $v0 = 0;
|
|
||||||
for my $v1 (@val) {
|
|
||||||
for my $v2 (@val) {
|
|
||||||
for my $v3 (@val) {
|
|
||||||
$sth->bind_param(1, $v0) or die $DBI::errstr;
|
|
||||||
$sth->bind_param(2, $v1) or die $DBI::errstr;
|
|
||||||
$sth->bind_param(3, $v2) or die $DBI::errstr;
|
|
||||||
$sth->bind_param(4, $v3) or die $DBI::errstr;
|
|
||||||
$sth->execute or die $DBI::errstr;
|
|
||||||
$v0++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn "generate cases\n";
|
|
||||||
my $key1 = 1;
|
|
||||||
my $key2 = 3;
|
|
||||||
my $a1 = mkall('b', $key1, $key2, \@val);
|
|
||||||
my $a2 = mkall('c', $key1, $key2, \@val);
|
|
||||||
my $a3 = mkall('d', $key1, $key2, \@val);
|
|
||||||
warn "select\n";
|
|
||||||
for my $ord (0, +1, -1) {
|
|
||||||
my $orderby =
|
|
||||||
$ord == 0 ? "" :
|
|
||||||
$ord == +1 ? " order by b, c, d" :
|
|
||||||
$ord == -1 ? " order by b desc, c desc, d desc" : die "not here";
|
|
||||||
for my $p1 (@$a1) {
|
|
||||||
my $res = [ $p1->{res}, \@val, \@val ];
|
|
||||||
$sql = "select b, c, d from $table" .
|
|
||||||
" where $p1->{exp}" .
|
|
||||||
$orderby;
|
|
||||||
verify($sql, $ord, $res);
|
|
||||||
for my $p2 (@$a2) {
|
|
||||||
my $res = [ $p1->{res}, $p2->{res}, \@val ];
|
|
||||||
$sql = "select b, c, d from $table" .
|
|
||||||
" where $p1->{exp} and $p2->{exp}" .
|
|
||||||
$orderby;
|
|
||||||
verify($sql, $ord, $res);
|
|
||||||
for my $p3 (@$a3) {
|
|
||||||
my $res = [ $p1->{res}, $p2->{res}, $p3->{res} ];
|
|
||||||
$sql = "select b, c, d from $table" .
|
|
||||||
" where $p1->{exp} and $p2->{exp} and $p3->{exp}" .
|
|
||||||
$orderby;
|
|
||||||
verify($sql, $ord, $res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn "drop table\n";
|
|
||||||
$sql = "drop table $table";
|
|
||||||
$dbh->do($sql) or die $DBI::errstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
warn "verified $casecnt cases\n";
|
|
||||||
warn "done\n";
|
|
||||||
|
|
||||||
# vim: set sw=2:
|
|
@ -798,13 +798,12 @@ else
|
|||||||
fi
|
fi
|
||||||
# echo "Analyzed: SERVER_TO_START=$SERVER_TO_START"
|
# echo "Analyzed: SERVER_TO_START=$SERVER_TO_START"
|
||||||
if [ ! -d $mysql_datadir/mysql ] ; then
|
if [ ! -d $mysql_datadir/mysql ] ; then
|
||||||
mkdir $mysql_datadir/mysql;
|
mkdir $mysql_datadir/mysql $mysql_datadir/test
|
||||||
echo "MySQL RPM installation of version $NEW_VERSION" >> $STATUS_FILE
|
echo "MySQL RPM installation of version $NEW_VERSION" >> $STATUS_FILE
|
||||||
else
|
else
|
||||||
# If the directory exists, we may assume it is an upgrade.
|
# If the directory exists, we may assume it is an upgrade.
|
||||||
echo "MySQL RPM upgrade to version $NEW_VERSION" >> $STATUS_FILE
|
echo "MySQL RPM upgrade to version $NEW_VERSION" >> $STATUS_FILE
|
||||||
fi
|
fi
|
||||||
if [ ! -d $mysql_datadir/test ] ; then mkdir $mysql_datadir/test; fi
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Make MySQL start/shutdown automatically when the machine does it.
|
# Make MySQL start/shutdown automatically when the machine does it.
|
||||||
@ -837,7 +836,12 @@ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Initiate databases if needed
|
# Initiate databases if needed
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
|
if ! grep '^MySQL RPM upgrade' $STATUS_FILE >/dev/null 2>&1 ; then
|
||||||
|
# Fix bug#45415: no "mysql_install_db" on an upgrade
|
||||||
|
# Do this as a negative to err towards more "install" runs
|
||||||
|
# rather than to miss one.
|
||||||
|
%{_bindir}/mysql_install_db --rpm --user=%{mysqld_user}
|
||||||
|
fi
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Upgrade databases if needed would go here - but it cannot be automated yet
|
# Upgrade databases if needed would go here - but it cannot be automated yet
|
||||||
@ -1161,6 +1165,12 @@ fi
|
|||||||
# merging BK trees)
|
# merging BK trees)
|
||||||
##############################################################################
|
##############################################################################
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jul 07 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
|
||||||
|
|
||||||
|
- Fix bug#45415: "rpm upgrade recreates test database"
|
||||||
|
Let the creation of the "test" database happen only during a new installation,
|
||||||
|
not in an RPM upgrade.
|
||||||
|
This affects both the "mkdir" and the call of "mysql_install_db".
|
||||||
|
|
||||||
* Thu Feb 03 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
|
* Thu Feb 03 2011 Joerg Bruehe <joerg.bruehe@oracle.com>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user