mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01: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:
parent
ab1191c039
commit
da09ae05a9
12 changed files with 269 additions and 116 deletions
|
@ -85,7 +85,7 @@ t2id id
|
|||
use test;
|
||||
drop database `#mysql50#-`;
|
||||
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_size=@save_query_cache_size;
|
||||
End of 10.2 tests
|
||||
|
|
|
@ -1077,7 +1077,7 @@ KEY `a_2` (`a`,`vbidxcol`),
|
|||
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
||||
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
||||
) 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` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`d` int(11) DEFAULT NULL,
|
||||
|
|
|
@ -1014,7 +1014,7 @@ CREATE TABLE `ibstd_16` (
|
|||
) ENGINE=INNODB;
|
||||
|
||||
# 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` (
|
||||
`a` int(11) DEFAULT NULL,
|
||||
`d` int(11) DEFAULT NULL,
|
||||
|
@ -1033,7 +1033,6 @@ CREATE TABLE `ibstd_16_fk` (
|
|||
KEY `vbidxcol_2` (`vbidxcol`,`d`),
|
||||
CONSTRAINT `fk_16` FOREIGN KEY (`a`) REFERENCES `ibstd_16` (`a`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB;
|
||||
DROP TABLE ibstd_16_fk;
|
||||
|
||||
# Take out "KEY `a_2` (`a`,`vbidxcol`)", this should then be successful
|
||||
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 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,
|
||||
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;
|
||||
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f3`
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`f1` int(11) NOT NULL,
|
||||
`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`),
|
||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
|
||||
) 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.
|
||||
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;
|
||||
ERROR HY000: Function or expression 'f1' cannot be used in the GENERATED ALWAYS AS clause of `f2`
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`f1` int(11) NOT NULL,
|
||||
`f2` int(11) GENERATED ALWAYS AS (`f1`) STORED,
|
||||
KEY `f1` (`f1`),
|
||||
CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE
|
||||
`f2` int(11) GENERATED ALWAYS AS (`f1`) STORED
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
|
||||
drop table t2;
|
||||
# adding foreign key constraint for base columns during online alter.
|
||||
create table t2(f1 int not null, f2 int as (f1) stored) engine=innodb;
|
||||
set foreign_key_checks = 0;
|
||||
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;
|
||||
# adding stored column via online alter.
|
||||
create table t2(f1 int not null,
|
||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||
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;
|
||||
#
|
||||
# BUG#26731689 FK ON TABLE WITH GENERATED COLS: ASSERTION POS < N_DEF
|
||||
|
|
|
@ -1,24 +1,28 @@
|
|||
--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
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t1(f1 int, f2 int as(f1) stored,
|
||||
foreign key(f1) references t2(f1) on delete cascade)engine=innodb;
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
create table t2(f1 int not null, f2 int as (f1) stored,
|
||||
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.
|
||||
create table t1(f1 int primary key) engine=innodb;
|
||||
create table t2(f1 int not null, f2 int as (f1) virtual,
|
||||
foreign key(f1) references t1(f1) on update cascade)engine=innodb;
|
||||
|
||||
# MySQL 5.7 would refuse this
|
||||
#--error ER_ERROR_ON_RENAME
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
alter table t2 add column f3 int as (f1) stored, add column f4 int as (f1) virtual;
|
||||
show create table t2;
|
||||
drop table t2;
|
||||
|
||||
--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;
|
||||
# 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;
|
||||
show create table t2;
|
||||
drop table t2;
|
||||
|
@ -26,14 +30,14 @@ drop table t2;
|
|||
--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;
|
||||
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;
|
||||
drop table t2;
|
||||
|
||||
--echo # adding stored column via online alter.
|
||||
create table t2(f1 int not null,
|
||||
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;
|
||||
drop table t2, t1;
|
||||
|
||||
|
|
|
@ -10,3 +10,73 @@ select * from t2;
|
|||
id
|
||||
drop table t2;
|
||||
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 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));
|
||||
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);
|
||||
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));
|
||||
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);
|
||||
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);
|
||||
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;
|
||||
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);
|
||||
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 check (y > 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));
|
||||
drop tables t1, t2;
|
||||
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));
|
||||
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);
|
||||
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));
|
||||
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
|
||||
#
|
||||
|
|
|
@ -14,3 +14,92 @@ select * from t1;
|
|||
select * from t2;
|
||||
drop table t2;
|
||||
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 #
|
||||
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));
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
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);
|
||||
--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);
|
||||
--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);
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
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;
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
alter table t1 add constraint check (t2.x > 0);
|
||||
|
||||
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;
|
||||
|
||||
--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));
|
||||
--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));
|
||||
--error ER_BAD_FIELD_ERROR
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
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));
|
||||
|
||||
--echo #
|
||||
|
|
36
sql/item.h
36
sql/item.h
|
@ -2005,15 +2005,6 @@ public:
|
|||
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
|
||||
or can be converted to such an exression using equalities.
|
||||
|
@ -2213,15 +2204,6 @@ public:
|
|||
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
|
||||
current value and pointer to current Item otherwise.
|
||||
|
@ -3592,24 +3574,6 @@ public:
|
|||
}
|
||||
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;
|
||||
Item_equal *get_item_equal() override { return item_equal; }
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (k.type != Key::FOREIGN_KEY)
|
||||
continue;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -4452,7 +4452,6 @@ without_overlaps_err:
|
|||
create_info->null_bits= null_fields;
|
||||
|
||||
/* Check fields. */
|
||||
Item::Check_table_name_prm walk_prm(alter_info->db, alter_info->table_name);
|
||||
it.rewind();
|
||||
while ((sql_field=it++))
|
||||
{
|
||||
|
@ -4510,33 +4509,22 @@ without_overlaps_err:
|
|||
|
||||
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 &&
|
||||
sql_field->vcol_info->expr->walk(&Item::check_table_name_processor,
|
||||
false, &walk_prm))
|
||||
{
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS");
|
||||
check_expression(sql_field->vcol_info, &sql_field->field_name,
|
||||
sql_field->vcol_info->stored_in_db
|
||||
? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL,
|
||||
alter_info))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (sql_field->default_value &&
|
||||
sql_field->default_value->expr->walk(&Item::check_table_name_processor,
|
||||
false, &walk_prm))
|
||||
{
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT");
|
||||
check_expression(sql_field->default_value, &sql_field->field_name,
|
||||
VCOL_DEFAULT, alter_info))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (sql_field->check_constraint &&
|
||||
sql_field->check_constraint->expr->walk(&Item::check_table_name_processor,
|
||||
false, &walk_prm))
|
||||
{
|
||||
my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK");
|
||||
check_expression(sql_field->check_constraint, &sql_field->field_name,
|
||||
VCOL_CHECK_FIELD, alter_info))
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4546,12 +4534,6 @@ without_overlaps_err:
|
|||
List_iterator_fast<Virtual_column_info> c_it(alter_info->check_constraint_list);
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
/* New key definitions are added here */
|
||||
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_iterator<Alter_drop> drop_it(alter_info->drop_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;
|
||||
LEX_CSTRING period_start_name= {nullptr, 0};
|
||||
LEX_CSTRING period_end_name= {nullptr, 0};
|
||||
DBUG_ENTER("mysql_prepare_alter_table");
|
||||
|
||||
if (table->s->period.name)
|
||||
{
|
||||
period_start_name= table->s->period_start_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
|
||||
|
@ -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, thd->mem_root);
|
||||
|
||||
table->file->get_foreign_key_list(thd, &fk_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);
|
||||
}
|
||||
}
|
||||
{
|
||||
// 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;
|
||||
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())
|
||||
{
|
||||
/* Check the table FOREIGN KEYs for name duplications. */
|
||||
List <FOREIGN_KEY_INFO> fk_child_key_list;
|
||||
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_child_key_list);
|
||||
List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_list);
|
||||
while ((f_key= fk_key_it++))
|
||||
{
|
||||
List_iterator_fast<Virtual_column_info>
|
||||
|
|
Loading…
Add table
Reference in a new issue