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

UPDATE or DELETE FOR PORTION OF increments the value of auto-increment column instead of copying the old one

Details

    Description

      create table t1 (a int auto_increment, b char(16), s date, e date, period for se(s,e), primary key(a,s));
      insert into t1 values (1,'new','2019-01-01','2020-01-01');
      update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1;
      select * from t1;
      delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1;
      select * from t1;
       
      drop table t1;
      

      Actual result, 10.4 503fd211

      update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1;
      select * from t1;
      a	b	s	e
      1	updated	2019-07-01	2020-01-01
      2	new	2019-01-01	2019-07-01
      delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1;
      select * from t1;
      a	b	s	e
      3	updated	2019-10-01	2020-01-01
      2	new	2019-01-01	2019-07-01
      

      The behavior is not specified in the documentation or (as far as I can tell) in the standard, but it seems obviously wrong, although understandable from the implementation point of view.

      Attachments

        Issue Links

          Activity

            After a brief investigation, on b2029c0300bf8c311ff5d9fdc4b73a9e48bf6930, I found that the weird update of the auto-increment column is caused by TABLE::update_generated_fields() in sql/table.cc. Removing update_auto_increment() from update_generated_fields() at least fixes the bug, while I'm not yet so sure about the side effect of the remove.

            nayuta-yanagisawa Nayuta Yanagisawa (Inactive) added a comment - - edited After a brief investigation, on b2029c0300bf8c311ff5d9fdc4b73a9e48bf6930, I found that the weird update of the auto-increment column is caused by TABLE::update_generated_fields() in sql/table.cc. Removing update_auto_increment() from update_generated_fields() at least fixes the bug, while I'm not yet so sure about the side effect of the remove.

            Just to make sure, the expected result is the below, right?

            create table t1 (a int auto_increment, b char(16), s date, e date, period for se(s,e), primary key(a,s));
            insert into t1 values (1,'new','2019-01-01','2020-01-01');
            update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1;
            select * from t1;
            a       b       s       e
            1       updated 2019-07-01      2020-01-01
            1       new     2019-01-01      2019-07-01
            delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1;
            select * from t1;
            a       b       s       e
            1       updated 2019-10-01      2020-01-01
            1       new     2019-01-01      2019-03-01
            drop table t1;
            

            nayuta-yanagisawa Nayuta Yanagisawa (Inactive) added a comment - Just to make sure, the expected result is the below, right? create table t1 (a int auto_increment, b char (16), s date , e date , period for se(s,e), primary key (a,s)); insert into t1 values (1, 'new' , '2019-01-01' , '2020-01-01' ); update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1; select * from t1; a b s e 1 updated 2019-07-01 2020-01-01 1 new 2019-01-01 2019-07-01 delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1; select * from t1; a b s e 1 updated 2019-10-01 2020-01-01 1 new 2019-01-01 2019-03-01 drop table t1;

            nayuta-yanagisawa I think the expected result should be "update auto_increment counter when we insert a new record". According to standard, "new" should be inserted, and "updated" should be updated/deleted:

            create table t1 (a int auto_increment, b char(16), s date, e date, period for se(s,e), primary key(a,s));
            insert into t1 values (1,'new','2019-01-01','2020-01-01');
            update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1;
            select * from t1;
            a       b       s       e
            1       updated 2019-07-01      2020-01-01
            2       new     2019-01-01      2019-07-01
            delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1;
            select * from t1;
            a       b       s       e
            3       updated 2019-10-01      2020-01-01
            2       new     2019-01-01      2019-03-01
            drop table t1;
            

            As far as I can see, this is the same as the actual result.

            elenst Please note, how the algorithm works:

            UPDATE t SET x = 'new' FOR PORTION OF p FROM a TO b

            transforms to

            UPDATE t SET x = '"updated", s=a, e=b
            # if row.s < a:
            INSERT t(x, s, e) values ("new", ....)
            # if row.e > b:
            INSERT t(x, s, e) values ("new", ....) 
            

            DELETE FROM t FOR PORTION OF p FROM a TO b

            transforms to

            DELETE FROM t;
            # if row.s < a:
            INSERT t(x, s, e) values (row.x, ....)
            # if row.e > b:
            INSERT t(x, s, e) values (row.x, ....) 
            

            nikitamalyavin Nikita Malyavin added a comment - nayuta-yanagisawa I think the expected result should be "update auto_increment counter when we insert a new record". According to standard, "new" should be inserted, and "updated" should be updated/deleted: create table t1 (a int auto_increment, b char(16), s date, e date, period for se(s,e), primary key(a,s)); insert into t1 values (1,'new','2019-01-01','2020-01-01'); update t1 for portion of se from '2019-07-01' to '2020-07-01' set b = 'updated' where a = 1; select * from t1; a b s e 1 updated 2019-07-01 2020-01-01 2 new 2019-01-01 2019-07-01 delete from t1 for portion of se from '2019-03-01' to '2019-10-01' where a = 1; select * from t1; a b s e 3 updated 2019-10-01 2020-01-01 2 new 2019-01-01 2019-03-01 drop table t1; As far as I can see, this is the same as the actual result. elenst Please note, how the algorithm works: UPDATE t SET x = 'new' FOR PORTION OF p FROM a TO b transforms to UPDATE t SET x = '"updated", s=a, e=b # if row.s < a: INSERT t(x, s, e) values ("new", ....) # if row.e > b: INSERT t(x, s, e) values ("new", ....) DELETE FROM t FOR PORTION OF p FROM a TO b transforms to DELETE FROM t; # if row.s < a: INSERT t(x, s, e) values (row.x, ....) # if row.e > b: INSERT t(x, s, e) values (row.x, ....)

            > I think the expected result should be "update auto_increment counter when we insert a new record".

            This sounds a bit counterintuitive to me but it is reasonable when we interpret insert operations, triggered by UPDATE or DELETE on an application time-period table, as just usual insert operations.

            nayuta-yanagisawa Nayuta Yanagisawa (Inactive) added a comment - - edited > I think the expected result should be "update auto_increment counter when we insert a new record". This sounds a bit counterintuitive to me but it is reasonable when we interpret insert operations, triggered by UPDATE or DELETE on an application time-period table, as just usual insert operations.

            Maybe that's counterintuitive on the one hand, but on the contrary, the INSERT triggers are called as well. It'd be controversial if the INSERT trigger is called, but no autoincrement update happened. And think about what if `a` would be PRIMARY KEY AUTO_INCREMENT – then updates/deletes would fail with duplicate error

            nikitamalyavin Nikita Malyavin added a comment - Maybe that's counterintuitive on the one hand, but on the contrary, the INSERT triggers are called as well. It'd be controversial if the INSERT trigger is called, but no autoincrement update happened. And think about what if `a` would be PRIMARY KEY AUTO_INCREMENT – then updates/deletes would fail with duplicate error

            People

              nikitamalyavin Nikita Malyavin
              elenst Elena Stepanova
              Votes:
              1 Vote for this issue
              Watchers:
              5 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.