Bug #32006 subquery parsing with
Submitted: 31 Oct 2007 20:37 Modified: 15 Nov 2007 3:34
Reporter: Justin Swanhart Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: Parser Severity:S3 (Non-critical)
Version:5.0.37 OS:Linux (OpenSuse 10.2)
Assigned to: CPU Architecture:Any
Tags: ambiguous, dependent subquery, Optimizer, parser, subquery

[31 Oct 2007 20:37] Justin Swanhart
Description:
drop table if exists test1;
drop table if exists test2;

create table test1(id int auto_increment primary key, fk_id int);
insert into test1 (fk_id) values (1),(2),(3);

create table test2(test2_id int auto_increment primary key, fk_val int);
insert into test2(fk_val) values (1),(2),(3);

-- This parses as a DEPENDENT SUBQUERY  
-- It shouldn't be dependent.  It should be a regular SUBQUERY, resolved first -- (and the parse should fail) but given the name resolution rules, it appears
-- that outer resolves after inner and this query works because of that.
-- this may or may not be a bug.

explain
select * from test1 
 where id = (select fk_id from test2 where fk_val = 2);
-- +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
-- | id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
-- +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
-- |  1 | PRIMARY            | test1 | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where |
-- |  2 | DEPENDENT SUBQUERY | test2 | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where |
-- +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
-- 2 rows in set (0.00 sec)

-- returns three rows.  I only expected 1 (or an error)
select * from test1;

-- +----+-------+
-- | id | fk_id |
-- +----+-------+
-- |  1 |     1 |
-- |  2 |     2 |
-- |  3 |     3 |
-- +----+-------+
-- 3 rows in set (0.00 sec)

-- Add a column with the same name as the outer table 
-- I hoped this would result in an ambiguous column error given the 
-- resolution rules of inner/outer and the column being defined in both 
-- tables
alter table test2 add fk_id int default 1;

-- This now parses as a SUBQUERY because fk_id is located in the 
-- both tables, but it uses the column from the second table and never
-- looks to see that the column is ambiguous with the outer

-- I would expect a warning or an error because the column is ambiguous
explain
select * from test1 
 where id = (select fk_id from test2 where fk_val = 2);

-- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
-- | id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra       |
-- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
-- |  1 | PRIMARY     | test1 | const | PRIMARY       | PRIMARY | 4       | const |    1 |             |
-- |  2 | SUBQUERY    | test2 | ALL   | NULL          | NULL    | NULL    | NULL  |    3 | Using where |
-- +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
-- 2 rows in set (0.00 sec)

-- returns only 1 row
select * from test1 
 where id = (select fk_id from test2 where fk_val = 2);

-- +----+-------+
-- | id | fk_id |
-- +----+-------+
-- |  1 |     1 |
-- +----+-------+
-- 1 row in set (0.00 sec)

How to repeat:
run above script
[31 Oct 2007 20:40] Justin Swanhart
Both test queries should read:
select * from test1  where id = (select fk_id from test2 where fk_val = 2);

The subselect wasn't included in the first example.  

Sorry about that.
[14 Nov 2007 20:23] Sveta Smirnova
Thank you for taking the time to write to us, but this is not a bug. Please double-check the documentation available at http://dev.mysql.com/doc/ and the instructions on
how to report a bug at http://bugs.mysql.com/how-to-report.php

There is no fk_id field in table test2 when you issue first statement. So behaviur is expected.

See also http://dev.mysql.com/doc/refman/5.0/en/correlated-subqueries.html
[15 Nov 2007 3:34] Justin Swanhart
The second statement should still _at least_ issue a warning.

The column is definitely AMBIGUOUS in the second statement.