mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-18114 Foreign Key Constraint actions don't affect Virtual Column
* invoke check_expression() for all vcol_info's in mysql_prepare_create_table() to check for FK CASCADE * also check for SET NULL and SET DEFAULT * to check against existing FKs when a vcol is added in ALTER TABLE, old FKs must be added to the new_key_list just like other indexes are * check columns recursively, if vcol1 references vcol2, flags of vcol2 must be taken into account * remove check_table_name_processor(), put that logic under check_vcol_func_processor() to avoid walking the tree twice
This commit is contained in:
@ -85,7 +85,7 @@ t2id id
|
|||||||
use test;
|
use test;
|
||||||
drop database `#mysql50#-`;
|
drop database `#mysql50#-`;
|
||||||
SET NAMES default;
|
SET NAMES default;
|
||||||
FOUND 8 /\[ERROR\] Invalid \(old\?\) table or database name/ in mysqld.1.err
|
FOUND 10 /\[ERROR\] Invalid \(old\?\) table or database name/ in mysqld.1.err
|
||||||
set global query_cache_type=DEFAULT;
|
set global query_cache_type=DEFAULT;
|
||||||
set global query_cache_size=@save_query_cache_size;
|
set global query_cache_size=@save_query_cache_size;
|
||||||
End of 10.2 tests
|
End of 10.2 tests
|
||||||
|
@ -1077,7 +1077,7 @@ KEY `a_2` (`a`,`vbidxcol`),
|
|||||||
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
||||||
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
DROP TABLE ibstd_16_fk;
|
ERROR HY000: Function or expression 'a' cannot be used in the GENERATED ALWAYS AS clause of `vadcol`
|
||||||
CREATE TABLE `ibstd_16_fk` (
|
CREATE TABLE `ibstd_16_fk` (
|
||||||
`a` int(11) DEFAULT NULL,
|
`a` int(11) DEFAULT NULL,
|
||||||
`d` int(11) DEFAULT NULL,
|
`d` int(11) DEFAULT NULL,
|
||||||
|
@ -1014,7 +1014,7 @@ CREATE TABLE `ibstd_16` (
|
|||||||
) ENGINE=INNODB;
|
) ENGINE=INNODB;
|
||||||
|
|
||||||
# Block when FK constraint on base column of stored column.
|
# Block when FK constraint on base column of stored column.
|
||||||
#--error ER_CANNOT_ADD_FOREIGN
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
CREATE TABLE `ibstd_16_fk` (
|
CREATE TABLE `ibstd_16_fk` (
|
||||||
`a` int(11) DEFAULT NULL,
|
`a` int(11) DEFAULT NULL,
|
||||||
`d` int(11) DEFAULT NULL,
|
`d` int(11) DEFAULT NULL,
|
||||||
@ -1033,7 +1033,6 @@ CREATE TABLE `ibstd_16_fk` (
|
|||||||
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
||||||
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
DROP TABLE ibstd_16_fk;
|
|
||||||
|
|
||||||
# Take out "KEY `a_2` (`a`,`vbidxcol`)", this should then be successful
|
# Take out "KEY `a_2` (`a`,`vbidxcol`)", this should then be successful
|
||||||
CREATE TABLE `ibstd_16_fk` (
|
CREATE TABLE `ibstd_16_fk` (
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
# Create statement with FK on base column of stored column
|
|
||||||
create table t1(f1 int, f2 int as(f1) stored,
|
|
||||||
foreign key(f1) references t2(f1) on delete cascade)engine=innodb;
|
|
||||||
ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed")
|
|
||||||
# adding new stored column during alter table copy operation.
|
|
||||||
create table t1(f1 int primary key) engine=innodb;
|
create table t1(f1 int primary key) engine=innodb;
|
||||||
|
# Create statement with FK on base column of stored column
|
||||||
|
create table t2(f1 int not null, f2 int as (f1) stored,
|
||||||
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
|
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2`
|
||||||
|
create table t2(f1 int not null, f2 int as (f1) virtual, f3 int as (f2) stored,
|
||||||
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
|
ERROR HY000: Function or expression 'f2' cannot be used in the GENERATED ALWAYS AS clause of `f3`
|
||||||
|
# adding new stored column during alter table copy operation.
|
||||||
create table t2(f1 int not null, f2 int as (f1) virtual,
|
create table t2(f1 int not null, f2 int as (f1) virtual,
|
||||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual;
|
alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual;
|
||||||
|
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f3`
|
||||||
show create table t2;
|
show create table t2;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t2 CREATE TABLE `t2` (
|
t2 CREATE TABLE `t2` (
|
||||||
`f1` int(11) NOT NULL,
|
`f1` int(11) NOT NULL,
|
||||||
`f2` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL,
|
`f2` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL,
|
||||||
`f3` int(11) GENERATED ALWAYS AS (`f1`) STORED,
|
|
||||||
`f4` int(11) GENERATED ALWAYS AS (`f1`) VIRTUAL,
|
|
||||||
KEY `f1` (`f1`),
|
KEY `f1` (`f1`),
|
||||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
|
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
@ -21,26 +23,25 @@ drop table t2;
|
|||||||
# adding foreign key constraint for base columns during alter copy.
|
# adding foreign key constraint for base columns during alter copy.
|
||||||
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
||||||
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy;
|
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy;
|
||||||
|
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2`
|
||||||
show create table t2;
|
show create table t2;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
t2 CREATE TABLE `t2` (
|
t2 CREATE TABLE `t2` (
|
||||||
`f1` int(11) NOT NULL,
|
`f1` int(11) NOT NULL,
|
||||||
`f2` int(11) GENERATED ALWAYS AS (`f1`) STORED,
|
`f2` int(11) GENERATED ALWAYS AS (`f1`) STORED
|
||||||
KEY `f1` (`f1`),
|
|
||||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||||
drop table t2;
|
drop table t2;
|
||||||
# adding foreign key constraint for base columns during online alter.
|
# adding foreign key constraint for base columns during online alter.
|
||||||
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
||||||
set foreign_key_checks = 0;
|
set foreign_key_checks = 0;
|
||||||
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace;
|
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace;
|
||||||
ERROR 0A000: Cannot add foreign key on the base column of stored column
|
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2`
|
||||||
drop table t2;
|
drop table t2;
|
||||||
# adding stored column via online alter.
|
# adding stored column via online alter.
|
||||||
create table t2(f1 int not null,
|
create table t2(f1 int not null,
|
||||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
alter table t2 add column f2 int as (f1) stored, algorithm=inplace;
|
alter table t2 add column f2 int as (f1) stored, algorithm=inplace;
|
||||||
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY
|
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2`
|
||||||
drop table t2, t1;
|
drop table t2, t1;
|
||||||
#
|
#
|
||||||
# BUG#26731689 FK ON TABLE WITH GENERATED COLS: ASSERTION POS < N_DEF
|
# BUG#26731689 FK ON TABLE WITH GENERATED COLS: ASSERTION POS < N_DEF
|
||||||
|
@ -1,24 +1,28 @@
|
|||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
|
|
||||||
|
create table t1(f1 int primary key) engine=innodb;
|
||||||
|
|
||||||
--echo # Create statement with FK on base column of stored column
|
--echo # Create statement with FK on base column of stored column
|
||||||
--error ER_CANT_CREATE_TABLE
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1(f1 int, f2 int as(f1) stored,
|
create table t2(f1 int not null, f2 int as (f1) stored,
|
||||||
foreign key(f1) references t2(f1) on delete cascade)engine=innodb;
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
|
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create table t2(f1 int not null, f2 int as (f1) virtual, f3 int as (f2) stored,
|
||||||
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
|
|
||||||
--echo # adding new stored column during alter table copy operation.
|
--echo # adding new stored column during alter table copy operation.
|
||||||
create table t1(f1 int primary key) engine=innodb;
|
|
||||||
create table t2(f1 int not null, f2 int as (f1) virtual,
|
create table t2(f1 int not null, f2 int as (f1) virtual,
|
||||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
|
|
||||||
# MySQL 5.7 would refuse this
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
#--error ER_ERROR_ON_RENAME
|
|
||||||
alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual;
|
alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual;
|
||||||
show create table t2;
|
show create table t2;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
|
||||||
--echo # adding foreign key constraint for base columns during alter copy.
|
--echo # adding foreign key constraint for base columns during alter copy.
|
||||||
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
||||||
# MySQL 5.7 would refuse this
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy;
|
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=copy;
|
||||||
show create table t2;
|
show create table t2;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
@ -26,14 +30,14 @@ drop table t2;
|
|||||||
--echo # adding foreign key constraint for base columns during online alter.
|
--echo # adding foreign key constraint for base columns during online alter.
|
||||||
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
||||||
set foreign_key_checks = 0;
|
set foreign_key_checks = 0;
|
||||||
--error 138
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace;
|
alter table t2 add foreign key(f1) references t1(f1) on update cascade, algorithm=inplace;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
|
|
||||||
--echo # adding stored column via online alter.
|
--echo # adding stored column via online alter.
|
||||||
create table t2(f1 int not null,
|
create table t2(f1 int not null,
|
||||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t2 add column f2 int as (f1) stored, algorithm=inplace;
|
alter table t2 add column f2 int as (f1) stored, algorithm=inplace;
|
||||||
drop table t2, t1;
|
drop table t2, t1;
|
||||||
|
|
||||||
|
@ -10,3 +10,73 @@ select * from t2;
|
|||||||
id
|
id
|
||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
#
|
||||||
|
# End of 10.2 tests
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# MDEV-18114 Foreign Key Constraint actions don't affect Virtual Column
|
||||||
|
#
|
||||||
|
create table t1 (id int primary key);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update set null);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update cascade);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the GENERATED ALWAYS AS clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update cascade);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete set null);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update set null);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the GENERATED ALWAYS AS clause of `id3`
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `id2`
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
ERROR HY000: Function or expression 'id' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update set null);
|
||||||
|
ERROR HY000: Function or expression 'id2' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
|
drop table if exists t2, t1;
|
||||||
|
Warnings:
|
||||||
|
Note 1051 Unknown table 'test.t2'
|
||||||
|
#
|
||||||
|
# End of 10.5 tests
|
||||||
|
#
|
||||||
|
@ -54,22 +54,22 @@ set session sql_mode=@OLD_SQL_MODE;
|
|||||||
#
|
#
|
||||||
create table t2 (x int);
|
create table t2 (x int);
|
||||||
create table t1 (x int, y int generated always as (t2.x));
|
create table t1 (x int, y int generated always as (t2.x));
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the GENERATED ALWAYS AS clause of `y`
|
||||||
create table t1 (x int, y int check (y > t2.x));
|
create table t1 (x int, y int check (y > t2.x));
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `y`
|
||||||
create table t1 (x int, y int default t2.x);
|
create table t1 (x int, y int default t2.x);
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the DEFAULT clause of `y`
|
||||||
create table t1 (x int, check (t2.x > 0));
|
create table t1 (x int, check (t2.x > 0));
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
create table t1 (x int);
|
create table t1 (x int);
|
||||||
alter table t1 add column y int generated always as (t2.x);
|
alter table t1 add column y int generated always as (t2.x);
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the GENERATED ALWAYS AS clause of `y`
|
||||||
alter table t1 add column y int check (z > t2.x);
|
alter table t1 add column y int check (z > t2.x);
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `y`
|
||||||
alter table t1 add column y int default t2.x;
|
alter table t1 add column y int default t2.x;
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the DEFAULT clause of `y`
|
||||||
alter table t1 add constraint check (t2.x > 0);
|
alter table t1 add constraint check (t2.x > 0);
|
||||||
ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 't2.x' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
create or replace table t1 (x int, y int generated always as (t1.x));
|
create or replace table t1 (x int, y int generated always as (t1.x));
|
||||||
create or replace table t1 (x int, y int check (y > t1.x));
|
create or replace table t1 (x int, y int check (y > t1.x));
|
||||||
create or replace table t1 (x int, y int default t1.x);
|
create or replace table t1 (x int, y int default t1.x);
|
||||||
@ -80,13 +80,13 @@ create or replace table t1 (x int, y int default test.t1.x);
|
|||||||
create or replace table t1 (x int, check (test.t1.x > 0));
|
create or replace table t1 (x int, check (test.t1.x > 0));
|
||||||
drop tables t1, t2;
|
drop tables t1, t2;
|
||||||
create table t1 (x int, y int generated always as (test2.t1.x));
|
create table t1 (x int, y int generated always as (test2.t1.x));
|
||||||
ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'GENERATED ALWAYS'
|
ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the GENERATED ALWAYS AS clause of `y`
|
||||||
create table t1 (x int, y int check (y > test2.t1.x));
|
create table t1 (x int, y int check (y > test2.t1.x));
|
||||||
ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the CHECK clause of `y`
|
||||||
create table t1 (x int, y int default test2.t1.x);
|
create table t1 (x int, y int default test2.t1.x);
|
||||||
ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'DEFAULT'
|
ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the DEFAULT clause of `y`
|
||||||
create table t1 (x int, check (test2.t1.x > 0));
|
create table t1 (x int, check (test2.t1.x > 0));
|
||||||
ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK'
|
ERROR HY000: Function or expression 'test2.t1.x' cannot be used in the CHECK clause of `CONSTRAINT_1`
|
||||||
#
|
#
|
||||||
# MDEV-25672 table alias from previous statement interferes later commands
|
# MDEV-25672 table alias from previous statement interferes later commands
|
||||||
#
|
#
|
||||||
|
@ -14,3 +14,92 @@ select * from t1;
|
|||||||
select * from t2;
|
select * from t2;
|
||||||
drop table t2;
|
drop table t2;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.2 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-18114 Foreign Key Constraint actions don't affect Virtual Column
|
||||||
|
--echo #
|
||||||
|
create table t1 (id int primary key);
|
||||||
|
|
||||||
|
# note that RESTRICT, NO ACTION, and DELETE CASCADE are fine
|
||||||
|
# because they don't change values of referenced columns
|
||||||
|
|
||||||
|
# virtual indexed
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, key(id2), foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# stored
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on delete set null);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) stored, foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# stored indirect
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on delete set null);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, id3 int as (id2) stored, foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# default
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
create or replace table t2 (id int, id2 int default (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# field check
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int check (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# table check
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int, check (id), foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
# table check indirect
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update restrict);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update no action);
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update cascade);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on delete set null);
|
||||||
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
|
create or replace table t2 (id int, id2 int as (id) virtual, check (id2), foreign key (id) references t1 (id) on update set null);
|
||||||
|
|
||||||
|
drop table if exists t2, t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.5 tests
|
||||||
|
--echo #
|
||||||
|
@ -29,23 +29,23 @@ set session sql_mode=@OLD_SQL_MODE;
|
|||||||
--echo #
|
--echo #
|
||||||
create table t2 (x int);
|
create table t2 (x int);
|
||||||
|
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int generated always as (t2.x));
|
create table t1 (x int, y int generated always as (t2.x));
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int check (y > t2.x));
|
create table t1 (x int, y int check (y > t2.x));
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int default t2.x);
|
create table t1 (x int, y int default t2.x);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, check (t2.x > 0));
|
create table t1 (x int, check (t2.x > 0));
|
||||||
|
|
||||||
create table t1 (x int);
|
create table t1 (x int);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t1 add column y int generated always as (t2.x);
|
alter table t1 add column y int generated always as (t2.x);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t1 add column y int check (z > t2.x);
|
alter table t1 add column y int check (z > t2.x);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t1 add column y int default t2.x;
|
alter table t1 add column y int default t2.x;
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
alter table t1 add constraint check (t2.x > 0);
|
alter table t1 add constraint check (t2.x > 0);
|
||||||
|
|
||||||
create or replace table t1 (x int, y int generated always as (t1.x));
|
create or replace table t1 (x int, y int generated always as (t1.x));
|
||||||
@ -60,13 +60,13 @@ create or replace table t1 (x int, check (test.t1.x > 0));
|
|||||||
|
|
||||||
drop tables t1, t2;
|
drop tables t1, t2;
|
||||||
|
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int generated always as (test2.t1.x));
|
create table t1 (x int, y int generated always as (test2.t1.x));
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int check (y > test2.t1.x));
|
create table t1 (x int, y int check (y > test2.t1.x));
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, y int default test2.t1.x);
|
create table t1 (x int, y int default test2.t1.x);
|
||||||
--error ER_BAD_FIELD_ERROR
|
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||||
create table t1 (x int, check (test2.t1.x > 0));
|
create table t1 (x int, check (test2.t1.x > 0));
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
36
sql/item.h
36
sql/item.h
@ -2005,15 +2005,6 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Check db/table_name if they defined in item and match arg values
|
|
||||||
|
|
||||||
@param arg Pointer to Check_table_name_prm structure
|
|
||||||
|
|
||||||
@retval true Match failed
|
|
||||||
@retval false Match succeeded
|
|
||||||
*/
|
|
||||||
virtual bool check_table_name_processor(void *arg) { return false; }
|
|
||||||
/*
|
/*
|
||||||
TRUE if the expression depends only on the table indicated by tab_map
|
TRUE if the expression depends only on the table indicated by tab_map
|
||||||
or can be converted to such an exression using equalities.
|
or can be converted to such an exression using equalities.
|
||||||
@ -2213,15 +2204,6 @@ public:
|
|||||||
bool collect;
|
bool collect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Check_table_name_prm
|
|
||||||
{
|
|
||||||
LEX_CSTRING db;
|
|
||||||
LEX_CSTRING table_name;
|
|
||||||
String field;
|
|
||||||
Check_table_name_prm(LEX_CSTRING _db, LEX_CSTRING _table_name) :
|
|
||||||
db(_db), table_name(_table_name) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
For SP local variable returns pointer to Item representing its
|
For SP local variable returns pointer to Item representing its
|
||||||
current value and pointer to current Item otherwise.
|
current value and pointer to current Item otherwise.
|
||||||
@ -3592,24 +3574,6 @@ public:
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool check_table_name_processor(void *arg) override
|
|
||||||
{
|
|
||||||
Check_table_name_prm &p= *static_cast<Check_table_name_prm*>(arg);
|
|
||||||
if (!field && p.table_name.length && table_name.length)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(p.db.length);
|
|
||||||
if ((db_name.length &&
|
|
||||||
my_strcasecmp(table_alias_charset, p.db.str, db_name.str)) ||
|
|
||||||
my_strcasecmp(table_alias_charset, p.table_name.str, table_name.str))
|
|
||||||
{
|
|
||||||
print(&p.field, (enum_query_type) (QT_ITEM_ORIGINAL_FUNC_NULLIF |
|
|
||||||
QT_NO_DATA_EXPANSION |
|
|
||||||
QT_TO_SYSTEM_CHARSET));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void cleanup() override;
|
void cleanup() override;
|
||||||
Item_equal *get_item_equal() override { return item_equal; }
|
Item_equal *get_item_equal() override { return item_equal; }
|
||||||
void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; }
|
void set_item_equal(Item_equal *item_eq) override { item_equal= item_eq; }
|
||||||
|
@ -254,12 +254,25 @@ Alter_info::algorithm(const THD *thd) const
|
|||||||
|
|
||||||
uint Alter_info::check_vcol_field(Item_field *item) const
|
uint Alter_info::check_vcol_field(Item_field *item) const
|
||||||
{
|
{
|
||||||
|
if (!item->field &&
|
||||||
|
((item->db_name.length && !db.streq(item->db_name)) ||
|
||||||
|
(item->table_name.length && !table_name.streq(item->table_name))))
|
||||||
|
{
|
||||||
|
char *ptr= (char*)current_thd->alloc(item->db_name.length +
|
||||||
|
item->table_name.length +
|
||||||
|
item->field_name.length + 3);
|
||||||
|
strxmov(ptr, safe_str(item->db_name.str), item->db_name.length ? "." : "",
|
||||||
|
item->table_name.str, ".", item->field_name.str, NullS);
|
||||||
|
item->field_name.str= ptr;
|
||||||
|
return VCOL_IMPOSSIBLE;
|
||||||
|
}
|
||||||
for (Key &k: key_list)
|
for (Key &k: key_list)
|
||||||
{
|
{
|
||||||
if (k.type != Key::FOREIGN_KEY)
|
if (k.type != Key::FOREIGN_KEY)
|
||||||
continue;
|
continue;
|
||||||
Foreign_key *fk= (Foreign_key*) &k;
|
Foreign_key *fk= (Foreign_key*) &k;
|
||||||
if (fk->update_opt != FK_OPTION_CASCADE)
|
if (fk->update_opt < FK_OPTION_CASCADE &&
|
||||||
|
fk->delete_opt < FK_OPTION_SET_NULL)
|
||||||
continue;
|
continue;
|
||||||
for (Key_part_spec& kp: fk->columns)
|
for (Key_part_spec& kp: fk->columns)
|
||||||
{
|
{
|
||||||
@ -267,6 +280,11 @@ uint Alter_info::check_vcol_field(Item_field *item) const
|
|||||||
return VCOL_NON_DETERMINISTIC;
|
return VCOL_NON_DETERMINISTIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (Create_field &cf: create_list)
|
||||||
|
{
|
||||||
|
if (item->field_name.streq(cf.field_name))
|
||||||
|
return cf.vcol_info ? cf.vcol_info->flags : 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4452,7 +4452,6 @@ without_overlaps_err:
|
|||||||
create_info->null_bits= null_fields;
|
create_info->null_bits= null_fields;
|
||||||
|
|
||||||
/* Check fields. */
|
/* Check fields. */
|
||||||
Item::Check_table_name_prm walk_prm(alter_info->db, alter_info->table_name);
|
|
||||||
it.rewind();
|
it.rewind();
|
||||||
while ((sql_field=it++))
|
while ((sql_field=it++))
|
||||||
{
|
{
|
||||||
@ -4510,33 +4509,22 @@ without_overlaps_err:
|
|||||||
|
|
||||||
if (create_simple)
|
if (create_simple)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
NOTE: we cannot do this in check_vcol_func_processor() as there is
|
|
||||||
already no table name qualifier in expression.
|
|
||||||
*/
|
|
||||||
if (sql_field->vcol_info && sql_field->vcol_info->expr &&
|
if (sql_field->vcol_info && sql_field->vcol_info->expr &&
|
||||||
sql_field->vcol_info->expr->walk(&Item::check_table_name_processor,
|
check_expression(sql_field->vcol_info, &sql_field->field_name,
|
||||||
false, &walk_prm))
|
sql_field->vcol_info->stored_in_db
|
||||||
{
|
? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL,
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS");
|
alter_info))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
|
||||||
|
|
||||||
if (sql_field->default_value &&
|
if (sql_field->default_value &&
|
||||||
sql_field->default_value->expr->walk(&Item::check_table_name_processor,
|
check_expression(sql_field->default_value, &sql_field->field_name,
|
||||||
false, &walk_prm))
|
VCOL_DEFAULT, alter_info))
|
||||||
{
|
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT");
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
|
||||||
|
|
||||||
if (sql_field->check_constraint &&
|
if (sql_field->check_constraint &&
|
||||||
sql_field->check_constraint->expr->walk(&Item::check_table_name_processor,
|
check_expression(sql_field->check_constraint, &sql_field->field_name,
|
||||||
false, &walk_prm))
|
VCOL_CHECK_FIELD, alter_info))
|
||||||
{
|
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK");
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4546,12 +4534,6 @@ without_overlaps_err:
|
|||||||
List_iterator_fast<Virtual_column_info> c_it(alter_info->check_constraint_list);
|
List_iterator_fast<Virtual_column_info> c_it(alter_info->check_constraint_list);
|
||||||
while (Virtual_column_info *check= c_it++)
|
while (Virtual_column_info *check= c_it++)
|
||||||
{
|
{
|
||||||
if (create_simple && check->expr->walk(&Item::check_table_name_processor,
|
|
||||||
false, &walk_prm))
|
|
||||||
{
|
|
||||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK");
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
if (check->name.length && !check->automatic_name)
|
if (check->name.length && !check->automatic_name)
|
||||||
{
|
{
|
||||||
/* Check that there's no repeating table CHECK constraint names. */
|
/* Check that there's no repeating table CHECK constraint names. */
|
||||||
@ -8438,6 +8420,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
List<Create_field> new_create_tail;
|
List<Create_field> new_create_tail;
|
||||||
/* New key definitions are added here */
|
/* New key definitions are added here */
|
||||||
List<Key> new_key_list;
|
List<Key> new_key_list;
|
||||||
|
List<FOREIGN_KEY_INFO> fk_list;
|
||||||
List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
|
List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
|
||||||
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
||||||
List_iterator<Create_field> def_it(alter_info->create_list);
|
List_iterator<Create_field> def_it(alter_info->create_list);
|
||||||
@ -8460,12 +8443,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
bool drop_period= false;
|
bool drop_period= false;
|
||||||
LEX_CSTRING period_start_name= {nullptr, 0};
|
LEX_CSTRING period_start_name= {nullptr, 0};
|
||||||
LEX_CSTRING period_end_name= {nullptr, 0};
|
LEX_CSTRING period_end_name= {nullptr, 0};
|
||||||
|
DBUG_ENTER("mysql_prepare_alter_table");
|
||||||
|
|
||||||
if (table->s->period.name)
|
if (table->s->period.name)
|
||||||
{
|
{
|
||||||
period_start_name= table->s->period_start_field()->field_name;
|
period_start_name= table->s->period_start_field()->field_name;
|
||||||
period_end_name= table->s->period_end_field()->field_name;
|
period_end_name= table->s->period_end_field()->field_name;
|
||||||
}
|
}
|
||||||
DBUG_ENTER("mysql_prepare_alter_table");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Merge incompatible changes flag in case of upgrade of a table from an
|
Merge incompatible changes flag in case of upgrade of a table from an
|
||||||
@ -8526,6 +8510,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
create_info->option_list= merge_engine_table_options(table->s->option_list,
|
create_info->option_list= merge_engine_table_options(table->s->option_list,
|
||||||
create_info->option_list, thd->mem_root);
|
create_info->option_list, thd->mem_root);
|
||||||
|
|
||||||
|
table->file->get_foreign_key_list(thd, &fk_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First collect all fields from table which isn't in drop_list
|
First collect all fields from table which isn't in drop_list
|
||||||
*/
|
*/
|
||||||
@ -9168,6 +9154,30 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
re_setup_keyinfo_hash(key_info);
|
re_setup_keyinfo_hash(key_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// add existing foreign keys
|
||||||
|
for (auto &fk : fk_list)
|
||||||
|
{
|
||||||
|
Alter_drop *drop;
|
||||||
|
for(drop_it.rewind(); (drop=drop_it++); )
|
||||||
|
if (drop->type == Alter_drop::FOREIGN_KEY &&
|
||||||
|
!my_strcasecmp(system_charset_info, fk.foreign_id->str, drop->name))
|
||||||
|
break;
|
||||||
|
if (drop)
|
||||||
|
continue;
|
||||||
|
List<Key_part_spec> cols, ref_cols;
|
||||||
|
for (LEX_CSTRING &c : fk.foreign_fields)
|
||||||
|
cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0));
|
||||||
|
for (LEX_CSTRING &c : fk.referenced_fields)
|
||||||
|
ref_cols.push_back(new (thd->mem_root) Key_part_spec(&c, 0));
|
||||||
|
auto key= new (thd->mem_root)
|
||||||
|
Foreign_key(fk.foreign_id, &cols, fk.foreign_id, fk.referenced_db,
|
||||||
|
fk.referenced_table, &ref_cols, fk.delete_method, fk.update_method,
|
||||||
|
Foreign_key::FK_MATCH_UNDEF, DDL_options());
|
||||||
|
key->old= true;
|
||||||
|
new_key_list.push_back(key, thd->mem_root);
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
while ((key=key_it++)) // Add new keys
|
while ((key=key_it++)) // Add new keys
|
||||||
@ -9291,10 +9301,8 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
if (!alter_info->check_constraint_list.is_empty())
|
if (!alter_info->check_constraint_list.is_empty())
|
||||||
{
|
{
|
||||||
/* Check the table FOREIGN KEYs for name duplications. */
|
/* Check the table FOREIGN KEYs for name duplications. */
|
||||||
List <FOREIGN_KEY_INFO> fk_child_key_list;
|
|
||||||
FOREIGN_KEY_INFO *f_key;
|
FOREIGN_KEY_INFO *f_key;
|
||||||
table->file->get_foreign_key_list(thd, &fk_child_key_list);
|
List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_list);
|
||||||
List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
|
|
||||||
while ((f_key= fk_key_it++))
|
while ((f_key= fk_key_it++))
|
||||||
{
|
{
|
||||||
List_iterator_fast<Virtual_column_info>
|
List_iterator_fast<Virtual_column_info>
|
||||||
|
Reference in New Issue
Block a user