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