mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Change optimizer_switch from no_xxx to xxx=on/xx=off.
This commit is contained in:
@ -1392,11 +1392,46 @@ WHERE
|
||||
`TESTID`='' AND `UCCHECK`='';
|
||||
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;
|
||||
@@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);
|
||||
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),
|
||||
@ -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
|
||||
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';
|
||||
set optimizer_switch='default,index_merge=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_union=off';
|
||||
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='';
|
||||
set optimizer_switch=default;
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_sort_union=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_union=off';
|
||||
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='';
|
||||
set optimizer_switch=default;
|
||||
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';
|
||||
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);
|
||||
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
|
||||
@ -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'
|
||||
from t0 A, t0 B, t0 C, t0 D where D.a<5;
|
||||
This should be intersect:
|
||||
set optimizer_switch='';
|
||||
set optimizer_switch=default;
|
||||
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';
|
||||
set optimizer_switch='default,index_merge=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_intersection=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_union=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_sort_union=off';
|
||||
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='';
|
||||
set optimizer_switch=default;
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_intersection=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_union=off';
|
||||
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
|
||||
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
|
||||
drop table t0, t1;
|
||||
|
@ -21,7 +21,47 @@ let $merge_table_support= 1;
|
||||
--source include/index_merge_ror_cpk.inc
|
||||
|
||||
--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 #
|
||||
select @@optimizer_switch;
|
||||
|
||||
@ -40,39 +80,39 @@ from t0 A, t0 B, t0 C;
|
||||
explain select * from t1 where a=1 or b=1;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
--echo This will use sort-union:
|
||||
set optimizer_switch='';
|
||||
set optimizer_switch=default;
|
||||
explain select * from t1 where a<1 or b <1;
|
||||
|
||||
--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;
|
||||
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
alter table t1 add d int, add key(d);
|
||||
update t1 set d=a;
|
||||
|
||||
--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);
|
||||
|
||||
--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);
|
||||
|
||||
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'
|
||||
from t0 A, t0 B, t0 C, t0 D where D.a<5;
|
||||
|
||||
--echo This should be intersect:
|
||||
set optimizer_switch='';
|
||||
set optimizer_switch=default;
|
||||
explain select * from t1 where a=10 and b=10;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
--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;
|
||||
|
||||
# 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='';
|
||||
set optimizer_switch=default;
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_intersection=off';
|
||||
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';
|
||||
set optimizer_switch='default,index_merge_union=off';
|
||||
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,11 +523,18 @@ protected:
|
||||
#define MODE_NO_ENGINE_SUBSTITUTION (MODE_HIGH_NOT_PRECEDENCE*2)
|
||||
#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
|
||||
/* @@optimizer_switch flags. These must be in sync with optimizer_switch_typelib */
|
||||
#define OPTIMIZER_SWITCH_INDEX_MERGE 1
|
||||
#define OPTIMIZER_SWITCH_INDEX_MERGE_UNION 2
|
||||
#define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION 4
|
||||
#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
|
||||
@ -1831,6 +1838,10 @@ extern enum_field_types agg_field_type(Item **items, uint nitems);
|
||||
/* strfunc.cc */
|
||||
ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs,
|
||||
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,
|
||||
bool part_match);
|
||||
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,"",
|
||||
|
||||
static const char *optimizer_switch_names[]=
|
||||
{
|
||||
"no_index_merge","no_index_merge_union","no_index_merge_sort_union",
|
||||
"no_index_merge_intersection", NullS
|
||||
"index_merge","index_merge_union","index_merge_sort_union",
|
||||
"index_merge_intersection", "default", 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
|
||||
sizeof("index_merge") - 1,
|
||||
sizeof("index_merge_union") - 1,
|
||||
sizeof("index_merge_sort_union") - 1,
|
||||
sizeof("index_merge_intersection") - 1,
|
||||
sizeof("default") - 1
|
||||
};
|
||||
TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"",
|
||||
optimizer_switch_names,
|
||||
@ -7657,6 +7658,7 @@ static int mysql_init_variables(void)
|
||||
*/
|
||||
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 */
|
||||
#ifndef DBUG_OFF
|
||||
default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
|
||||
@ -8252,12 +8254,22 @@ mysqld_get_one_option(int optid,
|
||||
}
|
||||
case OPT_OPTIMIZER_SWITCH:
|
||||
{
|
||||
bool not_used;
|
||||
char *error= 0;
|
||||
uint error_len= 0;
|
||||
optimizer_switch_str= argument;
|
||||
global_system_variables.optimizer_switch=
|
||||
find_bit_type_or_exit(argument, &optimizer_switch_typelib, opt->name,
|
||||
&error);
|
||||
(ulong)find_set_from_flags(&optimizer_switch_typelib,
|
||||
optimizer_switch_typelib.count,
|
||||
global_system_variables.optimizer_switch,
|
||||
global_system_variables.optimizer_switch,
|
||||
argument, strlen(argument), NULL,
|
||||
&error, &error_len, ¬_used);
|
||||
if (error)
|
||||
{
|
||||
fprintf(stderr, "Invalid optimizer_switch flag: %s\n", error);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPT_ONE_THREAD:
|
||||
|
@ -2387,7 +2387,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
table deletes.
|
||||
*/
|
||||
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
|
||||
@ -2411,7 +2411,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
|
||||
}
|
||||
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. */
|
||||
SEL_IMERGE *imerge;
|
||||
@ -3778,7 +3778,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
disabled in @@optimizer_switch
|
||||
*/
|
||||
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;
|
||||
goto skip_to_ror_scan;
|
||||
@ -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",
|
||||
imerge_cost));
|
||||
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;
|
||||
}
|
||||
@ -3839,7 +3839,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
|
||||
build_ror_index_merge:
|
||||
if (!all_scans_ror_able ||
|
||||
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);
|
||||
|
||||
/* 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,
|
||||
DBUG_ENTER("get_best_ror_intersect");
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
@ -4703,7 +4703,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
||||
ROR_SCAN_INFO **ror_scans_end= tree->ror_scans_end;
|
||||
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);
|
||||
|
||||
for (ROR_SCAN_INFO **scan= tree->ror_scans; scan != ror_scans_end; ++scan)
|
||||
|
@ -3926,18 +3926,18 @@ 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);
|
||||
|
||||
int i;
|
||||
ulonglong bit;
|
||||
tmp.length(0);
|
||||
|
||||
for (uint i= 0; val; val>>= 1, i++)
|
||||
{
|
||||
if (val & 1)
|
||||
for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1)
|
||||
{
|
||||
tmp.append(optimizer_switch_typelib.type_names[i],
|
||||
optimizer_switch_typelib.type_lengths[i]);
|
||||
tmp.append('=');
|
||||
tmp.append((val & bit)? "on":"off");
|
||||
tmp.append(',');
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp.length())
|
||||
tmp.length(tmp.length() - 1); /* trim the trailing comma */
|
||||
@ -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)
|
||||
global_system_variables.*offset= 0;
|
||||
else
|
||||
thd->variables.*offset= global_system_variables.*offset;
|
||||
bool not_used;
|
||||
char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
|
||||
uint error_len= 0;
|
||||
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, ¬_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 @@ public:
|
||||
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);
|
||||
bool check(THD *thd, set_var *var);
|
||||
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);
|
||||
|
182
sql/strfunc.cc
182
sql/strfunc.cc
@ -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
|
||||
(Same format as mysys/typelib.c)
|
||||
|
Reference in New Issue
Block a user