Bug #25580 The Parsing difers from a direct select to a create view

Submitted: 12 Jan 2007 11:53 Modified: 8 Feb 2007 18:16
Reporter: João Mota Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Views Severity:S2 (Serious)
Version:5.0.34-BK, 5.0.27-community OS:Linux (Linux, WIN32)
Assigned to: Igor Babaev CPU Architecture:Any

[12 Jan 2007 11:53] João Mota
Description:
I ran into some diferences in results when executing a query and executing the same query as a view using the function not when trying to avoid an IF().

How to repeat:
> select !0 * 5 as X;

  returns 5

> create view test as
   select !0 * 5 as X;
> select * from test;

  returns 1

Suggested fix:
I know I should use extra parentisis but either way the results should be the same . I imagine that the create view parser is a little more thorough than the query parser. I should at least get a warning when creating the view that the results may differ from the direct query.
[12 Jan 2007 12:37] Valeriy Kravchuk
Thank you for a bug report. Verified just as described with latest 5.0.34-BK on Linux:

openxs@suse:~/dbs/5.0> bin/mysql -uroot test
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.34-debug Source distribution

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

mysql> select !0*5 as x;
+---+
| x |
+---+
| 5 |
+---+
1 row in set (0.00 sec)

mysql> create table tt as select !0*5 as x;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> show create table tt\G
*************************** 1. row ***************************
       Table: tt
Create Table: CREATE TABLE `tt` (
  `x` int(3) NOT NULL default '0'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

mysql> select * from tt;
+---+
| x |
+---+
| 5 |
+---+
1 row in set (0.01 sec)

mysql> create view tv as select !0*5 as x;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from tv;
+---+
| x |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> show create view tv\G
*************************** 1. row ***************************
       View: tv
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY
DEFINER VIEW `tv` AS select not((0 * 5)) AS `x`
1 row in set (0.00 sec)

So, as we can see, view is created incorrectly.
[17 Jan 2007 22:39] Igor Babaev
This problem can be demostrated without using views:

mysql> SELECT (not(0) * 5) AS X FROM DUAL;
+---+
| X |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

mysql> EXPLAIN EXTENDED SELECT (not(0) * 5) AS X FROM DUAL;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------+
| Level | Code | Message                    |
+-------+------+----------------------------+
| Note  | 1003 | select not((0 * 5)) AS `X` |
+-------+------+----------------------------+
1 row in set (0.00 sec)

The problem is not observed for 4.1 though:

mysql> SELECT VERSION();
+--------------+
| VERSION()    |
+--------------+
| 4.1.23-debug |
+--------------+
1 row in set (0.00 sec)

mysql> EXPLAIN EXTENDED SELECT (not(0) * 5) AS X FROM DUAL;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL |    NULL | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------+
| Level | Code | Message                    |
+-------+------+----------------------------+
| Note  | 1003 | select (not(0) * 5) AS `X` |
+-------+------+----------------------------+
1 row in set (0.00 sec)
[18 Jan 2007 2:08] Igor Babaev
The following result can be explained by the fact that 'not' has a lower precedence than '*': 

mysql> SELECT (not(0) * 5) AS X FROM DUAL;
+---+
| X |
+---+
| 1 |
+---+

If we make 'not' to have the highest precedence the result is different:

mysql> SET sql_mode = HIGH_NOT_PRECEDENCE;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT (not(0) * 5) AS X FROM DUAL;
+---+
| X |
+---+
| 5 |
+---+
1 row in set (0.00 sec)

mysql> EXPLAIN EXTENDED SELECT (not(0) * 5) AS X FROM DUAL;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------+
| Level | Code | Message                    |
+-------+------+----------------------------+
| Note  | 1003 | select (not(0) * 5) AS `X` |
+-------+------+----------------------------+
1 row in set (0.00 sec)

However '!' has a higher precedence than '*'.

This explains why we have the correct result if we use '!' instead of 'not':

mysql> SELECT (!(0) * 5) AS X FROM DUAL;
+---+
| X |
+---+
| 5 |
+---+
1 row in set (0.00 sec)

The problem with views is that in internal stored representations of views any '!' operator is always replaced by a 'not' operator. 
This problem can be resolved by putting expressions under 'not' into parentheses.
[18 Jan 2007 4:11] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/18306

ChangeSet@1.2385, 2007-01-17 20:13:45-08:00, igor@olga.mysql.com +6 -0
  Fixed bug #25580: incorrect stored representations of views in cases
  when they contain the '!' operator.
  Added an implementation for the method Item_func_not::print. 
  The method encloses any NOT expression into extra parentheses to avoid
  incorrect stored representations of views that use the '!' operators.
  Without this change when a view was created that contained
  the expression !0*5  its stored representation contained not this
  expression but rather the expression not(0)*5 . 
  The operator '!' is of a higher precedence than '*', while NOT is 
  of a lower precedence than '*'. That's why the expression !0*5 
  is interpreted as not(0)*5, while the expression not(0)*5 is interpreted
  as not((0)*5) unless sql_mode is set to HIGH_NOT_PRECEDENCE.
  Now we translate !0*5 into (not(0))*5.
[28 Jan 2007 2:26] Igor Babaev
The fix has been pushed into 5.0.36, 5.1.16-beta main trees.
[8 Feb 2007 18:16] Paul DuBois
Noted in 5.0.36, 5.1.16 changelogs.

View definitions that used the ! operator were treated as containing
the NOT operator, which has a different precedence and can produce
different results.

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

Page generated in 0.044 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.