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:
2
VERSION
2
VERSION
@@ -1,4 +1,4 @@
|
||||
MYSQL_VERSION_MAJOR=5
|
||||
MYSQL_VERSION_MINOR=5
|
||||
MYSQL_VERSION_PATCH=44
|
||||
MYSQL_VERSION_PATCH=45
|
||||
MYSQL_VERSION_EXTRA=
|
||||
|
@@ -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);
|
||||
|
@@ -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},
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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= [];
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
#
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
156
mysql-test/r/sp-group.result
Normal file
156
mysql-test/r/sp-group.result
Normal 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;
|
@@ -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';
|
||||
|
@@ -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
|
||||
|
@@ -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.
|
||||
# -----------------------------------------------------------------
|
||||
|
@@ -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);
|
||||
|
@@ -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`
|
||||
|
13
mysql-test/suite/innodb/r/add_constraint.result
Normal file
13
mysql-test/suite/innodb/r/add_constraint.result
Normal 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;
|
105
mysql-test/suite/innodb/r/innodb-fk-warnings.result
Normal file
105
mysql-test/suite/innodb/r/innodb-fk-warnings.result
Normal 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;
|
@@ -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;
|
||||
|
22
mysql-test/suite/innodb/r/innodb_uninstall.result
Normal file
22
mysql-test/suite/innodb/r/innodb_uninstall.result
Normal 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
|
21
mysql-test/suite/innodb/t/add_constraint.test
Normal file
21
mysql-test/suite/innodb/t/add_constraint.test
Normal 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;
|
130
mysql-test/suite/innodb/t/innodb-fk-warnings.test
Normal file
130
mysql-test/suite/innodb/t/innodb-fk-warnings.test
Normal 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;
|
3
mysql-test/suite/innodb/t/innodb_uninstall.opt
Normal file
3
mysql-test/suite/innodb/t/innodb_uninstall.opt
Normal file
@@ -0,0 +1,3 @@
|
||||
--ignore-builtin-innodb
|
||||
--loose-innodb
|
||||
|
58
mysql-test/suite/innodb/t/innodb_uninstall.test
Normal file
58
mysql-test/suite/innodb/t/innodb_uninstall.test
Normal 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
|
||||
|
||||
|
33
mysql-test/suite/ndb/r/ndb_restore_discover.result
Normal file
33
mysql-test/suite/ndb/r/ndb_restore_discover.result
Normal 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;
|
70
mysql-test/suite/ndb/t/ndb_restore_discover.test
Normal file
70
mysql-test/suite/ndb/t/ndb_restore_discover.test
Normal 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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -17,3 +17,6 @@ commit;
|
||||
--source include/show_binlog_events.inc
|
||||
drop table t1;
|
||||
uninstall plugin innodb;
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
|
@@ -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
|
@@ -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
187
mysql-test/t/sp-group.test
Normal 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;
|
@@ -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
|
||||
|
@@ -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 # -----------------------------------------------------------------
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
|
58
sql/item.cc
58
sql/item.cc
@@ -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(). */
|
||||
|
@@ -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; }
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
25
sql/log.cc
25
sql/log.cc
@@ -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
|
||||
{
|
||||
|
@@ -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);
|
||||
/*
|
||||
|
@@ -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;
|
||||
|
@@ -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, (¶m));
|
||||
|
||||
/*
|
||||
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, (¶m));
|
||||
|
||||
/*
|
||||
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,
|
||||
(¶m, log_info->log_file, log_info->log_pos, flags));
|
||||
return ret;
|
||||
|
@@ -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;
|
||||
|
10
sql/slave.cc
10
sql/slave.cc
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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));
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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()));
|
||||
|
@@ -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++))
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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];
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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) "." \
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user