Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-34392

modification of the column fails to check foreign key constraint

Details

    Description

      Testcase with 2 tables

      create table tab1 (
          t1id int unsigned not null auto_increment,
          t1val varchar(30) not null,
          constraint pkt1 primary key (t1id)
      );
      create table tab2 (
          t2id int unsigned not null auto_increment,
          t1id int unsigned,
          t2tval datetime,
          t2nval int,
          constraint pkt2 primary key (t2id)
      );
      alter table tab2 add index FkIdxt2t1id (t1id), add constraint Fkt2t1id foreign key (t1id) references tab1 (t1id);
      

      Altering columns in one statement failes

      alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3), modify t2nval bigint;

      Cannot change column 't1id': used in a foreign key constraint 'Fkt2t1id'
      

      alter not null in seperate statement works, also 2 modify data types

      alter table tab2 modify t1id int unsigned not null;
      alter table tab2 modify t2tval timestamp(3), modify t2nval bigint;

      Attachments

        Issue Links

          Activity

            svh Stefan van Hasselt created issue -

            Thank you. I can confirm this, and it looks like this error was introduced by MDEV-31086. The function fk_check_column_changes() would return FK_COLUMN_DATA_CHANGE because the NOT NULL attribute is changing. Here is a simpler test:

            --source include/have_innodb.inc
             
            create table tab1 (t1id int unsigned primary key) engine=innodb;
            create table tab2 (
                t2id int unsigned primary key,
                t1id int unsigned references tab1(t1id),
                t2tval datetime
            ) engine=innodb;
             
            alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3);
            show create table tab2;
            

            If I declare tab2.t1id with not null to begin with, or if I omit one of the modify clauses, this will succeed. Else:

            10.11 5b89cab44f409d3774b6c8255dfd2c72b2ade1af

            mysqltest: At line 10: query 'alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3)' failed: ER_FK_COLUMN_CANNOT_CHANGE (1832): Cannot change column 't1id': used in a foreign key constraint 'tab2_ibfk_1'
            

            This looks like an unintended regression due to MDEV-31086, and regressions should be fixed at a critical priority.

            marko Marko Mäkelä added a comment - Thank you. I can confirm this, and it looks like this error was introduced by MDEV-31086 . The function fk_check_column_changes() would return FK_COLUMN_DATA_CHANGE because the NOT NULL attribute is changing. Here is a simpler test: --source include/have_innodb.inc   create table tab1 (t1id int unsigned primary key ) engine=innodb; create table tab2 ( t2id int unsigned primary key , t1id int unsigned references tab1(t1id), t2tval datetime ) engine=innodb;   alter table tab2 modify t1id int unsigned not null , modify t2tval timestamp (3); show create table tab2; If I declare tab2.t1id with not null to begin with, or if I omit one of the modify clauses, this will succeed. Else: 10.11 5b89cab44f409d3774b6c8255dfd2c72b2ade1af mysqltest: At line 10: query 'alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3)' failed: ER_FK_COLUMN_CANNOT_CHANGE (1832): Cannot change column 't1id': used in a foreign key constraint 'tab2_ibfk_1' This looks like an unintended regression due to MDEV-31086 , and regressions should be fixed at a critical priority.
            marko Marko Mäkelä made changes -
            Field Original Value New Value
            marko Marko Mäkelä made changes -
            Fix Version/s 10.5 [ 23123 ]
            Fix Version/s 10.6 [ 24028 ]
            Fix Version/s 10.11 [ 27614 ]
            Fix Version/s 11.4 [ 29301 ]
            Assignee Thirunarayanan Balathandayuthapani [ thiru ]
            Labels regression
            Priority Minor [ 4 ] Critical [ 2 ]
            marko Marko Mäkelä made changes -
            Status Open [ 1 ] Confirmed [ 10101 ]
            serg Sergei Golubchik made changes -
            Description Testcase with 2 tables
            {code:sql}
            reate table tab1 (
                t1id int unsigned not null auto_increment,
                t1val varchar(30) not null,
                constraint pkt1 primary key (t1id)
            );
            create table tab2 (
                t2id int unsigned not null auto_increment,
                t1id int unsigned,
                t2tval datetime,
                t2nval int,
                constraint pkt2 primary key (t2id)
            );
            alter table tab2 add index FkIdxt2t1id (t1id), add constraint Fkt2t1id foreign key (t1id) references tab1 (t1id);
            {code}
            Altering columns in one statement failes
            {code:sql}alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3), modify t2nval bigint;{code}
            {noformat}
            Cannot change column 't1id': used in a foreign key constraint 'Fkt2t1id'
            {noformat}
            alter not null in seperate statement works, also 2 modify data types
            {code:sql}alter table tab2 modify t1id int unsigned not null;
            alter table tab2 modify t2tval timestamp(3), modify t2nval bigint;{code}
            Testcase with 2 tables
            {code:sql}
            create table tab1 (
                t1id int unsigned not null auto_increment,
                t1val varchar(30) not null,
                constraint pkt1 primary key (t1id)
            );
            create table tab2 (
                t2id int unsigned not null auto_increment,
                t1id int unsigned,
                t2tval datetime,
                t2nval int,
                constraint pkt2 primary key (t2id)
            );
            alter table tab2 add index FkIdxt2t1id (t1id), add constraint Fkt2t1id foreign key (t1id) references tab1 (t1id);
            {code}
            Altering columns in one statement failes
            {code:sql}alter table tab2 modify t1id int unsigned not null, modify t2tval timestamp(3), modify t2nval bigint;{code}
            {noformat}
            Cannot change column 't1id': used in a foreign key constraint 'Fkt2t1id'
            {noformat}
            alter not null in seperate statement works, also 2 modify data types
            {code:sql}alter table tab2 modify t1id int unsigned not null;
            alter table tab2 modify t2tval timestamp(3), modify t2nval bigint;{code}
            thiru Thirunarayanan Balathandayuthapani made changes -
            Status Confirmed [ 10101 ] In Progress [ 3 ]
            thiru Thirunarayanan Balathandayuthapani made changes -
            Assignee Thirunarayanan Balathandayuthapani [ thiru ] Marko Mäkelä [ marko ]
            Status In Progress [ 3 ] In Review [ 10002 ]
            thiru Thirunarayanan Balathandayuthapani made changes -
            Summary alter foreign key column failed in combination 2nd modify column Inplace algorithm violates the foreign key constraint

            As far as I can tell, we should allow the addition or removal of NOT NULL in parent or child tables, except in the following cases:

            • A child column is NOT NULL REFERENCES … ON UPDATE CASCADE and the parent column allows NULL values
            • A child column is NOT NULL REFERENCES … ON UPDATE SET NULL
            • A child column is NOT NULL REFERENCES … ON DELETE SET NULL

            I think that the last two rules should be enforced even with foreign_key_checks=0. For the first rule to be enforced, the parent table must exist. A later CREATE TABLE of the parent probably shouldn’t flag an error, but we should test what happens on subsequent DML that would attempt to update the child column to NULL.

            On an ALTER TABLE of a parent, I think that we need to flag an error for the first case.

            marko Marko Mäkelä added a comment - As far as I can tell, we should allow the addition or removal of NOT NULL in parent or child tables, except in the following cases: A child column is NOT NULL REFERENCES … ON UPDATE CASCADE and the parent column allows NULL values A child column is NOT NULL REFERENCES … ON UPDATE SET NULL A child column is NOT NULL REFERENCES … ON DELETE SET NULL I think that the last two rules should be enforced even with foreign_key_checks=0 . For the first rule to be enforced, the parent table must exist. A later CREATE TABLE of the parent probably shouldn’t flag an error, but we should test what happens on subsequent DML that would attempt to update the child column to NULL . On an ALTER TABLE of a parent, I think that we need to flag an error for the first case.
            marko Marko Mäkelä made changes -
            Assignee Marko Mäkelä [ marko ] Thirunarayanan Balathandayuthapani [ thiru ]
            Status In Review [ 10002 ] Stalled [ 10000 ]
            thiru Thirunarayanan Balathandayuthapani made changes -
            Summary Inplace algorithm violates the foreign key constraint Nullability of the foreign key column fails to check foreign key constraint
            thiru Thirunarayanan Balathandayuthapani made changes -
            Summary Nullability of the foreign key column fails to check foreign key constraint Null-ability of the column fails to check foreign key constraint
            thiru Thirunarayanan Balathandayuthapani made changes -
            Summary Null-ability of the column fails to check foreign key constraint modification of the column fails to check foreign key constraint
            thiru Thirunarayanan Balathandayuthapani made changes -
            Assignee Thirunarayanan Balathandayuthapani [ thiru ] Marko Mäkelä [ marko ]
            Status Stalled [ 10000 ] In Review [ 10002 ]
            thiru Thirunarayanan Balathandayuthapani made changes -
            Assignee Marko Mäkelä [ marko ] Debarun Banerjee [ JIRAUSER54513 ]

            From thiru's explanation the difference in behaviour is actually related to the underlying algorithm (copy/inplace) being used. The modification of the other type forces COPY algorithm and the error is thrown from this path. The inplace algorithm is doing the right thing. Here is a simpler test to demonstrate the difference.

            create table t1 (id int primary key) engine=innodb;
            create table t2 (id int primary key, id_parent int references t1(id)) engine=innodb;
            

            MariaDB [test]> alter table t2 modify id_parent int not null, algorithm=copy;
            

            ERROR 1832 (HY000): Cannot change column 'id_parent': used in a foreign key constraint 't2_ibfk_1'
            

            MariaDB [test]> alter table t2 modify id_parent int not null, algorithm=inplace;
            

            Query OK, 0 rows affected (0.746 sec)
            

            Thanks thiru for fixing the issue. I am now reviewing the code changes.

            debarun Debarun Banerjee added a comment - From thiru 's explanation the difference in behaviour is actually related to the underlying algorithm (copy/inplace) being used. The modification of the other type forces COPY algorithm and the error is thrown from this path. The inplace algorithm is doing the right thing. Here is a simpler test to demonstrate the difference. create table t1 (id int primary key ) engine=innodb; create table t2 (id int primary key , id_parent int references t1(id)) engine=innodb; MariaDB [test]> alter table t2 modify id_parent int not null , algorithm=copy; ERROR 1832 (HY000): Cannot change column 'id_parent': used in a foreign key constraint 't2_ibfk_1' MariaDB [test]> alter table t2 modify id_parent int not null , algorithm=inplace; Query OK, 0 rows affected (0.746 sec) Thanks thiru for fixing the issue. I am now reviewing the code changes.
            debarun Debarun Banerjee made changes -
            Assignee Debarun Banerjee [ JIRAUSER54513 ] Thirunarayanan Balathandayuthapani [ thiru ]
            svh Stefan van Hasselt made changes -
            Affects Version/s 11.4.2 [ 29633 ]
            julien.fritsch Julien Fritsch made changes -
            Status In Review [ 10002 ] Stalled [ 10000 ]
            julien.fritsch Julien Fritsch made changes -
            Status Stalled [ 10000 ] In Progress [ 3 ]
            thiru Thirunarayanan Balathandayuthapani made changes -
            Fix Version/s 10.5.27 [ 29902 ]
            Fix Version/s 10.5 [ 23123 ]
            Fix Version/s 10.6 [ 24028 ]
            Fix Version/s 10.11 [ 27614 ]
            Fix Version/s 11.4 [ 29301 ]
            Resolution Fixed [ 1 ]
            Status In Progress [ 3 ] Closed [ 6 ]
            JIraAutomate JiraAutomate made changes -
            Fix Version/s 10.6.20 [ 29903 ]
            Fix Version/s 10.11.10 [ 29904 ]
            Fix Version/s 11.2.6 [ 29906 ]
            Fix Version/s 11.4.4 [ 29907 ]
            danblack Daniel Black made changes -
            danblack Daniel Black made changes -
            serg Sergei Golubchik made changes -
            marko Marko Mäkelä made changes -

            People

              thiru Thirunarayanan Balathandayuthapani
              svh Stefan van Hasselt
              Votes:
              1 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.