1 /* Copyright (c) 2010, 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 /**
24   @file storage/perfschema/table_events_statements.cc
25   Table EVENTS_STATEMENTS_xxx (implementation).
26 */
27 
28 #include "storage/perfschema/table_events_statements.h"
29 
30 #include <stddef.h>
31 
32 #include "my_compiler.h"
33 #include "my_dbug.h"
34 #include "my_thread.h"
35 #include "sql/plugin_table.h"
36 #include "sql/sp_head.h" /* TYPE_ENUM_FUNCTION, ... */
37 #include "sql/table.h"
38 #include "storage/perfschema/pfs_buffer_container.h"
39 #include "storage/perfschema/pfs_events_statements.h"
40 #include "storage/perfschema/pfs_instr.h"
41 #include "storage/perfschema/pfs_instr_class.h"
42 #include "storage/perfschema/pfs_timer.h"
43 #include "storage/perfschema/table_helper.h"
44 
45 THR_LOCK table_events_statements_current::m_table_lock;
46 
47 Plugin_table table_events_statements_current::m_table_def(
48     /* Schema name */
49     "performance_schema",
50     /* Name */
51     "events_statements_current",
52     /* Definition */
53     "  THREAD_ID BIGINT unsigned not null,\n"
54     "  EVENT_ID BIGINT unsigned not null,\n"
55     "  END_EVENT_ID BIGINT unsigned,\n"
56     "  EVENT_NAME VARCHAR(128) not null,\n"
57     "  SOURCE VARCHAR(64),\n"
58     "  TIMER_START BIGINT unsigned,\n"
59     "  TIMER_END BIGINT unsigned,\n"
60     "  TIMER_WAIT BIGINT unsigned,\n"
61     "  LOCK_TIME BIGINT unsigned not null,\n"
62     "  SQL_TEXT LONGTEXT,\n"
63     "  DIGEST VARCHAR(64),\n"
64     "  DIGEST_TEXT LONGTEXT,\n"
65     "  CURRENT_SCHEMA VARCHAR(64),\n"
66     "  OBJECT_TYPE VARCHAR(64),\n"
67     "  OBJECT_SCHEMA VARCHAR(64),\n"
68     "  OBJECT_NAME VARCHAR(64),\n"
69     "  OBJECT_INSTANCE_BEGIN BIGINT unsigned,\n"
70     "  MYSQL_ERRNO INTEGER,\n"
71     "  RETURNED_SQLSTATE VARCHAR(5),\n"
72     "  MESSAGE_TEXT VARCHAR(128),\n"
73     "  ERRORS BIGINT unsigned not null,\n"
74     "  WARNINGS BIGINT unsigned not null,\n"
75     "  ROWS_AFFECTED BIGINT unsigned not null,\n"
76     "  ROWS_SENT BIGINT unsigned not null,\n"
77     "  ROWS_EXAMINED BIGINT unsigned not null,\n"
78     "  CREATED_TMP_DISK_TABLES BIGINT unsigned not null,\n"
79     "  CREATED_TMP_TABLES BIGINT unsigned not null,\n"
80     "  SELECT_FULL_JOIN BIGINT unsigned not null,\n"
81     "  SELECT_FULL_RANGE_JOIN BIGINT unsigned not null,\n"
82     "  SELECT_RANGE BIGINT unsigned not null,\n"
83     "  SELECT_RANGE_CHECK BIGINT unsigned not null,\n"
84     "  SELECT_SCAN BIGINT unsigned not null,\n"
85     "  SORT_MERGE_PASSES BIGINT unsigned not null,\n"
86     "  SORT_RANGE BIGINT unsigned not null,\n"
87     "  SORT_ROWS BIGINT unsigned not null,\n"
88     "  SORT_SCAN BIGINT unsigned not null,\n"
89     "  NO_INDEX_USED BIGINT unsigned not null,\n"
90     "  NO_GOOD_INDEX_USED BIGINT unsigned not null,\n"
91     "  NESTING_EVENT_ID BIGINT unsigned,\n"
92     "  NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),\n"
93     "  NESTING_EVENT_LEVEL INTEGER,\n"
94     "  STATEMENT_ID BIGINT unsigned,\n"
95     "  PRIMARY KEY (THREAD_ID, EVENT_ID) USING HASH\n",
96     /* Options */
97     " ENGINE=PERFORMANCE_SCHEMA",
98     /* Tablespace */
99     nullptr);
100 
101 PFS_engine_table_share table_events_statements_current::m_share = {
102     &pfs_truncatable_acl,
103     table_events_statements_current::create,
104     nullptr, /* write_row */
105     table_events_statements_current::delete_all_rows,
106     table_events_statements_current::get_row_count,
107     sizeof(pos_events_statements_current), /* ref length */
108     &m_table_lock,
109     &m_table_def,
110     false, /* perpetual */
111     PFS_engine_table_proxy(),
112     {0},
113     false /* m_in_purgatory */
114 };
115 
116 THR_LOCK table_events_statements_history::m_table_lock;
117 
118 Plugin_table table_events_statements_history::m_table_def(
119     /* Schema name */
120     "performance_schema",
121     /* Name */
122     "events_statements_history",
123     /* Definition */
124     "  THREAD_ID BIGINT unsigned not null,\n"
125     "  EVENT_ID BIGINT unsigned not null,\n"
126     "  END_EVENT_ID BIGINT unsigned,\n"
127     "  EVENT_NAME VARCHAR(128) not null,\n"
128     "  SOURCE VARCHAR(64),\n"
129     "  TIMER_START BIGINT unsigned,\n"
130     "  TIMER_END BIGINT unsigned,\n"
131     "  TIMER_WAIT BIGINT unsigned,\n"
132     "  LOCK_TIME BIGINT unsigned not null,\n"
133     "  SQL_TEXT LONGTEXT,\n"
134     "  DIGEST VARCHAR(64),\n"
135     "  DIGEST_TEXT LONGTEXT,\n"
136     "  CURRENT_SCHEMA VARCHAR(64),\n"
137     "  OBJECT_TYPE VARCHAR(64),\n"
138     "  OBJECT_SCHEMA VARCHAR(64),\n"
139     "  OBJECT_NAME VARCHAR(64),\n"
140     "  OBJECT_INSTANCE_BEGIN BIGINT unsigned,\n"
141     "  MYSQL_ERRNO INTEGER,\n"
142     "  RETURNED_SQLSTATE VARCHAR(5),\n"
143     "  MESSAGE_TEXT VARCHAR(128),\n"
144     "  ERRORS BIGINT unsigned not null,\n"
145     "  WARNINGS BIGINT unsigned not null,\n"
146     "  ROWS_AFFECTED BIGINT unsigned not null,\n"
147     "  ROWS_SENT BIGINT unsigned not null,\n"
148     "  ROWS_EXAMINED BIGINT unsigned not null,\n"
149     "  CREATED_TMP_DISK_TABLES BIGINT unsigned not null,\n"
150     "  CREATED_TMP_TABLES BIGINT unsigned not null,\n"
151     "  SELECT_FULL_JOIN BIGINT unsigned not null,\n"
152     "  SELECT_FULL_RANGE_JOIN BIGINT unsigned not null,\n"
153     "  SELECT_RANGE BIGINT unsigned not null,\n"
154     "  SELECT_RANGE_CHECK BIGINT unsigned not null,\n"
155     "  SELECT_SCAN BIGINT unsigned not null,\n"
156     "  SORT_MERGE_PASSES BIGINT unsigned not null,\n"
157     "  SORT_RANGE BIGINT unsigned not null,\n"
158     "  SORT_ROWS BIGINT unsigned not null,\n"
159     "  SORT_SCAN BIGINT unsigned not null,\n"
160     "  NO_INDEX_USED BIGINT unsigned not null,\n"
161     "  NO_GOOD_INDEX_USED BIGINT unsigned not null,\n"
162     "  NESTING_EVENT_ID BIGINT unsigned,\n"
163     "  NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),\n"
164     "  NESTING_EVENT_LEVEL INTEGER,\n"
165     "  STATEMENT_ID BIGINT unsigned,\n"
166     "  PRIMARY KEY (THREAD_ID, EVENT_ID) USING HASH\n",
167     /* Options */
168     " ENGINE=PERFORMANCE_SCHEMA",
169     /* Tablespace */
170     nullptr);
171 
172 PFS_engine_table_share table_events_statements_history::m_share = {
173     &pfs_truncatable_acl,
174     table_events_statements_history::create,
175     nullptr, /* write_row */
176     table_events_statements_history::delete_all_rows,
177     table_events_statements_history::get_row_count,
178     sizeof(pos_events_statements_history), /* ref length */
179     &m_table_lock,
180     &m_table_def,
181     false, /* perpetual */
182     PFS_engine_table_proxy(),
183     {0},
184     false /* m_in_purgatory */
185 };
186 
187 THR_LOCK table_events_statements_history_long::m_table_lock;
188 
189 Plugin_table table_events_statements_history_long::m_table_def(
190     /* Schema name */
191     "performance_schema",
192     /* Name */
193     "events_statements_history_long",
194     /* Definition */
195     "  THREAD_ID BIGINT unsigned not null,\n"
196     "  EVENT_ID BIGINT unsigned not null,\n"
197     "  END_EVENT_ID BIGINT unsigned,\n"
198     "  EVENT_NAME VARCHAR(128) not null,\n"
199     "  SOURCE VARCHAR(64),\n"
200     "  TIMER_START BIGINT unsigned,\n"
201     "  TIMER_END BIGINT unsigned,\n"
202     "  TIMER_WAIT BIGINT unsigned,\n"
203     "  LOCK_TIME BIGINT unsigned not null,\n"
204     "  SQL_TEXT LONGTEXT,\n"
205     "  DIGEST VARCHAR(64),\n"
206     "  DIGEST_TEXT LONGTEXT,\n"
207     "  CURRENT_SCHEMA VARCHAR(64),\n"
208     "  OBJECT_TYPE VARCHAR(64),\n"
209     "  OBJECT_SCHEMA VARCHAR(64),\n"
210     "  OBJECT_NAME VARCHAR(64),\n"
211     "  OBJECT_INSTANCE_BEGIN BIGINT unsigned,\n"
212     "  MYSQL_ERRNO INTEGER,\n"
213     "  RETURNED_SQLSTATE VARCHAR(5),\n"
214     "  MESSAGE_TEXT VARCHAR(128),\n"
215     "  ERRORS BIGINT unsigned not null,\n"
216     "  WARNINGS BIGINT unsigned not null,\n"
217     "  ROWS_AFFECTED BIGINT unsigned not null,\n"
218     "  ROWS_SENT BIGINT unsigned not null,\n"
219     "  ROWS_EXAMINED BIGINT unsigned not null,\n"
220     "  CREATED_TMP_DISK_TABLES BIGINT unsigned not null,\n"
221     "  CREATED_TMP_TABLES BIGINT unsigned not null,\n"
222     "  SELECT_FULL_JOIN BIGINT unsigned not null,\n"
223     "  SELECT_FULL_RANGE_JOIN BIGINT unsigned not null,\n"
224     "  SELECT_RANGE BIGINT unsigned not null,\n"
225     "  SELECT_RANGE_CHECK BIGINT unsigned not null,\n"
226     "  SELECT_SCAN BIGINT unsigned not null,\n"
227     "  SORT_MERGE_PASSES BIGINT unsigned not null,\n"
228     "  SORT_RANGE BIGINT unsigned not null,\n"
229     "  SORT_ROWS BIGINT unsigned not null,\n"
230     "  SORT_SCAN BIGINT unsigned not null,\n"
231     "  NO_INDEX_USED BIGINT unsigned not null,\n"
232     "  NO_GOOD_INDEX_USED BIGINT unsigned not null,\n"
233     "  NESTING_EVENT_ID BIGINT unsigned,\n"
234     "  NESTING_EVENT_TYPE ENUM('TRANSACTION', 'STATEMENT', 'STAGE', 'WAIT'),\n"
235     "  NESTING_EVENT_LEVEL INTEGER,\n"
236     "  STATEMENT_ID BIGINT unsigned\n",
237     /* Options */
238     " ENGINE=PERFORMANCE_SCHEMA",
239     /* Tablespace */
240     nullptr);
241 
242 PFS_engine_table_share table_events_statements_history_long::m_share = {
243     &pfs_truncatable_acl,
244     table_events_statements_history_long::create,
245     nullptr, /* write_row */
246     table_events_statements_history_long::delete_all_rows,
247     table_events_statements_history_long::get_row_count,
248     sizeof(PFS_simple_index), /* ref length */
249     &m_table_lock,
250     &m_table_def,
251     false, /* perpetual */
252     PFS_engine_table_proxy(),
253     {0},
254     false /* m_in_purgatory */
255 };
256 
match(PFS_thread * pfs)257 bool PFS_index_events_statements::match(PFS_thread *pfs) {
258   if (m_fields >= 1) {
259     if (!m_key_1.match(pfs)) {
260       return false;
261     }
262   }
263   return true;
264 }
265 
match(PFS_events * pfs)266 bool PFS_index_events_statements::match(PFS_events *pfs) {
267   if (m_fields >= 2) {
268     if (!m_key_2.match(pfs)) {
269       return false;
270     }
271   }
272   return true;
273 }
274 
table_events_statements_common(const PFS_engine_table_share * share,void * pos)275 table_events_statements_common::table_events_statements_common(
276     const PFS_engine_table_share *share, void *pos)
277     : PFS_engine_table(share, pos) {
278   m_normalizer = time_normalizer::get_statement();
279 }
280 
281 /**
282   Build a row, part 1.
283 
284   This method is used while holding optimist locks.
285 
286   @param statement    The statement the cursor is reading
287   @param [out] digest Saved copy of the statement digest
288   @return 0 on success or HA_ERR_RECORD_DELETED
289 */
make_row_part_1(PFS_events_statements * statement,sql_digest_storage * digest)290 int table_events_statements_common::make_row_part_1(
291     PFS_events_statements *statement, sql_digest_storage *digest) {
292   ulonglong timer_end;
293 
294   PFS_statement_class *unsafe = (PFS_statement_class *)statement->m_class;
295   PFS_statement_class *klass = sanitize_statement_class(unsafe);
296   if (unlikely(klass == nullptr)) {
297     return HA_ERR_RECORD_DELETED;
298   }
299 
300   m_row.m_thread_internal_id = statement->m_thread_internal_id;
301   m_row.m_statement_id = statement->m_statement_id;
302   m_row.m_event_id = statement->m_event_id;
303   m_row.m_end_event_id = statement->m_end_event_id;
304   m_row.m_nesting_event_id = statement->m_nesting_event_id;
305   m_row.m_nesting_event_type = statement->m_nesting_event_type;
306   m_row.m_nesting_event_level = statement->m_nesting_event_level;
307 
308   if (m_row.m_end_event_id == 0) {
309     timer_end = get_statement_timer();
310   } else {
311     timer_end = statement->m_timer_end;
312   }
313 
314   m_normalizer->to_pico(statement->m_timer_start, timer_end,
315                         &m_row.m_timer_start, &m_row.m_timer_end,
316                         &m_row.m_timer_wait);
317   m_row.m_lock_time = statement->m_lock_time * MICROSEC_TO_PICOSEC;
318 
319   m_row.m_name = klass->m_name;
320   m_row.m_name_length = klass->m_name_length;
321 
322   m_row.m_current_schema_name_length = statement->m_current_schema_name_length;
323   if (m_row.m_current_schema_name_length > 0)
324     memcpy(m_row.m_current_schema_name, statement->m_current_schema_name,
325            m_row.m_current_schema_name_length);
326 
327   m_row.m_object_type = statement->m_sp_type;
328 
329   m_row.m_schema_name_length = statement->m_schema_name_length;
330   if (m_row.m_schema_name_length > 0)
331     memcpy(m_row.m_schema_name, statement->m_schema_name,
332            m_row.m_schema_name_length);
333 
334   m_row.m_object_name_length = statement->m_object_name_length;
335   if (m_row.m_object_name_length > 0)
336     memcpy(m_row.m_object_name, statement->m_object_name,
337            m_row.m_object_name_length);
338 
339   make_source_column(statement->m_source_file, statement->m_source_line,
340                      m_row.m_source, sizeof(m_row.m_source),
341                      m_row.m_source_length);
342 
343   memcpy(m_row.m_message_text, statement->m_message_text,
344          sizeof(m_row.m_message_text));
345   memcpy(m_row.m_sqlstate, statement->m_sqlstate, SQLSTATE_LENGTH);
346 
347   m_row.m_sql_errno = statement->m_sql_errno;
348   m_row.m_error_count = statement->m_error_count;
349   m_row.m_warning_count = statement->m_warning_count;
350   m_row.m_rows_affected = statement->m_rows_affected;
351   m_row.m_rows_sent = statement->m_rows_sent;
352   m_row.m_rows_examined = statement->m_rows_examined;
353   m_row.m_created_tmp_disk_tables = statement->m_created_tmp_disk_tables;
354   m_row.m_created_tmp_tables = statement->m_created_tmp_tables;
355   m_row.m_select_full_join = statement->m_select_full_join;
356   m_row.m_select_full_range_join = statement->m_select_full_range_join;
357   m_row.m_select_range = statement->m_select_range;
358   m_row.m_select_range_check = statement->m_select_range_check;
359   m_row.m_select_scan = statement->m_select_scan;
360   m_row.m_sort_merge_passes = statement->m_sort_merge_passes;
361   m_row.m_sort_range = statement->m_sort_range;
362   m_row.m_sort_rows = statement->m_sort_rows;
363   m_row.m_sort_scan = statement->m_sort_scan;
364   m_row.m_no_index_used = statement->m_no_index_used;
365   m_row.m_no_good_index_used = statement->m_no_good_index_used;
366 
367   /* Copy the digest storage. */
368   digest->copy(&statement->m_digest_storage);
369 
370   /* Format the sqltext string for output. */
371   format_sqltext(statement->m_sqltext, statement->m_sqltext_length,
372                  get_charset(statement->m_sqltext_cs_number, MYF(0)),
373                  statement->m_sqltext_truncated, m_row.m_sqltext);
374 
375   return 0;
376 }
377 
378 /**
379   Build a row, part 2.
380 
381   This method is used after all optimist locks have been released.
382 
383   @param [in] digest Statement digest to print in the row.
384   @return 0 on success or HA_ERR_RECORD_DELETED
385 */
make_row_part_2(const sql_digest_storage * digest)386 int table_events_statements_common::make_row_part_2(
387     const sql_digest_storage *digest) {
388   /*
389     Filling up statement digest information.
390   */
391   size_t safe_byte_count = digest->m_byte_count;
392   if (safe_byte_count > 0 && safe_byte_count <= pfs_max_digest_length) {
393     /* Generate the DIGEST string from the digest */
394     DIGEST_HASH_TO_STRING(digest->m_hash, m_row.m_digest.m_digest);
395     m_row.m_digest.m_digest_length = DIGEST_HASH_TO_STRING_LENGTH;
396 
397     /* Generate the DIGEST_TEXT string from the token array */
398     compute_digest_text(digest, &m_row.m_digest.m_digest_text);
399 
400     if (m_row.m_digest.m_digest_text.length() == 0) {
401       m_row.m_digest.m_digest_length = 0;
402     }
403   } else {
404     m_row.m_digest.m_digest_length = 0;
405     m_row.m_digest.m_digest_text.length(0);
406   }
407 
408   return 0;
409 }
410 
read_row_values(TABLE * table,unsigned char * buf,Field ** fields,bool read_all)411 int table_events_statements_common::read_row_values(TABLE *table,
412                                                     unsigned char *buf,
413                                                     Field **fields,
414                                                     bool read_all) {
415   Field *f;
416   uint len;
417 
418   /* Set the null bits */
419   DBUG_ASSERT(table->s->null_bytes == 3);
420   buf[0] = 0;
421   buf[1] = 0;
422   buf[2] = 0;
423 
424   for (; (f = *fields); fields++) {
425     if (read_all || bitmap_is_set(table->read_set, f->field_index())) {
426       switch (f->field_index()) {
427         case 0: /* THREAD_ID */
428           set_field_ulonglong(f, m_row.m_thread_internal_id);
429           break;
430         case 1: /* EVENT_ID */
431           set_field_ulonglong(f, m_row.m_event_id);
432           break;
433         case 2: /* END_EVENT_ID */
434           if (m_row.m_end_event_id > 0) {
435             set_field_ulonglong(f, m_row.m_end_event_id - 1);
436           } else {
437             f->set_null();
438           }
439           break;
440         case 3: /* EVENT_NAME */
441           set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length);
442           break;
443         case 4: /* SOURCE */
444           set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length);
445           break;
446         case 5: /* TIMER_START */
447           if (m_row.m_timer_start != 0) {
448             set_field_ulonglong(f, m_row.m_timer_start);
449           } else {
450             f->set_null();
451           }
452           break;
453         case 6: /* TIMER_END */
454           if (m_row.m_timer_end != 0) {
455             set_field_ulonglong(f, m_row.m_timer_end);
456           } else {
457             f->set_null();
458           }
459           break;
460         case 7: /* TIMER_WAIT */
461           /* TIMER_START != 0 when TIMED=YES. */
462           if (m_row.m_timer_start != 0) {
463             set_field_ulonglong(f, m_row.m_timer_wait);
464           } else {
465             f->set_null();
466           }
467           break;
468         case 8: /* LOCK_TIME */
469           if (m_row.m_lock_time != 0) {
470             set_field_ulonglong(f, m_row.m_lock_time);
471           } else {
472             f->set_null();
473           }
474           break;
475         case 9: /* SQL_TEXT */
476           if (m_row.m_sqltext.length())
477             set_field_text(f, m_row.m_sqltext.ptr(), m_row.m_sqltext.length(),
478                            m_row.m_sqltext.charset());
479           else {
480             f->set_null();
481           }
482           break;
483         case 10: /* DIGEST */
484           if (m_row.m_digest.m_digest_length > 0)
485             set_field_varchar_utf8(f, m_row.m_digest.m_digest,
486                                    m_row.m_digest.m_digest_length);
487           else {
488             f->set_null();
489           }
490           break;
491         case 11: /* DIGEST_TEXT */
492           if (m_row.m_digest.m_digest_text.length() > 0)
493             set_field_blob(f, m_row.m_digest.m_digest_text.ptr(),
494                            (uint)m_row.m_digest.m_digest_text.length());
495           else {
496             f->set_null();
497           }
498           break;
499         case 12: /* CURRENT_SCHEMA */
500           if (m_row.m_current_schema_name_length)
501             set_field_varchar_utf8(f, m_row.m_current_schema_name,
502                                    m_row.m_current_schema_name_length);
503           else {
504             f->set_null();
505           }
506           break;
507         case 13: /* OBJECT_TYPE */
508           if (m_row.m_object_name_length > 0) {
509             set_field_object_type(f, m_row.m_object_type);
510           } else {
511             f->set_null();
512           }
513           break;
514         case 14: /* OBJECT_SCHEMA */
515           if (m_row.m_schema_name_length)
516             set_field_varchar_utf8(f, m_row.m_schema_name,
517                                    m_row.m_schema_name_length);
518           else {
519             f->set_null();
520           }
521           break;
522         case 15: /* OBJECT_NAME */
523           if (m_row.m_object_name_length)
524             set_field_varchar_utf8(f, m_row.m_object_name,
525                                    m_row.m_object_name_length);
526           else {
527             f->set_null();
528           }
529           break;
530         case 16: /* OBJECT_INSTANCE_BEGIN */
531           f->set_null();
532           break;
533         case 17: /* MYSQL_ERRNO */
534           set_field_ulong(f, m_row.m_sql_errno);
535           break;
536         case 18: /* RETURNED_SQLSTATE */
537           if (m_row.m_sqlstate[0] != 0) {
538             set_field_varchar_utf8(f, m_row.m_sqlstate, SQLSTATE_LENGTH);
539           } else {
540             f->set_null();
541           }
542           break;
543         case 19: /* MESSAGE_TEXT */
544           len = (uint)strlen(m_row.m_message_text);
545           if (len) {
546             set_field_varchar_utf8(f, m_row.m_message_text, len);
547           } else {
548             f->set_null();
549           }
550           break;
551         case 20: /* ERRORS */
552           set_field_ulonglong(f, m_row.m_error_count);
553           break;
554         case 21: /* WARNINGS */
555           set_field_ulonglong(f, m_row.m_warning_count);
556           break;
557         case 22: /* ROWS_AFFECTED */
558           set_field_ulonglong(f, m_row.m_rows_affected);
559           break;
560         case 23: /* ROWS_SENT */
561           set_field_ulonglong(f, m_row.m_rows_sent);
562           break;
563         case 24: /* ROWS_EXAMINED */
564           set_field_ulonglong(f, m_row.m_rows_examined);
565           break;
566         case 25: /* CREATED_TMP_DISK_TABLES */
567           set_field_ulonglong(f, m_row.m_created_tmp_disk_tables);
568           break;
569         case 26: /* CREATED_TMP_TABLES */
570           set_field_ulonglong(f, m_row.m_created_tmp_tables);
571           break;
572         case 27: /* SELECT_FULL_JOIN */
573           set_field_ulonglong(f, m_row.m_select_full_join);
574           break;
575         case 28: /* SELECT_FULL_RANGE_JOIN */
576           set_field_ulonglong(f, m_row.m_select_full_range_join);
577           break;
578         case 29: /* SELECT_RANGE */
579           set_field_ulonglong(f, m_row.m_select_range);
580           break;
581         case 30: /* SELECT_RANGE_CHECK */
582           set_field_ulonglong(f, m_row.m_select_range_check);
583           break;
584         case 31: /* SELECT_SCAN */
585           set_field_ulonglong(f, m_row.m_select_scan);
586           break;
587         case 32: /* SORT_MERGE_PASSES */
588           set_field_ulonglong(f, m_row.m_sort_merge_passes);
589           break;
590         case 33: /* SORT_RANGE */
591           set_field_ulonglong(f, m_row.m_sort_range);
592           break;
593         case 34: /* SORT_ROWS */
594           set_field_ulonglong(f, m_row.m_sort_rows);
595           break;
596         case 35: /* SORT_SCAN */
597           set_field_ulonglong(f, m_row.m_sort_scan);
598           break;
599         case 36: /* NO_INDEX_USED */
600           set_field_ulonglong(f, m_row.m_no_index_used);
601           break;
602         case 37: /* NO_GOOD_INDEX_USED */
603           set_field_ulonglong(f, m_row.m_no_good_index_used);
604           break;
605         case 38: /* NESTING_EVENT_ID */
606           if (m_row.m_nesting_event_id != 0) {
607             set_field_ulonglong(f, m_row.m_nesting_event_id);
608           } else {
609             f->set_null();
610           }
611           break;
612         case 39: /* NESTING_EVENT_TYPE */
613           if (m_row.m_nesting_event_id != 0) {
614             set_field_enum(f, m_row.m_nesting_event_type);
615           } else {
616             f->set_null();
617           }
618           break;
619         case 40: /* NESTING_EVENT_LEVEL */
620           set_field_ulong(f, m_row.m_nesting_event_level);
621           break;
622         case 41: /* STATEMENT_ID */
623           if (m_row.m_statement_id != 0) {
624             set_field_ulonglong(f, m_row.m_statement_id);
625           } else {
626             f->set_null();
627           }
628           break;
629         default:
630           DBUG_ASSERT(false);
631       }
632     }
633   }
634   return 0;
635 }
636 
create(PFS_engine_table_share *)637 PFS_engine_table *table_events_statements_current::create(
638     PFS_engine_table_share *) {
639   return new table_events_statements_current();
640 }
641 
table_events_statements_current()642 table_events_statements_current::table_events_statements_current()
643     : table_events_statements_common(&m_share, &m_pos), m_pos(), m_next_pos() {}
644 
reset_position(void)645 void table_events_statements_current::reset_position(void) {
646   m_pos.reset();
647   m_next_pos.reset();
648 }
649 
rnd_init(bool)650 int table_events_statements_current::rnd_init(bool) { return 0; }
651 
rnd_next(void)652 int table_events_statements_current::rnd_next(void) {
653   PFS_thread *pfs_thread;
654   PFS_events_statements *statement;
655   bool has_more_thread = true;
656 
657   for (m_pos.set_at(&m_next_pos); has_more_thread; m_pos.next_thread()) {
658     pfs_thread = global_thread_container.get(m_pos.m_index_1, &has_more_thread);
659     if (pfs_thread != nullptr) {
660       uint safe_events_statements_count = pfs_thread->m_events_statements_count;
661 
662       if (safe_events_statements_count == 0) {
663         /* Display the last top level statement, when completed */
664         if (m_pos.m_index_2 >= 1) {
665           continue;
666         }
667       } else {
668         /* Display all pending statements, when in progress */
669         if (m_pos.m_index_2 >= safe_events_statements_count) {
670           continue;
671         }
672       }
673 
674       statement = &pfs_thread->m_statement_stack[m_pos.m_index_2];
675 
676       m_next_pos.set_after(&m_pos);
677       return make_row(pfs_thread, statement);
678     }
679   }
680 
681   return HA_ERR_END_OF_FILE;
682 }
683 
rnd_pos(const void * pos)684 int table_events_statements_current::rnd_pos(const void *pos) {
685   PFS_thread *pfs_thread;
686   PFS_events_statements *statement;
687 
688   set_position(pos);
689 
690   pfs_thread = global_thread_container.get(m_pos.m_index_1);
691   if (pfs_thread != nullptr) {
692     uint safe_events_statements_count = pfs_thread->m_events_statements_count;
693 
694     if (safe_events_statements_count == 0) {
695       /* Display the last top level statement, when completed */
696       if (m_pos.m_index_2 >= 1) {
697         return HA_ERR_RECORD_DELETED;
698       }
699     } else {
700       /* Display all pending statements, when in progress */
701       if (m_pos.m_index_2 >= safe_events_statements_count) {
702         return HA_ERR_RECORD_DELETED;
703       }
704     }
705 
706     DBUG_ASSERT(m_pos.m_index_2 < statement_stack_max);
707 
708     statement = &pfs_thread->m_statement_stack[m_pos.m_index_2];
709 
710     if (statement->m_class != nullptr) {
711       return make_row(pfs_thread, statement);
712     }
713   }
714 
715   return HA_ERR_RECORD_DELETED;
716 }
717 
index_next(void)718 int table_events_statements_current::index_next(void) {
719   PFS_thread *pfs_thread;
720   PFS_events_statements *statement;
721   bool has_more_thread = true;
722 
723   for (m_pos.set_at(&m_next_pos); has_more_thread; m_pos.next_thread()) {
724     pfs_thread = global_thread_container.get(m_pos.m_index_1, &has_more_thread);
725     if (pfs_thread != nullptr) {
726       if (m_opened_index->match(pfs_thread)) {
727         do {
728           uint safe_events_statements_count =
729               pfs_thread->m_events_statements_count;
730           if (safe_events_statements_count == 0) {
731             /* Display the last top level statement, when completed */
732             if (m_pos.m_index_2 >= 1) {
733               break;
734             }
735           } else {
736             /* Display all pending statements, when in progress */
737             if (m_pos.m_index_2 >= safe_events_statements_count) {
738               break;
739             }
740           }
741 
742           statement = &pfs_thread->m_statement_stack[m_pos.m_index_2];
743           if (statement->m_class != nullptr) {
744             if (m_opened_index->match(statement)) {
745               if (!make_row(pfs_thread, statement)) {
746                 m_next_pos.set_after(&m_pos);
747                 return 0;
748               }
749             }
750             m_pos.set_after(&m_pos);
751           }
752         } while (statement->m_class != nullptr);
753       }
754     }
755   }
756 
757   return HA_ERR_END_OF_FILE;
758 }
759 
make_row(PFS_thread * pfs_thread,PFS_events_statements * statement)760 int table_events_statements_current::make_row(
761     PFS_thread *pfs_thread, PFS_events_statements *statement) {
762   sql_digest_storage digest;
763   pfs_optimistic_state lock;
764   pfs_optimistic_state stmt_lock;
765 
766   digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE);
767   /* Protect this reader against thread termination. */
768   pfs_thread->m_lock.begin_optimistic_lock(&lock);
769   /* Protect this reader against writing on statement information. */
770   pfs_thread->m_stmt_lock.begin_optimistic_lock(&stmt_lock);
771 
772   if (table_events_statements_common::make_row_part_1(statement, &digest) !=
773       0) {
774     return HA_ERR_RECORD_DELETED;
775   }
776 
777   if (!pfs_thread->m_stmt_lock.end_optimistic_lock(&stmt_lock) ||
778       !pfs_thread->m_lock.end_optimistic_lock(&lock)) {
779     return HA_ERR_RECORD_DELETED;
780   }
781 
782   return table_events_statements_common::make_row_part_2(&digest);
783 }
784 
delete_all_rows(void)785 int table_events_statements_current::delete_all_rows(void) {
786   reset_events_statements_current();
787   return 0;
788 }
789 
get_row_count(void)790 ha_rows table_events_statements_current::get_row_count(void) {
791   return global_thread_container.get_row_count() * statement_stack_max;
792 }
793 
index_init(uint idx MY_ATTRIBUTE ((unused)),bool)794 int table_events_statements_current::index_init(uint idx MY_ATTRIBUTE((unused)),
795                                                 bool) {
796   PFS_index_events_statements *result;
797   DBUG_ASSERT(idx == 0);
798   result = PFS_NEW(PFS_index_events_statements);
799   m_opened_index = result;
800   m_index = result;
801   return 0;
802 }
803 
create(PFS_engine_table_share *)804 PFS_engine_table *table_events_statements_history::create(
805     PFS_engine_table_share *) {
806   return new table_events_statements_history();
807 }
808 
table_events_statements_history()809 table_events_statements_history::table_events_statements_history()
810     : table_events_statements_common(&m_share, &m_pos), m_pos(), m_next_pos() {}
811 
reset_position(void)812 void table_events_statements_history::reset_position(void) {
813   m_pos.reset();
814   m_next_pos.reset();
815 }
816 
rnd_init(bool)817 int table_events_statements_history::rnd_init(bool) { return 0; }
818 
rnd_next(void)819 int table_events_statements_history::rnd_next(void) {
820   PFS_thread *pfs_thread;
821   PFS_events_statements *statement;
822   bool has_more_thread = true;
823 
824   if (events_statements_history_per_thread == 0) {
825     return HA_ERR_END_OF_FILE;
826   }
827 
828   for (m_pos.set_at(&m_next_pos); has_more_thread; m_pos.next_thread()) {
829     pfs_thread = global_thread_container.get(m_pos.m_index_1, &has_more_thread);
830     if (pfs_thread != nullptr) {
831       if (m_pos.m_index_2 >= events_statements_history_per_thread) {
832         /* This thread does not have more (full) history */
833         continue;
834       }
835 
836       if (!pfs_thread->m_statements_history_full &&
837           (m_pos.m_index_2 >= pfs_thread->m_statements_history_index)) {
838         /* This thread does not have more (not full) history */
839         continue;
840       }
841 
842       statement = &pfs_thread->m_statements_history[m_pos.m_index_2];
843 
844       if (statement->m_class != nullptr) {
845         /* Next iteration, look for the next history in this thread */
846         m_next_pos.set_after(&m_pos);
847         return make_row(pfs_thread, statement);
848       }
849     }
850   }
851 
852   return HA_ERR_END_OF_FILE;
853 }
854 
rnd_pos(const void * pos)855 int table_events_statements_history::rnd_pos(const void *pos) {
856   PFS_thread *pfs_thread;
857   PFS_events_statements *statement;
858 
859   DBUG_ASSERT(events_statements_history_per_thread != 0);
860   set_position(pos);
861 
862   pfs_thread = global_thread_container.get(m_pos.m_index_1);
863   if (pfs_thread != nullptr) {
864     DBUG_ASSERT(m_pos.m_index_2 < events_statements_history_per_thread);
865 
866     if (!pfs_thread->m_statements_history_full &&
867         (m_pos.m_index_2 >= pfs_thread->m_statements_history_index)) {
868       return HA_ERR_RECORD_DELETED;
869     }
870 
871     statement = &pfs_thread->m_statements_history[m_pos.m_index_2];
872     if (statement->m_class != nullptr) {
873       return make_row(pfs_thread, statement);
874     }
875   }
876 
877   return HA_ERR_RECORD_DELETED;
878 }
879 
index_next(void)880 int table_events_statements_history::index_next(void) {
881   PFS_thread *pfs_thread;
882   PFS_events_statements *statement;
883   bool has_more_thread = true;
884 
885   if (events_statements_history_per_thread == 0) {
886     return HA_ERR_END_OF_FILE;
887   }
888 
889   for (m_pos.set_at(&m_next_pos); has_more_thread; m_pos.next_thread()) {
890     pfs_thread = global_thread_container.get(m_pos.m_index_1, &has_more_thread);
891     if (pfs_thread != nullptr) {
892       if (m_opened_index->match(pfs_thread)) {
893         do {
894           if (m_pos.m_index_2 >= events_statements_history_per_thread) {
895             /* This thread does not have more (full) history */
896             break;
897           }
898 
899           if (!pfs_thread->m_statements_history_full &&
900               (m_pos.m_index_2 >= pfs_thread->m_statements_history_index)) {
901             /* This thread does not have more (not full) history */
902             break;
903           }
904 
905           statement = &pfs_thread->m_statements_history[m_pos.m_index_2];
906           if (statement->m_class != nullptr) {
907             if (m_opened_index->match(statement)) {
908               if (!make_row(pfs_thread, statement)) {
909                 m_next_pos.set_after(&m_pos);
910                 return 0;
911               }
912             }
913             m_pos.set_after(&m_pos);
914           }
915         } while (statement->m_class != nullptr);
916       }
917     }
918   }
919 
920   return HA_ERR_END_OF_FILE;
921 }
922 
make_row(PFS_thread * pfs_thread,PFS_events_statements * statement)923 int table_events_statements_history::make_row(
924     PFS_thread *pfs_thread, PFS_events_statements *statement) {
925   sql_digest_storage digest;
926   pfs_optimistic_state lock;
927 
928   digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE);
929   /* Protect this reader against thread termination. */
930   pfs_thread->m_lock.begin_optimistic_lock(&lock);
931 
932   if (table_events_statements_common::make_row_part_1(statement, &digest) !=
933       0) {
934     return HA_ERR_RECORD_DELETED;
935   }
936 
937   if (!pfs_thread->m_lock.end_optimistic_lock(&lock)) {
938     return HA_ERR_RECORD_DELETED;
939   }
940 
941   return table_events_statements_common::make_row_part_2(&digest);
942 }
943 
delete_all_rows(void)944 int table_events_statements_history::delete_all_rows(void) {
945   reset_events_statements_history();
946   return 0;
947 }
948 
get_row_count(void)949 ha_rows table_events_statements_history::get_row_count(void) {
950   return events_statements_history_per_thread *
951          global_thread_container.get_row_count();
952 }
953 
index_init(uint idx MY_ATTRIBUTE ((unused)),bool)954 int table_events_statements_history::index_init(uint idx MY_ATTRIBUTE((unused)),
955                                                 bool) {
956   PFS_index_events_statements *result;
957   DBUG_ASSERT(idx == 0);
958   result = PFS_NEW(PFS_index_events_statements);
959   m_opened_index = result;
960   m_index = result;
961   return 0;
962 }
963 
create(PFS_engine_table_share *)964 PFS_engine_table *table_events_statements_history_long::create(
965     PFS_engine_table_share *) {
966   return new table_events_statements_history_long();
967 }
968 
table_events_statements_history_long()969 table_events_statements_history_long::table_events_statements_history_long()
970     : table_events_statements_common(&m_share, &m_pos),
971       m_pos(0),
972       m_next_pos(0) {}
973 
reset_position(void)974 void table_events_statements_history_long::reset_position(void) {
975   m_pos.m_index = 0;
976   m_next_pos.m_index = 0;
977 }
978 
rnd_init(bool)979 int table_events_statements_history_long::rnd_init(bool) { return 0; }
980 
rnd_next(void)981 int table_events_statements_history_long::rnd_next(void) {
982   PFS_events_statements *statement;
983   size_t limit;
984 
985   if (events_statements_history_long_size == 0) {
986     return HA_ERR_END_OF_FILE;
987   }
988 
989   if (events_statements_history_long_full) {
990     limit = events_statements_history_long_size;
991   } else
992     limit = events_statements_history_long_index.m_u32 %
993             events_statements_history_long_size;
994 
995   for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next()) {
996     statement = &events_statements_history_long_array[m_pos.m_index];
997 
998     if (statement->m_class != nullptr) {
999       /* Next iteration, look for the next entry */
1000       m_next_pos.set_after(&m_pos);
1001       return make_row(statement);
1002     }
1003   }
1004 
1005   return HA_ERR_END_OF_FILE;
1006 }
1007 
rnd_pos(const void * pos)1008 int table_events_statements_history_long::rnd_pos(const void *pos) {
1009   PFS_events_statements *statement;
1010   size_t limit;
1011 
1012   if (events_statements_history_long_size == 0) {
1013     return HA_ERR_RECORD_DELETED;
1014   }
1015 
1016   set_position(pos);
1017 
1018   if (events_statements_history_long_full) {
1019     limit = events_statements_history_long_size;
1020   } else
1021     limit = events_statements_history_long_index.m_u32 %
1022             events_statements_history_long_size;
1023 
1024   if (m_pos.m_index >= limit) {
1025     return HA_ERR_RECORD_DELETED;
1026   }
1027 
1028   statement = &events_statements_history_long_array[m_pos.m_index];
1029 
1030   if (statement->m_class == nullptr) {
1031     return HA_ERR_RECORD_DELETED;
1032   }
1033 
1034   return make_row(statement);
1035 }
1036 
make_row(PFS_events_statements * statement)1037 int table_events_statements_history_long::make_row(
1038     PFS_events_statements *statement) {
1039   sql_digest_storage digest;
1040 
1041   digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE);
1042   if (table_events_statements_common::make_row_part_1(statement, &digest) !=
1043       0) {
1044     return HA_ERR_RECORD_DELETED;
1045   }
1046 
1047   return table_events_statements_common::make_row_part_2(&digest);
1048 }
1049 
delete_all_rows(void)1050 int table_events_statements_history_long::delete_all_rows(void) {
1051   reset_events_statements_history_long();
1052   return 0;
1053 }
1054 
get_row_count(void)1055 ha_rows table_events_statements_history_long::get_row_count(void) {
1056   return events_statements_history_long_size;
1057 }
1058