From a7bdd19707cd0077560ff50160eb830a0266b43d Mon Sep 17 00:00:00 2001
From: "bell@sanja.is.com.ua" <>
Date: Thu, 16 Oct 2003 15:54:47 +0300
Subject: [PATCH] subqueries made printable new EXPLAIN parameter to show real
 query as it was interpreted (SCRUM) (WL#1274)

---
 mysql-test/r/subselect.result | 156 ++++++++++++++++++++--------
 mysql-test/r/union.result     |   8 +-
 mysql-test/t/subselect.test   |  84 ++++++++--------
 mysql-test/t/union.test       |   4 +-
 sql/item.cc                   | 102 ++++++++++++++-----
 sql/item.h                    |  46 +++------
 sql/item_cmpfunc.cc           |   8 ++
 sql/item_cmpfunc.h            |   6 +-
 sql/item_subselect.cc         | 161 +++++++++++++++++++++++++++--
 sql/item_subselect.h          |  27 +++--
 sql/mysql_priv.h              |   3 +
 sql/sql_derived.cc            |   4 -
 sql/sql_lex.cc                |  66 ++++++++++++
 sql/sql_lex.h                 |  14 ++-
 sql/sql_parse.cc              |  10 ++
 sql/sql_select.cc             | 184 +++++++++++++++++++++++++++++++++-
 sql/sql_select.h              |   7 +-
 sql/sql_yacc.yy               |  26 +++--
 18 files changed, 735 insertions(+), 181 deletions(-)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 6e35b6e78c..e34cd05ead 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2,32 +2,35 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
 select (select 2);
 (select 2)
 2
-explain select (select 2);
+explain extended select (select 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
 Note	1248	Select 2 was reduced during optimisation
+Note	1003	select high_priority 2 AS `(select 2)`
 SELECT (SELECT 1) UNION SELECT (SELECT 2);
 (SELECT 1)
 1
 2
-explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
+explain extended SELECT (SELECT 1) UNION SELECT (SELECT 2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
 Note	1248	Select 2 was reduced during optimisation
 Note	1248	Select 4 was reduced during optimisation
+Note	1003	select high_priority 1 AS `(SELECT 1)` union select 2 AS `(SELECT 2)`
 SELECT (SELECT (SELECT 0 UNION SELECT 0));
 (SELECT (SELECT 0 UNION SELECT 0))
 0
-explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
+explain extended SELECT (SELECT (SELECT 0 UNION SELECT 0));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 3	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 4	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 Warnings:
 Note	1248	Select 2 was reduced during optimisation
+Note	1003	select high_priority (select 0 AS `0` union select 0 AS `0`) AS `(SELECT (SELECT 0 UNION SELECT 0))`
 SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
 ERROR 42S22: Reference 'a' not supported (forward reference in item list)
 SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1) as c HAVING a=1) as b;
@@ -37,7 +40,7 @@ SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a;
 1	1
 SELECT (SELECT a) as a;
 ERROR 42S22: Reference 'a' not supported (forward reference in item list)
-EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b  HAVING (SELECT a)=1;
+EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b  HAVING (SELECT a)=1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	<derived2>	system	NULL	NULL	NULL	NULL	1	
 3	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
@@ -45,6 +48,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 Warnings:
 Note	1275	Field or reference 'a' of SELECT #3 was resolved in SELECT #1
 Note	1275	Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1
+Note	1003	select high_priority 1 AS `1` from (select 1 AS `a`) b having ((select b.a AS `a`) = 1)
 SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
 1
 1
@@ -172,12 +176,14 @@ a	b
 2	7
 3	8
 4	8
-explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	Using where
 2	SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	Using filesort
 3	UNION	t4	ALL	NULL	NULL	NULL	NULL	3	Using where; Using filesort
 4	SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	2	
+Warnings:
+Note	1003	(select high_priority test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.b = (select test.t3.a AS `a` from test.t3 order by test.t3.a desc limit 1))) union (select test.t4.a AS `a`,test.t4.b AS `b` from test.t4 where (test.t4.b = (select (max(test.t2.a) * 4) AS `max(t2.a)*4` from test.t2)) order by test.t4.a)
 select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
 (select a from t3 where a<t2.a*4 order by 1 desc limit 1)	a
 3	1
@@ -186,12 +192,14 @@ select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
 (select * from t2 where a>1) as tt;
 (select t3.a from t3 where a<8 order by 1 desc limit 1)	a
 7	2
-explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from 
+explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from 
 (select * from t2 where a>1) as tt;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	<derived3>	system	NULL	NULL	NULL	NULL	1	
 3	DERIVED	t2	ALL	NULL	NULL	NULL	NULL	2	Using where
 2	SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where; Using filesort
+Warnings:
+Note	1003	select high_priority (select test.t3.a AS `a` from test.t3 where (test.t3.a < 8) order by test.t3.a desc limit 1) AS `(select t3.a from t3 where a<8 order by 1 desc limit 1)`,t2.a AS `a` from (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.a > 1)) tt
 select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
 a
 2
@@ -205,13 +213,14 @@ b	(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
 8	7.5000
 8	4.5000
 9	7.5000
-explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t4	ALL	NULL	NULL	NULL	NULL	3	
 2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	2	
 3	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where
 Warnings:
 Note	1275	Field or reference 't4.a' of SELECT #3 was resolved in SELECT #1
+Note	1003	select high_priority test.t4.b AS `b`,(select avg((test.t2.a + (select min(test.t3.a) AS `min(t3.a)` from test.t3 where (test.t3.a >= test.t4.a)))) AS `avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a))` from test.t2) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from test.t4
 select * from t3 where exists (select * from t2 where t2.b=t3.a);
 a
 7
@@ -252,10 +261,12 @@ select * from t3 where a >= any (select b from t2);
 a
 6
 7
-explain select * from t3 where a >= any (select b from t2);
+explain extended select * from t3 where a >= any (select b from t2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	3	
+Warnings:
+Note	1003	select high_priority test.t3.a AS `a` from test.t3 where (test.t3.a >= (select min(test.t2.b) from test.t2 limit 1))
 select * from t3 where a >= all (select b from t2);
 a
 7
@@ -290,7 +301,7 @@ select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)
 (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)	a
 NULL	1
 2	2
-explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+explain extended select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ALL	NULL	NULL	NULL	NULL	2	
 2	DEPENDENT SUBQUERY	t1	system	NULL	NULL	NULL	NULL	1	
@@ -298,6 +309,7 @@ id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 Warnings:
 Note	1275	Field or reference 't2.a' of SELECT #2 was resolved in SELECT #1
 Note	1275	Field or reference 't2.a' of SELECT #3 was resolved in SELECT #1
+Note	1003	select high_priority (select test.t1.a AS `a` from test.t1 where (test.t1.a = test.t2.a) union select test.t5.a AS `a` from test.t5 where (test.t5.a = test.t2.a)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,test.t2.a AS `a` from test.t2
 select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
 ERROR 21000: Subquery returns more than 1 row
 create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -309,12 +321,13 @@ patient_uq	clinic_uq
 1	1
 1	2
 2	2
-explain select * from t6 where exists (select * from t7 where uq = clinic_uq);
+explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t6	ALL	NULL	NULL	NULL	NULL	4	Using where
 2	DEPENDENT SUBQUERY	t7	eq_ref	PRIMARY	PRIMARY	4	test.t6.clinic_uq	1	
 Warnings:
 Note	1275	Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1
+Note	1003	select high_priority test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select test.t7.uq AS `uq`,test.t7.name AS `name` from test.t7 where (test.t7.uq = test.t6.clinic_uq) limit 1)
 select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
 ERROR 23000: Column: 'a' in field list is ambiguous
 drop table if exists t1,t2,t3;
@@ -342,12 +355,14 @@ UNIQUE KEY `email` (`email`)
 INSERT INTO t8 (pseudo,email) VALUES ('joce','test');
 INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
 INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
-EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t8	const	PRIMARY	PRIMARY	35	const	1	
 4	SUBQUERY	t8	const	PRIMARY	PRIMARY	35		1	
 2	SUBQUERY	t8	const	PRIMARY	PRIMARY	35	const	1	
 3	SUBQUERY	t8	const	PRIMARY	PRIMARY	35		1	
+Warnings:
+Note	1003	select high_priority test.t8.pseudo AS `pseudo`,(select test.t8.email AS `email` from test.t8 where (test.t8.pseudo = (select test.t8.pseudo AS `pseudo` from test.t8 where (test.t8.pseudo = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from test.t8 where (test.t8.pseudo = (select test.t8.pseudo AS `pseudo` from test.t8 where (test.t8.pseudo = _latin1'joce')))
 SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
 t8 WHERE pseudo='joce');
 ERROR 21000: Operand should contain 1 column(s)
@@ -369,13 +384,17 @@ KEY `topic` (`topic`)
 ) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
 INSERT INTO t1 (topic,date,pseudo) VALUES
 ('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
-EXPLAIN SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+EXPLAIN EXTENDED SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	index	NULL	PRIMARY	41	NULL	2	Using where; Using index
-EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+Warnings:
+Note	1003	select high_priority distinct test.t1.date AS `date` from test.t1 where (test.t1.date = 20020803)
+EXPLAIN EXTENDED SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 2	SUBQUERY	t1	index	NULL	PRIMARY	41	NULL	2	Using where; Using index
+Warnings:
+Note	1003	select high_priority (select distinct test.t1.date AS `date` from test.t1 where (test.t1.date = 20020803)) AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
 SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
 date
 2002-08-03
@@ -389,11 +408,13 @@ SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1;
 1
 SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1;
 ERROR 21000: Subquery returns more than 1 row
-EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
+EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	topic	3	NULL	2	Using index
 2	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 3	UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+Warnings:
+Note	1003	select high_priority 1 AS `1` from test.t1
 drop table t1;
 CREATE TABLE `t1` (
 `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@@ -507,15 +528,19 @@ ERROR 42S22: Unknown column 'a' in 'having clause'
 SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a;
 numreponse	(SELECT numeropost FROM t1 HAVING numreponse=1)
 INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
-EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
+EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
 ERROR 21000: Subquery returns more than 1 row
-EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
+EXPLAIN EXTENDED SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
-EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
+Warnings:
+Note	1003	select high_priority max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1 where (test.t1.numeropost = _latin1'1')
+EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	const	PRIMARY,numreponse	PRIMARY	7	const,const	1	
 2	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
+Warnings:
+Note	1003	select high_priority test.t1.numreponse AS `numreponse` from test.t1 where ((test.t1.numeropost = _latin1'1') and (test.t1.numreponse = 3))
 drop table t1;
 CREATE TABLE t1 (a int(1));
 INSERT INTO t1 VALUES (1);
@@ -678,28 +703,32 @@ INSERT INTO t2 VALUES (1),(2);
 SELECT * FROM t2 WHERE id IN (SELECT 1);
 id
 1
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1);
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ref	id	id	5	const	1	Using where; Using index
 Warnings:
 Note	1248	Select 2 was reduced during optimisation
+Note	1003	select high_priority test.t2.id AS `id` from test.t2 where (test.t2.id = 1)
 SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
 id
 1
 SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
 id
 2
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	ref	id	id	5	const	1	Using where; Using index
 Warnings:
 Note	1248	Select 3 was reduced during optimisation
 Note	1248	Select 2 was reduced during optimisation
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+Note	1003	select high_priority test.t2.id AS `id` from test.t2 where (test.t2.id = (1 + 1))
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	id	5	NULL	2	Using where; Using index
 2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 3	DEPENDENT UNION	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
+Warnings:
+Note	1003	select high_priority test.t2.id AS `id` from test.t2 where <in_optimizer>(test.t2.id,<exists>(select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(1)) limit 1 union select 1 AS `Not_used` having (<cache>(test.t2.id) = <null_helper>(3)) limit 1))
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
 id
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
@@ -819,12 +848,13 @@ NULL
 select 10.5 > ANY (SELECT * from t1);
 10.5 > ANY (SELECT * from t1)
 1
-explain select (select a+1) from t1;
+explain extended select (select a+1) from t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	
 Warnings:
 Note	1275	Field or reference 'a' of SELECT #2 was resolved in SELECT #1
 Note	1248	Select 2 was reduced during optimisation
+Note	1003	select high_priority (test.t1.a + 1) AS `(select a+1)` from test.t1
 select (select a+1) from t1;
 (select a+1)
 2.5
@@ -841,10 +871,12 @@ a	t1.a in (select t2.a from t2)
 2	1
 3	1
 4	0
-explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	PRIMARY	4	NULL	4	Using index
 2	DEPENDENT SUBQUERY	t2	index_subquery	a	a	5	func	2	Using index
+Warnings:
+Note	1003	select high_priority test.t1.a AS `a`,<in_optimizer>(test.t1.a,<exists>(<index_lookup>(<cache>(test.t1.a) in t2 chicking NULL))) AS `t1.a in (select t2.a from t2)` from test.t1
 CREATE TABLE t3 (a int(11) default '0');
 INSERT INTO t3 VALUES (1),(2),(3);
 SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
@@ -853,11 +885,13 @@ a	t1.a in (select t2.a from t2,t3 where t3.a=t2.a)
 2	1
 3	1
 4	0
-explain SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
+explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	PRIMARY	4	NULL	4	Using index
 2	DEPENDENT SUBQUERY	t2	ref_or_null	a	a	5	func	2	Using where; Using index
 2	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where
+Warnings:
+Note	1003	select high_priority test.t1.a AS `a`,<in_optimizer>(test.t1.a,<exists>(select 1 AS `Not_used` from test.t2 join test.t3 where ((test.t3.a = test.t2.a) and ((<cache>(test.t1.a) = test.t2.a) or isnull(test.t2.a))) having <is_not_null_test>(test.t2.a) limit 1)) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from test.t1
 drop table t1,t2,t3;
 create table t1 (a float);
 select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -962,18 +996,24 @@ UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
 ERROR HY000: Invalid use of group function
 drop table t1;
 CREATE TABLE t1 (a int(1));
-EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1;
+EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
 2	UNCACHEABLE SUBQUERY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
-EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
+Warnings:
+Note	1003	select high_priority no_cache (select no_cache rand() AS `RAND()` from test.t1) AS `(SELECT RAND() FROM t1)` from test.t1
+EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
 2	UNCACHEABLE SUBQUERY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
-EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
+Warnings:
+Note	1003	select high_priority no_cache (select no_cache ecrypt(_latin1'test') AS `ENCRYPT('test')` from test.t1) AS `(SELECT ENCRYPT('test') FROM t1)` from test.t1
+EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
 2	UNCACHEABLE SUBQUERY	t1	system	NULL	NULL	NULL	NULL	0	const row not found
+Warnings:
+Note	1003	select high_priority no_cache (select no_cache benchmark(1) AS `BENCHMARK(1,1)` from test.t1) AS `(SELECT BENCHMARK(1,1) FROM t1)` from test.t1
 drop table t1;
 CREATE TABLE `t1` (
 `mot` varchar(30) character set latin1 NOT NULL default '',
@@ -1061,12 +1101,14 @@ t1	CREATE TABLE `t1` (
 drop table t1;
 create table t1 (a int);
 insert into t1 values (1), (2), (3);
-explain select a,(select (select rand() from t1 limit 1)  from t1 limit 1)
+explain extended select a,(select (select rand() from t1 limit 1)  from t1 limit 1)
 from t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	
 2	UNCACHEABLE SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	3	
 3	UNCACHEABLE SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	3	
+Warnings:
+Note	1003	select high_priority no_cache test.t1.a AS `a`,(select no_cache (select no_cache rand() AS `rand()` from test.t1 limit 1) AS `(select rand() from t1 limit 1)` from test.t1 limit 1) AS `(select (select rand() from t1 limit 1)  from t1 limit 1)` from test.t1
 drop table t1;
 select t1.Continent, t2.Name, t2.Population from t1 LEFT JOIN t2 ON t1.Code = t2.Country  where t2.Population IN (select max(t2.Population) AS Population from t2, t1 where t2.Country = t1.Code group by Continent);
 ERROR 42S02: Table 'test.t1' doesn't exist
@@ -1115,18 +1157,22 @@ INSERT INTO t1 (pseudo) VALUES ('test');
 SELECT 0 IN (SELECT 1 FROM t1 a);
 0 IN (SELECT 1 FROM t1 a)
 0
-EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
+EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+Warnings:
+Note	1003	select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a where isnull(1) having <is_not_null_test>(1) limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
 INSERT INTO t1 (pseudo) VALUES ('test1');
 SELECT 0 IN (SELECT 1 FROM t1 a);
 0 IN (SELECT 1 FROM t1 a)
 0
-EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
+EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
 2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
+Warnings:
+Note	1003	select high_priority <in_optimizer>(0,<exists>(select 1 AS `Not_used` from test.t1 a where isnull(1) having <is_not_null_test>(1) limit 1)) AS `0 IN (SELECT 1 FROM t1 a)`
 drop table t1;
 CREATE TABLE `t1` (
 `i` int(11) NOT NULL default '0',
@@ -1165,10 +1211,12 @@ NULL
 drop table t1;
 create table t1 (id int not null auto_increment primary key, salary int, key(salary));
 insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
-explain SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
+explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ref	salary	salary	5	const	1	Using where
 2	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Select tables optimized away
+Warnings:
+Note	1003	select high_priority test.t1.id AS `id` from test.t1 where (test.t1.salary = (select max(test.t1.salary) AS `MAX(salary)` from test.t1))
 drop table t1;
 CREATE TABLE t1 (
 ID int(10) unsigned NOT NULL auto_increment,
@@ -1255,27 +1303,33 @@ a
 2
 3
 4
-explain select * from t2 where t2.a in (select a from t1);
+explain extended select * from t2 where t2.a in (select a from t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	PRIMARY	4	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	unique_subquery	PRIMARY	PRIMARY	4	func	1	Using index
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<primary_index_lookup>(<cache>(test.t2.a) in t1)))
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 a
 2
 4
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	PRIMARY	4	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	unique_subquery	PRIMARY	PRIMARY	4	func	1	Using index; Using where
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<primary_index_lookup>(<cache>(test.t2.a) in t1 where (test.t1.b <> 30))))
 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 a
 2
 3
-explain select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
+explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	PRIMARY	4	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	eq_ref	PRIMARY	PRIMARY	4	func	1	Using where
 2	DEPENDENT SUBQUERY	t3	eq_ref	PRIMARY	PRIMARY	4	test.t1.b	1	Using where; Using index
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a)) limit 1))
 drop table t1, t2, t3;
 create table t1 (a int, b int, index a (a,b));
 create table t2 (a int, index a (a));
@@ -1288,27 +1342,33 @@ a
 2
 3
 4
-explain select * from t2 where t2.a in (select a from t1);
+explain extended select * from t2 where t2.a in (select a from t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	index_subquery	a	a	5	func	1001	Using index
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1)))
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 a
 2
 4
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	index_subquery	a	a	5	func	1001	Using index; Using where
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1 where (test.t1.b <> 30))))
 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 a
 2
 3
-explain select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
+explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t3	index	a	a	5	NULL	3	Using index
 2	DEPENDENT SUBQUERY	t1	ref	a	a	10	func,test.t3.a	1000	Using where; Using index
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a)) limit 1))
 insert into t1 values (3,31);
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 a
@@ -1319,10 +1379,12 @@ select * from t2 where t2.a in (select a from t1 where t1.b <> 30 and t1.b <> 31
 a
 2
 4
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t2	index	NULL	a	5	NULL	4	Using where; Using index
 2	DEPENDENT SUBQUERY	t1	index_subquery	a	a	5	func	1001	Using index; Using where
+Warnings:
+Note	1003	select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(<index_lookup>(<cache>(test.t2.a) in t1 where (test.t1.b <> 30))))
 drop table t1, t2, t3;
 create table t1 (a int, b int);
 create table t2 (a int, b int);
@@ -1387,9 +1449,11 @@ insert into t1 values ('tttt');
 select * from t1 where ('a','b')=(select 'a','b' from t1 union select 'a','b' from t1);
 s1
 tttt
-explain (select * from t1);
+explain extended (select * from t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	SIMPLE	t1	system	NULL	NULL	NULL	NULL	1	
+Warnings:
+Note	1003	(select high_priority test.t1.s1 AS `s1` from test.t1)
 (select * from t1);
 s1
 tttt
@@ -1408,14 +1472,18 @@ s1	s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')
 a1	0
 a2	1
 a3	1
-explain select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
+explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	s1	6	NULL	3	Using index
 2	DEPENDENT SUBQUERY	t2	index_subquery	s1	s1	6	func	2	Using index
-explain select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
+Warnings:
+Note	1003	select high_priority test.t1.s1 AS `s1`,not(<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 chicking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from test.t1
+explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	s1	6	NULL	3	Using index
 2	DEPENDENT SUBQUERY	t2	index_subquery	s1	s1	6	func	1	Using index; Using where
+Warnings:
+Note	1003	select high_priority test.t1.s1 AS `s1`,not(<in_optimizer>(test.t1.s1,<exists>(<index_lookup>(<cache>(test.t1.s1) in t2 chicking NULL where (test.t2.s1 < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from test.t1
 drop table t1,t2;
 create table t2 (a int, b int);
 create table t3 (a int);
@@ -1425,17 +1493,21 @@ a
 6
 7
 3
-explain select * from t3 where a >= all (select b from t2);
+explain extended select * from t3 where a >= all (select b from t2);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	SUBQUERY	t2	system	NULL	NULL	NULL	NULL	0	const row not found
+Warnings:
+Note	1003	select high_priority test.t3.a AS `a` from test.t3 where <not>((test.t3.a < (select max(test.t2.b) from test.t2 limit 1)))
 insert into t2 values (2,2), (2,1), (3,3), (3,1);
 select * from t3 where a > all (select max(b) from t2 group by a);
 a
 6
 7
-explain select * from t3 where a > all (select max(b) from t2 group by a);
+explain extended select * from t3 where a > all (select max(b) from t2 group by a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	3	Using where
 2	SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	4	Using temporary; Using filesort
+Warnings:
+Note	1003	select high_priority test.t3.a AS `a` from test.t3 where <not>((test.t3.a <= <max>(select max(test.t2.b) AS `max(b)` from test.t2 group by test.t2.a)))
 drop table if exists t2, t3;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index bf47e6ad43..5729d3b32e 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -86,10 +86,12 @@ a	b
 1	a
 (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by t1.b;
 ERROR 42000: Table 't1' from one of SELECT's can not be used  in global ORDER clause
-explain (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by b desc;
+explain extended (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by b desc;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	4	
 2	UNION	t2	ALL	NULL	NULL	NULL	NULL	4	Using filesort
+Warnings:
+Note	1003	(select high_priority test.t1.a AS `a`,test.t1.b AS `b` from test.t1 limit 2) union all (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 order by test.t2.a limit 1) order by b desc
 (select sql_calc_found_rows  a,b from t1 limit 2)  union all (select a,b from t2 order by a) limit 2;
 a	b
 1	a
@@ -463,10 +465,12 @@ create table t1 (a int not null primary key auto_increment, b int, key(b));
 create table t2 (a int not null primary key auto_increment, b int);
 insert into t1 (b) values (1),(2),(2),(3);
 insert into t2 (b) values (10),(11),(12),(13);
-explain (select * from t1 where a=1) union (select * from t2 where a=1);
+explain extended (select * from t1 where a=1) union (select * from t2 where a=1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	const	PRIMARY	PRIMARY	4	const	1	
 2	UNION	t2	const	PRIMARY	PRIMARY	4	const	1	
+Warnings:
+Note	1003	(select high_priority test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (test.t1.a = 1)) union (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.a = 1))
 (select * from t1 where a=5) union (select * from t2 where a=1);
 a	b
 1	10
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 9ba91c7e0a..1242aaaced 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -4,11 +4,11 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t11,t12;
 --enable_warnings
 
 select (select 2);
-explain select (select 2);
+explain extended select (select 2);
 SELECT (SELECT 1) UNION SELECT (SELECT 2);
-explain SELECT (SELECT 1) UNION SELECT (SELECT 2);
+explain extended SELECT (SELECT 1) UNION SELECT (SELECT 2);
 SELECT (SELECT (SELECT 0 UNION SELECT 0));
-explain SELECT (SELECT (SELECT 0 UNION SELECT 0));
+explain extended SELECT (SELECT (SELECT 0 UNION SELECT 0));
 -- error 1246
 SELECT (SELECT 1 FROM (SELECT 1) as b HAVING a=1) as a;
 -- error 1246
@@ -16,7 +16,7 @@ SELECT (SELECT 1 FROM (SELECT 1) as b HAVING b=1) as a,(SELECT 1 FROM (SELECT 1)
 SELECT (SELECT 1),MAX(1) FROM (SELECT 1) as a;
 -- error 1246
 SELECT (SELECT a) as a;
-EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b  HAVING (SELECT a)=1;
+EXPLAIN EXTENDED SELECT 1 FROM (SELECT 1 as a) as b  HAVING (SELECT a)=1;
 SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
 -- error 1054
 SELECT (SELECT 1), a;
@@ -74,17 +74,17 @@ insert into t3 values (6),(7),(3);
 select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
 (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
 (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
-explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
+explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
 select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
 select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from 
 (select * from t2 where a>1) as tt;
-explain select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from 
+explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from 
 (select * from t2 where a>1) as tt;
 select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1);
 select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1);
 select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a < t1.a) order by 1 desc limit 1);
 select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
-explain select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
+explain extended select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
 select * from t3 where exists (select * from t2 where t2.b=t3.a);
 select * from t3 where not exists (select * from t2 where t2.b=t3.a);
 select * from t3 where a in (select b from t2);
@@ -100,7 +100,7 @@ insert into t2 values (100, 5);
 select * from t3 where a < any (select b from t2);
 select * from t3 where a < all (select b from t2);
 select * from t3 where a >= any (select b from t2);
-explain select * from t3 where a >= any (select b from t2);
+explain extended select * from t3 where a >= any (select b from t2);
 select * from t3 where a >= all (select b from t2);
 delete from t2 where a=100;
 -- error 1240
@@ -120,7 +120,7 @@ insert into t5 values (5);
 select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
 insert into t5 values (2);
 select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
-explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
+explain extended select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
 -- error 1241
 select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
 create table t6 (patient_uq int, clinic_uq int, index i1 (clinic_uq));
@@ -128,7 +128,7 @@ create table t7( uq int primary key, name char(25));
 insert into t7 values(1,"Oblastnaia bolnitsa"),(2,"Bolnitsa Krasnogo Kresta");
 insert into t6 values (1,1),(1,2),(2,2),(1,3);
 select * from t6 where exists (select * from t7 where uq = clinic_uq);
-explain select * from t6 where exists (select * from t7 where uq = clinic_uq);
+explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq);
 
 # not unique fields
 -- error 1052
@@ -157,7 +157,7 @@ CREATE TABLE `t8` (
 INSERT INTO t8 (pseudo,email) VALUES ('joce','test');
 INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
 INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
-EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
+EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
 -- error 1240
 SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
 t8 WHERE pseudo='joce');
@@ -180,14 +180,14 @@ CREATE TABLE `t1` (
 ) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
 INSERT INTO t1 (topic,date,pseudo) VALUES
 ('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
-EXPLAIN SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
-EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
+EXPLAIN EXTENDED SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
+EXPLAIN EXTENDED SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
 SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
 SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
 SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL SELECT 1;
 -- error 1241
 SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1;
-EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
+EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
 drop table t1;
 
 #forumconthardwarefr7 searchconthardwarefr7
@@ -276,9 +276,9 @@ SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=a) FROM (SELECT
 SELECT numreponse, (SELECT numeropost FROM t1 HAVING numreponse=1) FROM (SELECT * FROM t1) as a;
 INSERT INTO t1 (numeropost,numreponse,pseudo) VALUES (1,1,'joce'),(1,2,'joce'),(1,3,'test');
 -- error 1241
-EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
-EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
-EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
+EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1 FROM t1 WHERE numeropost='1');
+EXPLAIN EXTENDED SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
+EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
 drop table t1;
 
 CREATE TABLE t1 (a int(1));
@@ -395,11 +395,11 @@ SELECT * FROM (SELECT 1) b WHERE 1 IN (SELECT *);
 CREATE TABLE t2 (id int(11) default NULL, KEY id (id)) TYPE=MyISAM CHARSET=latin1;
 INSERT INTO t2 VALUES (1),(2);
 SELECT * FROM t2 WHERE id IN (SELECT 1);
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1);
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1);
 SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
 SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
-EXPLAIN SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1+(select 1));
+EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3);
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3);
 SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2);
 -- error 1093
@@ -455,7 +455,7 @@ select 1.5 > ALL (SELECT * from t1);
 select 10.5 > ALL (SELECT * from t1);
 select 1.5 > ANY (SELECT * from t1);
 select 10.5 > ANY (SELECT * from t1);
-explain select (select a+1) from t1;
+explain extended select (select a+1) from t1;
 select (select a+1) from t1;
 drop table t1;
 
@@ -468,11 +468,11 @@ CREATE TABLE t2 (a int(11) default '0', INDEX (a));
 INSERT INTO t1 VALUES (1),(2),(3),(4);
 INSERT INTO t2 VALUES (1),(2),(3);
 SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
-explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
+explain extended SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
 CREATE TABLE t3 (a int(11) default '0');
 INSERT INTO t3 VALUES (1),(2),(3);
 SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
-explain SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
+explain extended SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1;
 drop table t1,t2,t3;
 
 #LIMIT is not supported now
@@ -549,9 +549,9 @@ drop table t1;
 
 #test of uncacheable subqueries
 CREATE TABLE t1 (a int(1));
-EXPLAIN SELECT (SELECT RAND() FROM t1) FROM t1;
-EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
-EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
+EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1;
+EXPLAIN EXTENDED SELECT (SELECT ENCRYPT('test') FROM t1) FROM t1;
+EXPLAIN EXTENDED SELECT (SELECT BENCHMARK(1,1) FROM t1) FROM t1;
 drop table t1;
 
 
@@ -613,7 +613,7 @@ drop table t1;
 
 create table t1 (a int);
 insert into t1 values (1), (2), (3);
-explain select a,(select (select rand() from t1 limit 1)  from t1 limit 1)
+explain extended select a,(select (select rand() from t1 limit 1)  from t1 limit 1)
 from t1;
 drop table t1;
 
@@ -677,10 +677,10 @@ CREATE TABLE `t1` (
 ) TYPE=MyISAM PACK_KEYS=1 ROW_FORMAT=DYNAMIC;
 INSERT INTO t1 (pseudo) VALUES ('test');
 SELECT 0 IN (SELECT 1 FROM t1 a);
-EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
+EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
 INSERT INTO t1 (pseudo) VALUES ('test1');
 SELECT 0 IN (SELECT 1 FROM t1 a);
-EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
+EXPLAIN EXTENDED SELECT 0 IN (SELECT 1 FROM t1 a);
 drop table t1;
 
 CREATE TABLE `t1` (
@@ -727,7 +727,7 @@ drop table t1;
 #
 create table t1 (id int not null auto_increment primary key, salary int, key(salary));
 insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000);
-explain SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
+explain extended SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1);
 drop table t1;
 
 CREATE TABLE t1 (
@@ -824,11 +824,11 @@ insert into t1 values (1,10), (2,20), (3,30),  (4,40);
 insert into t2 values (2), (3), (4), (5);
 insert into t3 values (10,3), (20,4), (30,5);
 select * from t2 where t2.a in (select a from t1);
-explain select * from t2 where t2.a in (select a from t1);
+explain extended select * from t2 where t2.a in (select a from t1);
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
-explain select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
+explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 drop table t1, t2, t3;
 create table t1 (a int, b int, index a (a,b));
 create table t2 (a int, index a (a));
@@ -846,15 +846,15 @@ enable_query_log;
 insert into t2 values (2), (3), (4), (5);
 insert into t3 values (10,3), (20,4), (30,5);
 select * from t2 where t2.a in (select a from t1);
-explain select * from t2 where t2.a in (select a from t1);
+explain extended select * from t2 where t2.a in (select a from t1);
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
-explain select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
+explain extended select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a);
 insert into t1 values (3,31);
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 select * from t2 where t2.a in (select a from t1 where t1.b <> 30 and t1.b <> 31);
-explain select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
+explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30);
 drop table t1, t2, t3;
 
 #
@@ -935,7 +935,7 @@ create table t1 (s1 char(5));
 select (select 'a','b' from t1 union select 'a','b' from t1) from t1;
 insert into t1 values ('tttt');
 select * from t1 where ('a','b')=(select 'a','b' from t1 union select 'a','b' from t1);
-explain (select * from t1);
+explain extended (select * from t1);
 (select * from t1);
 drop table t1;
 
@@ -948,8 +948,8 @@ insert into t1 values ('a1'),('a2'),('a3');
 insert into t2 values ('a1'),('a2');
 select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
 select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
-explain select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
-explain select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
+explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
+explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
 drop table t1,t2;
 #
 # correct ALL optimisation
@@ -958,10 +958,10 @@ create table t2 (a int, b int);
 create table t3 (a int);
 insert into t3 values (6),(7),(3);
 select * from t3 where a >= all (select b from t2);
-explain select * from t3 where a >= all (select b from t2);
+explain extended select * from t3 where a >= all (select b from t2);
 
 # optimized static ALL/ANY with grouping
 insert into t2 values (2,2), (2,1), (3,3), (3,1);
 select * from t3 where a > all (select max(b) from t2 group by a);
-explain select * from t3 where a > all (select max(b) from t2 group by a);
+explain extended select * from t3 where a > all (select max(b) from t2 group by a);
 drop table if exists t2, t3;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index b64f0b4e2e..1f3f408573 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -25,7 +25,7 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
 (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by b desc;
 --error 1249
 (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by t1.b;
-explain (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by b desc;
+explain extended (select a,b from t1 limit 2)  union all (select a,b from t2 order by a limit 1) order by b desc;
 (select sql_calc_found_rows  a,b from t1 limit 2)  union all (select a,b from t2 order by a) limit 2;
 select found_rows();
 select sql_calc_found_rows  a,b from t1  union all select a,b from t2 limit 2;
@@ -275,7 +275,7 @@ create table t2 (a int not null primary key auto_increment, b int);
 insert into t1 (b) values (1),(2),(2),(3);
 insert into t2 (b) values (10),(11),(12),(13);
 
-explain (select * from t1 where a=1) union (select * from t2 where a=1);
+explain extended (select * from t1 where a=1) union (select * from t2 where a=1);
 (select * from t1 where a=5) union (select * from t2 where a=1);
 (select * from t1 where a=5 and a=6) union (select * from t2 where a=1);
 (select t1.a,t1.b from t1,t2 where t1.a=5) union (select * from t2 where a=1);
diff --git a/sql/item.cc b/sql/item.cc
index ccca858c4c..19ea85f123 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -86,6 +86,19 @@ Item::Item(THD *thd, Item &item):
   thd->free_list= this;
 }
 
+
+void Item::print_item_w_name(String *str)
+{
+  print(str);
+  if (name)
+  {
+    str->append(" AS `");
+    str->append(name);
+    str->append('`');
+  }
+}
+
+
 // Constructor used by Item_field & Item_ref (see Item comment)
 Item_ident::Item_ident(THD *thd, Item_ident &item):
   Item(thd, item),
@@ -441,12 +454,8 @@ String *Item_int::val_str(String *str)
 
 void Item_int::print(String *str)
 {
-  if (!name)
-  {
-    str_value.set(value, default_charset());
-    name=str_value.c_ptr();
-  }
-  str->append(name);
+  str_value.set(value, default_charset());
+  str->append(str_value);
 }
 
 String *Item_uint::val_str(String *str)
@@ -457,12 +466,8 @@ String *Item_uint::val_str(String *str)
 
 void Item_uint::print(String *str)
 {
-  if (!name)
-  {
-    str_value.set((ulonglong) value, default_charset());
-    name=str_value.c_ptr();
-  }
-  str->append(name);
+  str_value.set((ulonglong) value, default_charset());
+  str->append(str_value);
 }
 
 
@@ -476,17 +481,9 @@ void Item_string::print(String *str)
 {
   str->append('_');
   str->append(collation.collation->csname);
-  if (varbin)
-  {
-    str->append(' ');
-    str->append(full_name());
-  }
-  else
-  { 
-    str->append('\'');
-    str->append(full_name());
-    str->append('\'');
-  }
+  str->append('\'');
+  str->append(str_value);
+  str->append('\'');
 }
 
 bool Item_null::eq(const Item *item, bool binary_cmp) const
@@ -785,7 +782,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
   // store pointer on SELECT_LEX from wich item is dependent
   item->depended_from= last;
   current->mark_as_dependent(last);
-  if (thd->lex.describe)
+  if (thd->lex.describe & DESCRIBE_EXTENDED)
   {
     char warn_buff[MYSQL_ERRMSG_SIZE];
     sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
@@ -1494,6 +1491,34 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
 }
 
 
+void Item_ref::print(String *str)
+{
+  if (ref && *ref)
+    (*ref)->print(str);
+  else
+    Item_ident::print(str);
+}
+
+
+void Item_ref_null_helper::print(String *str)
+{
+  str->append("<ref_null_helper>(");
+  if (ref && *ref)
+    (*ref)->print(str);
+  else
+    str->append('?');
+  str->append(')');
+}
+
+
+void Item_null_helper::print(String *str)
+{
+  str->append("<null_helper>(");
+  store->print(str);
+  str->append(')');
+}
+
+
 bool Item_default_value::eq(const Item *item, bool binary_cmp) const
 {
   return item->type() == DEFAULT_VALUE_ITEM && 
@@ -1715,6 +1740,34 @@ Item_cache* Item_cache::get_cache(Item_result type)
   }
 }
 
+
+void Item_cache::print(String *str)
+{
+  str->append("<cache>(");
+  if (example)
+    example->print(str);
+  else
+    Item::print(str);
+  str->append(')');
+}
+
+
+void Item_cache_int::store(Item *item)
+{
+  value= item->val_int_result();
+  null_value= item->null_value;
+  collation.set(item->collation);
+}
+
+
+void Item_cache_real::store(Item *item)
+{
+  value= item->val_result();
+  null_value= item->null_value;
+  collation.set(item->collation);
+}
+
+
 void Item_cache_str::store(Item *item)
 {
   value_buff.set(buffer, sizeof(buffer), item->collation.collation);
@@ -1765,6 +1818,7 @@ bool Item_cache_row::allocate(uint num)
 
 bool Item_cache_row::setup(Item * item)
 {
+  example= item;
   if (!values && allocate(item->cols()))
     return 1;
   for (uint i= 0; i < item_count; i++)
diff --git a/sql/item.h b/sql/item.h
index 5e6df464fb..78ca5a8f3f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -174,6 +174,7 @@ public:
   { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
   virtual bool const_item() const { return used_tables() == 0; }
   virtual void print(String *str_arg) { str_arg->append(full_name()); }
+  void print_item_w_name(String *);
   virtual void update_used_tables() {}
   virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
   virtual bool get_date(TIME *ltime,bool fuzzydate);
@@ -307,6 +308,7 @@ public:
   bool basic_const_item() const { return 1; }
   Item *new_item() { return new Item_null(name); }
   bool is_null() { return 1; }
+  void print(String *str) { str->append("NULL"); }
 };
 
 class Item_param :public Item
@@ -357,6 +359,7 @@ public:
   String *query_val_str(String *str);
   enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
   Item *new_item() { return new Item_param(pos_in_query); }
+  void print(String *str) { str->append('?'); }
 };
 
 class Item_int :public Item
@@ -449,11 +452,9 @@ public:
 
 class Item_string :public Item
 {
-  bool varbin;
 public:
   Item_string(const char *str,uint length,
   	      CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
-    :varbin(0)
   {
     collation.set(cs, dv);
     str_value.set(str,length,cs);
@@ -463,7 +464,6 @@ public:
   }
   Item_string(const char *name_par, const char *str, uint length,
 	      CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE)
-    :varbin(0)
   {
     collation.set(cs, dv);
     str_value.set(str,length,cs);
@@ -497,7 +497,6 @@ public:
   }
   String *const_string() { return &str_value; }
   inline void append(char *str, uint length) { str_value.append(str, length); }
-  inline void set_varbin_name(char *nm) { name= nm; varbin= 1; }
   void print(String *str);
 };
 
@@ -633,6 +632,7 @@ public:
     (*ref)->save_in_field(result_field, no_conversions);
   }
   Item *real_item() { return *ref; }
+  void print(String *str);
 };
 
 class Item_in_subselect;
@@ -648,15 +648,7 @@ public:
   longlong val_int();
   String* val_str(String* s);
   bool get_date(TIME *ltime, bool fuzzydate);
-  void print(String *str)
-  {
-    str->append("<ref_null_helper>(");
-    if (ref && *ref)
-      (*ref)->print(str);
-    else
-      str->append('?');
-    str->append(')');
-  }
+  void print(String *str);
 };
 
 class Item_null_helper :public Item_ref_null_helper
@@ -668,12 +660,7 @@ public:
     :Item_ref_null_helper(master, &store, table_name_par, field_name_par),
      store(item)
     {}
-  void print(String *str)
-  {
-    str->append("<null_helper>(");
-    store->print(str);
-    str->append(')');
-  }
+  void print(String *str);
 };
 
 /*
@@ -855,14 +842,16 @@ public:
 
 class Item_cache: public Item
 {
+protected:
+  Item *example;
   table_map used_table_map;
 public:
-  Item_cache(): used_table_map(0) {fixed= 1; null_value= 1;}
+  Item_cache(): example(0), used_table_map(0) {fixed= 1; null_value= 1;}
 
   void set_used_tables(table_map map) { used_table_map= map; }
 
   virtual bool allocate(uint i) { return 0; };
-  virtual bool setup(Item *) { return 0; };
+  virtual bool setup(Item *item) { example= item;  return 0; };
   virtual void store(Item *)= 0;
   void set_len_n_dec(uint32 max_len, uint8 dec)
   {
@@ -872,6 +861,7 @@ public:
   enum Type type() const { return CACHE_ITEM; }
   static Item_cache* get_cache(Item_result type);
   table_map used_tables() const { return used_table_map; }
+  void print(String *str);
 };
 
 class Item_cache_int: public Item_cache
@@ -880,12 +870,7 @@ class Item_cache_int: public Item_cache
 public:
   Item_cache_int(): Item_cache() {}
   
-  void store(Item *item)
-  {
-    value= item->val_int_result();
-    null_value= item->null_value;
-    collation.set(item->collation);
-  }
+  void store(Item *item);
   double val() { return (double) value; }
   longlong val_int() { return value; }
   String* val_str(String *str) { str->set(value, default_charset()); return str; }
@@ -898,12 +883,7 @@ class Item_cache_real: public Item_cache
 public:
   Item_cache_real(): Item_cache() {}
   
-  void store(Item *item)
-  {
-    value= item->val_result();
-    null_value= item->null_value;
-    collation.set(item->collation);
-  }
+  void store(Item *item);
   double val() { return value; }
   longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
   String* val_str(String *str)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 23b322ebd0..d183c81b23 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -112,6 +112,14 @@ longlong Item_func_not_all::val_int()
   return (!null_value && value == 0) ? 1 : 0;
 }
 
+void Item_func_not_all::print(String *str)
+{
+  if (show)
+    Item_func::print(str);
+  else
+    args[0]->print(str);
+}
+
 /*
   Convert a constant expression or string to an integer.
   This is done when comparing DATE's of different formats and
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index ab03782b16..eb473a1a73 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -160,10 +160,14 @@ class Item_func_not_all :public Item_func_not
 {
   bool abort_on_null;
 public:
-  Item_func_not_all(Item *a) :Item_func_not(a), abort_on_null(0) {}
+  bool show;
+
+  Item_func_not_all(Item *a) :Item_func_not(a), abort_on_null(0), show(0) {}
   virtual void top_level_item() { abort_on_null= 1; }
   bool top_level() { return abort_on_null; }
   longlong val_int();
+  const char *func_name() const { return "<not>"; }
+  void print(String *str);
 };
 
 class Item_func_eq :public Item_bool_rowready_func2
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 5e0221ad6c..0703179d92 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -141,17 +141,28 @@ Item::Type Item_subselect::type() const
   return SUBSELECT_ITEM;
 }
 
+
 void Item_subselect::fix_length_and_dec()
 {
   engine->fix_length_and_dec(0);
 }
 
+
 inline table_map Item_subselect::used_tables() const
 {
   return (table_map) (engine->dependent() ? 1L :
 		      (engine->uncacheable() ? RAND_TABLE_BIT : 0L));
 }
 
+
+void Item_subselect::print(String *str)
+{
+  str->append('(');
+  engine->print(str);
+  str->append(')');
+}
+
+
 Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
   :Item_subselect(), value(0)
 {
@@ -164,17 +175,24 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
 }
 
 Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex,
-					     bool max)
+					     bool max_arg)
   :Item_singlerow_subselect()
 {
   DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect");
-  init(select_lex, new select_max_min_finder_subselect(this, max));
+  max= max_arg;
+  init(select_lex, new select_max_min_finder_subselect(this, max_arg));
   max_columns= 1;
   maybe_null= 1;
   max_columns= 1;
   DBUG_VOID_RETURN;
 }
 
+void Item_maxmin_subselect::print(String *str)
+{
+  str->append(max?"<max>":"<min>");
+  Item_singlerow_subselect::print(str);
+}
+
 void Item_singlerow_subselect::reset()
 {
   null_value= 1;
@@ -217,7 +235,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
     */
     substitution->walk(&Item::remove_dependence_processor,
 		       (byte *) select_lex->outer_select());
-    if (select_lex->where || select_lex->having)
+    if (join->conds || join->having)
     {
       Item *cond;
       if (!join->having)
@@ -337,6 +355,7 @@ String *Item_singlerow_subselect::val_str (String *str)
   }
 }
 
+
 Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
   Item_subselect()
 {
@@ -351,6 +370,14 @@ Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
   DBUG_VOID_RETURN;
 }
 
+
+void Item_exists_subselect::print(String *str)
+{
+  str->append("exists");
+  Item_subselect::print(str);
+}
+
+
 bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
 {
   if (unit->fake_select_lex &&
@@ -368,7 +395,7 @@ bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
 
 Item_in_subselect::Item_in_subselect(Item * left_exp,
 				     st_select_lex *select_lex):
-  Item_exists_subselect(), upper_not(0)
+  Item_exists_subselect(), transformed(0), upper_not(0)
 {
   DBUG_ENTER("Item_in_subselect::Item_in_subselect");
   left_expr= left_exp;
@@ -384,8 +411,9 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
 
 Item_allany_subselect::Item_allany_subselect(Item * left_exp,
 					     compare_func_creator fn,
-					     st_select_lex *select_lex)
-  :Item_in_subselect()
+					     st_select_lex *select_lex,
+					     bool all_arg)
+  :Item_in_subselect(), all(all_arg)
 {
   DBUG_ENTER("Item_in_subselect::Item_in_subselect");
   left_expr= left_exp;
@@ -758,6 +786,7 @@ Item_in_subselect::row_value_transformer(JOIN *join,
 Item_subselect::trans_res
 Item_in_subselect::select_transformer(JOIN *join)
 {
+  transformed= 1;
   if (left_expr->cols() == 1)
     return single_value_transformer(join, left_expr,
 				    &Item_bool_func2::eq_creator);
@@ -765,12 +794,82 @@ Item_in_subselect::select_transformer(JOIN *join)
 }
 
 
+void Item_in_subselect::print(String *str)
+{
+  if (transformed)
+    str->append("<exists>");
+  else
+  {
+    left_expr->print(str);
+    str->append(" in ");
+  }
+  Item_subselect::print(str);
+}
+
+
 Item_subselect::trans_res
 Item_allany_subselect::select_transformer(JOIN *join)
 {
+  transformed= 1;
+  if (upper_not)
+    upper_not->show= 1;
   return single_value_transformer(join, left_expr, func);
 }
 
+
+void Item_allany_subselect::print(String *str)
+{
+  if (transformed)
+    str->append("<exists>");
+  else
+  {
+    left_expr->print(str);
+    str->append(' ');
+    if (all)
+    {
+      if (func ==  &Item_bool_func2::lt_creator)
+	str->append(">=");
+      else if (func ==  &Item_bool_func2::gt_creator)
+	str->append("<=");
+      else if (func ==  &Item_bool_func2::le_creator)
+	str->append('>');
+      else if (func ==  &Item_bool_func2::ge_creator)
+	str->append('<');
+      else if (func ==  &Item_bool_func2::eq_creator)
+	str->append("<>");
+      else if (func ==  &Item_bool_func2::ne_creator)
+	str->append('=');
+      else
+      {
+	DBUG_ASSERT(0);  // Impossible
+      }
+      str->append(" all ");
+    }
+    else
+    {
+      if (func ==  &Item_bool_func2::lt_creator)
+	str->append('<');
+      else if (func ==  &Item_bool_func2::gt_creator)
+	str->append('>');
+      else if (func ==  &Item_bool_func2::le_creator)
+	str->append("<=");
+      else if (func ==  &Item_bool_func2::ge_creator)
+	str->append(">=");
+      else if (func ==  &Item_bool_func2::eq_creator)
+	str->append('=');
+      else if (func ==  &Item_bool_func2::ne_creator)
+	str->append("<>");
+      else
+      {
+	DBUG_ASSERT(0);  // Impossible
+      }
+      str->append(" any ");
+    }
+  }
+  Item_subselect::print(str);
+}
+
+
 subselect_single_select_engine::
 subselect_single_select_engine(st_select_lex *select,
 			       select_subselect *result,
@@ -1098,11 +1197,13 @@ uint subselect_single_select_engine::cols()
   return select_lex->item_list.elements;
 }
 
+
 uint subselect_union_engine::cols()
 {
   return unit->first_select()->item_list.elements;
 }
 
+
 bool subselect_single_select_engine::dependent()
 {
   return select_lex->dependent;
@@ -1113,16 +1214,19 @@ bool subselect_union_engine::dependent()
   return unit->dependent;
 }
 
+
 bool subselect_single_select_engine::uncacheable()
 {
   return select_lex->uncacheable;
 }
 
+
 bool subselect_union_engine::uncacheable()
 {
   return unit->uncacheable;
 }
 
+
 void subselect_single_select_engine::exclude()
 {
   select_lex->master_unit()->exclude_level();
@@ -1133,8 +1237,53 @@ void subselect_union_engine::exclude()
   unit->exclude_level();
 }
 
+
 void subselect_uniquesubquery_engine::exclude()
 {
   //this never should be called
   DBUG_ASSERT(0);
 }
+
+
+void subselect_single_select_engine::print(String *str)
+{
+  select_lex->print(thd, str);
+}
+
+
+void subselect_union_engine::print(String *str)
+{
+  unit->print(str);
+}
+
+
+void subselect_uniquesubquery_engine::print(String *str)
+{
+  str->append("<primary_index_lookup>(");
+  tab->ref.items[0]->print(str);
+  str->append(" in ");
+  str->append(tab->table->real_name);
+  if (cond)
+  {
+    str->append(" where ");
+    cond->print(str);
+  }
+  str->append(')');
+}
+
+
+void subselect_indexsubquery_engine::print(String *str)
+{
+  str->append("<index_lookup>(");
+  tab->ref.items[0]->print(str);
+  str->append(" in ");
+  str->append(tab->table->real_name);
+  if (check_null)
+    str->append(" chicking NULL");
+    if (cond)
+  {
+    str->append(" where ");
+    cond->print(str);
+  }
+  str->append(')');
+}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 312b453a5a..fd4bca33c6 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -85,13 +85,7 @@ public:
   bool exec();
   virtual void fix_length_and_dec();
   table_map used_tables() const;
-  void print(String *str)
-  {
-    if (name)
-      str->append(name);
-    else
-      str->append("-subselect-");
-  }
+  void print(String *str);
   bool change_engine(subselect_engine *eng)
   {
     engine= eng;
@@ -138,8 +132,10 @@ public:
 /* used in static ALL/ANY optimisation */
 class Item_maxmin_subselect: public Item_singlerow_subselect
 {
+  bool max;
 public:
   Item_maxmin_subselect(st_select_lex *select_lex, bool max);
+  void print(String *str);
 };
 
 /* exists subselect */
@@ -164,6 +160,7 @@ public:
   double val();
   String *val_str(String*);
   void fix_length_and_dec();
+  void print(String *str);
 
   friend class select_exists_subselect;
   friend class subselect_uniquesubquery_engine;
@@ -184,12 +181,15 @@ protected:
   Item_in_optimizer *optimizer;
   bool was_null;
   bool abort_on_null;
+  bool transformed;
 public:
   Item_func_not_all *upper_not; // point on NOT before ALL subquery
 
   Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
   Item_in_subselect()
-    :Item_exists_subselect(), abort_on_null(0), upper_not(0) {}
+    :Item_exists_subselect(), abort_on_null(0), transformed(0), upper_not(0)
+     
+  {}
 
   subs_type substype() { return IN_SUBS; }
   void reset() 
@@ -209,6 +209,7 @@ public:
   String *val_str(String*);
   void top_level_item() { abort_on_null=1; }
   bool test_limit(st_select_lex_unit *unit);
+  void print(String *str);
 
   friend class Item_ref_null_helper;
   friend class Item_is_not_null_test;
@@ -223,12 +224,15 @@ protected:
   compare_func_creator func;
 
 public:
+  bool all;
+
   Item_allany_subselect(Item * left_expr, compare_func_creator f,
-		     st_select_lex *select_lex);
+		     st_select_lex *select_lex, bool all);
 
   // only ALL subquery has upper not
   subs_type substype() { return upper_not?ALL_SUBS:ANY_SUBS; }
   trans_res select_transformer(JOIN *join);
+  void print(String *str);
 };
 
 
@@ -264,6 +268,7 @@ public:
   enum Item_result type() { return res_type; }
   virtual void exclude()= 0;
   bool may_be_null() { return maybe_null; };
+  virtual void print(String *str)= 0;
 };
 
 
@@ -285,6 +290,7 @@ public:
   bool dependent();
   bool uncacheable();
   void exclude();
+  void print (String *str);
 };
 
 
@@ -302,6 +308,7 @@ public:
   bool dependent();
   bool uncacheable();
   void exclude();
+  void print (String *str);
 };
 
 
@@ -328,6 +335,7 @@ public:
   bool dependent() { return 1; }
   bool uncacheable() { return 1; }
   void exclude();
+  void print (String *str);
 };
 
 
@@ -344,4 +352,5 @@ public:
      check_null(chk_null)
   {}
   int exec();
+  void print (String *str);
 };
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index afbda2b4ad..6ee6b8c5cb 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -186,6 +186,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
 #define OPTION_QUOTE_SHOW_CREATE OPTION_QUICK*2
 #define OPTION_INTERNAL_SUBTRANSACTIONS OPTION_QUOTE_SHOW_CREATE*2
 
+/* options for UNION set by the yacc parser (stored in unit->union_option) */
+#define UNION_ALL		1
+
 /* Set if we are updating a non-transaction safe table */
 #define OPTION_STATUS_NO_TRANS_UPDATE 	OPTION_INTERNAL_SUBTRANSACTIONS*2
 
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 13d3cc2737..aac2e17086 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -222,10 +222,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
 	  else
 	    unit->exclude_level();
 	  org_table_list->db= (char *)"";
-#ifndef DBUG_OFF
-	  /* Try to catch errors if this is accessed */
-	  org_table_list->derived=(SELECT_LEX_UNIT *) 1;
-#endif
 	  // Force read of table stats in the optimizer
 	  table->file->info(HA_STATUS_VARIABLE);
 	}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 80d698dfc2..024d35150d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1421,7 +1421,73 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
 			       order_group_num)* 5)) == 0;
 }
 
+void st_select_lex_unit::print(String *str)
+{
+  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
+  {
+    if (sl != first_select())
+    {
+      str->append(" union ");
+      if (union_option & UNION_ALL)
+	str->append("all ");
+    }
+    if (sl->braces)
+      str->append('(');
+    sl->print(thd, str);
+    if (sl->braces)
+      str->append(')');
+  }
+  if (fake_select_lex == global_parameters)
+  {
+    if (fake_select_lex->order_list.elements)
+    {
+      str->append(" order by ");
+      fake_select_lex->print_order(str,
+				   (ORDER *) fake_select_lex->
+				   order_list.first);
+    }
+    fake_select_lex->print_limit(thd, str);
+  }
+}
+
+
+void st_select_lex::print_order(String *str, ORDER *order)
+{
+  for (; order; order= order->next)
+  {
+    (*order->item)->print(str);
+    if (!order->asc)
+      str->append(" desc");
+    if (order->next)
+      str->append(',');
+  }
+}
+ 
+void st_select_lex::print_limit(THD *thd, String *str)
+{
+  if (!thd)
+    thd= current_thd;
+
+  if (select_limit != thd->variables.select_limit ||
+      select_limit != HA_POS_ERROR ||
+      offset_limit != 0L)
+  {
+    str->append(" limit ");
+    char buff[21];
+    snprintf(buff, 21, "%ld", select_limit);
+    str->append(buff);
+    if (offset_limit)
+    {
+      str->append(',');
+      snprintf(buff, 21, "%ld", offset_limit);
+      str->append(buff);
+    }
+  }
+}
+
 /*
   There are st_select_lex::add_table_to_list & 
   st_select_lex::set_lock_for_tables in sql_parse.cc
+
+  st_select_lex::print is in sql_select.h
 */
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 8ce028020c..2e62d65fd2 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -79,6 +79,10 @@ enum enum_sql_command {
   SQLCOM_END
 };
 
+// describe/explain types
+#define DESCRIBE_NORMAL		1
+#define DESCRIBE_EXTENDED	2
+
 typedef List<Item> List_item;
 
 typedef struct st_lex_master_info
@@ -321,7 +325,9 @@ public:
   int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
   int exec();
   int cleanup();
-  
+
+  void print(String *str);
+
   friend void mysql_init_query(THD *thd);
   friend int subselect_union_engine::exec();
 private:
@@ -462,6 +468,9 @@ public:
     init_select();
   }
   bool setup_ref_array(THD *thd, uint order_group_num);
+  void print(THD *thd, String *str);
+  static void print_order(String *str, ORDER *order);
+  void print_limit(THD *thd, String *str);
 };
 typedef class st_select_lex SELECT_LEX;
 
@@ -535,9 +544,10 @@ typedef struct st_lex
   uint fk_delete_opt, fk_update_opt, fk_match_option;
   uint param_count;
   uint slave_thd_opt;
+  uint8 describe;
   bool drop_primary, drop_if_exists, drop_temporary, local_file;
   bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
-  bool derived_tables, describe;
+  bool derived_tables;
   bool safe_to_cache_query;
   st_lex() {}
   inline void uncacheable()
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e30fd0acfa..fbd74c68ff 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1781,6 +1781,16 @@ mysql_execute_command(THD *thd)
 	res= mysql_explain_union(thd, &thd->lex.unit, result);
 	MYSQL_LOCK *save_lock= thd->lock;
 	thd->lock= (MYSQL_LOCK *)0;
+	if (lex->describe & DESCRIBE_EXTENDED)
+	{
+	  char buff[1024];
+	  String str(buff,(uint32) sizeof(buff), system_charset_info);
+	  str.length(0);
+	  thd->lex.unit.print(&str);
+	  str.append('\0');
+	  push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+		       ER_YES, str.ptr());
+	}
 	result->send_eof();
 	thd->lock= save_lock;
       }
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4bab97d4a4..f86435e1bb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -328,6 +328,20 @@ JOIN::prepare(Item ***rref_pointer_array,
       having->split_sum_func(ref_pointer_array, all_fields);
   }
 
+#ifndef DEBUG_OFF
+  {
+    char buff[256];
+    String str(buff,(uint32) sizeof(buff), system_charset_info);
+    str.length(0);
+    if (select_lex->master_unit()->item)
+      select_lex->master_unit()->item->print(&str);
+    else
+      unit->print(&str);
+    str.append('\0');
+    DBUG_PRINT("info", ("(SUB)SELECT: %s", str.ptr()));
+  }
+#endif
+
   // Is it subselect
   {
     Item_subselect *subselect;
@@ -880,12 +894,12 @@ JOIN::optimize()
     need_tmp=1; simple_order=simple_group=0;	// Force tmp table without sort
   }
 
+  tmp_having= having;
   if (select_options & SELECT_DESCRIBE)
   {
     error= 0;
     DBUG_RETURN(0);
   }
-  tmp_having= having;
   having= 0;
 
   /* Perform FULLTEXT search before all regular searches */
@@ -1547,11 +1561,23 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
     goto err;					// 1
   }
 
+  if (thd->lex.describe & DESCRIBE_EXTENDED)
+  {
+    join->conds_history= join->conds;
+    join->having_history= (join->having?join->having:join->tmp_having);
+  }
+
   if (thd->net.report_error)
     goto err;
 
   join->exec();
 
+  if (thd->lex.describe & DESCRIBE_EXTENDED)
+  {
+    select_lex->where= join->conds_history;
+    select_lex->having= join->having_history;
+  }
+
 err:
   if (free_join)
   {
@@ -8909,3 +8935,159 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
 			result, unit, select_lex, 0);
   DBUG_RETURN(res);
 }
+
+
+void st_select_lex::print(THD *thd, String *str)
+{
+  if (!thd)
+    thd= current_thd;
+
+  str->append("select ");
+  
+  //options
+  if (options & SELECT_STRAIGHT_JOIN)
+    str->append("straight_join ");
+  if ((thd->lex.lock_option & TL_READ_HIGH_PRIORITY) &&
+      (this == &thd->lex.select_lex))
+    str->append("high_priority ");
+  if (options & SELECT_DISTINCT)
+    str->append("distinct ");
+  if (options & SELECT_SMALL_RESULT)
+    str->append("small_result ");
+  if (options & SELECT_BIG_RESULT)
+    str->append("big_result ");
+  if (options & OPTION_BUFFER_RESULT)
+    str->append("buffer_result ");
+  if (options & OPTION_FOUND_ROWS)
+    str->append("calc_found_rows ");
+  if (!thd->lex.safe_to_cache_query)
+    str->append("no_cache ");
+  if (options & OPTION_TO_QUERY_CACHE)
+    str->append("cache ");
+
+  //Item List
+  bool first= 1;
+  List_iterator_fast<Item> it(item_list);
+  Item *item;
+  while ((item= it++))
+  {
+    if (first)
+      first= 0;
+    else
+      str->append(',');
+    item->print_item_w_name(str);
+  }
+
+  /*
+    from clause
+    TODO: support USING/FORCE/IGNORE index
+  */
+  if (table_list.elements)
+  {
+    str->append(" from ");
+    Item *next_on= 0;
+    for (TABLE_LIST *table= (TABLE_LIST *) table_list.first;
+	 table;
+	 table= table->next)
+    {
+      if (table->derived)
+      {
+	str->append('(');
+	table->derived->print(str);
+	str->append(") ");
+	str->append(table->alias);
+      }
+      else
+      {
+	str->append(table->db);
+	str->append('.');
+	str->append(table->real_name);
+	if (strcmp(table->real_name, table->alias))
+	{
+	  str->append(' ');
+	  str->append(table->alias);
+	}
+      }
+
+      if (table->on_expr && ((table->outer_join & JOIN_TYPE_LEFT) ||
+			     !(table->outer_join & JOIN_TYPE_RIGHT)))
+	next_on= table->on_expr;
+
+      if (next_on)
+      {
+	str->append(" on(");
+	next_on->print(str);
+	str->append(')');
+	next_on= 0;
+      }
+
+      TABLE_LIST *next;
+      if ((next= table->next))
+      {
+	if (table->outer_join & JOIN_TYPE_RIGHT)
+	{
+	  str->append(" right join ");
+	  if (!(table->outer_join & JOIN_TYPE_LEFT) &&
+	      table->on_expr)
+	    next_on= table->on_expr;	    
+	}
+	else if (next->straight)
+	  str->append(" straight_join ");
+	else if (next->outer_join & JOIN_TYPE_LEFT)
+	  str->append(" left join ");
+	else
+	  str->append(" join ");
+      }
+    }
+  }
+
+  //where
+  Item *where= this->where;
+  if (join)
+    where= join->conds;
+  if (where)
+  {
+    str->append(" where ");
+    where->print(str);
+  }
+
+  //group by & olap
+  if (group_list.elements)
+  {
+    str->append(" group by ");
+    print_order(str, (ORDER *) group_list.first);
+    switch (olap)
+    {
+      case CUBE_TYPE:
+	str->append(" with cube");
+	break;
+      case ROLLUP_TYPE:
+	str->append(" with rollup");
+	break;
+      default:
+	;  //satisfy compiler
+    }
+  }
+
+  //having
+  Item *having= this->having;
+  if (join)
+    having= join->having;
+
+  if (having)
+  {
+    str->append(" having ");
+    having->print(str);
+  }
+
+  if (order_list.elements)
+  {
+    str->append(" order by ");
+    print_order(str, (ORDER *) order_list.first);
+  }
+
+  // limit
+  print_limit(thd, str);
+
+  // PROCEDURE unsupported here
+}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 6c17a646ee..6c1410102f 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -151,7 +151,8 @@ class JOIN :public Sql_alloc
   Item_sum  **sum_funcs2, ***sum_funcs_end2;
   Procedure *procedure;
   Item	    *having;
-  Item      *tmp_having; // To store Having when processed temporary table
+  Item      *tmp_having; // To store having when processed temporary table
+  Item      *having_history; // Store having for explain
   uint	    select_options;
   select_result *result;
   TMP_TABLE_PARAM tmp_table_param;
@@ -181,6 +182,7 @@ class JOIN :public Sql_alloc
 
   ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
   COND *conds;                            // ---"---
+  Item *conds_history;                    // store WHERE for explain
   TABLE_LIST *tables_list;           //hold 'tables' parameter of mysql_selec
   SQL_SELECT *select;                //created in optimisation phase
   Item **ref_pointer_array; //used pointer reference for this select
@@ -217,8 +219,7 @@ class JOIN :public Sql_alloc
     thd= thd_arg;
     sum_funcs= sum_funcs2= 0;
     procedure= 0;
-    having= 0;
-    tmp_having= 0;
+    having= tmp_having= having_history= 0;
     select_options= select_options_arg;
     result= result_arg;
     lock= thd_arg->lock;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ebe05ec565..38d251c3ae 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -704,6 +704,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
 	union_clause union_list union_option
 	precision subselect_start opt_and charset
 	subselect_end select_var_list select_var_list_init help opt_len
+	opt_extended_describe
 END_OF_INPUT
 
 %type <NONE>
@@ -2263,7 +2264,7 @@ expr_expr:
 	| expr comp_op all_or_any in_subselect %prec EQ
 	{
 	  Item_allany_subselect *it=
-	    new Item_allany_subselect($1, (*$2)($3), $4);
+	    new Item_allany_subselect($1, (*$2)($3), $4, $3);
 	  if ($3)
 	    $$ = it->upper_not= new Item_func_not_all(it);	/* ALL */
 	  else
@@ -2309,7 +2310,7 @@ no_in_expr:
 	| no_in_expr comp_op all_or_any in_subselect %prec EQ
 	{
 	  Item_allany_subselect *it=
-	    new Item_allany_subselect($1, (*$2)($3), $4);
+	    new Item_allany_subselect($1, (*$2)($3), $4, $3);
 	  if ($3)
 	    $$ = it->upper_not= new Item_func_not_all(it);	/* ALL */
 	  else
@@ -2364,7 +2365,7 @@ no_and_expr:
 	| no_and_expr comp_op all_or_any in_subselect %prec EQ
 	{
 	  Item_allany_subselect *it=
-	    new Item_allany_subselect($1, (*$2)($3), $4);
+	    new Item_allany_subselect($1, (*$2)($3), $4, $3);
 	  if ($3)
 	    $$ = it->upper_not= new Item_func_not_all(it);	/* ALL */
 	  else
@@ -4025,7 +4026,9 @@ describe:
 	    YYABORT;
 	}
 	opt_describe_column {}
-	| describe_command { Lex->describe=1; } select
+	| describe_command opt_extended_describe
+	  { Lex->describe|= DESCRIBE_NORMAL; }
+	  select
           {
 	    LEX *lex=Lex;
 	    lex->select_lex.options|= SELECT_DESCRIBE;
@@ -4036,6 +4039,11 @@ describe_command:
 	DESC
 	| DESCRIBE;
 
+opt_extended_describe:
+	/* empty */ {}
+	| EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
+	;
+
 opt_describe_column:
 	/* empty */	{}
 	| text_string	{ Lex->wild= $1; }
@@ -4291,11 +4299,9 @@ literal:
 	  {
 	    Item *tmp= new Item_varbinary($2.str,$2.length);
 	    String *str= tmp ? tmp->val_str((String*) 0) : (String*) 0;
-	    Item_string *item = new Item_string(str ? str->ptr() : "",
-						str ? str->length() :
-						0, Lex->charset);
-	    item->set_varbin_name(tmp->name);
-	    $$= item;
+	    $$= new Item_string(str ? str->ptr() : "",
+				str ? str->length() : 0,
+				Lex->charset);
 	  }
 	| DATE_SYM text_literal { $$ = $2; }
 	| TIME_SYM text_literal { $$ = $2; }
@@ -5349,7 +5355,7 @@ order_or_limit:
 
 union_option:
 	/* empty */ {}
-	| ALL {Select->master_unit()->union_option= 1;};
+	| ALL {Select->master_unit()->union_option|= UNION_ALL;};
 
 singlerow_subselect:
 	subselect_start singlerow_subselect_init
-- 
2.30.9