1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge tag 'mariadb-5.5.45' into 5.5-galera

This commit is contained in:
Nirbhay Choubey
2015-08-07 17:02:51 -04:00
95 changed files with 3002 additions and 378 deletions

View File

@@ -1,4 +1,4 @@
MYSQL_VERSION_MAJOR=5
MYSQL_VERSION_MINOR=5
MYSQL_VERSION_PATCH=44
MYSQL_VERSION_PATCH=45
MYSQL_VERSION_EXTRA=

View File

@@ -1066,7 +1066,7 @@ int main(int argc, char **argv)
printf("This installation of MySQL is already upgraded to %s, "
"use --force if you still need to run mysql_upgrade\n",
MYSQL_SERVER_VERSION);
die(NULL);
goto end;
}
if (opt_version_check && check_version_match())
@@ -1089,6 +1089,7 @@ int main(int argc, char **argv)
/* Create a file indicating upgrade has been performed */
create_mysql_upgrade_info_file();
end:
free_used_memory();
my_end(my_end_arg);
exit(0);

View File

@@ -66,6 +66,7 @@ ulong server_id = 0;
ulong bytes_sent = 0L, bytes_received = 0L;
ulong mysqld_net_retry_count = 10L;
ulong open_files_limit;
ulong opt_binlog_rows_event_max_size;
uint test_flags = 0;
static uint opt_protocol= 0;
static FILE *result_file;
@@ -1432,6 +1433,12 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for use by this program.",
&open_files_limit, &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
{"binlog-row-event-max-size", 0,
"The maximum size of a row-based binary log event in bytes. Rows will be "
"grouped into events smaller than this size if possible. "
"This value must be a multiple of 256.",
&opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
GET_ULONG, REQUIRED_ARG, UINT_MAX, 256, ULONG_MAX, 0, 256, 0},
{"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
(uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},

View File

@@ -1,5 +1,6 @@
/*
Copyright (c) 2005, 2012, Oracle and/or its affiliates.
Copyright (c) 2005, 2015, Oracle and/or its affiliates.
Copyright (c) 2010, 2015, MariaDB
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
@@ -244,7 +245,7 @@ void print_conclusions_csv(conclusions *con);
void generate_stats(conclusions *con, option_string *eng, stats *sptr);
uint parse_comma(const char *string, uint **range);
uint parse_delimiter(const char *script, statement **stmt, char delm);
uint parse_option(const char *origin, option_string **stmt, char delm);
int parse_option(const char *origin, option_string **stmt, char delm);
static int drop_schema(MYSQL *mysql, const char *db);
uint get_random_string(char *buf);
static statement *build_table_string(void);
@@ -1259,7 +1260,13 @@ get_options(int *argc,char ***argv)
if (num_int_cols_opt)
{
option_string *str;
parse_option(num_int_cols_opt, &str, ',');
if(parse_option(num_int_cols_opt, &str, ',') == -1)
{
fprintf(stderr, "Invalid value specified for the option "
"'number-int-cols'\n");
option_cleanup(str);
return 1;
}
num_int_cols= atoi(str->string);
if (str->option)
num_int_cols_index= atoi(str->option);
@@ -1270,7 +1277,13 @@ get_options(int *argc,char ***argv)
if (num_char_cols_opt)
{
option_string *str;
parse_option(num_char_cols_opt, &str, ',');
if(parse_option(num_char_cols_opt, &str, ',') == -1)
{
fprintf(stderr, "Invalid value specified for the option "
"'number-char-cols'\n");
option_cleanup(str);
return 1;
}
num_char_cols= atoi(str->string);
if (str->option)
num_char_cols_index= atoi(str->option);
@@ -1507,7 +1520,13 @@ get_options(int *argc,char ***argv)
printf("Parsing engines to use.\n");
if (default_engine)
parse_option(default_engine, &engine_options, ',');
{
if(parse_option(default_engine, &engine_options, ',') == -1)
{
fprintf(stderr, "Invalid value specified for the option 'engine'\n");
return 1;
}
}
if (tty_password)
opt_password= get_tty_password(NullS);
@@ -1984,7 +2003,7 @@ end:
DBUG_RETURN(0);
}
uint
int
parse_option(const char *origin, option_string **stmt, char delm)
{
char *retstr;
@@ -2009,6 +2028,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
char buffer[HUGE_STRING_LENGTH]= "";
char *buffer_ptr;
/*
Return an error if the length of the any of the comma seprated value
exceeds HUGE_STRING_LENGTH.
*/
if ((size_t)(retstr - ptr) > HUGE_STRING_LENGTH)
return -1;
count++;
strncpy(buffer, ptr, (size_t)(retstr - ptr));
/*
@@ -2048,6 +2074,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
{
char *origin_ptr;
/*
Return an error if the length of the any of the comma seprated value
exceeds HUGE_STRING_LENGTH.
*/
if (strlen(ptr) > HUGE_STRING_LENGTH)
return -1;
if ((origin_ptr= strchr(ptr, ':')))
{
char *option_ptr;
@@ -2058,13 +2091,13 @@ parse_option(const char *origin, option_string **stmt, char delm)
option_ptr= (char *)ptr + 1 + tmp->length;
/* Move past the : and the first string */
tmp->option_length= (size_t)((ptr + length) - option_ptr);
tmp->option_length= strlen(option_ptr);
tmp->option= my_strndup(option_ptr, tmp->option_length,
MYF(MY_FAE));
}
else
{
tmp->length= (size_t)((ptr + length) - ptr);
tmp->length= strlen(ptr);
tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
}

View File

@@ -228,7 +228,7 @@ rollback;
create table t0 (n int);
insert t0 select * from t1;
set autocommit=1;
insert into t0 select GET_LOCK("lock1",null);
insert into t0 select GET_LOCK("lock1",0);
set autocommit=0;
create table t2 (n int) engine=innodb;
insert into t2 values (3);

View File

@@ -4810,6 +4810,7 @@ sub extract_warning_lines ($$) {
qr|Plugin 'FEEDBACK' registration as a INFORMATION SCHEMA failed|,
qr|Failed to setup SSL|,
qr|SSL error: Failed to set ciphers to use|,
qr/Plugin 'InnoDB' will be forced to shutdown/,
);
my $matched_lines= [];

View File

@@ -1103,3 +1103,19 @@ ORDER BY field;
field
c,c
drop table t3, t2, t1;
#
# MDEV-7821 - Server crashes in Item_func_group_concat::fix_fields on 2nd
# execution of PS
#
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1),(2);
PREPARE stmt FROM "SELECT GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0) FROM t1 AS t1a, t1 AS t1b GROUP BY t1a.a";
EXECUTE stmt;
GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0)
1,1
2,2
EXECUTE stmt;
GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0)
1,1
2,2
DROP TABLE t1;

View File

@@ -361,5 +361,18 @@ set optimizer_switch=@optimizer_switch_save;
drop view v_merge, vm;
drop table t1,tv;
#
# MDEV-4017 - GET_LOCK() with negative timeouts has strange behavior
#
SELECT GET_LOCK('ul1', NULL);
GET_LOCK('ul1', NULL)
NULL
Warnings:
Warning 1411 Incorrect timeout value: 'NULL' for function get_lock
SELECT GET_LOCK('ul1', -1);
GET_LOCK('ul1', -1)
NULL
Warnings:
Warning 1411 Incorrect timeout value: '-1' for function get_lock
#
# End of 5.5 tests
#

View File

@@ -18,3 +18,5 @@ mysqld-bin.000001 # Query # # use `test`; insert t1 values (2)
mysqld-bin.000001 # Query # # COMMIT
drop table t1;
uninstall plugin innodb;
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown

View File

@@ -1,5 +1,7 @@
#
# Test of MyISAM MRG tables with corrupted children.
# Tests for corrupted MyISAM tables and MyISAMMRG tables with corrupted
# children..
#
# Run with --myisam-recover=force option.
#
# Preparation: we need to make sure that the merge parent
@@ -101,3 +103,48 @@ execute stmt;
deallocate prepare stmt;
set @@global.table_definition_cache=default;
set @@global.table_open_cache=default;
#
# 18075170 - sql node restart required to avoid deadlock after
# restore
#
# Check that auto-repair for MyISAM tables can now happen in the
# middle of transaction, without aborting it.
create table t1 (a int, key(a)) engine=myisam;
create table t2 (a int);
insert into t2 values (1);
# Create a table with a corrupted index file:
# save an old index file, insert more rows,
# overwrite the new index file with the old one.
insert into t1 (a) values (1);
flush table t1;
insert into t1 (a) values (4);
flush table t1;
# Check table is needed to mark the table as crashed.
check table t1;
Table Op Msg_type Msg_text
test.t1 check warning Size of datafile is: 14 Should be: 7
test.t1 check error Record-count is not ok; is 2 Should be: 1
test.t1 check warning Found 2 key parts. Should be: 1
test.t1 check error Corrupt
# At this point we have a corrupt t1
set autocommit = 0;
select * from t2;
a
1
# Without fix select from t1 will break the transaction. After the fix
# transaction should be active and should hold lock on table t2. Alter
# table from con2 will wait only if the transaction is not broken.
select * from t1;
a
1
4
Warnings:
Error 145 Table 't1' is marked as crashed and should be repaired
Error 1194 Table 't1' is marked as crashed and should be repaired
Error 1034 Number of rows changed from 1 to 2
ALTER TABLE t2 ADD val INT;
# With fix we should have alter table waiting for t2 lock here.
ROLLBACK;
SET autocommit = 1;
# Cleanup
drop table t1, t2;

View File

@@ -0,0 +1,156 @@
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
drop view if exists view_t1;
Warnings:
Note 1051 Unknown table 'test.view_t1'
SET sql_mode=ONLY_FULL_GROUP_BY;
CREATE TABLE t1 (
pk INT,
f0 INT, f1 INT, f2 INT, f3 INT, f4 INT,
f5 INT, f6 INT, f7 INT, f8 INT, f9 INT,
PRIMARY KEY (pk)
);
CREATE VIEW view_t1 AS SELECT * FROM t1;
CREATE PROCEDURE s1()
SELECT * FROM (
INFORMATION_SCHEMA.`INNODB_BUFFER_PAGE_LRU` AS table1
LEFT JOIN test.view_t1 AS table2
ON ( table2.`f6` = table1.FREE_PAGE_CLOCK)
)
ORDER BY table1.NUMBER_RECORDS
LIMIT 0
;
CALL s1;
POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9
CALL s1;
POOL_ID LRU_POSITION SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE COMPRESSED IO_FIX IS_OLD FREE_PAGE_CLOCK pk f0 f1 f2 f3 f4 f5 f6 f7 f8 f9
drop table t1;
drop view view_t1;
drop procedure s1;
CREATE TABLE A (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_varchar_key VARCHAR(1),
PRIMARY KEY (pk)
) ENGINE=MyISAM;
CREATE VIEW view_A AS SELECT * FROM A;
CREATE TABLE C (
pk INTEGER AUTO_INCREMENT,
col_int_nokey INTEGER,
col_int_key INTEGER,
col_date_key DATE,
col_date_nokey DATE,
col_time_key TIME,
col_time_nokey TIME,
col_datetime_key DATETIME,
col_datetime_nokey DATETIME,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk)
) ENGINE=MyISAM;
CREATE VIEW view_C AS SELECT * FROM C;
CREATE TABLE AA (
pk INTEGER AUTO_INCREMENT,
col_int_nokey INTEGER,
col_int_key INTEGER,
col_date_key DATE,
col_date_nokey DATE,
col_time_key TIME,
col_time_nokey TIME,
col_datetime_key DATETIME,
col_datetime_nokey DATETIME,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_AA AS SELECT * FROM AA;
CREATE TABLE BB (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_BB AS SELECT * FROM BB;
CREATE TABLE DD (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_date_key DATE,
col_time_key TIME,
col_datetime_key DATETIME,
col_varchar_key VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_DD AS SELECT * FROM DD;
CREATE TRIGGER k BEFORE INSERT ON `DD` FOR EACH ROW INSERT INTO `view_BB` SELECT * FROM `view_A` LIMIT 0 ;
CREATE TRIGGER r BEFORE INSERT ON `A` FOR EACH ROW INSERT INTO `view_AA` SELECT * FROM `view_C` LIMIT 0 ;
ALTER TABLE `DD` DROP PRIMARY KEY;
ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
INSERT INTO `view_A` ( `pk` ) VALUES (NULL);
INSERT INTO `DD` ( `pk` ) VALUES (NULL);
INSERT INTO `A` ( `pk` ) VALUES (NULL);
INSERT INTO `view_DD` ( `pk` ) VALUES (NULL);
drop trigger r;
drop trigger k;
drop view view_A,view_AA,view_C,view_BB,view_DD;
drop table A,C,AA,BB,DD;
CREATE TABLE A (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_A AS SELECT * FROM A;
CREATE TABLE B (
col_varchar_nokey VARCHAR(1)
) ENGINE=MyISAM;
CREATE TABLE AA (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_AA AS SELECT * FROM AA;
CREATE TABLE DD (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_DD AS SELECT * FROM DD;
CREATE TRIGGER tr1 BEFORE INSERT ON `AA` FOR EACH ROW INSERT INTO `view_A` SELECT * FROM `view_AA` LIMIT 0 ;
CREATE TRIGGER tr2 BEFORE INSERT ON `B` FOR EACH ROW INSERT INTO `D` SELECT * FROM `A` LIMIT 0 ;
INSERT INTO `view_AA` ( `i` ) VALUES (1);
INSERT INTO `AA` ( `i` ) VALUES (2);
DELETE FROM `B`;
INSERT INTO `view_DD` ( `i` ) VALUES (1);
INSERT INTO `view_AA` ( `i` ) VALUES (3);
drop trigger tr1;
drop trigger tr2;
drop view view_A, view_AA,view_DD;
drop table A,B,AA,DD;

View File

@@ -2145,6 +2145,24 @@ drop database mysqltest1;
drop database mysqltest2;
drop database mysqltest3;
drop database mysqltest4;
#
# MDEV-7810 Wrong result on execution of a query as a PS
# (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
PREPARE stmt FROM "
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
a
0
execute stmt;
a
0
drop table t1;
# End of 5.5 tests
set @subselect_mat_test_optimizer_switch_value=null;
set @@optimizer_switch='materialization=on,in_to_exists=off,semijoin=off';

View File

@@ -2185,4 +2185,22 @@ drop database mysqltest1;
drop database mysqltest2;
drop database mysqltest3;
drop database mysqltest4;
#
# MDEV-7810 Wrong result on execution of a query as a PS
# (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
a
0
PREPARE stmt FROM "
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
a
0
execute stmt;
a
0
drop table t1;
# End of 5.5 tests

View File

@@ -5429,6 +5429,21 @@ View Create View character_set_client collation_connection
v2 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select (`t1`.`b` + 1) AS `c` from `t1` latin1 latin1_swedish_ci
drop view v2;
drop table t1;
#
# MDEV-8554: Server crashes in base_list_iterator::next_fast on 1st execution of PS with a multi-table update
#
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (3),(4);
CREATE TABLE t3 (c INT) ENGINE=MyISAM;
INSERT INTO t3 VALUES (5),(6);
CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
PREPARE stmt FROM 'UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM t3 )';
UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );
EXECUTE stmt;
DROP TABLE t1, t2, t3;
DROP VIEW v3;
# -----------------------------------------------------------------
# -- End of 5.5 tests.
# -----------------------------------------------------------------

View File

@@ -258,7 +258,7 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
create table t0 (n int);
insert t0 select * from t1;
set autocommit=1;
insert into t0 select GET_LOCK("lock1",null);
insert into t0 select GET_LOCK("lock1",0);
set autocommit=0;
create table t2 (n int) engine=innodb;
insert into t2 values (3);

View File

@@ -242,7 +242,7 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
create table t0 (n int);
insert t0 select * from t1;
set autocommit=1;
insert into t0 select GET_LOCK("lock1",null);
insert into t0 select GET_LOCK("lock1",0);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
set autocommit=0;
@@ -288,7 +288,7 @@ master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; insert t0 select * from t1
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; insert into t0 select GET_LOCK("lock1",null)
master-bin.000001 # Query # # use `test`; insert into t0 select GET_LOCK("lock1",0)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb
master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`,`ti`

View File

@@ -0,0 +1,13 @@
#
# Bug #20762798 FK DDL: CRASH IN DICT_FOREIGN_REMOVE_FROM_CACHE
#
create table t1(a int, b int, key(a),key(b))engine=innodb;
create table t2(a int, b int, key(a),key(b))engine=innodb;
alter table t2 add constraint b foreign key (b) references t1(a);
alter table t1 add constraint b1 foreign key (b) references t2(a);
alter table t2 add constraint b1 foreign key (b) references t1(a);
ERROR HY000: Can't create table '#sql-temporary' (errno: 121)
alter table t2 drop foreign key b;
alter table t1 drop foreign key b1;
drop table t2;
drop table t1;

View File

@@ -0,0 +1,105 @@
CREATE TABLE t1 (
id int(11) NOT NULL PRIMARY KEY,
a int(11) NOT NULL,
b int(11) NOT NULL,
c int not null,
CONSTRAINT test FOREIGN KEY (b) REFERENCES t1 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE t2 (
id int(11) NOT NULL PRIMARY KEY,
a int(11) NOT NULL,
b int(11) NOT NULL,
c int not null,
CONSTRAINT mytest FOREIGN KEY (c) REFERENCES t1(id),
CONSTRAINT test FOREIGN KEY (b) REFERENCES t2 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ERROR HY000: Can't create table 'test.t2' (errno: 121)
show warnings;
Level Code Message
Warning 121 Create or Alter table `test`.`t2` with foreign key constraint failed. Foreign key constraint `test/test` already exists on data dictionary. Foreign key constraint names need to be unique in database. Error in foreign key definition: CONSTRAINT `test` FOREIGN KEY (`b`) REFERENCES `test`.`t2` (`id`).
Error 1005 Can't create table 'test.t2' (errno: 121)
drop table t1;
create table t1(a int) engine=innodb;
create table t2(a int, constraint a foreign key a (a) references t1(a)) engine=innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key a (a) references t1(a)) engine=innodb.
Error 1005 Can't create table 'test.t2' (errno: 150)
drop table t1;
create table t1(a int not null primary key, b int) engine=innodb;
create table t2(a int, b int, constraint a foreign key a (a) references t1(a),
constraint a foreign key a (a) references t1(b)) engine=innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key a (a) references t1(b)) engine=innodb.
Error 1005 Can't create table 'test.t2' (errno: 150)
create table t2(a int, b int, constraint a foreign key a (a) references t1(a)) engine=innodb;
alter table t2 add constraint b foreign key (b) references t2(b);
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table '`test`.`t2`' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. Error close to foreign key (b) references t2(b).
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t2, t1;
create table t1 (f1 integer primary key) engine=innodb;
alter table t1 add constraint c1 foreign key (f1) references t11(f1);
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Referenced table `test`.`t11` not found in the data dictionary close to foreign key (f1) references t11(f1).
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t1;
create temporary table t1(a int not null primary key, b int, key(b)) engine=innodb;
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table `mysqld.1`.`t2` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary close to foreign key(a) references t1(a)) engine=innodb.
Error 1005 Can't create table 'test.t2' (errno: 150)
alter table t1 add foreign key(b) references t1(a);
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `mysqld.1`.`t1` with foreign key constraint failed. Referenced table `mysqld.1`.`t1` not found in the data dictionary close to foreign key(b) references t1(a).
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t1;
create table t1(a int not null primary key, b int, key(b)) engine=innodb;
alter table t1 add foreign key(a,b) references t1(a);
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Foreign key constraint parse error in foreign key(a,b) references t1(a) close to ). Too few referenced columns, you have 1 when you should have 2.
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t1;
create table t1(a int not null primary key, b int, key(b)) engine=innodb;
alter table t1 add foreign key(a) references t1(a,b);
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `test`.`t1` with foreign key constraint failed. Foreign key constraint parse error in foreign key(a) references t1(a,b) close to ). Too few referenced columns, you have 2 when you should have 1.
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t1;
create table t1 (f1 integer not null primary key) engine=innodb;
alter table t1 add constraint c1 foreign key (f1) references t1(f1) on update set null;
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `test`.`t1` with foreign key constraint failed. You have defined a SET NULL condition but column f1 is defined as NOT NULL in foreign key (f1) references t1(f1) on update set null close to on update set null.
Error 1005 Can't create table '#sql-temporary' (errno: 150)
create table t2(a int not null, foreign key(a) references t1(f1) on delete set null) engine=innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table `test`.`t2` with foreign key constraint failed. You have defined a SET NULL condition but column a is defined as NOT NULL in foreign key(a) references t1(f1) on delete set null) engine=innodb close to on delete set null) engine=innodb.
Error 1005 Can't create table 'test.t2' (errno: 150)
drop table t1;
create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb;
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb;
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table `test`.`t2` with foreign key constraint failed. Field type or character set for column a does not mach referenced column f1 close to foreign key(a) references t1(f1)) engine=innodb
Error 1005 Can't create table 'test.t2' (errno: 150)
drop table t1;

View File

@@ -50,6 +50,8 @@ CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
ERROR HY000: Can't create table 'test.t2' (errno: 150)
show warnings;
Level Code Message
Warning 150 Create table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary close to FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE
) ENGINE=InnoDB.
Error 1005 Can't create table 'test.t2' (errno: 150)
CREATE TABLE t2 (
id int(11) NOT NULL AUTO_INCREMENT,
@@ -62,6 +64,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE
ERROR HY000: Can't create table '#sql-temporary' (errno: 150)
show warnings;
Level Code Message
Warning 150 Alter table `test`.`t2` with foreign key constraint failed. Referenced table `test`.`t3` not found in the data dictionary close to FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE CASCADE.
Error 1005 Can't create table '#sql-temporary' (errno: 150)
drop table t2;
drop table t1;

View File

@@ -0,0 +1,22 @@
install plugin innodb soname 'ha_innodb';
create table t1(a int not null primary key) engine=innodb;
begin;
insert into t1 values(1);
flush tables;
uninstall plugin innodb;
select sleep(1);
sleep(1)
0
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown
drop table t1;
install plugin innodb soname 'ha_innodb';
create table t2(a int not null primary key) engine=innodb;
insert into t2 values(1);
drop table t2;
uninstall plugin innodb;
select sleep(1);
sleep(1)
0
Warnings:
Warning 1620 Plugin is busy and will be uninstalled on shutdown

View File

@@ -0,0 +1,21 @@
--source include/have_innodb.inc
--echo #
--echo # Bug #20762798 FK DDL: CRASH IN DICT_FOREIGN_REMOVE_FROM_CACHE
--echo #
create table t1(a int, b int, key(a),key(b))engine=innodb;
create table t2(a int, b int, key(a),key(b))engine=innodb;
alter table t2 add constraint b foreign key (b) references t1(a);
alter table t1 add constraint b1 foreign key (b) references t2(a);
--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error ER_CANT_CREATE_TABLE
alter table t2 add constraint b1 foreign key (b) references t1(a);
alter table t2 drop foreign key b;
alter table t1 drop foreign key b1;
drop table t2;
drop table t1;

View File

@@ -0,0 +1,130 @@
--source include/have_innodb.inc
#
# MDEV-8524: Improve error messaging when there is duplicate key or foreign key names
#
CREATE TABLE t1 (
id int(11) NOT NULL PRIMARY KEY,
a int(11) NOT NULL,
b int(11) NOT NULL,
c int not null,
CONSTRAINT test FOREIGN KEY (b) REFERENCES t1 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
#
# Below create table fails because constraint name test
# is reserved for above table.
#
--error 1005
CREATE TABLE t2 (
id int(11) NOT NULL PRIMARY KEY,
a int(11) NOT NULL,
b int(11) NOT NULL,
c int not null,
CONSTRAINT mytest FOREIGN KEY (c) REFERENCES t1(id),
CONSTRAINT test FOREIGN KEY (b) REFERENCES t2 (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
show warnings;
drop table t1;
#
# MDEV-6697: Improve foreign keys warnings/errors
#
#
# No index for referenced columns
#
create table t1(a int) engine=innodb;
--error 1005
create table t2(a int, constraint a foreign key a (a) references t1(a)) engine=innodb;
show warnings;
drop table t1;
create table t1(a int not null primary key, b int) engine=innodb;
--error 1005
create table t2(a int, b int, constraint a foreign key a (a) references t1(a),
constraint a foreign key a (a) references t1(b)) engine=innodb;
show warnings;
create table t2(a int, b int, constraint a foreign key a (a) references t1(a)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t2 add constraint b foreign key (b) references t2(b);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t2, t1;
#
# Referenced table does not exists
#
create table t1 (f1 integer primary key) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t1 add constraint c1 foreign key (f1) references t11(f1);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;
#
# Foreign key on temporal tables
#
create temporary table t1(a int not null primary key, b int, key(b)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t1 add foreign key(b) references t1(a);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;
#
# Column numbers do not match
#
create table t1(a int not null primary key, b int, key(b)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t1 add foreign key(a,b) references t1(a);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;
create table t1(a int not null primary key, b int, key(b)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t1 add foreign key(a) references t1(a,b);
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;
#
# ON UPDATE/DELETE SET NULL on NOT NULL column
#
create table t1 (f1 integer not null primary key) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
alter table t1 add constraint c1 foreign key (f1) references t1(f1) on update set null;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
create table t2(a int not null, foreign key(a) references t1(f1) on delete set null) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;
#
# Incorrect types
#
create table t1 (id int not null primary key, f1 int, f2 int, key(f1)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1005
create table t2(a char(20), key(a), foreign key(a) references t1(f1)) engine=innodb;
--replace_regex /'[^']*test.#sql-[0-9a-f_]*'/'#sql-temporary'/
show warnings;
drop table t1;

View File

@@ -0,0 +1,3 @@
--ignore-builtin-innodb
--loose-innodb

View File

@@ -0,0 +1,58 @@
--source include/not_embedded.inc
--source include/not_windows.inc
if (!$HA_INNODB_SO) {
--skip Need InnoDB plugin
}
#
# MDEV-8474: InnoDB sets per-connection data unsafely
# Below test caused hang
#
install plugin innodb soname 'ha_innodb';
create table t1(a int not null primary key) engine=innodb;
connect (con1, localhost, root);
connection con1;
begin;
insert into t1 values(1);
connection default;
flush tables;
send uninstall plugin innodb;
connection con1;
select sleep(1);
disconnect con1;
connection default;
reap;
--source include/restart_mysqld.inc
drop table t1;
#
# Another test that caused hang.
#
connect (con1, localhost, root);
connection con1;
install plugin innodb soname 'ha_innodb';
create table t2(a int not null primary key) engine=innodb;
insert into t2 values(1);
drop table t2;
connection default;
send uninstall plugin innodb;
connection con1;
select sleep(1);
disconnect con1;
connection default;
reap;
--source include/restart_mysqld.inc

View File

@@ -0,0 +1,33 @@
#
# 18075170 - sql node restart required to avoid deadlock after
# restore
#
CREATE TABLE t1 (id INT) ENGINE=NDBCluster;
CREATE TABLE t2 (id INT) ENGINE=NDBCluster;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
DROP TABLE t1;
DROP TABLE t2;
SET autocommit = 0;
SELECT * FROM t1;
id
1
SELECT * FROM t2;
id
1
ROLLBACK;
SET autocommit = 1;
drop table t1;
drop table t2;
SET autocommit = 0;
SELECT * FROM t1;
id
1
SELECT * FROM t2;
id
1
ALTER TABLE t1 ADD val INT;
ROLLBACK;
SET autocommit = 1;
drop table t1;
drop table t2;

View File

@@ -0,0 +1,70 @@
-- source include/have_ndb.inc
-- source include/count_sessions.inc
--echo #
--echo # 18075170 - sql node restart required to avoid deadlock after
--echo # restore
--echo #
# Test Auto Discover option within a transaction
# and make sure the transaction is not broken.
CREATE TABLE t1 (id INT) ENGINE=NDBCluster;
CREATE TABLE t2 (id INT) ENGINE=NDBCluster;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
-- source include/ndb_backup.inc
DROP TABLE t1;
DROP TABLE t2;
-- source include/ndb_restore_master.inc
SET autocommit = 0;
SELECT * FROM t1;
# Without fix below select was resulting in DEADLOCK error. With fix select
# should succeed.
SELECT * FROM t2;
ROLLBACK;
SET autocommit = 1;
drop table t1;
drop table t2;
#
# Checking lock preservation in transaction
#
# Using existing backup to create the scenario. Tables are deleted as part of
# above test cleanup. Thus restoring the backup will bring the system to
# required state.
-- source include/ndb_restore_master.inc
SET autocommit = 0;
SELECT * FROM t1;
SELECT * FROM t2;
connect(con2, localhost, root);
--SEND ALTER TABLE t1 ADD val INT
connection default;
# Alter from con2 will be in waiting state as there is a lock on t1 from
# default connection due to active transaction. We check for this condition
# then releasing the lock by rollbacking active transaction.
let $wait_condition=
SELECT count(*) = 1 FROM information_schema.processlist WHERE state
LIKE "Waiting%" AND info = "ALTER TABLE t1 ADD val INT";
--source include/wait_condition.inc
ROLLBACK;
SET autocommit = 1;
connection con2;
--REAP
disconnect con2;
connection default;
drop table t1;
drop table t2;
# Wait till all disconnects are completed
-- source include/wait_until_count_sessions.inc

View File

@@ -14,4 +14,109 @@ select * from mysqltest.t3;
n
45
drop database mysqltest;
use test;
#
# Test bug where ALTER TABLE MODIFY didn't replicate properly
#
create table t1 (a int unsigned primary key, b int);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(10) unsigned NOT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 (a) values (1),((1<<32)-1);
select * from t1;
a b
1 NULL
4294967295 NULL
alter table t1 modify a bigint;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
a b
1 NULL
4294967295 NULL
alter table t1 modify a int unsigned;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(10) unsigned NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
a b
1 NULL
4294967295 NULL
alter table t1 modify a bigint unsigned;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
a b
1 NULL
4294967295 NULL
use test;
select * from t1;
a b
1 NULL
4294967295 NULL
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
create table t2 (a int unsigned auto_increment primary key, b int);
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` int(10) unsigned NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t2 modify a bigint;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` bigint(20) NOT NULL DEFAULT '0',
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
alter table t2 modify a bigint auto_increment;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
#
# MDEV-8432: Slave cannot replicate signed integer-type values
# with high bit set to 1
# Test replication when we have int on master and bigint on slave
#
create table t1 (a int unsigned primary key, b int);
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
alter table t1 modify a bigint unsigned;
insert into t1 (a) values (1),((1<<32)-1);
select * from t1;
a b
1 NULL
4294967295 NULL
SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
drop table t1;
include/rpl_end.inc

View File

@@ -15,4 +15,57 @@ drop database mysqltest;
sync_slave_with_master;
# End of 4.1 tests
connection master;
use test;
--echo #
--echo # Test bug where ALTER TABLE MODIFY didn't replicate properly
--echo #
create table t1 (a int unsigned primary key, b int);
show create table t1;
insert into t1 (a) values (1),((1<<32)-1);
select * from t1;
alter table t1 modify a bigint;
show create table t1;
select * from t1;
alter table t1 modify a int unsigned;
show create table t1;
select * from t1;
alter table t1 modify a bigint unsigned;
show create table t1;
select * from t1;
sync_slave_with_master;
use test;
select * from t1;
show create table t1;
connection master;
#
create table t2 (a int unsigned auto_increment primary key, b int);
show create table t2;
alter table t2 modify a bigint;
show create table t2;
alter table t2 modify a bigint auto_increment;
show create table t2;
drop table t1,t2;
--echo #
--echo # MDEV-8432: Slave cannot replicate signed integer-type values
--echo # with high bit set to 1
--echo # Test replication when we have int on master and bigint on slave
--echo #
create table t1 (a int unsigned primary key, b int);
sync_slave_with_master;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='ALL_NON_LOSSY';
alter table t1 modify a bigint unsigned;
connection master;
insert into t1 (a) values (1),((1<<32)-1);
sync_slave_with_master;
select * from t1;
SET GLOBAL SLAVE_TYPE_CONVERSIONS='';
connection master;
drop table t1;
--source include/rpl_end.inc

View File

@@ -821,3 +821,14 @@ FROM ( SELECT * FROM t2 ) AS sq2, t3
ORDER BY field;
drop table t3, t2, t1;
--echo #
--echo # MDEV-7821 - Server crashes in Item_func_group_concat::fix_fields on 2nd
--echo # execution of PS
--echo #
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES(1),(2);
PREPARE stmt FROM "SELECT GROUP_CONCAT(t1a.a ORDER BY 1, t1a.a=0) FROM t1 AS t1a, t1 AS t1b GROUP BY t1a.a";
EXECUTE stmt;
EXECUTE stmt;
DROP TABLE t1;

View File

@@ -391,6 +391,11 @@ set optimizer_switch=@optimizer_switch_save;
drop view v_merge, vm;
drop table t1,tv;
--echo #
--echo # MDEV-4017 - GET_LOCK() with negative timeouts has strange behavior
--echo #
SELECT GET_LOCK('ul1', NULL);
SELECT GET_LOCK('ul1', -1);
--echo #
--echo # End of 5.5 tests

View File

@@ -17,3 +17,6 @@ commit;
--source include/show_binlog_events.inc
drop table t1;
uninstall plugin innodb;
--source include/restart_mysqld.inc

View File

@@ -1,5 +1,9 @@
--source include/count_sessions.inc
--echo #
--echo # Tests for corrupted MyISAM tables and MyISAMMRG tables with corrupted
--echo # children..
--echo #
--echo # Test of MyISAM MRG tables with corrupted children.
--echo # Run with --myisam-recover=force option.
--echo #
--echo # Preparation: we need to make sure that the merge parent
@@ -111,3 +115,66 @@ set @@global.table_open_cache=default;
disconnect con1;
connection default;
--enable_ps_protocol
--echo #
--echo # 18075170 - sql node restart required to avoid deadlock after
--echo # restore
--echo #
--echo # Check that auto-repair for MyISAM tables can now happen in the
--echo # middle of transaction, without aborting it.
--enable_prepare_warnings
connection default;
create table t1 (a int, key(a)) engine=myisam;
create table t2 (a int);
insert into t2 values (1);
--echo # Create a table with a corrupted index file:
--echo # save an old index file, insert more rows,
--echo # overwrite the new index file with the old one.
insert into t1 (a) values (1);
flush table t1;
--copy_file $MYSQLD_DATADIR/test/t1.MYI $MYSQLD_DATADIR/test/t1_copy.MYI
insert into t1 (a) values (4);
flush table t1;
--remove_file $MYSQLD_DATADIR/test/t1.MYI
--copy_file $MYSQLD_DATADIR/test/t1_copy.MYI $MYSQLD_DATADIR/test/t1.MYI
--remove_file $MYSQLD_DATADIR/test/t1_copy.MYI
--echo # Check table is needed to mark the table as crashed.
check table t1;
--echo # At this point we have a corrupt t1
set autocommit = 0;
select * from t2;
--echo # Without fix select from t1 will break the transaction. After the fix
--echo # transaction should be active and should hold lock on table t2. Alter
--echo # table from con2 will wait only if the transaction is not broken.
--replace_regex /'.*[\/\\]/'/
select * from t1;
connect(con2, localhost, root);
--SEND ALTER TABLE t2 ADD val INT
connection default;
--echo # With fix we should have alter table waiting for t2 lock here.
let $wait_condition=
SELECT count(*) = 1 FROM information_schema.processlist WHERE state
LIKE "Waiting%" AND info = "ALTER TABLE t2 ADD val INT";
--source include/wait_condition.inc
ROLLBACK;
SET autocommit = 1;
connection con2;
--REAP
connection default;
disconnect con2;
--echo # Cleanup
drop table t1, t2;
# Wait till all disconnects are completed
-- source include/wait_until_count_sessions.inc

View File

@@ -14,7 +14,6 @@ file_exists $MYSQLD_DATADIR/mysql_upgrade_info;
--echo Run it again - should say already completed
--replace_result $MYSQL_SERVER_VERSION VERSION
--error 1
--exec $MYSQL_UPGRADE 2>&1
# It should have created a file in the MySQL Servers datadir

187
mysql-test/t/sp-group.test Normal file
View File

@@ -0,0 +1,187 @@
--source include/have_innodb.inc
drop table if exists t1;
drop view if exists view_t1;
#
# Test case for MDEV 7601, MDEV-7594 and MDEV-7555
# Server crashes in functions related to stored procedures
# Server crashes in different ways while executing concurrent
# flow involving views and non-empty sql_mode with ONLY_FULL_GROUP_BY
#
SET sql_mode=ONLY_FULL_GROUP_BY;
CREATE TABLE t1 (
pk INT,
f0 INT, f1 INT, f2 INT, f3 INT, f4 INT,
f5 INT, f6 INT, f7 INT, f8 INT, f9 INT,
PRIMARY KEY (pk)
);
CREATE VIEW view_t1 AS SELECT * FROM t1;
CREATE PROCEDURE s1()
SELECT * FROM (
INFORMATION_SCHEMA.`INNODB_BUFFER_PAGE_LRU` AS table1
LEFT JOIN test.view_t1 AS table2
ON ( table2.`f6` = table1.FREE_PAGE_CLOCK)
)
ORDER BY table1.NUMBER_RECORDS
LIMIT 0
;
CALL s1;
CALL s1;
drop table t1;
drop view view_t1;
drop procedure s1;
#
# MDEV-7590
# Server crashes in st_select_lex_unit::cleanup on executing a trigger
#
CREATE TABLE A (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_varchar_key VARCHAR(1),
PRIMARY KEY (pk)
) ENGINE=MyISAM;
CREATE VIEW view_A AS SELECT * FROM A;
CREATE TABLE C (
pk INTEGER AUTO_INCREMENT,
col_int_nokey INTEGER,
col_int_key INTEGER,
col_date_key DATE,
col_date_nokey DATE,
col_time_key TIME,
col_time_nokey TIME,
col_datetime_key DATETIME,
col_datetime_nokey DATETIME,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk)
) ENGINE=MyISAM;
CREATE VIEW view_C AS SELECT * FROM C;
CREATE TABLE AA (
pk INTEGER AUTO_INCREMENT,
col_int_nokey INTEGER,
col_int_key INTEGER,
col_date_key DATE,
col_date_nokey DATE,
col_time_key TIME,
col_time_nokey TIME,
col_datetime_key DATETIME,
col_datetime_nokey DATETIME,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_AA AS SELECT * FROM AA;
CREATE TABLE BB (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_varchar_key VARCHAR(1),
col_varchar_nokey VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_BB AS SELECT * FROM BB;
CREATE TABLE DD (
pk INTEGER AUTO_INCREMENT,
col_int_key INTEGER,
col_date_key DATE,
col_time_key TIME,
col_datetime_key DATETIME,
col_varchar_key VARCHAR(1),
PRIMARY KEY (pk),
KEY (col_varchar_key, col_int_key)
) ENGINE=MyISAM;
CREATE VIEW view_DD AS SELECT * FROM DD;
CREATE TRIGGER k BEFORE INSERT ON `DD` FOR EACH ROW INSERT INTO `view_BB` SELECT * FROM `view_A` LIMIT 0 ;
CREATE TRIGGER r BEFORE INSERT ON `A` FOR EACH ROW INSERT INTO `view_AA` SELECT * FROM `view_C` LIMIT 0 ;
--error ER_WRONG_AUTO_KEY
ALTER TABLE `DD` DROP PRIMARY KEY;
INSERT INTO `view_A` ( `pk` ) VALUES (NULL);
--error 0,ER_WRONG_VALUE_COUNT_ON_ROW
INSERT INTO `DD` ( `pk` ) VALUES (NULL);
INSERT INTO `A` ( `pk` ) VALUES (NULL);
--error 0,ER_WRONG_VALUE_COUNT_ON_ROW
INSERT INTO `view_DD` ( `pk` ) VALUES (NULL);
drop trigger r;
drop trigger k;
drop view view_A,view_AA,view_C,view_BB,view_DD;
drop table A,C,AA,BB,DD;
#
# MDEV-7581
# Server crashes in st_select_lex_unit::cleanup after a sequence of statements
#
CREATE TABLE A (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_A AS SELECT * FROM A;
CREATE TABLE B (
col_varchar_nokey VARCHAR(1)
) ENGINE=MyISAM;
CREATE TABLE AA (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_AA AS SELECT * FROM AA;
CREATE TABLE DD (
i INT,
i1 INT,
i2 INT,
d1 DATE,
d2 DATE,
col_time_nokey1 TIME,
col_time_nokey2 TIME,
col_datetime_nokey1 DATETIME,
col_datetime_nokey2 DATETIME,
col_varchar_nokey1 VARCHAR(1),
col_varchar_nokey2 VARCHAR(1)
) ENGINE=MyISAM;
CREATE VIEW view_DD AS SELECT * FROM DD;
CREATE TRIGGER tr1 BEFORE INSERT ON `AA` FOR EACH ROW INSERT INTO `view_A` SELECT * FROM `view_AA` LIMIT 0 ;
CREATE TRIGGER tr2 BEFORE INSERT ON `B` FOR EACH ROW INSERT INTO `D` SELECT * FROM `A` LIMIT 0 ;
INSERT INTO `view_AA` ( `i` ) VALUES (1);
INSERT INTO `AA` ( `i` ) VALUES (2);
DELETE FROM `B`;
INSERT INTO `view_DD` ( `i` ) VALUES (1);
INSERT INTO `view_AA` ( `i` ) VALUES (3);
drop trigger tr1;
drop trigger tr2;
drop view view_A, view_AA,view_DD;
drop table A,B,AA,DD;

View File

@@ -1841,5 +1841,20 @@ drop database mysqltest2;
drop database mysqltest3;
drop database mysqltest4;
--echo # End of 5.5 tests
--echo #
--echo # MDEV-7810 Wrong result on execution of a query as a PS
--echo # (both 1st and further executions)
CREATE TABLE t1 (a INT NOT NULL) ENGINE=MyISAM;
INSERT INTO t1 VALUES (0),(8);
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2));
PREPARE stmt FROM "
SELECT a FROM (SELECT DISTINCT * FROM t1) AS sq WHERE a IN (SELECT MIN(t2.a) FROM (t1 AS t2))
";
execute stmt;
execute stmt;
drop table t1;
--echo # End of 5.5 tests

View File

@@ -5380,6 +5380,27 @@ show create view v2;
drop view v2;
drop table t1;
--echo #
--echo # MDEV-8554: Server crashes in base_list_iterator::next_fast on 1st execution of PS with a multi-table update
--echo #
CREATE TABLE t1 (a INT) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1),(2); # Not necessary, the table can be empty
CREATE TABLE t2 (b INT) ENGINE=MyISAM;
INSERT INTO t2 VALUES (3),(4); # Not necessary, the table can be empty
CREATE TABLE t3 (c INT) ENGINE=MyISAM;
INSERT INTO t3 VALUES (5),(6); # Not necessary, the table can be empty
CREATE OR REPLACE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
PREPARE stmt FROM 'UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM t3 )';
UPDATE t1, t2 SET a = 1 WHERE a IN ( SELECT 0 FROM v3 );
EXECUTE stmt;
DROP TABLE t1, t2, t3;
DROP VIEW v3;
--echo # -----------------------------------------------------------------
--echo # -- End of 5.5 tests.
--echo # -----------------------------------------------------------------

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2000, 2015, 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
@@ -91,6 +91,7 @@ static int ptr_compare(size_t *compare_length, uchar **a, uchar **b)
reg3 int length= *compare_length;
reg1 uchar *first,*last;
DBUG_ASSERT(length > 0);
first= *a; last= *b;
while (--length)
{

View File

@@ -1,3 +1,11 @@
/* Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
See file COPYRIGHT for details.
This file was modified by Oracle on 2015-05-18 for 32-bit compatibility.
Modifications copyright (c) 2015, Oracle and/or its affiliates. All rights
reserved. */
#include <my_global.h>
#include <m_string.h>
#include <m_ctype.h>
@@ -133,12 +141,26 @@ CHARSET_INFO *charset;
} else
len = strlen((char *)pattern);
/*
Find the maximum len we can safely process
without a rollover and a mis-malloc.
p->ssize is a sopno is a long (32+ bit signed);
size_t is 16+ bit unsigned.
*/
{
size_t new_ssize = len / (size_t)2 * (size_t)3 + (size_t)1; /* ugh */
if ((new_ssize < len) || /* size_t rolled over */
((SIZE_T_MAX / sizeof(sop)) < new_ssize) || /* malloc arg */
(new_ssize > LONG_MAX)) /* won't fit in ssize */
return(REG_ESPACE); /* MY_REG_ESPACE or MY_REG_INVARG */
p->ssize = new_ssize;
}
/* do the mallocs early so failure handling is easy */
g = (struct re_guts *)malloc(sizeof(struct re_guts) +
(NC-1)*sizeof(cat_t));
if (g == NULL)
return(REG_ESPACE);
p->ssize = (long) (len/(size_t)2*(size_t)3 + (size_t)1); /* ugh */
p->strip = (sop *)malloc(p->ssize * sizeof(sop));
p->slen = 0;
if (p->strip == NULL) {

View File

@@ -7612,7 +7612,8 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
}
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) &&
from != value.ptr())
{ // Must make a copy
value.copy(from, length, cs);
from= value.ptr();

View File

@@ -1146,18 +1146,24 @@ Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
because Item_singlerow_subselect later calls Item_cache-specific methods,
e.g. row[i]->store() and row[i]->cache_value().
Let's wrap Item_func_conv_charset to a new Item_cache,
Let's wrap Item_func_conv_charset in a new Item_cache,
so the Item_cache-specific methods can still be used for
Item_singlerow_subselect::row[i] safely.
As a bonus we cache the converted value, instead of converting every time
TODO: we should eventually check all other use cases of change_item_tree().
Perhaps some more potentially dangerous substitution examples exist.
*/
Item *Item_cache::safe_charset_converter(CHARSET_INFO *tocs)
{
Item_func_conv_charset *conv= new Item_func_conv_charset(example, tocs, 1);
if (!example)
return Item::safe_charset_converter(tocs);
Item *conv= example->safe_charset_converter(tocs);
if (conv == example)
return this;
Item_cache *cache;
if (!conv || !conv->safe || !(cache= new Item_cache_str(conv)))
if (!conv || !(cache= new Item_cache_str(conv)))
return NULL; // Safe conversion is not possible, or OEM
cache->setup(conv);
cache->fixed= false; // Make Item::fix_fields() happy
@@ -4409,18 +4415,23 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
Item_ident *resolved_item,
Item_ident *mark_item)
{
DBUG_ENTER("mark_as_dependent");
/* store pointer on SELECT_LEX from which item is dependent */
if (mark_item && mark_item->can_be_depended)
{
DBUG_PRINT("info", ("mark_item: %p lex: %p", mark_item, last));
mark_item->depended_from= last;
}
if (current->mark_as_dependent(thd, last,
/** resolved_item psergey-thu **/ mark_item))
DBUG_RETURN(TRUE);
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
const char *db_name= (resolved_item->db_name ?
resolved_item->db_name : "");
const char *table_name= (resolved_item->table_name ?
resolved_item->table_name : "");
/* store pointer on SELECT_LEX from which item is dependent */
if (mark_item && mark_item->can_be_depended)
mark_item->depended_from= last;
if (current->mark_as_dependent(thd, last, /** resolved_item psergey-thu
**/mark_item))
return TRUE;
if (thd->lex->describe & DESCRIBE_EXTENDED)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED),
db_name, (db_name[0] ? "." : ""),
@@ -4428,7 +4439,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
resolved_item->field_name,
current->select_number, last->select_number);
}
return FALSE;
DBUG_RETURN(FALSE);
}
@@ -4877,7 +4888,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
non aggregated fields of the outer select.
*/
marker= select->cur_pos_in_select_list;
select->non_agg_fields.push_back(this);
select->join->non_agg_fields.push_back(this);
}
if (*from_field != view_ref_found)
{
@@ -5293,9 +5304,10 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
fixed= 1;
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
!outer_fixed && !thd->lex->in_sum_func &&
thd->lex->current_select->cur_pos_in_select_list != UNDEF_POS)
thd->lex->current_select->cur_pos_in_select_list != UNDEF_POS &&
thd->lex->current_select->join)
{
thd->lex->current_select->non_agg_fields.push_back(this);
thd->lex->current_select->join->non_agg_fields.push_back(this);
marker= thd->lex->current_select->cur_pos_in_select_list;
}
mark_non_agg_field:
@@ -6742,7 +6754,7 @@ Item_ref::Item_ref(Name_resolution_context *context_arg,
/*
This constructor used to create some internals references over fixed items
*/
if (ref && *ref && (*ref)->fixed)
if ((set_properties_only= (ref && *ref && (*ref)->fixed)))
set_properties();
}
@@ -6786,7 +6798,7 @@ Item_ref::Item_ref(TABLE_LIST *view_arg, Item **item,
/*
This constructor is used to create some internal references over fixed items
*/
if (ref && *ref && (*ref)->fixed)
if ((set_properties_only= (ref && *ref && (*ref)->fixed)))
set_properties();
}
@@ -6861,7 +6873,11 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
DBUG_ASSERT(fixed == 0);
SELECT_LEX *current_sel= thd->lex->current_select;
if (!ref || ref == not_found_item)
if (set_properties_only)
{
/* do nothing */
}
else if (!ref || ref == not_found_item)
{
DBUG_ASSERT(reference_trough_name != 0);
if (!(ref= resolve_ref_in_select_and_group(thd, this,
@@ -6879,7 +6895,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
{
/* The current reference cannot be resolved in this query. */
my_error(ER_BAD_FIELD_ERROR,MYF(0),
this->full_name(), current_thd->where);
this->full_name(), thd->where);
goto error;
}
@@ -7014,7 +7030,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
goto error;
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex,
thd->lex->current_select, fld, fld);
current_sel, fld, fld);
/*
A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of
@@ -7031,7 +7047,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
{
/* The item was not a table field and not a reference */
my_error(ER_BAD_FIELD_ERROR, MYF(0),
this->full_name(), current_thd->where);
this->full_name(), thd->where);
goto error;
}
/* Should be checked in resolve_ref_in_select_and_group(). */

View File

@@ -631,7 +631,7 @@ public:
*/
uint name_length; /* Length of name */
uint decimals;
int8 marker;
int marker;
bool maybe_null; /* If item may be null */
bool in_rollup; /* If used in GROUP BY list
of a query with ROLLUP */
@@ -2946,6 +2946,7 @@ class Item_ref :public Item_ident
{
protected:
void set_properties();
bool set_properties_only; // the item doesn't need full fix_fields
public:
enum Ref_Type { REF, DIRECT_REF, VIEW_REF, OUTER_REF, AGGREGATE_REF };
Field *result_field; /* Save result here */
@@ -2955,7 +2956,7 @@ public:
const char *db_arg, const char *table_name_arg,
const char *field_name_arg)
:Item_ident(context_arg, db_arg, table_name_arg, field_name_arg),
result_field(0), ref(0), reference_trough_name(1) {}
set_properties_only(0), result_field(0), ref(0), reference_trough_name(1) {}
/*
This constructor is used in two scenarios:
A) *item = NULL
@@ -2978,7 +2979,7 @@ public:
/* Constructor need to process subselect with temporary tables (see Item) */
Item_ref(THD *thd, Item_ref *item)
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref) {}
:Item_ident(thd, item), set_properties_only(0), result_field(item->result_field), ref(item->ref) {}
enum Type type() const { return REF_ITEM; }
enum Type real_type() const { return ref ? (*ref)->type() :
REF_ITEM; }

View File

@@ -4196,7 +4196,25 @@ longlong Item_func_get_lock::val_int()
it's not guaranteed to be same as on master.
*/
if (thd->slave_thread)
{
null_value= 0;
DBUG_RETURN(1);
}
if (args[1]->null_value ||
(!args[1]->unsigned_flag && ((longlong) timeout < 0)))
{
char buf[22];
if (args[1]->null_value)
strmov(buf, "NULL");
else
llstr(((longlong) timeout), buf);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
"timeout", buf, "get_lock");
null_value= 1;
DBUG_RETURN(0);
}
mysql_mutex_lock(&LOCK_user_locks);

View File

@@ -464,6 +464,7 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent,
{
List_iterator<Ref_to_outside> it(upper_refs);
Ref_to_outside *upper;
DBUG_ENTER("recalc_used_tables");
used_tables_cache= 0;
while ((upper= it++))
@@ -523,6 +524,8 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent,
he has done const table detection, and that will be our chance to update
const_tables_cache.
*/
DBUG_PRINT("exit", ("used_tables_cache: %llx", used_tables_cache));
DBUG_VOID_RETURN;
}
@@ -1989,7 +1992,7 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join)
*/
bool
Item_in_subselect::create_single_in_to_exists_cond(JOIN * join,
Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
Item **where_item,
Item **having_item)
{
@@ -1999,7 +2002,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join,
during JOIN::optimize: this->tmp_having= this->having; this->having= 0;
*/
Item* join_having= join->having ? join->having : join->tmp_having;
DBUG_ENTER("Item_in_subselect::create_single_in_to_exists_cond");
*where_item= NULL;

View File

@@ -3514,9 +3514,17 @@ bool Item_func_group_concat::setup(THD *thd)
"all_fields". The resulting field list is used as input to create
tmp table columns.
*/
if (arg_count_order &&
setup_order(thd, args, context->table_list, list, all_fields, *order))
if (arg_count_order)
{
uint n_elems= arg_count_order + all_fields.elements;
ref_pointer_array= static_cast<Item**>(thd->alloc(sizeof(Item*) * n_elems));
if (!ref_pointer_array)
DBUG_RETURN(TRUE);
memcpy(ref_pointer_array, args, arg_count * sizeof(Item*));
if (setup_order(thd, ref_pointer_array, context->table_list, list,
all_fields, *order))
DBUG_RETURN(TRUE);
}
count_field_types(select_lex, tmp_table_param, all_fields, 0);
tmp_table_param->force_copy_fields= force_copy_fields;

View File

@@ -1394,6 +1394,7 @@ class Item_func_group_concat : public Item_sum
String *separator;
TREE tree_base;
TREE *tree;
Item **ref_pointer_array;
/**
If DISTINCT is used with this GROUP_CONCAT, this member is used to filter

View File

@@ -3778,6 +3778,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
{
int error;
char *to_purge_if_included= NULL;
ulonglong log_space_reclaimed= 0;
DBUG_ENTER("purge_first_log");
DBUG_ASSERT(is_open());
@@ -3826,17 +3827,13 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE(););
mysql_mutex_lock(&rli->log_space_lock);
rli->relay_log.purge_logs(to_purge_if_included, included,
0, 0, &rli->log_space_total);
mysql_mutex_unlock(&rli->log_space_lock);
0, 0, &log_space_reclaimed);
/*
Ok to broadcast after the critical region as there is no risk of
the mutex being destroyed by this thread later - this helps save
context switches
*/
mysql_mutex_lock(&rli->log_space_lock);
rli->log_space_total-= log_space_reclaimed;
mysql_cond_broadcast(&rli->log_space_cond);
mysql_mutex_unlock(&rli->log_space_lock);
/*
* Need to update the log pos because purge logs has been called
@@ -3885,7 +3882,7 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads
@param need_mutex
@param need_update_threads If we want to update the log coordinates of
all threads. False for relay logs, true otherwise.
@param freed_log_space If not null, decrement this variable of
@param reclaimeed_log_space If not null, increment this variable to
the amount of log space freed
@note
@@ -3905,7 +3902,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
bool included,
bool need_mutex,
bool need_update_threads,
ulonglong *decrease_log_space)
ulonglong *reclaimed_space)
{
int error= 0;
bool exit_loop= 0;
@@ -3970,7 +3967,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log,
err:
/* Read each entry from purge_index_file and delete the file. */
if (is_inited_purge_index_file() &&
(error= purge_index_entry(thd, decrease_log_space, FALSE)))
(error= purge_index_entry(thd, reclaimed_space, FALSE)))
sql_print_error("MSYQL_BIN_LOG::purge_logs failed to process registered files"
" that would be purged.");
close_purge_index_file();
@@ -4075,7 +4072,7 @@ int MYSQL_BIN_LOG::register_create_index_entry(const char *entry)
DBUG_RETURN(register_purge_index_entry(entry));
}
int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *reclaimed_space,
bool need_mutex)
{
DBUG_ENTER("MYSQL_BIN_LOG:purge_index_entry");
@@ -4195,8 +4192,8 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space,
DBUG_PRINT("info",("purging %s",log_info.log_file_name));
if (!my_delete(log_info.log_file_name, MYF(0)))
{
if (decrease_log_space)
*decrease_log_space-= s.st_size;
if (reclaimed_space)
*reclaimed_space+= s.st_size;
}
else
{

View File

@@ -1252,9 +1252,10 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet,
}
data_len= uint4korr(buf + EVENT_LEN_OFFSET);
if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
data_len > current_thd->variables.max_allowed_packet)
data_len > max(current_thd->variables.max_allowed_packet,
opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
{
DBUG_PRINT("error",("data_len: %ld", data_len));
DBUG_PRINT("error",("data_len: %lu", data_len));
result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
LOG_READ_TOO_LARGE);
goto end;
@@ -1375,7 +1376,7 @@ failed my_b_read"));
*/
DBUG_RETURN(0);
}
uint data_len = uint4korr(head + EVENT_LEN_OFFSET);
ulong data_len = uint4korr(head + EVENT_LEN_OFFSET);
char *buf= 0;
const char *error= 0;
Log_event *res= 0;
@@ -1384,7 +1385,8 @@ failed my_b_read"));
uint max_allowed_packet= thd ? slave_max_allowed_packet:~(uint)0;
#endif
if (data_len > max_allowed_packet)
if (data_len > max(max_allowed_packet,
opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
{
error = "Event too big";
goto err;
@@ -1418,7 +1420,7 @@ err:
{
DBUG_ASSERT(error != 0);
sql_print_error("Error in Log_event::read_log_event(): "
"'%s', data_len: %d, event_type: %d",
"'%s', data_len: %lu, event_type: %d",
error,data_len,head[EVENT_TYPE_OFFSET]);
my_free(buf);
/*

View File

@@ -2644,7 +2644,6 @@ void unlink_thd(THD *thd)
thd->add_status_to_global();
mysql_mutex_lock(&LOCK_thread_count);
thread_count--;
thd->unlink();
/*
Used by binlog_reset_master. It would be cleaner to use
@@ -2652,6 +2651,16 @@ void unlink_thd(THD *thd)
sync feature has been shut down at this point.
*/
DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
if (unlikely(abort_loop))
{
/*
During shutdown, we have to delete thd inside the mutex
to not refer to mutexes that may be deleted during shutdown
*/
delete thd;
thd= 0;
}
thread_count--;
mysql_mutex_unlock(&LOCK_thread_count);
delete thd;

View File

@@ -38,8 +38,6 @@ typedef struct Trans_binlog_info {
char log_file[FN_REFLEN];
} Trans_binlog_info;
static pthread_key(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
int get_user_var_int(const char *name,
long long int *value, int *null_value)
{
@@ -143,13 +141,6 @@ int delegates_init()
}
#endif
if (pthread_key_create(&RPL_TRANS_BINLOG_INFO, NULL))
{
sql_print_error("Error while creating pthread specific data key for replication. "
"Please report a bug.");
return 1;
}
return 0;
}
@@ -195,27 +186,27 @@ void delegates_destroy()
int Trans_delegate::after_commit(THD *thd, bool all)
{
Trans_param param;
Trans_binlog_info *log_info;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
int ret= 0;
param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
log_info= thd->semisync_info;
param.log_file= log_info ? log_info->log_file : 0;
param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0;
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
FOREACH_OBSERVER(ret, after_commit, false, (&param));
/*
This is the end of a real transaction or autocommit statement, we
can free the memory allocated for binlog file and position.
can mark the memory unused.
*/
if (is_real_trans && log_info)
{
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL);
my_free(log_info);
log_info->log_file[0]= 0;
log_info->log_pos= 0;
}
return ret;
}
@@ -223,27 +214,27 @@ int Trans_delegate::after_commit(THD *thd, bool all)
int Trans_delegate::after_rollback(THD *thd, bool all)
{
Trans_param param;
Trans_binlog_info *log_info;
bool is_real_trans= (all || thd->transaction.all.ha_list == 0);
int ret= 0;
param.flags = is_real_trans ? TRANS_IS_REAL_TRANS : 0;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
log_info= thd->semisync_info;
param.log_file= log_info ? log_info->log_file : 0;
param.log_file= log_info && log_info->log_file[0] ? log_info->log_file : 0;
param.log_pos= log_info ? log_info->log_pos : 0;
int ret= 0;
FOREACH_OBSERVER(ret, after_rollback, false, (&param));
/*
This is the end of a real transaction or autocommit statement, we
can free the memory allocated for binlog file and position.
can mark the memory unused.
*/
if (is_real_trans && log_info)
{
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, NULL);
my_free(log_info);
log_info->log_file[0]= 0;
log_info->log_pos= 0;
}
return ret;
}
@@ -254,25 +245,24 @@ int Binlog_storage_delegate::after_flush(THD *thd,
bool synced)
{
Binlog_storage_param param;
Trans_binlog_info *log_info;
uint32 flags=0;
int ret= 0;
if (synced)
flags |= BINLOG_STORAGE_IS_SYNCED;
Trans_binlog_info *log_info=
my_pthread_getspecific_ptr(Trans_binlog_info*, RPL_TRANS_BINLOG_INFO);
if (!log_info)
if (!(log_info= thd->semisync_info))
{
if(!(log_info=
(Trans_binlog_info *)my_malloc(sizeof(Trans_binlog_info), MYF(0))))
(Trans_binlog_info*) my_malloc(sizeof(Trans_binlog_info), MYF(0))))
return 1;
my_pthread_setspecific_ptr(RPL_TRANS_BINLOG_INFO, log_info);
thd->semisync_info= log_info;
}
strcpy(log_info->log_file, log_file+dirname_length(log_file));
log_info->log_pos = log_pos;
int ret= 0;
FOREACH_OBSERVER(ret, after_flush, false,
(&param, log_info->log_file, log_info->log_pos, flags));
return ret;

View File

@@ -876,6 +876,7 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
{
Create_field *field_def=
(Create_field*) alloc_root(thd->mem_root, sizeof(Create_field));
bool unsigned_flag= 0;
if (field_list.push_back(field_def))
DBUG_RETURN(NULL);
@@ -885,8 +886,7 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
uint32 max_length=
max_display_length_for_field(type(col), field_metadata(col));
switch(type(col))
{
switch(type(col)) {
int precision;
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
@@ -925,6 +925,18 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
pack_length= field_metadata(col) & 0x00ff;
break;
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
/*
As we don't know if the integer was signed or not on the master,
assume we have same sign on master and slave. This is true when not
using conversions so it should be true also when using conversions.
*/
unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag;
break;
default:
break;
}
@@ -932,12 +944,13 @@ TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
type(col), target_table->field[col]->field_name,
max_length, decimals, TRUE, FALSE, pack_length));
max_length, decimals, TRUE, unsigned_flag,
pack_length));
field_def->init_for_tmp_table(type(col),
max_length,
decimals,
TRUE, // maybe_null
FALSE, // unsigned_flag
unsigned_flag,
pack_length);
field_def->charset= target_table->field[col]->charset();
field_def->interval= interval;

View File

@@ -3531,9 +3531,7 @@ pthread_handler_t handle_slave_sql(void *arg)
rli->clear_error();
//tell the I/O thread to take relay_log_space_limit into account from now on
mysql_mutex_lock(&rli->log_space_lock);
rli->ignore_log_space_limit= 0;
mysql_mutex_unlock(&rli->log_space_lock);
rli->trans_retries= 0; // start from "no error"
DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries));
@@ -5235,14 +5233,8 @@ static Log_event* next_event(Relay_log_info* rli)
rli->ignore_log_space_limit= true;
}
/*
If the I/O thread is blocked, unblock it. Ok to broadcast
after unlock, because the mutex is only destroyed in
~Relay_log_info(), i.e. when rli is destroyed, and rli will
not be destroyed before we exit the present function.
*/
mysql_mutex_unlock(&rli->log_space_lock);
mysql_cond_broadcast(&rli->log_space_cond);
mysql_mutex_unlock(&rli->log_space_lock);
// Note that wait_for_update_relay_log unlocks lock_log !
rli->relay_log.wait_for_update_relay_log(rli->sql_thd);
// re-acquire data lock since we released it earlier

View File

@@ -4067,10 +4067,11 @@ request_backoff_action(enum_open_table_action action_arg,
* We met a broken table that needs repair, or a table that
is not present on this MySQL server and needs re-discovery.
To perform the action, we need an exclusive metadata lock on
the table. Acquiring an X lock while holding other shared
locks is very deadlock-prone. If this is a multi- statement
transaction that holds metadata locks for completed
statements, we don't do it, and report an error instead.
the table. Acquiring X lock while holding other shared
locks can easily lead to deadlocks. We rely on MDL deadlock
detector to discover them. If this is a multi-statement
transaction that holds metadata locks for completed statements,
we should keep these locks after discovery/repair.
The action type in this case is OT_DISCOVER or OT_REPAIR.
* Our attempt to acquire an MDL lock lead to a deadlock,
detected by the MDL deadlock detector. The current
@@ -4111,7 +4112,7 @@ request_backoff_action(enum_open_table_action action_arg,
keep tables open between statements and a livelock
is not possible.
*/
if (action_arg != OT_REOPEN_TABLES && m_has_locks)
if (action_arg == OT_BACKOFF_AND_RETRY && m_has_locks)
{
my_error(ER_LOCK_DEADLOCK, MYF(0));
m_thd->mark_transaction_to_rollback(true);
@@ -4138,6 +4139,32 @@ request_backoff_action(enum_open_table_action action_arg,
}
/**
An error handler to mark transaction to rollback on DEADLOCK error
during DISCOVER / REPAIR.
*/
class MDL_deadlock_discovery_repair_handler : public Internal_error_handler
{
public:
virtual bool handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
{
if (sql_errno == ER_LOCK_DEADLOCK)
{
thd->mark_transaction_to_rollback(true);
}
/*
We have marked this transaction to rollback. Return false to allow
error to be reported or handled by other handlers.
*/
return false;
}
};
/**
Recover from failed attempt of open table by performing requested action.
@@ -4153,6 +4180,12 @@ Open_table_context::
recover_from_failed_open()
{
bool result= FALSE;
MDL_deadlock_discovery_repair_handler handler;
/*
Install error handler to mark transaction to rollback on DEADLOCK error.
*/
m_thd->push_internal_handler(&handler);
/* Execute the action. */
switch (m_action)
{
@@ -4174,7 +4207,12 @@ recover_from_failed_open()
m_thd->warning_info->clear_warning_info(m_thd->query_id);
m_thd->clear_error(); // Clear error message
m_thd->mdl_context.release_transactional_locks();
/*
Rollback to start of the current statement to release exclusive lock
on table which was discovered but preserve locks from previous statements
in current transaction.
*/
m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp());
break;
}
case OT_REPAIR:
@@ -4188,12 +4226,18 @@ recover_from_failed_open()
m_failed_table->table_name, FALSE);
result= auto_repair_table(m_thd, m_failed_table);
m_thd->mdl_context.release_transactional_locks();
/*
Rollback to start of the current statement to release exclusive lock
on table which was discovered but preserve locks from previous statements
in current transaction.
*/
m_thd->mdl_context.rollback_to_savepoint(start_of_statement_svp());
break;
}
default:
DBUG_ASSERT(0);
}
m_thd->pop_internal_handler();
/*
Reset the pointers to conflicting MDL request and the
TABLE_LIST element, set when we need auto-discovery or repair,
@@ -6879,6 +6923,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
if (item->cached_table)
{
DBUG_PRINT("info", ("using cached table"));
/*
This shortcut is used by prepared statements. We assume that
TABLE_LIST *first_table is not changed during query execution (which

View File

@@ -1058,6 +1058,7 @@ THD::THD()
file_id = 0;
query_id= 0;
query_name_consts= 0;
semisync_info= 0;
db_charset= global_system_variables.collation_database;
bzero(ha_data, sizeof(ha_data));
mysys_var=0;
@@ -1467,6 +1468,8 @@ void THD::init(void)
bzero((char *) &status_var, sizeof(status_var));
bzero((char *) &org_status_var, sizeof(org_status_var));
start_bytes_received= 0;
status_in_global= 0;
#ifdef WITH_WSREP
wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE;
wsrep_conflict_state= NO_CONFLICT;
@@ -1491,8 +1494,8 @@ void THD::init(void)
*/
if (variables.wsrep_causal_reads)
variables.wsrep_sync_wait|= WSREP_SYNC_WAIT_BEFORE_READ;
#endif /* WITH_WSREP */
#endif
if (variables.sql_log_bin)
variables.option_bits|= OPTION_BIN_LOG;
else
@@ -1595,6 +1598,7 @@ void THD::change_user(void)
cleanup();
reset_killed();
cleanup_done= 0;
status_in_global= 0;
init();
stmt_map.reset();
my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
@@ -1727,6 +1731,7 @@ THD::~THD()
mysql_audit_free_thd(this);
if (rli_slave)
rli_slave->cleanup_after_session();
my_free(semisync_info);
#endif
free_root(&main_mem_root, MYF(0));

View File

@@ -59,7 +59,6 @@ struct wsrep_thd_shadow {
#endif
class Reprepare_observer;
class Relay_log_info;
class Query_log_event;
class Load_log_event;
class Slave_log_event;
@@ -71,6 +70,7 @@ class Rows_log_event;
class Sroutine_hash_entry;
class User_level_lock;
class user_var_entry;
struct Trans_binlog_info;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
@@ -1689,6 +1689,9 @@ public:
*/
const char *where;
/* Needed by MariaDB semi sync replication */
Trans_binlog_info *semisync_info;
ulong client_capabilities; /* What the client supports */
ulong max_client_packet_length;
@@ -1752,11 +1755,11 @@ public:
/* Do not set socket timeouts for wait_timeout (used with threadpool) */
bool skip_wait_timeout;
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
bool prepare_derived_at_open;
/* Set to 1 if status of this THD is already in global status */
bool status_in_global;
/*
To signal that the tmp table to be created is created for materialized
derived table or a view.
@@ -1765,6 +1768,9 @@ public:
bool save_prep_leaf_list;
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
#ifndef MYSQL_CLIENT
binlog_cache_mngr * binlog_setup_trx_data();
@@ -3175,6 +3181,8 @@ public:
{
mysql_mutex_lock(&LOCK_status);
add_to_status(&global_status_var, &status_var);
/* Mark that this THD status has already been added in global status */
status_in_global= 1;
mysql_mutex_unlock(&LOCK_status);
}

View File

@@ -1928,7 +1928,6 @@ void st_select_lex::init_select()
with_sum_func= 0;
is_correlated= 0;
cur_pos_in_select_list= UNDEF_POS;
non_agg_fields.empty();
cond_value= having_value= Item::COND_UNDEF;
inner_refs_list.empty();
insert_tables= 0;
@@ -1936,6 +1935,7 @@ void st_select_lex::init_select()
m_non_agg_field_used= false;
m_agg_func_used= false;
name_visibility_map= 0;
join= 0;
}
/*

View File

@@ -877,8 +877,6 @@ public:
bool no_wrap_view_item;
/* exclude this select from check of unique_table() */
bool exclude_from_table_unique_test;
/* List of fields that aren't under an aggregate function */
List<Item_field> non_agg_fields;
/* index in the select list of the expression currently being fixed */
int cur_pos_in_select_list;

View File

@@ -6175,6 +6175,8 @@ void THD::reset_for_next_command()
thd->reset_current_stmt_binlog_format_row();
thd->binlog_unsafe_warning_flags= 0;
thd->save_prep_leaf_list= false;
DBUG_PRINT("debug",
("is_current_stmt_binlog_format_row(): %d",
thd->is_current_stmt_binlog_format_row()));

View File

@@ -4904,6 +4904,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
KEY_FIELD *key_fields, *end, *field;
uint sz;
uint m= max(select_lex->max_equal_elems,1);
DBUG_ENTER("update_ref_and_keys");
DBUG_PRINT("enter", ("normal_tables: %llx", normal_tables));
SELECT_LEX *sel=thd->lex->current_select;
sel->cond_count= 0;
@@ -4950,7 +4952,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
((sel->cond_count*2 + sel->between_count)*m+1);
if (!(key_fields=(KEY_FIELD*) thd->alloc(sz)))
return TRUE; /* purecov: inspected */
DBUG_RETURN(TRUE); /* purecov: inspected */
and_level= 0;
field= end= key_fields;
*sargables= (SARGABLE_PARAM *) key_fields +
@@ -4959,7 +4961,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
(*sargables)[0].field= 0;
if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
return TRUE;
DBUG_RETURN(TRUE);
if (cond)
{
@@ -5009,16 +5011,16 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
for ( ; field != end ; field++)
{
if (add_key_part(keyuse,field))
return TRUE;
DBUG_RETURN(TRUE);
}
if (select_lex->ftfunc_list->elements)
{
if (add_ft_keys(keyuse,join_tab,cond,normal_tables))
return TRUE;
DBUG_RETURN(TRUE);
}
return FALSE;
DBUG_RETURN(FALSE);
}
@@ -20705,7 +20707,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
Item_field *field;
int cur_pos_in_select_list= 0;
List_iterator<Item> li(fields);
List_iterator<Item_field> naf_it(thd->lex->current_select->non_agg_fields);
List_iterator<Item_field> naf_it(thd->lex->current_select->join->non_agg_fields);
field= naf_it++;
while (field && (item=li++))

View File

@@ -922,6 +922,9 @@ public:
Item *pre_sort_idx_pushed_cond;
void clean_pre_sort_join_tab();
/* List of fields that aren't under an aggregate function */
List<Item_field> non_agg_fields;
/*
For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
either:
@@ -1301,6 +1304,7 @@ public:
all_fields= fields_arg;
if (&fields_list != &fields_arg) /* Avoid valgrind-warning */
fields_list= fields_arg;
non_agg_fields.empty();
bzero((char*) &keyuse,sizeof(keyuse));
tmp_table_param.init();
tmp_table_param.end_write_records= HA_POS_ERROR;

View File

@@ -3126,7 +3126,10 @@ void calc_sum_of_all_status(STATUS_VAR *to)
/* Add to this status from existing threads */
while ((tmp= it++))
{
if (!tmp->status_in_global)
add_to_status(to, &tmp->status_var);
}
mysql_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;

View File

@@ -248,7 +248,7 @@ TEST_join(JOIN *join)
#define FT_KEYPART (MAX_REF_PARTS+10)
void print_keyuse(KEYUSE *keyuse)
static void print_keyuse(KEYUSE *keyuse)
{
char buff[256];
char buf2[64];
@@ -266,14 +266,11 @@ void print_keyuse(KEYUSE *keyuse)
else
fieldname= key_info->key_part[keyuse->keypart].field->field_name;
ll2str(keyuse->used_tables, buf2, 16, 0);
DBUG_LOCK_FILE;
fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s optimize: %u used_tables: %s "
"ref_table_rows: %lu keypart_map: %0lx\n",
keyuse->table->alias.c_ptr(), fieldname, str.ptr(),
(uint) keyuse->optimize, buf2, (ulong) keyuse->ref_table_rows,
(ulong) keyuse->keypart_map);
DBUG_UNLOCK_FILE;
//key_part_map keypart_map; --?? there can be several?
}
@@ -282,9 +279,9 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array)
{
DBUG_LOCK_FILE;
fprintf(DBUG_FILE, "KEYUSE array (%d elements)\n", keyuse_array->elements);
DBUG_UNLOCK_FILE;
for(uint i=0; i < keyuse_array->elements; i++)
print_keyuse((KEYUSE*)dynamic_array_ptr(keyuse_array, i));
DBUG_UNLOCK_FILE;
}

View File

@@ -1021,7 +1021,6 @@ bool st_select_lex::cleanup()
{
error= (bool) ((uint) error | (uint) lex_unit->cleanup());
}
non_agg_fields.empty();
inner_refs_list.empty();
exclude_from_table_unique_test= FALSE;
DBUG_RETURN(error);
@@ -1032,6 +1031,7 @@ void st_select_lex::cleanup_all_joins(bool full)
{
SELECT_LEX_UNIT *unit;
SELECT_LEX *sl;
DBUG_ENTER("st_select_lex::cleanup_all_joins");
if (join)
join->cleanup(full);
@@ -1039,6 +1039,7 @@ void st_select_lex::cleanup_all_joins(bool full)
for (unit= first_inner_unit(); unit; unit= unit->next_unit())
for (sl= unit->first_select(); sl; sl= sl->next_select())
sl->cleanup_all_joins(full);
DBUG_VOID_RETURN;
}

View File

@@ -5203,7 +5203,7 @@ Item *Field_iterator_table::create_item(THD *thd)
if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
!thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS)
{
select->non_agg_fields.push_back(item);
select->join->non_agg_fields.push_back(item);
item->marker= select->cur_pos_in_select_list;
select->set_non_agg_field_used(true);
}

View File

@@ -1419,6 +1419,104 @@ dict_create_add_foreign_field_to_dictionary(
table, foreign, trx));
}
/********************************************************************//**
Construct foreign key constraint defintion from data dictionary information.
*/
UNIV_INTERN
char*
dict_foreign_def_get(
/*=================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx) /*!< in: trx */
{
char* fk_def = mem_heap_alloc(foreign->heap, 4*1024);
const char* tbname;
char tablebuf[MAX_TABLE_NAME_LEN + 1] = "";
int i;
char* bufend;
tbname = dict_remove_db_name(foreign->id);
bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
tbname, strlen(tbname), trx->mysql_thd, FALSE);
tablebuf[bufend - tablebuf] = '\0';
sprintf(fk_def,
(char *)"CONSTRAINT %s FOREIGN KEY (", (char *)tablebuf);
for(i = 0; i < foreign->n_fields; i++) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->foreign_col_names[i],
strlen(foreign->foreign_col_names[i]),
trx->mysql_thd, FALSE);
strcat(fk_def, buf);
if (i < foreign->n_fields-1) {
strcat(fk_def, (char *)",");
}
}
strcat(fk_def,(char *)") REFERENCES ");
bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
foreign->referenced_table_name,
strlen(foreign->referenced_table_name),
trx->mysql_thd, TRUE);
tablebuf[bufend - tablebuf] = '\0';
strcat(fk_def, tablebuf);
strcat(fk_def, " (");
for(i = 0; i < foreign->n_fields; i++) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->referenced_col_names[i],
strlen(foreign->referenced_col_names[i]),
trx->mysql_thd, FALSE);
buf[bufend - buf] = '\0';
strcat(fk_def, buf);
if (i < foreign->n_fields-1) {
strcat(fk_def, (char *)",");
}
}
strcat(fk_def, (char *)")");
return fk_def;
}
/********************************************************************//**
Convert foreign key column names from data dictionary to SQL-layer.
*/
static
void
dict_foreign_def_get_fields(
/*========================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx, /*!< in: trx */
char** field, /*!< out: foreign column */
char** field2, /*!< out: referenced column */
int col_no) /*!< in: column number */
{
char* bufend;
char* fieldbuf = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
char* fieldbuf2 = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
bufend = innobase_convert_name(fieldbuf, MAX_TABLE_NAME_LEN,
foreign->foreign_col_names[col_no],
strlen(foreign->foreign_col_names[col_no]),
trx->mysql_thd, FALSE);
fieldbuf[bufend - fieldbuf] = '\0';
bufend = innobase_convert_name(fieldbuf2, MAX_TABLE_NAME_LEN,
foreign->referenced_col_names[col_no],
strlen(foreign->referenced_col_names[col_no]),
trx->mysql_thd, FALSE);
fieldbuf2[bufend - fieldbuf2] = '\0';
*field = fieldbuf;
*field2 = fieldbuf2;
}
/********************************************************************//**
Add a single foreign key definition to the data dictionary tables in the
database. We also generate names to constraints that were not named by the
@@ -1501,6 +1599,29 @@ dict_create_add_foreign_to_dictionary(
if (error != DB_SUCCESS) {
if (error == DB_DUPLICATE_KEY) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char tablename[MAX_TABLE_NAME_LEN + 1] = "";
char* fk_def;
innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
table->name, strlen(table->name),
trx->mysql_thd, TRUE);
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
fk_def = dict_foreign_def_get(foreign, trx);
ib_push_warning(trx, error,
"Create or Alter table %s with foreign key constraint"
" failed. Foreign key constraint %s"
" already exists on data dictionary."
" Foreign key constraint names need to be unique in database."
" Error in foreign key definition: %s.",
tablename, buf, fk_def);
}
return(error);
}
@@ -1509,6 +1630,26 @@ dict_create_add_foreign_to_dictionary(
i, table, foreign, trx);
if (error != DB_SUCCESS) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char tablename[MAX_TABLE_NAME_LEN + 1] = "";
char* field=NULL;
char* field2=NULL;
char* fk_def;
innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
table->name, strlen(table->name),
trx->mysql_thd, TRUE);
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
fk_def = dict_foreign_def_get(foreign, trx);
dict_foreign_def_get_fields(foreign, trx, &field, &field2, i);
ib_push_warning(trx, error,
"Create or Alter table %s with foreign key constraint"
" failed. Error adding foreign key constraint name %s"
" fields %s or %s to the dictionary."
" Error in foreign key definition: %s.",
tablename, buf, i+1, fk_def);
return(error);
}

View File

@@ -2534,8 +2534,9 @@ dict_foreign_remove_from_cache(
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
if (node) {
dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (node != NULL) {
dict_foreign_t* val
= *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
@@ -2555,9 +2556,10 @@ dict_foreign_remove_from_cache(
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
if (node) {
dict_foreign_t* val = *(dict_foreign_t**) node->value;
if (node != NULL) {
dict_foreign_t* val
= *(dict_foreign_t**) node->value;
if (val == foreign) {
rbt_delete(rbt, foreign->id);
@@ -2614,6 +2616,11 @@ dict_foreign_find(
DBUG_RETURN(NULL);
}
#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200
#define DB_FOREIGN_KEY_COL_NOT_NULL 201
#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202
#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203
/*********************************************************************//**
Tries to find an index whose first fields are the columns in the array,
in the same order and is not marked for deletion and is not the same
@@ -2631,12 +2638,21 @@ dict_foreign_find_index(
ibool check_charsets,
/*!< in: whether to check charsets.
only has an effect if types_idx != NULL */
ulint check_null)
ulint check_null,
/*!< in: nonzero if none of the columns must
be declared NOT NULL */
ulint* error, /*!< out: error code */
ulint* err_col_no,
/*!< out: column number where error happened */
dict_index_t** err_index)
/*!< out: index where error happened */
{
dict_index_t* index;
if (error) {
*error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
}
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -2662,6 +2678,12 @@ dict_foreign_find_index(
/* We do not accept column prefix
indexes here */
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_IS_PREFIX_INDEX;
*err_col_no = i;
*err_index = index;
}
break;
}
@@ -2673,6 +2695,11 @@ dict_foreign_find_index(
if (check_null
&& (field->col->prtype & DATA_NOT_NULL)) {
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_COL_NOT_NULL;
*err_col_no = i;
*err_index = index;
}
return(NULL);
}
@@ -2682,6 +2709,12 @@ dict_foreign_find_index(
i),
check_charsets)) {
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
*err_col_no = i;
*err_index = index;
}
break;
}
}
@@ -2689,6 +2722,10 @@ dict_foreign_find_index(
if (i == n_cols) {
/* We found a matching index */
if (error) {
*error = DB_SUCCESS;
}
return(index);
}
}
@@ -2715,8 +2752,9 @@ wsrep_dict_foreign_find_index(
/*!< in: nonzero if none of the columns must
be declared NOT NULL */
{
return dict_foreign_find_index(
table, columns, n_cols, types_idx, check_charsets, check_null);
return dict_foreign_find_index(table, columns, n_cols, types_idx,
check_charsets, check_null,
NULL, NULL, NULL);
}
#endif /* WITH_WSREP */
/**********************************************************************//**
@@ -2739,7 +2777,7 @@ dict_foreign_find_equiv_index(
foreign->foreign_table,
foreign->foreign_col_names, foreign->n_fields,
foreign->foreign_index, TRUE, /* check types */
FALSE/* allow columns to be NULL */));
FALSE/* allow columns to be NULL */, NULL, NULL, NULL));
}
#endif /* !UNIV_HOTBACKUP */
@@ -2902,11 +2940,15 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->referenced_table == NULL && ref_table) {
ulint index_error;
ulint err_col;
dict_index_t *err_index=NULL;
index = dict_foreign_find_index(
ref_table,
for_in_cache->referenced_col_names,
for_in_cache->n_fields, for_in_cache->foreign_index,
check_charsets, FALSE);
check_charsets, FALSE, &index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -2938,6 +2980,9 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->foreign_table == NULL && for_table) {
ulint index_error;
ulint err_col;
dict_index_t* err_index=NULL;
index = dict_foreign_find_index(
for_table,
@@ -2946,7 +2991,8 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index, check_charsets,
for_in_cache->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
| DICT_FOREIGN_ON_UPDATE_SET_NULL),
&index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -3557,6 +3603,8 @@ static
void
dict_foreign_report_syntax_err(
/*===========================*/
const char* fmt, /*!< in: syntax err msg */
const char* oper, /*!< in: operation */
const char* name, /*!< in: table name */
const char* start_of_latest_foreign,
/*!< in: start of the foreign key clause
@@ -3567,11 +3615,101 @@ dict_foreign_report_syntax_err(
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
start_of_latest_foreign, ptr);
fprintf(ef, fmt, oper, name, start_of_latest_foreign, ptr);
mutex_exit(&dict_foreign_err_mutex);
}
/*********************************************************************//**
Push warning message to SQL-layer based on foreign key constraint
index match error. */
static
void
dict_foreign_push_index_error(
/*==========================*/
trx_t* trx, /*!< in: trx */
const char* operation, /*!< in: operation create or alter
*/
const char* create_name, /*!< in: table name in create or
alter table */
const char* latest_foreign, /*!< in: start of latest foreign key
constraint name */
const char** columns, /*!< in: foreign key columns */
ulint index_error, /*!< in: error code */
ulint err_col, /*!< in: column where error happened
*/
dict_index_t* err_index, /*!< in: index where error happened
*/
dict_table_t* table, /*!< in: table */
FILE* ef) /*!< in: output stream */
{
switch (index_error) {
case DB_FOREIGN_KEY_INDEX_NOT_FOUND: {
fprintf(ef,
"%s table '%s' with foreign key constraint"
" failed. There is no index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.\n",
operation, create_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table '%s' with foreign key constraint"
" failed. There is no index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.",
operation, create_name, latest_foreign);
break;
}
case DB_FOREIGN_KEY_IS_PREFIX_INDEX: {
fprintf(ef,
"%s table '%s' with foreign key constraint"
" failed. There is only prefix index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.\n",
operation, create_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table '%s' with foreign key constraint"
" failed. There is only prefix index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.",
operation, create_name, latest_foreign);
break;
}
case DB_FOREIGN_KEY_COL_NOT_NULL: {
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but "
"field %s on index is defined as NOT NULL close to %s\n",
operation, create_name, columns[err_col], latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but "
"field %s on index is defined as NOT NULL close to %s",
operation, create_name, columns[err_col], latest_foreign);
break;
}
case DB_FOREIGN_KEY_COLS_NOT_EQUAL: {
dict_field_t* field;
const char* col_name;
field = dict_index_get_nth_field(err_index, err_col);
col_name = dict_table_get_col_name(
table, dict_col_get_no(field->col));
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Field type or character set for column %s "
"does not mach referenced column %s close to %s\n",
operation, create_name, columns[err_col], col_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Field type or character set for column %s "
"does not mach referenced column %s close to %s",
operation, create_name, columns[err_col], col_name, latest_foreign);
break;
}
default:
ut_error;
}
}
/*********************************************************************//**
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
@@ -3600,15 +3738,20 @@ dict_create_foreign_constraints_low(
DB_CANNOT_ADD_CONSTRAINT if any foreign
keys are found. */
{
dict_table_t* table;
dict_table_t* referenced_table;
dict_table_t* table_to_alter;
dict_table_t* table = NULL;
dict_table_t* referenced_table = NULL;
dict_table_t* table_to_alter = NULL;
dict_table_t* table_to_create = NULL;
ulint highest_id_so_far = 0;
dict_index_t* index;
dict_foreign_t* foreign;
dict_index_t* index = NULL;
dict_foreign_t* foreign = NULL;
const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
const char* start_of_latest_set = NULL;
FILE* ef = dict_foreign_err_file;
ulint index_error = DB_SUCCESS;
dict_index_t* err_index = NULL;
ulint err_col;
const char* constraint_name;
ibool success;
ulint error;
@@ -3621,29 +3764,68 @@ dict_create_foreign_constraints_low(
ulint n_on_updates;
const dict_col_t*columns[500];
const char* column_names[500];
const char* ref_column_names[500];
const char* referenced_table_name;
const char* create_table_name;
const char* orig;
char create_name[MAX_TABLE_NAME_LEN + 1];
const char operation[8];
ut_ad(mutex_own(&(dict_sys->mutex)));
table = dict_table_get_low(name, DICT_ERR_IGNORE_NONE);
/* First check if we are actually doing an ALTER TABLE, and in that
case look for the table being altered */
ptr = dict_accept(cs, ptr, "ALTER", &success);
strcpy((char *)operation, success ? "Alter " : "Create ");
if (!success) {
orig = ptr;
ptr = dict_scan_to(ptr, "CREATE");
ptr = dict_scan_to(ptr, "TABLE");
ptr = dict_accept(cs, ptr, "TABLE", &success);
if (success) {
ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
&success, heap, &create_table_name);
}
if (success) {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
create_table_name, strlen(create_table_name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
ptr = orig;
} else {
char *bufend;
ptr = orig;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
name, strlen(name), trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
}
goto loop;
}
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef,
"Cannot find the table in the internal"
" data dictionary of InnoDB.\n"
"Create table statement:\n%s\n", sql_string);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.\n",
operation, create_name, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_ERROR,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.",
operation, create_name, create_name, start_of_latest_foreign);
return(DB_ERROR);
}
/* First check if we are actually doing an ALTER TABLE, and in that
case look for the table being altered */
ptr = dict_accept(cs, ptr, "ALTER", &success);
/* If not alter table jump to loop */
if (!success) {
goto loop;
@@ -3658,13 +3840,40 @@ dict_create_foreign_constraints_low(
/* We are doing an ALTER TABLE: scan the table name we are altering */
orig = ptr;
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
&success, heap, &referenced_table_name);
if (table_to_alter) {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
table_to_alter->name, strlen(table_to_alter->name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
} else {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
referenced_table_name, strlen(referenced_table_name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
}
if (!success) {
fprintf(stderr,
"InnoDB: Error: could not find"
" the table being ALTERED in:\n%s\n",
sql_string);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.\n",
operation, create_name, create_name, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_ERROR,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.",
operation, create_name, create_name, orig);
return(DB_ERROR);
}
@@ -3730,7 +3939,19 @@ loop:
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s table %s with foreign key constraint"
" failed. Temporary tables can't have foreign key constraints."
" Error close to %s.\n",
operation, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Temporary tables can't have foreign key constraints."
" Error close to %s.",
operation, create_name, start_of_latest_foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3766,11 +3987,21 @@ loop:
if (!success) {
/* MySQL allows also an index id before the '('; we
skip it */
orig = ptr;
ptr = dict_skip_word(cs, ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3790,15 +4021,26 @@ loop:
/* Scan the columns in the first list */
col_loop1:
ut_a(i < (sizeof column_names) / sizeof *column_names);
orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3810,11 +4052,22 @@ col_loop1:
goto col_loop1;
}
orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3822,27 +4075,41 @@ col_loop1:
as the first fields and in the right order */
index = dict_foreign_find_index(table, column_names, i,
NULL, TRUE, FALSE);
NULL, TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
dict_foreign_error_report_low(ef, create_name);
fputs("There is no index in table ", ef);
ut_print_name(ef, NULL, TRUE, name);
ut_print_name(ef, NULL, TRUE, create_name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
"See " REFMAN "innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CHILD_NO_INDEX);
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
column_names, index_error, err_col, err_index, table, ef);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
if (!success || !my_isspace(cs, *ptr)) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3891,24 +4158,50 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char* bufend;
bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
referenced_table_name, strlen(referenced_table_name),
trx->mysql_thd, TRUE);
buf[bufend - buf] = '\0';
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
"close to %s.",
operation, create_name, buf, start_of_latest_foreign);
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
"%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
"close to %s.\n",
operation, create_name, buf, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3916,20 +4209,29 @@ col_loop1:
i = 0;
col_loop2:
orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
heap, column_names + i);
heap, ref_column_names + i);
i++;
if (!success) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve column name close to:\n"
"%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3939,13 +4241,23 @@ col_loop2:
goto col_loop2;
}
orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s. Too few referenced columns.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s. Too few referenced columns, you have %d when you should have %d.",
operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3955,6 +4267,7 @@ col_loop2:
scan_on_conditions:
/* Loop here as long as we can find ON ... conditions */
start_of_latest_set = ptr;
ptr = dict_accept(cs, ptr, "ON", &success);
if (!success) {
@@ -3965,13 +4278,24 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "DELETE", &success);
if (!success) {
orig = ptr;
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4003,12 +4327,22 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "NO", &success);
if (success) {
orig = ptr;
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4022,42 +4356,73 @@ scan_on_conditions:
goto scan_on_conditions;
}
orig = ptr;
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
const dict_col_t* col
= dict_index_get_nth_col(foreign->foreign_index, j);
const char* col_name = dict_table_get_col_name(foreign->foreign_index->table,
dict_col_get_no(col));
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
"You have defined a SET NULL condition"
" though some of the\n"
"columns are defined as NOT NULL.\n",
start_of_latest_foreign);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
" in %s close to %s.\n",
operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
" in %s close to %s.",
operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -4074,16 +4439,22 @@ try_find_index:
if (n_on_deletes > 1 || n_on_updates > 1) {
/* It is an error to define more than 1 action */
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
"You have twice an ON DELETE clause"
" or twice an ON UPDATE clause.\n",
start_of_latest_foreign);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have more than one on delete or on update clause"
" in %s close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have more than one on delete or on update clause"
" in %s close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4093,13 +4464,13 @@ try_find_index:
if (referenced_table) {
index = dict_foreign_find_index(referenced_table,
column_names, i,
ref_column_names, i,
foreign->foreign_index,
TRUE, FALSE);
TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s:\n"
"Cannot find an index in the"
" referenced table where the\n"
@@ -4117,9 +4488,13 @@ try_find_index:
"innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
column_names, index_error, err_col, err_index, referenced_table, ef);
mutex_exit(&dict_foreign_err_mutex);
return(DB_PARENT_NO_INDEX);
return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
ut_a(trx->check_foreigns == FALSE);
@@ -4137,7 +4512,7 @@ try_find_index:
i * sizeof(void*));
for (i = 0; i < foreign->n_fields; i++) {
foreign->referenced_col_names[i]
= mem_heap_strdup(foreign->heap, column_names[i]);
= mem_heap_strdup(foreign->heap, ref_column_names[i]);
}
/* We found an ok constraint definition: add to the lists */
@@ -5270,7 +5645,8 @@ dict_table_replace_index_in_foreign_list(
foreign->referenced_table,
foreign->referenced_col_names,
foreign->n_fields, index,
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
NULL, NULL, NULL);
ut_ad(new_index || !trx->check_foreigns);
ut_ad(!new_index || new_index->table == index->table);

View File

@@ -1654,6 +1654,7 @@ check_trx_exists(
if (trx == NULL) {
trx = innobase_trx_allocate(thd);
thd_set_ha_data(thd, innodb_hton_ptr, trx);
} else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
mem_analyze_corruption(trx);
ut_error;
@@ -13711,3 +13712,29 @@ ib_warn_row_too_big(const dict_table_t* table)
" ROW_FORMAT=COMPRESSED ": ""
, prefix ? DICT_MAX_FIXED_COL_LEN : 0);
}
/********************************************************************//**
Helper function to push warnings from InnoDB internals to SQL-layer. */
extern "C" UNIV_INTERN
void
ib_push_warning(
trx_t* trx, /*!< in: trx */
ulint error, /*!< in: error code to push as warning */
const char *format,/*!< in: warning message */
...)
{
va_list args;
THD *thd = (THD *)trx->mysql_thd;
char *buf;
#define MAX_BUF_SIZE 4*1024
va_start(args, format);
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
vsprintf(buf,format, args);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
convert_error_code_to_mysql(error, 0, thd),
buf);
my_free(buf);
va_end(args);
}

View File

@@ -106,6 +106,17 @@ UNIV_INTERN
ulint
dict_create_or_check_foreign_constraint_tables(void);
/*================================================*/
/********************************************************************//**
Construct foreign key constraint defintion from data dictionary information.
*/
UNIV_INTERN
char*
dict_foreign_def_get(
/*=================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx); /*!< in: trx */
/********************************************************************//**
Adds foreign key definitions to data dictionary tables in the database. We
look at table->foreign_list, and also generate names to constraints that were

View File

@@ -339,5 +339,14 @@ innobase_convert_to_filename_charset(
const char* from, /* in: identifier to convert */
ulint len); /* in: length of 'to', in bytes */
/********************************************************************//**
Helper function to push warnings from InnoDB internals to SQL-layer. */
UNIV_INTERN
void
ib_push_warning(
trx_t* trx, /*!< in: trx */
ulint error, /*!< in: error code to push as warning */
const char *format,/*!< in: warning message */
...);
#endif

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2015, 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
@@ -111,6 +111,17 @@ struct purge_node_struct{
purge of a row */
};
#ifdef UNIV_DEBUG
/***********************************************************//**
Validate the persisent cursor in the purge node. The purge node has two
references to the clustered index record - one via the ref member, and the
other via the persistent cursor. These two references must match each
other if the found_clust flag is set.
@return true if the persistent cursor is consistent with the ref member.*/
ibool
row_purge_validate_pcur(purge_node_t* node);
#endif /* UNIV_DEBUG */
#ifndef UNIV_NONINL
#include "row0purge.ic"
#endif

View File

@@ -1,6 +1,6 @@
/***********************************************************************
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Portions of this file contain modifications contributed and copyrighted
@@ -1287,18 +1287,21 @@ os_file_create_simple_no_error_handling_func(
#else /* __WIN__ */
os_file_t file;
int create_flag;
const char* mode_str = NULL;
ut_a(name);
if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW)
WAIT_ALLOW_WRITES();
if (create_mode == OS_FILE_OPEN) {
mode_str = "OPEN";
if (access_type == OS_FILE_READ_ONLY) {
create_flag = O_RDONLY;
} else {
create_flag = O_RDWR;
}
} else if (create_mode == OS_FILE_CREATE) {
mode_str = "CREATE";
create_flag = O_RDWR | O_CREAT | O_EXCL;
} else {
create_flag = 0;
@@ -1323,6 +1326,14 @@ os_file_create_simple_no_error_handling_func(
#endif
} else {
*success = TRUE;
/* This function is always called for data files, we should
disable OS caching (O_DIRECT) here as we do in
os_file_create_func(), so we open the same file in the same
mode, see man page of open(2). */
if (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
os_file_set_nocache(file, name, mode_str);
}
}
return(file);

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1997, 2015, 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
@@ -43,6 +43,7 @@ Created 3/14/1997 Heikki Tuuri
#include "row0vers.h"
#include "row0mysql.h"
#include "log0log.h"
#include "rem0cmp.h"
/*************************************************************************
IMPORTANT NOTE: Any operation that generates redo MUST check that there
@@ -80,7 +81,7 @@ row_purge_node_create(
/***********************************************************//**
Repositions the pcur in the purge node on the clustered index record,
if found.
if found. If the record is not found, close pcur.
@return TRUE if the record was found */
static
ibool
@@ -90,23 +91,28 @@ row_purge_reposition_pcur(
purge_node_t* node, /*!< in: row purge node */
mtr_t* mtr) /*!< in: mtr */
{
ibool found;
if (node->found_clust) {
ut_ad(row_purge_validate_pcur(node));
node->found_clust = btr_pcur_restore_position(
mode, &(node->pcur), mtr);
} else {
node->found_clust = row_search_on_row_ref(
&(node->pcur), mode, node->table, node->ref, mtr);
if (node->found_clust) {
found = btr_pcur_restore_position(mode, &(node->pcur), mtr);
return(found);
}
found = row_search_on_row_ref(&(node->pcur), mode, node->table,
node->ref, mtr);
node->found_clust = found;
if (found) {
btr_pcur_store_position(&(node->pcur), mtr);
}
}
return(found);
/* Close the current cursor if we fail to position it correctly. */
if (!node->found_clust) {
btr_pcur_close(&node->pcur);
}
return(node->found_clust);
}
/***********************************************************//**
@@ -143,8 +149,8 @@ row_purge_remove_clust_if_poss_low(
if (!success) {
/* The record is already removed */
btr_pcur_commit_specify_mtr(pcur, &mtr);
/* Persistent cursor is closed if reposition fails. */
mtr_commit(&mtr);
return(TRUE);
}
@@ -258,7 +264,12 @@ row_purge_poss_sec(
btr_pcur_get_rec(&node->pcur),
&mtr, index, entry);
/* Persistent cursor is closed if reposition fails. */
if (node->found_clust) {
btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
} else {
mtr_commit(&mtr);
}
return(can_delete);
}
@@ -806,3 +817,53 @@ row_purge_step(
return(thr);
}
#ifdef UNIV_DEBUG
/***********************************************************//**
Validate the persisent cursor in the purge node. The purge node has two
references to the clustered index record - one via the ref member, and the
other via the persistent cursor. These two references must match each
other if the found_clust flag is set.
@return true if the stored copy of persistent cursor is consistent
with the ref member.*/
ibool
row_purge_validate_pcur(
purge_node_t* node)
{
dict_index_t* clust_index;
ulint* offsets;
int st;
if (!node->found_clust) {
return(TRUE);
}
if (node->index == NULL) {
return(TRUE);
}
if (node->pcur.old_stored != BTR_PCUR_OLD_STORED) {
return(TRUE);
}
clust_index = node->pcur.btr_cur.index;
offsets = rec_get_offsets(node->pcur.old_rec, clust_index, NULL,
node->pcur.old_n_fields, &node->heap);
/* Here we are comparing the purge ref record and the stored initial
part in persistent cursor. Both cases we store n_uniq fields of the
cluster index and so it is fine to do the comparison. We note this
dependency here as pcur and ref belong to different modules. */
st = cmp_dtuple_rec(node->ref, node->pcur.old_rec, offsets);
if (st != 0) {
fprintf(stderr, "Purge node pcur validation failed\n");
dtuple_print(stderr, node->ref);
rec_print(stderr, node->pcur.old_rec, clust_index);
return(FALSE);
}
return(TRUE);
}
#endif /* UNIV_DEBUG */

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -1666,6 +1666,10 @@ buf_pool_watch_set(
/* buf_pool->watch is protected by zip_mutex for now */
mutex_enter(&buf_pool->zip_mutex);
/* The maximum number of purge threads should never exceed
BUF_POOL_WATCH_SIZE. So there is no way for purge thread
instance to hold a watch when setting another watch. */
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
bpage = &buf_pool->watch[i];

View File

@@ -1626,6 +1626,104 @@ dict_create_add_foreign_field_to_dictionary(
table, foreign, trx));
}
/********************************************************************//**
Construct foreign key constraint defintion from data dictionary information.
*/
UNIV_INTERN
char*
dict_foreign_def_get(
/*=================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx) /*!< in: trx */
{
char* fk_def = mem_heap_alloc(foreign->heap, 4*1024);
const char* tbname;
char tablebuf[MAX_TABLE_NAME_LEN + 1] = "";
int i;
char* bufend;
tbname = dict_remove_db_name(foreign->id);
bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
tbname, strlen(tbname), trx->mysql_thd, FALSE);
tablebuf[bufend - tablebuf] = '\0';
sprintf(fk_def,
(char *)"CONSTRAINT %s FOREIGN KEY (", (char *)tablebuf);
for(i = 0; i < foreign->n_fields; i++) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->foreign_col_names[i],
strlen(foreign->foreign_col_names[i]),
trx->mysql_thd, FALSE);
strcat(fk_def, buf);
if (i < foreign->n_fields-1) {
strcat(fk_def, (char *)",");
}
}
strcat(fk_def,(char *)") REFERENCES ");
bufend = innobase_convert_name(tablebuf, MAX_TABLE_NAME_LEN,
foreign->referenced_table_name,
strlen(foreign->referenced_table_name),
trx->mysql_thd, TRUE);
tablebuf[bufend - tablebuf] = '\0';
strcat(fk_def, tablebuf);
strcat(fk_def, " (");
for(i = 0; i < foreign->n_fields; i++) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->referenced_col_names[i],
strlen(foreign->referenced_col_names[i]),
trx->mysql_thd, FALSE);
buf[bufend - buf] = '\0';
strcat(fk_def, buf);
if (i < foreign->n_fields-1) {
strcat(fk_def, (char *)",");
}
}
strcat(fk_def, (char *)")");
return fk_def;
}
/********************************************************************//**
Convert foreign key column names from data dictionary to SQL-layer.
*/
static
void
dict_foreign_def_get_fields(
/*========================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx, /*!< in: trx */
char** field, /*!< out: foreign column */
char** field2, /*!< out: referenced column */
int col_no) /*!< in: column number */
{
char* bufend;
char* fieldbuf = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
char* fieldbuf2 = mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
bufend = innobase_convert_name(fieldbuf, MAX_TABLE_NAME_LEN,
foreign->foreign_col_names[col_no],
strlen(foreign->foreign_col_names[col_no]),
trx->mysql_thd, FALSE);
fieldbuf[bufend - fieldbuf] = '\0';
bufend = innobase_convert_name(fieldbuf2, MAX_TABLE_NAME_LEN,
foreign->referenced_col_names[col_no],
strlen(foreign->referenced_col_names[col_no]),
trx->mysql_thd, FALSE);
fieldbuf2[bufend - fieldbuf2] = '\0';
*field = fieldbuf;
*field2 = fieldbuf2;
}
/********************************************************************//**
Add a single foreign key definition to the data dictionary tables in the
database. We also generate names to constraints that were not named by the
@@ -1708,6 +1806,29 @@ dict_create_add_foreign_to_dictionary(
if (error != DB_SUCCESS) {
if (error == DB_DUPLICATE_KEY) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char tablename[MAX_TABLE_NAME_LEN + 1] = "";
char* fk_def;
innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
table->name, strlen(table->name),
trx->mysql_thd, TRUE);
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
fk_def = dict_foreign_def_get(foreign, trx);
ib_push_warning(trx, error,
"Create or Alter table %s with foreign key constraint"
" failed. Foreign key constraint %s"
" already exists on data dictionary."
" Foreign key constraint names need to be unique in database."
" Error in foreign key definition: %s.",
tablename, buf, fk_def);
}
return(error);
}
@@ -1716,6 +1837,26 @@ dict_create_add_foreign_to_dictionary(
i, table, foreign, trx);
if (error != DB_SUCCESS) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char tablename[MAX_TABLE_NAME_LEN + 1] = "";
char* field=NULL;
char* field2=NULL;
char* fk_def;
innobase_convert_name(tablename, MAX_TABLE_NAME_LEN,
table->name, strlen(table->name),
trx->mysql_thd, TRUE);
innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
foreign->id, strlen(foreign->id), trx->mysql_thd, FALSE);
fk_def = dict_foreign_def_get(foreign, trx);
dict_foreign_def_get_fields(foreign, trx, &field, &field2, i);
ib_push_warning(trx, error,
"Create or Alter table %s with foreign key constraint"
" failed. Error adding foreign key constraint name %s"
" fields %s or %s to the dictionary."
" Error in foreign key definition: %s.",
tablename, buf, i+1, fk_def);
return(error);
}

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1996, 2015, 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
@@ -2663,6 +2663,7 @@ dict_foreign_remove_from_cache(
foreign);
rbt = foreign->referenced_table->referenced_rbt;
if (rbt != NULL && foreign->id != NULL) {
const ib_rbt_node_t* node
= rbt_lookup(rbt, foreign->id);
@@ -2747,6 +2748,11 @@ dict_foreign_find(
DBUG_RETURN(NULL);
}
#define DB_FOREIGN_KEY_IS_PREFIX_INDEX 200
#define DB_FOREIGN_KEY_COL_NOT_NULL 201
#define DB_FOREIGN_KEY_COLS_NOT_EQUAL 202
#define DB_FOREIGN_KEY_INDEX_NOT_FOUND 203
/*********************************************************************//**
Tries to find an index whose first fields are the columns in the array,
in the same order and is not marked for deletion and is not the same
@@ -2764,12 +2770,21 @@ dict_foreign_find_index(
ibool check_charsets,
/*!< in: whether to check charsets.
only has an effect if types_idx != NULL */
ulint check_null)
ulint check_null,
/*!< in: nonzero if none of the columns must
be declared NOT NULL */
ulint* error, /*!< out: error code */
ulint* err_col_no,
/*!< out: column number where error happened */
dict_index_t** err_index)
/*!< out: index where error happened */
{
dict_index_t* index;
if (error) {
*error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
}
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -2795,6 +2810,12 @@ dict_foreign_find_index(
/* We do not accept column prefix
indexes here */
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_IS_PREFIX_INDEX;
*err_col_no = i;
*err_index = index;
}
break;
}
@@ -2806,6 +2827,11 @@ dict_foreign_find_index(
if (check_null
&& (field->col->prtype & DATA_NOT_NULL)) {
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_COL_NOT_NULL;
*err_col_no = i;
*err_index = index;
}
return(NULL);
}
@@ -2815,6 +2841,12 @@ dict_foreign_find_index(
i),
check_charsets)) {
if (error && err_col_no && err_index) {
*error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
*err_col_no = i;
*err_index = index;
}
break;
}
}
@@ -2822,6 +2854,10 @@ dict_foreign_find_index(
if (i == n_cols) {
/* We found a matching index */
if (error) {
*error = DB_SUCCESS;
}
return(index);
}
}
@@ -2848,8 +2884,9 @@ wsrep_dict_foreign_find_index(
/*!< in: nonzero if none of the columns must
be declared NOT NULL */
{
return dict_foreign_find_index(
table, columns, n_cols, types_idx, check_charsets, check_null);
return dict_foreign_find_index(table, columns, n_cols, types_idx,
check_charsets, check_null,
NULL, NULL, NULL);
}
#endif /* WITH_WSREP */
/**********************************************************************//**
@@ -2872,7 +2909,7 @@ dict_foreign_find_equiv_index(
foreign->foreign_table,
foreign->foreign_col_names, foreign->n_fields,
foreign->foreign_index, TRUE, /* check types */
FALSE/* allow columns to be NULL */));
FALSE/* allow columns to be NULL */, NULL, NULL, NULL));
}
#endif /* !UNIV_HOTBACKUP */
@@ -3035,11 +3072,15 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->referenced_table == NULL && ref_table) {
ulint index_error;
ulint err_col;
dict_index_t *err_index=NULL;
index = dict_foreign_find_index(
ref_table,
for_in_cache->referenced_col_names,
for_in_cache->n_fields, for_in_cache->foreign_index,
check_charsets, FALSE);
check_charsets, FALSE, &index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -3071,6 +3112,9 @@ dict_foreign_add_to_cache(
}
if (for_in_cache->foreign_table == NULL && for_table) {
ulint index_error;
ulint err_col;
dict_index_t* err_index=NULL;
index = dict_foreign_find_index(
for_table,
@@ -3079,7 +3123,8 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index, check_charsets,
for_in_cache->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
| DICT_FOREIGN_ON_UPDATE_SET_NULL),
&index_error, &err_col, &err_index);
if (index == NULL
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
@@ -3690,6 +3735,8 @@ static
void
dict_foreign_report_syntax_err(
/*===========================*/
const char* fmt, /*!< in: syntax err msg */
const char* oper, /*!< in: operation */
const char* name, /*!< in: table name */
const char* start_of_latest_foreign,
/*!< in: start of the foreign key clause
@@ -3700,11 +3747,101 @@ dict_foreign_report_syntax_err(
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nSyntax error close to:\n%s\n",
start_of_latest_foreign, ptr);
fprintf(ef, fmt, oper, name, start_of_latest_foreign, ptr);
mutex_exit(&dict_foreign_err_mutex);
}
/*********************************************************************//**
Push warning message to SQL-layer based on foreign key constraint
index match error. */
static
void
dict_foreign_push_index_error(
/*==========================*/
trx_t* trx, /*!< in: trx */
const char* operation, /*!< in: operation create or alter
*/
const char* create_name, /*!< in: table name in create or
alter table */
const char* latest_foreign, /*!< in: start of latest foreign key
constraint name */
const char** columns, /*!< in: foreign key columns */
ulint index_error, /*!< in: error code */
ulint err_col, /*!< in: column where error happened
*/
dict_index_t* err_index, /*!< in: index where error happened
*/
dict_table_t* table, /*!< in: table */
FILE* ef) /*!< in: output stream */
{
switch (index_error) {
case DB_FOREIGN_KEY_INDEX_NOT_FOUND: {
fprintf(ef,
"%s table '%s' with foreign key constraint"
" failed. There is no index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.\n",
operation, create_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table '%s' with foreign key constraint"
" failed. There is no index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.",
operation, create_name, latest_foreign);
break;
}
case DB_FOREIGN_KEY_IS_PREFIX_INDEX: {
fprintf(ef,
"%s table '%s' with foreign key constraint"
" failed. There is only prefix index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.\n",
operation, create_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table '%s' with foreign key constraint"
" failed. There is only prefix index in the referenced"
" table where the referenced columns appear"
" as the first columns. Error close to %s.",
operation, create_name, latest_foreign);
break;
}
case DB_FOREIGN_KEY_COL_NOT_NULL: {
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but "
"field %s on index is defined as NOT NULL close to %s\n",
operation, create_name, columns[err_col], latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but "
"field %s on index is defined as NOT NULL close to %s",
operation, create_name, columns[err_col], latest_foreign);
break;
}
case DB_FOREIGN_KEY_COLS_NOT_EQUAL: {
dict_field_t* field;
const char* col_name;
field = dict_index_get_nth_field(err_index, err_col);
col_name = dict_table_get_col_name(
table, dict_col_get_no(field->col));
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Field type or character set for column %s "
"does not mach referenced column %s close to %s\n",
operation, create_name, columns[err_col], col_name, latest_foreign);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Field type or character set for column %s "
"does not mach referenced column %s close to %s",
operation, create_name, columns[err_col], col_name, latest_foreign);
break;
}
default:
ut_error;
}
}
/*********************************************************************//**
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
@@ -3733,15 +3870,20 @@ dict_create_foreign_constraints_low(
DB_CANNOT_ADD_CONSTRAINT if any foreign
keys are found. */
{
dict_table_t* table;
dict_table_t* referenced_table;
dict_table_t* table_to_alter;
dict_table_t* table = NULL;
dict_table_t* referenced_table = NULL;
dict_table_t* table_to_alter = NULL;
dict_table_t* table_to_create = NULL;
ulint highest_id_so_far = 0;
dict_index_t* index;
dict_foreign_t* foreign;
dict_index_t* index = NULL;
dict_foreign_t* foreign = NULL;
const char* ptr = sql_string;
const char* start_of_latest_foreign = sql_string;
const char* start_of_latest_set = NULL;
FILE* ef = dict_foreign_err_file;
ulint index_error = DB_SUCCESS;
dict_index_t* err_index = NULL;
ulint err_col;
const char* constraint_name;
ibool success;
ulint error;
@@ -3754,29 +3896,68 @@ dict_create_foreign_constraints_low(
ulint n_on_updates;
const dict_col_t*columns[500];
const char* column_names[500];
const char* ref_column_names[500];
const char* referenced_table_name;
const char* create_table_name;
const char* orig;
char create_name[MAX_TABLE_NAME_LEN + 1];
const char operation[8];
ut_ad(mutex_own(&(dict_sys->mutex)));
table = dict_table_get_low(name, DICT_ERR_IGNORE_NONE);
/* First check if we are actually doing an ALTER TABLE, and in that
case look for the table being altered */
ptr = dict_accept(cs, ptr, "ALTER", &success);
strcpy((char *)operation, success ? "Alter " : "Create ");
if (!success) {
orig = ptr;
ptr = dict_scan_to(ptr, "CREATE");
ptr = dict_scan_to(ptr, "TABLE");
ptr = dict_accept(cs, ptr, "TABLE", &success);
if (success) {
ptr = dict_scan_table_name(cs, ptr, &table_to_create, name,
&success, heap, &create_table_name);
}
if (success) {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
create_table_name, strlen(create_table_name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
ptr = orig;
} else {
char *bufend;
ptr = orig;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
name, strlen(name), trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
}
goto loop;
}
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef,
"Cannot find the table in the internal"
" data dictionary of InnoDB.\n"
"Create table statement:\n%s\n", sql_string);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.\n",
operation, create_name, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_ERROR,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.",
operation, create_name, create_name, start_of_latest_foreign);
return(DB_ERROR);
}
/* First check if we are actually doing an ALTER TABLE, and in that
case look for the table being altered */
ptr = dict_accept(cs, ptr, "ALTER", &success);
/* If not alter table jump to loop */
if (!success) {
goto loop;
@@ -3791,13 +3972,40 @@ dict_create_foreign_constraints_low(
/* We are doing an ALTER TABLE: scan the table name we are altering */
orig = ptr;
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
&success, heap, &referenced_table_name);
if (table_to_alter) {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
table_to_alter->name, strlen(table_to_alter->name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
} else {
char *bufend;
bufend = innobase_convert_name((char *)create_name, MAX_TABLE_NAME_LEN,
referenced_table_name, strlen(referenced_table_name),
trx->mysql_thd, TRUE);
create_name[bufend-create_name]='\0';
}
if (!success) {
fprintf(stderr,
"InnoDB: Error: could not find"
" the table being ALTERED in:\n%s\n",
sql_string);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.\n",
operation, create_name, create_name, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_ERROR,
"%s table %s with foreign key constraint"
" failed. Table %s not found from data dictionary."
" Error close to %s.",
operation, create_name, create_name, orig);
return(DB_ERROR);
}
@@ -3863,7 +4071,19 @@ loop:
if so, immediately reject the command if the table is a
temporary one. For now, this kludge will work. */
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s table %s with foreign key constraint"
" failed. Temporary tables can't have foreign key constraints."
" Error close to %s.\n",
operation, create_name, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Temporary tables can't have foreign key constraints."
" Error close to %s.",
operation, create_name, start_of_latest_foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3899,11 +4119,21 @@ loop:
if (!success) {
/* MySQL allows also an index id before the '('; we
skip it */
orig = ptr;
ptr = dict_skip_word(cs, ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3923,15 +4153,26 @@ loop:
/* Scan the columns in the first list */
col_loop1:
ut_a(i < (sizeof column_names) / sizeof *column_names);
orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
heap, column_names + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve column name close to:\n%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3943,11 +4184,22 @@ col_loop1:
goto col_loop1;
}
orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -3955,27 +4207,41 @@ col_loop1:
as the first fields and in the right order */
index = dict_foreign_find_index(table, column_names, i,
NULL, TRUE, FALSE);
NULL, TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
dict_foreign_error_report_low(ef, create_name);
fputs("There is no index in table ", ef);
ut_print_name(ef, NULL, TRUE, name);
ut_print_name(ef, NULL, TRUE, create_name);
fprintf(ef, " where the columns appear\n"
"as the first columns. Constraint:\n%s\n"
"See " REFMAN "innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CHILD_NO_INDEX);
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
column_names, index_error, err_col, err_index, table, ef);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
if (!success || !my_isspace(cs, *ptr)) {
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4024,24 +4290,50 @@ col_loop1:
checking of foreign key constraints! */
if (!success || (!referenced_table && trx->check_foreigns)) {
char buf[MAX_TABLE_NAME_LEN + 1] = "";
char* bufend;
bufend = innobase_convert_name(buf, MAX_TABLE_NAME_LEN,
referenced_table_name, strlen(referenced_table_name),
trx->mysql_thd, TRUE);
buf[bufend - buf] = '\0';
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
"close to %s.",
operation, create_name, buf, start_of_latest_foreign);
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve table name close to:\n"
"%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint failed. Referenced table %s not found in the data dictionary "
"close to %s.\n",
operation, create_name, buf, start_of_latest_foreign);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "(", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4049,20 +4341,29 @@ col_loop1:
i = 0;
col_loop2:
orig = ptr;
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
heap, column_names + i);
heap, ref_column_names + i);
i++;
if (!success) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\nCannot resolve column name close to:\n"
"%s\n",
start_of_latest_foreign, ptr);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, orig);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, orig);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4072,13 +4373,23 @@ col_loop2:
goto col_loop2;
}
orig = ptr;
ptr = dict_accept(cs, ptr, ")", &success);
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s. Too few referenced columns\n",
operation, create_name, start_of_latest_foreign, orig);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s. Too few referenced columns, you have %d when you should have %d.",
operation, create_name, start_of_latest_foreign, orig, i, foreign->n_fields);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4088,6 +4399,7 @@ col_loop2:
scan_on_conditions:
/* Loop here as long as we can find ON ... conditions */
start_of_latest_set = ptr;
ptr = dict_accept(cs, ptr, "ON", &success);
if (!success) {
@@ -4098,13 +4410,24 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "DELETE", &success);
if (!success) {
orig = ptr;
ptr = dict_accept(cs, ptr, "UPDATE", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4136,12 +4459,22 @@ scan_on_conditions:
ptr = dict_accept(cs, ptr, "NO", &success);
if (success) {
orig = ptr;
ptr = dict_accept(cs, ptr, "ACTION", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(
name, start_of_latest_foreign, ptr);
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4155,42 +4488,73 @@ scan_on_conditions:
goto scan_on_conditions;
}
orig = ptr;
ptr = dict_accept(cs, ptr, "SET", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
orig = ptr;
ptr = dict_accept(cs, ptr, "NULL", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
dict_foreign_report_syntax_err(
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. Foreign key constraint parse error in %s"
" close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
return(DB_CANNOT_ADD_CONSTRAINT);
}
for (j = 0; j < foreign->n_fields; j++) {
if ((dict_index_get_nth_col(foreign->foreign_index, j)->prtype)
& DATA_NOT_NULL) {
const dict_col_t* col
= dict_index_get_nth_col(foreign->foreign_index, j);
const char* col_name = dict_table_get_col_name(foreign->foreign_index->table,
dict_col_get_no(col));
/* It is not sensible to define SET NULL
if the column is not allowed to be NULL! */
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
"You have defined a SET NULL condition"
" though some of the\n"
"columns are defined as NOT NULL.\n",
start_of_latest_foreign);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
" in %s close to %s.\n",
operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have defined a SET NULL condition but column %s is defined as NOT NULL"
" in %s close to %s.",
operation, create_name, col_name, start_of_latest_foreign, start_of_latest_set);
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@@ -4207,16 +4571,22 @@ try_find_index:
if (n_on_deletes > 1 || n_on_updates > 1) {
/* It is an error to define more than 1 action */
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
fprintf(ef, "%s:\n"
"You have twice an ON DELETE clause"
" or twice an ON UPDATE clause.\n",
start_of_latest_foreign);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef,
"%s table %s with foreign key constraint"
" failed. You have more than one on delete or on update clause"
" in %s close to %s.\n",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
mutex_exit(&dict_foreign_err_mutex);
ib_push_warning(trx, DB_CANNOT_ADD_CONSTRAINT,
"%s table %s with foreign key constraint"
" failed. You have more than one on delete or on update clause"
" in %s close to %s.",
operation, create_name, start_of_latest_foreign, start_of_latest_set);
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@@ -4226,13 +4596,13 @@ try_find_index:
if (referenced_table) {
index = dict_foreign_find_index(referenced_table,
column_names, i,
ref_column_names, i,
foreign->foreign_index,
TRUE, FALSE);
TRUE, FALSE, &index_error, &err_col, &err_index);
if (!index) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
dict_foreign_error_report_low(ef, name);
dict_foreign_error_report_low(ef, create_name);
fprintf(ef, "%s:\n"
"Cannot find an index in the"
" referenced table where the\n"
@@ -4250,9 +4620,13 @@ try_find_index:
"innodb-foreign-key-constraints.html\n"
"for correct foreign key definition.\n",
start_of_latest_foreign);
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
column_names, index_error, err_col, err_index, referenced_table, ef);
mutex_exit(&dict_foreign_err_mutex);
return(DB_PARENT_NO_INDEX);
return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
ut_a(trx->check_foreigns == FALSE);
@@ -4270,7 +4644,7 @@ try_find_index:
i * sizeof(void*));
for (i = 0; i < foreign->n_fields; i++) {
foreign->referenced_col_names[i]
= mem_heap_strdup(foreign->heap, column_names[i]);
= mem_heap_strdup(foreign->heap, ref_column_names[i]);
}
/* We found an ok constraint definition: add to the lists */
@@ -5815,7 +6189,8 @@ dict_table_replace_index_in_foreign_list(
foreign->referenced_table,
foreign->referenced_col_names,
foreign->n_fields, index,
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
NULL, NULL, NULL);
ut_ad(new_index || !trx->check_foreigns);
ut_ad(!new_index || new_index->table == index->table);

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2000, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -1910,6 +1910,7 @@ check_trx_exists(
if (trx == NULL) {
trx = innobase_trx_allocate(thd);
thd_set_ha_data(thd, innodb_hton_ptr, trx);
} else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
mem_analyze_corruption(trx);
ut_error;
@@ -10169,6 +10170,13 @@ ha_innobase::estimate_rows_upper_bound(void)
estimate = 2 * local_data_file_length /
dict_index_calc_min_rec_len(index);
/* Set num_rows less than MERGEBUFF to simulate the case where we do
not have enough space to merge the externally sorted file blocks. */
DBUG_EXECUTE_IF("set_num_rows_lt_MERGEBUFF",
estimate = 2;
DBUG_SET("-d,set_num_rows_lt_MERGEBUFF");
);
prebuilt->trx->op_info = (char*)"";
DBUG_RETURN((ha_rows) estimate);
@@ -10448,17 +10456,6 @@ ha_innobase::info_low(
prebuilt->trx->op_info = "returning various info to MySQL";
}
my_snprintf(path, sizeof(path), "%s/%s%s",
mysql_data_home, ib_table->name, reg_ext);
unpack_filename(path,path);
/* Note that we do not know the access time of the table,
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
if (os_file_get_status(path,&stat_info)) {
stats.create_time = (ulong) stat_info.ctime;
}
}
if (flag & HA_STATUS_VARIABLE) {
@@ -10702,6 +10699,20 @@ ha_innobase::info_low(
}
dict_table_stats_unlock(ib_table, RW_S_LATCH);
my_snprintf(path, sizeof(path), "%s/%s%s",
mysql_data_home,
table->s->normalized_path.str,
reg_ext);
unpack_filename(path,path);
/* Note that we do not know the access time of the table,
nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
if (os_file_get_status(path,&stat_info)) {
stats.create_time = (ulong) stat_info.ctime;
}
}
if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
@@ -15514,3 +15525,28 @@ ha_innobase::idx_cond_push(
DBUG_RETURN(NULL);
}
/********************************************************************//**
Helper function to push warnings from InnoDB internals to SQL-layer. */
extern "C" UNIV_INTERN
void
ib_push_warning(
trx_t* trx, /*!< in: trx */
ulint error, /*!< in: error code to push as warning */
const char *format,/*!< in: warning message */
...)
{
va_list args;
THD *thd = (THD *)trx->mysql_thd;
char *buf;
#define MAX_BUF_SIZE 4*1024
va_start(args, format);
buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME));
vsprintf(buf,format, args);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
convert_error_code_to_mysql(error, 0, thd),
buf);
my_free(buf);
va_end(args);
}

View File

@@ -121,6 +121,17 @@ UNIV_INTERN
ulint
dict_create_or_check_foreign_constraint_tables(void);
/*================================================*/
/********************************************************************//**
Construct foreign key constraint defintion from data dictionary information.
*/
UNIV_INTERN
char*
dict_foreign_def_get(
/*=================*/
dict_foreign_t* foreign,/*!< in: foreign */
trx_t* trx); /*!< in: trx */
/********************************************************************//**
Adds foreign key definitions to data dictionary tables in the database. We
look at table->foreign_list, and also generate names to constraints that were

View File

@@ -366,5 +366,14 @@ innobase_convert_to_filename_charset(
const char* from, /* in: identifier to convert */
ulint len); /* in: length of 'to', in bytes */
/********************************************************************//**
Helper function to push warnings from InnoDB internals to SQL-layer. */
UNIV_INTERN
void
ib_push_warning(
trx_t* trx, /*!< in: trx */
ulint error, /*!< in: error code to push as warning */
const char *format,/*!< in: warning message */
...);
#endif

View File

@@ -64,10 +64,10 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 37.2
#define PERCONA_INNODB_VERSION 37.3
#endif
#define INNODB_VERSION_STR "5.5.43-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
#define INNODB_VERSION_STR "5.5.44-MariaDB-" IB_TO_STR(PERCONA_INNODB_VERSION)
#define REFMAN "http://dev.mysql.com/doc/refman/" \
IB_TO_STR(MYSQL_MAJOR_VERSION) "." \

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Percona Inc.
@@ -2511,9 +2511,9 @@ innobase_shutdown_for_mysql(void)
ibuf_close();
log_shutdown();
lock_sys_close();
trx_sys_file_format_close();
trx_sys_close();
lock_sys_close();
mutex_free(&srv_monitor_file_mutex);
mutex_free(&srv_dict_tmpfile_mutex);

View File

@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2013, 2014, MariaDB Corporation. All Rights Reserved.
@@ -1114,8 +1114,9 @@ sync_array_output_info(
os_thread_id_t r;
fprintf(file,
"OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
(long) arr->res_count, (long) arr->sg_count);
"OS WAIT ARRAY INFO: reservation count " ULINTPF
", signal count " ULINTPF "\n",
arr->res_count, arr->sg_count);
i = 0;
count = 0;

View File

@@ -771,9 +771,9 @@ trx_lists_init_at_db_start(void)
" anyway.\n");
trx->state = TRX_ACTIVE;
trx_reserve_descriptor(
trx);
}
trx_reserve_descriptor(trx);
} else {
trx->state
= TRX_COMMITTED_IN_MEMORY;

View File

@@ -21,31 +21,42 @@
static my_bool ssl_algorithms_added = FALSE;
static my_bool ssl_error_strings_loaded= FALSE;
/* the function below was generated with "openssl dhparam -2 -C 1024" */
/* the function below was generated with "openssl dhparam -2 -C 2048" */
static
DH *get_dh1024()
DH *get_dh2048()
{
static unsigned char dh1024_p[]={
0xEC,0x46,0x7E,0xF9,0x4E,0x10,0x29,0xDC,0x44,0x97,0x71,0xFD,
0x71,0xC6,0x9F,0x0D,0xD1,0x09,0xF6,0x58,0x6F,0xAD,0xCA,0xF4,
0x37,0xD5,0xC3,0xBD,0xC3,0x9A,0x51,0x66,0x2C,0x58,0xBD,0x02,
0xBD,0xBA,0xBA,0xFC,0xE7,0x0E,0x5A,0xE5,0x97,0x81,0xC3,0xF3,
0x28,0x2D,0xAD,0x00,0x91,0xEF,0xF8,0xF0,0x5D,0xE9,0xE7,0x18,
0xE2,0xAD,0xC4,0x70,0xC5,0x3C,0x12,0x8A,0x80,0x6A,0x9F,0x3B,
0x00,0xA2,0x8F,0xA9,0x26,0xB0,0x0E,0x7F,0xED,0xF6,0xC2,0x03,
0x81,0xB5,0xC5,0x41,0xD0,0x00,0x2B,0x21,0xD4,0x4B,0x74,0xA6,
0xD7,0x1A,0x0E,0x82,0xC8,0xEE,0xD4,0xB1,0x6F,0xB4,0x79,0x01,
0x8A,0xF1,0x12,0xD7,0x3C,0xFD,0xCB,0x9B,0xAE,0x1C,0xA9,0x0F,
0x3D,0x0F,0xF8,0xD6,0x7D,0xDE,0xD6,0x0B,
static unsigned char dh2048_p[]={
0xA1,0xBB,0x7C,0x20,0xC5,0x5B,0xC0,0x7B,0x21,0x8B,0xD6,0xA8,
0x15,0xFC,0x3B,0xBA,0xAB,0x9F,0xDF,0x68,0xC4,0x79,0x78,0x0D,
0xC1,0x12,0x64,0xE4,0x15,0xC9,0x66,0xDB,0xF6,0xCB,0xB3,0x39,
0x02,0x5B,0x78,0x62,0xFB,0x09,0xAE,0x09,0x6B,0xDD,0xD4,0x5D,
0x97,0xBC,0xDC,0x7F,0xE6,0xD6,0xF1,0xCB,0xF5,0xEB,0xDA,0xA7,
0x2E,0x5A,0x43,0x2B,0xE9,0x40,0xE2,0x85,0x00,0x1C,0xC0,0x0A,
0x98,0x77,0xA9,0x31,0xDE,0x0B,0x75,0x4D,0x1E,0x1F,0x16,0x83,
0xCA,0xDE,0xBD,0x21,0xFC,0xC1,0x82,0x37,0x36,0x33,0x0B,0x66,
0x06,0x3C,0xF3,0xAF,0x21,0x57,0x57,0x80,0xF6,0x94,0x1B,0xA9,
0xD4,0xF6,0x8F,0x18,0x62,0x0E,0xC4,0x22,0xF9,0x5B,0x62,0xCC,
0x3F,0x19,0x95,0xCF,0x4B,0x00,0xA6,0x6C,0x0B,0xAF,0x9F,0xD5,
0xFA,0x3D,0x6D,0xDA,0x30,0x83,0x07,0x91,0xAC,0x15,0xFF,0x8F,
0x59,0x54,0xEA,0x25,0xBC,0x4E,0xEB,0x6A,0x54,0xDF,0x75,0x09,
0x72,0x0F,0xEF,0x23,0x70,0xE0,0xA8,0x04,0xEA,0xFF,0x90,0x54,
0xCD,0x84,0x18,0xC0,0x75,0x91,0x99,0x0F,0xA1,0x78,0x0C,0x07,
0xB7,0xC5,0xDE,0x55,0x06,0x7B,0x95,0x68,0x2C,0x33,0x39,0xBC,
0x2C,0xD0,0x6D,0xDD,0xFA,0xDC,0xB5,0x8F,0x82,0x39,0xF8,0x67,
0x44,0xF1,0xD8,0xF7,0x78,0x11,0x9A,0x77,0x9B,0x53,0x47,0xD6,
0x2B,0x5D,0x67,0xB8,0xB7,0xBC,0xC1,0xD7,0x79,0x62,0x15,0xC2,
0xC5,0x83,0x97,0xA7,0xF8,0xB4,0x9C,0xF6,0x8F,0x9A,0xC7,0xDA,
0x1B,0xBB,0x87,0x07,0xA7,0x71,0xAD,0xB2,0x8A,0x50,0xF8,0x26,
0x12,0xB7,0x3E,0x0B,
};
static unsigned char dh1024_g[]={
static unsigned char dh2048_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh1024_p,sizeof(dh1024_p),NULL);
dh->g=BN_bin2bn(dh1024_g,sizeof(dh1024_g),NULL);
dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return(dh);
@@ -259,7 +270,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
}
/* DH stuff */
dh=get_dh1024();
dh=get_dh2048();
SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh);
DH_free(dh);