1 | /* Copyright (c) 2010, 2016, 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 as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software Foundation, |
14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ |
15 | |
16 | /** |
17 | @file storage/perfschema/table_events_statements.cc |
18 | Table EVENTS_STATEMENTS_xxx (implementation). |
19 | */ |
20 | |
21 | #include "my_global.h" |
22 | #include "my_pthread.h" |
23 | #include "table_events_statements.h" |
24 | #include "pfs_instr_class.h" |
25 | #include "pfs_instr.h" |
26 | #include "pfs_events_statements.h" |
27 | #include "pfs_timer.h" |
28 | #include "sp_head.h" /* TYPE_ENUM_FUNCTION, ... */ |
29 | #include "table_helper.h" |
30 | #include "my_md5.h" |
31 | |
32 | THR_LOCK table_events_statements_current::m_table_lock; |
33 | |
34 | PFS_engine_table_share |
35 | table_events_statements_current::m_share= |
36 | { |
37 | { C_STRING_WITH_LEN("events_statements_current" ) }, |
38 | &pfs_truncatable_acl, |
39 | &table_events_statements_current::create, |
40 | NULL, /* write_row */ |
41 | &table_events_statements_current::delete_all_rows, |
42 | NULL, /* get_row_count */ |
43 | 1000, /* records */ |
44 | sizeof(pos_events_statements_current), /* ref length */ |
45 | &m_table_lock, |
46 | { C_STRING_WITH_LEN("CREATE TABLE events_statements_current(" |
47 | "THREAD_ID BIGINT unsigned not null," |
48 | "EVENT_ID BIGINT unsigned not null," |
49 | "END_EVENT_ID BIGINT unsigned," |
50 | "EVENT_NAME VARCHAR(128) not null," |
51 | "SOURCE VARCHAR(64)," |
52 | "TIMER_START BIGINT unsigned," |
53 | "TIMER_END BIGINT unsigned," |
54 | "TIMER_WAIT BIGINT unsigned," |
55 | "LOCK_TIME bigint unsigned not null," |
56 | "SQL_TEXT LONGTEXT," |
57 | "DIGEST VARCHAR(32)," |
58 | "DIGEST_TEXT LONGTEXT," |
59 | "CURRENT_SCHEMA VARCHAR(64)," |
60 | "OBJECT_TYPE VARCHAR(64)," |
61 | "OBJECT_SCHEMA VARCHAR(64)," |
62 | "OBJECT_NAME VARCHAR(64)," |
63 | "OBJECT_INSTANCE_BEGIN BIGINT unsigned," |
64 | "MYSQL_ERRNO INTEGER," |
65 | "RETURNED_SQLSTATE VARCHAR(5)," |
66 | "MESSAGE_TEXT VARCHAR(128)," |
67 | "ERRORS BIGINT unsigned not null," |
68 | "WARNINGS BIGINT unsigned not null," |
69 | "ROWS_AFFECTED BIGINT unsigned not null," |
70 | "ROWS_SENT BIGINT unsigned not null," |
71 | "ROWS_EXAMINED BIGINT unsigned not null," |
72 | "CREATED_TMP_DISK_TABLES BIGINT unsigned not null," |
73 | "CREATED_TMP_TABLES BIGINT unsigned not null," |
74 | "SELECT_FULL_JOIN BIGINT unsigned not null," |
75 | "SELECT_FULL_RANGE_JOIN BIGINT unsigned not null," |
76 | "SELECT_RANGE BIGINT unsigned not null," |
77 | "SELECT_RANGE_CHECK BIGINT unsigned not null," |
78 | "SELECT_SCAN BIGINT unsigned not null," |
79 | "SORT_MERGE_PASSES BIGINT unsigned not null," |
80 | "SORT_RANGE BIGINT unsigned not null," |
81 | "SORT_ROWS BIGINT unsigned not null," |
82 | "SORT_SCAN BIGINT unsigned not null," |
83 | "NO_INDEX_USED BIGINT unsigned not null," |
84 | "NO_GOOD_INDEX_USED BIGINT unsigned not null," |
85 | "NESTING_EVENT_ID BIGINT unsigned," |
86 | "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))" ) } |
87 | }; |
88 | |
89 | THR_LOCK table_events_statements_history::m_table_lock; |
90 | |
91 | PFS_engine_table_share |
92 | table_events_statements_history::m_share= |
93 | { |
94 | { C_STRING_WITH_LEN("events_statements_history" ) }, |
95 | &pfs_truncatable_acl, |
96 | &table_events_statements_history::create, |
97 | NULL, /* write_row */ |
98 | &table_events_statements_history::delete_all_rows, |
99 | NULL, /* get_row_count */ |
100 | 1000, /* records */ |
101 | sizeof(pos_events_statements_history), /* ref length */ |
102 | &m_table_lock, |
103 | { C_STRING_WITH_LEN("CREATE TABLE events_statements_history(" |
104 | "THREAD_ID BIGINT unsigned not null," |
105 | "EVENT_ID BIGINT unsigned not null," |
106 | "END_EVENT_ID BIGINT unsigned," |
107 | "EVENT_NAME VARCHAR(128) not null," |
108 | "SOURCE VARCHAR(64)," |
109 | "TIMER_START BIGINT unsigned," |
110 | "TIMER_END BIGINT unsigned," |
111 | "TIMER_WAIT BIGINT unsigned," |
112 | "LOCK_TIME bigint unsigned not null," |
113 | "SQL_TEXT LONGTEXT," |
114 | "DIGEST VARCHAR(32)," |
115 | "DIGEST_TEXT LONGTEXT," |
116 | "CURRENT_SCHEMA VARCHAR(64)," |
117 | "OBJECT_TYPE VARCHAR(64)," |
118 | "OBJECT_SCHEMA VARCHAR(64)," |
119 | "OBJECT_NAME VARCHAR(64)," |
120 | "OBJECT_INSTANCE_BEGIN BIGINT unsigned," |
121 | "MYSQL_ERRNO INTEGER," |
122 | "RETURNED_SQLSTATE VARCHAR(5)," |
123 | "MESSAGE_TEXT VARCHAR(128)," |
124 | "ERRORS BIGINT unsigned not null," |
125 | "WARNINGS BIGINT unsigned not null," |
126 | "ROWS_AFFECTED BIGINT unsigned not null," |
127 | "ROWS_SENT BIGINT unsigned not null," |
128 | "ROWS_EXAMINED BIGINT unsigned not null," |
129 | "CREATED_TMP_DISK_TABLES BIGINT unsigned not null," |
130 | "CREATED_TMP_TABLES BIGINT unsigned not null," |
131 | "SELECT_FULL_JOIN BIGINT unsigned not null," |
132 | "SELECT_FULL_RANGE_JOIN BIGINT unsigned not null," |
133 | "SELECT_RANGE BIGINT unsigned not null," |
134 | "SELECT_RANGE_CHECK BIGINT unsigned not null," |
135 | "SELECT_SCAN BIGINT unsigned not null," |
136 | "SORT_MERGE_PASSES BIGINT unsigned not null," |
137 | "SORT_RANGE BIGINT unsigned not null," |
138 | "SORT_ROWS BIGINT unsigned not null," |
139 | "SORT_SCAN BIGINT unsigned not null," |
140 | "NO_INDEX_USED BIGINT unsigned not null," |
141 | "NO_GOOD_INDEX_USED BIGINT unsigned not null," |
142 | "NESTING_EVENT_ID BIGINT unsigned," |
143 | "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))" ) } |
144 | }; |
145 | |
146 | THR_LOCK table_events_statements_history_long::m_table_lock; |
147 | |
148 | PFS_engine_table_share |
149 | table_events_statements_history_long::m_share= |
150 | { |
151 | { C_STRING_WITH_LEN("events_statements_history_long" ) }, |
152 | &pfs_truncatable_acl, |
153 | &table_events_statements_history_long::create, |
154 | NULL, /* write_row */ |
155 | &table_events_statements_history_long::delete_all_rows, |
156 | NULL, /* get_row_count */ |
157 | 10000, /* records */ |
158 | sizeof(PFS_simple_index), /* ref length */ |
159 | &m_table_lock, |
160 | { C_STRING_WITH_LEN("CREATE TABLE events_statements_history_long(" |
161 | "THREAD_ID BIGINT unsigned not null," |
162 | "EVENT_ID BIGINT unsigned not null," |
163 | "END_EVENT_ID BIGINT unsigned," |
164 | "EVENT_NAME VARCHAR(128) not null," |
165 | "SOURCE VARCHAR(64)," |
166 | "TIMER_START BIGINT unsigned," |
167 | "TIMER_END BIGINT unsigned," |
168 | "TIMER_WAIT BIGINT unsigned," |
169 | "LOCK_TIME bigint unsigned not null," |
170 | "SQL_TEXT LONGTEXT," |
171 | "DIGEST VARCHAR(32)," |
172 | "DIGEST_TEXT LONGTEXT," |
173 | "CURRENT_SCHEMA VARCHAR(64)," |
174 | "OBJECT_TYPE VARCHAR(64)," |
175 | "OBJECT_SCHEMA VARCHAR(64)," |
176 | "OBJECT_NAME VARCHAR(64)," |
177 | "OBJECT_INSTANCE_BEGIN BIGINT unsigned," |
178 | "MYSQL_ERRNO INTEGER," |
179 | "RETURNED_SQLSTATE VARCHAR(5)," |
180 | "MESSAGE_TEXT VARCHAR(128)," |
181 | "ERRORS BIGINT unsigned not null," |
182 | "WARNINGS BIGINT unsigned not null," |
183 | "ROWS_AFFECTED BIGINT unsigned not null," |
184 | "ROWS_SENT BIGINT unsigned not null," |
185 | "ROWS_EXAMINED BIGINT unsigned not null," |
186 | "CREATED_TMP_DISK_TABLES BIGINT unsigned not null," |
187 | "CREATED_TMP_TABLES BIGINT unsigned not null," |
188 | "SELECT_FULL_JOIN BIGINT unsigned not null," |
189 | "SELECT_FULL_RANGE_JOIN BIGINT unsigned not null," |
190 | "SELECT_RANGE BIGINT unsigned not null," |
191 | "SELECT_RANGE_CHECK BIGINT unsigned not null," |
192 | "SELECT_SCAN BIGINT unsigned not null," |
193 | "SORT_MERGE_PASSES BIGINT unsigned not null," |
194 | "SORT_RANGE BIGINT unsigned not null," |
195 | "SORT_ROWS BIGINT unsigned not null," |
196 | "SORT_SCAN BIGINT unsigned not null," |
197 | "NO_INDEX_USED BIGINT unsigned not null," |
198 | "NO_GOOD_INDEX_USED BIGINT unsigned not null," |
199 | "NESTING_EVENT_ID BIGINT unsigned," |
200 | "NESTING_EVENT_TYPE ENUM('STATEMENT', 'STAGE', 'WAIT'))" ) } |
201 | }; |
202 | |
203 | table_events_statements_common::table_events_statements_common |
204 | (const PFS_engine_table_share *share, void *pos) |
205 | : PFS_engine_table(share, pos), |
206 | m_row_exists(false) |
207 | {} |
208 | |
209 | /** |
210 | Build a row. |
211 | @param statement the statement the cursor is reading |
212 | */ |
213 | void table_events_statements_common::make_row_part_1(PFS_events_statements *statement, |
214 | sql_digest_storage *digest) |
215 | { |
216 | const char *base; |
217 | const char *safe_source_file; |
218 | ulonglong timer_end; |
219 | |
220 | m_row_exists= false; |
221 | |
222 | PFS_statement_class *unsafe= (PFS_statement_class*) statement->m_class; |
223 | PFS_statement_class *klass= sanitize_statement_class(unsafe); |
224 | if (unlikely(klass == NULL)) |
225 | return; |
226 | |
227 | m_row.m_thread_internal_id= statement->m_thread_internal_id; |
228 | m_row.m_event_id= statement->m_event_id; |
229 | m_row.m_end_event_id= statement->m_end_event_id; |
230 | m_row.m_nesting_event_id= statement->m_nesting_event_id; |
231 | m_row.m_nesting_event_type= statement->m_nesting_event_type; |
232 | |
233 | if (m_row.m_end_event_id == 0) |
234 | { |
235 | timer_end= get_timer_raw_value(statement_timer); |
236 | } |
237 | else |
238 | { |
239 | timer_end= statement->m_timer_end; |
240 | } |
241 | |
242 | m_normalizer->to_pico(statement->m_timer_start, timer_end, |
243 | & m_row.m_timer_start, & m_row.m_timer_end, & m_row.m_timer_wait); |
244 | m_row.m_lock_time= statement->m_lock_time * MICROSEC_TO_PICOSEC; |
245 | |
246 | m_row.m_name= klass->m_name; |
247 | m_row.m_name_length= klass->m_name_length; |
248 | |
249 | CHARSET_INFO *cs= get_charset(statement->m_sqltext_cs_number, MYF(0)); |
250 | size_t valid_length= statement->m_sqltext_length; |
251 | |
252 | if (cs != NULL) |
253 | { |
254 | if (cs->mbmaxlen > 1) |
255 | { |
256 | valid_length= Well_formed_prefix(cs, |
257 | statement->m_sqltext, |
258 | valid_length).length(); |
259 | } |
260 | } |
261 | |
262 | m_row.m_sqltext.set_charset(cs); |
263 | m_row.m_sqltext.length(0); |
264 | m_row.m_sqltext.append(statement->m_sqltext, (uint32)valid_length, cs); |
265 | |
266 | /* Indicate that sqltext is truncated or not well-formed. */ |
267 | if (statement->m_sqltext_truncated || valid_length < statement->m_sqltext_length) |
268 | { |
269 | size_t chars= m_row.m_sqltext.numchars(); |
270 | if (chars > 3) |
271 | { |
272 | chars-= 3; |
273 | uint32 bytes_offset= m_row.m_sqltext.charpos(chars, 0); |
274 | m_row.m_sqltext.length(bytes_offset); |
275 | m_row.m_sqltext.append("..." , 3); |
276 | } |
277 | } |
278 | |
279 | m_row.m_current_schema_name_length= statement->m_current_schema_name_length; |
280 | if (m_row.m_current_schema_name_length > 0) |
281 | memcpy(m_row.m_current_schema_name, statement->m_current_schema_name, m_row.m_current_schema_name_length); |
282 | |
283 | safe_source_file= statement->m_source_file; |
284 | if (unlikely(safe_source_file == NULL)) |
285 | return; |
286 | |
287 | base= base_name(safe_source_file); |
288 | m_row.m_source_length= (uint)my_snprintf(m_row.m_source, sizeof(m_row.m_source), |
289 | "%s:%d" , base, statement->m_source_line); |
290 | if (m_row.m_source_length > sizeof(m_row.m_source)) |
291 | m_row.m_source_length= sizeof(m_row.m_source); |
292 | |
293 | memcpy(m_row.m_message_text, statement->m_message_text, sizeof(m_row.m_message_text)); |
294 | m_row.m_sql_errno= statement->m_sql_errno; |
295 | memcpy(m_row.m_sqlstate, statement->m_sqlstate, SQLSTATE_LENGTH); |
296 | m_row.m_error_count= statement->m_error_count; |
297 | m_row.m_warning_count= statement->m_warning_count; |
298 | m_row.m_rows_affected= statement->m_rows_affected; |
299 | |
300 | m_row.m_rows_sent= statement->m_rows_sent; |
301 | m_row.m_rows_examined= statement->m_rows_examined; |
302 | m_row.m_created_tmp_disk_tables= statement->m_created_tmp_disk_tables; |
303 | m_row.m_created_tmp_tables= statement->m_created_tmp_tables; |
304 | m_row.m_select_full_join= statement->m_select_full_join; |
305 | m_row.m_select_full_range_join= statement->m_select_full_range_join; |
306 | m_row.m_select_range= statement->m_select_range; |
307 | m_row.m_select_range_check= statement->m_select_range_check; |
308 | m_row.m_select_scan= statement->m_select_scan; |
309 | m_row.m_sort_merge_passes= statement->m_sort_merge_passes; |
310 | m_row.m_sort_range= statement->m_sort_range; |
311 | m_row.m_sort_rows= statement->m_sort_rows; |
312 | m_row.m_sort_scan= statement->m_sort_scan; |
313 | m_row.m_no_index_used= statement->m_no_index_used; |
314 | m_row.m_no_good_index_used= statement->m_no_good_index_used; |
315 | /* |
316 | Making a copy of digest storage. |
317 | */ |
318 | digest->copy(& statement->m_digest_storage); |
319 | |
320 | m_row_exists= true; |
321 | return; |
322 | } |
323 | |
324 | |
325 | void table_events_statements_common::make_row_part_2(const sql_digest_storage *digest) |
326 | { |
327 | /* |
328 | Filling up statement digest information. |
329 | */ |
330 | size_t safe_byte_count= digest->m_byte_count; |
331 | if (safe_byte_count > 0 && |
332 | safe_byte_count <= pfs_max_digest_length) |
333 | { |
334 | /* Generate the DIGEST string from the MD5 digest */ |
335 | MD5_HASH_TO_STRING(digest->m_md5, |
336 | m_row.m_digest.m_digest); |
337 | m_row.m_digest.m_digest_length= MD5_HASH_TO_STRING_LENGTH; |
338 | |
339 | /* Generate the DIGEST_TEXT string from the token array */ |
340 | compute_digest_text(digest, &m_row.m_digest.m_digest_text); |
341 | |
342 | if (m_row.m_digest.m_digest_text.length() == 0) |
343 | m_row.m_digest.m_digest_length= 0; |
344 | } |
345 | else |
346 | { |
347 | m_row.m_digest.m_digest_length= 0; |
348 | m_row.m_digest.m_digest_text.length(0); |
349 | } |
350 | |
351 | return; |
352 | } |
353 | |
354 | int table_events_statements_common::read_row_values(TABLE *table, |
355 | unsigned char *buf, |
356 | Field **fields, |
357 | bool read_all) |
358 | { |
359 | Field *f; |
360 | uint len; |
361 | |
362 | if (unlikely(! m_row_exists)) |
363 | return HA_ERR_RECORD_DELETED; |
364 | |
365 | /* Set the null bits */ |
366 | DBUG_ASSERT(table->s->null_bytes == 3); |
367 | buf[0]= 0; |
368 | buf[1]= 0; |
369 | buf[2]= 0; |
370 | |
371 | for (; (f= *fields) ; fields++) |
372 | { |
373 | if (read_all || bitmap_is_set(table->read_set, f->field_index)) |
374 | { |
375 | switch(f->field_index) |
376 | { |
377 | case 0: /* THREAD_ID */ |
378 | set_field_ulonglong(f, m_row.m_thread_internal_id); |
379 | break; |
380 | case 1: /* EVENT_ID */ |
381 | set_field_ulonglong(f, m_row.m_event_id); |
382 | break; |
383 | case 2: /* END_EVENT_ID */ |
384 | if (m_row.m_end_event_id > 0) |
385 | set_field_ulonglong(f, m_row.m_end_event_id - 1); |
386 | else |
387 | f->set_null(); |
388 | break; |
389 | case 3: /* EVENT_NAME */ |
390 | set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length); |
391 | break; |
392 | case 4: /* SOURCE */ |
393 | set_field_varchar_utf8(f, m_row.m_source, m_row.m_source_length); |
394 | break; |
395 | case 5: /* TIMER_START */ |
396 | if (m_row.m_timer_start != 0) |
397 | set_field_ulonglong(f, m_row.m_timer_start); |
398 | else |
399 | f->set_null(); |
400 | break; |
401 | case 6: /* TIMER_END */ |
402 | if (m_row.m_timer_end != 0) |
403 | set_field_ulonglong(f, m_row.m_timer_end); |
404 | else |
405 | f->set_null(); |
406 | break; |
407 | case 7: /* TIMER_WAIT */ |
408 | if (m_row.m_timer_wait != 0) |
409 | set_field_ulonglong(f, m_row.m_timer_wait); |
410 | else |
411 | f->set_null(); |
412 | break; |
413 | case 8: /* LOCK_TIME */ |
414 | if (m_row.m_lock_time != 0) |
415 | set_field_ulonglong(f, m_row.m_lock_time); |
416 | else |
417 | f->set_null(); |
418 | break; |
419 | case 9: /* SQL_TEXT */ |
420 | if (m_row.m_sqltext.length()) |
421 | set_field_longtext_utf8(f, m_row.m_sqltext.ptr(), m_row.m_sqltext.length()); |
422 | else |
423 | f->set_null(); |
424 | break; |
425 | case 10: /* DIGEST */ |
426 | if (m_row.m_digest.m_digest_length > 0) |
427 | set_field_varchar_utf8(f, m_row.m_digest.m_digest, |
428 | m_row.m_digest.m_digest_length); |
429 | else |
430 | f->set_null(); |
431 | break; |
432 | case 11: /* DIGEST_TEXT */ |
433 | if (m_row.m_digest.m_digest_text.length() > 0) |
434 | set_field_longtext_utf8(f, m_row.m_digest.m_digest_text.ptr(), |
435 | m_row.m_digest.m_digest_text.length()); |
436 | else |
437 | f->set_null(); |
438 | break; |
439 | case 12: /* CURRENT_SCHEMA */ |
440 | if (m_row.m_current_schema_name_length) |
441 | set_field_varchar_utf8(f, m_row.m_current_schema_name, m_row.m_current_schema_name_length); |
442 | else |
443 | f->set_null(); |
444 | break; |
445 | case 13: /* OBJECT_TYPE */ |
446 | f->set_null(); |
447 | break; |
448 | case 14: /* OBJECT_SCHEMA */ |
449 | f->set_null(); |
450 | break; |
451 | case 15: /* OBJECT_NAME */ |
452 | f->set_null(); |
453 | break; |
454 | case 16: /* OBJECT_INSTANCE_BEGIN */ |
455 | f->set_null(); |
456 | break; |
457 | case 17: /* MYSQL_ERRNO */ |
458 | set_field_ulong(f, m_row.m_sql_errno); |
459 | break; |
460 | case 18: /* RETURNED_SQLSTATE */ |
461 | if (m_row.m_sqlstate[0] != 0) |
462 | set_field_varchar_utf8(f, m_row.m_sqlstate, SQLSTATE_LENGTH); |
463 | else |
464 | f->set_null(); |
465 | break; |
466 | case 19: /* MESSAGE_TEXT */ |
467 | len= (uint)strlen(m_row.m_message_text); |
468 | if (len) |
469 | set_field_varchar_utf8(f, m_row.m_message_text, len); |
470 | else |
471 | f->set_null(); |
472 | break; |
473 | case 20: /* ERRORS */ |
474 | set_field_ulonglong(f, m_row.m_error_count); |
475 | break; |
476 | case 21: /* WARNINGS */ |
477 | set_field_ulonglong(f, m_row.m_warning_count); |
478 | break; |
479 | case 22: /* ROWS_AFFECTED */ |
480 | set_field_ulonglong(f, m_row.m_rows_affected); |
481 | break; |
482 | case 23: /* ROWS_SENT */ |
483 | set_field_ulonglong(f, m_row.m_rows_sent); |
484 | break; |
485 | case 24: /* ROWS_EXAMINED */ |
486 | set_field_ulonglong(f, m_row.m_rows_examined); |
487 | break; |
488 | case 25: /* CREATED_TMP_DISK_TABLES */ |
489 | set_field_ulonglong(f, m_row.m_created_tmp_disk_tables); |
490 | break; |
491 | case 26: /* CREATED_TMP_TABLES */ |
492 | set_field_ulonglong(f, m_row.m_created_tmp_tables); |
493 | break; |
494 | case 27: /* SELECT_FULL_JOIN */ |
495 | set_field_ulonglong(f, m_row.m_select_full_join); |
496 | break; |
497 | case 28: /* SELECT_FULL_RANGE_JOIN */ |
498 | set_field_ulonglong(f, m_row.m_select_full_range_join); |
499 | break; |
500 | case 29: /* SELECT_RANGE */ |
501 | set_field_ulonglong(f, m_row.m_select_range); |
502 | break; |
503 | case 30: /* SELECT_RANGE_CHECK */ |
504 | set_field_ulonglong(f, m_row.m_select_range_check); |
505 | break; |
506 | case 31: /* SELECT_SCAN */ |
507 | set_field_ulonglong(f, m_row.m_select_scan); |
508 | break; |
509 | case 32: /* SORT_MERGE_PASSES */ |
510 | set_field_ulonglong(f, m_row.m_sort_merge_passes); |
511 | break; |
512 | case 33: /* SORT_RANGE */ |
513 | set_field_ulonglong(f, m_row.m_sort_range); |
514 | break; |
515 | case 34: /* SORT_ROWS */ |
516 | set_field_ulonglong(f, m_row.m_sort_rows); |
517 | break; |
518 | case 35: /* SORT_SCAN */ |
519 | set_field_ulonglong(f, m_row.m_sort_scan); |
520 | break; |
521 | case 36: /* NO_INDEX_USED */ |
522 | set_field_ulonglong(f, m_row.m_no_index_used); |
523 | break; |
524 | case 37: /* NO_GOOD_INDEX_USED */ |
525 | set_field_ulonglong(f, m_row.m_no_good_index_used); |
526 | break; |
527 | case 38: /* NESTING_EVENT_ID */ |
528 | if (m_row.m_nesting_event_id != 0) |
529 | set_field_ulonglong(f, m_row.m_nesting_event_id); |
530 | else |
531 | f->set_null(); |
532 | break; |
533 | case 39: /* NESTING_EVENT_TYPE */ |
534 | if (m_row.m_nesting_event_id != 0) |
535 | set_field_enum(f, m_row.m_nesting_event_type); |
536 | else |
537 | f->set_null(); |
538 | break; |
539 | default: |
540 | DBUG_ASSERT(false); |
541 | } |
542 | } |
543 | } |
544 | return 0; |
545 | } |
546 | |
547 | PFS_engine_table* table_events_statements_current::create(void) |
548 | { |
549 | return new table_events_statements_current(); |
550 | } |
551 | |
552 | table_events_statements_current::table_events_statements_current() |
553 | : table_events_statements_common(&m_share, &m_pos), |
554 | m_pos(), m_next_pos() |
555 | {} |
556 | |
557 | void table_events_statements_current::reset_position(void) |
558 | { |
559 | m_pos.reset(); |
560 | m_next_pos.reset(); |
561 | } |
562 | |
563 | int table_events_statements_current::rnd_init(bool scan) |
564 | { |
565 | m_normalizer= time_normalizer::get(statement_timer); |
566 | return 0; |
567 | } |
568 | |
569 | int table_events_statements_current::rnd_next(void) |
570 | { |
571 | PFS_thread *pfs_thread; |
572 | PFS_events_statements *statement; |
573 | |
574 | for (m_pos.set_at(&m_next_pos); |
575 | m_pos.m_index_1 < thread_max; |
576 | m_pos.next_thread()) |
577 | { |
578 | pfs_thread= &thread_array[m_pos.m_index_1]; |
579 | |
580 | if (! pfs_thread->m_lock.is_populated()) |
581 | { |
582 | /* This thread does not exist */ |
583 | continue; |
584 | } |
585 | |
586 | uint safe_events_statements_count= pfs_thread->m_events_statements_count; |
587 | |
588 | if (safe_events_statements_count == 0) |
589 | { |
590 | /* Display the last top level statement, when completed */ |
591 | if (m_pos.m_index_2 >= 1) |
592 | continue; |
593 | } |
594 | else |
595 | { |
596 | /* Display all pending statements, when in progress */ |
597 | if (m_pos.m_index_2 >= safe_events_statements_count) |
598 | continue; |
599 | } |
600 | |
601 | statement= &pfs_thread->m_statement_stack[m_pos.m_index_2]; |
602 | |
603 | make_row(pfs_thread, statement); |
604 | m_next_pos.set_after(&m_pos); |
605 | return 0; |
606 | } |
607 | |
608 | return HA_ERR_END_OF_FILE; |
609 | } |
610 | |
611 | int table_events_statements_current::rnd_pos(const void *pos) |
612 | { |
613 | PFS_thread *pfs_thread; |
614 | PFS_events_statements *statement; |
615 | |
616 | set_position(pos); |
617 | DBUG_ASSERT(m_pos.m_index_1 < thread_max); |
618 | pfs_thread= &thread_array[m_pos.m_index_1]; |
619 | |
620 | if (! pfs_thread->m_lock.is_populated()) |
621 | return HA_ERR_RECORD_DELETED; |
622 | |
623 | uint safe_events_statements_count= pfs_thread->m_events_statements_count; |
624 | |
625 | if (safe_events_statements_count == 0) |
626 | { |
627 | /* Display the last top level statement, when completed */ |
628 | if (m_pos.m_index_2 >= 1) |
629 | return HA_ERR_RECORD_DELETED; |
630 | } |
631 | else |
632 | { |
633 | /* Display all pending statements, when in progress */ |
634 | if (m_pos.m_index_2 >= safe_events_statements_count) |
635 | return HA_ERR_RECORD_DELETED; |
636 | } |
637 | |
638 | DBUG_ASSERT(m_pos.m_index_2 < statement_stack_max); |
639 | |
640 | statement= &pfs_thread->m_statement_stack[m_pos.m_index_2]; |
641 | |
642 | if (statement->m_class == NULL) |
643 | return HA_ERR_RECORD_DELETED; |
644 | |
645 | make_row(pfs_thread, statement); |
646 | return 0; |
647 | } |
648 | |
649 | void table_events_statements_current::make_row(PFS_thread *pfs_thread, |
650 | PFS_events_statements *statement) |
651 | { |
652 | sql_digest_storage digest; |
653 | pfs_lock lock; |
654 | pfs_lock stmt_lock; |
655 | |
656 | digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE); |
657 | /* Protect this reader against thread termination. */ |
658 | pfs_thread->m_lock.begin_optimistic_lock(&lock); |
659 | /* Protect this reader against writing on statement information. */ |
660 | pfs_thread->m_stmt_lock.begin_optimistic_lock(&stmt_lock); |
661 | |
662 | table_events_statements_common::make_row_part_1(statement, &digest); |
663 | |
664 | if (!pfs_thread->m_stmt_lock.end_optimistic_lock(&stmt_lock) || |
665 | !pfs_thread->m_lock.end_optimistic_lock(&lock)) |
666 | { |
667 | m_row_exists= false; |
668 | return; |
669 | } |
670 | table_events_statements_common::make_row_part_2(&digest); |
671 | return; |
672 | } |
673 | |
674 | int table_events_statements_current::delete_all_rows(void) |
675 | { |
676 | reset_events_statements_current(); |
677 | return 0; |
678 | } |
679 | |
680 | PFS_engine_table* table_events_statements_history::create(void) |
681 | { |
682 | return new table_events_statements_history(); |
683 | } |
684 | |
685 | table_events_statements_history::table_events_statements_history() |
686 | : table_events_statements_common(&m_share, &m_pos), |
687 | m_pos(), m_next_pos() |
688 | {} |
689 | |
690 | void table_events_statements_history::reset_position(void) |
691 | { |
692 | m_pos.reset(); |
693 | m_next_pos.reset(); |
694 | } |
695 | |
696 | int table_events_statements_history::rnd_init(bool scan) |
697 | { |
698 | m_normalizer= time_normalizer::get(statement_timer); |
699 | return 0; |
700 | } |
701 | |
702 | int table_events_statements_history::rnd_next(void) |
703 | { |
704 | PFS_thread *pfs_thread; |
705 | PFS_events_statements *statement; |
706 | |
707 | if (events_statements_history_per_thread == 0) |
708 | return HA_ERR_END_OF_FILE; |
709 | |
710 | for (m_pos.set_at(&m_next_pos); |
711 | m_pos.m_index_1 < thread_max; |
712 | m_pos.next_thread()) |
713 | { |
714 | pfs_thread= &thread_array[m_pos.m_index_1]; |
715 | |
716 | if (! pfs_thread->m_lock.is_populated()) |
717 | { |
718 | /* This thread does not exist */ |
719 | continue; |
720 | } |
721 | |
722 | if (m_pos.m_index_2 >= events_statements_history_per_thread) |
723 | { |
724 | /* This thread does not have more (full) history */ |
725 | continue; |
726 | } |
727 | |
728 | if ( ! pfs_thread->m_statements_history_full && |
729 | (m_pos.m_index_2 >= pfs_thread->m_statements_history_index)) |
730 | { |
731 | /* This thread does not have more (not full) history */ |
732 | continue; |
733 | } |
734 | |
735 | statement= &pfs_thread->m_statements_history[m_pos.m_index_2]; |
736 | |
737 | if (statement->m_class != NULL) |
738 | { |
739 | make_row(pfs_thread, statement); |
740 | /* Next iteration, look for the next history in this thread */ |
741 | m_next_pos.set_after(&m_pos); |
742 | return 0; |
743 | } |
744 | } |
745 | |
746 | return HA_ERR_END_OF_FILE; |
747 | } |
748 | |
749 | int table_events_statements_history::rnd_pos(const void *pos) |
750 | { |
751 | PFS_thread *pfs_thread; |
752 | PFS_events_statements *statement; |
753 | |
754 | DBUG_ASSERT(events_statements_history_per_thread != 0); |
755 | set_position(pos); |
756 | DBUG_ASSERT(m_pos.m_index_1 < thread_max); |
757 | pfs_thread= &thread_array[m_pos.m_index_1]; |
758 | |
759 | if (! pfs_thread->m_lock.is_populated()) |
760 | return HA_ERR_RECORD_DELETED; |
761 | |
762 | DBUG_ASSERT(m_pos.m_index_2 < events_statements_history_per_thread); |
763 | |
764 | if ( ! pfs_thread->m_statements_history_full && |
765 | (m_pos.m_index_2 >= pfs_thread->m_statements_history_index)) |
766 | return HA_ERR_RECORD_DELETED; |
767 | |
768 | statement= &pfs_thread->m_statements_history[m_pos.m_index_2]; |
769 | |
770 | if (statement->m_class == NULL) |
771 | return HA_ERR_RECORD_DELETED; |
772 | |
773 | make_row(pfs_thread, statement); |
774 | return 0; |
775 | } |
776 | |
777 | void table_events_statements_history::make_row(PFS_thread *pfs_thread, |
778 | PFS_events_statements *statement) |
779 | { |
780 | sql_digest_storage digest; |
781 | pfs_lock lock; |
782 | |
783 | digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE); |
784 | /* Protect this reader against thread termination. */ |
785 | pfs_thread->m_lock.begin_optimistic_lock(&lock); |
786 | |
787 | table_events_statements_common::make_row_part_1(statement, &digest); |
788 | |
789 | if (!pfs_thread->m_lock.end_optimistic_lock(&lock)) |
790 | { |
791 | m_row_exists= false; |
792 | return; |
793 | } |
794 | table_events_statements_common::make_row_part_2(&digest); |
795 | return; |
796 | } |
797 | |
798 | int table_events_statements_history::delete_all_rows(void) |
799 | { |
800 | reset_events_statements_history(); |
801 | return 0; |
802 | } |
803 | |
804 | PFS_engine_table* table_events_statements_history_long::create(void) |
805 | { |
806 | return new table_events_statements_history_long(); |
807 | } |
808 | |
809 | table_events_statements_history_long::table_events_statements_history_long() |
810 | : table_events_statements_common(&m_share, &m_pos), |
811 | m_pos(0), m_next_pos(0) |
812 | {} |
813 | |
814 | void table_events_statements_history_long::reset_position(void) |
815 | { |
816 | m_pos.m_index= 0; |
817 | m_next_pos.m_index= 0; |
818 | } |
819 | |
820 | int table_events_statements_history_long::rnd_init(bool scan) |
821 | { |
822 | m_normalizer= time_normalizer::get(statement_timer); |
823 | return 0; |
824 | } |
825 | |
826 | int table_events_statements_history_long::rnd_next(void) |
827 | { |
828 | PFS_events_statements *statement; |
829 | size_t limit; |
830 | |
831 | if (events_statements_history_long_size == 0) |
832 | return HA_ERR_END_OF_FILE; |
833 | |
834 | if (events_statements_history_long_full) |
835 | limit= events_statements_history_long_size; |
836 | else |
837 | limit= events_statements_history_long_index % events_statements_history_long_size; |
838 | |
839 | for (m_pos.set_at(&m_next_pos); m_pos.m_index < limit; m_pos.next()) |
840 | { |
841 | statement= &events_statements_history_long_array[m_pos.m_index]; |
842 | |
843 | if (statement->m_class != NULL) |
844 | { |
845 | make_row(statement); |
846 | /* Next iteration, look for the next entry */ |
847 | m_next_pos.set_after(&m_pos); |
848 | return 0; |
849 | } |
850 | } |
851 | |
852 | return HA_ERR_END_OF_FILE; |
853 | } |
854 | |
855 | int table_events_statements_history_long::rnd_pos(const void *pos) |
856 | { |
857 | PFS_events_statements *statement; |
858 | size_t limit; |
859 | |
860 | if (events_statements_history_long_size == 0) |
861 | return HA_ERR_RECORD_DELETED; |
862 | |
863 | set_position(pos); |
864 | |
865 | if (events_statements_history_long_full) |
866 | limit= events_statements_history_long_size; |
867 | else |
868 | limit= events_statements_history_long_index % events_statements_history_long_size; |
869 | |
870 | if (m_pos.m_index >= limit) |
871 | return HA_ERR_RECORD_DELETED; |
872 | |
873 | statement= &events_statements_history_long_array[m_pos.m_index]; |
874 | |
875 | if (statement->m_class == NULL) |
876 | return HA_ERR_RECORD_DELETED; |
877 | |
878 | make_row(statement); |
879 | return 0; |
880 | } |
881 | |
882 | void table_events_statements_history_long::make_row(PFS_events_statements *statement) |
883 | { |
884 | sql_digest_storage digest; |
885 | |
886 | digest.reset(m_token_array, MAX_DIGEST_STORAGE_SIZE); |
887 | table_events_statements_common::make_row_part_1(statement, &digest); |
888 | |
889 | table_events_statements_common::make_row_part_2(&digest); |
890 | return; |
891 | } |
892 | |
893 | int table_events_statements_history_long::delete_all_rows(void) |
894 | { |
895 | reset_events_statements_history_long(); |
896 | return 0; |
897 | } |
898 | |
899 | |