3214 Guilhem Bichot 2010-09-27
WL4800_validate_json.py: detect non-unique keys.
Review comment: add a "feature" parameter to the constructors of
Opt_trace_object/array, and a system variable "optimizer_trace_features"
which allows to select what features to trace; replaces
optimizer_trace=skip_plan=off
@ mysql-test/include/optimizer_trace.inc
test filtering by feature
@ mysql-test/suite/sys_vars/t/optimizer_trace_features_basic.test
basic test for new system variable
@ unittest/gunit/opt_trace-t.cc
test filtering by feature
added:
mysql-test/suite/sys_vars/r/optimizer_trace_features_basic.result
mysql-test/suite/sys_vars/t/optimizer_trace_features_basic.test
modified:
WL4800_TODO.txt
WL4800_validate_json.py
mysql-test/include/optimizer_trace.inc
mysql-test/r/mysqld--help-notwin.result
mysql-test/r/optimizer_trace_no_prot.result
mysql-test/r/optimizer_trace_ps_prot.result
mysql-test/suite/sys_vars/r/optimizer_trace_basic.result
sql/opt_trace.cc
sql/opt_trace.h
sql/opt_trace2server.cc
sql/sql_class.h
sql/sql_select.cc
sql/sys_vars.cc
unittest/gunit/opt_trace-t.cc
3213 Guilhem Bichot 2010-09-24
review comment: renamed "ooa" to "structure" or "struct".
This may have made lines longer than 79 chars; I will fix them in a batch later
modified:
WL4800_TODO.txt
sql/opt_trace.cc
sql/opt_trace.h
unittest/gunit/opt_trace-t.cc
=== modified file 'WL4800_TODO.txt'
--- a/WL4800_TODO.txt 2010-09-24 14:09:24 +0000
+++ b/WL4800_TODO.txt 2010-09-27 08:00:25 +0000
@@ -42,7 +42,7 @@ I find a proper combination of client/se
the trace makes the server do wrong?). Review how escaping is done in
opt_trace.cc.
-Review comments:
-- parameter for filtering
+Review comments left:
- in doc, mention DUMPFILE instead of OUTFILE
+- more checks for non-unique keys?
=== modified file 'WL4800_validate_json.py'
--- a/WL4800_validate_json.py 2010-09-24 09:11:29 +0000
+++ b/WL4800_validate_json.py 2010-09-27 08:00:25 +0000
@@ -39,14 +39,28 @@ def check(trace, first_trace_line):
global retcode
s = "".join(trace)
try:
- json.loads(s)
+ parsed = json.loads(s)
except:
- print "error at line", first_trace_line
+ print "parse error at line", first_trace_line
print sys.exc_info()
print s
- retcode=1
- else:
- print "ok at line", first_trace_line
+ retcode = 1
+ print
+ return
+ # detect non-unique keys in one object, by counting
+ # number of quote symbols ("'): the json module outputs only
+ # one of the non-unique keys, making the number of " and '
+ # smaller compared to the input string.
+ before = s.count('"') + s.count("'")
+ str_parsed = str(parsed)
+ after = str_parsed.count('"') + str_parsed.count("'")
+ if (before != after):
+ print "non-unique keys at line %d (%d vs %d)" % (first_trace_line, before, after)
+ print s
+ retcode = 1
+ print
+ return
+ print "ok at line", first_trace_line
print
all = open(sys.argv[1]).readlines()
=== modified file 'mysql-test/include/optimizer_trace.inc'
--- a/mysql-test/include/optimizer_trace.inc 2010-09-24 09:11:29 +0000
+++ b/mysql-test/include/optimizer_trace.inc 2010-09-27 08:00:25 +0000
@@ -138,10 +138,14 @@ set @@session.optimizer_prune_level=0;
explain select * from t1,t2;
select * from information_schema.OPTIMIZER_TRACE;
# don't print plans:
-set optimizer_trace="skip_plan=on";
+select @@optimizer_trace_features;
+set @@optimizer_trace_features="greedy_search=off";
explain select * from t1,t2;
select * from information_schema.OPTIMIZER_TRACE;
-set optimizer_trace="skip_plan=off";
+set @@optimizer_trace_features="greedy_search=on,misc=off";
+explain select * from t1,t2;
+select * from information_schema.OPTIMIZER_TRACE;
+set @@optimizer_trace_features=default;
set @@session.optimizer_prune_level=default;
drop table t1, t2;
=== modified file 'mysql-test/r/mysqld--help-notwin.result'
--- a/mysql-test/r/mysqld--help-notwin.result 2010-09-18 16:25:43 +0000
+++ b/mysql-test/r/mysqld--help-notwin.result 2010-09-27 08:00:25 +0000
@@ -410,8 +410,14 @@ The following options may be given as th
--optimizer-trace=name
Controls tracing of the Optimizer:
optimizer_trace=option=val[,option=val...], where option
- is one of {enabled, end_marker, one_line, skip_plan} and
- val is one of {on, off, default}
+ is one of {enabled, end_marker, one_line} and val is one
+ of {on, off, default}
+ --optimizer-trace-features=name
+ Enables/disables tracing of selected features of the
+ Optimizer:
+ optimizer_trace_features=option=val[,option=val...],
+ where option is one of {misc, greedy_search} and val is
+ one of {on, off, default}
--optimizer-trace-limit=#
Maximum number of shown optimizer traces
--optimizer-trace-max-mem-size=#
@@ -863,6 +869,7 @@ optimizer-prune-level 1
optimizer-search-depth 62
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on,materialization=on,semijoin=on,loosescan=on,firstmatch=on,mrr=on,mrr_cost_based=off,index_condition_pushdown=on
optimizer-trace
+optimizer-trace-features misc=on,greedy_search=on
optimizer-trace-limit 1
optimizer-trace-max-mem-size 16384
optimizer-trace-offset -1
=== modified file 'mysql-test/r/optimizer_trace_no_prot.result'
--- a/mysql-test/r/optimizer_trace_no_prot.result 2010-09-24 09:11:29 +0000
+++ b/mysql-test/r/optimizer_trace_no_prot.result 2010-09-27 08:00:25 +0000
@@ -1882,7 +1882,10 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
}
] /* steps */
} 0 0
-set optimizer_trace="skip_plan=on";
+select @@optimizer_trace_features;
+@@optimizer_trace_features
+misc=on,greedy_search=on
+set @@optimizer_trace_features="greedy_search=off";
explain select * from t1,t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
@@ -1924,9 +1927,7 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
] /* records_estimation */
},
{
- "considered_execution_plans": [
- "..."
- ] /* considered_execution_plans */
+ "considered_execution_plans": "..."
},
{
"attaching_conditions_to_tables": {
@@ -1948,7 +1949,15 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
}
] /* steps */
} 0 0
-set optimizer_trace="skip_plan=off";
+set @@optimizer_trace_features="greedy_search=on,misc=off";
+explain select * from t1,t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using join buffer (BNL, regular buffers)
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE OS_MALLOC_ERROR
+0 0 0
+set @@optimizer_trace_features=default;
set @@session.optimizer_prune_level=default;
drop table t1, t2;
set @@optimizer_switch='semijoin=off';
@@ -4715,7 +4724,7 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
} 0 0
select @@optimizer_trace|
@@optimizer_trace
-enabled=off,end_marker=on,one_line=off,skip_plan=off
+enabled=off,end_marker=on,one_line=off
set optimizer_trace="enabled=on";
drop table optt;
drop function f1;
@@ -4962,7 +4971,7 @@ drop view v1;
select * from information_schema.SESSION_VARIABLES where
VARIABLE_NAME="optimizer_trace";
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_TRACE enabled=on,end_marker=on,one_line=off,skip_plan=off
+OPTIMIZER_TRACE enabled=on,end_marker=on,one_line=off
select * from information_schema.OPTIMIZER_TRACE;
QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE OS_MALLOC_ERROR
0 {
=== modified file 'mysql-test/r/optimizer_trace_ps_prot.result'
--- a/mysql-test/r/optimizer_trace_ps_prot.result 2010-09-24 09:11:29 +0000
+++ b/mysql-test/r/optimizer_trace_ps_prot.result 2010-09-27 08:00:25 +0000
@@ -1866,7 +1866,10 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
}
] /* steps */
} 0 0
-set optimizer_trace="skip_plan=on";
+select @@optimizer_trace_features;
+@@optimizer_trace_features
+misc=on,greedy_search=on
+set @@optimizer_trace_features="greedy_search=off";
explain select * from t1,t2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
@@ -1908,9 +1911,7 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
] /* records_estimation */
},
{
- "considered_execution_plans": [
- "..."
- ] /* considered_execution_plans */
+ "considered_execution_plans": "..."
},
{
"attaching_conditions_to_tables": {
@@ -1932,7 +1933,15 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
}
] /* steps */
} 0 0
-set optimizer_trace="skip_plan=off";
+set @@optimizer_trace_features="greedy_search=on,misc=off";
+explain select * from t1,t2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ALL NULL NULL NULL NULL 2
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using join buffer (BNL, regular buffers)
+select * from information_schema.OPTIMIZER_TRACE;
+QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE OS_MALLOC_ERROR
+0 0 0
+set @@optimizer_trace_features=default;
set @@session.optimizer_prune_level=default;
drop table t1, t2;
set @@optimizer_switch='semijoin=off';
@@ -4691,7 +4700,7 @@ QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_
} 0 0
select @@optimizer_trace|
@@optimizer_trace
-enabled=off,end_marker=on,one_line=off,skip_plan=off
+enabled=off,end_marker=on,one_line=off
set optimizer_trace="enabled=on";
drop table optt;
drop function f1;
@@ -4938,7 +4947,7 @@ drop view v1;
select * from information_schema.SESSION_VARIABLES where
VARIABLE_NAME="optimizer_trace";
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_TRACE enabled=on,end_marker=on,one_line=off,skip_plan=off
+OPTIMIZER_TRACE enabled=on,end_marker=on,one_line=off
select * from information_schema.OPTIMIZER_TRACE;
QUERY_ID TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE OS_MALLOC_ERROR
0 {
=== modified file 'mysql-test/suite/sys_vars/r/optimizer_trace_basic.result'
--- a/mysql-test/suite/sys_vars/r/optimizer_trace_basic.result 2010-05-24 18:38:10 +0000
+++ b/mysql-test/suite/sys_vars/r/optimizer_trace_basic.result 2010-09-27 08:00:25 +0000
@@ -1,45 +1,45 @@
SET @start_global_value = @@global.optimizer_trace;
SELECT @start_global_value;
@start_global_value
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
select @@global.optimizer_trace;
@@global.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
select @@session.optimizer_trace;
@@session.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
show global variables like 'optimizer_trace';
Variable_name Value
-optimizer_trace enabled=off,end_marker=off,one_line=off,skip_plan=off
+optimizer_trace enabled=off,end_marker=off,one_line=off
show session variables like 'optimizer_trace';
Variable_name Value
-optimizer_trace enabled=off,end_marker=off,one_line=off,skip_plan=off
+optimizer_trace enabled=off,end_marker=off,one_line=off
select * from information_schema.global_variables where variable_name='optimizer_trace';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_TRACE enabled=off,end_marker=off,one_line=off,skip_plan=off
+OPTIMIZER_TRACE enabled=off,end_marker=off,one_line=off
select * from information_schema.session_variables where variable_name='optimizer_trace';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_TRACE enabled=off,end_marker=off,one_line=off,skip_plan=off
+OPTIMIZER_TRACE enabled=off,end_marker=off,one_line=off
set global optimizer_trace=10;
select @@global.optimizer_trace;
@@global.optimizer_trace
-enabled=off,end_marker=on,one_line=off,skip_plan=on
+enabled=off,end_marker=on,one_line=off
set session optimizer_trace=10;
select @@session.optimizer_trace;
@@session.optimizer_trace
-enabled=off,end_marker=on,one_line=off,skip_plan=on
+enabled=off,end_marker=on,one_line=off
set global optimizer_trace=0;
select @@global.optimizer_trace;
@@global.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
set session optimizer_trace=0;
select @@session.optimizer_trace;
@@session.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
set session optimizer_trace=default;
select @@session.optimizer_trace;
@@session.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
set global optimizer_trace=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_trace'
set global optimizer_trace=1e1;
@@ -49,4 +49,4 @@ ERROR 42000: Variable 'optimizer_trace'
SET @@global.optimizer_trace = @start_global_value;
SELECT @@global.optimizer_trace;
@@global.optimizer_trace
-enabled=off,end_marker=off,one_line=off,skip_plan=off
+enabled=off,end_marker=off,one_line=off
=== added file 'mysql-test/suite/sys_vars/r/optimizer_trace_features_basic.result'
--- a/mysql-test/suite/sys_vars/r/optimizer_trace_features_basic.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/r/optimizer_trace_features_basic.result 2010-09-27 08:00:25 +0000
@@ -0,0 +1,52 @@
+SET @start_global_value = @@global.optimizer_trace_features;
+SELECT @start_global_value;
+@start_global_value
+misc=on,greedy_search=on
+select @@global.optimizer_trace_features;
+@@global.optimizer_trace_features
+misc=on,greedy_search=on
+select @@session.optimizer_trace_features;
+@@session.optimizer_trace_features
+misc=on,greedy_search=on
+show global variables like 'optimizer_trace_features';
+Variable_name Value
+optimizer_trace_features misc=on,greedy_search=on
+show session variables like 'optimizer_trace_features';
+Variable_name Value
+optimizer_trace_features misc=on,greedy_search=on
+select * from information_schema.global_variables where variable_name='optimizer_trace_features';
+VARIABLE_NAME VARIABLE_VALUE
+OPTIMIZER_TRACE_FEATURES misc=on,greedy_search=on
+select * from information_schema.session_variables where variable_name='optimizer_trace_features';
+VARIABLE_NAME VARIABLE_VALUE
+OPTIMIZER_TRACE_FEATURES misc=on,greedy_search=on
+set global optimizer_trace_features=2;
+select @@global.optimizer_trace_features;
+@@global.optimizer_trace_features
+misc=off,greedy_search=on
+set session optimizer_trace_features=2;
+select @@session.optimizer_trace_features;
+@@session.optimizer_trace_features
+misc=off,greedy_search=on
+set global optimizer_trace_features=0;
+select @@global.optimizer_trace_features;
+@@global.optimizer_trace_features
+misc=off,greedy_search=off
+set session optimizer_trace_features=0;
+select @@session.optimizer_trace_features;
+@@session.optimizer_trace_features
+misc=off,greedy_search=off
+set session optimizer_trace_features=default;
+select @@session.optimizer_trace_features;
+@@session.optimizer_trace_features
+misc=off,greedy_search=off
+set global optimizer_trace_features=1.1;
+ERROR 42000: Incorrect argument type to variable 'optimizer_trace_features'
+set global optimizer_trace_features=1e1;
+ERROR 42000: Incorrect argument type to variable 'optimizer_trace_features'
+set session optimizer_trace_features="foobar";
+ERROR 42000: Variable 'optimizer_trace_features' can't be set to the value of 'foobar'
+SET @@global.optimizer_trace_features = @start_global_value;
+SELECT @@global.optimizer_trace_features;
+@@global.optimizer_trace_features
+misc=on,greedy_search=on
=== added file 'mysql-test/suite/sys_vars/t/optimizer_trace_features_basic.test'
--- a/mysql-test/suite/sys_vars/t/optimizer_trace_features_basic.test 1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/sys_vars/t/optimizer_trace_features_basic.test 2010-09-27 08:00:25 +0000
@@ -0,0 +1,41 @@
+--source include/have_optimizer_trace.inc
+
+SET @start_global_value = @@global.optimizer_trace_features;
+SELECT @start_global_value;
+
+#
+# exists as global and session
+#
+select @@global.optimizer_trace_features;
+select @@session.optimizer_trace_features;
+show global variables like 'optimizer_trace_features';
+show session variables like 'optimizer_trace_features';
+select * from information_schema.global_variables where variable_name='optimizer_trace_features';
+select * from information_schema.session_variables where variable_name='optimizer_trace_features';
+
+#
+# show that it's writable
+#
+set global optimizer_trace_features=2;
+select @@global.optimizer_trace_features;
+set session optimizer_trace_features=2;
+select @@session.optimizer_trace_features;
+set global optimizer_trace_features=0;
+select @@global.optimizer_trace_features;
+set session optimizer_trace_features=0;
+select @@session.optimizer_trace_features;
+set session optimizer_trace_features=default;
+select @@session.optimizer_trace_features;
+
+#
+# incorrect assignments
+#
+--error ER_WRONG_TYPE_FOR_VAR
+set global optimizer_trace_features=1.1;
+--error ER_WRONG_TYPE_FOR_VAR
+set global optimizer_trace_features=1e1;
+--error ER_WRONG_VALUE_FOR_VAR
+set session optimizer_trace_features="foobar";
+
+SET @@global.optimizer_trace_features = @start_global_value;
+SELECT @@global.optimizer_trace_features;
=== modified file 'sql/opt_trace.cc'
--- a/sql/opt_trace.cc 2010-09-24 14:09:24 +0000
+++ b/sql/opt_trace.cc 2010-09-27 08:00:25 +0000
@@ -54,9 +54,10 @@ void Opt_trace_struct::syntax_error(cons
void Opt_trace_struct::do_construct(Opt_trace_stmt *stmt_arg,
- Opt_trace_struct *parent_arg,
- bool requires_key_arg,
- const char *key)
+ Opt_trace_struct *parent_arg,
+ bool requires_key_arg,
+ const char *key,
+ Opt_trace_context::feature_value feature)
{
saved_key= key;
requires_key= requires_key_arg;
@@ -69,6 +70,24 @@ void Opt_trace_struct::do_construct(Opt_
#ifndef DBUG_OFF
previous_key[0]= 0;
#endif
+ save_stmt_support_I_S=
+ stmt->support_I_S;
+ if (save_stmt_support_I_S &&
+ (feature & stmt->ctx->features) == 0)
+ {
+ /*
+ User requested no tracing for this structure's feature. We are entering
+ a disabled portion; put an ellipsis "..." to alert the user
+ */
+ if (stmt->current_struct != NULL)
+ {
+ if (key != NULL)
+ stmt->current_struct->add(key, "...");
+ else
+ stmt->current_struct->add("...");
+ }
+ stmt->support_I_S= false; // disable tracing for this struct and children
+ }
if (stmt->support_I_S)
{
const size_t alloced= stmt->buffer.alloced_length();
@@ -168,17 +187,19 @@ void Opt_trace_struct::do_destruct(void)
*/
stmt->current_struct= parent;
DBUG_ASSERT(parent == NULL || stmt == parent->stmt);
- if (!stmt->support_I_S)
- return;
- stmt->pop();
- stmt->next_line();
- stmt->buffer.append(brackets[requires_key + 2]);
- if (stmt->ctx->end_marker && saved_key != NULL)
- {
- stmt->buffer.append(" /* ");
- stmt->buffer.append(saved_key);
- stmt->buffer.append(" */");
+ if (stmt->support_I_S)
+ {
+ stmt->pop();
+ stmt->next_line();
+ stmt->buffer.append(brackets[requires_key + 2]);
+ if (stmt->ctx->end_marker && saved_key != NULL)
+ {
+ stmt->buffer.append(" /* ");
+ stmt->buffer.append(saved_key);
+ stmt->buffer.append(" */");
+ }
}
+ stmt->support_I_S= save_stmt_support_I_S;
}
@@ -301,9 +322,17 @@ Opt_trace_struct& Opt_trace_struct::do_a
const char *Opt_trace_context::flag_names[]=
{
- "enabled", "end_marker", "one_line", "skip_plan", "default", NullS
+ "enabled", "end_marker", "one_line", "default", NullS
+};
+
+const char *Opt_trace_context::feature_names[]=
+{
+ "misc", "greedy_search", "default", NullS
};
+const Opt_trace_context::feature_value Opt_trace_context::FEATURES_DEFAULT=
+ Opt_trace_context::feature_value(Opt_trace_context::MISC |
+ Opt_trace_context::GREEDY_SEARCH);
Opt_trace_context::Opt_trace_context(void):
oldest_stmt_to_show(NULL), newest_stmt_to_show(NULL), stmt_to_del(NULL),
@@ -457,7 +486,8 @@ bool Opt_trace_context::start(bool suppo
bool one_line_arg,
long offset_arg,
long limit_arg,
- ulong max_mem_size_arg)
+ ulong max_mem_size_arg,
+ feature_value features_arg)
{
DBUG_ENTER("Opt_trace_context::start");
/*
@@ -496,6 +526,7 @@ bool Opt_trace_context::start(bool suppo
offset= offset_arg;
limit= limit_arg;
max_mem_size= max_mem_size_arg;
+ features= features_arg;
}
/*
Decide whether to-be-created trace should support I_S.
=== modified file 'sql/opt_trace.h'
--- a/sql/opt_trace.h 2010-09-24 14:09:24 +0000
+++ b/sql/opt_trace.h 2010-09-27 08:00:25 +0000
@@ -332,6 +332,39 @@ class Opt_trace_context
public:
Opt_trace_context(void);
~Opt_trace_context(void);
+
+ /**
+ Flags' names for @@@@optimizer_trace variable of @c sys_vars.cc :
+ @li "enabled" = tracing enabled
+ @li "end_marker" = see parameter of @ref Opt_trace_context::start
+ @li "one_line"= see parameter of @ref Opt_trace_context::start
+ @li "default".
+ */
+ static const char *flag_names[];
+ /** Flags' numeric values for @@@@optimizer_trace variable */
+ enum flag_value {
+ FLAG_DEFAULT= 0, FLAG_ENABLED= 1, FLAG_END_MARKER= 2, FLAG_ONE_LINE= 4
+ };
+ /**
+ Features' names for @@@@optimizer_trace_features variable of
+ @c sys_vars.cc:
+ @li "misc" = anything unclassified
+ @li "greedy_search" = the greedy search for a plan
+ @li "default".
+ */
+ static const char *feature_names[];
+ /** Features' numeric values for @@@@optimizer_trace_features variable */
+ enum feature_value {
+ /**
+ Anything unclassified, including the top object (thus, by "inheritance
+ from parent", disabling MISC makes an empty trace).
+ */
+ MISC= 1,
+ GREEDY_SEARCH= 2 ///@todo range opt, join cache, semijoin...
+ /* if you add here, update FEATURES_DEFAULT! */
+ };
+ static const feature_value FEATURES_DEFAULT;
+
/**
Starts a new trace.
@param need_it_for_I_S should trace produce output suitable for
@@ -355,12 +388,14 @@ public:
@param limit limit for restricting trace production
@param max_mem_size maximum allowed for cumulated size of all
remembered traces
+ @param features only those optimizer features should be traced
@retval false ok
@retval true error (OOM)
*/
bool start(bool need_it_for_I_S, bool end_marker, bool one_line,
- long offset, long limit, ulong max_mem_size);
+ long offset, long limit, ulong max_mem_size,
+ feature_value features);
/** Ends the current trace */
void end(void);
/** Returns whether there is a current trace */
@@ -379,22 +414,6 @@ public:
*/
void reset(void);
- /**
- Flags' names for @@@@optimizer_trace variable of @c sys_vars.cc :
- @li "enabled" = tracing enabled
- @li "end_marker" = see parameter of @ref Opt_trace_context::start
- @li "one_line"= see parameter of @ref Opt_trace_context::start
- @li "skip_plan" = no tracing of plan search (mandatory when using many
- tables, due to combinatorial explosion in @c greedy_search())
- @li "default".
- */
- static const char *flag_names[];
- /** Flags' numeric values for @@@@optimizer_trace variable */
- enum flag_values {
- FLAG_DEFAULT= 0, FLAG_ENABLED= 1, FLAG_END_MARKER= 2, FLAG_ONE_LINE= 4,
- FLAG_SKIP_PLAN= 8
- };
-
private:
/**
@@ -454,6 +473,7 @@ private:
long offset; ///< copy of parameter of Opt_trace_context::start
long limit; ///< copy of parameter of Opt_trace_context::start
size_t max_mem_size; ///< copy of parameter of Opt_trace_context::start
+ feature_value features; ///< copy of parameter of Opt_trace_context::start
/** Whether the settings above may be changed for a new trace */
bool cannot_change_settings;
@@ -669,11 +689,13 @@ protected:
NULL otherwise. This pointer must remain constant and
valid until the object is destroyed (to support
@ref saved_key).
+ @param feature optimizer feature to which this objects belong
This constructor is never called directly, only from subclasses.
*/
Opt_trace_struct(Opt_trace_context *ctx_arg, bool requires_key,
- const char *key) :
+ const char *key,
+ Opt_trace_context::feature_value feature) :
started(false)
{
/* A first inlined test */
@@ -682,7 +704,7 @@ protected:
/* tracing enabled: must fully initialize the structure */
do_construct(ctx_arg->current_stmt_in_gen,
ctx_arg->current_stmt_in_gen->current_struct,
- requires_key, key);
+ requires_key, key, feature);
}
/*
Otherwise, just leave "started" to false, it marks that the structure is
@@ -862,7 +884,8 @@ private:
void do_construct(Opt_trace_stmt *stmt,
Opt_trace_struct *parent,
bool requires_key,
- const char *key);
+ const char *key,
+ Opt_trace_context::feature_value feature);
/** Really does destruction */
void do_destruct(void);
/** Really adds to the object. @sa add() */
@@ -950,6 +973,14 @@ private:
char previous_key[20];
#endif
+ /**
+ A structure may, because it belongs to a feature for which tracing is not
+ wanted, disable the statement's tracing; it will thus apply to all the
+ structure's children. When the structure is destroyed, it restores the
+ initial setting.
+ */
+ bool save_stmt_support_I_S;
+
/** opening and closing symbols for arrays ([])and objects ({}) */
static const char brackets[];
/** human-readable names of structure types */
@@ -971,15 +1002,25 @@ class Opt_trace_object: public Opt_trace
{
public:
/**
- Constructs an object. If a key is specified, the object is the value of a
- key/value pair (serves for adding the object to an object). Otherwise the
- object is just a value (serves for the single root object, or for adding
- the object to an array).
+ Constructs an object. Key is specified, so the object is the value of a
+ key/value pair.
+ @param ctx context for this object
+ @param key key
+ */
+ Opt_trace_object(Opt_trace_context *ctx, const char *key,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) :
+ Opt_trace_struct(ctx, true, key, feature) {}
+ /**
+ Constructs an object. No key is specified, so the object is just a value
+ (serves for the single root object, or for adding the object to an array).
@param ctx context for this object
- @param key optional key
*/
- Opt_trace_object(Opt_trace_context *ctx, const char *key= NULL) :
- Opt_trace_struct(ctx, true, key) {}
+ Opt_trace_object(Opt_trace_context *ctx,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) :
+ Opt_trace_struct(ctx, true, NULL, feature) {}
+
};
@@ -991,14 +1032,18 @@ class Opt_trace_array: public Opt_trace_
{
public:
/**
- Constructs an array. If a key is specified, the array is the value of a
- key/value pair (serves for adding the array to an object). Otherwise the
- array is just a value (serves for adding the array to an array).
+ Constructs an array. @sa Opt_trace_object::Opt_trace_object.
@param ctx context for this array
- @param key optional key
+ @param key key
*/
- Opt_trace_array(Opt_trace_context *ctx, const char *key= NULL) :
- Opt_trace_struct(ctx, false, key) {}
+ Opt_trace_array(Opt_trace_context *ctx, const char *key,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) :
+ Opt_trace_struct(ctx, false, key, feature) {}
+ Opt_trace_array(Opt_trace_context *ctx,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) :
+ Opt_trace_struct(ctx, false, NULL, feature) {}
};
@@ -1012,6 +1057,8 @@ public:
undesirable, so it is silenced with such object below (trace only goes to
DBUG then, for the duration of @c TEST_join()).
Re-enabling happens when the instance is destroyed.
+ Note that this class should rarely be used; the "feature" parameter of
+ Opt_trace_struct is a good alternative.
*/
class Opt_trace_disable_I_S
{
@@ -1138,12 +1185,21 @@ extern ST_FIELD_INFO optimizer_trace_inf
/* all empty */
class Opt_trace_context
-{};
+{
+public:
+ /* We need this one */
+ enum feature_value { MISC= 1, GREEDY_SEARCH= 2 };
+};
class Opt_trace_object
{
public:
- Opt_trace_object(Opt_trace_context *ctx, const char *key= NULL) {}
+ Opt_trace_object(Opt_trace_context *ctx, const char *key,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) {}
+ Opt_trace_object(Opt_trace_context *ctx,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) {}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
Opt_trace_object& add(const char *key, const char *value) { return *this; }
@@ -1160,7 +1216,12 @@ public:
class Opt_trace_array
{
public:
- Opt_trace_array(Opt_trace_context *ctx, const char *key= NULL) {}
+ Opt_trace_array(Opt_trace_context *ctx, const char *key,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) {}
+ Opt_trace_array(Opt_trace_context *ctx,
+ Opt_trace_context::feature_value feature=
+ Opt_trace_context::MISC) {}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
Opt_trace_array& add(const char *value) { return *this; }
=== modified file 'sql/opt_trace2server.cc'
--- a/sql/opt_trace2server.cc 2010-09-22 19:50:59 +0000
+++ b/sql/opt_trace2server.cc 2010-09-27 08:00:25 +0000
@@ -90,7 +90,8 @@ bool opt_trace_start(THD *thd, TABLE_LIS
(var & Opt_trace_context::FLAG_ONE_LINE),
thd->variables.optimizer_trace_offset,
thd->variables.optimizer_trace_limit,
- thd->variables.optimizer_trace_max_mem_size))
+ thd->variables.optimizer_trace_max_mem_size,
+ Opt_trace_context::feature_value(thd->variables.optimizer_trace_features)))
{
delete thd->opt_trace;
thd->opt_trace= NULL;
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-09-18 16:25:43 +0000
+++ b/sql/sql_class.h 2010-09-27 08:00:25 +0000
@@ -387,6 +387,7 @@ typedef struct system_variables
/* A bitmap for switching optimizations on/off */
ulonglong optimizer_switch;
ulonglong optimizer_trace; ///< bitmap to tune optimizer tracing
+ ulonglong optimizer_trace_features; ///< bitmap to select features to trace
long optimizer_trace_offset;
long optimizer_trace_limit;
ulong optimizer_trace_max_mem_size;
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2010-09-24 09:11:29 +0000
+++ b/sql/sql_select.cc 2010-09-27 08:00:25 +0000
@@ -7886,13 +7886,6 @@ greedy_search(JOIN *join,
JOIN_TAB *best_table; // the next plan node to be added to the curr QEP
uint n_tables; // ==join->tables or # tables in the sj-mat nest we're optimizing
Opt_trace_context *opt_trace= join->thd->opt_trace;
-#ifdef OPTIMIZER_TRACE
- bool skip_plan_tracing= join->thd->variables.optimizer_trace &
- Opt_trace_context::FLAG_SKIP_PLAN;
-#else
- const bool skip_plan_tracing= false;
-#endif
-
DBUG_ENTER("greedy_search");
ulonglong now= my_getsystime();
@@ -7904,10 +7897,8 @@ greedy_search(JOIN *join,
~(table_map)0));
Opt_trace_object oto0(opt_trace);
- Opt_trace_array ota(opt_trace, "considered_execution_plans");
- if (unlikely(skip_plan_tracing))
- OPT_TRACE(opt_trace, add("..."));
- Opt_trace_disable_I_S otd(opt_trace, skip_plan_tracing);
+ Opt_trace_array ota(opt_trace, "considered_execution_plans",
+ Opt_trace_context::GREEDY_SEARCH);
do {
/* Find the extension of the current QEP with the lowest cost */
=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc 2010-09-18 16:25:43 +0000
+++ b/sql/sys_vars.cc 2010-09-27 08:00:25 +0000
@@ -1403,12 +1403,22 @@ static Sys_var_flagset Sys_optimizer_tra
"optimizer_trace",
"Controls tracing of the Optimizer:"
" optimizer_trace=option=val[,option=val...], where option is one of"
- " {enabled, end_marker, one_line, skip_plan}"
+ " {enabled, end_marker, one_line}"
" and val is one of {on, off, default}",
SESSION_VAR(optimizer_trace), CMD_LINE(REQUIRED_ARG),
Opt_trace_context::flag_names,
DEFAULT(Opt_trace_context::FLAG_DEFAULT));
+static Sys_var_flagset Sys_optimizer_trace_features(
+ "optimizer_trace_features",
+ "Enables/disables tracing of selected features of the Optimizer:"
+ " optimizer_trace_features=option=val[,option=val...], where option is one of"
+ " {misc, greedy_search}"
+ " and val is one of {on, off, default}",
+ SESSION_VAR(optimizer_trace_features), CMD_LINE(REQUIRED_ARG),
+ Opt_trace_context::feature_names,
+ DEFAULT(Opt_trace_context::FEATURES_DEFAULT));
+
/** Delete all old optimizer traces */
static bool optimizer_trace_update(sys_var *self, THD *thd,
enum_var_type type)
=== modified file 'unittest/gunit/opt_trace-t.cc'
--- a/unittest/gunit/opt_trace-t.cc 2010-09-24 14:09:24 +0000
+++ b/unittest/gunit/opt_trace-t.cc 2010-09-27 08:00:25 +0000
@@ -29,13 +29,15 @@
CHARSET_INFO *system_charset_info= &my_charset_utf8_general_ci;
/* ... end here. */
+const Opt_trace_context::feature_value all_features=
+ Opt_trace_context::FEATURES_DEFAULT;
/** Test empty trace */
TEST(Trace_content_test, empty)
{
/* Create a trace */
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, false, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, false, false, -1, 1, 0, all_features));
/*
Add at least an object to it. A really empty trace ("") is not
JSON-compliant, at least Python's JSON module raises an exception.
@@ -64,7 +66,7 @@ TEST(Trace_content_test, empty)
TEST(Trace_content_test, normal_usage)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -124,7 +126,7 @@ TEST(Trace_content_test, normal_usage)
TEST(Trace_content_test, tail)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -182,7 +184,7 @@ TEST(Trace_content_test, tail)
TEST(Trace_content_test, buggy_object)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -238,7 +240,7 @@ TEST(Trace_content_test, buggy_object)
TEST(Trace_content_test, buggy_array)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -283,7 +285,7 @@ TEST(Trace_content_test, buggy_array)
TEST(Trace_content_test, disable_I_S)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -348,7 +350,8 @@ TEST(Trace_content_test, disable_I_S)
static void make_one_trace(Opt_trace_context &trace, const char *name,
long offset, long limit)
{
- ASSERT_EQ(false, trace.start(true, true, false, offset, limit, 0));
+ ASSERT_EQ(false, trace.start(true, true, false, offset, limit, 0,
+ all_features));
{
Opt_trace_object oto(&trace);
oto.add(name, 0LL);
@@ -449,7 +452,7 @@ TEST(Trace_settings_test, max_mem_size)
{
Opt_trace_context trace;
ASSERT_EQ(false, trace.start(true, false, false, -1, 1,
- 1000 /* max_mem_size */));
+ 1000 /* max_mem_size */, all_features));
/* make a "long" trace */
{
Opt_trace_object oto(&trace);
@@ -488,7 +491,7 @@ TEST(Trace_settings_test, max_mem_size2)
{
Opt_trace_context trace;
ASSERT_EQ(false, trace.start(true, false, false, -2, 2,
- 21 /* max_mem_size */));
+ 21 /* max_mem_size */, all_features));
/* make a "long" trace */
{
Opt_trace_object oto(&trace);
@@ -496,7 +499,7 @@ TEST(Trace_settings_test, max_mem_size2)
}
trace.end();
/* A second similar trace */
- ASSERT_EQ(false, trace.start(true, false, false, -2, 2, 21));
+ ASSERT_EQ(false, trace.start(true, false, false, -2, 2, 21, all_features));
{
Opt_trace_object oto(&trace);
oto.add("some key2", "make it long");
@@ -520,7 +523,7 @@ TEST(Trace_settings_test, max_mem_size2)
3rd trace; the first one should automatically be purged, thus the 3rd
should have a bit of room.
*/
- ASSERT_EQ(false, trace.start(true, false, false, -2, 2, 21));
+ ASSERT_EQ(false, trace.start(true, false, false, -2, 2, 21, all_features));
{
Opt_trace_object oto(&trace);
oto.add("some key3", "make it long");
@@ -551,7 +554,7 @@ TEST(Trace_settings_test, max_mem_size2)
TEST(Trace_content_test, out_of_memory)
{
Opt_trace_context trace;
- ASSERT_EQ(false, trace.start(true, false, false, -1, 1, 0));
+ ASSERT_EQ(false, trace.start(true, false, false, -1, 1, 0, all_features));
{
Opt_trace_object oto(&trace);
{
@@ -580,4 +583,65 @@ TEST(Trace_content_test, out_of_memory)
}
#endif // !DBUG_OFF
+
+/** Test filtering by feature */
+TEST(Trace_content_test, filtering_by_feature)
+{
+ Opt_trace_context trace;
+ ASSERT_EQ(false, trace.start(true, false, false, -1, 1, 0,
+ Opt_trace_context::MISC));
+ {
+ Opt_trace_object oto(&trace);
+ {
+ Opt_trace_array ota(&trace, "one array");
+ ota.add(200.4);
+ {
+ Opt_trace_object oto1(&trace, Opt_trace_context::GREEDY_SEARCH);
+ oto1.add("one key", "one value").
+ add("another key", 100LL);
+ Opt_trace_object oto2(&trace, "a fourth key",
+ Opt_trace_context::MISC);
+ oto2.add("another key inside", 5LL);
+ }
+ ota.add(true);
+ }
+ {
+ Opt_trace_object oto3(&trace, "key for oto3",
+ Opt_trace_context::GREEDY_SEARCH);
+ oto3.add("etc", 25);
+ }
+ oto.add("yet another key", -1000LL);
+ {
+ Opt_trace_array ota(&trace, "another array");
+ ota.add(1LL).add(2LL).add(3LL).add(4LL);
+ }
+ }
+ trace.end();
+ Opt_trace_iterator it(&trace);
+ ASSERT_EQ(true, it != Opt_trace_iterator::end);
+ const Opt_trace_info info= *it;
+ const char expected[]=
+ "{\n"
+ " \"one array\": [\n"
+ " 200.4,\n"
+ " \"...\",\n"
+ " true\n"
+ " ],\n"
+ " \"key for oto3\": \"...\",\n"
+ " \"yet another key\": -1000,\n"
+ " \"another array\": [\n"
+ " 1,\n"
+ " 2,\n"
+ " 3,\n"
+ " 4\n"
+ " ]\n"
+ "}";
+ ASSERT_STREQ(expected, info.ptr);
+ ASSERT_EQ(sizeof(expected) - 1, info.length);
+ ASSERT_EQ((size_t)0, info.missing_bytes);
+ ASSERT_EQ(false, info.malloc_error);
+ it++;
+ ASSERT_EQ(false, it != Opt_trace_iterator::end);
+}
+
#endif // OPTIMIZER_TRACE
Attachment: [text/bzr-bundle] bzr/guilhem@mysql.com-20100927080025-k7l20zgflvnhlj2t.bundle
| Thread |
|---|
| • bzr push into mysql-next-mr-bugfixing branch (guilhem:3213 to 3214) | Guilhem Bichot | 27 Sep |