diff options
-rw-r--r-- | mysql-test/r/subselect.result | 156 | ||||
-rw-r--r-- | mysql-test/r/union.result | 8 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 88 | ||||
-rw-r--r-- | mysql-test/t/union.test | 4 | ||||
-rw-r--r-- | sql/item.cc | 92 | ||||
-rw-r--r-- | sql/item.h | 36 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 62 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 14 | ||||
-rw-r--r-- | sql/item_func.cc | 38 | ||||
-rw-r--r-- | sql/item_func.h | 8 | ||||
-rw-r--r-- | sql/item_geofunc.h | 3 | ||||
-rw-r--r-- | sql/item_row.cc | 12 | ||||
-rw-r--r-- | sql/item_row.h | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 8 | ||||
-rw-r--r-- | sql/item_strfunc.h | 9 | ||||
-rw-r--r-- | sql/item_subselect.cc | 170 | ||||
-rw-r--r-- | sql/item_subselect.h | 27 | ||||
-rw-r--r-- | sql/item_sum.cc | 33 | ||||
-rw-r--r-- | sql/item_sum.h | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 78 | ||||
-rw-r--r-- | sql/item_timefunc.h | 24 | ||||
-rw-r--r-- | sql/item_uniq.h | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/sql_derived.cc | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 66 | ||||
-rw-r--r-- | sql/sql_lex.h | 14 | ||||
-rw-r--r-- | sql/sql_parse.cc | 10 | ||||
-rw-r--r-- | sql/sql_select.cc | 184 | ||||
-rw-r--r-- | sql/sql_select.h | 7 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 41 |
30 files changed, 1016 insertions, 188 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a2e83729513..96defcfa79b 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 on a 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 on PRIMARY))) 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 on PRIMARY 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 on a))) 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 on a 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 on a 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 @@ -1418,7 +1482,7 @@ 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 @@ -1430,10 +1494,14 @@ explain select s1, s1 <> ALL (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 on s1 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 on s1 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); @@ -1443,19 +1511,23 @@ 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 t2, t3; CREATE TABLE `t1` ( `id` mediumint(9) NOT NULL auto_increment, `taskid` bigint(20) NOT NULL default '0', `dbid` int(11) NOT NULL default '0', `create_date` datetime NOT NULL default '0000-00-00 00:00:00', `last_update` datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (`id`)) TYPE=MyISAM CHARSET=latin1 AUTO_INCREMENT=3 ; INSERT INTO `t1` (`id`, `taskid`, `dbid`, `create_date`,`last_update`) VALUES (1, 1, 15, '2003-09-29 10:31:36', '2003-09-29 10:31:36'), (2, 1, 21, now(), now()); diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index bf47e6ad430..5729d3b32ee 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 3648210b943..bc49f0c28cd 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; @@ -950,10 +950,10 @@ select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; select s1, s1 = ANY (SELECT s1 FROM t2) from t1; select s1, s1 <> ALL (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 = ANY (SELECT s1 FROM t2) from t1; -explain select s1, s1 <> ALL (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 = ANY (SELECT s1 FROM t2) from t1; +explain extended select s1, s1 <> ALL (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; # @@ -963,14 +963,14 @@ 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 t2, t3; # diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index b64f0b4e2ee..1f3f4085734 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 0462a78376f..933d219d29d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -87,6 +87,19 @@ Item::Item(THD *c_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), @@ -445,12 +458,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) @@ -461,12 +470,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); } @@ -478,8 +483,10 @@ String *Item_real::val_str(String *str) void Item_string::print(String *str) { + str->append('_'); + str->append(collation.collation->csname); str->append('\''); - str->append(full_name()); + str->append(str_value); str->append('\''); } @@ -777,7 +784,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), @@ -1533,6 +1540,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 && @@ -1754,6 +1789,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); @@ -1804,6 +1867,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 c738f92124f..5f691c9e4e4 100644 --- a/sql/item.h +++ b/sql/item.h @@ -182,6 +182,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); @@ -315,6 +316,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 @@ -365,6 +367,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 @@ -637,6 +640,7 @@ public: (*ref)->save_in_field(result_field, no_conversions); } Item *real_item() { return *ref; } + void print(String *str); }; class Item_in_subselect; @@ -652,15 +656,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 @@ -672,6 +668,7 @@ public: :Item_ref_null_helper(master, &store, table_name_par, field_name_par), store(item) {} + void print(String *str); }; /* @@ -853,14 +850,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) { @@ -870,6 +869,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 @@ -878,12 +878,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; } @@ -896,12 +891,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 4e6301d2626..d183c81b230 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 @@ -704,6 +712,18 @@ longlong Item_func_between::val_int() return 0; } + +void Item_func_between::print(String *str) +{ + str->append('('); + args[0]->print(str); + str->append(" between "); + args[1]->print(str); + str->append(" and "); + args[2]->print(str); + str->append(')'); +} + void Item_func_ifnull::fix_length_and_dec() { @@ -1097,7 +1117,27 @@ void Item_func_case::fix_length_and_dec() void Item_func_case::print(String *str) { - str->append("case "); // Not yet complete + str->append("(case "); + if (first_expr_num != -1) + { + args[first_expr_num]->print(str); + str->append(' '); + } + for (uint i=0 ; i < ncases ; i+=2) + { + str->append("when "); + args[i]->print(str); + str->append(" then "); + args[i+1]->print(str); + str->append(' '); + } + if (else_expr_num != -1) + { + str->append("else "); + args[else_expr_num]->print(str); + str->append(' '); + } + str->append("end)"); } /* @@ -1504,8 +1544,15 @@ void Item_func_in::fix_length_and_dec() void Item_func_in::print(String *str) { str->append('('); - Item_func::print(str); - str->append(')'); + args[0]->print(str); + str->append(" IN ("); + for (uint i=1 ; i < arg_count ; i++) + { + if (i > 1) + str->append(','); + args[i]->print(str); + } + str->append("))"); } @@ -1866,12 +1913,21 @@ void Item_is_not_null_test::update_used_tables() } } + longlong Item_func_isnotnull::val_int() { return args[0]->is_null() ? 0 : 1; } +void Item_func_isnotnull::print(String *str) +{ + str->append('('); + args[0]->print(str); + str->append(" is not null)"); +} + + longlong Item_func_like::val_int() { String* res = args[0]->val_str(&tmp_value1); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 42b73c48606..eb473a1a73d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -105,7 +105,7 @@ public: Item_in_optimizer return NULL, else it evaluate Item_in_subselect. */ longlong val_int(); - const char *func_name() const { return "IN_OPTIMIZER"; } + const char *func_name() const { return "<in_optimizer>"; } Item_cache **get_cache() { return &cache; } }; @@ -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 @@ -262,6 +266,7 @@ public: enum Functype functype() const { return BETWEEN; } const char *func_name() const { return "between"; } void fix_length_and_dec(); + void print(String *str); }; @@ -704,7 +709,7 @@ public: {} enum Functype functype() const { return ISNOTNULLTEST_FUNC; } longlong val_int(); - const char *func_name() const { return "is_not_null_test"; } + const char *func_name() const { return "<is_not_null_test>"; } void update_used_tables(); }; @@ -722,6 +727,7 @@ public: const char *func_name() const { return "isnotnull"; } optimize_type select_optimize() const { return OPTIMIZE_NULL; } table_map not_null_tables() const { return 0; } + void print(String *str); }; @@ -775,6 +781,7 @@ public: longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); const char *func_name() const { return "regex"; } + void print(String *str) { print_op(str); } }; #else @@ -785,6 +792,7 @@ public: Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b) {} longlong val_int() { return 0;} const char *func_name() const { return "regex"; } + void print(String *str) { print_op(str); } }; #endif /* USE_REGEX */ diff --git a/sql/item_func.cc b/sql/item_func.cc index ce0614f1e7c..bff7c9a6bf3 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -462,6 +462,24 @@ String *Item_num_op::val_str(String *str) } +void Item_func_signed::print(String *str) +{ + str->append("cast("); + args[0]->print(str); + str->append("as signed)"); + +} + + +void Item_func_unsigned::print(String *str) +{ + str->append("cast("); + args[0]->print(str); + str->append("as unsigned)"); + +} + + double Item_func_plus::val() { double value=args[0]->val()+args[1]->val(); @@ -2820,6 +2838,26 @@ double Item_func_match::val() DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, record, 0)); } +void Item_func_match::print(String *str) +{ + str->append("(match "); + List_iterator_fast<Item> li(fields); + Item *item; + bool first= 1; + while ((item= li++)) + { + if (first) + first= 0; + else + str->append(','); + item->print(str); + } + str->append(" against ("); + args[0]->print(str); + if (mode == FT_BOOL) + str->append(" in boolean mode"); + str->append("))"); +} longlong Item_func_bit_xor::val_int() { diff --git a/sql/item_func.h b/sql/item_func.h index fe9c2645216..541ced0f1ba 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -214,6 +214,7 @@ public: longlong val_int() { return args[0]->val_int(); } void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=0; } + void print(String *str); }; @@ -225,6 +226,7 @@ public: longlong val_int() { return args[0]->val_int(); } void fix_length_and_dec() { max_length=args[0]->max_length; unsigned_flag=1; } + void print(String *str); }; @@ -662,6 +664,7 @@ public: longlong val_int(); const char *func_name() const { return "|"; } void fix_length_and_dec() { unsigned_flag=1; } + void print(String *str) { print_op(str); } }; class Item_func_bit_and :public Item_int_func @@ -671,6 +674,7 @@ public: longlong val_int(); const char *func_name() const { return "&"; } void fix_length_and_dec() { unsigned_flag=1; } + void print(String *str) { print_op(str); } }; class Item_func_bit_count :public Item_int_func @@ -689,6 +693,7 @@ public: longlong val_int(); const char *func_name() const { return "<<"; } void fix_length_and_dec() { unsigned_flag=1; } + void print(String *str) { print_op(str); } }; class Item_func_shift_right :public Item_int_func @@ -697,6 +702,7 @@ public: Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return ">>"; } + void print(String *str) { print_op(str); } }; class Item_func_bit_neg :public Item_int_func @@ -1005,6 +1011,7 @@ public: bool eq(const Item *, bool binary_cmp) const; longlong val_int() { return val()!=0.0; } double val(); + void print(String *str); bool fix_index(); void init_search(bool no_order); @@ -1040,6 +1047,7 @@ public: longlong val_int(); const char *func_name() const { return "^"; } void fix_length_xor_dec() { unsigned_flag=1; } + void print(String *str) { print_op(str); } }; class Item_func_is_free_lock :public Item_int_func diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 79e45cca26f..72dc6620f3b 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -118,6 +118,7 @@ public: case SP_EXTERIORRING: return "exteriorring"; default: + DBUG_ASSERT(0); // Should never happened return "spatial_decomp_unknown"; } } @@ -142,6 +143,7 @@ public: case SP_INTERIORRINGN: return "interiorringn"; default: + DBUG_ASSERT(0); // Should never happened return "spatial_decomp_n_unknown"; } } @@ -210,6 +212,7 @@ public: case SP_OVERLAPS_FUNC: return "overlaps"; default: + DBUG_ASSERT(0); // Should never happened return "sp_unknown"; } } diff --git a/sql/item_row.cc b/sql/item_row.cc index fcc6e5192ec..89b38c8a753 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -118,6 +118,18 @@ bool Item_row::check_cols(uint c) return 0; } +void Item_row::print(String *str) +{ + str->append('('); + for (uint i= 0; i < arg_count; i++) + { + if (i) + str->append(','); + items[i]->print(str); + } + str->append(')'); +} + bool Item_row::walk(Item_processor processor, byte *arg) { for (uint i= 0; i < arg_count; i++) diff --git a/sql/item_row.h b/sql/item_row.h index 6dd955ed426..a09bd1a2c31 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -68,6 +68,7 @@ public: bool const_item() const { return const_item_cache; }; enum Item_result result_type() const { return ROW_RESULT; } void update_used_tables(); + void print(String *str); bool walk(Item_processor processor, byte *arg); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 99dd06c566c..5afd52e3738 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2271,6 +2271,14 @@ String *Item_func_hex::val_str(String *str) } +void Item_func_binary::print(String *str) +{ + str->append("cast("); + args[0]->print(str); + str->append("as binary)"); +} + + #include <my_dir.h> // For my_stat String *Item_load_file::val_str(String *str) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index b82dacb4fe0..51dff0fbaf2 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -120,6 +120,7 @@ public: Item_func_reverse(Item *a) :Item_str_func(a) {} String *val_str(String *); void fix_length_and_dec(); + const char *func_name() const { return "reverse"; } }; @@ -324,10 +325,12 @@ public: Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {} String *val_str(String *); void fix_length_and_dec() { maybe_null=1; max_length = 13; } + const char *func_name() const { return "ecrypt"; } }; #include "sql_crypt.h" + class Item_func_encode :public Item_str_func { protected: @@ -337,13 +340,16 @@ public: Item_str_func(a),sql_crypt(seed) {} String *val_str(String *); void fix_length_and_dec(); + const char *func_name() const { return "encode"; } }; + class Item_func_decode :public Item_func_encode { public: Item_func_decode(Item *a, char *seed): Item_func_encode(a,seed) {} String *val_str(String *); + const char *func_name() const { return "decode"; } }; @@ -520,7 +526,6 @@ class Item_func_binary :public Item_str_func { public: Item_func_binary(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "binary"; } String *val_str(String *a) { String *tmp=args[0]->val_str(a); @@ -534,7 +539,7 @@ public: collation.set(&my_charset_bin); max_length=args[0]->max_length; } - void print(String *str) { print_op(str); } + void print(String *str); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 589a41052c5..5105323be22 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -146,21 +146,25 @@ Item::Type Item_subselect::type() const return SUBSELECT_ITEM; } + void Item_subselect::fix_length_and_dec() { engine->fix_length_and_dec(0); } + table_map Item_subselect::used_tables() const { return (table_map) (engine->dependent() ? used_tables_cache : 0L); } + bool Item_subselect::const_item() const { return const_item_cache; } + void Item_subselect::update_used_tables() { if (!engine->uncacheable()) @@ -171,6 +175,15 @@ void Item_subselect::update_used_tables() } } + +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) { @@ -184,11 +197,12 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, 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; @@ -203,6 +217,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, 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; @@ -245,7 +265,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) @@ -365,6 +385,7 @@ String *Item_singlerow_subselect::val_str (String *str) } } + Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): Item_subselect() { @@ -379,6 +400,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 && @@ -396,7 +425,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; @@ -412,8 +441,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; @@ -800,6 +830,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); @@ -807,12 +838,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, @@ -1140,11 +1241,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; @@ -1155,16 +1258,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(); @@ -1175,6 +1281,7 @@ void subselect_union_engine::exclude() unit->exclude_level(); } + void subselect_uniquesubquery_engine::exclude() { //this never should be called @@ -1201,8 +1308,59 @@ table_map subselect_single_select_engine::upper_select_const_tables() table_list.first); } + table_map subselect_union_engine::upper_select_const_tables() { return calc_const_tables((TABLE_LIST *) unit->outer_select()-> table_list.first); } + + +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); + KEY *key_info= tab->table->key_info+ tab->ref.key; + str->append(" on "); + str->append(key_info->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); + KEY *key_info= tab->table->key_info+ tab->ref.key; + str->append(" on "); + str->append(key_info->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 7e735165c02..8d438d0e72f 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -92,13 +92,7 @@ public: inline table_map get_used_tables_cache() { return used_tables_cache; } inline bool get_const_item_cache() { return const_item_cache; } void update_used_tables(); - 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; @@ -147,9 +141,11 @@ public: /* used in static ALL/ANY optimisation */ class Item_maxmin_subselect :public Item_singlerow_subselect { + bool max; public: Item_maxmin_subselect(Item_subselect *parent, st_select_lex *select_lex, bool max); + void print(String *str); }; /* exists subselect */ @@ -174,6 +170,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; @@ -194,12 +191,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() @@ -219,6 +219,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; @@ -233,12 +234,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); }; @@ -276,6 +280,7 @@ public: bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; static table_map calc_const_tables(TABLE_LIST *); + virtual void print(String *str)= 0; }; @@ -298,6 +303,7 @@ public: bool uncacheable(); void exclude(); table_map upper_select_const_tables(); + void print (String *str); }; @@ -316,6 +322,7 @@ public: bool uncacheable(); void exclude(); table_map upper_select_const_tables(); + void print (String *str); }; @@ -343,6 +350,7 @@ public: bool uncacheable() { return 1; } void exclude(); table_map upper_select_const_tables() { return 0; } + void print (String *str); }; @@ -359,4 +367,5 @@ public: check_null(chk_null) {} int exec(); + void print (String *str); }; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 9da1b21db72..1a5df9e8ccc 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1366,6 +1366,14 @@ longlong Item_sum_count_distinct::val_int() return table->file->records; } + +void Item_sum_count_distinct::print(String *str) +{ + str->append("count(distinct "); + args[0]->print(str); + str->append(')'); +} + /**************************************************************************** ** Functions to handle dynamic loadable aggregates ** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su> @@ -1960,3 +1968,28 @@ String* Item_func_group_concat::val_str(String* str) } return &result; } + +void Item_func_group_concat::print(String *str) +{ + str->append("group concat("); + if (distinct) + str->append(" distinct "); + for (uint i= 0; i < arg_count; i++) + { + if (i) + str->append(','); + args[i]->print(str); + } + if (arg_count_order) + { + for (uint i= 0 ; i < arg_count_order ; i++) + { + if (i) + str->append(','); + (*order[i]->item)->print(str); + } + } + str->append(" seperator \'"); + str->append(*separator); + str->append("\')"); +} diff --git a/sql/item_sum.h b/sql/item_sum.h index e5061e1e05a..d454f06ccde 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -238,6 +238,7 @@ class Item_sum_count_distinct :public Item_sum_int void make_unique(); Item *copy_or_same(THD* thd); void no_rows_in_result() {} + void print(String *str); }; @@ -748,4 +749,5 @@ class Item_func_group_concat : public Item_sum String* val_str(String* str); Item *copy_or_same(THD* thd); void no_rows_in_result() {} + void print(String *str); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 4009256ee17..a8c8f9bcf7f 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1644,6 +1644,35 @@ longlong Item_date_add_interval::val_int() ((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second; } +static const char *interval_names[]= +{ + "year", "month", "day", "hour", "minute", + "second", "microsecond", "year_month", + "day_hour", "day_minute", "day_second", + "hour_minute", "hour_second", "minute_second", + "day_microsecond", "hour_microsecond", + "minute_microsecond", "second_microsecond" +}; + +void Item_date_add_interval::print(String *str) +{ + str->append('('); + args[0]->print(str); + str->append(date_sub_interval?" - interval ":" + interval "); + args[1]->print(str); + str->append(interval_names[int_type]); + str->append(')'); +} + +void Item_extract::print(String *str) +{ + str->append("extract("); + str->append(interval_names[int_type]); + str->append(' '); + args[0]->print(str); + str->append(')'); +} + void Item_extract::fix_length_and_dec() { value.alloc(32); // alloc buffer @@ -1751,10 +1780,31 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const void Item_typecast::print(String *str) { - str->append("CAST("); + str->append("cast("); args[0]->print(str); - str->append(" AS "); - str->append(func_name()); + str->append(" as "); + str->append(cast_type()); + str->append(')'); +} + +void Item_char_typecast::print(String *str) +{ + str->append("cast("); + args[0]->print(str); + str->append(" as char"); + if (cast_length >= 0) + { + str->append('('); + char buff[10]; + snprintf(buff, 10, "%d", cast_length); + str->append(buff); + str->append(')'); + } + if (cast_cs) + { + str->append(" charset "); + str->append(cast_cs->name); + } str->append(')'); } @@ -2039,6 +2089,28 @@ null_date: return 0; } + +void Item_func_add_time::print(String *str) +{ + if (is_date) + { + DBUG_ASSERT(sign > 0); + str->append("timestamp("); + } + else + { + if (sign > 0) + str->append("addtime("); + else + str->append("subtime("); + } + args[0]->print(str); + str->append(','); + args[0]->print(str); + str->append(')'); +} + + /* TIMEDIFF(t,s) is a time function that calculates the time value between a start and end time. diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index b7bf294b83d..ea1e51614c7 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -544,13 +544,13 @@ public: enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, - INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, - INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, - INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, - INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND + INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, + INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, + INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, + INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, + INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND }; - class Item_date_add_interval :public Item_date_func { const interval_type int_type; @@ -568,6 +568,7 @@ public: double val() { return (double) val_int(); } longlong val_int(); bool get_date(TIME *res,bool fuzzy_date); + void print(String *str); }; @@ -583,6 +584,7 @@ class Item_extract :public Item_int_func const char *func_name() const { return "extract"; } void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; + void print(String *str); }; @@ -590,7 +592,6 @@ class Item_typecast :public Item_str_func { public: Item_typecast(Item *a) :Item_str_func(a) {} - const char *func_name() const { return "char"; } String *val_str(String *a) { String *tmp=args[0]->val_str(a); @@ -604,6 +605,7 @@ public: collation.set(default_charset()); max_length=args[0]->max_length; } + virtual const char* cast_type() const= 0; void print(String *str); }; @@ -617,8 +619,10 @@ class Item_char_typecast :public Item_typecast public: Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg) :Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {} + const char* cast_type() const { return "char"; }; String *val_str(String *a); void fix_length_and_dec(); + void print(String *str); }; @@ -628,7 +632,7 @@ public: Item_date_typecast(Item *a) :Item_typecast(a) {} String *val_str(String *str); bool get_date(TIME *ltime, bool fuzzy_date); - const char *func_name() const { return "date"; } + const char *cast_type() const { return "date"; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; } Field *tmp_table_field(TABLE *t_arg) { @@ -643,7 +647,7 @@ public: Item_time_typecast(Item *a) :Item_typecast(a) {} String *val_str(String *str); bool get_time(TIME *ltime); - const char *func_name() const { return "time"; } + const char *cast_type() const { return "time"; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; } Field *tmp_table_field(TABLE *t_arg) { @@ -657,7 +661,7 @@ class Item_datetime_typecast :public Item_typecast public: Item_datetime_typecast(Item *a) :Item_typecast(a) {} String *val_str(String *str); - const char *func_name() const { return "datetime"; } + const char *cast_type() const { return "datetime"; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } Field *tmp_table_field(TABLE *t_arg) { @@ -694,7 +698,6 @@ public: Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg) :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } String *val_str(String *str); - const char *func_name() const { return "addtime"; } enum_field_types field_type() const { return cached_field_type; } void fix_length_and_dec(); @@ -711,6 +714,7 @@ public: return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin)); } + void print(String *str); }; class Item_func_timediff :public Item_str_func diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 9b370b70181..2101fc4e45a 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -29,6 +29,7 @@ public: :Item_real_func(list) {} double val() { return 0.0; } void fix_length_and_dec() { decimals=0; max_length=6; } + void print(String *str) { str->append("0.0"); } }; @@ -54,4 +55,5 @@ public: { return new Item_sum_unique_users(thd, *this); } + void print(String *str) { str->append("0.0"); } }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1926314cef1..e387711e1f0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -199,6 +199,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 7fd2b751c1d..719686a56c3 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_tree(); 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 352a79843a9..ee0743d531e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1471,7 +1471,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 7545f525082..f78f1171d06 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 @@ -327,7 +331,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: @@ -468,6 +474,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; @@ -542,9 +551,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 36a7d19a3c5..270a249073d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1832,6 +1832,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 9bdb989b6a1..278839442e3 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) { @@ -8915,3 +8941,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 6c17a646ee6..6c1410102fd 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 c7a27592a7b..6d08e39c6a2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -711,6 +711,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> @@ -2878,17 +2879,19 @@ opt_gconcat_separator: opt_gorder_clause: - /* empty */ - { - LEX *lex=Lex; - lex->gorder_list = NULL; - } - | order_clause - { - LEX *lex=Lex; - lex->gorder_list= (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,sizeof(st_sql_list)); - lex->current_select->order_list.empty(); - }; + /* empty */ + { + LEX *lex=Lex; + lex->gorder_list = NULL; + } + | order_clause + { + LEX *lex=Lex; + lex->gorder_list= + (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list, + sizeof(st_sql_list)); + lex->current_select->order_list.empty(); + }; in_sum_expr: @@ -4027,7 +4030,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; @@ -4038,6 +4043,11 @@ describe_command: DESC | DESCRIBE; +opt_extended_describe: + /* empty */ {} + | EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; } + ; + opt_describe_column: /* empty */ {} | text_string { Lex->wild= $1; } @@ -4293,8 +4303,9 @@ literal: { Item *tmp= new Item_varbinary($2.str,$2.length); String *str= tmp ? tmp->val_str((String*) 0) : (String*) 0; - $$ = new Item_string(str ? str->ptr() : "", str ? str->length() : - 0, Lex->charset); + $$= new Item_string(str ? str->ptr() : "", + str ? str->length() : 0, + Lex->charset); } | DATE_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; } @@ -5352,7 +5363,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 |