Bug #46867 Support SQL 2003 SYMMETRIC/ASYMMETRIC options for BETWEEN clause

Submitted: 23 Aug 2009 1:32 Modified: 23 Aug 2009 10:12
Reporter: Justin Swanhart Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: General Severity:S4 (Feature request)
Version:5.4.1, 5.1.15,5.0.51a OS:Linux (CentOS 5.2)
Assigned to: CPU Architecture:Any

[23 Aug 2009 1:32] Justin Swanhart
Description:
This query (between 1 and 2) returns results:
---------------------------
select d.i1, count(*) from f join d using(i1) where d.i2=1 and f.i1 between 1 and 2;

This query returns empty set and the EXPLAIN plan detects and "impossible where clause", which is clearly not impossible:
---------------------------
select d.i1, count(*) from f join d using(i1) where d.i2=1 and f.i1 between 2 and 1;

I encountered this bug on an older 5.1, then tested on newest 5.4 and found the exact same problem.  This may be a problem in many versions.

How to repeat:
mysql> create table f ( id bigint auto_increment primary key, i1 tinyint ) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into f values (null, 1),(null,2),(null,3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> create table d (i1 tinyint, i2 tinyint, primary key(i1,i2)) engine=myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into d values (1,1),(1,2),(2,1),(2,2),(3,1),(3,2);
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> explain select d.i1, count(*) 
          from f join d
         using(i1) 
         where d.i2=1 
           and f.i1 between 1 and 2;
+----+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref                | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------+
|  1 | SIMPLE      | f     | ALL    | NULL          | NULL    | NULL    | NULL               |    3 | Using where |
|  1 | SIMPLE      | d     | eq_ref | PRIMARY       | PRIMARY | 2       | example.f.i1,const |    1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+--------------------+------+-------------+
2 rows in set (0.00 sec)

mysql> explain select d.i1, count(*) 
          from f join d 
         using(i1) 
          where d.i2=1 
           and f.i1 between 2 and 1;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                                               |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE noticed after reading const tables |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
1 row in set (0.00 sec)
[23 Aug 2009 1:45] Justin Swanhart
here is an easy way to duplicate w/out creating any tables:

mysql> select 1 from dual where 5 between 1 and 10;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> select 1 from dual where 5 between 10 and 1;
Empty set (0.00 sec)
[23 Aug 2009 2:11] Justin Swanhart
duplicated on 5.0.51a as well:

[root@localhost mysql]# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1 to server version: 5.0.51a-debug-log

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

mysql> (select 'Yes' from dual where 5 between 10 and 1 ) union (select 'No') limit 1;
+-----+
| Yes |
+-----+
| No  | 
+-----+
1 row in set (0.08 sec)

mysql>
[23 Aug 2009 7:00] Valeriy Kravchuk
Sorry, but this is NOT a bug. c BETWEEN a AND b is always interpreted as:

(c >= a) and (c <= b)

so if b < a there are no rows that can match this condition. Read http://dev.mysql.com/doc/refman/5.1/en/comparison-operators.html#operator_between also.
[23 Aug 2009 9:09] Justin Swanhart
Then an error should be raised in min is greater than max.  The empty result is wrong.

Regardless, I am reopening as feature request for the SQL2003 standard BETWEEN clause:
From the SQL:2003 spec, foundation, section 8.3:

<between predicate part 2> ::= 
    [ NOT ] BETWEEN [ ASYMMETRIC | SYMMETRIC ] 
    <row value predicand> AND <row value predicand> 

1) If neither SYMMETRIC nor ASYMMETRIC is specified, then ASYMMETRIC is implicit. 
...
6) “X BETWEEN ASYMMETRIC Y AND Z” is equivalent to “X>=Y AND X<=Z”.
[23 Aug 2009 9:10] Justin Swanhart
Changed synopsis.
[23 Aug 2009 10:00] Bradley Kuszmaul
I agree that it's not a bug.  As far as I can tell, the mysql behavior matches the SQL:2003 standard.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.040 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.