Commit d61f3264 authored by Sergey Petrunia's avatar Sergey Petrunia

Change optimizer_switch from no_xxx to xxx=on/xx=off.

mysql-test/r/index_merge_myisam.result:
  Testcases
mysql-test/t/index_merge_myisam.test:
  Testcases
sql/strfunc.cc:
  Change optimizer_switch from no_xxx to xxx=on/xx=off.
  - Add functions to parse the new syntax
parent 8527553a
...@@ -1392,11 +1392,46 @@ WHERE ...@@ -1392,11 +1392,46 @@ WHERE
`TESTID`='' AND `UCCHECK`=''; `TESTID`='' AND `UCCHECK`='';
drop table t1; drop table t1;
# #
# @@optimizer_switch support and check # Generic @@optimizer_switch tests (move those into a separate file if
# we get another @@optimizer_switch user)
# #
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
set optimizer_switch='index_merge=off,index_merge_union=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on
set optimizer_switch='index_merge_union=on';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
set optimizer_switch='default,index_merge_sort_union=off';
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on
set optimizer_switch=4;
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of '4'
set optimizer_switch=NULL;
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'NULL'
set optimizer_switch='default,index_merge';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge'
set optimizer_switch='index_merge=index_merge';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=index_merge'
set optimizer_switch='index_merge=on,but...';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'but...'
set optimizer_switch='index_merge=';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge='
set optimizer_switch='index_merge';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge'
set optimizer_switch='on';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'on'
#
# Check index_merge's @@optimizer_switch flags
#
select @@optimizer_switch;
@@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on
create table t0 (a int); create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); 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), create table t1 (a int, b int, c int, filler char(100),
...@@ -1412,44 +1447,44 @@ explain select * from t1 where a=1 or b=1; ...@@ -1412,44 +1447,44 @@ explain select * from t1 where a=1 or b=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 t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where 1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where
This should use ALL: This should use ALL:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a=1 or b=1; explain select * from t1 where a=1 or b=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 t1 ALL a,b NULL NULL NULL 1000 Using where 1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use sort-union: This should use sort-union:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=1 or b=1; explain select * from t1 where a=1 or b=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 t1 index_merge a,b a,b 5,5 NULL 2 Using sort_union(a,b); Using where 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: This will use sort-union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <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 t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where 1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where
This should use ALL: This should use ALL:
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <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 t1 ALL a,b NULL NULL NULL 1000 Using where 1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use ALL: This should use ALL:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <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 t1 ALL a,b NULL NULL NULL 1000 Using where 1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This will use sort-union: This will use sort-union:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <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 t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where 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); alter table t1 add d int, add key(d);
update t1 set d=a; update t1 set d=a;
This will use sort_union: This will use sort_union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4); 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 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 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: And if we disable sort_union, union:
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4); 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 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 1 SIMPLE t1 index_merge a,b,c,d c,d 5,5 NULL 100 Using union(c,d); Using where
...@@ -1463,48 +1498,48 @@ insert into t1 ...@@ -1463,48 +1498,48 @@ insert into t1
select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a, 'foo', 'bar' 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; from t0 A, t0 B, t0 C, t0 D where D.a<5;
This should be intersect: This should be intersect:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
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 t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where 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: No intersect when index_merge is disabled:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
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 t1 ref a,b a 5 const 49 Using where 1 SIMPLE t1 ref a,b a 5 const 49 Using where
No intersect if it is disabled: No intersect if it is disabled:
set optimizer_switch='no_index_merge_intersection'; set optimizer_switch='default,index_merge_intersection=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
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 t1 ref a,b a 5 const 49 Using where 1 SIMPLE t1 ref a,b a 5 const 49 Using where
Do intersect when union was disabled Do intersect when union was disabled
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
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 t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where 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 Do intersect when sort_union was disabled
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
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 t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where 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: This will use intersection inside a union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a=10 and b=10 or c=10; 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 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 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: Should be only union left:
set optimizer_switch='no_index_merge_intersection'; set optimizer_switch='default,index_merge_intersection=off';
explain select * from t1 where a=10 and b=10 or c=10; 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 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 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, This will switch to sort-union (intersection will be gone, too,
thats a known limitation: thats a known limitation:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=10 and b=10 or c=10; 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 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 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; set optimizer_switch=default;
show variables like 'optimizer_switch'; show variables like 'optimizer_switch';
Variable_name Value Variable_name Value
optimizer_switch optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
drop table t0, t1; drop table t0, t1;
...@@ -21,7 +21,47 @@ let $merge_table_support= 1; ...@@ -21,7 +21,47 @@ let $merge_table_support= 1;
--source include/index_merge_ror_cpk.inc --source include/index_merge_ror_cpk.inc
--echo # --echo #
--echo # @@optimizer_switch support and check --echo # Generic @@optimizer_switch tests (move those into a separate file if
--echo # we get another @@optimizer_switch user)
--echo #
select @@optimizer_switch;
set optimizer_switch='index_merge=off,index_merge_union=off';
select @@optimizer_switch;
set optimizer_switch='index_merge_union=on';
select @@optimizer_switch;
set optimizer_switch='default,index_merge_sort_union=off';
select @@optimizer_switch;
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch=4;
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch=NULL;
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='default,index_merge';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge=index_merge';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge=on,but...';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge=';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='on';
--echo #
--echo # Check index_merge's @@optimizer_switch flags
--echo # --echo #
select @@optimizer_switch; select @@optimizer_switch;
...@@ -40,39 +80,39 @@ from t0 A, t0 B, t0 C; ...@@ -40,39 +80,39 @@ from t0 A, t0 B, t0 C;
explain select * from t1 where a=1 or b=1; explain select * from t1 where a=1 or b=1;
--echo This should use ALL: --echo This should use ALL:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a=1 or b=1; explain select * from t1 where a=1 or b=1;
--echo This should use sort-union: --echo This should use sort-union:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=1 or b=1; explain select * from t1 where a=1 or b=1;
--echo This will use sort-union: --echo This will use sort-union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <1;
--echo This should use ALL: --echo This should use ALL:
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <1;
--echo This should use ALL: --echo This should use ALL:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <1;
--echo This will use sort-union: --echo This will use sort-union:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a<1 or b <1; explain select * from t1 where a<1 or b <1;
alter table t1 add d int, add key(d); alter table t1 add d int, add key(d);
update t1 set d=a; update t1 set d=a;
--echo This will use sort_union: --echo This will use sort_union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4); 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: --echo And if we disable sort_union, union:
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4); explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
drop table t1; drop table t1;
...@@ -89,40 +129,41 @@ select A.a+10*B.a, A.a+10*B.a, A.a+10*B.a+100*C.a, 'foo', 'bar' ...@@ -89,40 +129,41 @@ 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; from t0 A, t0 B, t0 C, t0 D where D.a<5;
--echo This should be intersect: --echo This should be intersect:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
--echo No intersect when index_merge is disabled: --echo No intersect when index_merge is disabled:
set optimizer_switch='no_index_merge'; set optimizer_switch='default,index_merge=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
--echo No intersect if it is disabled: --echo No intersect if it is disabled:
set optimizer_switch='no_index_merge_intersection'; set optimizer_switch='default,index_merge_intersection=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
--echo Do intersect when union was disabled --echo Do intersect when union was disabled
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
--echo Do intersect when sort_union was disabled --echo Do intersect when sort_union was disabled
set optimizer_switch='no_index_merge_sort_union'; set optimizer_switch='default,index_merge_sort_union=off';
explain select * from t1 where a=10 and b=10; explain select * from t1 where a=10 and b=10;
# Now take union-of-intersection and see how we can disable parts of it # Now take union-of-intersection and see how we can disable parts of it
--echo This will use intersection inside a union: --echo This will use intersection inside a union:
set optimizer_switch=''; set optimizer_switch=default;
explain select * from t1 where a=10 and b=10 or c=10; explain select * from t1 where a=10 and b=10 or c=10;
--echo Should be only union left: --echo Should be only union left:
set optimizer_switch='no_index_merge_intersection'; set optimizer_switch='default,index_merge_intersection=off';
explain select * from t1 where a=10 and b=10 or c=10; 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 This will switch to sort-union (intersection will be gone, too,
--echo thats a known limitation: --echo thats a known limitation:
set optimizer_switch='no_index_merge_union'; set optimizer_switch='default,index_merge_union=off';
explain select * from t1 where a=10 and b=10 or c=10; explain select * from t1 where a=10 and b=10 or c=10;
set optimizer_switch=default; set optimizer_switch=default;
show variables like 'optimizer_switch'; show variables like 'optimizer_switch';
drop table t0, t1; drop table t0, t1;
...@@ -523,11 +523,18 @@ class Default_object_creation_ctx : public Object_creation_ctx ...@@ -523,11 +523,18 @@ class Default_object_creation_ctx : public Object_creation_ctx
#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 */ /* @@optimizer_switch flags. These must be in sync with optimizer_switch_typelib */
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE 1 #define OPTIMIZER_SWITCH_INDEX_MERGE 1
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION 2 #define OPTIMIZER_SWITCH_INDEX_MERGE_UNION 2
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_SORT_UNION 4 #define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION 4
#define OPTIMIZER_SWITCH_NO_INDEX_MERGE_INTERSECT 8 #define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT 8
#define OPTIMIZER_SWITCH_LAST 16
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \
OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)
/* /*
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
...@@ -1831,6 +1838,10 @@ extern enum_field_types agg_field_type(Item **items, uint nitems); ...@@ -1831,6 +1838,10 @@ extern enum_field_types agg_field_type(Item **items, uint nitems);
/* strfunc.cc */ /* strfunc.cc */
ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs, ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
char **err_pos, uint *err_len, bool *set_warning); char **err_pos, uint *err_len, bool *set_warning);
ulonglong find_set_from_flags(TYPELIB *lib, uint default_set,
ulonglong cur_set, ulonglong default_set,
const char *str, uint length, CHARSET_INFO *cs,
char **err_pos, uint *err_len, bool *set_warning);
uint find_type(const TYPELIB *lib, const char *find, uint length, uint find_type(const TYPELIB *lib, const char *find, uint length,
bool part_match); bool part_match);
uint find_type2(const TYPELIB *lib, const char *find, uint length, uint find_type2(const TYPELIB *lib, const char *find, uint length,
......
...@@ -302,16 +302,17 @@ TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", ...@@ -302,16 +302,17 @@ TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
static const char *optimizer_switch_names[]= static const char *optimizer_switch_names[]=
{ {
"no_index_merge","no_index_merge_union","no_index_merge_sort_union", "index_merge","index_merge_union","index_merge_sort_union",
"no_index_merge_intersection", NullS "index_merge_intersection", "default", NullS
}; };
/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */ /* Corresponding defines are named OPTIMIZER_SWITCH_XXX */
static const unsigned int optimizer_switch_names_len[]= static const unsigned int optimizer_switch_names_len[]=
{ {
sizeof("no_index_merge") - 1, sizeof("index_merge") - 1,
sizeof("no_index_merge_union") - 1, sizeof("index_merge_union") - 1,
sizeof("ni_index_merge_sort_union") - 1, sizeof("index_merge_sort_union") - 1,
sizeof("no_index_merge_intersection") - 1 sizeof("index_merge_intersection") - 1,
sizeof("default") - 1
}; };
TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"", TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
optimizer_switch_names, optimizer_switch_names,
...@@ -7656,7 +7657,8 @@ static int mysql_init_variables(void) ...@@ -7656,7 +7657,8 @@ static int mysql_init_variables(void)
when collecting index statistics for MyISAM tables. when collecting index statistics for MyISAM tables.
*/ */
global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
global_system_variables.optimizer_switch= OPTIMIZER_SWITCH_DEFAULT;
/* Variables that depends on compile options */ /* Variables that depends on compile options */
#ifndef DBUG_OFF #ifndef DBUG_OFF
default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
...@@ -8252,12 +8254,22 @@ mysqld_get_one_option(int optid, ...@@ -8252,12 +8254,22 @@ mysqld_get_one_option(int optid,
} }
case OPT_OPTIMIZER_SWITCH: case OPT_OPTIMIZER_SWITCH:
{ {
bool not_used;
char *error= 0;
uint error_len= 0;
optimizer_switch_str= argument; optimizer_switch_str= argument;
global_system_variables.optimizer_switch= global_system_variables.optimizer_switch=
find_bit_type_or_exit(argument, &optimizer_switch_typelib, opt->name, (ulong)find_set_from_flags(&optimizer_switch_typelib,
&error); optimizer_switch_typelib.count,
if (error) global_system_variables.optimizer_switch,
return 1; global_system_variables.optimizer_switch,
argument, strlen(argument), NULL,
&error, &error_len, &not_used);
if (error)
{
fprintf(stderr, "Invalid optimizer_switch flag: %s\n", error);
return 1;
}
break; break;
} }
case OPT_ONE_THREAD: case OPT_ONE_THREAD:
......
...@@ -2387,7 +2387,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2387,7 +2387,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
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)) optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE))
{ {
/* /*
Get best non-covering ROR-intersection plan and prepare data for Get best non-covering ROR-intersection plan and prepare data for
...@@ -2411,7 +2411,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -2411,7 +2411,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
} }
else else
{ {
if (!optimizer_flag(thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE)) if (optimizer_flag(thd, OPTIMIZER_SWITCH_INDEX_MERGE))
{ {
/* Try creating index_merge/ROR-union scan. */ /* Try creating index_merge/ROR-union scan. */
SEL_IMERGE *imerge; SEL_IMERGE *imerge;
...@@ -3778,7 +3778,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3778,7 +3778,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
disabled in @@optimizer_switch disabled in @@optimizer_switch
*/ */
if (all_scans_rors && if (all_scans_rors &&
!optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION)) optimizer_flag(param->thd, OPTIMIZER_SWITCH_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;
...@@ -3798,7 +3798,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3798,7 +3798,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
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)) !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION))
{ {
goto build_ror_index_merge; goto build_ror_index_merge;
} }
...@@ -3839,7 +3839,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ...@@ -3839,7 +3839,7 @@ 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 || if (!all_scans_ror_able ||
param->thd->lex->sql_command == SQLCOM_DELETE || param->thd->lex->sql_command == SQLCOM_DELETE ||
optimizer_flag(param->thd, OPTIMIZER_SWITCH_NO_INDEX_MERGE_UNION)) !optimizer_flag(param->thd, OPTIMIZER_SWITCH_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. */
...@@ -4513,7 +4513,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ...@@ -4513,7 +4513,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
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)) !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT))
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
/* /*
...@@ -4703,7 +4703,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, ...@@ -4703,7 +4703,7 @@ 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)) if (!optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT))
DBUG_RETURN(NULL); 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)
......
...@@ -3926,17 +3926,17 @@ symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) ...@@ -3926,17 +3926,17 @@ symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
{ {
char buff[STRING_BUFFER_USUAL_SIZE*8]; char buff[STRING_BUFFER_USUAL_SIZE*8];
String tmp(buff, sizeof(buff), &my_charset_latin1); String tmp(buff, sizeof(buff), &my_charset_latin1);
int i;
ulonglong bit;
tmp.length(0); tmp.length(0);
for (uint i= 0; val; val>>= 1, i++) for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1)
{ {
if (val & 1) tmp.append(optimizer_switch_typelib.type_names[i],
{ optimizer_switch_typelib.type_lengths[i]);
tmp.append(optimizer_switch_typelib.type_names[i], tmp.append('=');
optimizer_switch_typelib.type_lengths[i]); tmp.append((val & bit)? "on":"off");
tmp.append(','); tmp.append(',');
}
} }
if (tmp.length()) if (tmp.length())
...@@ -3961,12 +3961,45 @@ uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type, ...@@ -3961,12 +3961,45 @@ uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type,
} }
void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type) /*
Check (and actually parse) string representation of @@optimizer_switch.
*/
bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var)
{ {
if (type == OPT_GLOBAL) bool not_used;
global_system_variables.*offset= 0; char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
else uint error_len= 0;
thd->variables.*offset= global_system_variables.*offset; String str(buff, sizeof(buff), system_charset_info), *res;
if (!(res= var->value->val_str(&str)))
{
strmov(buff, "NULL");
goto err;
}
if (res->length() == 0)
{
buff[0]= 0;
goto err;
}
var->save_result.ulong_value=
(ulong)find_set_from_flags(&optimizer_switch_typelib,
optimizer_switch_typelib.count,
thd->variables.optimizer_switch,
global_system_variables.optimizer_switch,
res->c_ptr(), res->length(), NULL,
&error, &error_len, &not_used);
if (error_len)
{
strmake(buff, error, min(sizeof(buff) - 1, error_len));
goto err;
}
return FALSE;
err:
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
return TRUE;
} }
......
...@@ -539,11 +539,7 @@ class sys_var_thd_optimizer_switch :public sys_var_thd_enum ...@@ -539,11 +539,7 @@ class sys_var_thd_optimizer_switch :public sys_var_thd_enum
ulong SV::*offset_arg) ulong SV::*offset_arg)
:sys_var_thd_enum(chain, name_arg, offset_arg, &optimizer_switch_typelib) :sys_var_thd_enum(chain, name_arg, offset_arg, &optimizer_switch_typelib)
{} {}
bool check(THD *thd, set_var *var) 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); uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode,
LEX_STRING *rep); LEX_STRING *rep);
......
...@@ -88,6 +88,188 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs, ...@@ -88,6 +88,188 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs,
} }
static const char *on_off_default_names[]=
{
"off","on","default", NullS
};
static const unsigned int on_off_default_names_len[]=
{
sizeof("off") - 1,
sizeof("on") - 1,
sizeof("default") - 1
};
static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1,
"", on_off_default_names,
(unsigned int *)on_off_default_names_len};
/*
Given a string, find the first field_separator char, minding the charset
*/
static uint parse_name(TYPELIB *lib, const char **strpos, const char *end,
CHARSET_INFO *cs)
{
const char *pos= *strpos;
const char *start= pos;
/* Find the length */
if (cs && cs->mbminlen > 1)
{
int mblen= 0;
for ( ; pos < end; pos+= mblen)
{
my_wc_t wc;
if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos,
(const uchar *) end)) < 1)
mblen= 1; // Not to hang on a wrong multibyte sequence
if (wc == (my_wc_t) '=' || wc == (my_wc_t) ',')
break;
}
}
else
for (; pos != end && *pos != '=' && *pos !=',' ; pos++);
uint var_len= (uint) (pos - start);
/* Determine which flag it is*/
uint find= cs ? find_type2(lib, start, var_len, cs) :
find_type(lib, start, var_len, (bool) 0);
*strpos= pos;
return find;
}
/* Read next character from the buffer in a charset-aware way */
static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs)
{
my_wc_t wc;
if (*pos == end)
return (my_wc_t)-1;
if (cs && cs->mbminlen > 1)
{
int mblen;
if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) *pos,
(const uchar *) end)) < 1)
mblen= 1; // Not to hang on a wrong multibyte sequence
*pos += mblen;
return wc;
}
else
return *((*pos)++);
}
/*
Parse a string representation of set of flags
SYNOPSIS
find_set_from_flags()
lib Flag names
default_name Number of "default" in the typelib
cur_set Current set of flags (start from this state)
default_set Default set of flags (use this for assign-default
keyword and flag=default assignments)
str String representation (see below)
length Length of the above
cs Charset used for the string
err_pos OUT If error, set to point to start of wrong set string
err_len OUT If error, set to the length of wrong set string
set_warning OUT TRUE <=> Some string in set couldn't be used
DESCRIPTION
Parse a set of flag assignments, that is, parse a string in form:
param_name1=value1,param_name2=value2,...
where the names are specified in the TYPELIB, and each value can be
either 'on','off', or 'default'. Besides param=val assignments, we
support "default" keyword (keyword #default_name in the typelib) which
means assign everything the default.
RETURN
FALSE Ok
TRUE Error
*/
ulonglong find_set_from_flags(TYPELIB *lib, uint default_name,
ulonglong cur_set, ulonglong default_set,
const char *str, uint length, CHARSET_INFO *cs,
char **err_pos, uint *err_len, bool *set_warning)
{
CHARSET_INFO *strip= cs ? cs : &my_charset_latin1;
const char *end= str + strip->cset->lengthsp(strip, str, length);
ulonglong flags= cur_set;
*err_pos= 0; // No error yet
if (str != end)
{
const char *start= str;
for (;;)
{
my_wc_t chr;
const char *pos= start;
uint flag, value;
if (!(flag= parse_name(lib, &pos, end, cs)))
{
*err_pos= (char*) start;
*err_len= pos - start;
*set_warning= 1;
break;
}
if (flag == default_name)
{
flags= default_set;
}
else
{
if ((chr= get_next_char(&pos, end, cs)) != '=')
{
*err_pos= (char*)start;
*err_len= pos - start;
*set_warning= 1;
break;
}
if (!(value= parse_name(&on_off_default_typelib, &pos, end, cs)))
{
*err_pos= (char*) start;
*err_len= pos - start;
*set_warning= 1;
break;
}
ulonglong bit= ((longlong) 1 << (flag - 1));
if (value == 1) // this is 'xxx=off'
flags &= ~bit;
else if (value == 2) // this is 'xxx=on'
flags |= bit;
else // this is 'xxx=default'
{
bit= default_set & bit;
flags= (flags & ~bit) | bit;
}
}
if (pos >= end)
break;
if ((chr= get_next_char(&pos, end, cs)) != ',')
{
*err_pos= (char*)start;
*err_len= pos - start;
*set_warning= 1;
}
start=pos;
}
}
return flags;
}
/* /*
Function to find a string in a TYPELIB Function to find a string in a TYPELIB
(Same format as mysys/typelib.c) (Same format as mysys/typelib.c)
......
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