Merge commit '96badb16afcf' into 10.0
Conflicts: client/mysql_upgrade.c mysql-test/r/func_misc.result mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result mysql-test/suite/innodb/r/innodb-fk.result mysql-test/t/subselect_sj_mat.test sql/item.cc sql/item_func.cc sql/log.cc sql/log_event.cc sql/rpl_utility.cc sql/slave.cc sql/sql_class.cc sql/sql_class.h sql/sql_select.cc storage/innobase/dict/dict0crea.c storage/innobase/dict/dict0dict.c storage/innobase/handler/ha_innodb.cc storage/xtradb/dict/dict0crea.c storage/xtradb/dict/dict0dict.c storage/xtradb/handler/ha_innodb.cc vio/viosslfactories.c
This commit is contained in:
commit
9a5787db51
@ -1095,7 +1095,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())
|
||||
@ -1124,6 +1124,7 @@ int main(int argc, char **argv)
|
||||
|
||||
DBUG_ASSERT(phase == phases_total);
|
||||
|
||||
end:
|
||||
free_used_memory();
|
||||
my_end(my_end_arg);
|
||||
exit(0);
|
||||
|
@ -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);
|
||||
|
@ -4862,6 +4862,7 @@ sub extract_warning_lines ($$) {
|
||||
qr|InnoDB: Setting thread \d+ nice to \d+ failed, current nice \d+, errno 13|, # setpriority() fails under valgrind
|
||||
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,7 +361,18 @@ set optimizer_switch=@optimizer_switch_save;
|
||||
drop view v_merge, vm;
|
||||
drop table t1,tv;
|
||||
#
|
||||
# GET_LOCK, RELEASE_LOCK, IS_USED_LOCK functions test
|
||||
# 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
|
||||
#
|
||||
# IS_USED_LOCK, IS_FREE_LOCK: the lock is not acquired
|
||||
# Note: IS_USED_LOCK returns NULL if the lock is unused
|
||||
|
@ -19,3 +19,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
|
||||
|
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
|
||||
#
|
||||
# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||
|
@ -2185,6 +2185,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
|
||||
#
|
||||
# MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||
|
@ -259,7 +259,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);
|
||||
|
@ -243,7 +243,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;
|
||||
@ -293,7 +293,7 @@ master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; insert t0 select * from t1
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||
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 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb
|
||||
|
112
mysql-test/suite/innodb/r/innodb-fk-warnings.result
Normal file
112
mysql-test/suite/innodb/r/innodb-fk-warnings.result
Normal file
@ -0,0 +1,112 @@
|
||||
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 "Duplicate key on write or update")
|
||||
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 "Duplicate key on write or update")
|
||||
Warning 1022 Can't write; duplicate key in table 't2'
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Error 1005 Can't create table `test`.`t2` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
alter table t1 add foreign key(b) references t1(a);
|
||||
ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 42000: Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Error 1239 Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match
|
||||
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 42000: Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Error 1239 Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
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 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
CREATE TABLE t2 (
|
||||
@ -63,6 +65,7 @@ ALTER TABLE t2 ADD CONSTRAINT fk3 FOREIGN KEY (f3) REFERENCES t3 (id) ON DELETE
|
||||
ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
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 `test`.`#sql-temporary` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||
Warning 1215 Cannot add foreign key constraint
|
||||
drop table t2;
|
||||
|
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
|
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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1005
|
||||
alter table t2 add constraint b foreign key (b) references t2(b);
|
||||
--replace_regex /#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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1005
|
||||
alter table t1 add constraint c1 foreign key (f1) references t11(f1);
|
||||
--replace_regex /#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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1005
|
||||
create temporary table t2(a int, foreign key(a) references t1(a)) engine=innodb;
|
||||
--replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
show warnings;
|
||||
--replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1005
|
||||
alter table t1 add foreign key(b) references t1(a);
|
||||
--replace_regex /#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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1239
|
||||
alter table t1 add foreign key(a,b) references t1(a);
|
||||
--replace_regex /#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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
--error 1239
|
||||
alter table t1 add foreign key(a) references t1(a,b);
|
||||
--replace_regex /#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 /#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 /#sql-[0-9a-f_]*`/#sql-temporary`/
|
||||
show warnings;
|
||||
--replace_regex /#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 /#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 /#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 /#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
|
||||
|
||||
|
@ -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 # GET_LOCK, RELEASE_LOCK, IS_USED_LOCK functions test
|
||||
|
@ -16,3 +16,6 @@ commit;
|
||||
--source include/show_binlog_events.inc
|
||||
drop table t1;
|
||||
uninstall plugin innodb;
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
|
@ -15,7 +15,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,8 +1841,23 @@ 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
|
||||
--echo #
|
||||
--echo # MDEV-7220: Materialization strategy is not used for REPLACE ... SELECT
|
||||
--echo #
|
||||
|
44
sql/item.cc
44
sql/item.cc
@ -4363,18 +4363,23 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
|
||||
Item_ident *resolved_item,
|
||||
Item_ident *mark_item)
|
||||
{
|
||||
const char *db_name= (resolved_item->db_name ?
|
||||
resolved_item->db_name : "");
|
||||
const char *table_name= (resolved_item->table_name ?
|
||||
resolved_item->table_name : "");
|
||||
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))
|
||||
return TRUE;
|
||||
}
|
||||
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 : "");
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_WARN_FIELD_RESOLVED, ER(ER_WARN_FIELD_RESOLVED),
|
||||
db_name, (db_name[0] ? "." : ""),
|
||||
@ -4382,7 +4387,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);
|
||||
}
|
||||
|
||||
|
||||
@ -4831,7 +4836,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)
|
||||
{
|
||||
@ -5247,9 +5252,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:
|
||||
@ -6730,7 +6736,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();
|
||||
}
|
||||
|
||||
@ -6774,7 +6780,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();
|
||||
}
|
||||
|
||||
@ -6849,7 +6855,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,
|
||||
@ -6867,7 +6877,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;
|
||||
}
|
||||
|
||||
@ -7002,7 +7012,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
|
||||
@ -7019,7 +7029,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(). */
|
||||
|
@ -657,7 +657,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 */
|
||||
@ -3356,6 +3356,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 */
|
||||
@ -3365,7 +3366,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
|
||||
@ -3388,7 +3389,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; }
|
||||
|
@ -4266,6 +4266,24 @@ longlong Item_func_get_lock::val_int()
|
||||
it's not guaranteed to be same as on master.
|
||||
*/
|
||||
if (thd->slave_thread)
|
||||
{
|
||||
null_value= 0;
|
||||
}
|
||||
|
||||
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, Sql_condition::WARN_LEVEL_WARN,
|
||||
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
|
||||
"timeout", buf, "get_lock");
|
||||
null_value= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
{
|
||||
null_value= 0;
|
||||
DBUG_RETURN(1);
|
||||
|
@ -477,6 +477,7 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent,
|
||||
{
|
||||
List_iterator_fast<Ref_to_outside> it(upper_refs);
|
||||
Ref_to_outside *upper;
|
||||
DBUG_ENTER("recalc_used_tables");
|
||||
|
||||
used_tables_cache= 0;
|
||||
while ((upper= it++))
|
||||
@ -536,6 +537,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;
|
||||
}
|
||||
|
||||
|
||||
@ -2002,7 +2005,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)
|
||||
{
|
||||
@ -2012,7 +2015,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;
|
||||
|
@ -3527,9 +3527,16 @@ 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))
|
||||
DBUG_RETURN(TRUE);
|
||||
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));
|
||||
memcpy(ref_pointer_array, args, arg_count * sizeof(Item*));
|
||||
if (!ref_pointer_array ||
|
||||
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
|
||||
|
33
sql/log.cc
33
sql/log.cc
@ -4129,6 +4129,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included)
|
||||
int error;
|
||||
char *to_purge_if_included= NULL;
|
||||
inuse_relaylog *ir;
|
||||
ulonglong log_space_reclaimed= 0;
|
||||
DBUG_ENTER("purge_first_log");
|
||||
|
||||
DBUG_ASSERT(is_open());
|
||||
@ -4200,17 +4201,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
|
||||
@ -4259,8 +4256,8 @@ 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
|
||||
the amount of log space freed
|
||||
@param reclaimeed_log_space If not null, increment this variable to
|
||||
the amount of log space freed
|
||||
|
||||
@note
|
||||
If any of the logs before the deleted one is in use,
|
||||
@ -4276,10 +4273,10 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads
|
||||
*/
|
||||
|
||||
int MYSQL_BIN_LOG::purge_logs(const char *to_log,
|
||||
bool included,
|
||||
bool need_mutex,
|
||||
bool need_update_threads,
|
||||
ulonglong *decrease_log_space)
|
||||
bool included,
|
||||
bool need_mutex,
|
||||
bool need_update_threads,
|
||||
ulonglong *reclaimed_space)
|
||||
{
|
||||
int error= 0;
|
||||
bool exit_loop= 0;
|
||||
@ -4343,7 +4340,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();
|
||||
@ -4448,7 +4445,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");
|
||||
@ -4568,8 +4565,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
|
||||
{
|
||||
|
@ -2768,6 +2768,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;
|
||||
|
@ -39,8 +39,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)
|
||||
{
|
||||
@ -144,13 +142,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;
|
||||
}
|
||||
|
||||
@ -196,27 +187,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;
|
||||
}
|
||||
@ -224,27 +215,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);
|
||||
|
||||
param.log_file= log_info ? log_info->log_file : 0;
|
||||
log_info= thd->semisync_info;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -255,25 +246,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;
|
||||
|
@ -947,6 +947,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
{
|
||||
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);
|
||||
|
||||
@ -956,8 +957,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
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:
|
||||
@ -996,6 +996,18 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
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;
|
||||
}
|
||||
@ -1003,12 +1015,13 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
||||
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
||||
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
||||
binlog_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
@ -4523,9 +4523,7 @@ pthread_handler_t handle_slave_sql(void *arg)
|
||||
rli->parallel.reset();
|
||||
|
||||
//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);
|
||||
|
||||
serial_rgi->gtid_sub_id= 0;
|
||||
serial_rgi->gtid_pending= false;
|
||||
@ -6626,14 +6624,8 @@ static Log_event* next_event(rpl_group_info *rgi, ulonglong *event_size)
|
||||
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_driver_thd);
|
||||
// re-acquire data lock since we released it earlier
|
||||
|
@ -6583,6 +6583,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
|
||||
|
@ -960,6 +960,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;
|
||||
@ -1395,6 +1396,7 @@ void THD::init(void)
|
||||
bzero((char *) &org_status_var, sizeof(org_status_var));
|
||||
start_bytes_received= 0;
|
||||
last_commit_gtid.seq_no= 0;
|
||||
status_in_global= 0;
|
||||
|
||||
if (variables.sql_log_bin)
|
||||
variables.option_bits|= OPTION_BIN_LOG;
|
||||
@ -1500,6 +1502,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,
|
||||
@ -1630,6 +1633,7 @@ THD::~THD()
|
||||
mysql_audit_free_thd(this);
|
||||
if (rgi_slave)
|
||||
rgi_slave->cleanup_after_session();
|
||||
my_free(semisync_info);
|
||||
#endif
|
||||
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
|
@ -64,7 +64,6 @@ class Reprepare_observer;
|
||||
class Relay_log_info;
|
||||
struct rpl_group_info;
|
||||
class Rpl_filter;
|
||||
|
||||
class Query_log_event;
|
||||
class Load_log_event;
|
||||
class Slave_log_event;
|
||||
@ -75,6 +74,7 @@ class Parser_state;
|
||||
class Rows_log_event;
|
||||
class Sroutine_hash_entry;
|
||||
class user_var_entry;
|
||||
struct Trans_binlog_info;
|
||||
class rpl_io_thread_info;
|
||||
class rpl_sql_thread_info;
|
||||
|
||||
@ -1959,6 +1959,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;
|
||||
|
||||
@ -2027,11 +2030,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.
|
||||
@ -2040,6 +2043,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();
|
||||
|
||||
@ -3687,6 +3693,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);
|
||||
}
|
||||
|
||||
|
@ -1910,7 +1910,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;
|
||||
@ -1918,6 +1917,7 @@ void st_select_lex::init_select()
|
||||
m_non_agg_field_used= false;
|
||||
m_agg_func_used= false;
|
||||
name_visibility_map= 0;
|
||||
join= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -823,8 +823,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;
|
||||
|
||||
|
@ -5185,6 +5185,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
|
||||
KEY_FIELD *key_fields, *end, *field;
|
||||
uint sz;
|
||||
uint m= MY_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;
|
||||
@ -5231,7 +5233,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
|
||||
sz= MY_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 +
|
||||
@ -5241,7 +5243,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
|
||||
|
||||
if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64,
|
||||
MYF(MY_THREAD_SPECIFIC)))
|
||||
return TRUE;
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (cond)
|
||||
{
|
||||
@ -5291,16 +5293,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);
|
||||
}
|
||||
|
||||
|
||||
@ -21544,7 +21546,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++))
|
||||
|
@ -934,6 +934,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:
|
||||
@ -1326,6 +1329,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;
|
||||
|
@ -3512,7 +3512,10 @@ void calc_sum_of_all_status(STATUS_VAR *to)
|
||||
|
||||
/* Add to this status from existing threads */
|
||||
while ((tmp= it++))
|
||||
add_to_status(to, &tmp->status_var);
|
||||
{
|
||||
if (!tmp->status_in_global)
|
||||
add_to_status(to, &tmp->status_var);
|
||||
}
|
||||
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
DBUG_VOID_RETURN;
|
||||
|
@ -222,7 +222,7 @@ TEST_join(JOIN *join)
|
||||
|
||||
#define FT_KEYPART (MAX_FIELDS+10)
|
||||
|
||||
void print_keyuse(KEYUSE *keyuse)
|
||||
static void print_keyuse(KEYUSE *keyuse)
|
||||
{
|
||||
char buff[256];
|
||||
char buf2[64];
|
||||
@ -240,14 +240,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?
|
||||
}
|
||||
|
||||
|
||||
@ -256,9 +253,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1029,7 +1029,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);
|
||||
@ -1040,6 +1039,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);
|
||||
@ -1047,6 +1047,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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -5271,7 +5271,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);
|
||||
}
|
||||
|
@ -1561,6 +1561,104 @@ dict_create_add_foreign_field_to_dictionary(
|
||||
table_name, foreign->id, 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 = (char *)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 = (char *)mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
|
||||
char* fieldbuf2 = (char *)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 foreign key definition to the data dictionary tables.
|
||||
@return error code or DB_SUCCESS */
|
||||
@ -1568,6 +1666,7 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
const char* name, /*!< in: table name */
|
||||
const dict_foreign_t* foreign,/*!< in: foreign key */
|
||||
trx_t* trx) /*!< in/out: dictionary transaction */
|
||||
@ -1595,6 +1694,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((dict_foreign_t*)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);
|
||||
}
|
||||
|
||||
@ -1603,6 +1725,26 @@ dict_create_add_foreign_to_dictionary(
|
||||
i, name, 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((dict_foreign_t*)foreign, trx);
|
||||
dict_foreign_def_get_fields((dict_foreign_t*)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);
|
||||
}
|
||||
@ -1649,7 +1791,7 @@ dict_create_add_foreigns_to_dictionary(
|
||||
foreign = *it;
|
||||
ut_ad(foreign->id != NULL);
|
||||
|
||||
error = dict_create_add_foreign_to_dictionary(table->name,
|
||||
error = dict_create_add_foreign_to_dictionary((dict_table_t*)table, table->name,
|
||||
foreign, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
@ -3259,6 +3259,11 @@ dict_index_build_internal_fts(
|
||||
}
|
||||
/*====================== FOREIGN KEY PROCESSING ========================*/
|
||||
|
||||
#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
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if a table is referenced by foreign keys.
|
||||
@return TRUE if table is referenced by a foreign key */
|
||||
@ -3413,15 +3418,26 @@ dict_foreign_find_index(
|
||||
/*!< 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;
|
||||
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
|
||||
if (error) {
|
||||
*error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
|
||||
}
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
|
||||
while (index != NULL) {
|
||||
@ -3431,7 +3447,12 @@ dict_foreign_find_index(
|
||||
&& dict_foreign_qualify_index(
|
||||
table, col_names, columns, n_cols,
|
||||
index, types_idx,
|
||||
check_charsets, check_null)) {
|
||||
check_charsets, check_null,
|
||||
error, err_col_no,err_index)) {
|
||||
if (error) {
|
||||
*error = DB_SUCCESS;
|
||||
}
|
||||
|
||||
return(index);
|
||||
}
|
||||
|
||||
@ -3536,11 +3557,15 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
if (ref_table && !for_in_cache->referenced_table) {
|
||||
ulint index_error;
|
||||
ulint err_col;
|
||||
dict_index_t *err_index=NULL;
|
||||
|
||||
index = dict_foreign_find_index(
|
||||
ref_table, NULL,
|
||||
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)) {
|
||||
@ -3572,6 +3597,10 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
if (for_table && !for_in_cache->foreign_table) {
|
||||
ulint index_error;
|
||||
ulint err_col;
|
||||
dict_index_t *err_index=NULL;
|
||||
|
||||
index = dict_foreign_find_index(
|
||||
for_table, col_names,
|
||||
for_in_cache->foreign_col_names,
|
||||
@ -3579,7 +3608,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)) {
|
||||
@ -4239,6 +4269,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
|
||||
@ -4251,11 +4283,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
|
||||
@ -4284,16 +4406,21 @@ 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;
|
||||
ulint number = 1;
|
||||
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;
|
||||
dberr_t error;
|
||||
@ -4306,37 +4433,80 @@ 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;
|
||||
dict_foreign_set local_fk_set;
|
||||
dict_foreign_set_free local_fk_set_free(local_fk_set);
|
||||
const char* create_table_name;
|
||||
const char* orig;
|
||||
char create_name[MAX_TABLE_NAME_LEN + 1];
|
||||
char operation[8];
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
table = dict_table_get_low(name);
|
||||
/* First check if we are actually doing an ALTER TABLE, and in that
|
||||
case look for the table being altered */
|
||||
orig = ptr;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "TABLE", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4346,13 +4516,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);
|
||||
}
|
||||
@ -4389,6 +4586,7 @@ loop:
|
||||
of the constraint to system tables. */
|
||||
ptr = ptr1;
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
|
||||
|
||||
ut_a(success);
|
||||
@ -4419,6 +4617,19 @@ loop:
|
||||
if so, immediately reject the command if the table is a
|
||||
temporary one. For now, this kludge will work. */
|
||||
if (reject_fks && !local_fk_set.empty()) {
|
||||
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);
|
||||
}
|
||||
@ -4444,6 +4655,7 @@ loop:
|
||||
|
||||
start_of_latest_foreign = ptr;
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4454,6 +4666,7 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "KEY", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4479,6 +4692,7 @@ loop:
|
||||
}
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "(", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4488,8 +4702,17 @@ loop:
|
||||
ptr = dict_skip_word(cs, ptr, &success);
|
||||
if (!success) {
|
||||
dict_foreign_report_syntax_err(
|
||||
name, start_of_latest_foreign, ptr);
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
"%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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -4516,15 +4739,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);
|
||||
}
|
||||
|
||||
@ -4536,11 +4770,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);
|
||||
}
|
||||
|
||||
@ -4551,27 +4796,41 @@ col_loop1:
|
||||
set to 0 */
|
||||
|
||||
index = dict_foreign_find_index(
|
||||
table, NULL, column_names, i, NULL, TRUE, FALSE);
|
||||
table, NULL, column_names, i,
|
||||
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);
|
||||
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
|
||||
column_names, index_error, err_col, err_index, table, ef);
|
||||
|
||||
return(DB_CHILD_NO_INDEX);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4640,21 +4899,46 @@ 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);
|
||||
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_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);
|
||||
}
|
||||
|
||||
@ -4662,34 +4946,54 @@ 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) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, ",", &success);
|
||||
|
||||
if (success) {
|
||||
goto col_loop2;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, ")", &success);
|
||||
|
||||
if (!success || foreign->n_fields != i) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4699,6 +5003,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) {
|
||||
@ -4706,15 +5011,27 @@ scan_on_conditions:
|
||||
goto try_find_index;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "DELETE", &success);
|
||||
|
||||
if (!success) {
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "UPDATE", &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, 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);
|
||||
}
|
||||
|
||||
@ -4725,12 +5042,14 @@ scan_on_conditions:
|
||||
n_on_deletes++;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
|
||||
|
||||
if (success) {
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "CASCADE", &success);
|
||||
|
||||
if (success) {
|
||||
@ -4743,14 +5062,25 @@ scan_on_conditions:
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "NO", &success);
|
||||
|
||||
if (success) {
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "ACTION", &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, 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);
|
||||
}
|
||||
@ -4764,38 +5094,69 @@ scan_on_conditions:
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "SET", &success);
|
||||
|
||||
if (!success) {
|
||||
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_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! */
|
||||
|
||||
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);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
}
|
||||
@ -4813,11 +5174,20 @@ try_find_index:
|
||||
/* It is an error to define more than 1 action */
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
@ -4829,12 +5199,12 @@ try_find_index:
|
||||
|
||||
if (referenced_table) {
|
||||
index = dict_foreign_find_index(referenced_table, NULL,
|
||||
column_names, i,
|
||||
ref_column_names, i,
|
||||
foreign->foreign_index,
|
||||
TRUE, FALSE);
|
||||
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);
|
||||
fprintf(ef, "%s:\n"
|
||||
"Cannot find an index in the"
|
||||
" referenced table where the\n"
|
||||
@ -4852,9 +5222,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);
|
||||
@ -4873,11 +5247,12 @@ try_find_index:
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Determines whether a string starts with the specified keyword.
|
||||
@return TRUE if str starts with keyword */
|
||||
@ -6029,7 +6404,8 @@ dict_foreign_replace_index(
|
||||
foreign->foreign_table, col_names,
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
|
||||
NULL, NULL, NULL);
|
||||
if (new_index) {
|
||||
ut_ad(new_index->table == index->table);
|
||||
ut_ad(!new_index->to_be_dropped);
|
||||
@ -6053,7 +6429,8 @@ dict_foreign_replace_index(
|
||||
foreign->referenced_table, NULL,
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
|
||||
NULL, NULL, NULL);
|
||||
/* There must exist an alternative index,
|
||||
since this must have been checked earlier. */
|
||||
if (new_index) {
|
||||
@ -6622,10 +6999,17 @@ dict_foreign_qualify_index(
|
||||
/*!< 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 */
|
||||
{
|
||||
if (dict_index_get_n_fields(index) < n_cols) {
|
||||
return(false);
|
||||
@ -6642,11 +7026,21 @@ dict_foreign_qualify_index(
|
||||
if (field->prefix_len != 0) {
|
||||
/* 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 = (dict_index_t*)index;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
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 = (dict_index_t*)index;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
@ -6662,6 +7056,12 @@ dict_foreign_qualify_index(
|
||||
dict_index_get_nth_col(index, i),
|
||||
dict_index_get_nth_col(types_idx, i),
|
||||
check_charsets)) {
|
||||
if (error && err_col_no && err_index) {
|
||||
*error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
|
||||
*err_col_no = i;
|
||||
*err_index = (dict_index_t*)index;
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +417,8 @@ dict_mem_table_col_rename_low(
|
||||
dict_index_t* new_index = dict_foreign_find_index(
|
||||
foreign->foreign_table, NULL,
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, NULL, true, false);
|
||||
foreign->n_fields, NULL, true, false,
|
||||
NULL, NULL, NULL);
|
||||
/* There must be an equivalent index in this case. */
|
||||
ut_ad(new_index != NULL);
|
||||
|
||||
|
@ -2125,6 +2125,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;
|
||||
@ -17633,3 +17634,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. */
|
||||
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, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
@ -824,7 +824,8 @@ innobase_find_fk_index(
|
||||
if (!(index->type & DICT_FTS)
|
||||
&& dict_foreign_qualify_index(
|
||||
table, col_names, columns, n_cols,
|
||||
index, NULL, true, 0)) {
|
||||
index, NULL, true, 0,
|
||||
NULL, NULL, NULL)) {
|
||||
for (ulint i = 0; i < n_drop_index; i++) {
|
||||
if (index == drop_index[i]) {
|
||||
/* Skip to-be-dropped indexes. */
|
||||
@ -1014,7 +1015,8 @@ innobase_get_foreign_key_info(
|
||||
referenced_table, 0,
|
||||
referenced_column_names,
|
||||
i, index,
|
||||
TRUE, FALSE);
|
||||
TRUE, FALSE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_test_no_reference_idx",
|
||||
@ -3317,7 +3319,8 @@ innobase_check_foreign_key_index(
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE,
|
||||
/*check_null=*/FALSE)
|
||||
/*check_null=*/FALSE,
|
||||
NULL, NULL, NULL)
|
||||
&& !innobase_find_equiv_index(
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields,
|
||||
@ -3345,7 +3348,8 @@ innobase_check_foreign_key_index(
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE,
|
||||
/*check_null=*/FALSE)
|
||||
/*check_null=*/FALSE,
|
||||
NULL, NULL, NULL)
|
||||
&& !innobase_find_equiv_index(
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields,
|
||||
@ -4789,7 +4793,8 @@ innobase_update_foreign_try(
|
||||
fk->n_fields, fk->referenced_index, TRUE,
|
||||
fk->type
|
||||
& (DICT_FOREIGN_ON_DELETE_SET_NULL
|
||||
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
|
||||
| DICT_FOREIGN_ON_UPDATE_SET_NULL),
|
||||
NULL, NULL, NULL);
|
||||
if (!fk->foreign_index) {
|
||||
my_error(ER_FK_INCORRECT_OPTION,
|
||||
MYF(0), table_name, fk->id);
|
||||
@ -4801,7 +4806,7 @@ innobase_update_foreign_try(
|
||||
names, while the columns in ctx->old_table have not
|
||||
been renamed yet. */
|
||||
error = dict_create_add_foreign_to_dictionary(
|
||||
ctx->old_table->name, fk, trx);
|
||||
(dict_table_t*)ctx->old_table,ctx->old_table->name, fk, trx);
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_test_cannot_add_fk_system",
|
||||
|
@ -110,6 +110,17 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
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 */
|
||||
|
||||
/********************************************************************//**
|
||||
Generate a foreign key constraint name when it was not named by the user.
|
||||
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
|
||||
@ -174,11 +185,22 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
const char* name, /*!< in: table name */
|
||||
const dict_foreign_t* foreign,/*!< in: foreign key */
|
||||
trx_t* trx) /*!< in/out: dictionary transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/********************************************************************//**
|
||||
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 */
|
||||
|
||||
/* Table create node structure */
|
||||
struct tab_node_t{
|
||||
que_common_t common; /*!< node type: QUE_NODE_TABLE_CREATE */
|
||||
|
@ -580,10 +580,18 @@ dict_foreign_find_index(
|
||||
/*!< 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 */
|
||||
|
||||
__attribute__((nonnull(1,3), warn_unused_result));
|
||||
/**********************************************************************//**
|
||||
Returns a column's name.
|
||||
@ -675,10 +683,17 @@ dict_foreign_qualify_index(
|
||||
/*!< 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 */
|
||||
__attribute__((nonnull(1,3), warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
|
@ -615,5 +615,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 /* HA_INNODB_PROTOTYPES_H */
|
||||
|
@ -1561,6 +1561,104 @@ dict_create_add_foreign_field_to_dictionary(
|
||||
table_name, foreign->id, 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 = (char *)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 = (char *)mem_heap_alloc(foreign->heap, MAX_TABLE_NAME_LEN+1);
|
||||
char* fieldbuf2 = (char *)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 foreign key definition to the data dictionary tables.
|
||||
@return error code or DB_SUCCESS */
|
||||
@ -1568,6 +1666,7 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
dict_table_t* table,
|
||||
const char* name, /*!< in: table name */
|
||||
const dict_foreign_t* foreign,/*!< in: foreign key */
|
||||
trx_t* trx) /*!< in/out: dictionary transaction */
|
||||
@ -1594,6 +1693,28 @@ dict_create_add_foreign_to_dictionary(
|
||||
, name, foreign->id, trx);
|
||||
|
||||
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((dict_foreign_t*)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);
|
||||
}
|
||||
@ -1603,6 +1724,26 @@ dict_create_add_foreign_to_dictionary(
|
||||
i, name, 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((dict_foreign_t*)foreign, trx);
|
||||
dict_foreign_def_get_fields((dict_foreign_t*)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);
|
||||
}
|
||||
@ -1649,7 +1790,7 @@ dict_create_add_foreigns_to_dictionary(
|
||||
foreign = *it;
|
||||
ut_ad(foreign->id != NULL);
|
||||
|
||||
error = dict_create_add_foreign_to_dictionary(table->name,
|
||||
error = dict_create_add_foreign_to_dictionary((dict_table_t*)table, table->name,
|
||||
foreign, trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
@ -3263,6 +3263,11 @@ dict_index_build_internal_fts(
|
||||
}
|
||||
/*====================== FOREIGN KEY PROCESSING ========================*/
|
||||
|
||||
#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
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if a table is referenced by foreign keys.
|
||||
@return TRUE if table is referenced by a foreign key */
|
||||
@ -3417,15 +3422,26 @@ dict_foreign_find_index(
|
||||
/*!< 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;
|
||||
|
||||
ut_ad(mutex_own(&dict_sys->mutex));
|
||||
|
||||
if (error) {
|
||||
*error = DB_FOREIGN_KEY_INDEX_NOT_FOUND;
|
||||
}
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
|
||||
while (index != NULL) {
|
||||
@ -3435,7 +3451,8 @@ dict_foreign_find_index(
|
||||
&& dict_foreign_qualify_index(
|
||||
table, col_names, columns, n_cols,
|
||||
index, types_idx,
|
||||
check_charsets, check_null)) {
|
||||
check_charsets, check_null,
|
||||
error, err_col_no,err_index)) {
|
||||
return(index);
|
||||
}
|
||||
|
||||
@ -3544,7 +3561,7 @@ dict_foreign_add_to_cache(
|
||||
ref_table, NULL,
|
||||
for_in_cache->referenced_col_names,
|
||||
for_in_cache->n_fields, for_in_cache->foreign_index,
|
||||
check_charsets, false);
|
||||
check_charsets, false, NULL, NULL, NULL);
|
||||
|
||||
if (index == NULL
|
||||
&& !(ignore_err & DICT_ERR_IGNORE_FK_NOKEY)) {
|
||||
@ -3576,6 +3593,10 @@ dict_foreign_add_to_cache(
|
||||
}
|
||||
|
||||
if (for_table && !for_in_cache->foreign_table) {
|
||||
ulint index_error;
|
||||
ulint err_col;
|
||||
dict_index_t *err_index=NULL;
|
||||
|
||||
index = dict_foreign_find_index(
|
||||
for_table, col_names,
|
||||
for_in_cache->foreign_col_names,
|
||||
@ -3583,7 +3604,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)) {
|
||||
@ -4243,6 +4265,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
|
||||
@ -4255,11 +4279,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
|
||||
@ -4288,16 +4402,21 @@ 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;
|
||||
ulint number = 1;
|
||||
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;
|
||||
dberr_t error;
|
||||
@ -4310,37 +4429,80 @@ 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;
|
||||
dict_foreign_set local_fk_set;
|
||||
dict_foreign_set_free local_fk_set_free(local_fk_set);
|
||||
const char* create_table_name;
|
||||
const char* orig;
|
||||
char create_name[MAX_TABLE_NAME_LEN + 1];
|
||||
char operation[8];
|
||||
|
||||
ut_ad(!srv_read_only_mode);
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
table = dict_table_get_low(name);
|
||||
/* First check if we are actually doing an ALTER TABLE, and in that
|
||||
case look for the table being altered */
|
||||
orig = ptr;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "TABLE", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4350,13 +4512,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);
|
||||
}
|
||||
@ -4393,6 +4582,7 @@ loop:
|
||||
of the constraint to system tables. */
|
||||
ptr = ptr1;
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
|
||||
|
||||
ut_a(success);
|
||||
@ -4423,6 +4613,19 @@ loop:
|
||||
if so, immediately reject the command if the table is a
|
||||
temporary one. For now, this kludge will work. */
|
||||
if (reject_fks && !local_fk_set.empty()) {
|
||||
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);
|
||||
}
|
||||
@ -4448,6 +4651,7 @@ loop:
|
||||
|
||||
start_of_latest_foreign = ptr;
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4458,6 +4662,7 @@ loop:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "KEY", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4483,6 +4688,7 @@ loop:
|
||||
}
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "(", &success);
|
||||
|
||||
if (!success) {
|
||||
@ -4492,8 +4698,17 @@ loop:
|
||||
ptr = dict_skip_word(cs, ptr, &success);
|
||||
if (!success) {
|
||||
dict_foreign_report_syntax_err(
|
||||
name, start_of_latest_foreign, ptr);
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
"%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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -4520,15 +4735,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);
|
||||
}
|
||||
|
||||
@ -4540,11 +4766,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);
|
||||
}
|
||||
|
||||
@ -4555,27 +4792,41 @@ col_loop1:
|
||||
set to 0 */
|
||||
|
||||
index = dict_foreign_find_index(
|
||||
table, NULL, column_names, i, NULL, TRUE, FALSE);
|
||||
table, NULL, column_names, i,
|
||||
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);
|
||||
dict_foreign_push_index_error(trx, operation, create_name, start_of_latest_foreign,
|
||||
column_names, index_error, err_col, err_index, table, ef);
|
||||
|
||||
return(DB_CHILD_NO_INDEX);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4644,21 +4895,46 @@ 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);
|
||||
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_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);
|
||||
}
|
||||
|
||||
@ -4666,34 +4942,54 @@ 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) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, ",", &success);
|
||||
|
||||
if (success) {
|
||||
goto col_loop2;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, ")", &success);
|
||||
|
||||
if (!success || foreign->n_fields != i) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4703,6 +4999,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) {
|
||||
@ -4710,15 +5007,27 @@ scan_on_conditions:
|
||||
goto try_find_index;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "DELETE", &success);
|
||||
|
||||
if (!success) {
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "UPDATE", &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, 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);
|
||||
}
|
||||
|
||||
@ -4729,12 +5038,14 @@ scan_on_conditions:
|
||||
n_on_deletes++;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
|
||||
|
||||
if (success) {
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "CASCADE", &success);
|
||||
|
||||
if (success) {
|
||||
@ -4747,14 +5058,25 @@ scan_on_conditions:
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "NO", &success);
|
||||
|
||||
if (success) {
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "ACTION", &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, 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);
|
||||
}
|
||||
@ -4768,38 +5090,69 @@ scan_on_conditions:
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
orig = ptr;
|
||||
ptr = dict_accept(cs, ptr, "SET", &success);
|
||||
|
||||
if (!success) {
|
||||
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_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! */
|
||||
|
||||
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);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
}
|
||||
@ -4817,11 +5170,20 @@ try_find_index:
|
||||
/* It is an error to define more than 1 action */
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
@ -4833,12 +5195,12 @@ try_find_index:
|
||||
|
||||
if (referenced_table) {
|
||||
index = dict_foreign_find_index(referenced_table, NULL,
|
||||
column_names, i,
|
||||
ref_column_names, i,
|
||||
foreign->foreign_index,
|
||||
TRUE, FALSE);
|
||||
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);
|
||||
fprintf(ef, "%s:\n"
|
||||
"Cannot find an index in the"
|
||||
" referenced table where the\n"
|
||||
@ -4856,9 +5218,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);
|
||||
@ -4877,11 +5243,12 @@ try_find_index:
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Determines whether a string starts with the specified keyword.
|
||||
@return TRUE if str starts with keyword */
|
||||
@ -6071,7 +6438,8 @@ dict_foreign_replace_index(
|
||||
foreign->foreign_table, col_names,
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
|
||||
NULL, NULL, NULL);
|
||||
if (new_index) {
|
||||
ut_ad(new_index->table == index->table);
|
||||
ut_ad(!new_index->to_be_dropped);
|
||||
@ -6095,7 +6463,8 @@ dict_foreign_replace_index(
|
||||
foreign->referenced_table, NULL,
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE);
|
||||
/*check_charsets=*/TRUE, /*check_null=*/FALSE,
|
||||
NULL, NULL, NULL);
|
||||
/* There must exist an alternative index,
|
||||
since this must have been checked earlier. */
|
||||
if (new_index) {
|
||||
@ -6656,10 +7025,15 @@ dict_foreign_qualify_index(
|
||||
/*!< 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 */
|
||||
{
|
||||
if (dict_index_get_n_fields(index) < n_cols) {
|
||||
return(false);
|
||||
@ -6676,11 +7050,21 @@ dict_foreign_qualify_index(
|
||||
if (field->prefix_len != 0) {
|
||||
/* 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 = (dict_index_t*)index;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
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 = (dict_index_t*)index;
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
@ -6696,6 +7080,12 @@ dict_foreign_qualify_index(
|
||||
dict_index_get_nth_col(index, i),
|
||||
dict_index_get_nth_col(types_idx, i),
|
||||
check_charsets)) {
|
||||
if (error && err_col_no && err_index) {
|
||||
*error = DB_FOREIGN_KEY_COLS_NOT_EQUAL;
|
||||
*err_col_no = i;
|
||||
*err_index = (dict_index_t*)index;
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
@ -420,7 +420,8 @@ dict_mem_table_col_rename_low(
|
||||
dict_index_t* new_index = dict_foreign_find_index(
|
||||
foreign->foreign_table, NULL,
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, NULL, true, false);
|
||||
foreign->n_fields, NULL, true, false,
|
||||
NULL, NULL, NULL);
|
||||
/* There must be an equivalent index in this case. */
|
||||
ut_ad(new_index != NULL);
|
||||
|
||||
|
@ -2413,6 +2413,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;
|
||||
@ -18958,3 +18959,28 @@ 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. */
|
||||
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, Sql_condition::WARN_LEVEL_WARN,
|
||||
convert_error_code_to_mysql((dberr_t)error, 0, thd),
|
||||
buf);
|
||||
my_free(buf);
|
||||
va_end(args);
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ innobase_find_fk_index(
|
||||
if (!(index->type & DICT_FTS)
|
||||
&& dict_foreign_qualify_index(
|
||||
table, col_names, columns, n_cols,
|
||||
index, NULL, true, 0)) {
|
||||
index, NULL, true, 0, NULL, NULL, NULL)) {
|
||||
for (ulint i = 0; i < n_drop_index; i++) {
|
||||
if (index == drop_index[i]) {
|
||||
/* Skip to-be-dropped indexes. */
|
||||
@ -1015,7 +1015,7 @@ innobase_get_foreign_key_info(
|
||||
referenced_table, 0,
|
||||
referenced_column_names,
|
||||
i, index,
|
||||
TRUE, FALSE);
|
||||
TRUE, FALSE, NULL, NULL, NULL);
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_test_no_reference_idx",
|
||||
@ -3330,7 +3330,7 @@ innobase_check_foreign_key_index(
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE,
|
||||
/*check_null=*/FALSE)
|
||||
/*check_null=*/FALSE, NULL, NULL, NULL)
|
||||
&& !innobase_find_equiv_index(
|
||||
foreign->referenced_col_names,
|
||||
foreign->n_fields,
|
||||
@ -3358,7 +3358,7 @@ innobase_check_foreign_key_index(
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields, index,
|
||||
/*check_charsets=*/TRUE,
|
||||
/*check_null=*/FALSE)
|
||||
/*check_null=*/FALSE, NULL,NULL, NULL)
|
||||
&& !innobase_find_equiv_index(
|
||||
foreign->foreign_col_names,
|
||||
foreign->n_fields,
|
||||
@ -4806,7 +4806,8 @@ innobase_update_foreign_try(
|
||||
fk->n_fields, fk->referenced_index, TRUE,
|
||||
fk->type
|
||||
& (DICT_FOREIGN_ON_DELETE_SET_NULL
|
||||
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
|
||||
| DICT_FOREIGN_ON_UPDATE_SET_NULL),
|
||||
NULL, NULL, NULL);
|
||||
if (!fk->foreign_index) {
|
||||
my_error(ER_FK_INCORRECT_OPTION,
|
||||
MYF(0), table_name, fk->id);
|
||||
@ -4818,7 +4819,7 @@ innobase_update_foreign_try(
|
||||
names, while the columns in ctx->old_table have not
|
||||
been renamed yet. */
|
||||
error = dict_create_add_foreign_to_dictionary(
|
||||
ctx->old_table->name, fk, trx);
|
||||
(dict_table_t*)ctx->old_table, ctx->old_table->name, fk, trx);
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"innodb_test_cannot_add_fk_system",
|
||||
|
@ -110,6 +110,17 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
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 */
|
||||
|
||||
/********************************************************************//**
|
||||
Generate a foreign key constraint name when it was not named by the user.
|
||||
A generated constraint has a name of the format dbname/tablename_ibfk_NUMBER,
|
||||
@ -174,6 +185,7 @@ UNIV_INTERN
|
||||
dberr_t
|
||||
dict_create_add_foreign_to_dictionary(
|
||||
/*==================================*/
|
||||
dict_table_t* table, /*!< in: table */
|
||||
const char* name, /*!< in: table name */
|
||||
const dict_foreign_t* foreign,/*!< in: foreign key */
|
||||
trx_t* trx) /*!< in/out: dictionary transaction */
|
||||
|
@ -580,10 +580,17 @@ dict_foreign_find_index(
|
||||
/*!< 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 */
|
||||
__attribute__((nonnull(1,3), warn_unused_result));
|
||||
/**********************************************************************//**
|
||||
Returns a column's name.
|
||||
@ -675,10 +682,18 @@ dict_foreign_qualify_index(
|
||||
/*!< 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 */
|
||||
|
||||
__attribute__((nonnull(1,3), warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
|
@ -611,5 +611,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 /* HA_INNODB_PROTOTYPES_H */
|
||||
|
@ -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);
|
||||
@ -248,7 +259,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
|
||||
}
|
||||
|
||||
/* DH stuff */
|
||||
dh=get_dh1024();
|
||||
dh=get_dh2048();
|
||||
if (!SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh))
|
||||
{
|
||||
*error= SSL_INITERR_DH;
|
||||
|
Loading…
x
Reference in New Issue
Block a user