Bug #81513 Incorrect result of ROUND with subquery
Submitted: 19 May 2016 19:39 Modified: 23 May 2016 7:15
Reporter: Power Gamer Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: DML Severity:S3 (Non-critical)
Version:5.7.11, 5.7.12, 5.6.30 OS:Windows
Assigned to: CPU Architecture:Any

[19 May 2016 19:39] Power Gamer
Description:
When second argument of ROUND function is specified as subquery that selects from a table the result is rounded correctly but includes extra zeros not present otherwise (see examples in "How to repeat" section).

How to repeat:
SELECT ROUND(1.23456, 2); -- OK: 1.23
SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
SELECT ROUND(1.23456, (SELECT '2' FROM sometable LIMIT 1)); -- WRONG: 1.23000
[20 May 2016 5:23] MySQL Verification Team
Hello!!

Thank you for the report and test case.
Observed that 5.6.30/5.7.12 release builds are affected.

Thanks,
Umesh
[20 May 2016 5:24] MySQL Verification Team
-- 4.1.25->5.5.49 not affected

-- 4.1.25

[umshastr@hod03]/export/umesh/server/binaries/mysql-4.1.25: bin/mysql -uroot -S/tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 4.1.25-classic

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create database if not exists test;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> use test;
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                         1.23 |
+----------------------------------------------+
1 row in set (0.01 sec)

-- 5.0.96

[umshastr@hod03]/export/umesh/server/binaries/mysql-5.0.96: bin/mysql -uroot -S/tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.96 MySQL Community Server (GPL)

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database if not exists test;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> use test;
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                         1.23 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql>

-- 5.1.77

[umshastr@hod03]/export/umesh/server/binaries/mysql-5.1.77: bin/mysql -uroot -S/tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.1.77 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database if not exists test;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> use test;
Database changed
mysql> create table t1(id int);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                         1.23 |
+----------------------------------------------+
1 row in set (0.01 sec)

mysql>

-- 5.5.49

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.5.49: bin/mysql -uroot -S/tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.49-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database if not exists test;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> use test;
Database changed
mysql> drop table if exists t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t1(id int);
insert into t1 values(1);
SELECT ROUND(1.23456, 2); -- OK: 1.23
SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                         1.23 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql>
[20 May 2016 5:25] MySQL Verification Team
-- 5.6.30/5.7.12 affected

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.6.30: bin/mysql -uroot -S/tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.30-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql> create database if not exists test;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> use test;
Database changed
mysql> drop table if exists t1;
insert into t1 values(1);
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t1(id int);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.01 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                      1.23000 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql>

-- 5.7.12

[root@cluster-repo ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 59
Server version: 5.7.12 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database if not exists test;
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> drop table if exists t1;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t1(id int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 values(1);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT ROUND(1.23456, 2); -- OK: 1.23
+-------------------+
| ROUND(1.23456, 2) |
+-------------------+
|              1.23 |
+-------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2')); -- OK: 1.23
+------------------------------+
| ROUND(1.23456, (SELECT '2')) |
+------------------------------+
|                         1.23 |
+------------------------------+
1 row in set (0.00 sec)

mysql> SELECT ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)); -- WRONG: 1.23000
+----------------------------------------------+
| ROUND(1.23456, (SELECT '2' FROM t1 LIMIT 1)) |
+----------------------------------------------+
|                                      1.23000 |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql>
[23 May 2016 7:15] Roy Lyseng
This is not a bug:

MySQL determines the data type of the result column during resolving of the query, which is a process that takes place before reading data from tables.

In the first two examples, the round argument is constant, so it can be used to determine the data type of the result of the ROUND operation.

However, in the third example, we must read data from 'sometable' to determine the argument to ROUND, so MySQL chooses some arbitrary value for the number of decimals (in this case 5), since this value is not available when resolving the query.