Commit c7e44fdd authored by Sergey Petrunia's avatar Sergey Petrunia

@@optimizer_switch backport and change from no_xxx to xx=on|off: post-review fixes

parent d9921533
...@@ -1426,12 +1426,31 @@ set optimizer_switch='index_merge'; ...@@ -1426,12 +1426,31 @@ set optimizer_switch='index_merge';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge' ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge'
set optimizer_switch='on'; set optimizer_switch='on';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'on' ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'on'
set optimizer_switch='index_merge=on,index_merge=off';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off'
set optimizer_switch='index_merge_union=on,index_merge_union=default';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge_union=default'
set optimizer_switch='default,index_merge=on,index_merge=off,default';
ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'index_merge=off,default'
set optimizer_switch=default;
set optimizer_switch='index_merge=off,index_merge_union=off,default';
select @@optimizer_switch;
@@optimizer_switch
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=on
set optimizer_switch=default;
select @@global.optimizer_switch;
@@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
set @@global.optimizer_switch=default;
select @@global.optimizer_switch;
@@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on
# #
# Check index_merge's @@optimizer_switch flags # Check index_merge's @@optimizer_switch flags
# #
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,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),
......
...@@ -60,6 +60,25 @@ set optimizer_switch='index_merge'; ...@@ -60,6 +60,25 @@ set optimizer_switch='index_merge';
--error ER_WRONG_VALUE_FOR_VAR --error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='on'; set optimizer_switch='on';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge=on,index_merge=off';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='index_merge_union=on,index_merge_union=default';
--error ER_WRONG_VALUE_FOR_VAR
set optimizer_switch='default,index_merge=on,index_merge=off,default';
set optimizer_switch=default;
set optimizer_switch='index_merge=off,index_merge_union=off,default';
select @@optimizer_switch;
set optimizer_switch=default;
# Check setting defaults for global vars
select @@global.optimizer_switch;
set @@global.optimizer_switch=default;
select @@global.optimizer_switch;
--echo # --echo #
--echo # Check index_merge's @@optimizer_switch flags --echo # Check index_merge's @@optimizer_switch flags
--echo # --echo #
......
...@@ -530,6 +530,7 @@ class Default_object_creation_ctx : public Object_creation_ctx ...@@ -530,6 +530,7 @@ class Default_object_creation_ctx : public Object_creation_ctx
#define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT 8 #define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT 8
#define OPTIMIZER_SWITCH_LAST 16 #define OPTIMIZER_SWITCH_LAST 16
/* The following must be kept in sync with optimizer_switch_str in mysqld.cc */
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \
......
...@@ -383,7 +383,10 @@ static ulong max_used_connections; ...@@ -383,7 +383,10 @@ 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=""; /* Text representation for OPTIMIZER_SWITCH_DEFAULT */
static const char *optimizer_switch_str="index_merge=on,index_merge_union=on,"
"index_merge_sort_union=on,"
"index_merge_intersection=on";
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;
...@@ -6747,8 +6750,11 @@ The minimum value for this variable is 4096.", ...@@ -6747,8 +6750,11 @@ The minimum value for this variable is 4096.",
(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", 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", "optimizer_switch=option=val[,option=val...], where option={index_merge, "
(uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, 0, "index_merge_union, index_merge_sort_union, index_merge_intersection} and "
"val={on, off, default}.",
(uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG,
/*OPTIMIZER_SWITCH_DEFAULT*/0,
0, 0, 0, 0, 0}, 0, 0, 0, 0, 0},
{"plugin_dir", OPT_PLUGIN_DIR, {"plugin_dir", OPT_PLUGIN_DIR,
"Directory for plugins.", "Directory for plugins.",
...@@ -8267,7 +8273,10 @@ mysqld_get_one_option(int optid, ...@@ -8267,7 +8273,10 @@ mysqld_get_one_option(int optid,
&error, &error_len, &not_used); &error, &error_len, &not_used);
if (error) if (error)
{ {
fprintf(stderr, "Invalid optimizer_switch flag: %s\n", error); char buf[512];
char *cbuf= buf;
cbuf += my_snprintf(buf, 512, "Error in parsing optimizer_switch setting near %*s\n", error_len, error);
sql_perror(buf);
return 1; return 1;
} }
break; break;
......
...@@ -4003,6 +4003,14 @@ bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var) ...@@ -4003,6 +4003,14 @@ bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var)
} }
void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
global_system_variables.*offset= OPTIMIZER_SWITCH_DEFAULT;
else
thd->variables.*offset= global_system_variables.*offset;
}
/**************************************************************************** /****************************************************************************
Named list handling Named list handling
****************************************************************************/ ****************************************************************************/
......
...@@ -540,6 +540,7 @@ class sys_var_thd_optimizer_switch :public sys_var_thd_enum ...@@ -540,6 +540,7 @@ class sys_var_thd_optimizer_switch :public sys_var_thd_enum
: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);
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);
......
...@@ -106,7 +106,24 @@ static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, ...@@ -106,7 +106,24 @@ static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1,
/* /*
Given a string, find the first field_separator char, minding the charset Parse a TYPELIB name from the buffer
SYNOPSIS
parse_name()
lib Set of names to scan for.
strpos INOUT Start of the buffer (updated to point to the next
character after the name)
end End of the buffer
cs Charset used in the buffer
DESCRIPTION
Parse a TYPELIB name from the buffer. The buffer is assumed to contain
one of the names specified in the TYPELIB, followed by comma, '=', or
end of the buffer.
RETURN
0 No matching name
>0 Offset+1 in typelib for matched name
*/ */
static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, static uint parse_name(TYPELIB *lib, const char **strpos, const char *end,
...@@ -133,7 +150,7 @@ static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, ...@@ -133,7 +150,7 @@ static uint parse_name(TYPELIB *lib, const char **strpos, const char *end,
for (; pos != end && *pos != '=' && *pos !=',' ; pos++); for (; pos != end && *pos != '=' && *pos !=',' ; pos++);
uint var_len= (uint) (pos - start); uint var_len= (uint) (pos - start);
/* Determine which flag it is*/ /* Determine which flag it is */
uint find= cs ? find_type2(lib, start, var_len, cs) : uint find= cs ? find_type2(lib, start, var_len, cs) :
find_type(lib, start, var_len, (bool) 0); find_type(lib, start, var_len, (bool) 0);
*strpos= pos; *strpos= pos;
...@@ -164,7 +181,7 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs ...@@ -164,7 +181,7 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs
/* /*
Parse a string representation of set of flags Parse and apply a set of flag assingments
SYNOPSIS SYNOPSIS
find_set_from_flags() find_set_from_flags()
...@@ -173,10 +190,11 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs ...@@ -173,10 +190,11 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs
cur_set Current set of flags (start from this state) cur_set Current set of flags (start from this state)
default_set Default set of flags (use this for assign-default default_set Default set of flags (use this for assign-default
keyword and flag=default assignments) keyword and flag=default assignments)
str String representation (see below) str String to be parsed
length Length of the above length Length of the string
cs Charset used for the string cs String charset
err_pos OUT If error, set to point to start of wrong set string err_pos OUT If error, set to point to start of wrong set string
NULL on success
err_len OUT If error, set to the length 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 set_warning OUT TRUE <=> Some string in set couldn't be used
...@@ -186,13 +204,17 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs ...@@ -186,13 +204,17 @@ static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs
param_name1=value1,param_name2=value2,... param_name1=value1,param_name2=value2,...
where the names are specified in the TYPELIB, and each value can be where the names are specified in the TYPELIB, and each value can be
either 'on','off', or 'default'. Besides param=val assignments, we either 'on','off', or 'default'. Setting the same name twice is not
support "default" keyword (keyword #default_name in the typelib) which allowed.
means assign everything the default.
Besides param=val assignments, we support the "default" keyword (keyword
#default_name in the typelib). It can be used one time, if specified it
causes us to build the new set over the default_set rather than cur_set
value.
RETURN RETURN
FALSE Ok Parsed set value if (*errpos == NULL)
TRUE Error Otherwise undefined
*/ */
ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, ulonglong find_set_from_flags(TYPELIB *lib, uint default_name,
...@@ -202,71 +224,69 @@ ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, ...@@ -202,71 +224,69 @@ ulonglong find_set_from_flags(TYPELIB *lib, uint default_name,
{ {
CHARSET_INFO *strip= cs ? cs : &my_charset_latin1; CHARSET_INFO *strip= cs ? cs : &my_charset_latin1;
const char *end= str + strip->cset->lengthsp(strip, str, length); const char *end= str + strip->cset->lengthsp(strip, str, length);
ulonglong flags= cur_set; ulonglong flags_to_set= 0, flags_to_clear= 0;
bool set_defaults= 0;
*err_pos= 0; // No error yet *err_pos= 0; // No error yet
if (str != end) if (str != end)
{ {
const char *start= str; const char *start= str;
for (;;) for (;;)
{ {
my_wc_t chr;
const char *pos= start; const char *pos= start;
uint flag, value; uint flag_no, value;
if (!(flag= parse_name(lib, &pos, end, cs))) if (!(flag_no= parse_name(lib, &pos, end, cs)))
{ goto err;
*err_pos= (char*) start;
*err_len= pos - start;
*set_warning= 1;
break;
}
if (flag == default_name) if (flag_no == default_name)
{ {
flags= default_set; /* Using 'default' twice isn't allowed. */
if (set_defaults)
goto err;
set_defaults= TRUE;
} }
else else
{ {
if ((chr= get_next_char(&pos, end, cs)) != '=') ulonglong bit= ((longlong) 1 << (flag_no - 1));
{ /* parse the '=on|off|default' */
*err_pos= (char*)start; if ((flags_to_clear | flags_to_set) & bit ||
*err_len= pos - start; get_next_char(&pos, end, cs) != '=' ||
*set_warning= 1; !(value= parse_name(&on_off_default_typelib, &pos, end, cs)))
break;
}
if (!(value= parse_name(&on_off_default_typelib, &pos, end, cs)))
{ {
*err_pos= (char*) start; goto err;
*err_len= pos - start;
*set_warning= 1;
break;
} }
ulonglong bit= ((longlong) 1 << (flag - 1)); if (value == 1) // this is '=off'
if (value == 1) // this is 'xxx=off' flags_to_clear|= bit;
flags &= ~bit; else if (value == 2) // this is '=on'
else if (value == 2) // this is 'xxx=on' flags_to_set|= bit;
flags |= bit; else // this is '=default'
else // this is 'xxx=default'
{ {
bit= default_set & bit; if (default_set & bit)
flags= (flags & ~bit) | bit; flags_to_set|= bit;
else
flags_to_clear|= bit;
} }
} }
if (pos >= end) if (pos >= end)
break; break;
if ((chr= get_next_char(&pos, end, cs)) != ',')
{ if (get_next_char(&pos, end, cs) != ',')
*err_pos= (char*)start; goto err;
*err_len= pos - start;
*set_warning= 1;
}
start=pos; start=pos;
continue;
err:
*err_pos= (char*)start;
*err_len= end - start;
*set_warning= TRUE;
break;
} }
} }
return flags; ulonglong res= set_defaults? default_set : cur_set;
res|= flags_to_set;
res&= ~flags_to_clear;
return res;
} }
......
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