mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Post-merge post-merge fix (new error codes for fparser).
This commit is contained in:
@ -386,6 +386,7 @@ libmysqld/opt_ft.cc
|
|||||||
libmysqld/opt_range.cc
|
libmysqld/opt_range.cc
|
||||||
libmysqld/opt_sum.cc
|
libmysqld/opt_sum.cc
|
||||||
libmysqld/pack.c
|
libmysqld/pack.c
|
||||||
|
libmysqld/parse_file.cc
|
||||||
libmysqld/password.c
|
libmysqld/password.c
|
||||||
libmysqld/procedure.cc
|
libmysqld/procedure.cc
|
||||||
libmysqld/protocol.cc
|
libmysqld/protocol.cc
|
||||||
|
@ -161,6 +161,7 @@ tim@sand.box
|
|||||||
tim@threads.polyesthetic.msg
|
tim@threads.polyesthetic.msg
|
||||||
tim@white.box
|
tim@white.box
|
||||||
tim@work.mysql.com
|
tim@work.mysql.com
|
||||||
|
timour@mysql.com
|
||||||
tom@basil-firewall.home.com
|
tom@basil-firewall.home.com
|
||||||
tomas@mc05.(none)
|
tomas@mc05.(none)
|
||||||
tonu@hundin.mysql.fi
|
tonu@hundin.mysql.fi
|
||||||
|
@ -121,6 +121,13 @@ extern int NEAR my_errno; /* Last error in mysys */
|
|||||||
#define MY_ERRNO_EDOM 33
|
#define MY_ERRNO_EDOM 33
|
||||||
#define MY_ERRNO_ERANGE 34
|
#define MY_ERRNO_ERANGE 34
|
||||||
|
|
||||||
|
/* Bits for get_date timeflag */
|
||||||
|
#define GETDATE_DATE_TIME 1
|
||||||
|
#define GETDATE_SHORT_DATE 2
|
||||||
|
#define GETDATE_HHMMSSTIME 4
|
||||||
|
#define GETDATE_GMT 8
|
||||||
|
#define GETDATE_FIXEDLENGTH 16
|
||||||
|
|
||||||
/* defines when allocating data */
|
/* defines when allocating data */
|
||||||
#ifdef SAFEMALLOC
|
#ifdef SAFEMALLOC
|
||||||
#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG )
|
#define my_malloc(SZ,FLAG) _mymalloc((SZ), __FILE__, __LINE__, FLAG )
|
||||||
|
@ -349,4 +349,9 @@
|
|||||||
#define ER_SP_VARCOND_AFTER_CURSHNDLR 1330
|
#define ER_SP_VARCOND_AFTER_CURSHNDLR 1330
|
||||||
#define ER_SP_CURSOR_AFTER_HANDLER 1331
|
#define ER_SP_CURSOR_AFTER_HANDLER 1331
|
||||||
#define ER_SP_CASE_NOT_FOUND 1332
|
#define ER_SP_CASE_NOT_FOUND 1332
|
||||||
#define ER_ERROR_MESSAGES 333
|
#define ER_FPARSER_TOO_BIG_FILE 1333
|
||||||
|
#define ER_FPARSER_BAD_HEADER 1334
|
||||||
|
#define ER_FPARSER_EOF_IN_COMMENT 1335
|
||||||
|
#define ER_FPARSER_ERROR_IN_PARAMETER 1336
|
||||||
|
#define ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER 1337
|
||||||
|
#define ER_ERROR_MESSAGES 338
|
||||||
|
@ -58,7 +58,8 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
|||||||
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
|
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
|
||||||
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
|
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
|
||||||
spatial.cc gstream.cc sql_help.cc protocol_cursor.cc \
|
spatial.cc gstream.cc sql_help.cc protocol_cursor.cc \
|
||||||
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc
|
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
|
||||||
|
parse_file.cc
|
||||||
|
|
||||||
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
|
libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
|
||||||
libmysqld_a_SOURCES=
|
libmysqld_a_SOURCES=
|
||||||
|
@ -388,8 +388,8 @@ SELECT DISTINCTROW email, shipcode FROM t1, t2 WHERE t1.infoID=t2.infoID;
|
|||||||
email shipcode
|
email shipcode
|
||||||
test1@testdomain.com Z001
|
test1@testdomain.com Z001
|
||||||
test2@testdomain.com Z001
|
test2@testdomain.com Z001
|
||||||
test3@testdomain.com Z001
|
|
||||||
test2@testdomain.com R002
|
test2@testdomain.com R002
|
||||||
|
test3@testdomain.com Z001
|
||||||
SELECT DISTINCTROW email FROM t1 ORDER BY dateentered DESC;
|
SELECT DISTINCTROW email FROM t1 ORDER BY dateentered DESC;
|
||||||
email
|
email
|
||||||
test1@testdomain.com
|
test1@testdomain.com
|
||||||
|
@ -183,12 +183,12 @@ insert into t2 values('BBB', 20, 1.0);
|
|||||||
select t1.a1, t1.a2, t2.a1, t2.a2 from t1,t2;
|
select t1.a1, t1.a2, t2.a1, t2.a2 from t1,t2;
|
||||||
a1 a2 a1 a2
|
a1 a2 a1 a2
|
||||||
10 aaa AAA 10
|
10 aaa AAA 10
|
||||||
10 NULL AAA 10
|
|
||||||
10 bbb AAA 10
|
|
||||||
20 zzz AAA 10
|
|
||||||
10 aaa BBB 20
|
10 aaa BBB 20
|
||||||
|
10 NULL AAA 10
|
||||||
10 NULL BBB 20
|
10 NULL BBB 20
|
||||||
|
10 bbb AAA 10
|
||||||
10 bbb BBB 20
|
10 bbb BBB 20
|
||||||
|
20 zzz AAA 10
|
||||||
20 zzz BBB 20
|
20 zzz BBB 20
|
||||||
select max(t1.a1), max(t2.a1) from t1, t2 where t2.a2=9;
|
select max(t1.a1), max(t2.a1) from t1, t2 where t2.a2=9;
|
||||||
max(t1.a1) max(t2.a1)
|
max(t1.a1) max(t2.a1)
|
||||||
|
657
mysql-test/r/greedy_optimizer.result
Normal file
657
mysql-test/r/greedy_optimizer.result
Normal file
@ -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;
|
@ -1393,8 +1393,8 @@ companynr companynr
|
|||||||
41 40
|
41 40
|
||||||
explain select distinct t2.companynr,t4.companynr from t2,t4 where t2.companynr=t4.companynr+1;
|
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
|
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 index; Using temporary
|
||||||
1 SIMPLE t4 index NULL PRIMARY 1 NULL 12 Using where; Using index
|
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;
|
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
|
fld1 companynr fld3 period
|
||||||
038008 37 reporters 1008
|
038008 37 reporters 1008
|
||||||
@ -2314,8 +2314,8 @@ 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
|
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 t3 system NULL NULL NULL NULL 0 const row not found
|
||||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2
|
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
|
||||||
1 SIMPLE t4 ALL id4 NULL NULL NULL 1 Using where
|
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
|
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;
|
left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
|
||||||
id1 id2 id3 id4 id44
|
id1 id2 id3 id4 id44
|
||||||
|
@ -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);
|
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
|
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
|
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 index
|
||||||
2 DEPENDENT SUBQUERY t3 index a a 5 NULL 3 Using where; Using index
|
2 DEPENDENT SUBQUERY t1 ref a a 10 func,test.t3.a 1000 Using where; Using index
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a))))
|
Note 1003 select high_priority test.t2.a AS `a` from test.t2 where <in_optimizer>(test.t2.a,<exists>(select 1 AS `Not_used` from test.t1 join test.t3 where ((test.t1.b = test.t3.a) and (<cache>(test.t2.a) = test.t1.a))))
|
||||||
insert into t1 values (3,31);
|
insert into t1 values (3,31);
|
||||||
|
313
mysql-test/t/greedy_optimizer.test
Normal file
313
mysql-test/t/greedy_optimizer.test
Normal file
@ -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;
|
@ -19,11 +19,20 @@
|
|||||||
#include "mysys_priv.h"
|
#include "mysys_priv.h"
|
||||||
#include <m_string.h>
|
#include <m_string.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If flag & 1 Return date and time
|
get date as string
|
||||||
If flag & 2 Return short date format YYMMDD
|
|
||||||
if flag & 4 Return time in HHMMDD format.
|
SYNOPSIS
|
||||||
*/
|
get_date()
|
||||||
|
to - string where date will be written
|
||||||
|
flag - format of date:
|
||||||
|
If flag & GETDATE_TIME Return date and time
|
||||||
|
If flag & GETDATE_SHORT_DATE Return short date format YYMMDD
|
||||||
|
If flag & GETDATE_HHMMSSTIME Return time in HHMMDD format.
|
||||||
|
If flag & GETDATE_GMT Date/time in GMT
|
||||||
|
If flag & GETDATE_FIXEDLENGTH Return fixed length date/time
|
||||||
|
date - for conversion
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
void get_date(register my_string to, int flag, time_t date)
|
void get_date(register my_string to, int flag, time_t date)
|
||||||
@ -36,27 +45,36 @@ void get_date(register my_string to, int flag, time_t date)
|
|||||||
|
|
||||||
skr=date ? (time_t) date : time((time_t*) 0);
|
skr=date ? (time_t) date : time((time_t*) 0);
|
||||||
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
|
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
|
||||||
localtime_r(&skr,&tm_tmp);
|
if (flag & GETDATE_GMT)
|
||||||
|
localtime_r(&skr,&tm_tmp);
|
||||||
|
else
|
||||||
|
gmtime_r(&skr,&tm_tmp);
|
||||||
start_time= &tm_tmp;
|
start_time= &tm_tmp;
|
||||||
#else
|
#else
|
||||||
start_time=localtime(&skr);
|
if (flag & GETDATE_GMT)
|
||||||
|
start_time= localtime(&skr);
|
||||||
|
else
|
||||||
|
gmtime(&skr,&tm_tmp);
|
||||||
#endif
|
#endif
|
||||||
if (flag & 2)
|
if (flag & GETDATE_SHORT_DATE)
|
||||||
sprintf(to,"%02d%02d%02d",
|
sprintf(to,"%02d%02d%02d",
|
||||||
start_time->tm_year % 100,
|
start_time->tm_year % 100,
|
||||||
start_time->tm_mon+1,
|
start_time->tm_mon+1,
|
||||||
start_time->tm_mday);
|
start_time->tm_mday);
|
||||||
else
|
else
|
||||||
sprintf(to,"%d-%02d-%02d",
|
sprintf(to, ((flag & GETDATE_FIXEDLENGTH) ?
|
||||||
|
"%4d-%02d-%02d" : "%d-%02d-%02d"),
|
||||||
start_time->tm_year+1900,
|
start_time->tm_year+1900,
|
||||||
start_time->tm_mon+1,
|
start_time->tm_mon+1,
|
||||||
start_time->tm_mday);
|
start_time->tm_mday);
|
||||||
if (flag & 1)
|
if (flag & GETDATE_DATE_TIME)
|
||||||
sprintf(strend(to)," %2d:%02d:%02d",
|
sprintf(strend(to),
|
||||||
|
((flag & GETDATE_FIXEDLENGTH) ?
|
||||||
|
" %02d:%02d:%02d" : " %2d:%02d:%02d"),
|
||||||
start_time->tm_hour,
|
start_time->tm_hour,
|
||||||
start_time->tm_min,
|
start_time->tm_min,
|
||||||
start_time->tm_sec);
|
start_time->tm_sec);
|
||||||
else if (flag & 4)
|
else if (flag & GETDATE_HHMMSSTIME)
|
||||||
sprintf(strend(to),"%02d%02d%02d",
|
sprintf(strend(to),"%02d%02d%02d",
|
||||||
start_time->tm_hour,
|
start_time->tm_hour,
|
||||||
start_time->tm_min,
|
start_time->tm_min,
|
||||||
|
@ -59,7 +59,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
|||||||
stacktrace.h sql_sort.h sql_cache.h set_var.h \
|
stacktrace.h sql_sort.h sql_cache.h set_var.h \
|
||||||
spatial.h gstream.h client_settings.h \
|
spatial.h gstream.h client_settings.h \
|
||||||
examples/ha_example.h \
|
examples/ha_example.h \
|
||||||
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h
|
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
|
||||||
|
parse_file.h
|
||||||
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
|
mysqld_SOURCES = sql_lex.cc sql_handler.cc \
|
||||||
item.cc item_sum.cc item_buff.cc item_func.cc \
|
item.cc item_sum.cc item_buff.cc item_func.cc \
|
||||||
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
|
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
|
||||||
@ -91,7 +92,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
|
|||||||
gstream.cc spatial.cc sql_help.cc protocol_cursor.cc \
|
gstream.cc spatial.cc sql_help.cc protocol_cursor.cc \
|
||||||
examples/ha_example.cc \
|
examples/ha_example.cc \
|
||||||
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
|
||||||
sp_cache.cc
|
sp_cache.cc parse_file.cc
|
||||||
gen_lex_hash_SOURCES = gen_lex_hash.cc
|
gen_lex_hash_SOURCES = gen_lex_hash.cc
|
||||||
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
|
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
|
||||||
|
|
||||||
|
@ -375,6 +375,7 @@ inline THD *_current_thd(void)
|
|||||||
#include "sql_list.h"
|
#include "sql_list.h"
|
||||||
#include "sql_map.h"
|
#include "sql_map.h"
|
||||||
#include "handler.h"
|
#include "handler.h"
|
||||||
|
#include "parse_file.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
#include "field.h" /* Field definitions */
|
#include "field.h" /* Field definitions */
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
@ -787,6 +788,8 @@ extern "C" pthread_handler_decl(handle_manager, arg);
|
|||||||
void print_where(COND *cond,const char *info);
|
void print_where(COND *cond,const char *info);
|
||||||
void print_cached_tables(void);
|
void print_cached_tables(void);
|
||||||
void TEST_filesort(SORT_FIELD *sortorder,uint s_length);
|
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
|
#endif
|
||||||
void mysql_print_status(THD *thd);
|
void mysql_print_status(THD *thd);
|
||||||
/* key.cc */
|
/* key.cc */
|
||||||
@ -854,6 +857,7 @@ extern char language[LIBLEN],reg_ext[FN_EXTLEN];
|
|||||||
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
||||||
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
|
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
|
||||||
extern char log_error_file[FN_REFLEN];
|
extern char log_error_file[FN_REFLEN];
|
||||||
|
extern double last_query_cost;
|
||||||
extern double log_10[32];
|
extern double log_10[32];
|
||||||
extern ulonglong log_10_int[20];
|
extern ulonglong log_10_int[20];
|
||||||
extern ulonglong keybuff_size;
|
extern ulonglong keybuff_size;
|
||||||
|
@ -312,6 +312,7 @@ ulong expire_logs_days = 0;
|
|||||||
ulong rpl_recovery_rank=0;
|
ulong rpl_recovery_rank=0;
|
||||||
ulong my_bind_addr; /* the address we bind to */
|
ulong my_bind_addr; /* the address we bind to */
|
||||||
volatile ulong cached_thread_count= 0;
|
volatile ulong cached_thread_count= 0;
|
||||||
|
double last_query_cost= -1; /* -1 denotes that no query was compiled yet */
|
||||||
|
|
||||||
double log_10[32]; /* 10 potences */
|
double log_10[32]; /* 10 potences */
|
||||||
ulonglong log_10_int[20]=
|
ulonglong log_10_int[20]=
|
||||||
@ -3775,7 +3776,9 @@ enum options_mysqld
|
|||||||
OPT_DATE_FORMAT,
|
OPT_DATE_FORMAT,
|
||||||
OPT_TIME_FORMAT,
|
OPT_TIME_FORMAT,
|
||||||
OPT_DATETIME_FORMAT,
|
OPT_DATETIME_FORMAT,
|
||||||
OPT_LOG_QUERIES_NOT_USING_INDEXES
|
OPT_LOG_QUERIES_NOT_USING_INDEXES,
|
||||||
|
OPT_PLAN_SEARCH_DEPTH,
|
||||||
|
OPT_HEURISTIC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -4400,6 +4403,11 @@ log and this option does nothing anymore.",
|
|||||||
"Use stopwords from this file instead of built-in list.",
|
"Use stopwords from this file instead of built-in list.",
|
||||||
(gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR,
|
(gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR,
|
||||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
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
|
#ifdef HAVE_INNOBASE_DB
|
||||||
{"innodb_mirrored_log_groups", OPT_INNODB_MIRRORED_LOG_GROUPS,
|
{"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.",
|
"Number of identical copies of log groups we keep for the database. Currently this should be set to 1.",
|
||||||
@ -4640,6 +4648,11 @@ The minimum value for this variable is 4096.",
|
|||||||
"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.",
|
"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,
|
(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, OS_FILE_LIMIT, 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,
|
{"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE,
|
||||||
"The size of the buffer that is allocated when preloading indexes",
|
"The size of the buffer that is allocated when preloading indexes",
|
||||||
(gptr*) &global_system_variables.preload_buff_size,
|
(gptr*) &global_system_variables.preload_buff_size,
|
||||||
@ -4930,6 +4943,7 @@ struct show_var_st status_vars[]= {
|
|||||||
SHOW_KEY_CACHE_LONG},
|
SHOW_KEY_CACHE_LONG},
|
||||||
{"Key_writes", (char*) &dflt_key_cache_var.global_cache_write,
|
{"Key_writes", (char*) &dflt_key_cache_var.global_cache_write,
|
||||||
SHOW_KEY_CACHE_LONG},
|
SHOW_KEY_CACHE_LONG},
|
||||||
|
{"Last_query_cost", (char*) &last_query_cost, SHOW_DOUBLE},
|
||||||
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
|
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
|
||||||
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
|
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
|
||||||
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
|
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
|
||||||
|
785
sql/parse_file.cc
Normal file
785
sql/parse_file.cc
Normal file
@ -0,0 +1,785 @@
|
|||||||
|
/* Copyright (C) 2004 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
// Text .frm files management routines
|
||||||
|
|
||||||
|
#include "mysql_priv.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <m_ctype.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
#include <my_dir.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
write string with escaping
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
write_escaped_string()
|
||||||
|
file - IO_CACHE for record
|
||||||
|
val_s - string for writing
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool
|
||||||
|
write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
|
||||||
|
{
|
||||||
|
char *eos= val_s->str + val_s->length;
|
||||||
|
char *ptr= val_s->str;
|
||||||
|
|
||||||
|
for (; ptr < eos; ptr++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Should be in sync with read_escaped_string() and
|
||||||
|
parse_quated_escaped_string()
|
||||||
|
*/
|
||||||
|
switch(*ptr) {
|
||||||
|
case '\\': // escape character
|
||||||
|
if (my_b_write(file, "\\\\", 2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case '\n': // parameter value delimiter
|
||||||
|
if (my_b_write(file, "\\n", 2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case '\0': // problem for some string processing utilites
|
||||||
|
if (my_b_write(file, "\\0", 2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case 26: // problem for windows utilites (Ctrl-Z)
|
||||||
|
if (my_b_write(file, "\\z", 2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case '\'': // list of string delimiter
|
||||||
|
if (my_b_write(file, "\\\'", 2))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (my_b_write(file, ptr, 1))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
write parameter value to IO_CACHE
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
write_parameter()
|
||||||
|
file pointer to IO_CACHE structure for writing
|
||||||
|
base pointer to data structure
|
||||||
|
parameter pointer to parameter descriptor
|
||||||
|
old_version for returning back old version number value
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static my_bool
|
||||||
|
write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
|
||||||
|
ulonglong *old_version)
|
||||||
|
{
|
||||||
|
char num_buf[20]; // buffer for numeric operations
|
||||||
|
// string for numeric operations
|
||||||
|
String num(num_buf, sizeof(num_buf), &my_charset_bin);
|
||||||
|
DBUG_ENTER("write_parameter");
|
||||||
|
|
||||||
|
switch (parameter->type) {
|
||||||
|
case FILE_OPTIONS_STRING:
|
||||||
|
{
|
||||||
|
LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);
|
||||||
|
if (my_b_write(file, val_s->str, val_s->length))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_ESTRING:
|
||||||
|
{
|
||||||
|
if (write_escaped_string(file, (LEX_STRING *)(base + parameter->offset)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_ULONGLONG:
|
||||||
|
{
|
||||||
|
num.set(*((ulonglong *)(base + parameter->offset)), &my_charset_bin);
|
||||||
|
if (my_b_write(file, num.ptr(), num.length()))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_REV:
|
||||||
|
{
|
||||||
|
ulonglong *val_i= (ulonglong *)(base + parameter->offset);
|
||||||
|
*old_version= (*val_i)++;
|
||||||
|
num.set(*val_i, &my_charset_bin);
|
||||||
|
if (my_b_write(file, num.ptr(), num.length()))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_TIMESTAMP:
|
||||||
|
{
|
||||||
|
/* string have to be allocated already */
|
||||||
|
LEX_STRING *val_s= (LEX_STRING *)(base + parameter->offset);
|
||||||
|
time_t tm= time(NULL);
|
||||||
|
|
||||||
|
get_date(val_s->str, GETDATE_DATE_TIME|GETDATE_GMT|GETDATE_FIXEDLENGTH,
|
||||||
|
tm);
|
||||||
|
val_s->length= PARSE_FILE_TIMESTAMPLENGTH;
|
||||||
|
if (my_b_write(file, val_s->str, PARSE_FILE_TIMESTAMPLENGTH))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_STRLIST:
|
||||||
|
{
|
||||||
|
List_iterator_fast<LEX_STRING> it(*((List<LEX_STRING>*)
|
||||||
|
(base + parameter->offset)));
|
||||||
|
bool first= 1;
|
||||||
|
LEX_STRING *str;
|
||||||
|
while ((str= it++))
|
||||||
|
{
|
||||||
|
num.set((ulonglong)str->length, &my_charset_bin);
|
||||||
|
// ',' after string to detect list continuation
|
||||||
|
if ((!first && my_b_write(file, " ", 1)) ||
|
||||||
|
my_b_write(file, "\'", 1) ||
|
||||||
|
my_b_write(file, str->str, str->length) ||
|
||||||
|
my_b_write(file, "\'", 1))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
first= 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0); // never should happened
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
write new .frm
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
sql_create_definition_file()
|
||||||
|
dir directory where put .frm
|
||||||
|
file .frm file name
|
||||||
|
type .frm type string (VIEW, TABLE)
|
||||||
|
base base address for parameter reading (structure like
|
||||||
|
TABLE)
|
||||||
|
parameters parameters description
|
||||||
|
max_versions number of versions to save
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool
|
||||||
|
sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
|
||||||
|
const LEX_STRING *type,
|
||||||
|
gptr base, File_option *parameters,
|
||||||
|
uint max_versions)
|
||||||
|
{
|
||||||
|
File handler;
|
||||||
|
IO_CACHE file;
|
||||||
|
char path[FN_REFLEN+1]; // +1 to put temporary file name for sure
|
||||||
|
ulonglong old_version= ULONGLONG_MAX;
|
||||||
|
int path_end;
|
||||||
|
DBUG_ENTER("sql_create_definition_file");
|
||||||
|
DBUG_PRINT("enter", ("Dir: %s, file: %s, base 0x%lx",
|
||||||
|
dir->str, file_name->str, (ulong) base));
|
||||||
|
|
||||||
|
fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME);
|
||||||
|
path_end= strlen(path);
|
||||||
|
|
||||||
|
// temporary file name
|
||||||
|
path[path_end]='~';
|
||||||
|
path[path_end+1]= '\0';
|
||||||
|
if ((handler= my_create(path, CREATE_MODE, O_RDWR | O_TRUNC,
|
||||||
|
MYF(MY_WME))) <= 0)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_io_cache(&file, handler, 0, SEQ_READ_APPEND, 0L, 0, MYF(MY_WME)))
|
||||||
|
goto err_w_file;
|
||||||
|
|
||||||
|
// write header (file signature)
|
||||||
|
if (my_b_write(&file, "TYPE=", 5) ||
|
||||||
|
my_b_write(&file, type->str, type->length) ||
|
||||||
|
my_b_write(&file, "\n", 1))
|
||||||
|
goto err_w_file;
|
||||||
|
|
||||||
|
// write parameters to temporary file
|
||||||
|
for (File_option *param= parameters; param->name.str; param++)
|
||||||
|
{
|
||||||
|
if (my_b_write(&file, param->name.str, param->name.length) ||
|
||||||
|
my_b_write(&file, "=", 1) ||
|
||||||
|
write_parameter(&file, base, param, &old_version) ||
|
||||||
|
my_b_write(&file, "\n", 1))
|
||||||
|
goto err_w_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_io_cache(&file))
|
||||||
|
goto err_w_file;
|
||||||
|
|
||||||
|
if (my_close(handler, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// archive copies management
|
||||||
|
path[path_end]='\0';
|
||||||
|
if (!access(path, F_OK))
|
||||||
|
{
|
||||||
|
if (old_version != ULONGLONG_MAX && max_versions != 0)
|
||||||
|
{
|
||||||
|
// save buckup
|
||||||
|
char path_arc[FN_REFLEN];
|
||||||
|
// backup old version
|
||||||
|
char path_to[FN_REFLEN];
|
||||||
|
|
||||||
|
// check archive directory existence
|
||||||
|
fn_format(path_arc, "arc", dir->str, "", MY_UNPACK_FILENAME);
|
||||||
|
if (access(path_arc, F_OK))
|
||||||
|
{
|
||||||
|
if (my_mkdir(path_arc, 0777, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lld",
|
||||||
|
path_arc, file_name->str, old_version);
|
||||||
|
if (my_rename(path, path_to, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove very old version
|
||||||
|
if (old_version > max_versions)
|
||||||
|
{
|
||||||
|
my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lld",
|
||||||
|
path_arc, file_name->str,
|
||||||
|
old_version - max_versions);
|
||||||
|
if (!access(path_arc, F_OK) && my_delete(path_to, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (my_delete(path, MYF(MY_WME))) // no backups
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// rename temporary file
|
||||||
|
char path_to[FN_REFLEN];
|
||||||
|
memcpy(path_to, path, path_end+1);
|
||||||
|
path[path_end]='~';
|
||||||
|
if (my_rename(path, path_to, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
err_w_cache:
|
||||||
|
end_io_cache(&file);
|
||||||
|
err_w_file:
|
||||||
|
my_close(handler, MYF(MY_WME));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Prepare frm to parse (read to memory)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
sql_parse_prepare()
|
||||||
|
file_name - path & filename to .frm file
|
||||||
|
mem_root - MEM_ROOT for buffer allocation
|
||||||
|
bad_format_errors - send errors on bad content
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
parser object
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
returned pointer + 1 will be type of .frm
|
||||||
|
*/
|
||||||
|
|
||||||
|
File_parser *
|
||||||
|
sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root,
|
||||||
|
bool bad_format_errors)
|
||||||
|
{
|
||||||
|
MY_STAT stat_info;
|
||||||
|
uint len;
|
||||||
|
char *end, *sign;
|
||||||
|
File_parser *parser;
|
||||||
|
File file;
|
||||||
|
DBUG_ENTER("sql__parse_prepare");
|
||||||
|
|
||||||
|
if (!my_stat(file_name->str, &stat_info, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat_info.st_size > INT_MAX-1)
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_TOO_BIG_FILE, MYF(0), file_name->str);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(parser= new(mem_root) File_parser))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(parser->buff= alloc_root(mem_root, stat_info.st_size+1)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file= my_open(file_name->str, O_RDONLY | O_SHARE, MYF(MY_WME))) < 0)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((len= my_read(file, parser->buff, stat_info.st_size, MYF(MY_WME))) ==
|
||||||
|
MY_FILE_ERROR)
|
||||||
|
{
|
||||||
|
my_close(file, MYF(MY_WME));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (my_close(file, MYF(MY_WME)))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
end= parser->end= parser->buff + len;
|
||||||
|
*end= '\0'; // barriaer for more simple parsing
|
||||||
|
|
||||||
|
// 7 = 5 (TYPE=) + 1 (leter at least of type name) + 1 ('\n')
|
||||||
|
if (len < 7 ||
|
||||||
|
parser->buff[0] != 'T' ||
|
||||||
|
parser->buff[1] != 'Y' ||
|
||||||
|
parser->buff[2] != 'P' ||
|
||||||
|
parser->buff[3] != 'E' ||
|
||||||
|
parser->buff[4] != '=')
|
||||||
|
goto frm_error;
|
||||||
|
|
||||||
|
// skip signature;
|
||||||
|
parser->file_type.str= sign= parser->buff + 5;
|
||||||
|
while (*sign >= 'A' && *sign <= 'Z' && sign < end)
|
||||||
|
sign++;
|
||||||
|
if (*sign != '\n')
|
||||||
|
goto frm_error;
|
||||||
|
parser->file_type.length= sign - parser->file_type.str;
|
||||||
|
// EOS for file signature just for safety
|
||||||
|
*sign= '\0';
|
||||||
|
|
||||||
|
parser->start= sign + 1;
|
||||||
|
parser->content_ok= 1;
|
||||||
|
|
||||||
|
DBUG_RETURN(parser);
|
||||||
|
|
||||||
|
frm_error:
|
||||||
|
if (bad_format_errors)
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_BAD_HEADER, MYF(0), file_name->str);
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBUG_RETURN(parser); // upper level have to check parser->ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
parse LEX_STRING
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
parse_string()
|
||||||
|
ptr - pointer on string beginning
|
||||||
|
end - pointer on symbol after parsed string end (still owned
|
||||||
|
by buffer and can be accessed
|
||||||
|
mem_root - MEM_ROOT for parameter allocation
|
||||||
|
str - pointer on string, where results should be stored
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
# - pointer on symbol after string
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *
|
||||||
|
parse_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||||
|
{
|
||||||
|
// get string length
|
||||||
|
char *eol= strchr(ptr, '\n');
|
||||||
|
|
||||||
|
if (eol >= end)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
str->length= eol - ptr;
|
||||||
|
|
||||||
|
if (!(str->str= alloc_root(mem_root, str->length+1)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(str->str, ptr, str->length);
|
||||||
|
str->str[str->length]= '\0'; // just for safety
|
||||||
|
return eol+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
read escaped string from ptr to eol in already allocated str
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
parse_escaped_string()
|
||||||
|
ptr - pointer on string beginning
|
||||||
|
eol - pointer on character after end of string
|
||||||
|
str - target string
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool
|
||||||
|
read_escaped_string(char *ptr, char *eol, LEX_STRING *str)
|
||||||
|
{
|
||||||
|
char *write_pos= str->str;
|
||||||
|
|
||||||
|
for(; ptr < eol; ptr++, write_pos++)
|
||||||
|
{
|
||||||
|
char c= *ptr;
|
||||||
|
if (c == '\\')
|
||||||
|
{
|
||||||
|
ptr++;
|
||||||
|
if (ptr >= eol)
|
||||||
|
return TRUE;
|
||||||
|
/*
|
||||||
|
Should be in sync with write_escaped_string() and
|
||||||
|
parse_quated_escaped_string()
|
||||||
|
*/
|
||||||
|
switch(*ptr) {
|
||||||
|
case '\\':
|
||||||
|
*write_pos= '\\';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
*write_pos= '\n';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
*write_pos= '\0';
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
*write_pos= 26;
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
*write_pos= '\'';
|
||||||
|
default:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*write_pos= c;
|
||||||
|
}
|
||||||
|
str->str[str->length= write_pos-str->str]= '\0'; // just for safety
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
parse \n delimited escaped string
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
parse_escaped_string()
|
||||||
|
ptr - pointer on string beginning
|
||||||
|
end - pointer on symbol after parsed string end (still owned
|
||||||
|
by buffer and can be accessed
|
||||||
|
mem_root - MEM_ROOT for parameter allocation
|
||||||
|
str - pointer on string, where results should be stored
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
# - pointer on symbol after string
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *
|
||||||
|
parse_escaped_string(char *ptr, char *end, MEM_ROOT *mem_root, LEX_STRING *str)
|
||||||
|
{
|
||||||
|
char *eol= strchr(ptr, '\n');
|
||||||
|
|
||||||
|
if (eol == 0 || eol >= end ||
|
||||||
|
!(str->str= alloc_root(mem_root, (eol - ptr) + 1)) ||
|
||||||
|
read_escaped_string(ptr, eol, str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return eol+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
parse '' delimited escaped string
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
parse_escaped_string()
|
||||||
|
ptr - pointer on string beginning
|
||||||
|
end - pointer on symbol after parsed string end (still owned
|
||||||
|
by buffer and can be accessed
|
||||||
|
mem_root - MEM_ROOT for parameter allocation
|
||||||
|
str - pointer on string, where results should be stored
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - error
|
||||||
|
# - pointer on symbol after string
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *
|
||||||
|
parse_quated_escaped_string(char *ptr, char *end,
|
||||||
|
MEM_ROOT *mem_root, LEX_STRING *str)
|
||||||
|
{
|
||||||
|
char *eol;
|
||||||
|
uint result_len= 0;
|
||||||
|
bool escaped= 0;
|
||||||
|
|
||||||
|
// starting '
|
||||||
|
if (*(ptr++) != '\'')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// find ending '
|
||||||
|
for (eol= ptr; (*eol != '\'' || escaped) && eol < end; eol++)
|
||||||
|
{
|
||||||
|
if (!(escaped= (*eol == '\\' && !escaped)))
|
||||||
|
result_len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process string
|
||||||
|
if (eol >= end ||
|
||||||
|
!(str->str= alloc_root(mem_root, result_len + 1)) ||
|
||||||
|
read_escaped_string(ptr, eol, str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return eol+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
parse parameters
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
File_parser::parse()
|
||||||
|
base base address for parameter writing (structure like
|
||||||
|
TABLE)
|
||||||
|
mem_root MEM_ROOT for parameters allocation
|
||||||
|
parameters parameters description
|
||||||
|
required number of required parameters in above list
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - error
|
||||||
|
*/
|
||||||
|
|
||||||
|
my_bool
|
||||||
|
File_parser::parse(gptr base, MEM_ROOT *mem_root,
|
||||||
|
struct File_option *parameters, uint required)
|
||||||
|
{
|
||||||
|
uint first_param= 0, found= 0;
|
||||||
|
register char *ptr= start;
|
||||||
|
char *eol;
|
||||||
|
LEX_STRING *str;
|
||||||
|
MEM_ROOT *sql_mem;
|
||||||
|
List<LEX_STRING> *list;
|
||||||
|
bool change_mem;
|
||||||
|
DBUG_ENTER("File_parser::parse");
|
||||||
|
|
||||||
|
while (ptr < end && found < required)
|
||||||
|
{
|
||||||
|
char *line= ptr;
|
||||||
|
if (*ptr == '#')
|
||||||
|
{
|
||||||
|
// it is comment
|
||||||
|
if (!(ptr= strchr(ptr, '\n')))
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_EOF_IN_COMMENT, MYF(0), line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
File_option *parameter= parameters+first_param,
|
||||||
|
*parameters_end= parameters+required;
|
||||||
|
int len= 0;
|
||||||
|
for(; parameter < parameters_end; parameter++)
|
||||||
|
{
|
||||||
|
len= parameter->name.length;
|
||||||
|
// check length
|
||||||
|
if (len < (end-ptr) && ptr[len] != '=')
|
||||||
|
continue;
|
||||||
|
// check keyword
|
||||||
|
if (memcmp(parameter->name.str, ptr, len) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameter < parameters_end)
|
||||||
|
{
|
||||||
|
found++;
|
||||||
|
/*
|
||||||
|
if we found first parameter, start search from next parameter
|
||||||
|
next time.
|
||||||
|
(this small optimisation should work, because they should be
|
||||||
|
written in same order)
|
||||||
|
*/
|
||||||
|
if (parameter == parameters+first_param)
|
||||||
|
first_param++;
|
||||||
|
|
||||||
|
// get value
|
||||||
|
ptr+= (len+1);
|
||||||
|
switch (parameter->type) {
|
||||||
|
case FILE_OPTIONS_STRING:
|
||||||
|
{
|
||||||
|
if (!(ptr= parse_string(ptr, end, mem_root,
|
||||||
|
(LEX_STRING *)(base +
|
||||||
|
parameter->offset))))
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_ESTRING:
|
||||||
|
{
|
||||||
|
if (!(ptr= parse_escaped_string(ptr, end, mem_root,
|
||||||
|
(LEX_STRING *)
|
||||||
|
(base + parameter->offset))))
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_ULONGLONG:
|
||||||
|
case FILE_OPTIONS_REV:
|
||||||
|
if (!(eol= strchr(ptr, '\n')))
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
*eol= '\0';
|
||||||
|
*((ulonglong*)(base + parameter->offset))= atoll(ptr);
|
||||||
|
*eol= '\n';
|
||||||
|
ptr= eol+1;
|
||||||
|
break;
|
||||||
|
case FILE_OPTIONS_TIMESTAMP:
|
||||||
|
{
|
||||||
|
/* string have to be allocated already */
|
||||||
|
LEX_STRING *val= (LEX_STRING *)(base + parameter->offset);
|
||||||
|
/* yyyy-mm-dd HH:MM:SS = 19(PARSE_FILE_TIMESTAMPLENGTH) characters */
|
||||||
|
if (ptr[PARSE_FILE_TIMESTAMPLENGTH] != '\n')
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
memcpy(val->str, ptr, PARSE_FILE_TIMESTAMPLENGTH);
|
||||||
|
val->str[val->length= PARSE_FILE_TIMESTAMPLENGTH]= '\0';
|
||||||
|
ptr+= (PARSE_FILE_TIMESTAMPLENGTH+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FILE_OPTIONS_STRLIST:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TODO: remove play with mem_root, when List will be able
|
||||||
|
to store MEM_ROOT* pointer for list elements allocation
|
||||||
|
*/
|
||||||
|
sql_mem= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
|
||||||
|
list= (List<LEX_STRING>*)(base + parameter->offset);
|
||||||
|
if ((change_mem= (sql_mem != mem_root)))
|
||||||
|
{
|
||||||
|
change_mem= 1;
|
||||||
|
my_pthread_setspecific_ptr(THR_MALLOC, mem_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
list->empty();
|
||||||
|
// list parsing
|
||||||
|
while (ptr < end)
|
||||||
|
{
|
||||||
|
if (!(str= (LEX_STRING*)alloc_root(mem_root,
|
||||||
|
sizeof(LEX_STRING))) ||
|
||||||
|
list->push_back(str))
|
||||||
|
goto list_err;
|
||||||
|
if(!(ptr= parse_quated_escaped_string(ptr, end, mem_root, str)))
|
||||||
|
goto list_err_w_message;
|
||||||
|
switch (*ptr) {
|
||||||
|
case '\n':
|
||||||
|
goto end_of_list;
|
||||||
|
case ' ':
|
||||||
|
// we cant go over buffer bounds, because we have \0 at the end
|
||||||
|
ptr++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto list_err_w_message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end_of_list:
|
||||||
|
if (*(ptr++) != '\n')
|
||||||
|
goto list_err;
|
||||||
|
|
||||||
|
if (change_mem)
|
||||||
|
my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
|
||||||
|
break;
|
||||||
|
|
||||||
|
list_err_w_message:
|
||||||
|
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
|
||||||
|
parameter->name.str, line);
|
||||||
|
list_err:
|
||||||
|
if (change_mem)
|
||||||
|
my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
DBUG_ASSERT(0); // never should happened
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// skip unknown parameter
|
||||||
|
if (!(ptr= strchr(ptr, '\n')))
|
||||||
|
{
|
||||||
|
my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0),
|
||||||
|
line);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
68
sql/parse_file.h
Normal file
68
sql/parse_file.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* -*- C++ -*- */
|
||||||
|
/* Copyright (C) 2004 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
|
#ifndef _PARSE_FILE_H_
|
||||||
|
#define _PARSE_FILE_H_
|
||||||
|
|
||||||
|
#define PARSE_FILE_TIMESTAMPLENGTH 19
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FILE_OPTIONS_STRING, /* String (LEX_STRING) */
|
||||||
|
FILE_OPTIONS_ESTRING, /* Escaped string (LEX_STRING) */
|
||||||
|
FILE_OPTIONS_ULONGLONG, /* ulonglong parapeter (ulonglong) */
|
||||||
|
FILE_OPTIONS_REV, /* Revision version number (ulonglong) */
|
||||||
|
FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be
|
||||||
|
allocated with length 20 (19+1) */
|
||||||
|
FILE_OPTIONS_STRLIST /* list of strings (List<char*>) */
|
||||||
|
} file_opt_type;
|
||||||
|
|
||||||
|
struct File_option
|
||||||
|
{
|
||||||
|
const LEX_STRING name; /* Name of the option */
|
||||||
|
int offset; /* offset to base address of value */
|
||||||
|
enum file_opt_type type; /* Option type */
|
||||||
|
};
|
||||||
|
|
||||||
|
class File_parser;
|
||||||
|
File_parser *sql_parse_prepare(const LEX_STRING *file_name,
|
||||||
|
MEM_ROOT *mem_root);
|
||||||
|
|
||||||
|
my_bool
|
||||||
|
sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
|
||||||
|
const LEX_STRING *type,
|
||||||
|
gptr base, File_option *parameters, uint versions);
|
||||||
|
|
||||||
|
class File_parser: public Sql_alloc
|
||||||
|
{
|
||||||
|
char *buff, *start, *end;
|
||||||
|
LEX_STRING file_type;
|
||||||
|
my_bool content_ok;
|
||||||
|
public:
|
||||||
|
File_parser() :buff(0), start(0), end(0), content_ok(0)
|
||||||
|
{ file_type.str= 0; file_type.length= 0; }
|
||||||
|
|
||||||
|
my_bool ok() { return content_ok; }
|
||||||
|
LEX_STRING *type() { return &file_type; }
|
||||||
|
my_bool parse(gptr base, MEM_ROOT *mem_root,
|
||||||
|
struct File_option *parameters, uint required);
|
||||||
|
|
||||||
|
friend File_parser *sql_parse_prepare(const LEX_STRING *file_name,
|
||||||
|
MEM_ROOT *mem_root,
|
||||||
|
bool bad_format_errors);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _PARSE_FILE_H_ */
|
@ -160,6 +160,7 @@ sys_var_str sys_ft_boolean_syntax("ft_boolean_syntax",
|
|||||||
sys_update_ftb_syntax,
|
sys_update_ftb_syntax,
|
||||||
sys_default_ftb_syntax,
|
sys_default_ftb_syntax,
|
||||||
ft_boolean_syntax);
|
ft_boolean_syntax);
|
||||||
|
sys_var_thd_ulong sys_heuristic("heuristic", &SV::heuristic);
|
||||||
sys_var_str sys_init_connect("init_connect", 0,
|
sys_var_str sys_init_connect("init_connect", 0,
|
||||||
sys_update_init_connect,
|
sys_update_init_connect,
|
||||||
sys_default_init_connect,0);
|
sys_default_init_connect,0);
|
||||||
@ -262,6 +263,8 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
|
|||||||
0, fix_net_retry_count);
|
0, fix_net_retry_count);
|
||||||
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
|
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
|
||||||
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
|
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
|
||||||
|
sys_var_thd_ulong sys_plan_search_depth("plan_search_depth",
|
||||||
|
&SV::plan_search_depth);
|
||||||
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
|
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
|
||||||
&SV::preload_buff_size);
|
&SV::preload_buff_size);
|
||||||
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
|
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
|
||||||
@ -488,6 +491,7 @@ sys_var *sys_variables[]=
|
|||||||
&sys_ft_boolean_syntax,
|
&sys_ft_boolean_syntax,
|
||||||
&sys_foreign_key_checks,
|
&sys_foreign_key_checks,
|
||||||
&sys_group_concat_max_len,
|
&sys_group_concat_max_len,
|
||||||
|
&sys_heuristic,
|
||||||
&sys_identity,
|
&sys_identity,
|
||||||
&sys_init_connect,
|
&sys_init_connect,
|
||||||
&sys_init_slave,
|
&sys_init_slave,
|
||||||
@ -536,6 +540,7 @@ sys_var *sys_variables[]=
|
|||||||
&sys_net_write_timeout,
|
&sys_net_write_timeout,
|
||||||
&sys_new_mode,
|
&sys_new_mode,
|
||||||
&sys_old_passwords,
|
&sys_old_passwords,
|
||||||
|
&sys_plan_search_depth,
|
||||||
&sys_preload_buff_size,
|
&sys_preload_buff_size,
|
||||||
&sys_pseudo_thread_id,
|
&sys_pseudo_thread_id,
|
||||||
&sys_query_alloc_block_size,
|
&sys_query_alloc_block_size,
|
||||||
@ -812,6 +817,8 @@ struct show_var_st init_vars[]= {
|
|||||||
{"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR},
|
{"version_compile_machine", (char*) MACHINE_TYPE, SHOW_CHAR},
|
||||||
{sys_os.name, (char*) &sys_os, SHOW_SYS},
|
{sys_os.name, (char*) &sys_os, SHOW_SYS},
|
||||||
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
|
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
|
||||||
|
{sys_heuristic.name, (char*) &sys_heuristic, SHOW_SYS},
|
||||||
|
{sys_plan_search_depth.name,(char*) &sys_plan_search_depth, SHOW_SYS},
|
||||||
{NullS, NullS, SHOW_LONG}
|
{NullS, NullS, SHOW_LONG}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -345,3 +345,8 @@ character-set=latin2
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -339,3 +339,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -347,3 +347,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -341,3 +341,8 @@ character-set=latin7
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -348,3 +348,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=greek
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=latin2
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=ujis
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=euckr
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -340,3 +340,8 @@ character-set=latin2
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -337,3 +337,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -340,3 +340,8 @@ character-set=latin2
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=koi8r
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s' (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: '%-.64s')"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
@ -330,3 +330,8 @@ character-set=cp1250
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -344,3 +344,8 @@ character-set=latin2
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -338,3 +338,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -336,3 +336,8 @@ character-set=latin1
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"Configuration file '%-.64s' is too big"
|
||||||
|
"Malformed file type header in file '%-.64s'"
|
||||||
|
"Unexpected end of file during parsing comment '%-.64s'"
|
||||||
|
"Error during parsing parameter '%-.64s' (line: '%-.64s')"
|
||||||
|
"Unexpected end of file during skipping unknown parameter '%-.64s'"
|
||||||
|
@ -341,3 +341,8 @@ character-set=koi8u
|
|||||||
"Variable or condition declaration after cursor or handler declaration"
|
"Variable or condition declaration after cursor or handler declaration"
|
||||||
"Cursor declaration after handler declaration"
|
"Cursor declaration after handler declaration"
|
||||||
"Case not found for CASE statement"
|
"Case not found for CASE statement"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ʀ<EFBFBD><C6A6><EFBFBD><EFBFBD>æ<EFBFBD><C3A6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
"<22><>צ<EFBFBD><D7A6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD>̦ '%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD>Ħ<EFBFBD><C4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ˦<><CBA6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҧ '%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD>Ц<EFBFBD><D0A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Φ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s' (<28><><EFBFBD><EFBFBD><EFBFBD>: '%-.64s')"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD>Ħ<EFBFBD><C4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ˦<><CBA6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>¦ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>צ<EFBFBD><D7A6><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
|
@ -392,6 +392,8 @@ struct system_variables
|
|||||||
ulong table_type;
|
ulong table_type;
|
||||||
ulong tmp_table_size;
|
ulong tmp_table_size;
|
||||||
ulong tx_isolation;
|
ulong tx_isolation;
|
||||||
|
ulong heuristic;
|
||||||
|
ulong plan_search_depth;
|
||||||
/* Determines which non-standard SQL behaviour should be enabled */
|
/* Determines which non-standard SQL behaviour should be enabled */
|
||||||
ulong sql_mode;
|
ulong sql_mode;
|
||||||
ulong default_week_format;
|
ulong default_week_format;
|
||||||
|
@ -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 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,
|
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
|
||||||
table_map used_tables);
|
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,
|
static void find_best(JOIN *join,table_map rest_tables,uint index,
|
||||||
double record_count,double read_time);
|
double record_count,double read_time);
|
||||||
static uint cache_record_length(JOIN *join,uint index);
|
static uint cache_record_length(JOIN *join,uint index);
|
||||||
@ -2002,7 +2020,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||||||
if (join->const_tables != join->tables)
|
if (join->const_tables != join->tables)
|
||||||
{
|
{
|
||||||
optimize_keyuse(join, keyuse_array);
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -2579,7 +2597,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)
|
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
|
||||||
@ -2647,16 +2665,952 @@ 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
|
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");
|
KEYUSE *best_key= 0;
|
||||||
join->best_read=DBL_MAX;
|
uint best_max_key_part= 0;
|
||||||
find_best(join,rest_tables, join->const_tables,1.0,0.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 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)
|
||||||
|
{
|
||||||
|
/* 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;
|
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;
|
||||||
|
if (thd->killed) // Abort
|
||||||
|
return;
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
|
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
|
||||||
double read_time)
|
double read_time)
|
||||||
|
@ -116,6 +116,7 @@ typedef struct st_join_table {
|
|||||||
typedef struct st_position /* Used in find_best */
|
typedef struct st_position /* Used in find_best */
|
||||||
{
|
{
|
||||||
double records_read;
|
double records_read;
|
||||||
|
double read_time;
|
||||||
JOIN_TAB *table;
|
JOIN_TAB *table;
|
||||||
KEYUSE *key;
|
KEYUSE *key;
|
||||||
} POSITION;
|
} POSITION;
|
||||||
@ -133,8 +134,9 @@ typedef struct st_rollup
|
|||||||
class JOIN :public Sql_alloc
|
class JOIN :public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
JOIN_TAB *join_tab,**best_ref,**map2table;
|
JOIN_TAB *join_tab,**best_ref;
|
||||||
JOIN_TAB *join_tab_save; //saved join_tab for subquery reexecution
|
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;
|
TABLE **table,**all_tables,*sort_by_table;
|
||||||
uint tables,const_tables;
|
uint tables,const_tables;
|
||||||
uint send_group_parts;
|
uint send_group_parts;
|
||||||
|
@ -1845,6 +1845,11 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
|
|||||||
end= strend(pos);
|
end= strend(pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SHOW_DOUBLE:
|
||||||
|
{
|
||||||
|
end= buff + sprintf(buff, "%f", *(double*) value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
/* First group - functions relying on CTX */
|
/* First group - functions relying on CTX */
|
||||||
case SHOW_SSL_CTX_SESS_ACCEPT:
|
case SHOW_SSL_CTX_SESS_ACCEPT:
|
||||||
|
@ -232,6 +232,102 @@ TEST_join(JOIN *join)
|
|||||||
DBUG_VOID_RETURN;
|
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
|
#endif
|
||||||
|
|
||||||
typedef struct st_debug_lock
|
typedef struct st_debug_lock
|
||||||
|
@ -167,8 +167,8 @@ typedef struct st_known_date_time_format {
|
|||||||
enum SHOW_TYPE
|
enum SHOW_TYPE
|
||||||
{
|
{
|
||||||
SHOW_UNDEF,
|
SHOW_UNDEF,
|
||||||
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL,
|
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_DOUBLE,
|
||||||
SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
|
SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
|
||||||
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
|
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
|
||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
|
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
|
||||||
|
Reference in New Issue
Block a user