diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 6c00b91b13f..f99ac506ad0 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -153,6 +153,7 @@ tim@hundin.mysql.fi tim@threads.polyesthetic.msg tim@white.box tim@work.mysql.com +timour@mysql.com tom@basil-firewall.home.com tonu@hundin.mysql.fi tonu@volk.internalnet diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index de1d1c6cb14..290cb9361f1 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -388,8 +388,8 @@ SELECT DISTINCTROW email, shipcode FROM t1, t2 WHERE t1.infoID=t2.infoID; email shipcode test1@testdomain.com Z001 test2@testdomain.com Z001 -test3@testdomain.com Z001 test2@testdomain.com R002 +test3@testdomain.com Z001 SELECT DISTINCTROW email FROM t1 ORDER BY dateentered DESC; email test1@testdomain.com diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 147d7776e4d..d256bdf7a77 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -183,12 +183,12 @@ insert into t2 values('BBB', 20, 1.0); select t1.a1, t1.a2, t2.a1, t2.a2 from t1,t2; a1 a2 a1 a2 10 aaa AAA 10 -10 NULL AAA 10 -10 bbb AAA 10 -20 zzz AAA 10 10 aaa BBB 20 +10 NULL AAA 10 10 NULL BBB 20 +10 bbb AAA 10 10 bbb BBB 20 +20 zzz AAA 10 20 zzz BBB 20 select max(t1.a1), max(t2.a1) from t1, t2 where t2.a2=9; max(t1.a1) max(t2.a1) @@ -551,7 +551,7 @@ id select_type table type possible_keys key key_len ref rows Extra explain select min(a1) from t1 where a1 between a3 and 'KKK'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 14 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 14 Using where explain select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08; id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/greedy_optimizer.result b/mysql-test/r/greedy_optimizer.result new file mode 100644 index 00000000000..a6b92d38f74 --- /dev/null +++ b/mysql-test/r/greedy_optimizer.result @@ -0,0 +1,657 @@ +drop table if exists t1,t2,t3,t4,t5,t6,t7; +create table t1 ( +c11 integer,c12 integer,c13 integer,c14 integer,c15 integer,c16 integer, +primary key (c11) +); +create table t2 ( +c21 integer,c22 integer,c23 integer,c24 integer,c25 integer,c26 integer, +); +create table t3 ( +c31 integer,c32 integer,c33 integer,c34 integer,c35 integer,c36 integer, +primary key (c31) +); +create table t4 ( +c41 integer,c42 integer,c43 integer,c44 integer,c45 integer,c46 integer +); +create table t5 ( +c51 integer,c52 integer,c53 integer,c54 integer,c55 integer,c56 integer, +primary key (c51) +); +create table t6 ( +c61 integer,c62 integer,c63 integer,c64 integer,c65 integer,c66 integer +); +create table t7 ( +c71 integer,c72 integer,c73 integer,c74 integer,c75 integer,c76 integer, +primary key (c71) +); +insert into t1 values (1,2,3,4,5,6); +insert into t1 values (2,2,3,4,5,6); +insert into t1 values (3,2,3,4,5,6); +insert into t2 values (1,2,3,4,5,6); +insert into t2 values (2,2,3,4,5,6); +insert into t2 values (3,2,3,4,5,6); +insert into t2 values (4,2,3,4,5,6); +insert into t2 values (5,2,3,4,5,6); +insert into t2 values (6,2,3,4,5,6); +insert into t3 values (1,2,3,4,5,6); +insert into t3 values (2,2,3,4,5,6); +insert into t3 values (3,2,3,4,5,6); +insert into t3 values (4,2,3,4,5,6); +insert into t3 values (5,2,3,4,5,6); +insert into t3 values (6,2,3,4,5,6); +insert into t3 values (7,2,3,4,5,6); +insert into t3 values (8,2,3,4,5,6); +insert into t3 values (9,2,3,4,5,6); +insert into t4 values (1,2,3,4,5,6); +insert into t4 values (2,2,3,4,5,6); +insert into t4 values (3,2,3,4,5,6); +insert into t4 values (4,2,3,4,5,6); +insert into t4 values (5,2,3,4,5,6); +insert into t4 values (6,2,3,4,5,6); +insert into t4 values (7,2,3,4,5,6); +insert into t4 values (8,2,3,4,5,6); +insert into t4 values (9,2,3,4,5,6); +insert into t4 values (10,2,3,4,5,6); +insert into t4 values (11,2,3,4,5,6); +insert into t4 values (12,2,3,4,5,6); +insert into t5 values (1,2,3,4,5,6); +insert into t5 values (2,2,3,4,5,6); +insert into t5 values (3,2,3,4,5,6); +insert into t5 values (4,2,3,4,5,6); +insert into t5 values (5,2,3,4,5,6); +insert into t5 values (6,2,3,4,5,6); +insert into t5 values (7,2,3,4,5,6); +insert into t5 values (8,2,3,4,5,6); +insert into t5 values (9,2,3,4,5,6); +insert into t5 values (10,2,3,4,5,6); +insert into t5 values (11,2,3,4,5,6); +insert into t5 values (12,2,3,4,5,6); +insert into t5 values (13,2,3,4,5,6); +insert into t5 values (14,2,3,4,5,6); +insert into t5 values (15,2,3,4,5,6); +insert into t6 values (1,2,3,4,5,6); +insert into t6 values (2,2,3,4,5,6); +insert into t6 values (3,2,3,4,5,6); +insert into t6 values (4,2,3,4,5,6); +insert into t6 values (5,2,3,4,5,6); +insert into t6 values (6,2,3,4,5,6); +insert into t6 values (7,2,3,4,5,6); +insert into t6 values (8,2,3,4,5,6); +insert into t6 values (9,2,3,4,5,6); +insert into t6 values (10,2,3,4,5,6); +insert into t6 values (11,2,3,4,5,6); +insert into t6 values (12,2,3,4,5,6); +insert into t6 values (13,2,3,4,5,6); +insert into t6 values (14,2,3,4,5,6); +insert into t6 values (15,2,3,4,5,6); +insert into t6 values (16,2,3,4,5,6); +insert into t6 values (17,2,3,4,5,6); +insert into t6 values (18,2,3,4,5,6); +insert into t7 values (1,2,3,4,5,6); +insert into t7 values (2,2,3,4,5,6); +insert into t7 values (3,2,3,4,5,6); +insert into t7 values (4,2,3,4,5,6); +insert into t7 values (5,2,3,4,5,6); +insert into t7 values (6,2,3,4,5,6); +insert into t7 values (7,2,3,4,5,6); +insert into t7 values (8,2,3,4,5,6); +insert into t7 values (9,2,3,4,5,6); +insert into t7 values (10,2,3,4,5,6); +insert into t7 values (11,2,3,4,5,6); +insert into t7 values (12,2,3,4,5,6); +insert into t7 values (13,2,3,4,5,6); +insert into t7 values (14,2,3,4,5,6); +insert into t7 values (15,2,3,4,5,6); +insert into t7 values (16,2,3,4,5,6); +insert into t7 values (17,2,3,4,5,6); +insert into t7 values (18,2,3,4,5,6); +insert into t7 values (19,2,3,4,5,6); +insert into t7 values (20,2,3,4,5,6); +insert into t7 values (21,2,3,4,5,6); +select @@plan_search_depth; +@@plan_search_depth +62 +select @@heuristic; +@@heuristic +1 +set plan_search_depth=63; +select @@plan_search_depth; +@@plan_search_depth +63 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +set heuristic=0; +select @@heuristic; +@@heuristic +0 +set plan_search_depth=0; +select @@plan_search_depth; +@@plan_search_depth +0 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +set plan_search_depth=1; +select @@plan_search_depth; +@@plan_search_depth +1 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +set plan_search_depth=62; +select @@plan_search_depth; +@@plan_search_depth +62 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.c21 1 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 274.419727 +set heuristic=1; +select @@heuristic; +@@heuristic +1 +set plan_search_depth=0; +select @@plan_search_depth; +@@plan_search_depth +0 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +set plan_search_depth=1; +select @@plan_search_depth; +@@plan_search_depth +1 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +set plan_search_depth=62; +select @@plan_search_depth; +@@plan_search_depth +62 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t2.c22 1 +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t4.c42 1 +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t6.c62 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 821.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using index +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using index +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using index +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL PRIMARY NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 6 Using where +1 SIMPLE t3 eq_ref PRIMARY PRIMARY 4 test.t1.c12 1 Using where +1 SIMPLE t4 ALL NULL NULL NULL NULL 12 Using where +1 SIMPLE t5 eq_ref PRIMARY PRIMARY 4 test.t1.c14 1 Using where +1 SIMPLE t6 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t7 eq_ref PRIMARY PRIMARY 4 test.t1.c16 1 Using where +show status like 'Last_query_cost'; +Variable_name Value +Last_query_cost 794.838037 +drop table t1,t2,t3,t4,t5,t6,t7; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 43c41378f30..5ed2587336e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -1393,8 +1393,8 @@ companynr companynr 41 40 explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using temporary -1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using where; Using index +1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using index; Using temporary +1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 Using where select t2.fld1,t2.companynr,fld3,period from t3,t2 where t2.fld1 = 38208 and t2.fld1=t3.t2nr and period = 1008 or t2.fld1 = 38008 and t2.fld1 =t3.t2nr and period = 1008; fld1 companynr fld3 period 038008 37 reporters 1008 @@ -2279,10 +2279,10 @@ a a a 2 2 2 3 3 3 select * from t1 natural join (t1 as t2 left join t1 as t3 using (a)); -a a -1 1 -2 2 -3 3 +a a a +1 1 1 +2 2 2 +3 3 3 select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1; a a a 1 1 1 @@ -2314,30 +2314,10 @@ left join t4 on id3 = id4 where id2 = 1 or id4 = 1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 -1 SIMPLE t2 ALL NULL NULL NULL NULL 1 -1 SIMPLE t4 ALL id4 NULL NULL NULL 1 Using where +1 SIMPLE t4 ALL id4 NULL NULL NULL 1 +1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3 left join t4 on id3 = id4 where id2 = 1 or id4 = 1; id1 id2 id3 id4 id44 1 1 NULL NULL NULL drop table t1,t2,t3,t4; -create table t1(s varchar(10) not null); -create table t2(s varchar(10) not null primary key); -create table t3(s varchar(10) not null primary key); -insert into t1 values ('one\t'), ('two\t'); -insert into t2 values ('one\r'), ('two\t'); -insert into t3 values ('one '), ('two\t'); -select * from t1 where s = 'one'; -s -select * from t2 where s = 'one'; -s -select * from t3 where s = 'one'; -s -one -select * from t1,t2 where t1.s = t2.s; -s s -two two -select * from t2,t3 where t2.s = t3.s; -s s -two two -drop table t1, t2, t3; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 19bda2fec44..9477506cb96 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -6,7 +6,7 @@ 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 1249 Select 2 was reduced during optimisation +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) @@ -17,8 +17,8 @@ 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 1249 Select 2 was reduced during optimisation -Note 1249 Select 4 was reduced during optimisation +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)) @@ -29,7 +29,7 @@ id select_type table type possible_keys key key_len ref rows Extra 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 1249 Select 2 was reduced during optimisation +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) @@ -46,8 +46,8 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used Warnings: -Note 1276 Field or reference 'a' of SELECT #3 was resolved in SELECT #1 -Note 1276 Field or reference 'b.a' of SELECT #3 was resolved in SELECT #1 +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 @@ -219,7 +219,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where Warnings: -Note 1276 Field or reference 't4.a' of SELECT #3 was resolved in SELECT #1 +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 @@ -307,8 +307,8 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 1 3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1276 Field or reference 't2.a' of SELECT #2 was resolved in SELECT #1 -Note 1276 Field or reference 't2.a' of SELECT #3 was resolved in SELECT #1 +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 @@ -326,7 +326,7 @@ 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 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1 +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 @@ -715,7 +715,7 @@ 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 1249 Select 2 was reduced during optimisation +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 @@ -727,8 +727,8 @@ 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 1249 Select 3 was reduced during optimisation -Note 1249 Select 2 was reduced during optimisation +Note 1248 Select 3 was reduced during optimisation +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 + 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 @@ -860,8 +860,8 @@ 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 1276 Field or reference 'a' of SELECT #2 was resolved in SELECT #1 -Note 1249 Select 2 was reduced during optimisation +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) @@ -978,7 +978,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist CREATE TABLE t1 (a int, KEY(a)); HANDLER t1 OPEN; HANDLER t1 READ a=((SELECT 1)); -ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT 1))' at line 1 +ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use HANDLER t1 CLOSE; drop table t1; create table t1 (a int); @@ -1049,12 +1049,12 @@ UNIQUE KEY `maxnumrep` (`maxnumrep`) ) ENGINE=MyISAM CHARSET=latin1; INSERT INTO t1 VALUES ('joce','1','','joce'),('test','2','','test'); Warnings: -Warning 1265 Data truncated for column 'date' at row 1 -Warning 1265 Data truncated for column 'date' at row 2 +Warning 1264 Data truncated for column 'date' at row 1 +Warning 1264 Data truncated for column 'date' at row 2 INSERT INTO t2 VALUES ('joce','1','','joce'),('test','2','','test'); Warnings: -Warning 1265 Data truncated for column 'date' at row 1 -Warning 1265 Data truncated for column 'date' at row 2 +Warning 1264 Data truncated for column 'date' at row 1 +Warning 1264 Data truncated for column 'date' at row 2 INSERT INTO t3 VALUES (1,1); SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE numeropost=topic); @@ -1168,9 +1168,9 @@ 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 +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select high_priority (0,(select 1 AS `Not_used` from test.t1 a limit 1)) AS `0 IN (SELECT 1 FROM t1 a)` +Note 1003 select high_priority (0,(select 1 AS `Not_used` from test.t1 a where isnull(1) having (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) @@ -1178,9 +1178,9 @@ 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 +2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select high_priority (0,(select 1 AS `Not_used` from test.t1 a limit 1)) AS `0 IN (SELECT 1 FROM t1 a)` +Note 1003 select high_priority (0,(select 1 AS `Not_used` from test.t1 a where isnull(1) having (1) limit 1)) AS `0 IN (SELECT 1 FROM t1 a)` drop table t1; CREATE TABLE `t1` ( `i` int(11) NOT NULL default '0', @@ -1246,7 +1246,7 @@ insert into t1 values (1,0), (2,0), (3,0); insert into t2 values (1,1), (2,1), (3,1), (2,2); update ignore t1 set b=(select b from t2 where t1.a=t2.a); Warnings: -Error 1242 Subquery returns more than 1 row +Error 1241 Subquery returns more than 1 row select * from t1; a b 1 1 @@ -1348,8 +1348,8 @@ 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 t1 ref a a 5 func 1001 Using where; Using index -2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 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 (test.t2.a,(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and ((test.t2.a) = test.t1.a)) limit 1)) insert into t1 values (3,31); @@ -1577,16 +1577,6 @@ INSERT INTO t2 VALUES (100, 200, 'C'); SELECT DISTINCT COLC FROM t1 WHERE COLA = (SELECT COLA FROM t2 WHERE COLB = 200 AND COLC ='C' LIMIT 1); COLC DROP TABLE t1, t2; -CREATE TABLE t1 (a int(1)); -INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(3),(4),(5); -SELECT DISTINCT (SELECT a) FROM t1 LIMIT 100; -(SELECT a) -1 -2 -3 -4 -5 -DROP TABLE t1; create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); select a, (select max(b) from t1) into outfile "subselect.out.file.1" from t1; @@ -1621,97 +1611,3 @@ id max_anno_dep PIPPO 50 1990 0 51 1990 NULL DROP TABLE t1, t2; -create table t1 (a int); -insert into t1 values (1), (2), (3); -SET SQL_SELECT_LIMIT=1; -select sum(a) from (select * from t1) as a; -sum(a) -6 -select 2 in (select * from t1); -2 in (select * from t1) -1 -SET SQL_SELECT_LIMIT=default; -drop table t1; -CREATE TABLE t1 (a int, b int, INDEX (a)); -INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3); -SELECT * FROM t1 WHERE a = (SELECT MAX(a) FROM t1 WHERE a = 1) ORDER BY b; -a b -1 1 -1 2 -1 3 -DROP TABLE t1; -create table t1(val varchar(10)); -insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp'); -select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%'); -count(*) -0 -drop table t1; -create table t1 (id int not null, text varchar(20) not null default '', primary key (id)); -insert into t1 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text11'), (12, 'text12'); -select * from t1 where id not in (select id from t1 where id < 8); -id text -8 text8 -9 text9 -10 text10 -11 text11 -12 text12 -select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); -id text -8 text8 -9 text9 -10 text10 -11 text11 -12 text12 -explain extended select * from t1 where id not in (select id from t1 where id < 8); -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where -2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where -Warnings: -Note 1003 select high_priority test.t1.id AS `id`,test.t1.text AS `text` from test.t1 where not((test.t1.id,(((test.t1.id) in t1 on PRIMARY where (test.t1.id < 8))))) -explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where -2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 7 Using where; Using index -Warnings: -Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1 -Note 1003 select high_priority test.tt.id AS `id`,test.tt.text AS `text` from test.t1 tt where not(exists(select test.t1.id AS `id` from test.t1 where ((test.t1.id < 8) and ((test.t1.id = test.tt.id) or isnull(test.t1.id))) having (test.t1.id is not null) limit 1)) -insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001'); -create table t2 (id int not null, text varchar(20) not null default '', primary key (id)); -insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10'); -select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id); -id text id text id text -1 text1 1 text1 1 text1 -2 text2 2 text2 2 text2 -3 text3 3 text3 3 text3 -4 text4 4 text4 4 text4 -5 text5 5 text5 5 text5 -6 text6 6 text6 6 text6 -7 text7 7 text7 7 text7 -8 text8 8 text8 8 text8 -9 text9 9 text9 9 text9 -10 text10 10 text10 10 text10 -11 text11 11 text1 11 text11 -12 text12 12 text2 12 text12 -1000 text1000 NULL NULL 1000 text1000 -1001 text1001 NULL NULL 1000 text1000 -explain extended select * from t1 a left join t2 b on (a.id=b.id or b.id is null) join t1 c on (if(isnull(b.id), 1000, b.id)=c.id); -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE a ALL NULL NULL NULL NULL 14 -1 SIMPLE b eq_ref PRIMARY PRIMARY 4 test.a.id 2 -1 SIMPLE c eq_ref PRIMARY PRIMARY 4 func 1 Using where -Warnings: -Note 1003 select high_priority test.a.id AS `id`,test.a.text AS `text`,test.b.id AS `id`,test.b.text AS `text`,test.c.id AS `id`,test.c.text AS `text` from test.t1 a left join test.t2 b on(((test.a.id = test.b.id) or isnull(test.b.id))) join test.t1 c where (if(isnull(test.b.id),1000,test.b.id) = test.c.id) -drop table t1,t2; -create table t1 (a int); -insert into t1 values (1); -explain select benchmark(1000, (select a from t1 where a=sha(rand()))); -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 UNCACHEABLE SUBQUERY t1 system NULL NULL NULL NULL 1 -drop table t1; -create table t1(id int); -create table t2(id int); -create table t3(flag int); -select (select * from t3 where id not null) from t1, t2; -ERROR 42000: You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'null) from t1, t2' at line 1 -drop table t1,t2,t3; diff --git a/mysql-test/t/greedy_optimizer.test b/mysql-test/t/greedy_optimizer.test new file mode 100644 index 00000000000..8fd5bbb022a --- /dev/null +++ b/mysql-test/t/greedy_optimizer.test @@ -0,0 +1,313 @@ +# +# A simple test of the greedy query optimization algorithm and the switches that +# control the optimizationprocess. +# + +# +# Schema +# +--disable_warnings +drop table if exists t1,t2,t3,t4,t5,t6,t7; +--enable_warnings + +create table t1 ( + c11 integer,c12 integer,c13 integer,c14 integer,c15 integer,c16 integer, + primary key (c11) +); +create table t2 ( + c21 integer,c22 integer,c23 integer,c24 integer,c25 integer,c26 integer, +); +create table t3 ( + c31 integer,c32 integer,c33 integer,c34 integer,c35 integer,c36 integer, + primary key (c31) +); +create table t4 ( + c41 integer,c42 integer,c43 integer,c44 integer,c45 integer,c46 integer +); +create table t5 ( + c51 integer,c52 integer,c53 integer,c54 integer,c55 integer,c56 integer, + primary key (c51) +); +create table t6 ( + c61 integer,c62 integer,c63 integer,c64 integer,c65 integer,c66 integer +); +create table t7 ( + c71 integer,c72 integer,c73 integer,c74 integer,c75 integer,c76 integer, + primary key (c71) +); + +# +# Data +# cardinality(Ti) = cardinality(T(i-1)) + 3 +# +insert into t1 values (1,2,3,4,5,6); +insert into t1 values (2,2,3,4,5,6); +insert into t1 values (3,2,3,4,5,6); + +insert into t2 values (1,2,3,4,5,6); +insert into t2 values (2,2,3,4,5,6); +insert into t2 values (3,2,3,4,5,6); +insert into t2 values (4,2,3,4,5,6); +insert into t2 values (5,2,3,4,5,6); +insert into t2 values (6,2,3,4,5,6); + +insert into t3 values (1,2,3,4,5,6); +insert into t3 values (2,2,3,4,5,6); +insert into t3 values (3,2,3,4,5,6); +insert into t3 values (4,2,3,4,5,6); +insert into t3 values (5,2,3,4,5,6); +insert into t3 values (6,2,3,4,5,6); +insert into t3 values (7,2,3,4,5,6); +insert into t3 values (8,2,3,4,5,6); +insert into t3 values (9,2,3,4,5,6); + +insert into t4 values (1,2,3,4,5,6); +insert into t4 values (2,2,3,4,5,6); +insert into t4 values (3,2,3,4,5,6); +insert into t4 values (4,2,3,4,5,6); +insert into t4 values (5,2,3,4,5,6); +insert into t4 values (6,2,3,4,5,6); +insert into t4 values (7,2,3,4,5,6); +insert into t4 values (8,2,3,4,5,6); +insert into t4 values (9,2,3,4,5,6); +insert into t4 values (10,2,3,4,5,6); +insert into t4 values (11,2,3,4,5,6); +insert into t4 values (12,2,3,4,5,6); + +insert into t5 values (1,2,3,4,5,6); +insert into t5 values (2,2,3,4,5,6); +insert into t5 values (3,2,3,4,5,6); +insert into t5 values (4,2,3,4,5,6); +insert into t5 values (5,2,3,4,5,6); +insert into t5 values (6,2,3,4,5,6); +insert into t5 values (7,2,3,4,5,6); +insert into t5 values (8,2,3,4,5,6); +insert into t5 values (9,2,3,4,5,6); +insert into t5 values (10,2,3,4,5,6); +insert into t5 values (11,2,3,4,5,6); +insert into t5 values (12,2,3,4,5,6); +insert into t5 values (13,2,3,4,5,6); +insert into t5 values (14,2,3,4,5,6); +insert into t5 values (15,2,3,4,5,6); + +insert into t6 values (1,2,3,4,5,6); +insert into t6 values (2,2,3,4,5,6); +insert into t6 values (3,2,3,4,5,6); +insert into t6 values (4,2,3,4,5,6); +insert into t6 values (5,2,3,4,5,6); +insert into t6 values (6,2,3,4,5,6); +insert into t6 values (7,2,3,4,5,6); +insert into t6 values (8,2,3,4,5,6); +insert into t6 values (9,2,3,4,5,6); +insert into t6 values (10,2,3,4,5,6); +insert into t6 values (11,2,3,4,5,6); +insert into t6 values (12,2,3,4,5,6); +insert into t6 values (13,2,3,4,5,6); +insert into t6 values (14,2,3,4,5,6); +insert into t6 values (15,2,3,4,5,6); +insert into t6 values (16,2,3,4,5,6); +insert into t6 values (17,2,3,4,5,6); +insert into t6 values (18,2,3,4,5,6); + +insert into t7 values (1,2,3,4,5,6); +insert into t7 values (2,2,3,4,5,6); +insert into t7 values (3,2,3,4,5,6); +insert into t7 values (4,2,3,4,5,6); +insert into t7 values (5,2,3,4,5,6); +insert into t7 values (6,2,3,4,5,6); +insert into t7 values (7,2,3,4,5,6); +insert into t7 values (8,2,3,4,5,6); +insert into t7 values (9,2,3,4,5,6); +insert into t7 values (10,2,3,4,5,6); +insert into t7 values (11,2,3,4,5,6); +insert into t7 values (12,2,3,4,5,6); +insert into t7 values (13,2,3,4,5,6); +insert into t7 values (14,2,3,4,5,6); +insert into t7 values (15,2,3,4,5,6); +insert into t7 values (16,2,3,4,5,6); +insert into t7 values (17,2,3,4,5,6); +insert into t7 values (18,2,3,4,5,6); +insert into t7 values (19,2,3,4,5,6); +insert into t7 values (20,2,3,4,5,6); +insert into t7 values (21,2,3,4,5,6); + +# +# The actual test begins here +# + +# Check the default values for the optimizer paramters + +select @@plan_search_depth; +select @@heuristic; + +-- This value swithes back to the old implementation of 'find_best()' +-- set plan_search_depth=63; - old (independent of the heuristic) +-- +-- These are the values for the parameters that control the greedy optimizer +-- (total 6 combinations - 3 for plan_search_depth, 2 for heuristic): +-- +-- set plan_search_depth=0; - automatic +-- set plan_search_depth=1; - min +-- set plan_search_depth=62; - max (default) +-- +-- set heuristic=0 - exhaustive; +-- set heuristic=1 - heuristic; -- default + + +# +# Compile several queries with all combinations of the query +# optimizer parameters. Each test query has two variants, where +# in the second variant the tables in the FROM clause are in +# inverse order to the tables in the first variant. +# Due to pre-sorting of tables before compilation, there should +# be no difference in the plans for each two such query variants. +# + +# First, for reference compile the test queries with the 'old' optimization +# procedure 'find_best'. Notice that 'find_best' does not depend on the +# choice of heuristic. + +set plan_search_depth=63; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + + +# Test the new optimization procedures + +set heuristic=0; +select @@heuristic; + +set plan_search_depth=0; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + +set plan_search_depth=1; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + +set plan_search_depth=62; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + + +set heuristic=1; +select @@heuristic; + +set plan_search_depth=0; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + +set plan_search_depth=1; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + +set plan_search_depth=62; +select @@plan_search_depth; + +-- 6-table join, chain +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c12 = t2.c21 and t2.c22 = t3.c31 and t3.c32 = t4.c41 and t4.c42 = t5.c51 and t5.c52 = t6.c61 and t6.c62 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, star +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71; +show status like 'Last_query_cost'; +-- 6-table join, clique +explain select t1.c11 from t1, t2, t3, t4, t5, t6, t7 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; +explain select t1.c11 from t7, t6, t5, t4, t3, t2, t1 where t1.c11 = t2.c21 and t1.c12 = t3.c31 and t1.c13 = t4.c41 and t1.c14 = t5.c51 and t1.c15 = t6.c61 and t1.c16 = t7.c71 and t2.c22 = t3.c32 and t2.c23 = t4.c42 and t2.c24 = t5.c52 and t2.c25 = t6.c62 and t2.c26 = t7.c72 and t3.c33 = t4.c43 and t3.c34 = t5.c53 and t3.c35 = t6.c63 and t3.c36 = t7.c73 and t4.c42 = t5.c54 and t4.c43 = t6.c64 and t4.c44 = t7.c74 and t5.c52 = t6.c65 and t5.c53 = t7.c75 and t6.c62 = t7.c76; +show status like 'Last_query_cost'; + +drop table t1,t2,t3,t4,t5,t6,t7; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 697b5146b7d..efa5d798e91 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -73,6 +73,14 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) #define all_bits_set(A,B) ((A) & (B) != (B)) +#ifndef LL +#ifdef HAVE_LONG_LONG +#define LL(A) A ## LL +#else +#define LL(A) A ## L +#endif +#endif + extern CHARSET_INFO *system_charset_info, *files_charset_info ; extern CHARSET_INFO *national_charset_info, *table_alias_charset; @@ -156,9 +164,6 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; /* Time handling defaults */ #define TIMESTAMP_MAX_YEAR 2038 #define YY_PART_YEAR 70 -#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) -#define TIMESTAMP_MAX_VALUE 2145916799 -#define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 @@ -200,8 +205,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */ #define TEST_NO_STACKTRACE 512 #define TEST_SIGINT 1024 /* Allow sigint on threads */ -#define TEST_SYNCHRONIZATION 2048 /* get server to do sleep in some - places */ + #endif /* @@ -251,6 +255,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; /* The rest of the file is included in the server only */ #ifndef MYSQL_CLIENT +/* options for UNION set by the yacc parser (stored in unit->union_option) */ +#define UNION_ALL 1 + /* Bits for different SQL modes modes (including ANSI mode) */ #define MODE_REAL_AS_FLOAT 1 #define MODE_PIPES_AS_CONCAT 2 @@ -326,7 +333,6 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); struct st_table; class THD; -class Statement; /* Struct to handle simple linked lists */ @@ -381,11 +387,6 @@ inline THD *_current_thd(void) #include "sql_udf.h" #include "item.h" typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); -/* sql_parse.cc */ -void free_items(Item *item); -void cleanup_items(Item *item); -class THD; -void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); #include "sql_class.h" #include "opt_range.h" @@ -446,8 +447,8 @@ int quick_rm_table(enum db_type base,const char *db, bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list); bool mysql_change_db(THD *thd,const char *name); void mysql_parse(THD *thd,char *inBuf,uint length); -bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); bool is_update_query(enum enum_sql_command command); +void free_items(Item *item); bool alloc_query(THD *thd, char *packet, ulong packet_length); void mysql_init_select(LEX *lex); void mysql_init_query(THD *thd, bool lexonly=0); @@ -466,8 +467,13 @@ bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, char* packet, uint packet_length); bool check_dup(const char *db, const char *name, TABLE_LIST *tables); +#ifndef EMBEDDED_LIBRARY +bool check_stack_overrun(THD *thd,char *dummy); +#else +#define check_stack_overrun(A, B) 0 +#endif -bool table_cache_init(void); +void table_cache_init(void); void table_cache_free(void); uint cached_tables(void); void kill_mysql(void); @@ -571,6 +577,7 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list, int mysql_insert(THD *thd,TABLE_LIST *table,List &fields, List &values, List &update_fields, List &update_values, enum_duplicates flag); +void kill_delayed_threads(void); int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order, ha_rows rows, ulong options); int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok=0); @@ -594,8 +601,7 @@ extern const Field *not_found_field; Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables, TABLE_LIST **where, bool report_error); Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, - bool check_grant,bool allow_rowid, - uint *cached_field_index_ptr); + bool check_grant,bool allow_rowid); #ifdef HAVE_OPENSSL #include struct st_des_keyblock @@ -647,13 +653,14 @@ int mysqld_show_column_types(THD *thd); int mysqld_help (THD *thd, const char *text); /* sql_prepare.cc */ -void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); -void mysql_stmt_execute(THD *thd, char *packet, uint packet_length); +bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length); +void mysql_stmt_execute(THD *thd, char *packet); void mysql_stmt_free(THD *thd, char *packet); void mysql_stmt_reset(THD *thd, char *packet); void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); int check_insert_fields(THD *thd,TABLE *table,List &fields, List &values, ulong counter); +void setup_param_functions(Item_param *param, uchar param_type); /* sql_error.cc */ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, @@ -675,7 +682,7 @@ void set_item_name(Item *item,char *pos,uint length); bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type, char *length, char *decimal, uint type_modifier, - Item *default_value, Item *on_update_value, + Item *default_value, LEX_STRING *comment, char *change, TYPELIB *interval,CHARSET_INFO *cs, uint uint_geom_type); @@ -698,7 +705,7 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table, bool insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, const char *table_name, List_iterator *it); -bool setup_tables(TABLE_LIST *tables); +bool setup_tables(TABLE_LIST *tables, my_bool reinit); int setup_wild(THD *thd, TABLE_LIST *tables, List &fields, List *sum_func_list, uint wild_num); int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, @@ -718,6 +725,7 @@ bool rm_temporary_table(enum db_type base, char *path); void free_io_cache(TABLE *entry); void intern_close_table(TABLE *entry); bool close_thread_table(THD *thd, TABLE **table_ptr); +void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0); void close_temporary_tables(THD *thd); TABLE_LIST * find_table_in_list(TABLE_LIST *table, const char *db_name, const char *table_name); @@ -761,6 +769,8 @@ extern "C" pthread_handler_decl(handle_manager, arg); void print_where(COND *cond,const char *info); void print_cached_tables(void); void TEST_filesort(SORT_FIELD *sortorder,uint s_length); +void print_plan(JOIN* join, double read_time, double record_count, + uint idx, const char *info); #endif void mysql_print_status(THD *thd); /* key.cc */ @@ -786,9 +796,6 @@ bool open_log(MYSQL_LOG *log, const char *hostname, /* mysqld.cc */ extern void yyerror(const char*); -/* item_func.cc */ -extern bool check_reserved_words(LEX_STRING *name); - /* strfunc.cc */ ulonglong find_set(TYPELIB *typelib,const char *x, uint length, char **err_pos, uint *err_len, bool *set_warning); @@ -798,6 +805,9 @@ uint check_word(TYPELIB *lib, const char *val, const char *end, bool is_keyword(const char *name, uint len); +/* sql_parse.cc */ +void free_items(Item *item); +void cleanup_items(Item *item); #define MY_DB_OPT_FILE "db.opt" bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); @@ -808,8 +818,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); extern time_t start_time; extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], - mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], - opt_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; + mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[]; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; extern const char *command_name[]; @@ -829,11 +838,10 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN]; extern double log_10[32]; -extern ulonglong log_10_int[20]; +extern double last_query_cost; extern ulonglong keybuff_size; extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables; -extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent; -extern ulong binlog_cache_use, binlog_cache_disk_use; +extern ulong created_tmp_tables, created_tmp_disk_tables; extern ulong aborted_threads,aborted_connects; extern ulong delayed_insert_timeout; extern ulong delayed_insert_limit, delayed_queue_size; @@ -854,7 +862,7 @@ extern ulong ha_read_rnd_count, ha_read_rnd_next_count; extern ulong ha_commit_count, ha_rollback_count,table_cache_size; extern ulong max_connections,max_connect_errors, connect_timeout; extern ulong slave_net_timeout; -extern ulong max_user_connections; +extern ulong max_insert_delayed_threads, max_user_connections; extern ulong long_query_count, what_to_log,flush_time; extern ulong query_buff_size, thread_stack,thread_stack_min; extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; @@ -866,7 +874,7 @@ extern ulong expire_logs_days; extern my_bool relay_log_purge; extern uint test_flags,select_errors,ha_open_options; extern uint protocol_version, mysqld_port, dropping_tables; -extern uint delay_key_write_options, lower_case_table_names; +extern uint delay_key_write_options; extern bool opt_endinfo, using_udf_functions, locked_in_memory; extern bool opt_using_transactions, mysql_embedded; extern bool using_update_log, opt_large_files; @@ -875,10 +883,10 @@ extern bool opt_disable_networking, opt_skip_show_db; extern bool volatile abort_loop, shutdown_in_progress, grant_option; extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; -extern my_bool opt_safe_show_db, opt_local_infile; +extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names; extern my_bool opt_slave_compressed_protocol, use_temp_pool; -extern my_bool opt_readonly, lower_case_file_system; -extern my_bool opt_enable_named_pipe, opt_sync_frm; +extern my_bool opt_readonly; +extern my_bool opt_enable_named_pipe; extern my_bool opt_secure_auth; extern char *shared_memory_base_name, *mysqld_unix_port; extern bool opt_enable_shared_memory; @@ -888,7 +896,7 @@ extern FILE *bootstrap_file; extern pthread_key(MEM_ROOT*,THR_MALLOC); extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status, - LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator, + LOCK_error_log, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_system_variables, LOCK_user_conn; @@ -990,8 +998,6 @@ timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time, void localtime_to_TIME(TIME *to, struct tm *from); void calc_time_from_sec(TIME *to, long seconds, long microseconds); -void make_truncated_value_warning(THD *thd, const char *str_val, - uint str_length, timestamp_type time_type); extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, const char *format_str, uint format_length); @@ -1007,6 +1013,11 @@ void make_datetime(DATE_TIME_FORMAT *format, TIME *l_time, String *str); int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); +#ifndef EMBEDDED_LIBRARY +extern "C" void unireg_abort(int exit_code); +#else +#define unireg_abort(exit_code) DBUG_RETURN(exit_code) +#endif void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, SQL_SELECT *select, int use_record_cache, bool print_errors); @@ -1108,19 +1119,6 @@ inline void table_case_convert(char * name, uint length) my_casedn(files_charset_info, name, length); } -inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) -{ - return ((lower_case_table_names == 2 && info->alias) ? info->alias : name); -} - -inline ulong sql_rnd_with_mutex() -{ - pthread_mutex_lock(&LOCK_thread_count); - ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */ - pthread_mutex_unlock(&LOCK_thread_count); - return tmp; -} - Comp_creator *comp_eq_creator(bool invert); Comp_creator *comp_ge_creator(bool invert); Comp_creator *comp_gt_creator(bool invert); @@ -1156,20 +1154,13 @@ inline void setup_table_map(TABLE *table, TABLE_LIST *table_list, uint tablenr) table->force_index= table_list->force_index; } +typedef struct st_sym_group { + const char *name; + const char *needed_define; +} SYM_GROUP; -/* - Some functions that are different in the embedded library and the normal - server -*/ - -#ifndef EMBEDDED_LIBRARY -extern "C" void unireg_abort(int exit_code); -void kill_delayed_threads(void); -bool check_stack_overrun(THD *thd,char *dummy); -#else -#define unireg_abort(exit_code) DBUG_RETURN(exit_code) -inline void kill_delayed_threads(void) {} -#define check_stack_overrun(A, B) 0 -#endif +extern SYM_GROUP sym_group_common; +extern SYM_GROUP sym_group_geom; +extern SYM_GROUP sym_group_rtree; #endif /* MYSQL_CLIENT */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d242a54f141..43d6528a425 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -152,7 +152,7 @@ int initgroups(const char *,unsigned int); typedef fp_except fp_except_t; #endif - /* We can't handle floating point exceptions with threads, so disable + /* We can't handle floating point expections with threads, so disable this on freebsd */ @@ -186,11 +186,15 @@ inline void reset_floating_point_exceptions() #else #include // For thr_setconcurency() #endif +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(HAVE_mit_thread) +#define SET_RLIMIT_NOFILE +#endif #ifdef SOLARIS extern "C" int gethostname(char *name, int namelen); #endif + /* Set prefix for windows binary */ #ifdef __WIN__ #undef MYSQL_SERVER_SUFFIX @@ -250,7 +254,6 @@ arg_cmp_func Arg_comparator::comparator_matrix[4][2] = bool opt_log, opt_update_log, opt_bin_log, opt_slow_log; bool opt_error_log= IF_WIN(1,0); bool opt_disable_networking=0, opt_skip_show_db=0; -bool lower_case_table_names_used= 0; bool server_id_supplied = 0; bool opt_endinfo,using_udf_functions, locked_in_memory; bool opt_using_transactions, using_update_log; @@ -262,20 +265,18 @@ my_bool opt_reckless_slave = 0; my_bool opt_enable_named_pipe= 0, opt_debugging= 0; my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; +my_bool lower_case_table_names, opt_old_rpl_compat; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam; my_bool opt_readonly, use_temp_pool, relay_log_purge; -my_bool opt_sync_bdb_logs, opt_sync_frm; my_bool opt_secure_auth= 0; my_bool opt_short_log_format= 0; my_bool opt_log_queries_not_using_indexes= 0; -my_bool lower_case_file_system= 0; volatile bool mqh_used = 0; uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint delay_key_write_options, protocol_version; -uint lower_case_table_names; uint volatile thread_count, thread_running, kill_cached_threads, wake_thread; ulong back_log, connect_timeout, concurrency; @@ -300,8 +301,7 @@ ulong select_range_check_count, select_range_count, select_scan_count; ulong select_full_range_join_count,select_full_join_count; ulong specialflag=0,opened_tables=0,created_tmp_tables=0, created_tmp_disk_tables=0; -ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; -ulong max_connections,max_used_connections, +ulong max_connections,max_insert_delayed_threads,max_used_connections, max_connect_errors, max_user_connections = 0; ulong thread_id=1L,current_pid; ulong slow_launch_threads = 0; @@ -311,14 +311,7 @@ ulong my_bind_addr; /* the address we bind to */ volatile ulong cached_thread_count= 0; double log_10[32]; /* 10 potences */ -ulonglong log_10_int[20]= -{ - 1, 10, 100, 1000, 10000UL, 100000UL, 1000000UL, 10000000UL, - ULL(100000000), ULL(1000000000), ULL(10000000000), ULL(100000000000), - ULL(1000000000000), ULL(10000000000000), ULL(100000000000000), - ULL(1000000000000000), ULL(10000000000000000), ULL(100000000000000000), - ULL(1000000000000000000), ULL(10000000000000000000) -}; +double last_query_cost= -1; /* -1 denotes that no query was compiled yet */ time_t start_time; @@ -328,8 +321,7 @@ char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], max_sort_char,*mysqld_user,*mysqld_chroot, *opt_init_file, - *opt_init_connect, *opt_init_slave, - opt_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; + *opt_init_connect, *opt_init_slave; const char *opt_date_time_formats[3]; @@ -383,7 +375,7 @@ pthread_key(MEM_ROOT*,THR_MALLOC); pthread_key(THD*, THR_THD); pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count, LOCK_mapped_file, LOCK_status, - LOCK_error_log, LOCK_uuid_generator, + LOCK_error_log, LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received, LOCK_global_system_variables, @@ -443,7 +435,7 @@ static NTService Service; // Service object for WinNT #endif /* __WIN__ */ #ifdef __NT__ -static char pipe_name[512]; +static char szPipeName [ 257 ]; static SECURITY_ATTRIBUTES saPipeSecurity; static SECURITY_DESCRIPTOR sdPipeDescriptor; static HANDLE hPipe = INVALID_HANDLE_VALUE; @@ -503,6 +495,9 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg); static pthread_handler_decl(handle_connections_shared_memory,arg); #endif extern "C" pthread_handler_decl(handle_slave,arg); +#ifdef SET_RLIMIT_NOFILE +static uint set_maximum_open_files(uint max_file_limit); +#endif static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static void clean_up(bool print_message); static void clean_up_mutexes(void); @@ -586,7 +581,7 @@ static void close_connections(void) DBUG_PRINT( "quit", ("Closing named pipes") ); /* Create connection to the handle named pipe handler to break the loop */ - if ((temp = CreateFile(pipe_name, + if ((temp = CreateFile(szPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, @@ -594,7 +589,7 @@ static void close_connections(void) 0, NULL )) != INVALID_HANDLE_VALUE) { - WaitNamedPipe(pipe_name, 1000); + WaitNamedPipe(szPipeName, 1000); DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT; SetNamedPipeHandleState(temp, &dwMode, NULL, NULL); CancelIo(temp); @@ -927,7 +922,6 @@ void clean_up(bool print_message) #ifdef USE_RAID end_raid(); #endif - my_free_open_file_info(); my_free((char*) global_system_variables.date_format, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) global_system_variables.time_format, @@ -1063,8 +1057,8 @@ static void set_user(const char *user) { /* Don't give a warning, if real user is same as given with --user */ struct passwd *user_info= getpwnam(user); - if ((!user_info || user_id != user_info->pw_uid) && - global_system_variables.log_warnings) + + if (!user_info || user_id != user_info->pw_uid) fprintf(stderr, "Warning: One can only use the --user switch if running as root\n"); } @@ -1198,14 +1192,11 @@ static void server_init(void) if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) { - - pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */ - strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\", - mysqld_unix_port, NullS); - bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity)); - bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor)); - if (!InitializeSecurityDescriptor(&sdPipeDescriptor, - SECURITY_DESCRIPTOR_REVISION)) + sprintf(szPipeName, "\\\\.\\pipe\\%s", mysqld_unix_port ); + ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) ); + ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) ); + if ( !InitializeSecurityDescriptor(&sdPipeDescriptor, + SECURITY_DESCRIPTOR_REVISION) ) { sql_perror("Can't start server : Initialize security descriptor"); unireg_abort(1); @@ -1218,16 +1209,16 @@ static void server_init(void) saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES ); saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor; saPipeSecurity.bInheritHandle = FALSE; - if ((hPipe= CreateNamedPipe(pipe_name, - PIPE_ACCESS_DUPLEX, - PIPE_TYPE_BYTE | - PIPE_READMODE_BYTE | - PIPE_WAIT, - PIPE_UNLIMITED_INSTANCES, - (int) global_system_variables.net_buffer_length, - (int) global_system_variables.net_buffer_length, - NMPWAIT_USE_DEFAULT_WAIT, - &saPipeSecurity)) == INVALID_HANDLE_VALUE) + if ((hPipe = CreateNamedPipe(szPipeName, + PIPE_ACCESS_DUPLEX, + PIPE_TYPE_BYTE | + PIPE_READMODE_BYTE | + PIPE_WAIT, + PIPE_UNLIMITED_INSTANCES, + (int) global_system_variables.net_buffer_length, + (int) global_system_variables.net_buffer_length, + NMPWAIT_USE_DEFAULT_WAIT, + &saPipeSecurity )) == INVALID_HANDLE_VALUE) { LPVOID lpMsgBuf; int error=GetLastError(); @@ -1725,7 +1716,7 @@ static void start_signal_handler(void) (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); if (!(opt_specialflag & SPECIAL_NO_PRIOR)) my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR); - pthread_attr_setstacksize(&thr_attr,thread_stack); + pthread_attr_setstacksize(&thr_attr, 129*1024); #endif (void) pthread_mutex_lock(&LOCK_thread_count); @@ -1759,8 +1750,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused))) This should actually be '+ max_number_of_slaves' instead of +10, but the +10 should be quite safe. */ - init_thr_alarm(max_connections + - global_system_variables.max_insert_delayed_threads + 10); + init_thr_alarm(max_connections+max_insert_delayed_threads+10); #if SIGINT != THR_KILL_SIGNAL if (test_flags & TEST_SIGINT) { @@ -2111,11 +2101,10 @@ static int init_common_variables(const char *conf_file_name, int argc, strmov(fn_ext(pidfile_name),".pid"); // Add proper extension #ifndef DBUG_OFF - if (!*(MYSQL_SERVER_SUFFIX)) - strmov(strend(server_version),"-debug"); - else + strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS); +#else + strmov(strend(server_version),MYSQL_SERVER_SUFFIX); #endif - strmov(strend(server_version),MYSQL_SERVER_SUFFIX); load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; @@ -2125,33 +2114,28 @@ static int init_common_variables(const char *conf_file_name, int argc, DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, server_version, SYSTEM_TYPE,MACHINE_TYPE)); +#if defined( SET_RLIMIT_NOFILE) || defined( OS2) /* connections and databases needs lots of files */ { - uint files, wanted_files; - - wanted_files= 10+(uint) max(max_connections*5, - max_connections+table_cache_size*2); + uint wanted_files=10+(uint) max(max_connections*5, + max_connections+table_cache_size*2); set_if_bigger(wanted_files, open_files_limit); - files= my_set_max_open_files(wanted_files); - - if (files < wanted_files) + // Note that some system returns 0 if we succeed here: + uint files=set_maximum_open_files(wanted_files); + if (files && files < wanted_files && ! open_files_limit) { - if (!open_files_limit) - { - max_connections= (ulong) min((files-10),max_connections); - table_cache_size= (ulong) max((files-10-max_connections)/2,64); - DBUG_PRINT("warning", - ("Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", - files, max_connections, table_cache_size)); - if (global_system_variables.log_warnings) - sql_print_error("Warning: Changed limits: max_open_files: %u max_connections: %ld table_cache: %ld", - files, max_connections, table_cache_size); - } - else if (global_system_variables.log_warnings) - sql_print_error("Warning: Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files); + max_connections= (ulong) min((files-10),max_connections); + table_cache_size= (ulong) max((files-10-max_connections)/2,64); + DBUG_PRINT("warning", + ("Changed limits: max_connections: %ld table_cache: %ld", + max_connections,table_cache_size)); + sql_print_error("Warning: Changed limits: max_connections: %ld table_cache: %ld",max_connections,table_cache_size); } open_files_limit= files; } +#else + open_files_limit= 0; /* Can't set or detect limit */ +#endif unireg_init(opt_specialflag); /* Set up extern variabels */ if (init_errmessage()) /* Read error messages from file */ return 1; @@ -2196,14 +2180,10 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_init_connect.value_length= 0; if ((sys_init_connect.value= opt_init_connect)) sys_init_connect.value_length= strlen(opt_init_connect); - else - sys_init_connect.value=my_strdup("",MYF(0)); sys_init_slave.value_length= 0; if ((sys_init_slave.value= opt_init_slave)) sys_init_slave.value_length= strlen(opt_init_slave); - else - sys_init_slave.value=my_strdup("",MYF(0)); if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) return 1; @@ -2230,7 +2210,6 @@ static int init_thread_environment() (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); (void) my_rwlock_init(&LOCK_sys_init_connect, NULL); (void) my_rwlock_init(&LOCK_sys_init_slave, NULL); (void) my_rwlock_init(&LOCK_grant, NULL); @@ -2284,9 +2263,8 @@ static void init_ssl() static int init_server_components() { DBUG_ENTER("init_server_components"); - if (table_cache_init() || hostname_cache_init()) - unireg_abort(1); - + table_cache_init(); + hostname_cache_init(); query_cache_result_size_limit(query_cache_limit); query_cache_set_min_res_unit(query_cache_min_res_unit); query_cache_resize(query_cache_size); @@ -2413,10 +2391,10 @@ Now disabling --log-slave-updates."); { if (mlockall(MCL_CURRENT)) { - if (global_system_variables.log_warnings) - sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno); - locked_in_memory= 0; + sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno); } + else + locked_in_memory=1; } #else locked_in_memory=0; @@ -2434,7 +2412,7 @@ static void create_maintenance_thread() { if ( #ifdef HAVE_BERKELEY_DB - (have_berkeley_db == SHOW_OPTION_YES) || + !berkeley_skip || #endif (flush_time && flush_time != ~(ulong) 0L)) { @@ -2580,38 +2558,8 @@ int main(int argc, char **argv) } } #endif - thread_stack_min=thread_stack - STACK_MIN_SIZE; - (void) thr_setconcurrency(concurrency); // 10 by default - /* - Ensure that lower_case_table_names is set on system where we have case - insensitive names. If this is not done the users MyISAM tables will - get corrupted if accesses with names of different case. - */ - DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names)); - if (!lower_case_table_names && - (lower_case_file_system= - (test_if_case_insensitive(mysql_real_data_home) == 1))) - { - if (lower_case_table_names_used) - { - if (global_system_variables.log_warnings) - sql_print_error("\ -Warning: You have forced lower_case_table_names to 0 through a command-line \ -option, even though your file system '%s' is case insensitive. This means \ -that you can corrupt a MyISAM table by accessing it with different cases. \ -You should consider changing lower_case_table_names to 1 or 2", - mysql_real_data_home); - } - else - { - if (global_system_variables.log_warnings) - sql_print_error("Warning: Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home); - lower_case_table_names= 2; - } - } - select_thread=pthread_self(); select_thread_in_use=1; init_ssl(); @@ -3041,6 +2989,8 @@ static void create_new_thread(THD *thd) DBUG_VOID_RETURN; } pthread_mutex_lock(&LOCK_thread_count); + if (thread_count-delayed_insert_threads > max_used_connections) + max_used_connections=thread_count-delayed_insert_threads; thd->thread_id=thread_id++; thd->real_id=pthread_self(); // Keep purify happy @@ -3069,8 +3019,6 @@ static void create_new_thread(THD *thd) thread_count++; thread_created++; threads.append(thd); - if (thread_count-delayed_insert_threads > max_used_connections) - max_used_connections=thread_count-delayed_insert_threads; DBUG_PRINT("info",(("creating thread %d"), thd->thread_id)); thd->connect_time = time(NULL); if ((error=pthread_create(&thd->real_id,&connection_attrib, @@ -3363,7 +3311,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) if (!fConnected) { CloseHandle( hPipe ); - if ((hPipe = CreateNamedPipe(pipe_name, + if ((hPipe = CreateNamedPipe(szPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | @@ -3381,7 +3329,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg) } hConnectedPipe = hPipe; /* create new pipe for new connection */ - if ((hPipe = CreateNamedPipe(pipe_name, + if ((hPipe = CreateNamedPipe(szPipeName, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | @@ -3646,7 +3594,7 @@ enum options_mysqld OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG, OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR, OPT_BDB_HOME, OPT_BDB_LOG, - OPT_BDB_TMP, OPT_BDB_SYNC, + OPT_BDB_TMP, OPT_BDB_NOSYNC, OPT_BDB_LOCK, OPT_BDB, OPT_BDB_NO_RECOVER, OPT_BDB_SHARED, OPT_MASTER_HOST, OPT_MASTER_USER, @@ -3686,7 +3634,7 @@ enum options_mysqld OPT_HAVE_NAMED_PIPE, OPT_DO_PSTACK, OPT_REPORT_HOST, OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT, - OPT_SHOW_SLAVE_AUTH_INFO, + OPT_SHOW_SLAVE_AUTH_INFO, OPT_OLD_RPL_COMPAT, OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE, OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE, OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE, @@ -3696,7 +3644,7 @@ enum options_mysqld OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE, OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT, OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE, - OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN, OPT_FT_BOOLEAN_SYNTAX, + OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN, OPT_FT_MAX_WORD_LEN, OPT_FT_QUERY_EXPANSION_LIMIT, OPT_FT_STOPWORD_FILE, OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE, OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE, @@ -3718,7 +3666,7 @@ enum options_mysqld OPT_OPEN_FILES_LIMIT, OPT_PRELOAD_BUFFER_SIZE, OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE, - OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER, + OPT_QUERY_CACHE_TYPE, OPT_RECORD_BUFFER, OPT_RECORD_RND_BUFFER, OPT_RELAY_LOG_SPACE_LIMIT, OPT_RELAY_LOG_PURGE, OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME, OPT_READONLY, OPT_DEBUGGING, @@ -3747,7 +3695,6 @@ enum options_mysqld OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, - OPT_SYNC_FRM, OPT_BDB_NOSYNC, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, @@ -3760,7 +3707,9 @@ enum options_mysqld OPT_DATE_FORMAT, OPT_TIME_FORMAT, OPT_DATETIME_FORMAT, - OPT_LOG_QUERIES_NOT_USING_INDEXES + OPT_LOG_QUERIES_NOT_USING_INDEXES, + OPT_PLAN_SEARCH_DEPTH, + OPT_HEURISTIC }; @@ -3786,14 +3735,8 @@ struct my_option my_long_options[] = {"bdb-no-recover", OPT_BDB_NO_RECOVER, "Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"bdb-no-sync", OPT_BDB_NOSYNC, - "Disable synchronously flushing logs. This option is deprecated, use --skip-sync-bdb-logs or sync-bdb-logs=0 instead", - // (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL, - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"sync-bdb-logs", OPT_BDB_SYNC, - "Synchronously flush logs. Enabled by default", - (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL, - NO_ARG, 1, 0, 0, 0, 0, 0}, + {"bdb-no-sync", OPT_BDB_NOSYNC, "Don't synchronously flush logs.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"bdb-shared-data", OPT_BDB_SHARED, "Start Berkeley DB in multi-process mode.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -3801,9 +3744,6 @@ struct my_option my_long_options[] = (gptr*) &berkeley_tmpdir, (gptr*) &berkeley_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_BERKELEY_DB */ - {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default", - (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, - 0, 0, 0, 0}, {"bdb", OPT_BDB, "Enable Berkeley DB (if this version of MySQL supports it). \ Disable with --skip-bdb (will save memory).", (gptr*) &opt_bdb, (gptr*) &opt_bdb, 0, GET_BOOL, NO_ARG, 1, 0, 0, @@ -4020,8 +3960,7 @@ log and this option justs turns on --log-bin instead.", 0, 0, 0, 0}, {"master-password", OPT_MASTER_PASSWORD, "The password the slave thread will authenticate with when connecting to the master. If not set, an empty password is assumed.The value in master.info will take precedence if it can be read.", - (gptr*)&master_password, (gptr*)&master_password, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-port", OPT_MASTER_PORT, "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.", (gptr*) &master_port, (gptr*) &master_port, 0, GET_UINT, REQUIRED_ARG, @@ -4106,6 +4045,10 @@ master-ssl", (gptr*) &global_system_variables.old_passwords, (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"old-rpl-compat", OPT_OLD_RPL_COMPAT, + "Use old LOAD DATA format in the binary log (don't save data in file).", + (gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL, + NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef ONE_THREAD {"one-thread", OPT_ONE_THREAD, "Only use one thread (for debugging under Linux).", 0, 0, 0, GET_NO_ARG, @@ -4274,7 +4217,7 @@ log and this option does nothing anymore.", 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files. Several paths may be specified, separated by a " -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(OS2) "semicolon (;)" #else "colon (:)" @@ -4300,11 +4243,11 @@ log and this option does nothing anymore.", NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-warnings", 'W', "Log some not critical warnings to the log file.", (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0, + (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"warnings", 'W', "Deprecated ; Use --log-warnings instead.", (gptr*) &global_system_variables.log_warnings, - (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 1, 0, 0, + (gptr*) &max_system_variables.log_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { "back_log", OPT_BACK_LOG, "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", @@ -4352,10 +4295,6 @@ log and this option does nothing anymore.", "A dedicated thread is created to flush all tables at the given interval.", (gptr*) &flush_time, (gptr*) &flush_time, 0, GET_ULONG, REQUIRED_ARG, FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0}, - { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX, - "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE)", - 0, 0, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, "The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_ULONG, @@ -4372,6 +4311,11 @@ log and this option does nothing anymore.", "Use stopwords from this file instead of built-in list.", (gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"heuristic", OPT_HEURISTIC, + "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on rows and read time.", + (gptr*) &global_system_variables.heuristic, + (gptr*) &max_system_variables.heuristic, + 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0}, #ifdef HAVE_INNOBASE_DB {"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS, "Number of identical copies of log groups we keep for the database. Currently this should be set to 1.", @@ -4466,15 +4410,15 @@ log and this option does nothing anymore.", (gptr*) &max_system_variables.long_query_time, 0, GET_ULONG, REQUIRED_ARG, 10, 1, LONG_TIMEOUT, 0, 1, 0}, {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES, - "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive. Should be set to 2 if you are using a case insensitive file system", + "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive.", (gptr*) &lower_case_table_names, - (gptr*) &lower_case_table_names, 0, GET_UINT, OPT_ARG, + (gptr*) &lower_case_table_names, 0, GET_BOOL, NO_ARG, #ifdef FN_NO_CASE_SENCE 1 #else 0 #endif - , 0, 2, 0, 1, 0}, + , 0, 1, 0, 1, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "Max packetlength to send/receive from to server.", (gptr*) &global_system_variables.max_allowed_packet, @@ -4500,8 +4444,7 @@ The minimum value for this variable is 4096.", REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ~0L, 0, 1, 0}, {"max_delayed_threads", OPT_MAX_DELAYED_THREADS, "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.", - (gptr*) &global_system_variables.max_insert_delayed_threads, - (gptr*) &max_system_variables.max_insert_delayed_threads, + (gptr*) &max_insert_delayed_threads, (gptr*) &max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, {"max_error_count", OPT_MAX_ERROR_COUNT, "Max number of errors/warnings to store for a statement.", @@ -4606,7 +4549,12 @@ The minimum value for this variable is 4096.", {"open_files_limit", OPT_OPEN_FILES_LIMIT, "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0}, + REQUIRED_ARG, 0, 0, 65535, 0, 1, 0}, + {"plan_search_depth", OPT_PLAN_SEARCH_DEPTH, + "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).", + (gptr*) &global_system_variables.plan_search_depth, + (gptr*) &max_system_variables.plan_search_depth, + 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes", (gptr*) &global_system_variables.preload_buff_size, @@ -4638,17 +4586,12 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.query_cache_type, (gptr*) &max_system_variables.query_cache_type, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, - {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE, - "Invalidate queries in query cache on LOCK for write", - (gptr*) &global_system_variables.query_cache_wlock_invalidate, - (gptr*) &max_system_variables.query_cache_wlock_invalidate, - 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, -#endif /*HAVE_QUERY_CACHE*/ {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE, "Persistent buffer for query parsing and execution", (gptr*) &global_system_variables.query_prealloc_size, (gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0}, +#endif /*HAVE_QUERY_CACHE*/ {"read_buffer_size", OPT_RECORD_BUFFER, "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", (gptr*) &global_system_variables.read_buff_size, @@ -4692,7 +4635,7 @@ The minimum value for this variable is 4096.", (gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0}, {"read-only", OPT_READONLY, - "Make all tables readonly, with the exception for replication (slave) threads and users with the SUPER privilege", + "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege.", (gptr*) &opt_readonly, (gptr*) &opt_readonly, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, @@ -4708,8 +4651,8 @@ The minimum value for this variable is 4096.", 1, 0}, {"table_cache", OPT_TABLE_CACHE, "The number of open tables for all threads.", (gptr*) &table_cache_size, - (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L, - 0, 1, 0}, + (gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, ~0L, 0, 1, + 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_ULONG, REQUIRED_ARG, @@ -4741,8 +4684,7 @@ The minimum value for this variable is 4096.", "The number of seconds the server waits for activity on a connection before closing it.", (gptr*) &global_system_variables.net_wait_timeout, (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, - REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), - 0, 1, 0}, + REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, "Binary logs will be rotated after expire-log-days days ", (gptr*) &expire_logs_days, @@ -4775,8 +4717,6 @@ The minimum value for this variable is 4096.", struct show_var_st status_vars[]= { {"Aborted_clients", (char*) &aborted_threads, SHOW_LONG}, {"Aborted_connects", (char*) &aborted_connects, SHOW_LONG}, - {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG}, - {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG}, {"Bytes_received", (char*) &bytes_received, SHOW_LONG}, {"Bytes_sent", (char*) &bytes_sent, SHOW_LONG}, {"Com_admin_commands", (char*) &com_other, SHOW_LONG}, @@ -4831,13 +4771,13 @@ struct show_var_st status_vars[]= { {"Com_savepoint", (char*) (com_stat+(uint) SQLCOM_SAVEPOINT),SHOW_LONG}, {"Com_select", (char*) (com_stat+(uint) SQLCOM_SELECT),SHOW_LONG}, {"Com_set_option", (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG}, - {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG}, {"Com_show_binlogs", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG}, + {"Com_show_binlog_events", (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOG_EVENTS),SHOW_LONG}, {"Com_show_charsets", (char*) (com_stat+(uint) SQLCOM_SHOW_CHARSETS),SHOW_LONG}, {"Com_show_collations", (char*) (com_stat+(uint) SQLCOM_SHOW_COLLATIONS),SHOW_LONG}, {"Com_show_column_types", (char*) (com_stat+(uint) SQLCOM_SHOW_COLUMN_TYPES),SHOW_LONG}, - {"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG}, {"Com_show_create_table", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG}, + {"Com_show_create_db", (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE_DB),SHOW_LONG}, {"Com_show_databases", (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG}, {"Com_show_errors", (char*) (com_stat+(uint) SQLCOM_SHOW_ERRORS),SHOW_LONG}, {"Com_show_fields", (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG}, @@ -4865,11 +4805,11 @@ struct show_var_st status_vars[]= { {"Com_update_multi", (char*) (com_stat+(uint) SQLCOM_UPDATE_MULTI),SHOW_LONG}, {"Connections", (char*) &thread_id, SHOW_LONG_CONST}, {"Created_tmp_disk_tables", (char*) &created_tmp_disk_tables,SHOW_LONG}, - {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, {"Created_tmp_tables", (char*) &created_tmp_tables, SHOW_LONG}, - {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, + {"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG}, {"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_CONST}, {"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG}, + {"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG}, {"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST}, {"Handler_commit", (char*) &ha_commit_count, SHOW_LONG}, {"Handler_delete", (char*) &ha_delete_count, SHOW_LONG}, @@ -4896,24 +4836,24 @@ struct show_var_st status_vars[]= { SHOW_KEY_CACHE_LONG}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST}, + {"Open_tables", (char*) 0, SHOW_OPENTABLES}, {"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST}, {"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST}, - {"Open_tables", (char*) 0, SHOW_OPENTABLES}, {"Opened_tables", (char*) &opened_tables, SHOW_LONG}, + {"Questions", (char*) 0, SHOW_QUESTION}, #ifdef HAVE_QUERY_CACHE - {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, - SHOW_LONG_CONST}, - {"Qcache_free_memory", (char*) &query_cache.free_memory, - SHOW_LONG_CONST}, - {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG}, + {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST}, {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG}, + {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG}, {"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG}, {"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG}, - {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST}, + {"Qcache_free_memory", (char*) &query_cache.free_memory, + SHOW_LONG_CONST}, + {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, + SHOW_LONG_CONST}, {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST}, #endif /*HAVE_QUERY_CACHE*/ - {"Questions", (char*) 0, SHOW_QUESTION}, {"Rpl_status", (char*) 0, SHOW_RPL_STATUS}, {"Select_full_join", (char*) &select_full_join_count, SHOW_LONG}, {"Select_full_range_join", (char*) &select_full_range_join_count, SHOW_LONG}, @@ -4929,37 +4869,38 @@ struct show_var_st status_vars[]= { {"Sort_rows", (char*) &filesort_rows, SHOW_LONG}, {"Sort_scan", (char*) &filesort_scan_count, SHOW_LONG}, #ifdef HAVE_OPENSSL - {"Ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE}, {"Ssl_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT}, - {"Ssl_callback_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS}, - {"Ssl_cipher", (char*) 0, SHOW_SSL_GET_CIPHER}, - {"Ssl_cipher_list", (char*) 0, SHOW_SSL_GET_CIPHER_LIST}, - {"Ssl_client_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT}, - {"Ssl_connect_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE}, - {"Ssl_ctx_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH}, - {"Ssl_ctx_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE}, - {"Ssl_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT}, {"Ssl_finished_accepts", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_GOOD}, {"Ssl_finished_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_GOOD}, + {"Ssl_accept_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE}, + {"Ssl_connect_renegotiates", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE}, + {"Ssl_callback_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_CB_HITS}, {"Ssl_session_cache_hits", (char*) 0, SHOW_SSL_CTX_SESS_HITS}, {"Ssl_session_cache_misses", (char*) 0, SHOW_SSL_CTX_SESS_MISSES}, - {"Ssl_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE}, + {"Ssl_session_cache_timeouts", (char*) 0, SHOW_SSL_CTX_SESS_TIMEOUTS}, + {"Ssl_used_session_cache_entries",(char*) 0, SHOW_SSL_CTX_SESS_NUMBER}, + {"Ssl_client_connects", (char*) 0, SHOW_SSL_CTX_SESS_CONNECT}, {"Ssl_session_cache_overflows", (char*) 0, SHOW_SSL_CTX_SESS_CACHE_FULL}, {"Ssl_session_cache_size", (char*) 0, SHOW_SSL_CTX_SESS_GET_CACHE_SIZE}, - {"Ssl_session_cache_timeouts", (char*) 0, SHOW_SSL_CTX_SESS_TIMEOUTS}, + {"Ssl_session_cache_mode", (char*) 0, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE}, {"Ssl_sessions_reused", (char*) 0, SHOW_SSL_SESSION_REUSED}, - {"Ssl_used_session_cache_entries",(char*) 0, SHOW_SSL_CTX_SESS_NUMBER}, - {"Ssl_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH}, + {"Ssl_ctx_verify_mode", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_MODE}, + {"Ssl_ctx_verify_depth", (char*) 0, SHOW_SSL_CTX_GET_VERIFY_DEPTH}, {"Ssl_verify_mode", (char*) 0, SHOW_SSL_GET_VERIFY_MODE}, + {"Ssl_verify_depth", (char*) 0, SHOW_SSL_GET_VERIFY_DEPTH}, {"Ssl_version", (char*) 0, SHOW_SSL_GET_VERSION}, + {"Ssl_cipher", (char*) 0, SHOW_SSL_GET_CIPHER}, + {"Ssl_cipher_list", (char*) 0, SHOW_SSL_GET_CIPHER_LIST}, + {"Ssl_default_timeout", (char*) 0, SHOW_SSL_GET_DEFAULT_TIMEOUT}, #endif /* HAVE_OPENSSL */ {"Table_locks_immediate", (char*) &locks_immediate, SHOW_LONG}, {"Table_locks_waited", (char*) &locks_waited, SHOW_LONG}, {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_CONST}, - {"Threads_connected", (char*) &thread_count, SHOW_INT_CONST}, {"Threads_created", (char*) &thread_created, SHOW_LONG_CONST}, + {"Threads_connected", (char*) &thread_count, SHOW_INT_CONST}, {"Threads_running", (char*) &thread_running, SHOW_INT_CONST}, {"Uptime", (char*) 0, SHOW_STARTTIME}, + {"Last_query_cost", (char*) &last_query_cost, SHOW_DOUBLE}, {NullS, NullS, SHOW_LONG} }; @@ -5071,7 +5012,6 @@ static void mysql_init_variables(void) filesort_merge_passes= select_range_check_count= select_range_count= 0; select_scan_count= select_full_range_join_count= select_full_join_count= 0; specialflag= opened_tables= created_tmp_tables= created_tmp_disk_tables= 0; - binlog_cache_use= binlog_cache_disk_use= 0; max_used_connections= slow_launch_threads = 0; max_sort_char= 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; @@ -5543,8 +5483,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), break; case OPT_STORAGE_ENGINE: { - if ((enum db_type)((global_system_variables.table_type= - ha_resolve_by_name(argument, strlen(argument)))) == DB_TYPE_UNKNOWN) + if ((enum db_type)((global_system_variables.table_type= + ha_resolve_by_name(argument, strlen(argument)))) == DB_TYPE_UNKNOWN) { fprintf(stderr,"Unknown table type: %s\n",argument); exit(1); @@ -5591,14 +5531,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } #ifdef HAVE_BERKELEY_DB case OPT_BDB_NOSYNC: - /* Deprecated option */ - opt_sync_bdb_logs= 0; - /* Fall through */ - case OPT_BDB_SYNC: - if (!opt_sync_bdb_logs) - berkeley_env_flags|= DB_TXN_NOSYNC; - else - berkeley_env_flags&= ~DB_TXN_NOSYNC; + berkeley_env_flags|=DB_TXN_NOSYNC; break; case OPT_BDB_NO_RECOVER: berkeley_init_flags&= ~(DB_RECOVER); @@ -5632,25 +5565,43 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_BDB: #ifdef HAVE_BERKELEY_DB if (opt_bdb) + { + berkeley_skip=0; have_berkeley_db=SHOW_OPTION_YES; + } else + { + berkeley_skip=1; have_berkeley_db=SHOW_OPTION_DISABLED; + } #endif break; case OPT_ISAM: #ifdef HAVE_ISAM if (opt_isam) + { + isam_skip=0; have_isam= SHOW_OPTION_YES; + } else + { + isam_skip=1; have_isam= SHOW_OPTION_DISABLED; + } #endif break; case OPT_INNODB: #ifdef HAVE_INNOBASE_DB if (opt_innodb) + { + innodb_skip=0; have_innodb=SHOW_OPTION_YES; + } else + { + innodb_skip=1; have_innodb=SHOW_OPTION_DISABLED; + } #endif break; case OPT_INNODB_DATA_FILE_PATH: @@ -5697,25 +5648,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } global_system_variables.sql_mode= fix_sql_mode(global_system_variables. sql_mode); - break; } - case OPT_FT_BOOLEAN_SYNTAX: - if (ft_boolean_check_syntax_string((byte*) argument)) - { - fprintf(stderr, "Invalid ft-boolean-syntax string: %s\n", argument); - exit(1); - } - strmake(opt_ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1); + case OPT_MASTER_PASSWORD: + master_password=argument; break; case OPT_SKIP_SAFEMALLOC: #ifdef SAFEMALLOC sf_malloc_quick=1; #endif break; - case OPT_LOWER_CASE_TABLE_NAMES: - lower_case_table_names= argument ? atoi(argument) : 1; - lower_case_table_names_used= 1; - break; } return 0; } @@ -5755,8 +5696,6 @@ static void get_options(int argc,char **argv) int ho_error; my_getopt_register_get_addr(mysql_getopt_value); - strmake(opt_ft_boolean_syntax, ft_boolean_syntax, - sizeof(ft_boolean_syntax)-1); if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option))) exit(ho_error); if (argc > 0) @@ -5812,9 +5751,6 @@ static void get_options(int argc,char **argv) table_alias_charset= (lower_case_table_names ? files_charset_info : &my_charset_bin); - strmake(ft_boolean_syntax, opt_ft_boolean_syntax, - sizeof(ft_boolean_syntax)-1); - if (opt_short_log_format) opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT; if (opt_log_queries_not_using_indexes) @@ -5911,9 +5847,110 @@ static void fix_paths(void) exit(1); } #endif /* HAVE_REPLICATION */ + + /* + Ensure that lower_case_table_names is set on system where we have case + insensitive names. If this is not done the users MyISAM tables will + get corrupted if accesses with names of different case. + */ + if (!lower_case_table_names && + test_if_case_insensitive(mysql_real_data_home) == 1) + { + sql_print_error("Warning: Setting lower_case_table_names=1 becasue file system %s is case insensitive", mysql_real_data_home); + lower_case_table_names= 1; + } } +/* + set how many open files we want to be able to handle + + SYNOPSIS + set_maximum_open_files() + max_file_limit Files to open + + NOTES + The request may not fulfilled becasue of system limitations + + RETURN + Files available to open +*/ + +#ifdef SET_RLIMIT_NOFILE + +#ifndef RLIM_INFINITY +#define RLIM_INFINITY ((uint) 0xffffffff) +#endif + +static uint set_maximum_open_files(uint max_file_limit) +{ + struct rlimit rlimit; + uint old_cur; + DBUG_ENTER("set_maximum_open_files"); + DBUG_PRINT("enter",("files: %u", max_file_limit)); + + if (!getrlimit(RLIMIT_NOFILE,&rlimit)) + { + old_cur= (uint) rlimit.rlim_cur; + DBUG_PRINT("info", ("rlim_cur: %u rlim_max: %u", + (uint) rlimit.rlim_cur, + (uint) rlimit.rlim_max)); + if (rlimit.rlim_cur >= max_file_limit || + rlimit.rlim_cur == RLIM_INFINITY) + DBUG_RETURN(rlimit.rlim_cur); /* purecov: inspected */ + rlimit.rlim_cur= rlimit.rlim_max= max_file_limit; + if (setrlimit(RLIMIT_NOFILE,&rlimit)) + { + if (global_system_variables.log_warnings) + sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %u (request: %u)", + old_cur, max_file_limit); /* purecov: inspected */ + max_file_limit= old_cur; + } + else + { + rlimit.rlim_cur= 0; // Safety if next call fails + (void) getrlimit(RLIMIT_NOFILE,&rlimit); + DBUG_PRINT("info", ("rlim_cur: %u", (uint) rlimit.rlim_cur)); + if ((uint) rlimit.rlim_cur < max_file_limit && + global_system_variables.log_warnings) + sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %u (request: %u)", + (uint) rlimit.rlim_cur, + max_file_limit); /* purecov: inspected */ + max_file_limit= (uint) rlimit.rlim_cur; + } + } + DBUG_PRINT("exit",("max_file_limit: %u", max_file_limit)); + DBUG_RETURN(max_file_limit); +} +#endif + + +#ifdef OS2 +static uint set_maximum_open_files(uint max_file_limit) +{ + LONG cbReqCount; + ULONG cbCurMaxFH, cbCurMaxFH0; + APIRET ulrc; + DBUG_ENTER("set_maximum_open_files"); + + // get current limit + cbReqCount = 0; + DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0); + + // set new limit + cbReqCount = max_file_limit - cbCurMaxFH0; + ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH); + if (ulrc) { + sql_print_error("Warning: DosSetRelMaxFH couldn't increase number of open files to more than %d", + cbCurMaxFH0); + cbCurMaxFH = cbCurMaxFH0; + } + + DBUG_RETURN(cbCurMaxFH); +} +#endif + + /* Return a bitfield from a string of substrings separated by ',' returns ~(ulong) 0 on error. @@ -5994,7 +6031,6 @@ static int test_if_case_insensitive(const char *dir_name) File file; char buff[FN_REFLEN], buff2[FN_REFLEN]; MY_STAT stat_info; - DBUG_ENTER("test_if_case_insensitive"); fn_format(buff, glob_hostname, dir_name, ".lower-test", MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); @@ -6004,14 +6040,13 @@ static int test_if_case_insensitive(const char *dir_name) if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0) { sql_print_error("Warning: Can't create test file %s", buff); - DBUG_RETURN(-1); + return -1; } my_close(file, MYF(0)); if (my_stat(buff2, &stat_info, MYF(0))) result= 1; // Can access file (void) my_delete(buff, MYF(MY_WME)); - DBUG_PRINT("exit", ("result: %d", result)); - DBUG_RETURN(result); + return result; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6004778781d..b170e3bf54d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -48,7 +48,25 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b); static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key); static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, table_map used_tables); -static void find_best_combination(JOIN *join,table_map rest_tables); +static void choose_plan(JOIN *join,table_map join_tables); + +static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd, + table_map remaining_tables, uint idx, + double record_count, double read_time); +static void optimize_straight_join(JOIN *join, table_map join_tables); +static void greedy_search(JOIN *join, table_map remaining_tables, + uint depth, uint heuristic); +static void best_extension_by_limited_search(JOIN *join, + table_map remaining_tables, + uint idx, double record_count, + double read_time, uint depth, + uint heuristic); +static uint determine_search_depth(JOIN* join); +static int join_tab_cmp(const void* ptr1, const void* ptr2); +/* + TODO: 'find_best' is here only temporarily until 'greedy_search' is + tested and approved. +*/ static void find_best(JOIN *join,table_map rest_tables,uint index, double record_count,double read_time); static uint cache_record_length(JOIN *join,uint index); @@ -71,10 +89,8 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, uint select_options, const char *info, Item *having, Procedure *proc, SELECT_LEX_UNIT *unit); -static COND *optimize_cond(THD *thd, COND *conds, - Item::cond_result *cond_value); -static COND *remove_eq_conds(THD *thd, COND *cond, - Item::cond_result *cond_value); +static COND *optimize_cond(COND *conds,Item::cond_result *cond_value); +static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, @@ -294,10 +310,6 @@ JOIN::prepare(Item ***rref_pointer_array, { DBUG_ENTER("JOIN::prepare"); - // to prevent double initialization on EXPLAIN - if (optimized) - DBUG_RETURN(0); - conds= conds_init; order= order_init; group_list= group_init; @@ -310,7 +322,7 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ - if (setup_tables(tables_list) || + if (setup_tables(tables_list, 0) || setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, @@ -327,9 +339,8 @@ JOIN::prepare(Item ***rref_pointer_array, thd->where="having clause"; thd->allow_sum_func=1; select_lex->having_fix_field= 1; - bool having_fix_rc= (!having->fixed && - (having->fix_fields(thd, tables_list, &having) || - having->check_cols(1))); + bool having_fix_rc= (having->fix_fields(thd, tables_list, &having) || + having->check_cols(1)); select_lex->having_fix_field= 0; if (having_fix_rc || thd->net.report_error) DBUG_RETURN(-1); /* purecov: inspected */ @@ -340,7 +351,8 @@ JOIN::prepare(Item ***rref_pointer_array, // Is it subselect { Item_subselect *subselect; - if ((subselect= select_lex->master_unit()->item)) + if ((subselect= select_lex->master_unit()->item) && + select_lex->linkage != GLOBAL_OPTIONS_TYPE) { Item_subselect::trans_res res; if ((res= subselect->select_transformer(this)) != @@ -531,7 +543,7 @@ JOIN::optimize() } #endif - conds= optimize_cond(thd, conds, &cond_value); + conds= optimize_cond(conds,&cond_value); if (thd->net.report_error) { error= 1; @@ -597,10 +609,7 @@ JOIN::optimize() DBUG_RETURN(1); // error == -1 } if (const_table_map != found_const_table_map && - !(select_options & SELECT_DESCRIBE) && - (!conds || - !(conds->used_tables() & RAND_TABLE_BIT) || - select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT + !(select_options & SELECT_DESCRIBE)) { zero_result_cause= "no matching row in const table"; DBUG_PRINT("error",("Error: %s", zero_result_cause)); @@ -858,7 +867,8 @@ JOIN::optimize() for (uint i_h = const_tables; i_h < tables; i_h++) { TABLE* table_h = join_tab[i_h].table; - table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY); + if (table_h->db_type == DB_TYPE_INNODB) + table_h->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); } } #endif @@ -1023,7 +1033,7 @@ JOIN::reinit() /* TODO move to unit reinit */ unit->set_limit(select_lex, select_lex); - if (setup_tables(tables_list)) + if (setup_tables(tables_list, 1)) DBUG_RETURN(1); /* Reset of sum functions */ @@ -1090,7 +1100,7 @@ JOIN::exec() if (!tables_list) { // Only test of functions if (select_options & SELECT_DESCRIBE) - select_describe(this, FALSE, FALSE, FALSE, + select_describe(this, false, false, false, (zero_result_cause?zero_result_cause:"No tables used")); else { @@ -1429,17 +1439,9 @@ JOIN::exec() if (!curr_table->select->cond) curr_table->select->cond= sort_table_cond; else // This should never happen - { if (!(curr_table->select->cond= - new Item_cond_and(curr_table->select->cond, - sort_table_cond))) + new Item_cond_and(curr_table->select->cond, sort_table_cond))) DBUG_VOID_RETURN; - /* - Item_cond_and do not need fix_fields for execution, its parameters - are fixed or do not need fix_fields, too - */ - curr_table->select->cond->quick_fix_field(); - } curr_table->select_cond= curr_table->select->cond; curr_table->select_cond->top_level_item(); DBUG_EXECUTE("where",print_where(curr_table->select->cond, @@ -1536,10 +1538,10 @@ JOIN::cleanup() lock=0; // It's faster to unlock later join_free(1); - if (exec_tmp_table1) - free_tmp_table(thd, exec_tmp_table1); - if (exec_tmp_table2) - free_tmp_table(thd, exec_tmp_table2); + if (exec_tmp_table1) + free_tmp_table(thd, exec_tmp_table1); + if (exec_tmp_table2) + free_tmp_table(thd, exec_tmp_table2); delete select; delete_dynamic(&keyuse); delete procedure; @@ -1992,7 +1994,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, if (join->const_tables != join->tables) { optimize_keyuse(join, keyuse_array); - find_best_combination(join,all_table_map & ~join->const_table_map); + choose_plan(join,all_table_map & ~join->const_table_map); } else { @@ -2161,8 +2163,8 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond, bool optimizable=0; for (uint i=0; iused_tables(); - if (!((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT))) + used_tables|=(*value)->used_tables(); + if (!((*value)->used_tables() & (field->table->map | RAND_TABLE_BIT))) optimizable=1; } if (!optimizable) @@ -2569,7 +2571,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, } /* - Update some values in keyuse for faster find_best_combination() loop + Update some values in keyuse for faster choose_plan() loop */ static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array) @@ -2637,16 +2639,942 @@ set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key) } +/* + Find the best access path for an extension of a partial execution plan and + add this path to the plan. + + SYNOPSIS + best_access_path() + join pointer to the structure providing all context info + for the query + s the table to be joined by the function + thd thread for the connection that submitted the query + remaining_tables set of tables not included into the partial plan yet + idx the length of the partial plan + record_count estimate for the number of records returned by the partial + plan + read_time the cost of the partial plan + + DESCRIPTION + The function finds the best access path to table 's' from the passed + partial plan where an access path is the general term for any means to + access the data in 's'. An access path may use either an index or a scan, + whichever is cheaper. The input partial plan is passed via the array + 'join->positions' of length 'idx'. The chosen access method for 's' and its + cost are stored in 'join->positions[idx]'. + + RETURN + None +*/ + static void -find_best_combination(JOIN *join, table_map rest_tables) +best_access_path(JOIN *join, + JOIN_TAB *s, + THD *thd, + table_map remaining_tables, + uint idx, + double record_count, + double read_time) { - DBUG_ENTER("find_best_combination"); - join->best_read=DBL_MAX; - find_best(join,rest_tables, join->const_tables,1.0,0.0); + KEYUSE *best_key= 0; + uint best_max_key_part= 0; + my_bool found_constraint= 0; + double best= DBL_MAX; + double best_time= DBL_MAX; + double records= DBL_MAX; + double tmp; + ha_rows rec; + + DBUG_ENTER("best_access_path"); + + if (s->keyuse) + { /* Use key if possible */ + TABLE *table= s->table; + KEYUSE *keyuse,*start_key=0; + double best_records= DBL_MAX; + uint max_key_part=0; + + /* Test how we can use keys */ + rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; // Assumed records/key + for (keyuse=s->keyuse ; keyuse->table == table ;) + { + key_part_map found_part= 0; + table_map found_ref= 0; + uint found_ref_or_null= 0; + uint key= keyuse->key; + KEY *keyinfo= table->key_info+key; + bool ft_key= (keyuse->keypart == FT_KEYPART); + + /* Calculate how many key segments of the current key we can use */ + start_key= keyuse; + do + { /* for each keypart */ + uint keypart= keyuse->keypart; + uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL; + do + { + if (!(remaining_tables & keyuse->used_tables) && + !(found_ref_or_null & keyuse->optimize)) + { + found_part|= keyuse->keypart_map; + found_ref|= keyuse->used_tables; + if (rec > keyuse->ref_table_rows) + rec= keyuse->ref_table_rows; + found_part_ref_or_null&= keyuse->optimize; + } + keyuse++; + found_ref_or_null|= found_part_ref_or_null; + } while (keyuse->table == table && keyuse->key == key && + keyuse->keypart == keypart); + } while (keyuse->table == table && keyuse->key == key); + + /* + Assume that that each key matches a proportional part of table. + */ + if (!found_part && !ft_key) + continue; // Nothing usable found + + if (rec < MATCHING_ROWS_IN_OTHER_TABLE) + rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables + + /* + ft-keys require special treatment + */ + if (ft_key) + { + /* + Really, there should be records=0.0 (yes!) + but 1.0 would be probably safer + */ + tmp= prev_record_reads(join, found_ref); + records= 1.0; + } + else + { + found_constraint= 1; + /* + Check if we found full key + */ + if (found_part == PREV_BITS(uint,keyinfo->key_parts) && + !found_ref_or_null) + { /* use eq key */ + max_key_part= (uint) ~0; + if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) + { + tmp = prev_record_reads(join, found_ref); + records=1.0; + } + else + { + if (!found_ref) + { /* We found a const key */ + if (table->quick_keys.is_set(key)) + records= (double) table->quick_rows[key]; + else + { + /* quick_range couldn't use key! */ + records= (double) s->records/rec; + } + } + else + { + if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1])) + { /* Prefer longer keys */ + records= + ((double) s->records / (double) rec * + (1.0 + + ((double) (table->max_key_length-keyinfo->key_length) / + (double) table->max_key_length))); + if (records < 2.0) + records=2.0; /* Can't be as good as a unique */ + } + } + /* Limit the number of matched rows */ + tmp = records; + set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key); + if (table->used_keys.is_set(key)) + { + /* we can use only index tree */ + uint keys_per_block= table->file->block_size/2/ + (keyinfo->key_length+table->file->ref_length)+1; + tmp = record_count*(tmp+keys_per_block-1)/keys_per_block; + } + else + tmp = record_count*min(tmp,s->worst_seeks); + } + } + else + { + /* + Use as much key-parts as possible and a uniq key is better + than a not unique key + Set tmp to (previous record count) * (records / combination) + */ + if ((found_part & 1) && + (!(table->file->index_flags(key) & HA_ONLY_WHOLE_INDEX) || + found_part == PREV_BITS(uint,keyinfo->key_parts))) + { + max_key_part=max_part_bit(found_part); + /* + Check if quick_range could determinate how many rows we + will match + */ + if (table->quick_keys.is_set(key) && + table->quick_key_parts[key] <= max_key_part) + tmp = records = (double) table->quick_rows[key]; + else + { + /* Check if we have statistic about the distribution */ + if ((records = keyinfo->rec_per_key[max_key_part-1])) + tmp = records; + else + { + /* + Assume that the first key part matches 1% of the file + and that the hole key matches 10 (duplicates) or 1 + (unique) records. + Assume also that more key matches proportionally more + records + This gives the formula: + records = (x * (b-a) + a*c-b)/(c-1) + + b = records matched by whole key + a = records matched by first key part (10% of all records?) + c = number of key parts in key + x = used key parts (1 <= x <= c) + */ + double rec_per_key; + if (!(rec_per_key=(double) + keyinfo->rec_per_key[keyinfo->key_parts-1])) + rec_per_key=(double) s->records/rec+1; + + if (!s->records) + tmp = 0; + else if (rec_per_key/(double) s->records >= 0.01) + tmp = rec_per_key; + else + { + double a=s->records*0.01; + tmp = (max_key_part * (rec_per_key - a) + + a*keyinfo->key_parts - rec_per_key)/ + (keyinfo->key_parts-1); + set_if_bigger(tmp,1.0); + } + records = (ulong) tmp; + } + if (found_ref_or_null) + { + /* We need to do two key searches to find key */ + tmp *= 2.0; + records *= 2.0; + } + } + /* Limit the number of matched rows */ + set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key); + if (table->used_keys.is_set(key)) + { + /* we can use only index tree */ + uint keys_per_block= table->file->block_size/2/ + (keyinfo->key_length+table->file->ref_length)+1; + tmp = record_count*(tmp+keys_per_block-1)/keys_per_block; + } + else + tmp = record_count*min(tmp,s->worst_seeks); + } + else + tmp = best_time; // Do nothing + } + } /* not ft_key */ + if (tmp < best_time - records/(double) TIME_FOR_COMPARE) + { + best_time= tmp + records/(double) TIME_FOR_COMPARE; + best= tmp; + best_records= records; + best_key= start_key; + best_max_key_part= max_key_part; + } + } + records= best_records; + } + + /* + Don't test table scan if it can't be better. + Prefer key lookup if we would use the same key for scanning. + + Don't do a table scan on InnoDB tables, if we can read the used + parts of the row from any of the used index. + This is because table scans uses index and we would not win + anything by using a table scan. + */ + if ((records >= s->found_records || best > s->read_time) && + !(s->quick && best_key && s->quick->index == best_key->key && + best_max_key_part >= s->table->quick_key_parts[best_key->key]) && + !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) && + ! s->table->used_keys.is_clear_all() && best_key) && + !(s->table->force_index && best_key)) + { // Check full join + ha_rows rnd_records= s->found_records; + /* + If there is a restriction on the table, assume that 25% of the + rows can be skipped on next part. + This is to force tables that this table depends on before this + table + */ + if (found_constraint) + rnd_records-= rnd_records/4; + + /* + Range optimizer never proposes a RANGE if it isn't better + than FULL: so if RANGE is present, it's always preferred to FULL. + Here we estimate its cost. + */ + if (s->quick) + { + /* + For each record we: + - read record range through 'quick' + - skip rows which does not satisfy WHERE constraints + */ + tmp= record_count * + (s->quick->read_time + + (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE); + } + else + { + /* Estimate cost of reading table. */ + tmp= s->table->file->scan_time(); + if (s->on_expr) // Can't use join cache + { + /* + For each record we have to: + - read the whole table record + - skip rows which does not satisfy join condition + */ + tmp= record_count * + (tmp + + (s->records - rnd_records)/(double) TIME_FOR_COMPARE); + } + else + { + /* We read the table as many times as join buffer becomes full. */ + tmp*= (1.0 + floor((double) cache_record_length(join,idx) * + record_count / + (double) thd->variables.join_buff_size)); + /* + We don't make full cartesian product between rows in the scanned + table and existing records because we skip all rows from the + scanned table, which does not satisfy join condition when + we read the table (see flush_cached_records for details). Here we + take into account cost to read and skip these records. + */ + tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE; + } + } + + /* + We estimate the cost of evaluating WHERE clause for found records + as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus + tmp give us total cost of using TABLE SCAN + */ + if (best == DBL_MAX || + (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records < + best + record_count/(double) TIME_FOR_COMPARE*records)) + { + /* + If the table has a range (s->quick is set) make_join_select() + will ensure that this will be used + */ + best= tmp; + records= rows2double(rnd_records); + best_key= 0; + } + } + + /* Update the cost information for the current partial plan */ + join->positions[idx].records_read= records; + join->positions[idx].read_time= best; + join->positions[idx].key= best_key; + join->positions[idx].table= s; + + if (!best_key && + idx == join->const_tables && + s->table == join->sort_by_table && + join->unit->select_limit_cnt >= records) + join->sort_by_table= (TABLE*) 1; // Must use temporary table + DBUG_VOID_RETURN; } +/* + Selects and invokes a search strategy for an optimal query plan. + + SYNOPSIS + choose_plan() + join pointer to the structure providing all context info for + the query + join_tables set of the tables in the query + + DESCRIPTION + The function checks user-configurable parameters that control the search + strategy for an optimal plan, selects the search method and then invokes + it. Each specific optimization procedure stores the final optimal plan in + the array 'join->best_positions', and the cost of the plan in + 'join->best_read'. + + RETURN + None +*/ + +static void +choose_plan(JOIN *join, table_map join_tables) +{ + uint search_depth= join->thd->variables.plan_search_depth; + uint heuristic= join->thd->variables.heuristic; + + DBUG_ENTER("choose_plan"); + + if (join->select_options & SELECT_STRAIGHT_JOIN) + { + optimize_straight_join(join, join_tables); + } + else + { + /* + Heuristic: pre-sort all access plans with respect to the number of + records accessed. + */ + qsort(join->best_ref + join->const_tables, join->tables - join->const_tables, + sizeof(JOIN_TAB*), join_tab_cmp); + + if (search_depth == MAX_TABLES+2) + { /* + TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before + the greedy version. Will be removed when greedy_search is approved. + */ + join->best_read= DBL_MAX; + find_best(join, join_tables, join->const_tables, 1.0, 0.0); + } + else + { + if (search_depth == 0) + /* Automatically determine a reasonable value for 'search_depth' */ + search_depth= determine_search_depth(join); + greedy_search(join, join_tables, search_depth, heuristic); + } + } + + /* Store the cost of this query into a user variable */ + last_query_cost= join->best_read; + + DBUG_VOID_RETURN; +} + + +/* + Compare two JOIN_TAB objects based on the number of accessed records. + + SYNOPSIS + join_tab_cmp() + ptr1 pointer to first JOIN_TAB object + ptr2 pointer to second JOIN_TAB object + + RETURN + 1 if first is bigger + -1 if second is bigger + 0 if equal +*/ + +static int +join_tab_cmp(const void* ptr1, const void* ptr2) +{ + JOIN_TAB *jt1= *(JOIN_TAB**) ptr1; + JOIN_TAB *jt2= *(JOIN_TAB**) ptr2; + if (jt1->found_records > jt2->found_records) + return 1; + else if (jt1->found_records < jt2->found_records) + return -1; + else + return 0; +} + + +/* + Heuristic procedure to automatically guess a reasonable degree of + exhaustiveness for the greedy search procedure. + + SYNOPSIS + determine_search_depth() + join pointer to the structure providing all context info for the query + + DESCRIPTION + The procedure estimates the optimization time and selects a search depth + big enough to result in a near-optimal QEP, that doesn't take too long to + find. If the number of tables in the query exceeds some constant, then + search_depth is set to this constant. + + NOTES + This is an extremely simplistic implementation that serves as a stub for a + more advanced analysis of the join. Ideally the search depth should be + determined by learning from previous query optimizations, because it will + depend on the CPU power (and other factors). + + RETURN + A positive integer that specifies the search depth (and thus the + exhaustiveness) of the depth-first search algorithm used by + 'greedy_search'. +*/ + +static uint +determine_search_depth(JOIN *join) +{ + uint table_count= join->tables - join->const_tables; + uint search_depth; + /* TODO: this value should be determined dynamically, based on statistics: */ + uint max_tables_for_exhaustive_opt= 7; + + if (table_count <= max_tables_for_exhaustive_opt) + search_depth= table_count+1; // use exhaustive for small number of tables + else + /* + TODO: this value could be determined by some mapping of the form: + depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE] + */ + search_depth= max_tables_for_exhaustive_opt; // use greedy search + + return search_depth; +} + + +/* + Select the best ways to access the tables in a query without reordering them. + + SYNOPSIS + optimize_straight_join() + join pointer to the structure providing all context info for + the query + join_tables set of the tables in the query + + DESCRIPTION + Find the best access paths for each query table and compute their costs + according to their order in the array 'join->best_ref' (thus without + reordering the join tables). The function calls sequentially + 'best_access_path' for each table in the query to select the best table + access method. The final optimal plan is stored in the array + 'join->best_positions', and the corresponding cost in 'join->best_read'. + + NOTES + This function can be applied to: + - queries with STRAIGHT_JOIN + - internally to compute the cost of an arbitrary QEP + Thus 'optimize_straight_join' can be used at any stage of the query + optimization process to finalize a QEP as it is. + + RETURN + None +*/ + +static void +optimize_straight_join(JOIN *join, table_map join_tables) +{ + JOIN_TAB *s; + uint idx= join->const_tables; + double record_count= 1.0; + double read_time= 0.0; + + for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) + { + /* Find the best access method from 's' to the current partial plan */ + best_access_path(join, s, join->thd, join_tables, idx, record_count, read_time); + /* compute the cost of the new plan extended with 's' */ + record_count*= join->positions[idx].records_read; + read_time+= join->positions[idx].read_time; + join_tables&= ~(s->table->map); + ++idx; + } + + read_time+= record_count / (double) TIME_FOR_COMPARE; + if (join->sort_by_table && + join->sort_by_table != join->positions[join->const_tables].table->table) + read_time+= record_count; // We have to make a temp table + memcpy((gptr) join->best_positions, (gptr) join->positions, + sizeof(POSITION)*idx); + join->best_read= read_time; +} + + +/* + Find a good, possibly optimal, query execution plan (QEP) by a greedy search. + + SYNOPSIS + join pointer to the structure providing all context info + for the query + remaining_tables set of tables not included into the partial plan yet + search_depth controlls the exhaustiveness of the search + heuristic the pruning heuristics that should be applied during + search + + DESCRIPTION + The search procedure uses a hybrid greedy/exhaustive search with controlled + exhaustiveness. The search is performed in N = card(remaining_tables) + steps. Each step evaluates how promising is each of the unoptimized tables, + selects the most promising table, and extends the current partial QEP with + that table. Currenly the most 'promising' table is the one with least + expensive extension. + There are two extreme cases: + 1. When (card(remaining_tables) < search_depth), the estimate finds the best + complete continuation of the partial QEP. This continuation can be + used directly as a result of the search. + 2. When (search_depth == 1) the 'best_extension_by_limited_search' + consideres the extension of the current QEP with each of the remaining + unoptimized tables. + All other cases are in-between these two extremes. Thus the parameter + 'search_depth' controlls the exhaustiveness of the search. The higher the + value, the longer the optimizaton time and possibly the better the + resulting plan. The lower the value, the fewer alternative plans are + estimated, but the more likely to get a bad QEP. + + All intermediate and final results of the procedure are stored in 'join': + join->positions modified for every partial QEP that is explored + join->best_positions modified for the current best complete QEP + join->best_read modified for the current best complete QEP + join->best_ref might be partially reordered + The final optimal plan is stored in 'join->best_positions', and its + corresponding cost in 'join->best_read'. + + NOTES + The following pseudocode describes the algorithm of 'greedy_search': + + procedure greedy_search + input: remaining_tables + output: pplan; + { + pplan = <>; + do { + (t, a) = best_extension(pplan, remaining_tables); + pplan = concat(pplan, (t, a)); + remaining_tables = remaining_tables - t; + } while (remaining_tables != {}) + return pplan; + } + + where 'best_extension' is a placeholder for a procedure that selects the + most "promising" of all tables in 'remaining_tables'. + Currently this estimate is performed by calling + 'best_extension_by_limited_search' to evaluate all extensions of the + current QEP of size 'search_depth', thus the complexity of 'greedy_search' + mainly depends on that of 'best_extension_by_limited_search'. + + If 'best_extension()' == 'best_extension_by_limited_search()', then the + worst-case complexity of this algorithm is <= + O(N*N^search_depth/search_depth). When serch_depth >= N, then the + complexity of greedy_search is O(N!). + + In the future, 'greedy_search' might be extended to support other + implementations of 'best_extension', e.g. some simpler quadratic procedure. + + RETURN + None +*/ + +static void +greedy_search(JOIN *join, + table_map remaining_tables, + uint search_depth, + uint heuristic) +{ + double record_count= 1.0; + double read_time= 0.0; + uint idx= join->const_tables; // index into 'join->best_ref' + uint best_idx; + uint rem_size; // cardinality of remaining_tables + POSITION best_pos; + JOIN_TAB *best_table; // the next plan node to be added to the curr QEP + + DBUG_ENTER("greedy_search"); + + /* number of tables that remain to be optimized */ + rem_size= my_count_bits(remaining_tables); + + do { + /* Find the extension of the current QEP with the lowest cost */ + join->best_read= DBL_MAX; + best_extension_by_limited_search(join, remaining_tables, idx, record_count, + read_time, search_depth, heuristic); + + if (rem_size <= search_depth) + { + /* + 'join->best_positions' contains a complete optimal extension of the + current partial QEP. + */ + DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, + join->tables, "optimal");); + DBUG_VOID_RETURN; + } + + /* select the first table in the optimal extension as most promising */ + best_pos= join->best_positions[idx]; + best_table= best_pos.table; + /* + Each subsequent loop of 'best_extension_by_limited_search' uses + 'join->positions' for cost estimates, therefore we have to update its + value. + */ + join->positions[idx]= best_pos; + + /* find the position of 'best_table' in 'join->best_ref' */ + best_idx= idx; + JOIN_TAB *pos= join->best_ref[best_idx]; + while (pos && best_table != pos) + pos= join->best_ref[++best_idx]; + DBUG_ASSERT((pos != NULL)); // should always find 'best_table' + /* move 'best_table' at the first free position in the array of joins */ + swap(JOIN_TAB*, join->best_ref[idx], join->best_ref[best_idx]); + + /* compute the cost of the new plan extended with 'best_table' */ + record_count*= join->positions[idx].records_read; + read_time+= join->positions[idx].read_time; + + remaining_tables&= ~(best_table->table->map); + --rem_size; + ++idx; + + DBUG_EXECUTE("opt", + print_plan(join, read_time, record_count, idx, "extended");); + } while (TRUE); +} + + +/* + Find a good, possibly optimal, query execution plan (QEP) by a possibly + exhaustive search. + + SYNOPSIS + best_extension_by_limited_search() + join pointer to the structure providing all context info for + the query + remaining_tables set of tables not included into the partial plan yet + idx length of the partial QEP in 'join->positions'; + since a depth-first search is used, also corresponds to + the current depth of the search tree; + also an index in the array 'join->best_ref'; + record_count estimate for the number of records returned by the best + partial plan + read_time the cost of the best partial plan + search_depth maximum depth of the recursion and thus size of the found + optimal plan (0 < search_depth <= join->tables+1). + heuristic pruning heuristics that should be applied during optimization + (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS) + + DESCRIPTION + The procedure searches for the optimal ordering of the query tables in set + 'remaining_tables' of size N, and the corresponding optimal access paths to each + table. The choice of a table order and an access path for each table + constitutes a query execution plan (QEP) that fully specifies how to + execute the query. + + The maximal size of the found plan is controlled by the parameter + 'search_depth'. When search_depth == N, the resulting plan is complete and + can be used directly as a QEP. If search_depth < N, the found plan consists + of only some of the query tables. Such "partial" optimal plans are useful + only as input to query optimization procedures, and cannot be used directly + to execute a query. + + The algorithm begins with an empty partial plan stored in 'join->positions' + and a set of N tables - 'remaining_tables'. Each step of the algorithm + evaluates the cost of the partial plan extended by all access plans for + each of the relations in 'remaining_tables', expands the current partial + plan with the access plan that results in lowest cost of the expanded + partial plan, and removes the corresponding relation from + 'remaining_tables'. The algorithm continues until it either constructs a + complete optimal plan, or constructs an optimal plartial plan with size = + search_depth. + + The final optimal plan is stored in 'join->best_positions'. The + corresponding cost of the optimal plan is in 'join->best_read'. + + NOTES + The procedure uses a recursive depth-first search where the depth of the + recursion (and thus the exhaustiveness of the search) is controlled by the + parameter 'search_depth'. + + The pseudocode below describes the algorithm of + 'best_extension_by_limited_search'. The worst-case complexity of this + algorithm is O(N*N^search_depth/search_depth). When serch_depth >= N, then + the complexity of greedy_search is O(N!). + + procedure best_extension_by_limited_search( + pplan in, // in, partial plan of tables-joined-so-far + pplan_cost, // in, cost of pplan + remaining_tables, // in, set of tables not referenced in pplan + best_plan_so_far, // in/out, best plan found so far + best_plan_so_far_cost,// in/out, cost of best_plan_so_far + search_depth) // in, maximum size of the plans being considered + { + for each table T from remaining_tables + { + // Calculate the cost of using table T as above + cost = complex-series-of-calculations; + + // Add the cost to the cost so far. + pplan_cost+= cost; + + if (pplan_cost >= best_plan_so_far_cost) + // pplan_cost already too great, stop search + continue; + + pplan= expand pplan by best_access_method; + remaining_tables= remaining_tables - table T; + if (remaining_tables is not an empty set + and + search_depth > 1) + { + best_extension_by_limited_search(pplan, pplan_cost, + remaining_tables, + best_plan_so_far, + best_plan_so_far_cost, + search_depth - 1); + } + else + { + best_plan_so_far_cost= pplan_cost; + best_plan_so_far= pplan; + } + } + } + + IMPLEMENTATION + When 'best_extension_by_limited_search' is called for the first time, + 'join->best_read' must be set to the largest possible value (e.g. DBL_MAX). + The actual implementation provides a way to optionally use pruning + heuristics (controlled by the parameter 'heuristic') to reduce the search + space by skipping some partial plans. + The parameter 'search_depth' provides control over the recursion + depth, and thus the size of the resulting optimal plan. + + RETURN + None +*/ + +static void +best_extension_by_limited_search(JOIN *join, + table_map remaining_tables, + uint idx, + double record_count, + double read_time, + uint search_depth, + uint heuristic) +{ + THD *thd= join->thd; + + DBUG_ENTER("best_extension_by_limited_search"); + + /* + 'join' is a partial plan with lower cost than the best plan so far, + so continue expanding it further with the tables in 'remaining_tables'. + */ + JOIN_TAB *s; + double best_record_count= DBL_MAX; + double best_read_time= DBL_MAX; + + DBUG_EXECUTE("opt", + print_plan(join, read_time, record_count, idx, "part_plan");); + + for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) + { + table_map real_table_bit= s->table->map; + if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent)) + { + double current_record_count, current_read_time; + + /* Find the best access method from 's' to the current partial plan */ + best_access_path(join, s, thd, remaining_tables, idx, record_count, read_time); + /* Compute the cost of extending the plan with 's' */ + current_record_count= record_count * join->positions[idx].records_read; + current_read_time= read_time + join->positions[idx].read_time; + + /* Expand only partial plans with lower cost than the best QEP so far */ + if ((current_read_time + + current_record_count / (double) TIME_FOR_COMPARE) >= join->best_read) + { + DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx, + "prune_by_cost");); + continue; + } + + /* + Prune some less promising partial plans. This heuristic may miss + the optimal QEPs, thus it results in a non-exhaustive search. + */ + if (heuristic == 1) + { + if (best_record_count > current_record_count || + best_read_time > current_read_time || + idx == join->const_tables && // 's' is the first table in the QEP + s->table == join->sort_by_table) + { + if (best_record_count >= current_record_count && + best_read_time >= current_read_time && + /* TODO: What is the reasoning behind this condition? */ + (!(s->key_dependent & remaining_tables) || + join->positions[idx].records_read < 2.0)) + { + best_record_count= current_record_count; + best_read_time= current_read_time; + } + } + else + { + DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx, + "prune_by_heuristic");); + continue; + } + } + + if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) ) + { /* Recursively expand the current partial plan */ + swap(JOIN_TAB*, join->best_ref[idx], *pos); + best_extension_by_limited_search(join, + remaining_tables & ~real_table_bit, + idx + 1, + current_record_count, + current_read_time, + search_depth - 1, + heuristic); + if (thd->killed) + DBUG_VOID_RETURN; + swap(JOIN_TAB*, join->best_ref[idx], *pos); + } + else + { /* + 'join' is either the best partial QEP with 'search_depth' relations, + or the best complete QEP so far, whichever is smaller. + */ + current_read_time+= current_record_count / (double) TIME_FOR_COMPARE; + if (join->sort_by_table && + join->sort_by_table != join->positions[join->const_tables].table->table) + /* We have to make a temp table */ + current_read_time+= current_record_count; + if ((search_depth == 1) || (current_read_time < join->best_read)) + { + memcpy((gptr) join->best_positions, (gptr) join->positions, + sizeof(POSITION) * (idx + 1)); + join->best_read= current_read_time; + } + DBUG_EXECUTE("opt", + print_plan(join, current_read_time, current_record_count, idx, "full_plan");); + } + } + } + DBUG_VOID_RETURN; +} + + +/* + TODO: this function is here only temporarily until 'greedy_search' is + tested and accepted. +*/ static void find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) @@ -2654,8 +3582,6 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ha_rows rec; double tmp; THD *thd= join->thd; - if (thd->killed) // Abort - return; if (!rest_tables) { @@ -2664,8 +3590,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, read_time+=record_count/(double) TIME_FOR_COMPARE; if (join->sort_by_table && - join->sort_by_table != - join->positions[join->const_tables].table->table) + join->sort_by_table != join->positions[join->const_tables].table->table) read_time+=record_count; // We have to make a temp table if (read_time < join->best_read) { @@ -2837,7 +3762,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, will match */ if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] == max_key_part) + table->quick_key_parts[key] <= max_key_part) tmp=records= (double) table->quick_rows[key]; else { @@ -2879,15 +3804,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, } records=(ulong) tmp; } - /* - If quick_select was used on a part of this key, we know - the maximum number of rows that the key can match. - */ - if (table->quick_keys.is_set(key) && - table->quick_key_parts[key] <= max_key_part && - records > (double) table->quick_rows[key]) - tmp= records= (double) table->quick_rows[key]; - else if (found_ref_or_null) + if (found_ref_or_null) { /* We need to do two key searches to find key */ tmp*= 2.0; @@ -3286,12 +4203,8 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, keyuse,join->const_table_map, &keyinfo->key_part[i], (char*) key_buff,maybe_null); - /* - Remeber if we are going to use REF_OR_NULL - But only if field _really_ can be null i.e. we force JT_REF - instead of JT_REF_OR_NULL in case if field can't be null - */ - if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null) + /* Remmeber if we are going to use REF_OR_NULL */ + if (keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) null_ref_key= key_buff; key_buff+=keyinfo->key_part[i].store_length; } @@ -3367,15 +4280,9 @@ store_val_in_field(Field *field,Item *item) bool error; THD *thd=current_thd; ha_rows cuted_fields=thd->cuted_fields; - /* - we should restore old value of count_cuted_fields because - store_val_in_field can be called from mysql_insert - with select_insert, which make count_cuted_fields= 1 - */ - enum_check_fields old_count_cuted_fields= thd->count_cuted_fields; thd->count_cuted_fields= CHECK_FIELD_WARN; error= item->save_in_field(field, 1); - thd->count_cuted_fields= old_count_cuted_fields; + thd->count_cuted_fields= CHECK_FIELD_IGNORE; return error || cuted_fields != thd->cuted_fields; } @@ -3432,9 +4339,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) table_map used_tables; if (join->tables > 1) cond->update_used_tables(); // Tablenr may have changed - if (join->const_tables == join->tables && - join->thd->lex->current_select->master_unit() == - &join->thd->lex->unit) // not upper level SELECT + if (join->const_tables == join->tables) join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= @@ -3469,7 +4374,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) tab->type=JT_ALL; use_quick_range=1; tab->use_quick=1; - tab->ref.key= -1; tab->ref.key_parts=0; // Don't use ref key. join->best_positions[i].records_read= rows2double(tab->quick->records); } @@ -3537,9 +4441,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) { /* Join with outer join condition */ COND *orig_cond=sel->cond; - sel->cond= and_conds(sel->cond, tab->on_expr); - if (sel->cond && !sel->cond->fixed) - sel->cond->fix_fields(join->thd, 0, &sel->cond); + sel->cond=and_conds(sel->cond,tab->on_expr); if (sel->test_quick_select(join->thd, tab->keys, used_tables & ~ current_map, (join->select_options & @@ -3611,7 +4513,7 @@ static void make_join_readinfo(JOIN *join, uint options) { uint i; - bool statistics= test(!(join->select_options & SELECT_DESCRIBE)); + SELECT_LEX *select_lex= &join->thd->lex->select_lex; DBUG_ENTER("make_join_readinfo"); for (i=join->const_tables ; i < join->tables ; i++) @@ -3705,8 +4607,7 @@ make_join_readinfo(JOIN *join, uint options) { join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED; tab->read_first_record= join_init_quick_read_record; - if (statistics) - statistic_increment(select_range_check_count, &LOCK_status); + statistic_increment(select_range_check_count, &LOCK_status); } else { @@ -3715,28 +4616,24 @@ make_join_readinfo(JOIN *join, uint options) { if (tab->select && tab->select->quick) { - if (statistics) - statistic_increment(select_range_count, &LOCK_status); + statistic_increment(select_range_count, &LOCK_status); } else { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; - if (statistics) - statistic_increment(select_scan_count, &LOCK_status); + statistic_increment(select_scan_count, &LOCK_status); } } else { if (tab->select && tab->select->quick) { - if (statistics) - statistic_increment(select_full_range_join_count, &LOCK_status); + statistic_increment(select_full_range_join_count, &LOCK_status); } else { join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED; - if (statistics) - statistic_increment(select_full_join_count, &LOCK_status); + statistic_increment(select_full_join_count, &LOCK_status); } } if (!table->no_keyread) @@ -3880,7 +4777,9 @@ JOIN::join_free(bool full) else { for (tab= join_tab, end= tab+tables; tab != end; tab++) + { tab->cleanup(); + } table= 0; } } @@ -4112,7 +5011,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, if (select_options & SELECT_DESCRIBE) { - select_describe(join, FALSE, FALSE, FALSE, info); + select_describe(join, false, false, false, info); DBUG_RETURN(0); } @@ -4356,7 +5255,6 @@ propagate_cond_constants(I_List *save_list,COND *and_father, SYNPOSIS eliminate_not_funcs() - thd thread handler cond condition tree DESCRIPTION @@ -4373,7 +5271,7 @@ propagate_cond_constants(I_List *save_list,COND *and_father, New condition tree */ -COND *eliminate_not_funcs(THD *thd, COND *cond) +COND *eliminate_not_funcs(COND *cond) { if (!cond) return cond; @@ -4383,7 +5281,7 @@ COND *eliminate_not_funcs(THD *thd, COND *cond) Item *item; while ((item= li++)) { - Item *new_item= eliminate_not_funcs(thd, item); + Item *new_item= eliminate_not_funcs(item); if (item != new_item) VOID(li.replace(new_item)); /* replace item with a new condition */ } @@ -4391,13 +5289,14 @@ COND *eliminate_not_funcs(THD *thd, COND *cond) else if (cond->type() == Item::FUNC_ITEM && /* 'NOT' operation? */ ((Item_func*) cond)->functype() == Item_func::NOT_FUNC) { - COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer(thd); + COND *new_cond= ((Item_func*) cond)->arguments()[0]->neg_transformer(); if (new_cond) { /* Here we can delete the NOT function. Something like: delete cond; But we don't need to do it. All items will be deleted later at once. */ + new_cond->fix_fields(current_thd, 0, &new_cond); cond= new_cond; } } @@ -4406,7 +5305,7 @@ COND *eliminate_not_funcs(THD *thd, COND *cond) static COND * -optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) +optimize_cond(COND *conds,Item::cond_result *cond_value) { DBUG_ENTER("optimize_cond"); if (!conds) @@ -4416,7 +5315,7 @@ optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) } DBUG_EXECUTE("where",print_where(conds,"original");); /* eliminate NOT operators */ - conds= eliminate_not_funcs(thd, conds); + conds= eliminate_not_funcs(conds); DBUG_EXECUTE("where", print_where(conds, "after negation elimination");); /* change field = field to field = const for each found field = const */ propagate_cond_constants((I_List *) 0,conds,conds); @@ -4425,7 +5324,7 @@ optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) Remove all and-levels where CONST item != CONST item */ DBUG_EXECUTE("where",print_where(conds,"after const change");); - conds= remove_eq_conds(thd, conds, cond_value) ; + conds=remove_eq_conds(conds,cond_value) ; DBUG_EXECUTE("info",print_where(conds,"after remove");); DBUG_RETURN(conds); } @@ -4440,7 +5339,7 @@ optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) */ static COND * -remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) +remove_eq_conds(COND *cond,Item::cond_result *cond_value) { if (cond->type() == Item::COND_ITEM) { @@ -4454,7 +5353,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Item *item; while ((item=li++)) { - Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value); + Item *new_item=remove_eq_conds(item,&tmp_cond_value); if (!new_item) li.remove(); else if (item != new_item) @@ -4488,7 +5387,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) } } if (should_fix_fields) - cond->update_used_tables(); + cond->fix_fields(current_thd,0, &cond); if (!((Item_cond*) cond)->argument_list()->elements || *cond_value != Item::COND_OK) @@ -4515,6 +5414,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Item_func_isnull *func=(Item_func_isnull*) cond; Item **args= func->arguments(); + THD *thd=current_thd; if (args[0]->type() == Item::FIELD_ITEM) { Field *field=((Item_field*) args[0])->field; @@ -4787,7 +5687,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, else return new Field_double(item_sum->max_length,maybe_null, item->name, table, item_sum->decimals); - case Item_sum::VARIANCE_FUNC: /* Place for sum & count */ + case Item_sum::VARIANCE_FUNC: /* Place for sum & count */ case Item_sum::STD_FUNC: if (group) return new Field_string(sizeof(double)*2+sizeof(longlong), @@ -4815,19 +5715,17 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, default: // This case should never be choosen DBUG_ASSERT(0); - thd->fatal_error(); return 0; } } - /* We never come here */ + thd->fatal_error(); + return 0; // Error } case Item::FIELD_ITEM: case Item::DEFAULT_VALUE_ITEM: - { - Item_field *field= (Item_field*) item; - return create_tmp_field_from_field(thd, (*from_field= field->field), + return create_tmp_field_from_field(thd, (*from_field= + ((Item_field*) item)->field), item, table, modify_item); - } case Item::FUNC_ITEM: case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: @@ -5480,22 +6378,13 @@ free_tmp_table(THD *thd, TABLE *entry) save_proc_info=thd->proc_info; thd->proc_info="removing tmp table"; free_blobs(entry); - if (entry->file) + if (entry->db_stat && entry->file) { - if (entry->db_stat) - { - (void) entry->file->close(); - } - /* - We can't call ha_delete_table here as the table may created in mixed case - here and we have to ensure that delete_table gets the table name in - the original case. - */ - if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP) - entry->file->delete_table(entry->real_name); + (void) entry->file->close(); delete entry->file; } - + if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP) + (void) ha_delete_table(entry->db_type,entry->real_name); /* free blobs */ for (Field **ptr=entry->field ; *ptr ; ptr++) (*ptr)->free(); @@ -5798,15 +6687,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records) return 0; } else - { - /* - This row failed selection, release lock on it. - XXX: There is no table handler in MySQL which makes use of this - call. It's kept from Gemini times. A lot of new code was added - recently (i. e. subselects) without having it in mind. - */ info->file->unlock_row(); - } } } while (!(error=info->read_record(info)) && !(*report_error)); } @@ -5968,8 +6849,8 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) if (tab->on_expr && !table->null_row) { if ((table->null_row= test(tab->on_expr->val_int() == 0))) - mark_as_null_row(table); - } + empty_record(table); + } if (!table->null_row) table->maybe_null=0; DBUG_RETURN(0); @@ -6760,11 +7641,8 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) /* We can remove binary fields and numerical fields except float, as float comparison isn't 100 % secure - We have to keep binary strings to be able to check for end spaces */ if (field->binary() && - field->real_type() != FIELD_TYPE_STRING && - field->real_type() != FIELD_TYPE_VAR_STRING && (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0)) { return !store_val_in_field(field,right_item); @@ -6777,7 +7655,7 @@ static bool test_if_ref(Item_field *left_item,Item *right_item) static COND * -make_cond_for_table(COND *cond, table_map tables, table_map used_table) +make_cond_for_table(COND *cond,table_map tables,table_map used_table) { if (used_table && !(cond->used_tables() & used_table)) return (COND*) 0; // Already checked @@ -6803,13 +7681,7 @@ make_cond_for_table(COND *cond, table_map tables, table_map used_table) case 1: return new_cond->argument_list()->head(); default: - /* - Item_cond_and do not need fix_fields for execution, its parameters - are fixed or do not need fix_fields, too - */ - new_cond->quick_fix_field(); - new_cond->used_tables_cache= - ((Item_cond_and*) cond)->used_tables_cache & + new_cond->used_tables_cache=((Item_cond*) cond)->used_tables_cache & tables; return new_cond; } @@ -6828,12 +7700,7 @@ make_cond_for_table(COND *cond, table_map tables, table_map used_table) return (COND*) 0; // Always true new_cond->argument_list()->push_back(fix); } - /* - Item_cond_and do not need fix_fields for execution, its parameters - are fixed or do not need fix_fields, too - */ - new_cond->quick_fix_field(); - new_cond->used_tables_cache= ((Item_cond_or*) cond)->used_tables_cache; + new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache; new_cond->top_level_item(); return new_cond; } @@ -7062,7 +7929,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, ref_key= -1; /* Test if constant range in WHERE */ - if (tab->ref.key >= 0 && tab->ref.key_parts) + if (tab->ref.key >= 0) { ref_key= tab->ref.key; ref_key_parts= tab->ref.key_parts; @@ -7182,20 +8049,13 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ if (select_limit >= table->file->records) { - keys= *table->file->keys_to_use_for_scanning(); + keys=*table->file->keys_to_use_for_scanning(); keys.merge(table->used_keys); - - /* - We are adding here also the index speified in FORCE INDEX clause, - if any. - This is to allow users to use index in ORDER BY. - */ - if (table->force_index) - keys.merge(table->keys_in_use_for_query); - keys.intersect(usable_keys); } else - keys= usable_keys; + keys.set_all(); + + keys.intersect(usable_keys); for (nr=0; nr < table->keys ; nr++) { @@ -7357,10 +8217,8 @@ static bool fix_having(JOIN *join, Item **having) if (!table->select->cond) table->select->cond=sort_table_cond; else // This should never happen - if (!(table->select->cond= new Item_cond_and(table->select->cond, - sort_table_cond)) || - table->select->cond->fix_fields(join->thd, join->tables_list, - &table->select->cond)) + if (!(table->select->cond=new Item_cond_and(table->select->cond, + sort_table_cond))) return 1; table->select_cond=table->select->cond; table->select_cond->top_level_item(); @@ -7979,16 +8837,10 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, } order->in_field_list=0; Item *it= *order->item; - /* - We check it->fixed because Item_func_group_concat can put - arguments for which fix_fields already was called. - - 'it' reassigned in if condition because fix_field can change it. - */ - if (!it->fixed && - (it->fix_fields(thd, tables, order->item) || - (it= *order->item)->check_cols(1) || - thd->is_fatal_error)) + if (it->fix_fields(thd, tables, order->item) || + //'it' ressigned because fix_field can change it + (it= *order->item)->check_cols(1) || + thd->is_fatal_error) return 1; // Wrong field uint el= all_fields.elements; all_fields.push_front(it); // Add new field to field list @@ -8016,29 +8868,6 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, } -/* - Intitialize the GROUP BY list. - - SYNOPSIS - setup_group() - thd Thread handler - ref_pointer_array We store references to all fields that was not in - 'fields' here. - fields All fields in the select part. Any item in 'order' - that is part of these list is replaced by a pointer - to this fields. - all_fields Total list of all unique fields used by the select. - All items in 'order' that was not part of fields will - be added first to this list. - order The fields we should do GROUP BY on. - hidden_group_fields Pointer to flag that is set to 1 if we added any fields - to all_fields. - - RETURN - 0 ok - 1 error (probably out of memory) -*/ - int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, List &fields, List &all_fields, ORDER *order, @@ -8418,11 +9247,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, Item *pos; List_iterator_fast li(all_fields); Copy_field *copy; + DBUG_ENTER("setup_copy_fields"); res_selected_fields.empty(); res_all_fields.empty(); List_iterator_fast itr(res_all_fields); + uint i, border= all_fields.elements - elements; - DBUG_ENTER("setup_copy_fields"); if (!(copy=param->copy_field= new Copy_field[param->field_count])) goto err2; @@ -8557,23 +9387,6 @@ bool JOIN::alloc_func_list() } -/* - Initialize 'sum_funcs' array with all Item_sum objects - - SYNOPSIS - make_sum_func_list() - field_list All items - send_fields Items in select list - before_group_by Set to 1 if this is called before GROUP BY handling - - NOTES - Calls ::setup() for all item_sum objects in field_list - - RETURN - 0 ok - 1 error -*/ - bool JOIN::make_sum_func_list(List &field_list, List &send_fields, bool before_group_by) { @@ -8610,7 +9423,7 @@ bool JOIN::make_sum_func_list(List &field_list, List &send_fields, /* - Change all funcs and sum_funcs to fields in tmp table, and create + Change all funcs and sum_funcs to fields in tmp table, and create new list of all items. change_to_use_tmp_fields() @@ -8830,7 +9643,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i]. fieldnr-1]; Item *value=join_tab->ref.items[i]; - cond->add(new Item_func_equal(new Item_field(field), value)); + cond->add(new Item_func_equal(new Item_field(field),value)); } if (thd->is_fatal_error) DBUG_RETURN(TRUE); @@ -9110,6 +9923,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, List field_list; List item_list; THD *thd=join->thd; + SELECT_LEX *select_lex= &join->thd->lex->select_lex; select_result *result=join->result; Item *item_null= new Item_null(); CHARSET_INFO *cs= &my_charset_latin1; @@ -9476,7 +10290,7 @@ void st_select_lex::print(THD *thd, String *str) str->append(table->db); str->append('.'); str->append(table->real_name); - if (my_strcasecmp(table_alias_charset, table->real_name, table->alias)) + if (strcmp(table->real_name, table->alias)) { str->append(' '); str->append(table->alias); diff --git a/sql/sql_select.h b/sql/sql_select.h index 07b94b0afed..e22acf4d186 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -116,6 +116,7 @@ typedef struct st_join_table { typedef struct st_position /* Used in find_best */ { double records_read; + double read_time; JOIN_TAB *table; KEYUSE *key; } POSITION; @@ -133,8 +134,9 @@ typedef struct st_rollup class JOIN :public Sql_alloc { public: - JOIN_TAB *join_tab,**best_ref,**map2table; - JOIN_TAB *join_tab_save; //saved join_tab for subquery reexecution + JOIN_TAB *join_tab,**best_ref; + JOIN_TAB **map2table; // mapping between table indexes and JOIN_TABs + JOIN_TAB *join_tab_save; // saved join_tab for subquery reexecution TABLE **table,**all_tables,*sort_by_table; uint tables,const_tables; uint send_group_parts; @@ -436,4 +438,4 @@ bool cp_buffer_from_ref(TABLE_REF *ref); bool error_if_full_join(JOIN *join); int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); -COND *eliminate_not_funcs(THD *thd, COND *cond); +COND *eliminate_not_funcs(COND *cond); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 2e755c419ff..8ad0238e7c6 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -31,11 +31,9 @@ static const char *grant_names[]={ "select","insert","update","delete","create","drop","reload","shutdown", "process","file","grant","references","index","alter"}; -#ifndef NO_EMBEDDED_ACCESS_CHECKS static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **), "grant_types", grant_names}; -#endif static int mysql_find_files(THD *thd,List *files, const char *db, const char *path, const char *wild, bool dir); @@ -221,32 +219,30 @@ struct show_privileges_st { const char *comment; }; + +/* + TODO: Update with new privileges +*/ static struct show_privileges_st sys_privileges[]= { - {"Alter", "Tables", "To alter the table"}, - {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"}, - {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, - {"Delete", "Tables", "To delete existing rows"}, - {"Drop", "Databases,Tables", "To drop databases and tables"}, - {"File", "File access on server", "To read and write files on the server"}, - {"Grant option", "Databases,Tables", "To give to other users those privileges you possess"}, - {"Index", "Tables", "To create or drop indexes"}, - {"Insert", "Tables", "To insert data into tables"}, - {"Lock tables","Databases","To use LOCK TABLES (together with SELECT privilege)"}, - {"Process", "Server Admin", "To view the plain text of currently executing queries"}, - {"References", "Databases,Tables", "To have references on tables"}, - {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"}, - {"Replication client","Server Admin","To ask where the slave or master servers are"}, - {"Replication slave","Server Admin","To read binary log events from the master"}, {"Select", "Tables", "To retrieve rows from table"}, - {"Show databases","Server Admin","To see all databases with SHOW DATABASES"}, + {"Insert", "Tables", "To insert data into tables"}, + {"Update", "Tables", "To update existing rows "}, + {"Delete", "Tables", "To delete existing rows"}, + {"Index", "Tables", "To create or drop indexes"}, + {"Alter", "Tables", "To alter the table"}, + {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, + {"Drop", "Databases,Tables", "To drop databases and tables"}, + {"Grant", "Databases,Tables", "To give to other users those privileges you possess"}, + {"References", "Databases,Tables", "To have references on tables"}, + {"Reload", "Server Admin", "To reload or refresh tables, logs and privileges"}, {"Shutdown","Server Admin", "To shutdown the server"}, - {"Super","Server Admin","To use KILL thread, SET GLOBAL, CHANGE MASTER, etc."}, - {"Update", "Tables", "To update existing rows"}, - {"Usage","Server Admin","No privileges - allow connect only"}, + {"Process", "Server Admin", "To view the plain text of currently executing queries"}, + {"File", "File access on server", "To read and write files on the server"}, {NullS, NullS, NullS} }; + int mysqld_show_privileges(THD *thd) { List field_list; @@ -303,11 +299,11 @@ static struct show_column_type_st sys_column_types[]= { {"tinyint", 1, "-128", "127", 0, 0, "YES", "YES", - "NO", "YES", "YES", "NO", "NULL,0", - "A very small integer"}, + "NO", "YES", "YES", "NO", "NULL,0", + "A very small integer"}, {"tinyint unsigned", - 1, "0" , "255", 0, 0, "YES", "YES", - "YES", "YES", "YES", "NO", "NULL,0", + 1, "0" , "255", 0, 0, "YES", "YES", + "YES", "YES", "YES", "NO", "NULL,0", "A very small integer"}, }; @@ -369,9 +365,7 @@ mysql_find_files(THD *thd,List *files, const char *db,const char *path, char *ext; MY_DIR *dirp; FILEINFO *file; -#ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access=thd->col_access; -#endif TABLE_LIST table_list; DBUG_ENTER("mysql_find_files"); @@ -698,11 +692,17 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, if (!wild || !wild[0] || !wild_case_compare(system_charset_info, field->field_name,wild)) { +#ifdef NOT_USED + if (thd->col_access & TABLE_ACLS || + ! check_grant_column(thd,table,field->field_name, + (uint) strlen(field->field_name),1)) +#endif { byte *pos; uint flags=field->flags; String type(tmp,sizeof(tmp), system_charset_info); uint col_access; + bool null_default_value=0; protocol->prepare_for_resend(); protocol->store(field->field_name, system_charset_info); @@ -711,12 +711,6 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, if (verbose) protocol->store(field->has_charset() ? field->charset()->name : "NULL", system_charset_info); - /* - Altough TIMESTAMP fields can't contain NULL as its value they - will accept NULL if you will try to insert such value and will - convert it to current TIMESTAMP. So YES here means that NULL - is allowed for assignment but can't be returned. - */ pos=(byte*) ((flags & NOT_NULL_FLAG) && field->type() != FIELD_TYPE_TIMESTAMP ? "" : "YES"); @@ -726,24 +720,16 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild, (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); protocol->store((char*) pos, system_charset_info); - if (table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_UN_FIELD) - { - /* - We have NOW() as default value but we use CURRENT_TIMESTAMP form - because it is more SQL standard comatible - */ - protocol->store("CURRENT_TIMESTAMP", system_charset_info); - } - else if (field->unireg_check != Field::NEXT_NUMBER && - !field->is_null()) + if (field->type() == FIELD_TYPE_TIMESTAMP || + field->unireg_check == Field::NEXT_NUMBER) + null_default_value=1; + if (!null_default_value && !field->is_null()) { // Not null by default type.set(tmp, sizeof(tmp), field->charset()); field->val_str(&type,&type); protocol->store(type.ptr(),type.length(),type.charset()); } - else if (field->unireg_check == Field::NEXT_NUMBER || - field->maybe_null()) + else if (field->maybe_null() || null_default_value) protocol->store_null(); // Null as default else protocol->store("",0, system_charset_info); // empty string @@ -833,9 +819,7 @@ int mysqld_show_create_db(THD *thd, char *dbname, char path[FN_REFLEN]; char buff[2048]; String buffer(buff, sizeof(buff), system_charset_info); -#ifndef NO_EMBEDDED_ACCESS_CHECKS uint db_access; -#endif bool found_libchar; HA_CREATE_INFO create; uint create_options = create_info ? create_info->options : 0; @@ -932,7 +916,7 @@ mysqld_show_logs(THD *thd) DBUG_RETURN(1); #ifdef HAVE_BERKELEY_DB - if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol)) + if (!berkeley_skip && berkeley_show_logs(protocol)) DBUG_RETURN(-1); #endif @@ -1011,8 +995,9 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list) protocol->store_null(); /* Check if we have a key part that only uses part of the field */ - if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field || - key_part->length != table->field[key_part->fieldnr-1]->key_length())) + if (!key_part->field || + key_part->length != + table->field[key_part->fieldnr-1]->key_length()) protocol->store_tiny((longlong) key_part->length); else protocol->store_null(); @@ -1100,85 +1085,100 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd) DBUG_RETURN(0); } -/* - Go through all character combinations and ensure that sql_lex.cc can - parse it as an identifer. - - SYNOPSIS - require_quotes() - name attribute name - name_length length of name - - RETURN - # Pointer to conflicting character - 0 No conflicting character -*/ - -static const char *require_quotes(const char *name, uint name_length) +static inline const char *require_quotes(const char *name, uint length) { - uint length; - const char *end= name + name_length; - - for ( ; name < end ; name++) + uint i, d, c; + for (i=0; iident_map[chr]) - return name; + c=((uchar *)name)[i]; + d=my_mbcharlen(system_charset_info, c); + if (d==1 && !system_charset_info->ident_map[c]) + return name+i; } return 0; } +/* + Looking for char in multibyte string -static void append_quoted_simple_identifier(String *packet, char quote_char, - const char *name, uint length) + SYNOPSIS + look_for_char() + name string for looking at + length length of name + q '\'' or '\"' for looking for + + RETURN VALUES + # pointer to found char in string + 0 string doesn't contain required char +*/ + +static inline const char *look_for_char(const char *name, + uint length, char q) { - packet->append("e_char, 1, system_charset_info); - packet->append(name, length, system_charset_info); - packet->append("e_char, 1, system_charset_info); -} - + const char *cur= name; + const char *end= cur+length; + uint symbol_length; + for (; curvariables.sql_mode & MODE_ANSI_QUOTES) - quote_char= '\"'; + qtype= '\"'; else - quote_char= '`'; + qtype= '`'; if (is_keyword(name,length)) { - append_quoted_simple_identifier(packet, quote_char, name, length); - return; + packet->append(&qtype, 1, system_charset_info); + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1, system_charset_info); } - - if (!require_quotes(name, length)) + else { - if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) - packet->append(name, length, system_charset_info); + if (!(qplace= require_quotes(name, length))) + { + if (!(thd->options & OPTION_QUOTE_SHOW_CREATE)) + packet->append(name, length, system_charset_info); + else + { + packet->append(&qtype, 1, system_charset_info); + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1, system_charset_info); + } + } else - append_quoted_simple_identifier(packet, quote_char, name, length); - return; + { + packet->shrink(packet->length()+length+2); + packet->append(&qtype, 1, system_charset_info); + if (*qplace != qtype) + qplace= look_for_char(qplace+1,length-(qplace-name)-1,qtype); + while (qplace) + { + if ((part_len= qplace-name)) + { + packet->append(name, part_len, system_charset_info); + length-= part_len; + } + packet->append(qplace, 1, system_charset_info); + name= qplace; + qplace= look_for_char(name+1,length-1,qtype); + } + packet->append(name, length, system_charset_info); + packet->append(&qtype, 1, system_charset_info); + } } - - /* The identifier must be quoted as it includes a quote character */ - - packet->reserve(length*2 + 2); - packet->append("e_char, 1, system_charset_info); - - for (name_end= name+length ; name < name_end ; name+= length) - { - char chr= *name; - length= my_mbcharlen(system_charset_info, chr); - if (length == 1 && chr == quote_char) - packet->append("e_char, 1, system_charset_info); - packet->append(name, length, packet->charset()); - } - packet->append("e_char, 1, system_charset_info); } @@ -1206,7 +1206,7 @@ static int store_create_info(THD *thd, TABLE *table, String *packet) { List field_list; - char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias; + char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end; String type(tmp, sizeof(tmp),&my_charset_bin); Field **ptr,*field; uint primary_key; @@ -1232,15 +1232,12 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append("CREATE TEMPORARY TABLE ", 23); else packet->append("CREATE TABLE ", 13); - alias= (lower_case_table_names == 2 ? table->table_name : - table->real_name); - append_identifier(thd, packet, alias, strlen(alias)); + append_identifier(thd,packet, table->real_name, strlen(table->real_name)); packet->append(" (\n", 3); for (ptr=table->field ; (field= *ptr); ptr++) { bool has_default; - bool has_now_default; uint flags = field->flags; if (ptr != table->field) @@ -1256,46 +1253,40 @@ store_create_info(THD *thd, TABLE *table, String *packet) field->sql_type(type); packet->append(type.ptr(),type.length()); - if (field->has_charset() && !limited_mysql_mode && !foreign_db_mode) + if (field->has_charset()) { - if (field->charset() != table->table_charset) + if (field->charset() == &my_charset_bin) + packet->append(" binary", 7); + else if (!limited_mysql_mode && !foreign_db_mode) { - packet->append(" character set ", 15); - packet->append(field->charset()->csname); - } - /* - For string types dump collation name only if - collation is not primary for the given charset - */ - if (!(field->charset()->state & MY_CS_PRIMARY)) - { - packet->append(" collate ", 9); - packet->append(field->charset()->name); + if (field->charset() != table->table_charset) + { + packet->append(" character set ", 15); + packet->append(field->charset()->csname); + } + /* + For string types dump collation name only if + collation is not primary for the given charset + */ + if (!(field->charset()->state & MY_CS_PRIMARY)) + { + packet->append(" collate ", 9); + packet->append(field->charset()->name); + } } } if (flags & NOT_NULL_FLAG) packet->append(" NOT NULL", 9); - - /* - Again we are using CURRENT_TIMESTAMP instead of NOW because it is - more standard - */ - has_now_default= table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_UN_FIELD; - has_default= (field->type() != FIELD_TYPE_BLOB && - field->unireg_check != Field::NEXT_NUMBER && - !((foreign_db_mode || limited_mysql_mode) && - has_now_default)); + field->type() != FIELD_TYPE_TIMESTAMP && + field->unireg_check != Field::NEXT_NUMBER); if (has_default) { packet->append(" default ", 9); - if (has_now_default) - packet->append("CURRENT_TIMESTAMP",17); - else if (!field->is_null()) + if (!field->is_null()) { // Not null by default type.set(tmp, sizeof(tmp), field->charset()); field->val_str(&type,&type); @@ -1316,11 +1307,6 @@ store_create_info(THD *thd, TABLE *table, String *packet) packet->append(tmp,0); } - if (!foreign_db_mode && !limited_mysql_mode && - table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_DN_FIELD) - packet->append(" on update CURRENT_TIMESTAMP",28); - if (field->unireg_check == Field::NEXT_NUMBER && !foreign_db_mode) packet->append(" auto_increment", 15 ); @@ -1828,10 +1814,10 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, break; case SHOW_SLAVE_RUNNING: { - pthread_mutex_lock(&LOCK_active_mi); + LOCK_ACTIVE_MI; end= strmov(buff, (active_mi->slave_running && active_mi->rli.slave_running) ? "ON" : "OFF"); - pthread_mutex_unlock(&LOCK_active_mi); + UNLOCK_ACTIVE_MI; break; } #endif /* HAVE_REPLICATION */ @@ -1845,6 +1831,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, end= strend(pos); break; } + case SHOW_DOUBLE: + { + end= buff + sprintf(buff, "%f", *(double*) value); + break; + } #ifdef HAVE_OPENSSL /* First group - functions relying on CTX */ case SHOW_SSL_CTX_SESS_ACCEPT: diff --git a/sql/sql_test.cc b/sql/sql_test.cc index f2909b93a2a..ec6845a74f7 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -232,6 +232,102 @@ TEST_join(JOIN *join) DBUG_VOID_RETURN; } + +/* + Print the current state during query optimization. + + SYNOPSIS + print_plan() + join pointer to the structure providing all context info for + the query + read_time the cost of the best partial plan + record_count estimate for the number of records returned by the best + partial plan + idx length of the partial QEP in 'join->positions'; + also an index in the array 'join->best_ref'; + info comment string to appear above the printout + + DESCRIPTION + This function prints to the log file DBUG_FILE the members of 'join' that + are used during query optimization (join->positions, join->best_positions, + and join->best_ref) and few other related variables (read_time, + record_count). + Useful to trace query optimizer functions. + + RETURN + None +*/ + +void +print_plan(JOIN* join, double read_time, double record_count, + uint idx, const char *info) +{ + uint i; + POSITION pos; + JOIN_TAB *join_table; + JOIN_TAB **plan_nodes; + TABLE* table; + + if (info == 0) + info= ""; + + DBUG_LOCK_FILE; + if (join->best_read == DBL_MAX) + { + fprintf(DBUG_FILE,"%s; idx:%u, best: DBL_MAX, current:%g\n", + info, idx, read_time); + } + else + { + fprintf(DBUG_FILE,"%s; idx: %u, best: %g, current: %g\n", + info, idx, join->best_read, read_time); + } + + /* Print the tables in JOIN->positions */ + fputs(" POSITIONS: ", DBUG_FILE); + for (i= 0; i < idx ; i++) + { + pos = join->positions[i]; + table= pos.table->table; + if (table) + fputs(table->real_name, DBUG_FILE); + fputc(' ', DBUG_FILE); + } + fputc('\n', DBUG_FILE); + + /* + Print the tables in JOIN->best_positions only if at least one complete plan + has been found. An indicator for this is the value of 'join->best_read'. + */ + fputs("BEST_POSITIONS: ", DBUG_FILE); + if (join->best_read < DBL_MAX) + { + for (i= 0; i < idx ; i++) + { + pos= join->best_positions[i]; + table= pos.table->table; + if (table) + fputs(table->real_name, DBUG_FILE); + fputc(' ', DBUG_FILE); + } + } + fputc('\n', DBUG_FILE); + + /* Print the tables in JOIN->best_ref */ + fputs(" BEST_REF: ", DBUG_FILE); + for (plan_nodes= join->best_ref ; *plan_nodes ; plan_nodes++) + { + join_table= (*plan_nodes); + fputs(join_table->table->real_name, DBUG_FILE); + fprintf(DBUG_FILE, "(%u,%u,%u)", + join_table->found_records, join_table->records, join_table->read_time); + fputc(' ', DBUG_FILE); + } + fputc('\n', DBUG_FILE); + + DBUG_UNLOCK_FILE; +} + #endif typedef struct st_debug_lock @@ -306,14 +402,10 @@ static void display_table_locks(void) THR_LOCK *lock=(THR_LOCK*) list->data; VOID(pthread_mutex_lock(&lock->mutex)); - push_locks_into_array(&saved_table_locks, lock->write.data, FALSE, - "Locked - write"); - push_locks_into_array(&saved_table_locks, lock->write_wait.data, TRUE, - "Waiting - write"); - push_locks_into_array(&saved_table_locks, lock->read.data, FALSE, - "Locked - read"); - push_locks_into_array(&saved_table_locks, lock->read_wait.data, TRUE, - "Waiting - read"); + push_locks_into_array(&saved_table_locks, lock->write.data, false, "Locked - write"); + push_locks_into_array(&saved_table_locks, lock->write_wait.data, true, "Waiting - write"); + push_locks_into_array(&saved_table_locks, lock->read.data, false, "Locked - read"); + push_locks_into_array(&saved_table_locks, lock->read_wait.data, true, "Waiting - read"); VOID(pthread_mutex_unlock(&lock->mutex)); } VOID(pthread_mutex_unlock(&THR_LOCK_lock)); diff --git a/sql/structs.h b/sql/structs.h index 86d754f00d6..3279428c888 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -20,21 +20,11 @@ struct st_table; class Field; -typedef struct st_lex_string -{ +typedef struct lex_string { char *str; uint length; } LEX_STRING; -typedef struct st_lex_string_with_init :public st_lex_string -{ - st_lex_string_with_init(const char *str_arg, uint length_arg) - { - str= (char*) str_arg; - length= length_arg; - } -} LEX_STRING_WITH_INIT; - typedef struct st_date_time_format { uchar positions[8]; @@ -166,8 +156,8 @@ typedef struct st_known_date_time_format { enum SHOW_TYPE { SHOW_UNDEF, - SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL, - SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION, + SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_DOUBLE, + SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION, SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS, #ifdef HAVE_OPENSSL SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD, @@ -220,7 +210,7 @@ typedef struct user_conn { #define REG_NEW_RECORD 2 /* Write a new record if not found */ #define REG_UPDATE 4 /* Uppdate record */ #define REG_DELETE 8 /* Delete found record */ -#define REG_PROG 16 /* User is updating database */ +#define REG_PROG 16 /* User is updateing database */ #define REG_CLEAR_AFTER_WRITE 32 #define REG_MAY_BE_UPDATED 64 #define REG_AUTO_UPDATE 64 /* Used in D-forms for scroll-tables */