Commit cb6581d8 authored by Sergey Petrunia's avatar Sergey Petrunia

- Backport @@optimizer_switch support from 6.0

- Add support for setting it as a server commandline argument
- Add support for those switches:
  = no_index_merge
  = no_index_merge_union
  = no_index_merge_sort_union
  = no_index_merge_intersection

mysql-test/r/index_merge_myisam.result:
  Testcases for index_merge related @@optimizer_switch flags.
mysql-test/t/index_merge_myisam.test:
  Testcases for index_merge related @@optimizer_switch flags.
sql/set_var.cc:
  - Backport @@optimizer_switch support from 6.0
  - Add support for setting it as a server commandline argument
sql/sql_class.h:
  - Backport @@optimizer_switch support from 6.0
sql/sql_select.h:
  - Backport @@optimizer_switch support from 6.0
parent fecaef26
...@@ -1391,3 +1391,120 @@ WHERE ...@@ -1391,3 +1391,120 @@ WHERE
`RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND `RUNID`= '' AND `SUBMITNR`= '' AND `ORDERNR`='' AND `PROGRAMM`='' AND
`TESTID`='' AND `UCCHECK`=''; `TESTID`='' AND `UCCHECK`='';
drop table t1; drop table t1;
#
# @@optimizer_switch support and check
#
select @@optimizer_switch;
@@optimizer_switch
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int, filler char(100),
key(a), key(b), key(c));
insert into t1 select
A.a * B.a*10 + C.a*100,
A.a * B.a*10 + C.a*100,
A.a,
'filler'
from t0 A, t0 B, t0 C;
This should use union:
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where
This should use ALL:
set optimizer_switch='no_index_merge';
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use sort-union:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using sort_union(a,b); Using where
This will use sort-union:
set optimizer_switch='';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where
This should use ALL:
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use ALL:
set optimizer_switch='no_index_merge';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This will use sort-union:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where
alter table t1 add d int, add key(d);
update t1 set d=a;
This will use sort_union:
set optimizer_switch='';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c,d a,b 5,5 NULL 3 Using sort_union(a,b); Using where
And if we disable sort_union, union:
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c,d c,d 5,5 NULL 100 Using union(c,d); Using where
drop table t1;
create table t1 (
a int, b int, c int,
filler1 char(200), filler2 char(200),
key(a),key(b),key(c)
);
insert into t1
select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a, 'foo', 'bar'
from t0 A, t0 B, t0 C, t0 D where D.a<5;
This should be intersect:
set optimizer_switch='';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
No intersect when index_merge is disabled:
set optimizer_switch='no_index_merge';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 49 Using where
No intersect if it is disabled:
set optimizer_switch='no_index_merge_intersection';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 49 Using where
Do intersect when union was disabled
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
Do intersect when sort_union was disabled
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
This will use intersection inside a union:
set optimizer_switch='';
explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,b,c 5,5,5 NULL 6 Using union(intersect(a,b),c); Using where
Should be only union left:
set optimizer_switch='no_index_merge_intersection';
explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using union(a,c); Using where
This will switch to sort-union (intersection will be gone, too,
thats a known limitation:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using sort_union(a,c); Using where
set optimizer_switch=default;
show variables like 'optimizer_switch';
Variable_name Value
optimizer_switch
drop table t0, t1;
...@@ -19,3 +19,110 @@ let $merge_table_support= 1; ...@@ -19,3 +19,110 @@ let $merge_table_support= 1;
--source include/index_merge2.inc --source include/index_merge2.inc
--source include/index_merge_2sweeps.inc --source include/index_merge_2sweeps.inc
--source include/index_merge_ror_cpk.inc --source include/index_merge_ror_cpk.inc
--echo #
--echo # @@optimizer_switch support and check
--echo #
select @@optimizer_switch;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int, b int, c int, filler char(100),
key(a), key(b), key(c));
insert into t1 select
A.a * B.a*10 + C.a*100,
A.a * B.a*10 + C.a*100,
A.a,
'filler'
from t0 A, t0 B, t0 C;
--echo This should use union:
explain select * from t1 where a=1 or b=1;
--echo This should use ALL:
set optimizer_switch='no_index_merge';
explain select * from t1 where a=1 or b=1;
--echo This should use sort-union:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=1 or b=1;
--echo This will use sort-union:
set optimizer_switch='';
explain select * from t1 where a<1 or b <1;
--echo This should use ALL:
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where a<1 or b <1;
--echo This should use ALL:
set optimizer_switch='no_index_merge';
explain select * from t1 where a<1 or b <1;
--echo This will use sort-union:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a<1 or b <1;
alter table t1 add d int, add key(d);
update t1 set d=a;
--echo This will use sort_union:
set optimizer_switch='';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
--echo And if we disable sort_union, union:
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
drop table t1;
# Now test that intersection can be disabled
create table t1 (
a int, b int, c int,
filler1 char(200), filler2 char(200),
key(a),key(b),key(c)
);
insert into t1
select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a, 'foo', 'bar'
from t0 A, t0 B, t0 C, t0 D where D.a<5;
--echo This should be intersect:
set optimizer_switch='';
explain select * from t1 where a=10 and b=10;
--echo No intersect when index_merge is disabled:
set optimizer_switch='no_index_merge';
explain select * from t1 where a=10 and b=10;
--echo No intersect if it is disabled:
set optimizer_switch='no_index_merge_intersection';
explain select * from t1 where a=10 and b=10;
--echo Do intersect when union was disabled
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=10 and b=10;
--echo Do intersect when sort_union was disabled
set optimizer_switch='no_index_merge_sort_union';
explain select * from t1 where a=10 and b=10;
# Now take union-of-intersection and see how we can disable parts of it
--echo This will use intersection inside a union:
set optimizer_switch='';
explain select * from t1 where a=10 and b=10 or c=10;
--echo Should be only union left:
set optimizer_switch='no_index_merge_intersection';
explain select * from t1 where a=10 and b=10 or c=10;
--echo This will switch to sort-union (intersection will be gone, too,
--echo thats a known limitation:
set optimizer_switch='no_index_merge_union';
explain select * from t1 where a=10 and b=10 or c=10;
set optimizer_switch=default;
show variables like 'optimizer_switch';
drop table t0, t1;
...@@ -523,6 +523,12 @@ protected: ...@@ -523,6 +523,12 @@ protected:
#define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2) #define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2)
#define MODE_PAD_CHAR_TO_FULL_LENGTH (ULL(1) << 31) #define MODE_PAD_CHAR_TO_FULL_LENGTH (ULL(1) << 31)
/* @@optimizer_switch flags */
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE 1
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION 2
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_SORT_UNION 4
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_INTERSECT 8
/* /*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
use strictly more than 64 bits by adding one more define above, you should use strictly more than 64 bits by adding one more define above, you should
......
...@@ -297,6 +297,24 @@ static const unsigned int sql_mode_names_len[]= ...@@ -297,6 +297,24 @@ static const unsigned int sql_mode_names_len[]=
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
sql_mode_names, sql_mode_names,
(unsigned int *)sql_mode_names_len }; (unsigned int *)sql_mode_names_len };
static const char *optimizer_switch_names[]=
{
"no_index_merge","no_index_merge_union","no_index_merge_sort_union",
"no_index_merge_intersection", NullS
};
/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */
static const unsigned int optimizer_switch_names_len[]=
{
sizeof("no_index_merge") - 1,
sizeof("no_index_merge_union") - 1,
sizeof("ni_index_merge_sort_union") - 1,
sizeof("no_index_merge_intersection") - 1
};
TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
optimizer_switch_names,
(unsigned int *)optimizer_switch_names_len };
static const char *tc_heuristic_recover_names[]= static const char *tc_heuristic_recover_names[]=
{ {
"COMMIT", "ROLLBACK", NullS "COMMIT", "ROLLBACK", NullS
...@@ -362,6 +380,7 @@ static ulong max_used_connections; ...@@ -362,6 +380,7 @@ static ulong max_used_connections;
static ulong my_bind_addr; /**< the address we bind to */ static ulong my_bind_addr; /**< the address we bind to */
static volatile ulong cached_thread_count= 0; static volatile ulong cached_thread_count= 0;
static const char *sql_mode_str= "OFF"; static const char *sql_mode_str= "OFF";
static const char *optimizer_switch_str="";
static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr; static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr;
static char *opt_init_slave, *language_ptr, *opt_init_connect; static char *opt_init_slave, *language_ptr, *opt_init_connect;
static char *default_character_set_name; static char *default_character_set_name;
...@@ -5565,6 +5584,7 @@ enum options_mysqld ...@@ -5565,6 +5584,7 @@ enum options_mysqld
OPT_SYSDATE_IS_NOW, OPT_SYSDATE_IS_NOW,
OPT_OPTIMIZER_SEARCH_DEPTH, OPT_OPTIMIZER_SEARCH_DEPTH,
OPT_OPTIMIZER_PRUNE_LEVEL, OPT_OPTIMIZER_PRUNE_LEVEL,
OPT_OPTIMIZER_SWITCH,
OPT_UPDATABLE_VIEWS_WITH_LIMIT, OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_SP_AUTOMATIC_PRIVILEGES, OPT_SP_AUTOMATIC_PRIVILEGES,
OPT_MAX_SP_RECURSION_DEPTH, OPT_MAX_SP_RECURSION_DEPTH,
...@@ -6717,6 +6737,10 @@ The minimum value for this variable is 4096.", ...@@ -6717,6 +6737,10 @@ The minimum value for this variable is 4096.",
(uchar**) &global_system_variables.optimizer_search_depth, (uchar**) &global_system_variables.optimizer_search_depth,
(uchar**) &max_system_variables.optimizer_search_depth, (uchar**) &max_system_variables.optimizer_search_depth,
0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0},
{"optimizer_switch", OPT_OPTIMIZER_SWITCH,
"optimizer_switch=option[,option[,option...]] where option can be one of: no_index_merge, no_index_merge_union, no_index_merge_sort_union, no_index_merge_intersection",
(uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
{"plugin_dir", OPT_PLUGIN_DIR, {"plugin_dir", OPT_PLUGIN_DIR,
"Directory for plugins.", "Directory for plugins.",
(uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0, (uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0,
...@@ -8206,6 +8230,13 @@ mysqld_get_one_option(int optid, ...@@ -8206,6 +8230,13 @@ mysqld_get_one_option(int optid,
sql_mode); sql_mode);
break; break;
} }
case OPT_OPTIMIZER_SWITCH:
{
optimizer_switch_str= argument;
global_system_variables.optimizer_switch=
find_bit_type_or_exit(argument, &optimizer_switch_typelib, opt->name);
break;
}
case OPT_ONE_THREAD: case OPT_ONE_THREAD:
global_system_variables.thread_handling= global_system_variables.thread_handling=
SCHEDULER_ONE_THREAD_PER_CONNECTION; SCHEDULER_ONE_THREAD_PER_CONNECTION;
......
...@@ -2386,7 +2386,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2386,7 +2386,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
objects are not allowed so don't use ROR-intersection for objects are not allowed so don't use ROR-intersection for
table deletes. table deletes.
*/ */
if ((thd->lex->sql_command != SQLCOM_DELETE)) if ((thd->lex->sql_command != SQLCOM_DELETE) &&
!optimizer_flag(thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE))
{ {
/* /*
Get best non-covering ROR-intersection plan and prepare data for Get best non-covering ROR-intersection plan and prepare data for
...@@ -2409,6 +2410,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2409,6 +2410,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
} }
} }
else else
{
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE))
{ {
/* Try creating index_merge/ROR-union scan. */ /* Try creating index_merge/ROR-union scan. */
SEL_IMERGE *imerge; SEL_IMERGE *imerge;
...@@ -2431,6 +2434,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2431,6 +2434,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
best_trp= best_conj_trp; best_trp= best_conj_trp;
} }
} }
}
thd->mem_root= param.old_root; thd->mem_root= param.old_root;
...@@ -3767,11 +3771,19 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3767,11 +3771,19 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
"full table scan, bailing out")); "full table scan, bailing out"));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} }
if (all_scans_rors)
/*
If all scans happen to be ROR, proceed to generate a ROR-union plan (it's
guaranteed to be cheaper than non-ROR union), unless ROR-unions are
disabled in @@optimizer_switch
*/
if (all_scans_rors &&
!optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION))
{ {
roru_read_plans= (TABLE_READ_PLAN**)range_scans; roru_read_plans= (TABLE_READ_PLAN**)range_scans;
goto skip_to_ror_scan; goto skip_to_ror_scan;
} }
if (cpk_scan) if (cpk_scan)
{ {
/* /*
...@@ -3785,8 +3797,11 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3785,8 +3797,11 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records); imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records);
DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g", DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g",
imerge_cost)); imerge_cost));
if (imerge_cost > read_time) if (imerge_cost > read_time ||
optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_SORT_UNION))
{
goto build_ror_index_merge; goto build_ror_index_merge;
}
/* Add Unique operations cost */ /* Add Unique operations cost */
unique_calc_buff_size= unique_calc_buff_size=
...@@ -3822,7 +3837,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3822,7 +3837,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
} }
build_ror_index_merge: build_ror_index_merge:
if (!all_scans_ror_able || param->thd->lex->sql_command == SQLCOM_DELETE) if (!all_scans_ror_able ||
param->thd->lex->sql_command == SQLCOM_DELETE ||
optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION))
DBUG_RETURN(imerge_trp); DBUG_RETURN(imerge_trp);
/* Ok, it is possible to build a ROR-union, try it. */ /* Ok, it is possible to build a ROR-union, try it. */
...@@ -4495,7 +4512,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ...@@ -4495,7 +4512,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
double min_cost= DBL_MAX; double min_cost= DBL_MAX;
DBUG_ENTER("get_best_ror_intersect"); DBUG_ENTER("get_best_ror_intersect");
if ((tree->n_ror_scans < 2) || !param->table->file->stats.records) if ((tree->n_ror_scans < 2) || !param->table->file->stats.records ||
optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_INTERSECT))
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
/* /*
...@@ -4685,6 +4703,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, ...@@ -4685,6 +4703,9 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end; ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
DBUG_ENTER("get_best_covering_ror_intersect"); DBUG_ENTER("get_best_covering_ror_intersect");
if (optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_INTERSECT))
DBUG_RETURN(NULL);
for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan) for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan)
(*scan)->key_components= (*scan)->key_components=
param->table->key_info[(*scan)->keynr].key_parts; param->table->key_info[(*scan)->keynr].key_parts;
......
...@@ -468,6 +468,8 @@ static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prun ...@@ -468,6 +468,8 @@ static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prun
&SV::optimizer_prune_level); &SV::optimizer_prune_level);
static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth", static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth",
&SV::optimizer_search_depth); &SV::optimizer_search_depth);
static sys_var_thd_optimizer_switch sys_optimizer_switch(&vars, "optimizer_switch",
&SV::optimizer_switch);
static sys_var_const sys_pid_file(&vars, "pid_file", static sys_var_const sys_pid_file(&vars, "pid_file",
OPT_GLOBAL, SHOW_CHAR, OPT_GLOBAL, SHOW_CHAR,
(uchar*) pidfile_name); (uchar*) pidfile_name);
...@@ -3837,6 +3839,56 @@ ulong fix_sql_mode(ulong sql_mode) ...@@ -3837,6 +3839,56 @@ ulong fix_sql_mode(ulong sql_mode)
} }
bool
sys_var_thd_optimizer_switch::
symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
{
char buff[STRING_BUFFER_USUAL_SIZE*8];
String tmp(buff, sizeof(buff), &my_charset_latin1);
tmp.length(0);
for (uint i= 0; val; val>>= 1, i++)
{
if (val & 1)
{
tmp.append(optimizer_switch_typelib.type_names[i],
optimizer_switch_typelib.type_lengths[i]);
tmp.append(',');
}
}
if (tmp.length())
tmp.length(tmp.length() - 1); /* trim the trailing comma */
rep->str= thd->strmake(tmp.ptr(), tmp.length());
rep->length= rep->str ? tmp.length() : 0;
return rep->length != tmp.length();
}
uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
LEX_STRING opts;
ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
thd->variables.*offset);
(void) symbolic_mode_representation(thd, val, &opts);
return (uchar *) opts.str;
}
void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.*offset= 0;
else
thd->variables.*offset= global_system_variables.*offset;
}
/**************************************************************************** /****************************************************************************
Named list handling Named list handling
****************************************************************************/ ****************************************************************************/
......
...@@ -31,7 +31,7 @@ typedef struct system_variables SV; ...@@ -31,7 +31,7 @@ typedef struct system_variables SV;
typedef struct my_locale_st MY_LOCALE; typedef struct my_locale_st MY_LOCALE;
extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib, extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib,
slave_exec_mode_typelib; optimizer_switch_typelib, slave_exec_mode_typelib;
typedef int (*sys_check_func)(THD *, set_var *); typedef int (*sys_check_func)(THD *, set_var *);
typedef bool (*sys_update_func)(THD *, set_var *); typedef bool (*sys_update_func)(THD *, set_var *);
...@@ -532,6 +532,23 @@ public: ...@@ -532,6 +532,23 @@ public:
}; };
class sys_var_thd_optimizer_switch :public sys_var_thd_enum
{
public:
sys_var_thd_optimizer_switch(sys_var_chain *chain, const char *name_arg,
ulong SV::*offset_arg)
:sys_var_thd_enum(chain, name_arg, offset_arg, &optimizer_switch_typelib)
{}
bool check(THD *thd, set_var *var)
{
return check_set(thd, var, enum_names);
}
void set_default(THD *thd, enum_var_type type);
uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode,
LEX_STRING *rep);
};
extern void fix_sql_mode_var(THD *thd, enum_var_type type); extern void fix_sql_mode_var(THD *thd, enum_var_type type);
class sys_var_thd_sql_mode :public sys_var_thd_enum class sys_var_thd_sql_mode :public sys_var_thd_enum
......
...@@ -321,6 +321,8 @@ struct system_variables ...@@ -321,6 +321,8 @@ struct system_variables
ulong net_write_timeout; ulong net_write_timeout;
ulong optimizer_prune_level; ulong optimizer_prune_level;
ulong optimizer_search_depth; ulong optimizer_search_depth;
/* A bitmap for switching optimizations on/off */
ulong optimizer_switch;
ulong preload_buff_size; ulong preload_buff_size;
ulong profiling_history_size; ulong profiling_history_size;
ulong query_cache_type; ulong query_cache_type;
......
...@@ -729,3 +729,9 @@ bool error_if_full_join(JOIN *join); ...@@ -729,3 +729,9 @@ bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error); int report_error(TABLE *table, int error);
int safe_index_read(JOIN_TAB *tab); int safe_index_read(JOIN_TAB *tab);
COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value); COND *remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value);
inline bool optimizer_flag(THD *thd, uint flag)
{
return (thd->variables.optimizer_switch & flag);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment