MySQL  8.0.23
Source Code Documentation
opt_trace_context.h
Go to the documentation of this file.
1 /* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License, version 2.0,
5  as published by the Free Software Foundation.
6 
7  This program is also distributed with certain software (including
8  but not limited to OpenSSL) that is licensed under separate terms,
9  as designated in a particular file or component or in included license
10  documentation. The authors of MySQL hereby grant you an additional
11  permission to link the program and your derivative works with the
12  separately licensed software that they have included with MySQL.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License, version 2.0, for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22 
23 #ifndef OPT_TRACE_CONTEXT_INCLUDED
24 #define OPT_TRACE_CONTEXT_INCLUDED
25 
26 #include "my_dbug.h"
27 #include "my_inttypes.h"
29 #include "prealloced_array.h"
30 
31 /**
32  @file
33  This contains the declaration of class Opt_trace_context, which is needed
34  to declare THD.
35  It is recommend to read opt_trace.h first.
36 */
37 
38 class Opt_trace_stmt; // implementation detail local to opt_trace.cc
39 
41 
42 /**
43  @class Opt_trace_context
44 
45  A per-session context which is always available at any point of execution,
46  because in practice it's accessible from THD which contains:
47  @verbatim Opt_trace_context opt_trace; @endverbatim
48  It maintains properties of the session's regarding tracing: enabled/disabled
49  state, style (all trace on one line, or not, etc), a list of all remembered
50  traces of previous and current SQL statement (as restricted by
51  OFFSET/LIMIT), and a pointer to the current (being-generated) trace (which
52  itself has a pointer to its current open object/array).
53 
54  Here is why the context needs to provide the current open object/array:
55 
56  @li When adding a value (scalar or array or object) to an array, or adding a
57  key/value pair to an object, we need this outer object or array (from now
58  on, we will use the term "structure" for "object or array", as both are
59  structured types).
60 
61  @li The most natural way would be that the outer object would be passed in
62  argument to the adder (the function which wants to add the value or
63  key/value).
64 
65  @li But tracing is sometimes produced from deep down the stack trace, with
66  many intermediate frames doing no tracing (writing nothing to the trace), so
67  it would require passing the outer structure through many levels, thus
68  modifying many function prototypes.
69  Example (in gdb "backtrace" notation: inner frames first):
70 @verbatim
71  #0 Item_in_subselect::single_value_transformer
72  - opens an object for key "transformation"
73  #1 Item_in_subselect::select_in_like_transformer - does no tracing
74  #2 Item_allany_subselect::select_transformer - does no tracing
75  #3 SELECT_LEX::prepare - opens an object for key "join_preparation"
76 @endverbatim
77  So the object opened in #3 would have to be passed in argument to #2 and #1
78  in order to finally reach #0 where object "transformation" would be added to
79  it.
80 
81  @li So, as we cannot practically pass the object down, we rather maintain a
82  "current object or array" accessible from the Opt_trace_context context;
83  it's a pointer to an instance of Opt_trace_struct, and the function deep
84  down (frame #0) grabs it from the context, where it was depositted by the
85  function high up (frame #3 in the last example).
86 */
87 
89  public:
92 
93  /**
94  Starts a new trace.
95  @param support_I_S Whether this statement should have its trace in
96  information_schema
97  @param support_dbug_or_missing_priv 'true' if this statement
98  should have its trace in the dbug log (--debug),
99  or if missing_privilege() may be called on this
100  trace
101  @param end_marker For a key/(object|array) pair, should the key be
102  repeated in a comment when the object|array
103  closes? like
104  @verbatim
105  "key_foo": {
106  multi-line blah
107  } / * key_foo * /
108  @endverbatim
109  This is for human-readability only, not valid in
110  JSON. Note that YAML supports #-prefixed
111  comments (we would just need to put the next
112  item's "," before the current item's "#").
113  @param one_line Should the trace be on a single line without
114  indentation? (More compact for network transfer
115  to programs, less human-readable.)
116  @param offset Offset for restricting trace production.
117  @param limit Limit for restricting trace production.
118  @param max_mem_size Maximum allowed for cumulated size of all
119  remembered traces.
120  @param features Only these optimizer features should be traced.
121 
122  @retval false ok
123  @retval true error (OOM): instance is unusable, so only
124  destructor is permitted on it; any other
125  member function has undefined effects.
126  */
127  bool start(bool support_I_S, bool support_dbug_or_missing_priv,
128  bool end_marker, bool one_line, long offset, long limit,
129  ulong max_mem_size, ulonglong features);
130 
131  /**
132  Ends the current (=open, unfinished, being-generated) trace.
133 
134  If @c missing_privilege() has been called between start() and end(),
135  end() restores I_S support to what it was before the call to
136  @c missing_privilege(). This is the key to ensure that missing_privilege()
137  does not disable I_S support for the rest of the connection's life!
138  */
139  void end();
140 
141  /// Returns whether there is a current trace
142  bool is_started() const {
143  return unlikely(pimpl != nullptr) && pimpl->current_stmt_in_gen != nullptr;
144  }
145 
146  /**
147  @returns whether the current trace writes to I_S.
148  This function should rarely be used. Don't you use this for some clever
149  optimizations bypassing opt trace!
150  */
151  bool support_I_S() const;
152 
153  /**
154  Set the "original" query (not transformed, as sent by client) for the
155  current trace.
156  @param query query
157  @param length query's length
158  @param charset charset which was used to encode this query
159  */
160  void set_query(const char *query, size_t length, const CHARSET_INFO *charset);
161 
162  /**
163  Brainwash: deletes all remembered traces and resets counters regarding
164  OFFSET/LIMIT (so that the next statement is considered as "at offset
165  0"). Does not reset the @@@@optimizer_trace_offset/limit variables.
166  */
167  void reset();
168 
169  /// @sa parameters of Opt_trace_context::start()
170  bool get_end_marker() const { return pimpl->end_marker; }
171  /// @sa parameters of Opt_trace_context::start()
172  bool get_one_line() const { return pimpl->one_line; }
173 
174  /**
175  Names of flags for @@@@optimizer_trace variable of @c sys_vars.cc :
176  @li "enabled" = tracing enabled
177  @li "one_line"= see parameter of @ref Opt_trace_context::start
178  @li "default".
179  */
180  static const char *flag_names[];
181 
182  /** Flags' numeric values for @@@@optimizer_trace variable */
183  enum { FLAG_DEFAULT = 0, FLAG_ENABLED = 1 << 0, FLAG_ONE_LINE = 1 << 1 };
184 
185  /**
186  Features' names for @@@@optimizer_trace_features variable of
187  @c sys_vars.cc:
188  @li "greedy_search" = the greedy search for a plan
189  @li "range_optimizer" = the cost analysis of accessing data through
190  ranges in indexes
191  @li "dynamic_range" = the range optimization performed for each record
192  when access method is dynamic range
193  @li "repeated_subselect" = the repeated execution of subselects
194  @li "default".
195  */
196  static const char *feature_names[];
197 
198  /** Features' numeric values for @@@@optimizer_trace_features variable */
200  GREEDY_SEARCH = 1 << 0,
201  RANGE_OPTIMIZER = 1 << 1,
202  DYNAMIC_RANGE = 1 << 2,
204  /*
205  If you add here, update feature_value of empty implementation
206  and default_features!
207  */
208  /**
209  Anything unclassified, including the top object (thus, by "inheritance
210  from parent", disabling MISC makes an empty trace).
211  This feature cannot be disabled by the user; for this it is important
212  that it always has biggest flag; flag's value itself does not matter.
213  */
214  MISC = 1 << 7
215  };
216 
217  /**
218  User lacks privileges to see the current trace. Make the trace appear
219  empty in Opt_trace_info, and disable I_S for all its upcoming children.
220 
221  Once a call to this function has been made, subsequent calls to it before
222  @c end() have no effects.
223  */
224  void missing_privilege();
225 
226  /// Optimizer features which are traced by default.
228 
229  /**
230  @returns whether an optimizer feature should be traced.
231  @param f feature
232  */
234  return unlikely(pimpl != nullptr) && (pimpl->features & f);
235  }
236 
237  /**
238  Opt_trace_struct is passed Opt_trace_context*, and needs to know
239  to which statement's trace to attach, so Opt_trace_context must provide
240  this information.
241  */
243  return pimpl->current_stmt_in_gen;
244  }
245 
246  /**
247  @returns the next statement to show in I_S.
248  @param[in,out] got_so_far How many statements the caller got so far
249  (by previous calls to this function); function updates this count.
250  @note traces are returned from oldest to newest.
251  */
252  const Opt_trace_stmt *get_next_stmt_for_I_S(long *got_so_far) const;
253 
254  /// Temporarily disables I_S for this trace and its children.
256  ++I_S_disabled;
258  }
259 
260  /**
261  Restores I_S support to what it was before the previous call to
262  disable_I_S_for_this_and_children().
263  */
264  void restore_I_S() {
265  --I_S_disabled;
267  if (unlikely(pimpl != nullptr)) pimpl->restore_I_S();
268  }
269 
270  private:
271  /**
272  To have the smallest impact on THD's size, most of the implementation is
273  moved to a separate class Opt_trace_context_impl which is instantiated on
274  the heap when really needed. So if a connection never sets
275  @@@@optimizer_trace to "enabled=on" and does not use --debug, this heap
276  allocation never happens.
277  This class is declared here so that frequently called functions like
278  Opt_trace_context::is_started() can be inlined.
279  */
281  public:
288  offset(0),
289  limit(0),
290  since_offset_0(0) {}
291 
293  void restore_I_S();
294 
295  /**
296  Trace which is currently being generated, where structures are being
297  added. "in_gen" stands for "in generation", being-generated.
298 
299  In simple cases it is equal to the last element of array
300  all_stmts_for_I_S. But it can be prior to it, for example when calling
301  a stored routine:
302 @verbatim
303  CALL statement starts executing
304  create trace of CALL (call it "trace #1")
305  add structure to trace #1
306  add structure to trace #1
307  First sub-statement executing
308  create trace of sub-statement (call it "trace #2")
309  add structure to trace #2
310  add structure to trace #2
311  First sub-statement ends
312  add structure to trace #1
313 @endverbatim
314  In the beginning, the CALL statement's trace is the newest and current;
315  when the first sub-statement is executing, that sub-statement's trace
316  is the newest and current; when the first sub-statement ends, it is
317  still the newest but it's not the current anymore: the current is then
318  again the CALL's one, where structures will be added, until a second
319  sub-statement is executed.
320  Another case is when the current statement sends only to DBUG:
321  all_stmts_for_I_S lists only traces shown in OPTIMIZER_TRACE.
322  */
324 
325  /**
326  To keep track of what is the current statement, as execution goes into
327  a sub-statement, and back to the upper statement, we have a stack of
328  successive values of current_stmt_in_gen:
329  when in a statement we enter a substatement (a new trace), we push the
330  statement's trace on the stack and change current_stmt_in_gen to the
331  substatement's trace; when leaving the substatement we pop from the
332  stack and set current_stmt_in_gen to the popped value.
333  */
335 
336  /**
337  List of remembered traces for putting into the OPTIMIZER_TRACE
338  table. Element 0 is the one created first, will be first row of
339  OPTIMIZER_TRACE table. The array structure fullfills those needs:
340  - to output traces "oldest first" in OPTIMIZER_TRACE
341  - to preserve traces "newest first" when @@@@optimizer_trace_offset<0
342  - to delete a trace in the middle of the list when it is permanently
343  out of the offset/limit showable window.
344  */
346  /**
347  List of traces which are unneeded because of OFFSET/LIMIT, and
348  scheduled for deletion from memory.
349  */
351 
352  bool end_marker; ///< copy of parameter of Opt_trace_context::start
353  bool one_line;
355  long offset;
356  long limit;
357  size_t max_mem_size;
358 
359  /**
360  Number of statements traced so far since "offset 0", for comparison
361  with OFFSET and LIMIT, when OFFSET >= 0.
362  */
364  };
365 
366  Opt_trace_context_impl *pimpl; /// Dynamically allocated implementation.
367 
368  /**
369  <>0 <=> any to-be-created statement's trace should not be in
370  information_schema. This applies to next statements, their substatements,
371  etc.
372  */
374 
375  /**
376  Find and delete unneeded traces.
377  For example if OFFSET=-1,LIMIT=1, only the last trace is needed. When a
378  new trace is started, the previous traces becomes unneeded and this
379  function deletes them which frees memory.
380  @param purge_all if true, ignore OFFSET and thus delete everything
381  */
382  void purge_stmts(bool purge_all);
383 
384  /**
385  Compute maximum allowed memory size for current trace. The current trace
386  is the only one active. Other traces break down in two groups:
387  - the finished ones (from previously executed statements),
388  - the "started but not finished ones": they are not current, are not
389  being updated at this moment: this must be the trace of a top
390  statement calling a substatement which is the current trace now: trace's
391  top statement is not being updated at this moment.
392  So the current trace can grow in the room left by all traces above.
393  */
394  size_t allowed_mem_size_for_current_stmt() const;
395 
396  /// Not defined copy constructor, to disallow copy.
398  /// Not defined assignment operator, to disallow assignment.
400 };
401 
402 #endif /* OPT_TRACE_CONTEXT_INCLUDED */
unlikely
bool unlikely(bool expr)
Definition: my_compiler.h:55
Opt_trace_context::MISC
@ MISC
Anything unclassified, including the top object (thus, by "inheritance from parent",...
Definition: opt_trace_context.h:214
Opt_trace_context::disable_I_S_for_this_and_children
void disable_I_S_for_this_and_children()
Temporarily disables I_S for this trace and its children.
Definition: opt_trace_context.h:255
Opt_trace_context::RANGE_OPTIMIZER
@ RANGE_OPTIMIZER
Definition: opt_trace_context.h:201
PSI_INSTRUMENT_ME
static constexpr unsigned PSI_INSTRUMENT_ME
Definition: psi_bits.h:42
Opt_trace_context::restore_I_S
void restore_I_S()
Restores I_S support to what it was before the previous call to disable_I_S_for_this_and_children().
Definition: opt_trace_context.h:264
Opt_trace_context::REPEATED_SUBSELECT
@ REPEATED_SUBSELECT
Definition: opt_trace_context.h:203
Prealloced_array< Opt_trace_stmt *, 16 >
Opt_trace_context::Opt_trace_context_impl::max_mem_size
size_t max_mem_size
Definition: opt_trace_context.h:357
Opt_trace_context::Opt_trace_context_impl::Opt_trace_context_impl
Opt_trace_context_impl()
Definition: opt_trace_context.h:282
Opt_trace_context::Opt_trace_context_impl::offset
long offset
Definition: opt_trace_context.h:355
CHARSET_INFO
Definition: m_ctype.h:354
nullptr
Dialog Client Authentication nullptr
Definition: dialog.cc:353
Opt_trace_context::start
bool start(bool support_I_S, bool support_dbug_or_missing_priv, bool end_marker, bool one_line, long offset, long limit, ulong max_mem_size, ulonglong features)
Starts a new trace.
Definition: opt_trace.cc:849
Opt_trace_context::GREEDY_SEARCH
@ GREEDY_SEARCH
Definition: opt_trace_context.h:200
Opt_trace_context
Definition: opt_trace_context.h:88
my_dbug.h
Opt_trace_context::feature_value
feature_value
Features' numeric values for @@optimizer_trace_features variable.
Definition: opt_trace_context.h:199
Opt_trace_context::FLAG_ONE_LINE
@ FLAG_ONE_LINE
Definition: opt_trace_context.h:183
Opt_trace_context::Opt_trace_context_impl::stack_of_current_stmts
Opt_trace_stmt_array stack_of_current_stmts
To keep track of what is the current statement, as execution goes into a sub-statement,...
Definition: opt_trace_context.h:334
Opt_trace_context::is_started
bool is_started() const
Returns whether there is a current trace.
Definition: opt_trace_context.h:142
prealloced_array.h
Opt_trace_context::FLAG_ENABLED
@ FLAG_ENABLED
Definition: opt_trace_context.h:183
Opt_trace_context::I_S_disabled
int I_S_disabled
Dynamically allocated implementation.
Definition: opt_trace_context.h:373
Opt_trace_context::flag_names
static const char * flag_names[]
Names of flags for @@optimizer_trace variable of sys_vars.cc :
Definition: opt_trace_context.h:180
consts::charset
const std::string charset("charset")
Opt_trace_context::pimpl
Opt_trace_context_impl * pimpl
Definition: opt_trace_context.h:366
Opt_trace_context::FLAG_DEFAULT
@ FLAG_DEFAULT
Definition: opt_trace_context.h:183
Opt_trace_context::Opt_trace_context_impl::disable_I_S_for_this_and_children
void disable_I_S_for_this_and_children()
Definition: opt_trace.cc:1139
Opt_trace_context::reset
void reset()
Brainwash: deletes all remembered traces and resets counters regarding OFFSET/LIMIT (so that the next...
Definition: opt_trace.cc:1132
my_inttypes.h
Opt_trace_context::Opt_trace_context_impl::all_stmts_for_I_S
Opt_trace_stmt_array all_stmts_for_I_S
List of remembered traces for putting into the OPTIMIZER_TRACE table.
Definition: opt_trace_context.h:345
Opt_trace_context::DYNAMIC_RANGE
@ DYNAMIC_RANGE
Definition: opt_trace_context.h:202
Opt_trace_context::support_I_S
bool support_I_S() const
Definition: opt_trace.cc:1017
Opt_trace_context::purge_stmts
void purge_stmts(bool purge_all)
Find and delete unneeded traces.
Definition: opt_trace.cc:1022
Opt_trace_context::Opt_trace_context_impl::since_offset_0
long since_offset_0
Number of statements traced so far since "offset 0", for comparison with OFFSET and LIMIT,...
Definition: opt_trace_context.h:363
Opt_trace_context::Opt_trace_context
Opt_trace_context(const Opt_trace_context &)
Not defined copy constructor, to disallow copy.
Opt_trace_context::feature_enabled
bool feature_enabled(feature_value f) const
Definition: opt_trace_context.h:233
query
static char * query
Definition: myisam_ftdump.cc:44
Opt_trace_context::allowed_mem_size_for_current_stmt
size_t allowed_mem_size_for_current_stmt() const
Compute maximum allowed memory size for current trace.
Definition: opt_trace.cc:1106
Opt_trace_context::~Opt_trace_context
~Opt_trace_context()
Definition: opt_trace.cc:822
Opt_trace_context::get_next_stmt_for_I_S
const Opt_trace_stmt * get_next_stmt_for_I_S(long *got_so_far) const
Definition: opt_trace.cc:1163
Opt_trace_context::get_one_line
bool get_one_line() const
Definition: opt_trace_context.h:172
Opt_trace_context::operator=
Opt_trace_context & operator=(const Opt_trace_context &)
Not defined assignment operator, to disallow assignment.
Opt_trace_context::Opt_trace_context
Opt_trace_context()
Definition: opt_trace_context.h:90
Opt_trace_context::Opt_trace_context_impl::features
feature_value features
Definition: opt_trace_context.h:354
Opt_trace_context::Opt_trace_context_impl
To have the smallest impact on THD's size, most of the implementation is moved to a separate class Op...
Definition: opt_trace_context.h:280
Opt_trace_context::Opt_trace_context_impl::limit
long limit
Definition: opt_trace_context.h:356
DBUG_ASSERT
#define DBUG_ASSERT(A)
Definition: my_dbug.h:199
Opt_trace_context::missing_privilege
void missing_privilege()
User lacks privileges to see the current trace.
Definition: opt_trace.cc:1147
Opt_trace_context::get_end_marker
bool get_end_marker() const
Definition: opt_trace_context.h:170
Opt_trace_context::default_features
static const feature_value default_features
Optimizer features which are traced by default.
Definition: opt_trace_context.h:227
Opt_trace_context::set_query
void set_query(const char *query, size_t length, const CHARSET_INFO *charset)
Set the "original" query (not transformed, as sent by client) for the current trace.
Definition: opt_trace.cc:1127
gis::length
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:75
Opt_trace_stmt_array
Prealloced_array< Opt_trace_stmt *, 16 > Opt_trace_stmt_array
Definition: opt_trace_context.h:38
Opt_trace_context::get_current_stmt_in_gen
Opt_trace_stmt * get_current_stmt_in_gen()
Opt_trace_struct is passed Opt_trace_context*, and needs to know to which statement's trace to attach...
Definition: opt_trace_context.h:242
psi_bits.h
ulonglong
unsigned long long int ulonglong
Definition: my_inttypes.h:55
Opt_trace_context::Opt_trace_context_impl::current_stmt_in_gen
Opt_trace_stmt * current_stmt_in_gen
Definition: opt_trace_context.h:323
Opt_trace_context::Opt_trace_context_impl::end_marker
bool end_marker
copy of parameter of Opt_trace_context::start
Definition: opt_trace_context.h:352
Opt_trace_context::Opt_trace_context_impl::restore_I_S
void restore_I_S()
Definition: opt_trace.cc:1143
Opt_trace_context::end
void end()
Ends the current (=open, unfinished, being-generated) trace.
Definition: opt_trace.cc:975
Opt_trace_context::Opt_trace_context_impl::all_stmts_to_del
Opt_trace_stmt_array all_stmts_to_del
List of traces which are unneeded because of OFFSET/LIMIT, and scheduled for deletion from memory.
Definition: opt_trace_context.h:350
Opt_trace_context::Opt_trace_context_impl::one_line
bool one_line
Definition: opt_trace_context.h:353
Opt_trace_stmt
Definition: opt_trace.cc:108
Opt_trace_context::feature_names
static const char * feature_names[]
Features' names for @@optimizer_trace_features variable of sys_vars.cc:
Definition: opt_trace_context.h:196