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