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

Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

Details

    Description

      Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

      SET sql_mode='';
      SET time_zone='+00:00';
      CREATE OR REPLACE TABLE t1 (a TIMESTAMP);
      INSERT INTO t1 VALUES ('0000-00-00 00:00:00');
      SELECT * FROM t1;
      

      +---------------------+
      | a                   |
      +---------------------+
      | 0000-00-00 00:00:00 |
      +---------------------+
      

      CREATE OR REPLACE TABLE t2 (a datetime);
      INSERT INTO t2 SELECT a FROM t1;
      SELECT * FROM t2;
      

      +---------------------+
      | a                   |
      +---------------------+
      | 1970-01-01 00:00:00 |
      +---------------------+
      

      Looks wrong. The zero datetime was erroneously re-interpreted as '1970-01-01 00:00:00'.

      Note, if I wrap the column t2.a into COALESCE(), it works OK:

      INSERT INTO t2 SELECT COALESCE(a) FROM t1;
      SELECT * FROM t2;
      

      +---------------------+
      | a                   |
      +---------------------+
      | 1970-01-01 00:00:00 |
      | 0000-00-00 00:00:00 |
      +---------------------+
      

      The problem resides in this code:

      int Field_timestamp::save_in_field(Field *to)
      {
        ulong sec_part;
        my_time_t ts= get_timestamp(&sec_part);
        return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
      }
      

      It should not call store_timestamp_dec() for zero datetime, as this method knows nothing about zero datetime. It can store only real timestamp values.

      A proposed fix:

      int Field_timestamp::save_in_field(Field *to)
      {
        ulong sec_part;
        my_time_t ts= get_timestamp(&sec_part);
        if (!ts && ! sec_part)
          return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals());
        return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
      }
      

      Attachments

        Issue Links

          Activity

            bar Alexander Barkov created issue -
            bar Alexander Barkov made changes -
            Field Original Value New Value
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            Description Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

            {code:sql}
            SET sql_mode=DEFAULT;
            SET time_zone='+00:00';
            CREATE OR REPLACE TABLE t1 (a TIMESTAMP);
            INSERT INTO t1 VALUES (0);
            SELECT * FROM t1;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            {code:sql}
            CREATE OR REPLACE TABLE t2 (a datetime);
            INSERT INTO t2 SELECT a FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            +---------------------+
            {noformat}

            Looks wrong. The zero datetime was erroneously re-interpreted as '1970-01-01 00:00:00'.

            Note, if I wrap the column t2.a into COALESCE(), it works OK:

            {code:sql}
            INSERT INTO t2 SELECT COALESCE(a) FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            The problem resides in this code:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}

            It should not call store_timestamp_dec() for zero datetime, as this method knows nothing about zero datetime. It can store only real timestamp values.

            A proposed fix:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              if (!ts && ! sec_part)
                return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals());
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}
            Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

            {code:sql}
            SET sql_mode='';
            SET time_zone='+00:00';
            CREATE OR REPLACE TABLE t1 (a TIMESTAMP);
            INSERT INTO t1 VALUES (0);
            SELECT * FROM t1;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            {code:sql}
            CREATE OR REPLACE TABLE t2 (a datetime);
            INSERT INTO t2 SELECT a FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            +---------------------+
            {noformat}

            Looks wrong. The zero datetime was erroneously re-interpreted as '1970-01-01 00:00:00'.

            Note, if I wrap the column t2.a into COALESCE(), it works OK:

            {code:sql}
            INSERT INTO t2 SELECT COALESCE(a) FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            The problem resides in this code:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}

            It should not call store_timestamp_dec() for zero datetime, as this method knows nothing about zero datetime. It can store only real timestamp values.

            A proposed fix:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              if (!ts && ! sec_part)
                return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals());
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}
            bar Alexander Barkov made changes -
            Description Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

            {code:sql}
            SET sql_mode='';
            SET time_zone='+00:00';
            CREATE OR REPLACE TABLE t1 (a TIMESTAMP);
            INSERT INTO t1 VALUES (0);
            SELECT * FROM t1;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            {code:sql}
            CREATE OR REPLACE TABLE t2 (a datetime);
            INSERT INTO t2 SELECT a FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            +---------------------+
            {noformat}

            Looks wrong. The zero datetime was erroneously re-interpreted as '1970-01-01 00:00:00'.

            Note, if I wrap the column t2.a into COALESCE(), it works OK:

            {code:sql}
            INSERT INTO t2 SELECT COALESCE(a) FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            The problem resides in this code:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}

            It should not call store_timestamp_dec() for zero datetime, as this method knows nothing about zero datetime. It can store only real timestamp values.

            A proposed fix:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              if (!ts && ! sec_part)
                return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals());
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}
            Zero datetime reinterprets as '1970-01-01 00:00:00' on field_datetime=field_timestamp

            {code:sql}
            SET sql_mode='';
            SET time_zone='+00:00';
            CREATE OR REPLACE TABLE t1 (a TIMESTAMP);
            INSERT INTO t1 VALUES ('0000-00-00 00:00:00');
            SELECT * FROM t1;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            {code:sql}
            CREATE OR REPLACE TABLE t2 (a datetime);
            INSERT INTO t2 SELECT a FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            +---------------------+
            {noformat}

            Looks wrong. The zero datetime was erroneously re-interpreted as '1970-01-01 00:00:00'.

            Note, if I wrap the column t2.a into COALESCE(), it works OK:

            {code:sql}
            INSERT INTO t2 SELECT COALESCE(a) FROM t1;
            SELECT * FROM t2;
            {code}
            {noformat}
            +---------------------+
            | a |
            +---------------------+
            | 1970-01-01 00:00:00 |
            | 0000-00-00 00:00:00 |
            +---------------------+
            {noformat}


            The problem resides in this code:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}

            It should not call store_timestamp_dec() for zero datetime, as this method knows nothing about zero datetime. It can store only real timestamp values.

            A proposed fix:
            {code:cpp}
            int Field_timestamp::save_in_field(Field *to)
            {
              ulong sec_part;
              my_time_t ts= get_timestamp(&sec_part);
              if (!ts && ! sec_part)
                return to->store_time_dec(Datetime::zero().get_mysql_time(), decimals());
              return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
            }
            {code}
            bar Alexander Barkov made changes -
            issue.field.resolutiondate 2024-05-04 19:31:42.0 2024-05-04 19:31:42.397
            bar Alexander Barkov made changes -
            Fix Version/s 10.5.25 [ 29626 ]
            Fix Version/s 10.6.18 [ 29627 ]
            Fix Version/s 10.11.8 [ 29630 ]
            Fix Version/s 11.1.5 [ 29629 ]
            Fix Version/s 11.2.4 [ 29631 ]
            Fix Version/s 11.4.2 [ 29633 ]
            Fix Version/s 11.5.1 [ 29634 ]
            Fix Version/s 11.3.2 [ 29522 ]
            Fix Version/s 11.0.1 [ 28548 ]
            Fix Version/s 10.5 [ 23123 ]
            Resolution Fixed [ 1 ]
            Status Open [ 1 ] Closed [ 6 ]
            bar Alexander Barkov made changes -
            julien.fritsch Julien Fritsch made changes -
            Fix Version/s 11.0.6 [ 29628 ]
            Fix Version/s 11.0.1 [ 28548 ]

            People

              bar Alexander Barkov
              bar Alexander Barkov
              Votes:
              0 Vote for this issue
              Watchers:
              1 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.