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

FLOOR()/CEIL() incorrectly calculate the precision of a DECIMAL(M,D) column.

Details

    • Bug
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 10.1(EOL), 10.2(EOL), 10.3(EOL), 10.4(EOL), 10.5
    • 10.4.16, 10.5.7
    • Data types
    • None

    Description

      MariaDB [test]> create table i1 (a decimal(38,10));
      Query OK, 0 rows affected (0.057 sec)
       
      MariaDB [test]> create table i2 as select floor(a), ceil(a) from i1;
      Query OK, 0 rows affected (0.019 sec)
      Records: 0  Duplicates: 0  Warnings: 0
       
      MariaDB [test]> show create table i2;
      +-------+--------------------------------------------------------------------------------------------------------------------------------------------+
      | Table | Create Table                                                                                                                               |
      +-------+--------------------------------------------------------------------------------------------------------------------------------------------+
      | i2    | CREATE TABLE `i2` (
        `floor(a)` decimal(28,0) DEFAULT NULL,
        `ceil(a)` decimal(28,0) DEFAULT NULL
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
      +-------+--------------------------------------------------------------------------------------------------------------------------------------------+
      1 row in set (0.001 sec)
       
      MariaDB [test]> insert into i1 values (9999999999999999999999999999.9999999999), (-9999999999999999999999999999.9999999999);
      Query OK, 2 rows affected (0.002 sec)
      Records: 2  Duplicates: 0  Warnings: 0
       
      MariaDB [test]> create table i3 as select floor(a), ceil(a) from i1;
      ERROR 1264 (22003): Out of range value for column 'ceil(a)' at row 1
      MariaDB [test]> create table i3 as select floor(a) from i1;
      ERROR 1264 (22003): Out of range value for column 'floor(a)' at row 2
      

      For DECIMAL(M,0), i2 should have M=29, instead of M=28 as in the above. This is because M can exceed by 1 for FLOOR/CEIL functions, for example, when we insert the 2 rows into i1, the result of the functions would contain 29 digits, instead of 28.

      Attachments

        Issue Links

          Activity

            tntnatbry Gagan Goel (Inactive) created issue -
            tntnatbry Gagan Goel (Inactive) made changes -
            Field Original Value New Value
            Attachment MDEV-23032.patch [ 52411 ]

            MDEV-23032.patch

            Attached is a quick patch I wrote to get this case working.

            tntnatbry Gagan Goel (Inactive) added a comment - MDEV-23032.patch Attached is a quick patch I wrote to get this case working.
            tntnatbry Gagan Goel (Inactive) made changes -
            elenst Elena Stepanova made changes -
            Fix Version/s 10.5 [ 23123 ]
            bar Alexander Barkov added a comment - - edited

            Update: this problem was fixed by MDEV-23320

            A related problem:

            CREATE OR REPLACE TABLE t1 AS SELECT floor(0xffffffffff);
            

            ERROR 1264 (22003): Out of range value for column 'floor(0xffffffffff)' at row 1
            

            bar Alexander Barkov added a comment - - edited Update: this problem was fixed by MDEV-23320 A related problem: CREATE OR REPLACE TABLE t1 AS SELECT floor(0xffffffffff); ERROR 1264 (22003): Out of range value for column 'floor(0xffffffffff)' at row 1
            bar Alexander Barkov added a comment - - edited

            A related problem (now reported in MDEV-23323):

            CREATE OR REPLACE TABLE t1 (a BIT(64));
            CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1;
            DESC t2;
            

            +----------+---------------+------+-----+---------+-------+
            | Field    | Type          | Null | Key | Default | Extra |
            +----------+---------------+------+-----+---------+-------+
            | FLOOR(a) | decimal(64,0) | YES  |     | NULL    |       |
            +----------+---------------+------+-----+---------+-------+
            

            Looks redundant. A DECIMAL(19,0) or even a BIGINT() column would be enough.

            bar Alexander Barkov added a comment - - edited A related problem (now reported in MDEV-23323 ): CREATE OR REPLACE TABLE t1 (a BIT (64)); CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1; DESC t2; +----------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------------+------+-----+---------+-------+ | FLOOR(a) | decimal(64,0) | YES | | NULL | | +----------+---------------+------+-----+---------+-------+ Looks redundant. A DECIMAL(19,0) or even a BIGINT() column would be enough.
            bar Alexander Barkov added a comment - - edited

            Update: This problem was fixed by MDEV-23323

            A related problem:

            CREATE OR REPLACE TABLE t1 (a SET('1000000000000000000000000000000000000000000000000000000000000000000000000000000000000'));
            INSERT INTO t1 VALUES (1);
            CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1;
            SELECT * FROM t2;
            DESC t2;
            

            +----------+
            | FLOOR(a) |
            +----------+
            |        1 |
            +----------+
            

            +----------+---------------+------+-----+---------+-------+
            | Field    | Type          | Null | Key | Default | Extra |
            +----------+---------------+------+-----+---------+-------+
            | FLOOR(a) | decimal(65,0) | YES  |     | NULL    |       |
            +----------+---------------+------+-----+---------+-------+
            

            Looks redundant. In numeric context SET can return a value beween 0 and 0xFF or between and 0xFFFF, depending on the amount of values in SET. INT should be enough (or even TINYINT/SMALLINT).

            bar Alexander Barkov added a comment - - edited Update: This problem was fixed by MDEV-23323 A related problem: CREATE OR REPLACE TABLE t1 (a SET ( '1000000000000000000000000000000000000000000000000000000000000000000000000000000000000' )); INSERT INTO t1 VALUES (1); CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1; SELECT * FROM t2; DESC t2; +----------+ | FLOOR(a) | +----------+ | 1 | +----------+ +----------+---------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------------+------+-----+---------+-------+ | FLOOR(a) | decimal(65,0) | YES | | NULL | | +----------+---------------+------+-----+---------+-------+ Looks redundant. In numeric context SET can return a value beween 0 and 0xFF or between and 0xFFFF, depending on the amount of values in SET. INT should be enough (or even TINYINT/SMALLINT).
            bar Alexander Barkov added a comment - - edited

            Update 2020-06-29: The problem described below was fixed under terms of MDEV-23311. FLOOR(TIME) and CEILING(TIME) now return TIME rather than BIGINT.

            A related problem:

            CREATE OR REPLACE TABLE t1 (a TIME(6));
            INSERT INTO t1 VALUES ('10:20:30');
            CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1;
            SELECT * FROM t2;
            DESC t2;
            

            +----------+
            | FLOOR(a) |
            +----------+
            |   102030 |
            +----------+
            

            +----------+------------+------+-----+---------+-------+
            | Field    | Type       | Null | Key | Default | Extra |
            +----------+------------+------+-----+---------+-------+
            | FLOOR(a) | bigint(12) | YES  |     | NULL    |       |
            +----------+------------+------+-----+---------+-------+
            

            Looks redundant. FLOOR(time) should never return more than 9 digits (hhhmmss). So INT(9) should be enough.

            Or even better TIME(0), like in this script:

            CREATE OR REPLACE TABLE t1 (a TIME(6));
            CREATE OR REPLACE TABLE t2 AS SELECT ROUND(a) FROM t1;
            DESC t2;
            

            +----------+------+------+-----+---------+-------+
            | Field    | Type | Null | Key | Default | Extra |
            +----------+------+------+-----+---------+-------+
            | ROUND(a) | time | YES  |     | NULL    |       |
            +----------+------+------+-----+---------+-------+
            

            bar Alexander Barkov added a comment - - edited Update 2020-06-29: The problem described below was fixed under terms of MDEV-23311 . FLOOR(TIME) and CEILING(TIME) now return TIME rather than BIGINT. A related problem: CREATE OR REPLACE TABLE t1 (a TIME (6)); INSERT INTO t1 VALUES ( '10:20:30' ); CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(a) FROM t1; SELECT * FROM t2; DESC t2; +----------+ | FLOOR(a) | +----------+ | 102030 | +----------+ +----------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+------------+------+-----+---------+-------+ | FLOOR(a) | bigint(12) | YES | | NULL | | +----------+------------+------+-----+---------+-------+ Looks redundant. FLOOR(time) should never return more than 9 digits (hhhmmss). So INT(9) should be enough. Or even better TIME(0), like in this script: CREATE OR REPLACE TABLE t1 (a TIME (6)); CREATE OR REPLACE TABLE t2 AS SELECT ROUND(a) FROM t1; DESC t2; +----------+------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+------+------+-----+---------+-------+ | ROUND(a) | time | YES | | NULL | | +----------+------+------+-----+---------+-------+
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            Affects Version/s 10.1 [ 16100 ]
            Affects Version/s 10.2 [ 14601 ]
            Affects Version/s 10.3 [ 22126 ]
            Affects Version/s 10.4 [ 22408 ]
            Affects Version/s 10.5 [ 23123 ]
            Affects Version/s 10.5.3 [ 24263 ]
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            bar Alexander Barkov made changes -
            issue.field.resolutiondate 2020-08-04 04:14:27.0 2020-08-04 04:14:27.583
            bar Alexander Barkov made changes -
            Fix Version/s 10.4.14 [ 24305 ]
            Fix Version/s 10.5.5 [ 24423 ]
            Fix Version/s 10.5 [ 23123 ]
            Resolution Fixed [ 1 ]
            Status Open [ 1 ] Closed [ 6 ]
            dbart Daniel Bartholomew made changes -
            Fix Version/s 10.4.15 [ 24507 ]
            Fix Version/s 10.5.6 [ 24508 ]
            Fix Version/s 10.4.14 [ 24305 ]
            Fix Version/s 10.5.5 [ 24423 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.5.7 [ 25019 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.5.6 [ 24508 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.4.16 [ 25020 ]
            ralf.gebhardt Ralf Gebhardt made changes -
            Fix Version/s 10.4.15 [ 24507 ]
            serg Sergei Golubchik made changes -
            Workflow MariaDB v3 [ 110570 ] MariaDB v4 [ 158030 ]

            People

              bar Alexander Barkov
              tntnatbry Gagan Goel (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              3 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.