1 /*****************************************************************************
2
3 Copyright (c) 2007, 2020, Oracle and/or its affiliates.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation. The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License, version 2.0, for more details.
20
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25 *****************************************************************************/
26
27 /**************************************************//**
28 @file handler/i_s.cc
29 InnoDB INFORMATION SCHEMA tables interface to MySQL.
30
31 Created July 18, 2007 Vasil Dimov
32 *******************************************************/
33
34 #include <mysqld_error.h>
35 #include <sql_acl.h>
36
37 #include <m_ctype.h>
38 #include <hash.h>
39 #include <myisampack.h>
40 #include <mysys_err.h>
41 #include <my_sys.h>
42 #include "i_s.h"
43 #include <sql_plugin.h>
44 #include <mysql/innodb_priv.h>
45
46 #include <string>
47 #include <sstream>
48 #include <iostream>
49
50 #include "btr0pcur.h"
51 #include "btr0types.h"
52 #include "dict0dict.h"
53 #include "dict0load.h"
54 #include "buf0buddy.h"
55 #include "buf0buf.h"
56 #include "ibuf0ibuf.h"
57 #include "dict0mem.h"
58 #include "dict0types.h"
59 #include "ha_prototypes.h"
60 #include "srv0start.h"
61 #include "trx0i_s.h"
62 #include "trx0trx.h"
63 #include "srv0mon.h"
64 #include "fut0fut.h"
65 #include "pars0pars.h"
66 #include "fts0types.h"
67 #include "fts0opt.h"
68 #include "fts0priv.h"
69 #include "btr0btr.h"
70 #include "page0zip.h"
71
72 #include <string>
73
74 /** structure associates a name string with a file page type and/or buffer
75 page state. */
76 struct buf_page_desc_t{
77 const char* type_str; /*!< String explain the page
78 type/state */
79 ulint type_value; /*!< Page type or page state */
80 };
81
82 /** Change buffer B-tree page */
83 #define I_S_PAGE_TYPE_IBUF (FIL_PAGE_TYPE_LAST + 1)
84
85 /** Any states greater than I_S_PAGE_TYPE_IBUF would be treated as
86 unknown. */
87 #define I_S_PAGE_TYPE_UNKNOWN (I_S_PAGE_TYPE_IBUF + 1)
88
89 /** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
90 in i_s_page_type[] array */
91 #define I_S_PAGE_TYPE_INDEX 1
92
93 /** Name string for File Page Types */
94 static buf_page_desc_t i_s_page_type[] = {
95 {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
96 {"INDEX", FIL_PAGE_INDEX},
97 {"UNDO_LOG", FIL_PAGE_UNDO_LOG},
98 {"INODE", FIL_PAGE_INODE},
99 {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
100 {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
101 {"SYSTEM", FIL_PAGE_TYPE_SYS},
102 {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
103 {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
104 {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
105 {"BLOB", FIL_PAGE_TYPE_BLOB},
106 {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
107 {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
108 {"IBUF_INDEX", I_S_PAGE_TYPE_IBUF},
109 {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
110 };
111
112 /* Check if we can hold all page type in a 4 bit value */
113 #if I_S_PAGE_TYPE_UNKNOWN > 1<<4
114 # error "i_s_page_type[] is too large"
115 #endif
116
117 /** This structure defines information we will fetch from pages
118 currently cached in the buffer pool. It will be used to populate
119 table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
120 struct buf_page_info_t{
121 ulint block_id; /*!< Buffer Pool block ID */
122 unsigned space_id:32; /*!< Tablespace ID */
123 unsigned page_num:32; /*!< Page number/offset */
124 unsigned access_time:32; /*!< Time of first access */
125 unsigned pool_id:MAX_BUFFER_POOLS_BITS;
126 /*!< Buffer Pool ID. Must be less than
127 MAX_BUFFER_POOLS */
128 unsigned flush_type:2; /*!< Flush type */
129 unsigned io_fix:2; /*!< type of pending I/O operation */
130 unsigned fix_count:19; /*!< Count of how manyfold this block
131 is bufferfixed */
132 unsigned hashed:1; /*!< Whether hash index has been
133 built on this page */
134 unsigned is_old:1; /*!< TRUE if the block is in the old
135 blocks in buf_pool->LRU_old */
136 unsigned freed_page_clock:31; /*!< the value of
137 buf_pool->freed_page_clock */
138 unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS;
139 /*!< Compressed page size */
140 unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
141 unsigned page_type:4; /*!< Page type */
142 unsigned num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2;
143 /*!< Number of records on Page */
144 unsigned data_size:UNIV_PAGE_SIZE_SHIFT_MAX;
145 /*!< Sum of the sizes of the records */
146 lsn_t newest_mod; /*!< Log sequence number of
147 the youngest modification */
148 lsn_t oldest_mod; /*!< Log sequence number of
149 the oldest modification */
150 index_id_t index_id; /*!< Index ID if a index page */
151 };
152
153 /** maximum number of buffer page info we would cache. */
154 #define MAX_BUF_INFO_CACHED 10000
155
156 #define OK(expr) \
157 if ((expr) != 0) { \
158 DBUG_RETURN(1); \
159 }
160
161 #define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
162 do { \
163 if (!srv_was_started) { \
164 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, \
165 ER_CANT_FIND_SYSTEM_REC, \
166 "InnoDB: SELECTing from " \
167 "INFORMATION_SCHEMA.%s but " \
168 "the InnoDB storage engine " \
169 "is not installed", plugin_name); \
170 DBUG_RETURN(0); \
171 } \
172 } while (0)
173
174 #if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && \
175 !defined __INTEL_COMPILER && !defined __clang__
176 #define STRUCT_FLD(name, value) name: value
177 #else
178 #define STRUCT_FLD(name, value) value
179 #endif
180
181 /* Don't use a static const variable here, as some C++ compilers (notably
182 HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
183 #define END_OF_ST_FIELD_INFO \
184 {STRUCT_FLD(field_name, NULL), \
185 STRUCT_FLD(field_length, 0), \
186 STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
187 STRUCT_FLD(value, 0), \
188 STRUCT_FLD(field_flags, 0), \
189 STRUCT_FLD(old_name, ""), \
190 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
191
192 /*
193 Use the following types mapping:
194
195 C type ST_FIELD_INFO::field_type
196 ---------------------------------
197 long MYSQL_TYPE_LONGLONG
198 (field_length=MY_INT64_NUM_DECIMAL_DIGITS)
199
200 long unsigned MYSQL_TYPE_LONGLONG
201 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
202
203 char* MYSQL_TYPE_STRING
204 (field_length=n)
205
206 float MYSQL_TYPE_FLOAT
207 (field_length=0 is ignored)
208
209 void* MYSQL_TYPE_LONGLONG
210 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
211
212 boolean (if else) MYSQL_TYPE_LONG
213 (field_length=1)
214
215 time_t MYSQL_TYPE_DATETIME
216 (field_length=0 ignored)
217 ---------------------------------
218 */
219
220 /*******************************************************************//**
221 Common function to fill any of the dynamic tables:
222 INFORMATION_SCHEMA.innodb_trx
223 INFORMATION_SCHEMA.innodb_locks
224 INFORMATION_SCHEMA.innodb_lock_waits
225 @return 0 on success */
226 static
227 int
228 trx_i_s_common_fill_table(
229 /*======================*/
230 THD* thd, /*!< in: thread */
231 TABLE_LIST* tables, /*!< in/out: tables to fill */
232 Item* ); /*!< in: condition (not used) */
233
234 /*******************************************************************//**
235 Unbind a dynamic INFORMATION_SCHEMA table.
236 @return 0 on success */
237 static
238 int
239 i_s_common_deinit(
240 /*==============*/
241 void* p); /*!< in/out: table schema object */
242 /*******************************************************************//**
243 Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
244 field.
245 @return 0 on success */
246 static
247 int
field_store_time_t(Field * field,time_t time)248 field_store_time_t(
249 /*===============*/
250 Field* field, /*!< in/out: target field for storage */
251 time_t time) /*!< in: value to store */
252 {
253 MYSQL_TIME my_time;
254 struct tm tm_time;
255
256 if (time) {
257 #if 0
258 /* use this if you are sure that `variables' and `time_zone'
259 are always initialized */
260 thd->variables.time_zone->gmt_sec_to_TIME(
261 &my_time, (my_time_t) time);
262 #else
263 localtime_r(&time, &tm_time);
264 localtime_to_TIME(&my_time, &tm_time);
265 my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
266 #endif
267 } else {
268 memset(&my_time, 0, sizeof(my_time));
269 }
270
271 return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
272 }
273
274 /*******************************************************************//**
275 Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
276 @return 0 on success */
277 static
278 int
field_store_string(Field * field,const char * str)279 field_store_string(
280 /*===============*/
281 Field* field, /*!< in/out: target field for storage */
282 const char* str) /*!< in: NUL-terminated utf-8 string,
283 or NULL */
284 {
285 int ret;
286
287 if (str != NULL) {
288
289 ret = field->store(str, static_cast<uint>(strlen(str)),
290 system_charset_info);
291 field->set_notnull();
292 } else {
293
294 ret = 0; /* success */
295 field->set_null();
296 }
297
298 return(ret);
299 }
300
301 /*******************************************************************//**
302 Store the name of an index in a MYSQL_TYPE_VARCHAR field.
303 Handles the names of incomplete secondary indexes.
304 @return 0 on success */
305 static
306 int
field_store_index_name(Field * field,const char * index_name)307 field_store_index_name(
308 /*===================*/
309 Field* field, /*!< in/out: target field for
310 storage */
311 const char* index_name) /*!< in: NUL-terminated utf-8
312 index name, possibly starting with
313 TEMP_INDEX_PREFIX */
314 {
315 int ret;
316
317 ut_ad(index_name != NULL);
318 ut_ad(field->real_type() == MYSQL_TYPE_VARCHAR);
319
320 /* Since TEMP_INDEX_PREFIX is not a valid UTF8, we need to convert
321 it to something else. */
322 if (index_name[0] == TEMP_INDEX_PREFIX) {
323 char buf[NAME_LEN + 1];
324 buf[0] = '?';
325 memcpy(buf + 1, index_name + 1, strlen(index_name));
326 ret = field->store(
327 buf, static_cast<uint>(strlen(buf)),
328 system_charset_info);
329 } else {
330 ret = field->store(
331 index_name, static_cast<uint>(strlen(index_name)),
332 system_charset_info);
333 }
334
335 field->set_notnull();
336
337 return(ret);
338 }
339
340 /*******************************************************************//**
341 Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
342 If the value is ULINT_UNDEFINED then the field it set to NULL.
343 @return 0 on success */
344 static
345 int
field_store_ulint(Field * field,ulint n)346 field_store_ulint(
347 /*==============*/
348 Field* field, /*!< in/out: target field for storage */
349 ulint n) /*!< in: value to store */
350 {
351 int ret;
352
353 if (n != ULINT_UNDEFINED) {
354
355 ret = field->store(static_cast<double>(n));
356 field->set_notnull();
357 } else {
358
359 ret = 0; /* success */
360 field->set_null();
361 }
362
363 return(ret);
364 }
365
366 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
367 static ST_FIELD_INFO innodb_trx_fields_info[] =
368 {
369 #define IDX_TRX_ID 0
370 {STRUCT_FLD(field_name, "trx_id"),
371 STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
372 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
373 STRUCT_FLD(value, 0),
374 STRUCT_FLD(field_flags, 0),
375 STRUCT_FLD(old_name, ""),
376 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
377
378 #define IDX_TRX_STATE 1
379 {STRUCT_FLD(field_name, "trx_state"),
380 STRUCT_FLD(field_length, TRX_QUE_STATE_STR_MAX_LEN + 1),
381 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
382 STRUCT_FLD(value, 0),
383 STRUCT_FLD(field_flags, 0),
384 STRUCT_FLD(old_name, ""),
385 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
386
387 #define IDX_TRX_STARTED 2
388 {STRUCT_FLD(field_name, "trx_started"),
389 STRUCT_FLD(field_length, 0),
390 STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
391 STRUCT_FLD(value, 0),
392 STRUCT_FLD(field_flags, 0),
393 STRUCT_FLD(old_name, ""),
394 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
395
396 #define IDX_TRX_REQUESTED_LOCK_ID 3
397 {STRUCT_FLD(field_name, "trx_requested_lock_id"),
398 STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
399 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
400 STRUCT_FLD(value, 0),
401 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
402 STRUCT_FLD(old_name, ""),
403 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
404
405 #define IDX_TRX_WAIT_STARTED 4
406 {STRUCT_FLD(field_name, "trx_wait_started"),
407 STRUCT_FLD(field_length, 0),
408 STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
409 STRUCT_FLD(value, 0),
410 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
411 STRUCT_FLD(old_name, ""),
412 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
413
414 #define IDX_TRX_WEIGHT 5
415 {STRUCT_FLD(field_name, "trx_weight"),
416 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
417 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
418 STRUCT_FLD(value, 0),
419 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
420 STRUCT_FLD(old_name, ""),
421 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
422
423 #define IDX_TRX_MYSQL_THREAD_ID 6
424 {STRUCT_FLD(field_name, "trx_mysql_thread_id"),
425 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
426 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
427 STRUCT_FLD(value, 0),
428 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
429 STRUCT_FLD(old_name, ""),
430 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
431
432 #define IDX_TRX_QUERY 7
433 {STRUCT_FLD(field_name, "trx_query"),
434 STRUCT_FLD(field_length, TRX_I_S_TRX_QUERY_MAX_LEN),
435 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
436 STRUCT_FLD(value, 0),
437 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
438 STRUCT_FLD(old_name, ""),
439 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
440
441 #define IDX_TRX_OPERATION_STATE 8
442 {STRUCT_FLD(field_name, "trx_operation_state"),
443 STRUCT_FLD(field_length, TRX_I_S_TRX_OP_STATE_MAX_LEN),
444 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
445 STRUCT_FLD(value, 0),
446 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
447 STRUCT_FLD(old_name, ""),
448 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
449
450 #define IDX_TRX_TABLES_IN_USE 9
451 {STRUCT_FLD(field_name, "trx_tables_in_use"),
452 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
453 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
454 STRUCT_FLD(value, 0),
455 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
456 STRUCT_FLD(old_name, ""),
457 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
458
459 #define IDX_TRX_TABLES_LOCKED 10
460 {STRUCT_FLD(field_name, "trx_tables_locked"),
461 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
462 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
463 STRUCT_FLD(value, 0),
464 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
465 STRUCT_FLD(old_name, ""),
466 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
467
468 #define IDX_TRX_LOCK_STRUCTS 11
469 {STRUCT_FLD(field_name, "trx_lock_structs"),
470 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
471 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
472 STRUCT_FLD(value, 0),
473 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
474 STRUCT_FLD(old_name, ""),
475 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
476
477 #define IDX_TRX_LOCK_MEMORY_BYTES 12
478 {STRUCT_FLD(field_name, "trx_lock_memory_bytes"),
479 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
480 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
481 STRUCT_FLD(value, 0),
482 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
483 STRUCT_FLD(old_name, ""),
484 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
485
486 #define IDX_TRX_ROWS_LOCKED 13
487 {STRUCT_FLD(field_name, "trx_rows_locked"),
488 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
489 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
490 STRUCT_FLD(value, 0),
491 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
492 STRUCT_FLD(old_name, ""),
493 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
494
495 #define IDX_TRX_ROWS_MODIFIED 14
496 {STRUCT_FLD(field_name, "trx_rows_modified"),
497 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
498 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
499 STRUCT_FLD(value, 0),
500 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
501 STRUCT_FLD(old_name, ""),
502 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
503
504 #define IDX_TRX_CONNCURRENCY_TICKETS 15
505 {STRUCT_FLD(field_name, "trx_concurrency_tickets"),
506 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
507 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
508 STRUCT_FLD(value, 0),
509 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
510 STRUCT_FLD(old_name, ""),
511 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
512
513 #define IDX_TRX_ISOLATION_LEVEL 16
514 {STRUCT_FLD(field_name, "trx_isolation_level"),
515 STRUCT_FLD(field_length, TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN),
516 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
517 STRUCT_FLD(value, 0),
518 STRUCT_FLD(field_flags, 0),
519 STRUCT_FLD(old_name, ""),
520 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
521
522 #define IDX_TRX_UNIQUE_CHECKS 17
523 {STRUCT_FLD(field_name, "trx_unique_checks"),
524 STRUCT_FLD(field_length, 1),
525 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
526 STRUCT_FLD(value, 1),
527 STRUCT_FLD(field_flags, 0),
528 STRUCT_FLD(old_name, ""),
529 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
530
531 #define IDX_TRX_FOREIGN_KEY_CHECKS 18
532 {STRUCT_FLD(field_name, "trx_foreign_key_checks"),
533 STRUCT_FLD(field_length, 1),
534 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
535 STRUCT_FLD(value, 1),
536 STRUCT_FLD(field_flags, 0),
537 STRUCT_FLD(old_name, ""),
538 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
539
540 #define IDX_TRX_LAST_FOREIGN_KEY_ERROR 19
541 {STRUCT_FLD(field_name, "trx_last_foreign_key_error"),
542 STRUCT_FLD(field_length, TRX_I_S_TRX_FK_ERROR_MAX_LEN),
543 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
544 STRUCT_FLD(value, 0),
545 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
546 STRUCT_FLD(old_name, ""),
547 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
548
549 #define IDX_TRX_ADAPTIVE_HASH_LATCHED 20
550 {STRUCT_FLD(field_name, "trx_adaptive_hash_latched"),
551 STRUCT_FLD(field_length, 1),
552 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
553 STRUCT_FLD(value, 0),
554 STRUCT_FLD(field_flags, 0),
555 STRUCT_FLD(old_name, ""),
556 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
557
558 #define IDX_TRX_ADAPTIVE_HASH_TIMEOUT 21
559 {STRUCT_FLD(field_name, "trx_adaptive_hash_timeout"),
560 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
561 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
562 STRUCT_FLD(value, 0),
563 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
564 STRUCT_FLD(old_name, ""),
565 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
566
567 #define IDX_TRX_READ_ONLY 22
568 {STRUCT_FLD(field_name, "trx_is_read_only"),
569 STRUCT_FLD(field_length, 1),
570 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
571 STRUCT_FLD(value, 0),
572 STRUCT_FLD(field_flags, 0),
573 STRUCT_FLD(old_name, ""),
574 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
575
576 #define IDX_TRX_AUTOCOMMIT_NON_LOCKING 23
577 {STRUCT_FLD(field_name, "trx_autocommit_non_locking"),
578 STRUCT_FLD(field_length, 1),
579 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
580 STRUCT_FLD(value, 0),
581 STRUCT_FLD(field_flags, 0),
582 STRUCT_FLD(old_name, ""),
583 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
584
585 END_OF_ST_FIELD_INFO
586 };
587
588 /*******************************************************************//**
589 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
590 table with it.
591 @return 0 on success */
592 static
593 int
fill_innodb_trx_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)594 fill_innodb_trx_from_cache(
595 /*=======================*/
596 trx_i_s_cache_t* cache, /*!< in: cache to read from */
597 THD* thd, /*!< in: used to call
598 schema_table_store_record() */
599 TABLE* table) /*!< in/out: fill this table */
600 {
601 Field** fields;
602 ulint rows_num;
603 char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
604 ulint i;
605
606 DBUG_ENTER("fill_innodb_trx_from_cache");
607
608 fields = table->field;
609
610 rows_num = trx_i_s_cache_get_rows_used(cache,
611 I_S_INNODB_TRX);
612
613 for (i = 0; i < rows_num; i++) {
614
615 i_s_trx_row_t* row;
616 char trx_id[TRX_ID_MAX_LEN + 1];
617
618 row = (i_s_trx_row_t*)
619 trx_i_s_cache_get_nth_row(
620 cache, I_S_INNODB_TRX, i);
621
622 /* trx_id */
623 ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
624 OK(field_store_string(fields[IDX_TRX_ID], trx_id));
625
626 /* trx_state */
627 OK(field_store_string(fields[IDX_TRX_STATE],
628 row->trx_state));
629
630 /* trx_started */
631 OK(field_store_time_t(fields[IDX_TRX_STARTED],
632 (time_t) row->trx_started));
633
634 /* trx_requested_lock_id */
635 /* trx_wait_started */
636 if (row->trx_wait_started != 0) {
637
638 OK(field_store_string(
639 fields[IDX_TRX_REQUESTED_LOCK_ID],
640 trx_i_s_create_lock_id(
641 row->requested_lock_row,
642 lock_id, sizeof(lock_id))));
643 /* field_store_string() sets it no notnull */
644
645 OK(field_store_time_t(
646 fields[IDX_TRX_WAIT_STARTED],
647 (time_t) row->trx_wait_started));
648 fields[IDX_TRX_WAIT_STARTED]->set_notnull();
649 } else {
650
651 fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
652 fields[IDX_TRX_WAIT_STARTED]->set_null();
653 }
654
655 /* trx_weight */
656 OK(fields[IDX_TRX_WEIGHT]->store((longlong) row->trx_weight,
657 true));
658
659 /* trx_mysql_thread_id */
660 OK(fields[IDX_TRX_MYSQL_THREAD_ID]->store(
661 static_cast<double>(row->trx_mysql_thread_id)));
662
663 /* trx_query */
664 if (row->trx_query) {
665 /* store will do appropriate character set
666 conversion check */
667 fields[IDX_TRX_QUERY]->store(
668 row->trx_query,
669 static_cast<uint>(strlen(row->trx_query)),
670 row->trx_query_cs);
671 fields[IDX_TRX_QUERY]->set_notnull();
672 } else {
673 fields[IDX_TRX_QUERY]->set_null();
674 }
675
676 /* trx_operation_state */
677 OK(field_store_string(fields[IDX_TRX_OPERATION_STATE],
678 row->trx_operation_state));
679
680 /* trx_tables_in_use */
681 OK(fields[IDX_TRX_TABLES_IN_USE]->store(
682 (longlong) row->trx_tables_in_use, true));
683
684 /* trx_tables_locked */
685 OK(fields[IDX_TRX_TABLES_LOCKED]->store(
686 (longlong) row->trx_tables_locked, true));
687
688 /* trx_lock_structs */
689 OK(fields[IDX_TRX_LOCK_STRUCTS]->store(
690 (longlong) row->trx_lock_structs, true));
691
692 /* trx_lock_memory_bytes */
693 OK(fields[IDX_TRX_LOCK_MEMORY_BYTES]->store(
694 (longlong) row->trx_lock_memory_bytes, true));
695
696 /* trx_rows_locked */
697 OK(fields[IDX_TRX_ROWS_LOCKED]->store(
698 (longlong) row->trx_rows_locked, true));
699
700 /* trx_rows_modified */
701 OK(fields[IDX_TRX_ROWS_MODIFIED]->store(
702 (longlong) row->trx_rows_modified, true));
703
704 /* trx_concurrency_tickets */
705 OK(fields[IDX_TRX_CONNCURRENCY_TICKETS]->store(
706 (longlong) row->trx_concurrency_tickets, true));
707
708 /* trx_isolation_level */
709 OK(field_store_string(fields[IDX_TRX_ISOLATION_LEVEL],
710 row->trx_isolation_level));
711
712 /* trx_unique_checks */
713 OK(fields[IDX_TRX_UNIQUE_CHECKS]->store(
714 static_cast<double>(row->trx_unique_checks)));
715
716 /* trx_foreign_key_checks */
717 OK(fields[IDX_TRX_FOREIGN_KEY_CHECKS]->store(
718 static_cast<double>(row->trx_foreign_key_checks)));
719
720 /* trx_last_foreign_key_error */
721 OK(field_store_string(fields[IDX_TRX_LAST_FOREIGN_KEY_ERROR],
722 row->trx_foreign_key_error));
723
724 /* trx_adaptive_hash_latched */
725 OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(
726 static_cast<double>(row->trx_has_search_latch)));
727
728 /* trx_adaptive_hash_timeout */
729 OK(fields[IDX_TRX_ADAPTIVE_HASH_TIMEOUT]->store(
730 (longlong) row->trx_search_latch_timeout, true));
731
732 /* trx_is_read_only*/
733 OK(fields[IDX_TRX_READ_ONLY]->store(
734 (longlong) row->trx_is_read_only, true));
735
736 /* trx_is_autocommit_non_locking */
737 OK(fields[IDX_TRX_AUTOCOMMIT_NON_LOCKING]->store(
738 (longlong) row->trx_is_autocommit_non_locking,
739 true));
740
741 OK(schema_table_store_record(thd, table));
742 }
743
744 DBUG_RETURN(0);
745 }
746
747 /*******************************************************************//**
748 Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
749 @return 0 on success */
750 static
751 int
innodb_trx_init(void * p)752 innodb_trx_init(
753 /*============*/
754 void* p) /*!< in/out: table schema object */
755 {
756 ST_SCHEMA_TABLE* schema;
757
758 DBUG_ENTER("innodb_trx_init");
759
760 schema = (ST_SCHEMA_TABLE*) p;
761
762 schema->fields_info = innodb_trx_fields_info;
763 schema->fill_table = trx_i_s_common_fill_table;
764
765 DBUG_RETURN(0);
766 }
767
768 static struct st_mysql_information_schema i_s_info =
769 {
770 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
771 };
772
773 UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx =
774 {
775 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
776 /* int */
777 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
778
779 /* pointer to type-specific plugin descriptor */
780 /* void* */
781 STRUCT_FLD(info, &i_s_info),
782
783 /* plugin name */
784 /* const char* */
785 STRUCT_FLD(name, "INNODB_TRX"),
786
787 /* plugin author (for SHOW PLUGINS) */
788 /* const char* */
789 STRUCT_FLD(author, plugin_author),
790
791 /* general descriptive text (for SHOW PLUGINS) */
792 /* const char* */
793 STRUCT_FLD(descr, "InnoDB transactions"),
794
795 /* the plugin license (PLUGIN_LICENSE_XXX) */
796 /* int */
797 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
798
799 /* the function to invoke when plugin is loaded */
800 /* int (*)(void*); */
801 STRUCT_FLD(init, innodb_trx_init),
802
803 /* the function to invoke when plugin is unloaded */
804 /* int (*)(void*); */
805 STRUCT_FLD(deinit, i_s_common_deinit),
806
807 /* plugin version (for SHOW PLUGINS) */
808 /* unsigned int */
809 STRUCT_FLD(version, INNODB_VERSION_SHORT),
810
811 /* struct st_mysql_show_var* */
812 STRUCT_FLD(status_vars, NULL),
813
814 /* struct st_mysql_sys_var** */
815 STRUCT_FLD(system_vars, NULL),
816
817 /* reserved for dependency checking */
818 /* void* */
819 STRUCT_FLD(__reserved1, NULL),
820
821 /* Plugin flags */
822 /* unsigned long */
823 STRUCT_FLD(flags, 0UL),
824 };
825
826 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
827 static ST_FIELD_INFO innodb_locks_fields_info[] =
828 {
829 #define IDX_LOCK_ID 0
830 {STRUCT_FLD(field_name, "lock_id"),
831 STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
832 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
833 STRUCT_FLD(value, 0),
834 STRUCT_FLD(field_flags, 0),
835 STRUCT_FLD(old_name, ""),
836 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
837
838 #define IDX_LOCK_TRX_ID 1
839 {STRUCT_FLD(field_name, "lock_trx_id"),
840 STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
841 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
842 STRUCT_FLD(value, 0),
843 STRUCT_FLD(field_flags, 0),
844 STRUCT_FLD(old_name, ""),
845 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
846
847 #define IDX_LOCK_MODE 2
848 {STRUCT_FLD(field_name, "lock_mode"),
849 /* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
850 STRUCT_FLD(field_length, 32),
851 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
852 STRUCT_FLD(value, 0),
853 STRUCT_FLD(field_flags, 0),
854 STRUCT_FLD(old_name, ""),
855 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
856
857 #define IDX_LOCK_TYPE 3
858 {STRUCT_FLD(field_name, "lock_type"),
859 STRUCT_FLD(field_length, 32 /* RECORD|TABLE|UNKNOWN */),
860 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
861 STRUCT_FLD(value, 0),
862 STRUCT_FLD(field_flags, 0),
863 STRUCT_FLD(old_name, ""),
864 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
865
866 #define IDX_LOCK_TABLE 4
867 {STRUCT_FLD(field_name, "lock_table"),
868 STRUCT_FLD(field_length, 1024),
869 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
870 STRUCT_FLD(value, 0),
871 STRUCT_FLD(field_flags, 0),
872 STRUCT_FLD(old_name, ""),
873 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
874
875 #define IDX_LOCK_INDEX 5
876 {STRUCT_FLD(field_name, "lock_index"),
877 STRUCT_FLD(field_length, 1024),
878 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
879 STRUCT_FLD(value, 0),
880 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
881 STRUCT_FLD(old_name, ""),
882 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
883
884 #define IDX_LOCK_SPACE 6
885 {STRUCT_FLD(field_name, "lock_space"),
886 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
887 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
888 STRUCT_FLD(value, 0),
889 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
890 STRUCT_FLD(old_name, ""),
891 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
892
893 #define IDX_LOCK_PAGE 7
894 {STRUCT_FLD(field_name, "lock_page"),
895 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
896 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
897 STRUCT_FLD(value, 0),
898 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
899 STRUCT_FLD(old_name, ""),
900 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
901
902 #define IDX_LOCK_REC 8
903 {STRUCT_FLD(field_name, "lock_rec"),
904 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
905 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
906 STRUCT_FLD(value, 0),
907 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
908 STRUCT_FLD(old_name, ""),
909 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
910
911 #define IDX_LOCK_DATA 9
912 {STRUCT_FLD(field_name, "lock_data"),
913 STRUCT_FLD(field_length, TRX_I_S_LOCK_DATA_MAX_LEN),
914 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
915 STRUCT_FLD(value, 0),
916 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
917 STRUCT_FLD(old_name, ""),
918 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
919
920 END_OF_ST_FIELD_INFO
921 };
922
923 /*******************************************************************//**
924 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
925 table with it.
926 @return 0 on success */
927 static
928 int
fill_innodb_locks_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)929 fill_innodb_locks_from_cache(
930 /*=========================*/
931 trx_i_s_cache_t* cache, /*!< in: cache to read from */
932 THD* thd, /*!< in: MySQL client connection */
933 TABLE* table) /*!< in/out: fill this table */
934 {
935 Field** fields;
936 ulint rows_num;
937 char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
938 ulint i;
939
940 DBUG_ENTER("fill_innodb_locks_from_cache");
941
942 fields = table->field;
943
944 rows_num = trx_i_s_cache_get_rows_used(cache,
945 I_S_INNODB_LOCKS);
946
947 for (i = 0; i < rows_num; i++) {
948
949 i_s_locks_row_t* row;
950 char buf[MAX_FULL_NAME_LEN + 1];
951 const char* bufend;
952
953 char lock_trx_id[TRX_ID_MAX_LEN + 1];
954
955 row = (i_s_locks_row_t*)
956 trx_i_s_cache_get_nth_row(
957 cache, I_S_INNODB_LOCKS, i);
958
959 /* lock_id */
960 trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
961 OK(field_store_string(fields[IDX_LOCK_ID],
962 lock_id));
963
964 /* lock_trx_id */
965 ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
966 TRX_ID_FMT, row->lock_trx_id);
967 OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
968
969 /* lock_mode */
970 OK(field_store_string(fields[IDX_LOCK_MODE],
971 row->lock_mode));
972
973 /* lock_type */
974 OK(field_store_string(fields[IDX_LOCK_TYPE],
975 row->lock_type));
976
977 /* lock_table */
978 bufend = innobase_convert_name(buf, sizeof(buf),
979 row->lock_table,
980 strlen(row->lock_table),
981 thd, TRUE);
982 OK(fields[IDX_LOCK_TABLE]->store(
983 buf, static_cast<uint>(bufend - buf),
984 system_charset_info));
985
986 /* lock_index */
987 if (row->lock_index != NULL) {
988 OK(field_store_index_name(fields[IDX_LOCK_INDEX],
989 row->lock_index));
990 } else {
991 fields[IDX_LOCK_INDEX]->set_null();
992 }
993
994 /* lock_space */
995 OK(field_store_ulint(fields[IDX_LOCK_SPACE],
996 row->lock_space));
997
998 /* lock_page */
999 OK(field_store_ulint(fields[IDX_LOCK_PAGE],
1000 row->lock_page));
1001
1002 /* lock_rec */
1003 OK(field_store_ulint(fields[IDX_LOCK_REC],
1004 row->lock_rec));
1005
1006 /* lock_data */
1007 OK(field_store_string(fields[IDX_LOCK_DATA],
1008 row->lock_data));
1009
1010 OK(schema_table_store_record(thd, table));
1011 }
1012
1013 DBUG_RETURN(0);
1014 }
1015
1016 /*******************************************************************//**
1017 Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
1018 @return 0 on success */
1019 static
1020 int
innodb_locks_init(void * p)1021 innodb_locks_init(
1022 /*==============*/
1023 void* p) /*!< in/out: table schema object */
1024 {
1025 ST_SCHEMA_TABLE* schema;
1026
1027 DBUG_ENTER("innodb_locks_init");
1028
1029 schema = (ST_SCHEMA_TABLE*) p;
1030
1031 schema->fields_info = innodb_locks_fields_info;
1032 schema->fill_table = trx_i_s_common_fill_table;
1033
1034 DBUG_RETURN(0);
1035 }
1036
1037 UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks =
1038 {
1039 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1040 /* int */
1041 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1042
1043 /* pointer to type-specific plugin descriptor */
1044 /* void* */
1045 STRUCT_FLD(info, &i_s_info),
1046
1047 /* plugin name */
1048 /* const char* */
1049 STRUCT_FLD(name, "INNODB_LOCKS"),
1050
1051 /* plugin author (for SHOW PLUGINS) */
1052 /* const char* */
1053 STRUCT_FLD(author, plugin_author),
1054
1055 /* general descriptive text (for SHOW PLUGINS) */
1056 /* const char* */
1057 STRUCT_FLD(descr, "InnoDB conflicting locks"),
1058
1059 /* the plugin license (PLUGIN_LICENSE_XXX) */
1060 /* int */
1061 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1062
1063 /* the function to invoke when plugin is loaded */
1064 /* int (*)(void*); */
1065 STRUCT_FLD(init, innodb_locks_init),
1066
1067 /* the function to invoke when plugin is unloaded */
1068 /* int (*)(void*); */
1069 STRUCT_FLD(deinit, i_s_common_deinit),
1070
1071 /* plugin version (for SHOW PLUGINS) */
1072 /* unsigned int */
1073 STRUCT_FLD(version, INNODB_VERSION_SHORT),
1074
1075 /* struct st_mysql_show_var* */
1076 STRUCT_FLD(status_vars, NULL),
1077
1078 /* struct st_mysql_sys_var** */
1079 STRUCT_FLD(system_vars, NULL),
1080
1081 /* reserved for dependency checking */
1082 /* void* */
1083 STRUCT_FLD(__reserved1, NULL),
1084
1085 /* Plugin flags */
1086 /* unsigned long */
1087 STRUCT_FLD(flags, 0UL),
1088 };
1089
1090 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
1091 static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
1092 {
1093 #define IDX_REQUESTING_TRX_ID 0
1094 {STRUCT_FLD(field_name, "requesting_trx_id"),
1095 STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
1096 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1097 STRUCT_FLD(value, 0),
1098 STRUCT_FLD(field_flags, 0),
1099 STRUCT_FLD(old_name, ""),
1100 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1101
1102 #define IDX_REQUESTED_LOCK_ID 1
1103 {STRUCT_FLD(field_name, "requested_lock_id"),
1104 STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
1105 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1106 STRUCT_FLD(value, 0),
1107 STRUCT_FLD(field_flags, 0),
1108 STRUCT_FLD(old_name, ""),
1109 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1110
1111 #define IDX_BLOCKING_TRX_ID 2
1112 {STRUCT_FLD(field_name, "blocking_trx_id"),
1113 STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
1114 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1115 STRUCT_FLD(value, 0),
1116 STRUCT_FLD(field_flags, 0),
1117 STRUCT_FLD(old_name, ""),
1118 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1119
1120 #define IDX_BLOCKING_LOCK_ID 3
1121 {STRUCT_FLD(field_name, "blocking_lock_id"),
1122 STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
1123 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1124 STRUCT_FLD(value, 0),
1125 STRUCT_FLD(field_flags, 0),
1126 STRUCT_FLD(old_name, ""),
1127 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1128
1129 END_OF_ST_FIELD_INFO
1130 };
1131
1132 /*******************************************************************//**
1133 Read data from cache buffer and fill the
1134 INFORMATION_SCHEMA.innodb_lock_waits table with it.
1135 @return 0 on success */
1136 static
1137 int
fill_innodb_lock_waits_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)1138 fill_innodb_lock_waits_from_cache(
1139 /*==============================*/
1140 trx_i_s_cache_t* cache, /*!< in: cache to read from */
1141 THD* thd, /*!< in: used to call
1142 schema_table_store_record() */
1143 TABLE* table) /*!< in/out: fill this table */
1144 {
1145 Field** fields;
1146 ulint rows_num;
1147 char requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1148 char blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1149 ulint i;
1150
1151 DBUG_ENTER("fill_innodb_lock_waits_from_cache");
1152
1153 fields = table->field;
1154
1155 rows_num = trx_i_s_cache_get_rows_used(cache,
1156 I_S_INNODB_LOCK_WAITS);
1157
1158 for (i = 0; i < rows_num; i++) {
1159
1160 i_s_lock_waits_row_t* row;
1161
1162 char requesting_trx_id[TRX_ID_MAX_LEN + 1];
1163 char blocking_trx_id[TRX_ID_MAX_LEN + 1];
1164
1165 row = (i_s_lock_waits_row_t*)
1166 trx_i_s_cache_get_nth_row(
1167 cache, I_S_INNODB_LOCK_WAITS, i);
1168
1169 /* requesting_trx_id */
1170 ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
1171 TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
1172 OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
1173 requesting_trx_id));
1174
1175 /* requested_lock_id */
1176 OK(field_store_string(
1177 fields[IDX_REQUESTED_LOCK_ID],
1178 trx_i_s_create_lock_id(
1179 row->requested_lock_row,
1180 requested_lock_id,
1181 sizeof(requested_lock_id))));
1182
1183 /* blocking_trx_id */
1184 ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
1185 TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
1186 OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
1187 blocking_trx_id));
1188
1189 /* blocking_lock_id */
1190 OK(field_store_string(
1191 fields[IDX_BLOCKING_LOCK_ID],
1192 trx_i_s_create_lock_id(
1193 row->blocking_lock_row,
1194 blocking_lock_id,
1195 sizeof(blocking_lock_id))));
1196
1197 OK(schema_table_store_record(thd, table));
1198 }
1199
1200 DBUG_RETURN(0);
1201 }
1202
1203 /*******************************************************************//**
1204 Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
1205 @return 0 on success */
1206 static
1207 int
innodb_lock_waits_init(void * p)1208 innodb_lock_waits_init(
1209 /*===================*/
1210 void* p) /*!< in/out: table schema object */
1211 {
1212 ST_SCHEMA_TABLE* schema;
1213
1214 DBUG_ENTER("innodb_lock_waits_init");
1215
1216 schema = (ST_SCHEMA_TABLE*) p;
1217
1218 schema->fields_info = innodb_lock_waits_fields_info;
1219 schema->fill_table = trx_i_s_common_fill_table;
1220
1221 DBUG_RETURN(0);
1222 }
1223
1224 UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
1225 {
1226 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1227 /* int */
1228 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1229
1230 /* pointer to type-specific plugin descriptor */
1231 /* void* */
1232 STRUCT_FLD(info, &i_s_info),
1233
1234 /* plugin name */
1235 /* const char* */
1236 STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
1237
1238 /* plugin author (for SHOW PLUGINS) */
1239 /* const char* */
1240 STRUCT_FLD(author, plugin_author),
1241
1242 /* general descriptive text (for SHOW PLUGINS) */
1243 /* const char* */
1244 STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
1245
1246 /* the plugin license (PLUGIN_LICENSE_XXX) */
1247 /* int */
1248 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1249
1250 /* the function to invoke when plugin is loaded */
1251 /* int (*)(void*); */
1252 STRUCT_FLD(init, innodb_lock_waits_init),
1253
1254 /* the function to invoke when plugin is unloaded */
1255 /* int (*)(void*); */
1256 STRUCT_FLD(deinit, i_s_common_deinit),
1257
1258 /* plugin version (for SHOW PLUGINS) */
1259 /* unsigned int */
1260 STRUCT_FLD(version, INNODB_VERSION_SHORT),
1261
1262 /* struct st_mysql_show_var* */
1263 STRUCT_FLD(status_vars, NULL),
1264
1265 /* struct st_mysql_sys_var** */
1266 STRUCT_FLD(system_vars, NULL),
1267
1268 /* reserved for dependency checking */
1269 /* void* */
1270 STRUCT_FLD(__reserved1, NULL),
1271
1272 /* Plugin flags */
1273 /* unsigned long */
1274 STRUCT_FLD(flags, 0UL),
1275 };
1276
1277 /*******************************************************************//**
1278 Common function to fill any of the dynamic tables:
1279 INFORMATION_SCHEMA.innodb_trx
1280 INFORMATION_SCHEMA.innodb_locks
1281 INFORMATION_SCHEMA.innodb_lock_waits
1282 @return 0 on success */
1283 static
1284 int
trx_i_s_common_fill_table(THD * thd,TABLE_LIST * tables,Item *)1285 trx_i_s_common_fill_table(
1286 /*======================*/
1287 THD* thd, /*!< in: thread */
1288 TABLE_LIST* tables, /*!< in/out: tables to fill */
1289 Item* ) /*!< in: condition (not used) */
1290 {
1291 const char* table_name;
1292 int ret;
1293 trx_i_s_cache_t* cache;
1294
1295 DBUG_ENTER("trx_i_s_common_fill_table");
1296
1297 /* deny access to non-superusers */
1298 if (check_global_access(thd, PROCESS_ACL)) {
1299
1300 DBUG_RETURN(0);
1301 }
1302
1303 /* minimize the number of places where global variables are
1304 referenced */
1305 cache = trx_i_s_cache;
1306
1307 /* which table we have to fill? */
1308 table_name = tables->schema_table_name;
1309 /* or table_name = tables->schema_table->table_name; */
1310
1311 RETURN_IF_INNODB_NOT_STARTED(table_name);
1312
1313 /* update the cache */
1314 trx_i_s_cache_start_write(cache);
1315 trx_i_s_possibly_fetch_data_into_cache(cache);
1316 trx_i_s_cache_end_write(cache);
1317
1318 if (trx_i_s_cache_is_truncated(cache)) {
1319
1320 /* XXX show warning to user if possible */
1321 fprintf(stderr, "Warning: data in %s truncated due to "
1322 "memory limit of %d bytes\n", table_name,
1323 TRX_I_S_MEM_LIMIT);
1324 }
1325
1326 ret = 0;
1327
1328 trx_i_s_cache_start_read(cache);
1329
1330 if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
1331
1332 if (fill_innodb_trx_from_cache(
1333 cache, thd, tables->table) != 0) {
1334
1335 ret = 1;
1336 }
1337
1338 } else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
1339
1340 if (fill_innodb_locks_from_cache(
1341 cache, thd, tables->table) != 0) {
1342
1343 ret = 1;
1344 }
1345
1346 } else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
1347
1348 if (fill_innodb_lock_waits_from_cache(
1349 cache, thd, tables->table) != 0) {
1350
1351 ret = 1;
1352 }
1353
1354 } else {
1355
1356 /* huh! what happened!? */
1357 fprintf(stderr,
1358 "InnoDB: trx_i_s_common_fill_table() was "
1359 "called to fill unknown table: %s.\n"
1360 "This function only knows how to fill "
1361 "innodb_trx, innodb_locks and "
1362 "innodb_lock_waits tables.\n", table_name);
1363
1364 ret = 1;
1365 }
1366
1367 trx_i_s_cache_end_read(cache);
1368
1369 #if 0
1370 DBUG_RETURN(ret);
1371 #else
1372 /* if this function returns something else than 0 then a
1373 deadlock occurs between the mysqld server and mysql client,
1374 see http://bugs.mysql.com/29900 ; when that bug is resolved
1375 we can enable the DBUG_RETURN(ret) above */
1376 ret++; // silence a gcc46 warning
1377 DBUG_RETURN(0);
1378 #endif
1379 }
1380
1381 /* Fields of the dynamic table information_schema.innodb_cmp. */
1382 static ST_FIELD_INFO i_s_cmp_fields_info[] =
1383 {
1384 {STRUCT_FLD(field_name, "page_size"),
1385 STRUCT_FLD(field_length, 5),
1386 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1387 STRUCT_FLD(value, 0),
1388 STRUCT_FLD(field_flags, 0),
1389 STRUCT_FLD(old_name, "Compressed Page Size"),
1390 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1391
1392 {STRUCT_FLD(field_name, "compress_ops"),
1393 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1394 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1395 STRUCT_FLD(value, 0),
1396 STRUCT_FLD(field_flags, 0),
1397 STRUCT_FLD(old_name, "Total Number of Compressions"),
1398 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1399
1400 {STRUCT_FLD(field_name, "compress_ops_ok"),
1401 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1402 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1403 STRUCT_FLD(value, 0),
1404 STRUCT_FLD(field_flags, 0),
1405 STRUCT_FLD(old_name, "Total Number of"
1406 " Successful Compressions"),
1407 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1408
1409 {STRUCT_FLD(field_name, "compress_time"),
1410 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1411 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1412 STRUCT_FLD(value, 0),
1413 STRUCT_FLD(field_flags, 0),
1414 STRUCT_FLD(old_name, "Total Duration of Compressions,"
1415 " in Seconds"),
1416 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1417
1418 {STRUCT_FLD(field_name, "uncompress_ops"),
1419 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1420 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1421 STRUCT_FLD(value, 0),
1422 STRUCT_FLD(field_flags, 0),
1423 STRUCT_FLD(old_name, "Total Number of Decompressions"),
1424 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1425
1426 {STRUCT_FLD(field_name, "uncompress_time"),
1427 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1428 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1429 STRUCT_FLD(value, 0),
1430 STRUCT_FLD(field_flags, 0),
1431 STRUCT_FLD(old_name, "Total Duration of Decompressions,"
1432 " in Seconds"),
1433 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1434
1435 END_OF_ST_FIELD_INFO
1436 };
1437
1438
1439 /*******************************************************************//**
1440 Fill the dynamic table information_schema.innodb_cmp or
1441 innodb_cmp_reset.
1442 @return 0 on success, 1 on failure */
1443 static
1444 int
i_s_cmp_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)1445 i_s_cmp_fill_low(
1446 /*=============*/
1447 THD* thd, /*!< in: thread */
1448 TABLE_LIST* tables, /*!< in/out: tables to fill */
1449 Item* , /*!< in: condition (ignored) */
1450 ibool reset) /*!< in: TRUE=reset cumulated counts */
1451 {
1452 TABLE* table = (TABLE*) tables->table;
1453 int status = 0;
1454
1455 DBUG_ENTER("i_s_cmp_fill_low");
1456
1457 /* deny access to non-superusers */
1458 if (check_global_access(thd, PROCESS_ACL)) {
1459
1460 DBUG_RETURN(0);
1461 }
1462
1463 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1464
1465 for (uint i = 0; i < PAGE_ZIP_SSIZE_MAX; i++) {
1466 page_zip_stat_t* zip_stat = &page_zip_stat[i];
1467
1468 table->field[0]->store(UNIV_ZIP_SIZE_MIN << i);
1469
1470 /* The cumulated counts are not protected by any
1471 mutex. Thus, some operation in page0zip.cc could
1472 increment a counter between the time we read it and
1473 clear it. We could introduce mutex protection, but it
1474 could cause a measureable performance hit in
1475 page0zip.cc. */
1476 table->field[1]->store(
1477 static_cast<double>(zip_stat->compressed));
1478 table->field[2]->store(
1479 static_cast<double>(zip_stat->compressed_ok));
1480 table->field[3]->store(
1481 static_cast<double>(zip_stat->compressed_usec / 1000000));
1482 table->field[4]->store(
1483 static_cast<double>(zip_stat->decompressed));
1484 table->field[5]->store(
1485 static_cast<double>(zip_stat->decompressed_usec / 1000000));
1486
1487 if (reset) {
1488 memset(zip_stat, 0, sizeof *zip_stat);
1489 }
1490
1491 if (schema_table_store_record(thd, table)) {
1492 status = 1;
1493 break;
1494 }
1495 }
1496
1497 DBUG_RETURN(status);
1498 }
1499
1500 /*******************************************************************//**
1501 Fill the dynamic table information_schema.innodb_cmp.
1502 @return 0 on success, 1 on failure */
1503 static
1504 int
i_s_cmp_fill(THD * thd,TABLE_LIST * tables,Item * cond)1505 i_s_cmp_fill(
1506 /*=========*/
1507 THD* thd, /*!< in: thread */
1508 TABLE_LIST* tables, /*!< in/out: tables to fill */
1509 Item* cond) /*!< in: condition (ignored) */
1510 {
1511 return(i_s_cmp_fill_low(thd, tables, cond, FALSE));
1512 }
1513
1514 /*******************************************************************//**
1515 Fill the dynamic table information_schema.innodb_cmp_reset.
1516 @return 0 on success, 1 on failure */
1517 static
1518 int
i_s_cmp_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)1519 i_s_cmp_reset_fill(
1520 /*===============*/
1521 THD* thd, /*!< in: thread */
1522 TABLE_LIST* tables, /*!< in/out: tables to fill */
1523 Item* cond) /*!< in: condition (ignored) */
1524 {
1525 return(i_s_cmp_fill_low(thd, tables, cond, TRUE));
1526 }
1527
1528 /*******************************************************************//**
1529 Bind the dynamic table information_schema.innodb_cmp.
1530 @return 0 on success */
1531 static
1532 int
i_s_cmp_init(void * p)1533 i_s_cmp_init(
1534 /*=========*/
1535 void* p) /*!< in/out: table schema object */
1536 {
1537 DBUG_ENTER("i_s_cmp_init");
1538 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1539
1540 schema->fields_info = i_s_cmp_fields_info;
1541 schema->fill_table = i_s_cmp_fill;
1542
1543 DBUG_RETURN(0);
1544 }
1545
1546 /*******************************************************************//**
1547 Bind the dynamic table information_schema.innodb_cmp_reset.
1548 @return 0 on success */
1549 static
1550 int
i_s_cmp_reset_init(void * p)1551 i_s_cmp_reset_init(
1552 /*===============*/
1553 void* p) /*!< in/out: table schema object */
1554 {
1555 DBUG_ENTER("i_s_cmp_reset_init");
1556 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1557
1558 schema->fields_info = i_s_cmp_fields_info;
1559 schema->fill_table = i_s_cmp_reset_fill;
1560
1561 DBUG_RETURN(0);
1562 }
1563
1564 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp =
1565 {
1566 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1567 /* int */
1568 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1569
1570 /* pointer to type-specific plugin descriptor */
1571 /* void* */
1572 STRUCT_FLD(info, &i_s_info),
1573
1574 /* plugin name */
1575 /* const char* */
1576 STRUCT_FLD(name, "INNODB_CMP"),
1577
1578 /* plugin author (for SHOW PLUGINS) */
1579 /* const char* */
1580 STRUCT_FLD(author, plugin_author),
1581
1582 /* general descriptive text (for SHOW PLUGINS) */
1583 /* const char* */
1584 STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
1585
1586 /* the plugin license (PLUGIN_LICENSE_XXX) */
1587 /* int */
1588 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1589
1590 /* the function to invoke when plugin is loaded */
1591 /* int (*)(void*); */
1592 STRUCT_FLD(init, i_s_cmp_init),
1593
1594 /* the function to invoke when plugin is unloaded */
1595 /* int (*)(void*); */
1596 STRUCT_FLD(deinit, i_s_common_deinit),
1597
1598 /* plugin version (for SHOW PLUGINS) */
1599 /* unsigned int */
1600 STRUCT_FLD(version, INNODB_VERSION_SHORT),
1601
1602 /* struct st_mysql_show_var* */
1603 STRUCT_FLD(status_vars, NULL),
1604
1605 /* struct st_mysql_sys_var** */
1606 STRUCT_FLD(system_vars, NULL),
1607
1608 /* reserved for dependency checking */
1609 /* void* */
1610 STRUCT_FLD(__reserved1, NULL),
1611
1612 /* Plugin flags */
1613 /* unsigned long */
1614 STRUCT_FLD(flags, 0UL),
1615 };
1616
1617 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
1618 {
1619 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1620 /* int */
1621 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1622
1623 /* pointer to type-specific plugin descriptor */
1624 /* void* */
1625 STRUCT_FLD(info, &i_s_info),
1626
1627 /* plugin name */
1628 /* const char* */
1629 STRUCT_FLD(name, "INNODB_CMP_RESET"),
1630
1631 /* plugin author (for SHOW PLUGINS) */
1632 /* const char* */
1633 STRUCT_FLD(author, plugin_author),
1634
1635 /* general descriptive text (for SHOW PLUGINS) */
1636 /* const char* */
1637 STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
1638 " reset cumulated counts"),
1639
1640 /* the plugin license (PLUGIN_LICENSE_XXX) */
1641 /* int */
1642 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1643
1644 /* the function to invoke when plugin is loaded */
1645 /* int (*)(void*); */
1646 STRUCT_FLD(init, i_s_cmp_reset_init),
1647
1648 /* the function to invoke when plugin is unloaded */
1649 /* int (*)(void*); */
1650 STRUCT_FLD(deinit, i_s_common_deinit),
1651
1652 /* plugin version (for SHOW PLUGINS) */
1653 /* unsigned int */
1654 STRUCT_FLD(version, INNODB_VERSION_SHORT),
1655
1656 /* struct st_mysql_show_var* */
1657 STRUCT_FLD(status_vars, NULL),
1658
1659 /* struct st_mysql_sys_var** */
1660 STRUCT_FLD(system_vars, NULL),
1661
1662 /* reserved for dependency checking */
1663 /* void* */
1664 STRUCT_FLD(__reserved1, NULL),
1665
1666 /* Plugin flags */
1667 /* unsigned long */
1668 STRUCT_FLD(flags, 0UL),
1669 };
1670
1671 /* Fields of the dynamic tables
1672 information_schema.innodb_cmp_per_index and
1673 information_schema.innodb_cmp_per_index_reset. */
1674 static ST_FIELD_INFO i_s_cmp_per_index_fields_info[] =
1675 {
1676 #define IDX_DATABASE_NAME 0
1677 {STRUCT_FLD(field_name, "database_name"),
1678 STRUCT_FLD(field_length, 192),
1679 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1680 STRUCT_FLD(value, 0),
1681 STRUCT_FLD(field_flags, 0),
1682 STRUCT_FLD(old_name, ""),
1683 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1684
1685 #define IDX_TABLE_NAME 1
1686 {STRUCT_FLD(field_name, "table_name"),
1687 STRUCT_FLD(field_length, 192),
1688 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1689 STRUCT_FLD(value, 0),
1690 STRUCT_FLD(field_flags, 0),
1691 STRUCT_FLD(old_name, ""),
1692 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1693
1694 #define IDX_INDEX_NAME 2
1695 {STRUCT_FLD(field_name, "index_name"),
1696 STRUCT_FLD(field_length, 192),
1697 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
1698 STRUCT_FLD(value, 0),
1699 STRUCT_FLD(field_flags, 0),
1700 STRUCT_FLD(old_name, ""),
1701 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1702
1703 #define IDX_COMPRESS_OPS 3
1704 {STRUCT_FLD(field_name, "compress_ops"),
1705 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1706 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1707 STRUCT_FLD(value, 0),
1708 STRUCT_FLD(field_flags, 0),
1709 STRUCT_FLD(old_name, ""),
1710 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1711
1712 #define IDX_COMPRESS_OPS_OK 4
1713 {STRUCT_FLD(field_name, "compress_ops_ok"),
1714 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1715 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1716 STRUCT_FLD(value, 0),
1717 STRUCT_FLD(field_flags, 0),
1718 STRUCT_FLD(old_name, ""),
1719 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1720
1721 #define IDX_COMPRESS_TIME 5
1722 {STRUCT_FLD(field_name, "compress_time"),
1723 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1724 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1725 STRUCT_FLD(value, 0),
1726 STRUCT_FLD(field_flags, 0),
1727 STRUCT_FLD(old_name, ""),
1728 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1729
1730 #define IDX_UNCOMPRESS_OPS 6
1731 {STRUCT_FLD(field_name, "uncompress_ops"),
1732 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1733 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1734 STRUCT_FLD(value, 0),
1735 STRUCT_FLD(field_flags, 0),
1736 STRUCT_FLD(old_name, ""),
1737 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1738
1739 #define IDX_UNCOMPRESS_TIME 7
1740 {STRUCT_FLD(field_name, "uncompress_time"),
1741 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
1742 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
1743 STRUCT_FLD(value, 0),
1744 STRUCT_FLD(field_flags, 0),
1745 STRUCT_FLD(old_name, ""),
1746 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
1747
1748 END_OF_ST_FIELD_INFO
1749 };
1750
1751 /*******************************************************************//**
1752 Fill the dynamic table
1753 information_schema.innodb_cmp_per_index or
1754 information_schema.innodb_cmp_per_index_reset.
1755 @return 0 on success, 1 on failure */
1756 static
1757 int
i_s_cmp_per_index_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)1758 i_s_cmp_per_index_fill_low(
1759 /*=======================*/
1760 THD* thd, /*!< in: thread */
1761 TABLE_LIST* tables, /*!< in/out: tables to fill */
1762 Item* , /*!< in: condition (ignored) */
1763 ibool reset) /*!< in: TRUE=reset cumulated counts */
1764 {
1765 TABLE* table = tables->table;
1766 Field** fields = table->field;
1767 int status = 0;
1768
1769 DBUG_ENTER("i_s_cmp_per_index_fill_low");
1770
1771 /* deny access to non-superusers */
1772 if (check_global_access(thd, PROCESS_ACL)) {
1773
1774 DBUG_RETURN(0);
1775 }
1776
1777 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1778
1779 /* Create a snapshot of the stats so we do not bump into lock
1780 order violations with dict_sys->mutex below. */
1781 mutex_enter(&page_zip_stat_per_index_mutex);
1782 page_zip_stat_per_index_t snap (page_zip_stat_per_index);
1783 mutex_exit(&page_zip_stat_per_index_mutex);
1784
1785 mutex_enter(&dict_sys->mutex);
1786
1787 page_zip_stat_per_index_t::iterator iter;
1788 ulint i;
1789
1790 for (iter = snap.begin(), i = 0; iter != snap.end(); iter++, i++) {
1791
1792 char name[192];
1793 dict_index_t* index = dict_index_find_on_id_low(iter->first);
1794
1795 if (index != NULL) {
1796 char db_utf8[MAX_DB_UTF8_LEN];
1797 char table_utf8[MAX_TABLE_UTF8_LEN];
1798
1799 dict_fs2utf8(index->table_name,
1800 db_utf8, sizeof(db_utf8),
1801 table_utf8, sizeof(table_utf8));
1802
1803 field_store_string(fields[IDX_DATABASE_NAME], db_utf8);
1804 field_store_string(fields[IDX_TABLE_NAME], table_utf8);
1805 field_store_index_name(fields[IDX_INDEX_NAME],
1806 index->name);
1807 } else {
1808 /* index not found */
1809 ut_snprintf(name, sizeof(name),
1810 "index_id:" IB_ID_FMT, iter->first);
1811 field_store_string(fields[IDX_DATABASE_NAME],
1812 "unknown");
1813 field_store_string(fields[IDX_TABLE_NAME],
1814 "unknown");
1815 field_store_string(fields[IDX_INDEX_NAME],
1816 name);
1817 }
1818
1819 fields[IDX_COMPRESS_OPS]->store(
1820 static_cast<double>(iter->second.compressed));
1821
1822 fields[IDX_COMPRESS_OPS_OK]->store(
1823 static_cast<double>(iter->second.compressed_ok));
1824
1825 fields[IDX_COMPRESS_TIME]->store(
1826 static_cast<double>(iter->second.compressed_usec / 1000000));
1827
1828 fields[IDX_UNCOMPRESS_OPS]->store(
1829 static_cast<double>(iter->second.decompressed));
1830
1831 fields[IDX_UNCOMPRESS_TIME]->store(
1832 static_cast<double>(iter->second.decompressed_usec / 1000000));
1833
1834 if (schema_table_store_record(thd, table)) {
1835 status = 1;
1836 break;
1837 }
1838
1839 /* Release and reacquire the dict mutex to allow other
1840 threads to proceed. This could eventually result in the
1841 contents of INFORMATION_SCHEMA.innodb_cmp_per_index being
1842 inconsistent, but it is an acceptable compromise. */
1843 if (i % 1000 == 0) {
1844 mutex_exit(&dict_sys->mutex);
1845 mutex_enter(&dict_sys->mutex);
1846 }
1847 }
1848
1849 mutex_exit(&dict_sys->mutex);
1850
1851 if (reset) {
1852 page_zip_reset_stat_per_index();
1853 }
1854
1855 DBUG_RETURN(status);
1856 }
1857
1858 /*******************************************************************//**
1859 Fill the dynamic table information_schema.innodb_cmp_per_index.
1860 @return 0 on success, 1 on failure */
1861 static
1862 int
i_s_cmp_per_index_fill(THD * thd,TABLE_LIST * tables,Item * cond)1863 i_s_cmp_per_index_fill(
1864 /*===================*/
1865 THD* thd, /*!< in: thread */
1866 TABLE_LIST* tables, /*!< in/out: tables to fill */
1867 Item* cond) /*!< in: condition (ignored) */
1868 {
1869 return(i_s_cmp_per_index_fill_low(thd, tables, cond, FALSE));
1870 }
1871
1872 /*******************************************************************//**
1873 Fill the dynamic table information_schema.innodb_cmp_per_index_reset.
1874 @return 0 on success, 1 on failure */
1875 static
1876 int
i_s_cmp_per_index_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)1877 i_s_cmp_per_index_reset_fill(
1878 /*=========================*/
1879 THD* thd, /*!< in: thread */
1880 TABLE_LIST* tables, /*!< in/out: tables to fill */
1881 Item* cond) /*!< in: condition (ignored) */
1882 {
1883 return(i_s_cmp_per_index_fill_low(thd, tables, cond, TRUE));
1884 }
1885
1886 /*******************************************************************//**
1887 Bind the dynamic table information_schema.innodb_cmp_per_index.
1888 @return 0 on success */
1889 static
1890 int
i_s_cmp_per_index_init(void * p)1891 i_s_cmp_per_index_init(
1892 /*===================*/
1893 void* p) /*!< in/out: table schema object */
1894 {
1895 DBUG_ENTER("i_s_cmp_init");
1896 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1897
1898 schema->fields_info = i_s_cmp_per_index_fields_info;
1899 schema->fill_table = i_s_cmp_per_index_fill;
1900
1901 DBUG_RETURN(0);
1902 }
1903
1904 /*******************************************************************//**
1905 Bind the dynamic table information_schema.innodb_cmp_per_index_reset.
1906 @return 0 on success */
1907 static
1908 int
i_s_cmp_per_index_reset_init(void * p)1909 i_s_cmp_per_index_reset_init(
1910 /*=========================*/
1911 void* p) /*!< in/out: table schema object */
1912 {
1913 DBUG_ENTER("i_s_cmp_reset_init");
1914 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1915
1916 schema->fields_info = i_s_cmp_per_index_fields_info;
1917 schema->fill_table = i_s_cmp_per_index_reset_fill;
1918
1919 DBUG_RETURN(0);
1920 }
1921
1922 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index =
1923 {
1924 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1925 /* int */
1926 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1927
1928 /* pointer to type-specific plugin descriptor */
1929 /* void* */
1930 STRUCT_FLD(info, &i_s_info),
1931
1932 /* plugin name */
1933 /* const char* */
1934 STRUCT_FLD(name, "INNODB_CMP_PER_INDEX"),
1935
1936 /* plugin author (for SHOW PLUGINS) */
1937 /* const char* */
1938 STRUCT_FLD(author, plugin_author),
1939
1940 /* general descriptive text (for SHOW PLUGINS) */
1941 /* const char* */
1942 STRUCT_FLD(descr, "Statistics for the InnoDB compression (per index)"),
1943
1944 /* the plugin license (PLUGIN_LICENSE_XXX) */
1945 /* int */
1946 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1947
1948 /* the function to invoke when plugin is loaded */
1949 /* int (*)(void*); */
1950 STRUCT_FLD(init, i_s_cmp_per_index_init),
1951
1952 /* the function to invoke when plugin is unloaded */
1953 /* int (*)(void*); */
1954 STRUCT_FLD(deinit, i_s_common_deinit),
1955
1956 /* plugin version (for SHOW PLUGINS) */
1957 /* unsigned int */
1958 STRUCT_FLD(version, INNODB_VERSION_SHORT),
1959
1960 /* struct st_mysql_show_var* */
1961 STRUCT_FLD(status_vars, NULL),
1962
1963 /* struct st_mysql_sys_var** */
1964 STRUCT_FLD(system_vars, NULL),
1965
1966 /* reserved for dependency checking */
1967 /* void* */
1968 STRUCT_FLD(__reserved1, NULL),
1969
1970 /* Plugin flags */
1971 /* unsigned long */
1972 STRUCT_FLD(flags, 0UL),
1973 };
1974
1975 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_per_index_reset =
1976 {
1977 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
1978 /* int */
1979 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1980
1981 /* pointer to type-specific plugin descriptor */
1982 /* void* */
1983 STRUCT_FLD(info, &i_s_info),
1984
1985 /* plugin name */
1986 /* const char* */
1987 STRUCT_FLD(name, "INNODB_CMP_PER_INDEX_RESET"),
1988
1989 /* plugin author (for SHOW PLUGINS) */
1990 /* const char* */
1991 STRUCT_FLD(author, plugin_author),
1992
1993 /* general descriptive text (for SHOW PLUGINS) */
1994 /* const char* */
1995 STRUCT_FLD(descr, "Statistics for the InnoDB compression (per index);"
1996 " reset cumulated counts"),
1997
1998 /* the plugin license (PLUGIN_LICENSE_XXX) */
1999 /* int */
2000 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2001
2002 /* the function to invoke when plugin is loaded */
2003 /* int (*)(void*); */
2004 STRUCT_FLD(init, i_s_cmp_per_index_reset_init),
2005
2006 /* the function to invoke when plugin is unloaded */
2007 /* int (*)(void*); */
2008 STRUCT_FLD(deinit, i_s_common_deinit),
2009
2010 /* plugin version (for SHOW PLUGINS) */
2011 /* unsigned int */
2012 STRUCT_FLD(version, INNODB_VERSION_SHORT),
2013
2014 /* struct st_mysql_show_var* */
2015 STRUCT_FLD(status_vars, NULL),
2016
2017 /* struct st_mysql_sys_var** */
2018 STRUCT_FLD(system_vars, NULL),
2019
2020 /* reserved for dependency checking */
2021 /* void* */
2022 STRUCT_FLD(__reserved1, NULL),
2023
2024 /* Plugin flags */
2025 /* unsigned long */
2026 STRUCT_FLD(flags, 0UL),
2027 };
2028
2029 /* Fields of the dynamic table information_schema.innodb_cmpmem. */
2030 static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
2031 {
2032 {STRUCT_FLD(field_name, "page_size"),
2033 STRUCT_FLD(field_length, 5),
2034 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
2035 STRUCT_FLD(value, 0),
2036 STRUCT_FLD(field_flags, 0),
2037 STRUCT_FLD(old_name, "Buddy Block Size"),
2038 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2039
2040 {STRUCT_FLD(field_name, "buffer_pool_instance"),
2041 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
2042 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
2043 STRUCT_FLD(value, 0),
2044 STRUCT_FLD(field_flags, 0),
2045 STRUCT_FLD(old_name, "Buffer Pool Id"),
2046 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2047
2048 {STRUCT_FLD(field_name, "pages_used"),
2049 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
2050 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
2051 STRUCT_FLD(value, 0),
2052 STRUCT_FLD(field_flags, 0),
2053 STRUCT_FLD(old_name, "Currently in Use"),
2054 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2055
2056 {STRUCT_FLD(field_name, "pages_free"),
2057 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
2058 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
2059 STRUCT_FLD(value, 0),
2060 STRUCT_FLD(field_flags, 0),
2061 STRUCT_FLD(old_name, "Currently Available"),
2062 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2063
2064 {STRUCT_FLD(field_name, "relocation_ops"),
2065 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2066 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2067 STRUCT_FLD(value, 0),
2068 STRUCT_FLD(field_flags, 0),
2069 STRUCT_FLD(old_name, "Total Number of Relocations"),
2070 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2071
2072 {STRUCT_FLD(field_name, "relocation_time"),
2073 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
2074 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
2075 STRUCT_FLD(value, 0),
2076 STRUCT_FLD(field_flags, 0),
2077 STRUCT_FLD(old_name, "Total Duration of Relocations,"
2078 " in Seconds"),
2079 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2080
2081 END_OF_ST_FIELD_INFO
2082 };
2083
2084 /*******************************************************************//**
2085 Fill the dynamic table information_schema.innodb_cmpmem or
2086 innodb_cmpmem_reset.
2087 @return 0 on success, 1 on failure */
2088 static
2089 int
i_s_cmpmem_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)2090 i_s_cmpmem_fill_low(
2091 /*================*/
2092 THD* thd, /*!< in: thread */
2093 TABLE_LIST* tables, /*!< in/out: tables to fill */
2094 Item* , /*!< in: condition (ignored) */
2095 ibool reset) /*!< in: TRUE=reset cumulated counts */
2096 {
2097 int status = 0;
2098 TABLE* table = (TABLE*) tables->table;
2099
2100 DBUG_ENTER("i_s_cmpmem_fill_low");
2101
2102 /* deny access to non-superusers */
2103 if (check_global_access(thd, PROCESS_ACL)) {
2104
2105 DBUG_RETURN(0);
2106 }
2107
2108 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
2109
2110 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
2111 buf_pool_t* buf_pool;
2112
2113 status = 0;
2114
2115 buf_pool = buf_pool_from_array(i);
2116
2117 buf_pool_mutex_enter(buf_pool);
2118
2119 for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
2120 buf_buddy_stat_t* buddy_stat;
2121
2122 buddy_stat = &buf_pool->buddy_stat[x];
2123
2124 table->field[0]->store(BUF_BUDDY_LOW << x);
2125 table->field[1]->store(static_cast<double>(i));
2126 table->field[2]->store(static_cast<double>(
2127 buddy_stat->used));
2128 table->field[3]->store(static_cast<double>(
2129 (x < BUF_BUDDY_SIZES)
2130 ? UT_LIST_GET_LEN(buf_pool->zip_free[x])
2131 : 0));
2132 table->field[4]->store(
2133 (longlong) buddy_stat->relocated, true);
2134 table->field[5]->store(
2135 static_cast<double>(buddy_stat->relocated_usec / 1000000));
2136
2137 if (reset) {
2138 /* This is protected by buf_pool->mutex. */
2139 buddy_stat->relocated = 0;
2140 buddy_stat->relocated_usec = 0;
2141 }
2142
2143 if (schema_table_store_record(thd, table)) {
2144 status = 1;
2145 break;
2146 }
2147 }
2148
2149 buf_pool_mutex_exit(buf_pool);
2150
2151 if (status) {
2152 break;
2153 }
2154 }
2155
2156 DBUG_RETURN(status);
2157 }
2158
2159 /*******************************************************************//**
2160 Fill the dynamic table information_schema.innodb_cmpmem.
2161 @return 0 on success, 1 on failure */
2162 static
2163 int
i_s_cmpmem_fill(THD * thd,TABLE_LIST * tables,Item * cond)2164 i_s_cmpmem_fill(
2165 /*============*/
2166 THD* thd, /*!< in: thread */
2167 TABLE_LIST* tables, /*!< in/out: tables to fill */
2168 Item* cond) /*!< in: condition (ignored) */
2169 {
2170 return(i_s_cmpmem_fill_low(thd, tables, cond, FALSE));
2171 }
2172
2173 /*******************************************************************//**
2174 Fill the dynamic table information_schema.innodb_cmpmem_reset.
2175 @return 0 on success, 1 on failure */
2176 static
2177 int
i_s_cmpmem_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)2178 i_s_cmpmem_reset_fill(
2179 /*==================*/
2180 THD* thd, /*!< in: thread */
2181 TABLE_LIST* tables, /*!< in/out: tables to fill */
2182 Item* cond) /*!< in: condition (ignored) */
2183 {
2184 return(i_s_cmpmem_fill_low(thd, tables, cond, TRUE));
2185 }
2186
2187 /*******************************************************************//**
2188 Bind the dynamic table information_schema.innodb_cmpmem.
2189 @return 0 on success */
2190 static
2191 int
i_s_cmpmem_init(void * p)2192 i_s_cmpmem_init(
2193 /*============*/
2194 void* p) /*!< in/out: table schema object */
2195 {
2196 DBUG_ENTER("i_s_cmpmem_init");
2197 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2198
2199 schema->fields_info = i_s_cmpmem_fields_info;
2200 schema->fill_table = i_s_cmpmem_fill;
2201
2202 DBUG_RETURN(0);
2203 }
2204
2205 /*******************************************************************//**
2206 Bind the dynamic table information_schema.innodb_cmpmem_reset.
2207 @return 0 on success */
2208 static
2209 int
i_s_cmpmem_reset_init(void * p)2210 i_s_cmpmem_reset_init(
2211 /*==================*/
2212 void* p) /*!< in/out: table schema object */
2213 {
2214 DBUG_ENTER("i_s_cmpmem_reset_init");
2215 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2216
2217 schema->fields_info = i_s_cmpmem_fields_info;
2218 schema->fill_table = i_s_cmpmem_reset_fill;
2219
2220 DBUG_RETURN(0);
2221 }
2222
2223 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem =
2224 {
2225 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
2226 /* int */
2227 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2228
2229 /* pointer to type-specific plugin descriptor */
2230 /* void* */
2231 STRUCT_FLD(info, &i_s_info),
2232
2233 /* plugin name */
2234 /* const char* */
2235 STRUCT_FLD(name, "INNODB_CMPMEM"),
2236
2237 /* plugin author (for SHOW PLUGINS) */
2238 /* const char* */
2239 STRUCT_FLD(author, plugin_author),
2240
2241 /* general descriptive text (for SHOW PLUGINS) */
2242 /* const char* */
2243 STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
2244
2245 /* the plugin license (PLUGIN_LICENSE_XXX) */
2246 /* int */
2247 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2248
2249 /* the function to invoke when plugin is loaded */
2250 /* int (*)(void*); */
2251 STRUCT_FLD(init, i_s_cmpmem_init),
2252
2253 /* the function to invoke when plugin is unloaded */
2254 /* int (*)(void*); */
2255 STRUCT_FLD(deinit, i_s_common_deinit),
2256
2257 /* plugin version (for SHOW PLUGINS) */
2258 /* unsigned int */
2259 STRUCT_FLD(version, INNODB_VERSION_SHORT),
2260
2261 /* struct st_mysql_show_var* */
2262 STRUCT_FLD(status_vars, NULL),
2263
2264 /* struct st_mysql_sys_var** */
2265 STRUCT_FLD(system_vars, NULL),
2266
2267 /* reserved for dependency checking */
2268 /* void* */
2269 STRUCT_FLD(__reserved1, NULL),
2270
2271 /* Plugin flags */
2272 /* unsigned long */
2273 STRUCT_FLD(flags, 0UL),
2274 };
2275
2276 UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
2277 {
2278 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
2279 /* int */
2280 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2281
2282 /* pointer to type-specific plugin descriptor */
2283 /* void* */
2284 STRUCT_FLD(info, &i_s_info),
2285
2286 /* plugin name */
2287 /* const char* */
2288 STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
2289
2290 /* plugin author (for SHOW PLUGINS) */
2291 /* const char* */
2292 STRUCT_FLD(author, plugin_author),
2293
2294 /* general descriptive text (for SHOW PLUGINS) */
2295 /* const char* */
2296 STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
2297 " reset cumulated counts"),
2298
2299 /* the plugin license (PLUGIN_LICENSE_XXX) */
2300 /* int */
2301 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2302
2303 /* the function to invoke when plugin is loaded */
2304 /* int (*)(void*); */
2305 STRUCT_FLD(init, i_s_cmpmem_reset_init),
2306
2307 /* the function to invoke when plugin is unloaded */
2308 /* int (*)(void*); */
2309 STRUCT_FLD(deinit, i_s_common_deinit),
2310
2311 /* plugin version (for SHOW PLUGINS) */
2312 /* unsigned int */
2313 STRUCT_FLD(version, INNODB_VERSION_SHORT),
2314
2315 /* struct st_mysql_show_var* */
2316 STRUCT_FLD(status_vars, NULL),
2317
2318 /* struct st_mysql_sys_var** */
2319 STRUCT_FLD(system_vars, NULL),
2320
2321 /* reserved for dependency checking */
2322 /* void* */
2323 STRUCT_FLD(__reserved1, NULL),
2324
2325 /* Plugin flags */
2326 /* unsigned long */
2327 STRUCT_FLD(flags, 0UL),
2328 };
2329
2330 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_metrics */
2331 static ST_FIELD_INFO innodb_metrics_fields_info[] =
2332 {
2333 #define METRIC_NAME 0
2334 {STRUCT_FLD(field_name, "NAME"),
2335 STRUCT_FLD(field_length, NAME_LEN + 1),
2336 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2337 STRUCT_FLD(value, 0),
2338 STRUCT_FLD(field_flags, 0),
2339 STRUCT_FLD(old_name, ""),
2340 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2341
2342 #define METRIC_SUBSYS 1
2343 {STRUCT_FLD(field_name, "SUBSYSTEM"),
2344 STRUCT_FLD(field_length, NAME_LEN + 1),
2345 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2346 STRUCT_FLD(value, 0),
2347 STRUCT_FLD(field_flags, 0),
2348 STRUCT_FLD(old_name, ""),
2349 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2350
2351 #define METRIC_VALUE_START 2
2352 {STRUCT_FLD(field_name, "COUNT"),
2353 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2354 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2355 STRUCT_FLD(value, 0),
2356 STRUCT_FLD(field_flags, 0),
2357 STRUCT_FLD(old_name, ""),
2358 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2359
2360 #define METRIC_MAX_VALUE_START 3
2361 {STRUCT_FLD(field_name, "MAX_COUNT"),
2362 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2363 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2364 STRUCT_FLD(value, 0),
2365 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2366 STRUCT_FLD(old_name, ""),
2367 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2368
2369 #define METRIC_MIN_VALUE_START 4
2370 {STRUCT_FLD(field_name, "MIN_COUNT"),
2371 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2372 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2373 STRUCT_FLD(value, 0),
2374 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2375 STRUCT_FLD(old_name, ""),
2376 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2377
2378 #define METRIC_AVG_VALUE_START 5
2379 {STRUCT_FLD(field_name, "AVG_COUNT"),
2380 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
2381 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
2382 STRUCT_FLD(value, 0),
2383 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2384 STRUCT_FLD(old_name, ""),
2385 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2386
2387 #define METRIC_VALUE_RESET 6
2388 {STRUCT_FLD(field_name, "COUNT_RESET"),
2389 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2390 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2391 STRUCT_FLD(value, 0),
2392 STRUCT_FLD(field_flags, 0),
2393 STRUCT_FLD(old_name, ""),
2394 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2395
2396 #define METRIC_MAX_VALUE_RESET 7
2397 {STRUCT_FLD(field_name, "MAX_COUNT_RESET"),
2398 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2399 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2400 STRUCT_FLD(value, 0),
2401 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2402 STRUCT_FLD(old_name, ""),
2403 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2404
2405 #define METRIC_MIN_VALUE_RESET 8
2406 {STRUCT_FLD(field_name, "MIN_COUNT_RESET"),
2407 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2408 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2409 STRUCT_FLD(value, 0),
2410 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2411 STRUCT_FLD(old_name, ""),
2412 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2413
2414 #define METRIC_AVG_VALUE_RESET 9
2415 {STRUCT_FLD(field_name, "AVG_COUNT_RESET"),
2416 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
2417 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
2418 STRUCT_FLD(value, 0),
2419 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2420 STRUCT_FLD(old_name, ""),
2421 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2422
2423 #define METRIC_START_TIME 10
2424 {STRUCT_FLD(field_name, "TIME_ENABLED"),
2425 STRUCT_FLD(field_length, 0),
2426 STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
2427 STRUCT_FLD(value, 0),
2428 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2429 STRUCT_FLD(old_name, ""),
2430 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2431
2432 #define METRIC_STOP_TIME 11
2433 {STRUCT_FLD(field_name, "TIME_DISABLED"),
2434 STRUCT_FLD(field_length, 0),
2435 STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
2436 STRUCT_FLD(value, 0),
2437 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2438 STRUCT_FLD(old_name, ""),
2439 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2440
2441 #define METRIC_TIME_ELAPSED 12
2442 {STRUCT_FLD(field_name, "TIME_ELAPSED"),
2443 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2444 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2445 STRUCT_FLD(value, 0),
2446 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2447 STRUCT_FLD(old_name, ""),
2448 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2449
2450 #define METRIC_RESET_TIME 13
2451 {STRUCT_FLD(field_name, "TIME_RESET"),
2452 STRUCT_FLD(field_length, 0),
2453 STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
2454 STRUCT_FLD(value, 0),
2455 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
2456 STRUCT_FLD(old_name, ""),
2457 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2458
2459 #define METRIC_STATUS 14
2460 {STRUCT_FLD(field_name, "STATUS"),
2461 STRUCT_FLD(field_length, NAME_LEN + 1),
2462 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2463 STRUCT_FLD(value, 0),
2464 STRUCT_FLD(field_flags, 0),
2465 STRUCT_FLD(old_name, ""),
2466 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2467
2468 #define METRIC_TYPE 15
2469 {STRUCT_FLD(field_name, "TYPE"),
2470 STRUCT_FLD(field_length, NAME_LEN + 1),
2471 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2472 STRUCT_FLD(value, 0),
2473 STRUCT_FLD(field_flags, 0),
2474 STRUCT_FLD(old_name, ""),
2475 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2476
2477 #define METRIC_DESC 16
2478 {STRUCT_FLD(field_name, "COMMENT"),
2479 STRUCT_FLD(field_length, NAME_LEN + 1),
2480 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2481 STRUCT_FLD(value, 0),
2482 STRUCT_FLD(field_flags, 0),
2483 STRUCT_FLD(old_name, ""),
2484 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2485
2486 END_OF_ST_FIELD_INFO
2487 };
2488
2489 /**********************************************************************//**
2490 Fill the information schema metrics table.
2491 @return 0 on success */
2492 static
2493 int
i_s_metrics_fill(THD * thd,TABLE * table_to_fill)2494 i_s_metrics_fill(
2495 /*=============*/
2496 THD* thd, /*!< in: thread */
2497 TABLE* table_to_fill) /*!< in/out: fill this table */
2498 {
2499 int count;
2500 Field** fields;
2501 double time_diff = 0;
2502 monitor_info_t* monitor_info;
2503 mon_type_t min_val;
2504 mon_type_t max_val;
2505
2506 DBUG_ENTER("i_s_metrics_fill");
2507 fields = table_to_fill->field;
2508
2509 for (count = 0; count < NUM_MONITOR; count++) {
2510 monitor_info = srv_mon_get_info((monitor_id_t) count);
2511
2512 /* A good place to sanity check the Monitor ID */
2513 ut_a(count == monitor_info->monitor_id);
2514
2515 /* If the item refers to a Module, nothing to fill,
2516 continue. */
2517 if ((monitor_info->monitor_type & MONITOR_MODULE)
2518 || (monitor_info->monitor_type & MONITOR_HIDDEN)) {
2519 continue;
2520 }
2521
2522 /* If this is an existing "status variable", and
2523 its corresponding counter is still on, we need
2524 to calculate the result from its corresponding
2525 counter. */
2526 if (monitor_info->monitor_type & MONITOR_EXISTING
2527 && MONITOR_IS_ON(count)) {
2528 srv_mon_process_existing_counter((monitor_id_t) count,
2529 MONITOR_GET_VALUE);
2530 }
2531
2532 /* Fill in counter's basic information */
2533 OK(field_store_string(fields[METRIC_NAME],
2534 monitor_info->monitor_name));
2535
2536 OK(field_store_string(fields[METRIC_SUBSYS],
2537 monitor_info->monitor_module));
2538
2539 OK(field_store_string(fields[METRIC_DESC],
2540 monitor_info->monitor_desc));
2541
2542 /* Fill in counter values */
2543 OK(fields[METRIC_VALUE_RESET]->store(
2544 MONITOR_VALUE(count), FALSE));
2545
2546 OK(fields[METRIC_VALUE_START]->store(
2547 MONITOR_VALUE_SINCE_START(count), FALSE));
2548
2549 /* If the max value is MAX_RESERVED, counter max
2550 value has not been updated. Set the column value
2551 to NULL. */
2552 if (MONITOR_MAX_VALUE(count) == MAX_RESERVED
2553 || MONITOR_MAX_MIN_NOT_INIT(count)) {
2554 fields[METRIC_MAX_VALUE_RESET]->set_null();
2555 } else {
2556 OK(fields[METRIC_MAX_VALUE_RESET]->store(
2557 MONITOR_MAX_VALUE(count), FALSE));
2558 fields[METRIC_MAX_VALUE_RESET]->set_notnull();
2559 }
2560
2561 /* If the min value is MAX_RESERVED, counter min
2562 value has not been updated. Set the column value
2563 to NULL. */
2564 if (MONITOR_MIN_VALUE(count) == MIN_RESERVED
2565 || MONITOR_MAX_MIN_NOT_INIT(count)) {
2566 fields[METRIC_MIN_VALUE_RESET]->set_null();
2567 } else {
2568 OK(fields[METRIC_MIN_VALUE_RESET]->store(
2569 MONITOR_MIN_VALUE(count), FALSE));
2570 fields[METRIC_MIN_VALUE_RESET]->set_notnull();
2571 }
2572
2573 /* Calculate the max value since counter started */
2574 max_val = srv_mon_calc_max_since_start((monitor_id_t) count);
2575
2576 if (max_val == MAX_RESERVED
2577 || MONITOR_MAX_MIN_NOT_INIT(count)) {
2578 fields[METRIC_MAX_VALUE_START]->set_null();
2579 } else {
2580 OK(fields[METRIC_MAX_VALUE_START]->store(
2581 max_val, FALSE));
2582 fields[METRIC_MAX_VALUE_START]->set_notnull();
2583 }
2584
2585 /* Calculate the min value since counter started */
2586 min_val = srv_mon_calc_min_since_start((monitor_id_t) count);
2587
2588 if (min_val == MIN_RESERVED
2589 || MONITOR_MAX_MIN_NOT_INIT(count)) {
2590 fields[METRIC_MIN_VALUE_START]->set_null();
2591 } else {
2592 OK(fields[METRIC_MIN_VALUE_START]->store(
2593 min_val, FALSE));
2594
2595 fields[METRIC_MIN_VALUE_START]->set_notnull();
2596 }
2597
2598 /* If monitor has been enabled (no matter it is disabled
2599 or not now), fill METRIC_START_TIME and METRIC_TIME_ELAPSED
2600 field */
2601 if (MONITOR_FIELD(count, mon_start_time)) {
2602 OK(field_store_time_t(fields[METRIC_START_TIME],
2603 (time_t)MONITOR_FIELD(count, mon_start_time)));
2604 fields[METRIC_START_TIME]->set_notnull();
2605
2606 /* If monitor is enabled, the TIME_ELAPSED is the
2607 time difference between current and time when monitor
2608 is enabled. Otherwise, it is the time difference
2609 between time when monitor is enabled and time
2610 when it is disabled */
2611 if (MONITOR_IS_ON(count)) {
2612 time_diff = difftime(time(NULL),
2613 MONITOR_FIELD(count, mon_start_time));
2614 } else {
2615 time_diff = difftime(
2616 MONITOR_FIELD(count, mon_stop_time),
2617 MONITOR_FIELD(count, mon_start_time));
2618 }
2619
2620 OK(fields[METRIC_TIME_ELAPSED]->store(
2621 time_diff));
2622 fields[METRIC_TIME_ELAPSED]->set_notnull();
2623 } else {
2624 fields[METRIC_START_TIME]->set_null();
2625 fields[METRIC_TIME_ELAPSED]->set_null();
2626 time_diff = 0;
2627 }
2628
2629 /* Unless MONITOR__NO_AVERAGE is marked, we will need
2630 to calculate the average value. If this is a monitor set
2631 owner marked by MONITOR_SET_OWNER, divide
2632 the value by another counter (number of calls) designated
2633 by monitor_info->monitor_related_id.
2634 Otherwise average the counter value by the time between the
2635 time that the counter is enabled and time it is disabled
2636 or time it is sampled. */
2637 if (!(monitor_info->monitor_type & MONITOR_NO_AVERAGE)
2638 && (monitor_info->monitor_type & MONITOR_SET_OWNER)
2639 && monitor_info->monitor_related_id) {
2640 mon_type_t value_start
2641 = MONITOR_VALUE_SINCE_START(
2642 monitor_info->monitor_related_id);
2643
2644 if (value_start) {
2645 OK(fields[METRIC_AVG_VALUE_START]->store(
2646 MONITOR_VALUE_SINCE_START(count)
2647 / value_start, FALSE));
2648
2649 fields[METRIC_AVG_VALUE_START]->set_notnull();
2650 } else {
2651 fields[METRIC_AVG_VALUE_START]->set_null();
2652 }
2653
2654 if (MONITOR_VALUE(monitor_info->monitor_related_id)) {
2655 OK(fields[METRIC_AVG_VALUE_RESET]->store(
2656 MONITOR_VALUE(count)
2657 / MONITOR_VALUE(
2658 monitor_info->monitor_related_id),
2659 FALSE));
2660 } else {
2661 fields[METRIC_AVG_VALUE_RESET]->set_null();
2662 }
2663 } else if (!(monitor_info->monitor_type & MONITOR_NO_AVERAGE)
2664 && !(monitor_info->monitor_type
2665 & MONITOR_DISPLAY_CURRENT)) {
2666 if (time_diff) {
2667 OK(fields[METRIC_AVG_VALUE_START]->store(
2668 (double) MONITOR_VALUE_SINCE_START(
2669 count) / time_diff));
2670 fields[METRIC_AVG_VALUE_START]->set_notnull();
2671 } else {
2672 fields[METRIC_AVG_VALUE_START]->set_null();
2673 }
2674
2675 if (MONITOR_FIELD(count, mon_reset_time)) {
2676 /* calculate the time difference since last
2677 reset */
2678 if (MONITOR_IS_ON(count)) {
2679 time_diff = difftime(
2680 time(NULL), MONITOR_FIELD(
2681 count, mon_reset_time));
2682 } else {
2683 time_diff = difftime(
2684 MONITOR_FIELD(count, mon_stop_time),
2685 MONITOR_FIELD(count, mon_reset_time));
2686 }
2687 } else {
2688 time_diff = 0;
2689 }
2690
2691 if (time_diff) {
2692 OK(fields[METRIC_AVG_VALUE_RESET]->store(
2693 static_cast<double>(
2694 MONITOR_VALUE(count) / time_diff)));
2695 fields[METRIC_AVG_VALUE_RESET]->set_notnull();
2696 } else {
2697 fields[METRIC_AVG_VALUE_RESET]->set_null();
2698 }
2699 } else {
2700 fields[METRIC_AVG_VALUE_START]->set_null();
2701 fields[METRIC_AVG_VALUE_RESET]->set_null();
2702 }
2703
2704
2705 if (MONITOR_IS_ON(count)) {
2706 /* If monitor is on, the stop time will set to NULL */
2707 fields[METRIC_STOP_TIME]->set_null();
2708
2709 /* Display latest Monitor Reset Time only if Monitor
2710 counter is on. */
2711 if (MONITOR_FIELD(count, mon_reset_time)) {
2712 OK(field_store_time_t(
2713 fields[METRIC_RESET_TIME],
2714 (time_t)MONITOR_FIELD(
2715 count, mon_reset_time)));
2716 fields[METRIC_RESET_TIME]->set_notnull();
2717 } else {
2718 fields[METRIC_RESET_TIME]->set_null();
2719 }
2720
2721 /* Display the monitor status as "enabled" */
2722 OK(field_store_string(fields[METRIC_STATUS],
2723 "enabled"));
2724 } else {
2725 if (MONITOR_FIELD(count, mon_stop_time)) {
2726 OK(field_store_time_t(fields[METRIC_STOP_TIME],
2727 (time_t)MONITOR_FIELD(count, mon_stop_time)));
2728 fields[METRIC_STOP_TIME]->set_notnull();
2729 } else {
2730 fields[METRIC_STOP_TIME]->set_null();
2731 }
2732
2733 fields[METRIC_RESET_TIME]->set_null();
2734
2735 OK(field_store_string(fields[METRIC_STATUS],
2736 "disabled"));
2737 }
2738
2739 if (monitor_info->monitor_type & MONITOR_DISPLAY_CURRENT) {
2740 OK(field_store_string(fields[METRIC_TYPE],
2741 "value"));
2742 } else if (monitor_info->monitor_type & MONITOR_EXISTING) {
2743 OK(field_store_string(fields[METRIC_TYPE],
2744 "status_counter"));
2745 } else if (monitor_info->monitor_type & MONITOR_SET_OWNER) {
2746 OK(field_store_string(fields[METRIC_TYPE],
2747 "set_owner"));
2748 } else if ( monitor_info->monitor_type & MONITOR_SET_MEMBER) {
2749 OK(field_store_string(fields[METRIC_TYPE],
2750 "set_member"));
2751 } else {
2752 OK(field_store_string(fields[METRIC_TYPE],
2753 "counter"));
2754 }
2755
2756 OK(schema_table_store_record(thd, table_to_fill));
2757 }
2758
2759 DBUG_RETURN(0);
2760 }
2761
2762 /*******************************************************************//**
2763 Function to fill information schema metrics tables.
2764 @return 0 on success */
2765 static
2766 int
i_s_metrics_fill_table(THD * thd,TABLE_LIST * tables,Item *)2767 i_s_metrics_fill_table(
2768 /*===================*/
2769 THD* thd, /*!< in: thread */
2770 TABLE_LIST* tables, /*!< in/out: tables to fill */
2771 Item* ) /*!< in: condition (not used) */
2772 {
2773 DBUG_ENTER("i_s_metrics_fill_table");
2774
2775 /* deny access to non-superusers */
2776 if (check_global_access(thd, PROCESS_ACL)) {
2777 DBUG_RETURN(0);
2778 }
2779
2780 i_s_metrics_fill(thd, tables->table);
2781
2782 DBUG_RETURN(0);
2783 }
2784 /*******************************************************************//**
2785 Bind the dynamic table INFORMATION_SCHEMA.innodb_metrics
2786 @return 0 on success */
2787 static
2788 int
innodb_metrics_init(void * p)2789 innodb_metrics_init(
2790 /*================*/
2791 void* p) /*!< in/out: table schema object */
2792 {
2793 ST_SCHEMA_TABLE* schema;
2794
2795 DBUG_ENTER("innodb_metrics_init");
2796
2797 schema = (ST_SCHEMA_TABLE*) p;
2798
2799 schema->fields_info = innodb_metrics_fields_info;
2800 schema->fill_table = i_s_metrics_fill_table;
2801
2802 DBUG_RETURN(0);
2803 }
2804
2805 UNIV_INTERN struct st_mysql_plugin i_s_innodb_metrics =
2806 {
2807 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
2808 /* int */
2809 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2810
2811 /* pointer to type-specific plugin descriptor */
2812 /* void* */
2813 STRUCT_FLD(info, &i_s_info),
2814
2815 /* plugin name */
2816 /* const char* */
2817 STRUCT_FLD(name, "INNODB_METRICS"),
2818
2819 /* plugin author (for SHOW PLUGINS) */
2820 /* const char* */
2821 STRUCT_FLD(author, plugin_author),
2822
2823 /* general descriptive text (for SHOW PLUGINS) */
2824 /* const char* */
2825 STRUCT_FLD(descr, "InnoDB Metrics Info"),
2826
2827 /* the plugin license (PLUGIN_LICENSE_XXX) */
2828 /* int */
2829 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2830
2831 /* the function to invoke when plugin is loaded */
2832 /* int (*)(void*); */
2833 STRUCT_FLD(init, innodb_metrics_init),
2834
2835 /* the function to invoke when plugin is unloaded */
2836 /* int (*)(void*); */
2837 STRUCT_FLD(deinit, i_s_common_deinit),
2838
2839 /* plugin version (for SHOW PLUGINS) */
2840 /* unsigned int */
2841 STRUCT_FLD(version, INNODB_VERSION_SHORT),
2842
2843 /* struct st_mysql_show_var* */
2844 STRUCT_FLD(status_vars, NULL),
2845
2846 /* struct st_mysql_sys_var** */
2847 STRUCT_FLD(system_vars, NULL),
2848
2849 /* reserved for dependency checking */
2850 /* void* */
2851 STRUCT_FLD(__reserved1, NULL),
2852
2853 /* Plugin flags */
2854 /* unsigned long */
2855 STRUCT_FLD(flags, 0UL),
2856 };
2857 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_ft_default_stopword */
2858 static ST_FIELD_INFO i_s_stopword_fields_info[] =
2859 {
2860 #define STOPWORD_VALUE 0
2861 {STRUCT_FLD(field_name, "value"),
2862 STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
2863 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
2864 STRUCT_FLD(value, 0),
2865 STRUCT_FLD(field_flags, 0),
2866 STRUCT_FLD(old_name, ""),
2867 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2868
2869 END_OF_ST_FIELD_INFO
2870 };
2871
2872 /*******************************************************************//**
2873 Fill the dynamic table information_schema.innodb_ft_default_stopword.
2874 @return 0 on success, 1 on failure */
2875 static
2876 int
i_s_stopword_fill(THD * thd,TABLE_LIST * tables,Item *)2877 i_s_stopword_fill(
2878 /*==============*/
2879 THD* thd, /*!< in: thread */
2880 TABLE_LIST* tables, /*!< in/out: tables to fill */
2881 Item* ) /*!< in: condition (not used) */
2882 {
2883 Field** fields;
2884 ulint i = 0;
2885 TABLE* table = (TABLE*) tables->table;
2886
2887 DBUG_ENTER("i_s_stopword_fill");
2888
2889 fields = table->field;
2890
2891 /* Fill with server default stopword list in array
2892 fts_default_stopword */
2893 while (fts_default_stopword[i]) {
2894 OK(field_store_string(fields[STOPWORD_VALUE],
2895 fts_default_stopword[i]));
2896
2897 OK(schema_table_store_record(thd, table));
2898 i++;
2899 }
2900
2901 DBUG_RETURN(0);
2902 }
2903
2904 /*******************************************************************//**
2905 Bind the dynamic table information_schema.innodb_ft_default_stopword.
2906 @return 0 on success */
2907 static
2908 int
i_s_stopword_init(void * p)2909 i_s_stopword_init(
2910 /*==============*/
2911 void* p) /*!< in/out: table schema object */
2912 {
2913 DBUG_ENTER("i_s_stopword_init");
2914 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2915
2916 schema->fields_info = i_s_stopword_fields_info;
2917 schema->fill_table = i_s_stopword_fill;
2918
2919 DBUG_RETURN(0);
2920 }
2921
2922 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_default_stopword =
2923 {
2924 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
2925 /* int */
2926 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2927
2928 /* pointer to type-specific plugin descriptor */
2929 /* void* */
2930 STRUCT_FLD(info, &i_s_info),
2931
2932 /* plugin name */
2933 /* const char* */
2934 STRUCT_FLD(name, "INNODB_FT_DEFAULT_STOPWORD"),
2935
2936 /* plugin author (for SHOW PLUGINS) */
2937 /* const char* */
2938 STRUCT_FLD(author, plugin_author),
2939
2940 /* general descriptive text (for SHOW PLUGINS) */
2941 /* const char* */
2942 STRUCT_FLD(descr, "Default stopword list for InnDB Full Text Search"),
2943
2944 /* the plugin license (PLUGIN_LICENSE_XXX) */
2945 /* int */
2946 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2947
2948 /* the function to invoke when plugin is loaded */
2949 /* int (*)(void*); */
2950 STRUCT_FLD(init, i_s_stopword_init),
2951
2952 /* the function to invoke when plugin is unloaded */
2953 /* int (*)(void*); */
2954 STRUCT_FLD(deinit, i_s_common_deinit),
2955
2956 /* plugin version (for SHOW PLUGINS) */
2957 /* unsigned int */
2958 STRUCT_FLD(version, INNODB_VERSION_SHORT),
2959
2960 /* struct st_mysql_show_var* */
2961 STRUCT_FLD(status_vars, NULL),
2962
2963 /* struct st_mysql_sys_var** */
2964 STRUCT_FLD(system_vars, NULL),
2965
2966 /* reserved for dependency checking */
2967 /* void* */
2968 STRUCT_FLD(__reserved1, NULL),
2969
2970 /* Plugin flags */
2971 /* unsigned long */
2972 STRUCT_FLD(flags, 0UL),
2973 };
2974
2975 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
2976 INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED */
2977 static ST_FIELD_INFO i_s_fts_doc_fields_info[] =
2978 {
2979 #define I_S_FTS_DOC_ID 0
2980 {STRUCT_FLD(field_name, "DOC_ID"),
2981 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
2982 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
2983 STRUCT_FLD(value, 0),
2984 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
2985 STRUCT_FLD(old_name, ""),
2986 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
2987
2988 END_OF_ST_FIELD_INFO
2989 };
2990
2991 /*******************************************************************//**
2992 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED or
2993 INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
2994 @return 0 on success, 1 on failure */
2995 static
2996 int
i_s_fts_deleted_generic_fill(THD * thd,TABLE_LIST * tables,ibool being_deleted)2997 i_s_fts_deleted_generic_fill(
2998 /*=========================*/
2999 THD* thd, /*!< in: thread */
3000 TABLE_LIST* tables, /*!< in/out: tables to fill */
3001 ibool being_deleted) /*!< in: BEING_DELTED table */
3002 {
3003 Field** fields;
3004 TABLE* table = (TABLE*) tables->table;
3005 trx_t* trx;
3006 fts_table_t fts_table;
3007 fts_doc_ids_t* deleted;
3008 dict_table_t* user_table;
3009
3010 DBUG_ENTER("i_s_fts_deleted_generic_fill");
3011
3012 /* deny access to non-superusers */
3013 if (check_global_access(thd, PROCESS_ACL)) {
3014 DBUG_RETURN(0);
3015 }
3016
3017 mysql_mutex_lock(&LOCK_global_system_variables);
3018
3019 if (!fts_internal_tbl_name) {
3020 mysql_mutex_unlock(&LOCK_global_system_variables);
3021 DBUG_RETURN(0);
3022 }
3023
3024 std::string fts_table_name(fts_internal_tbl_name);
3025 mysql_mutex_unlock(&LOCK_global_system_variables);
3026
3027 if(!fts_table_name.c_str()) {
3028 DBUG_RETURN(0);
3029 }
3030
3031 /* Prevent DDL to drop fts aux tables. */
3032 rw_lock_s_lock(&dict_operation_lock);
3033
3034 user_table = dict_table_open_on_name(
3035 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3036
3037 if (!user_table) {
3038 rw_lock_s_unlock(&dict_operation_lock);
3039
3040 DBUG_RETURN(0);
3041 } else if (!dict_table_has_fts_index(user_table)) {
3042 dict_table_close(user_table, FALSE, FALSE);
3043
3044 rw_lock_s_unlock(&dict_operation_lock);
3045
3046 DBUG_RETURN(0);
3047 }
3048
3049 deleted = fts_doc_ids_create();
3050
3051 trx = trx_allocate_for_background();
3052 trx->op_info = "Select for FTS DELETE TABLE";
3053
3054 FTS_INIT_FTS_TABLE(&fts_table,
3055 (being_deleted) ? "BEING_DELETED" : "DELETED",
3056 FTS_COMMON_TABLE, user_table);
3057
3058 fts_table_fetch_doc_ids(trx, &fts_table, deleted);
3059
3060 fields = table->field;
3061
3062 for (ulint j = 0; j < ib_vector_size(deleted->doc_ids); ++j) {
3063 doc_id_t doc_id;
3064
3065 doc_id = *(doc_id_t*) ib_vector_get_const(deleted->doc_ids, j);
3066
3067 OK(fields[I_S_FTS_DOC_ID]->store((longlong) doc_id, true));
3068
3069 OK(schema_table_store_record(thd, table));
3070 }
3071
3072 trx_free_for_background(trx);
3073
3074 fts_doc_ids_free(deleted);
3075
3076 dict_table_close(user_table, FALSE, FALSE);
3077
3078 rw_lock_s_unlock(&dict_operation_lock);
3079
3080 DBUG_RETURN(0);
3081 }
3082
3083 /*******************************************************************//**
3084 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
3085 @return 0 on success, 1 on failure */
3086 static
3087 int
i_s_fts_deleted_fill(THD * thd,TABLE_LIST * tables,Item *)3088 i_s_fts_deleted_fill(
3089 /*=================*/
3090 THD* thd, /*!< in: thread */
3091 TABLE_LIST* tables, /*!< in/out: tables to fill */
3092 Item* ) /*!< in: condition (ignored) */
3093 {
3094 DBUG_ENTER("i_s_fts_deleted_fill");
3095
3096 DBUG_RETURN(i_s_fts_deleted_generic_fill(thd, tables, FALSE));
3097 }
3098
3099 /*******************************************************************//**
3100 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
3101 @return 0 on success */
3102 static
3103 int
i_s_fts_deleted_init(void * p)3104 i_s_fts_deleted_init(
3105 /*=================*/
3106 void* p) /*!< in/out: table schema object */
3107 {
3108 DBUG_ENTER("i_s_fts_deleted_init");
3109 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3110
3111 schema->fields_info = i_s_fts_doc_fields_info;
3112 schema->fill_table = i_s_fts_deleted_fill;
3113
3114 DBUG_RETURN(0);
3115 }
3116
3117 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_deleted =
3118 {
3119 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3120 /* int */
3121 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3122
3123 /* pointer to type-specific plugin descriptor */
3124 /* void* */
3125 STRUCT_FLD(info, &i_s_info),
3126
3127 /* plugin name */
3128 /* const char* */
3129 STRUCT_FLD(name, "INNODB_FT_DELETED"),
3130
3131 /* plugin author (for SHOW PLUGINS) */
3132 /* const char* */
3133 STRUCT_FLD(author, plugin_author),
3134
3135 /* general descriptive text (for SHOW PLUGINS) */
3136 /* const char* */
3137 STRUCT_FLD(descr, "INNODB AUXILIARY FTS DELETED TABLE"),
3138
3139 /* the plugin license (PLUGIN_LICENSE_XXX) */
3140 /* int */
3141 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3142
3143 /* the function to invoke when plugin is loaded */
3144 /* int (*)(void*); */
3145 STRUCT_FLD(init, i_s_fts_deleted_init),
3146
3147 /* the function to invoke when plugin is unloaded */
3148 /* int (*)(void*); */
3149 STRUCT_FLD(deinit, i_s_common_deinit),
3150
3151 /* plugin version (for SHOW PLUGINS) */
3152 /* unsigned int */
3153 STRUCT_FLD(version, INNODB_VERSION_SHORT),
3154
3155 /* struct st_mysql_show_var* */
3156 STRUCT_FLD(status_vars, NULL),
3157
3158 /* struct st_mysql_sys_var** */
3159 STRUCT_FLD(system_vars, NULL),
3160
3161 /* reserved for dependency checking */
3162 /* void* */
3163 STRUCT_FLD(__reserved1, NULL),
3164
3165 /* Plugin flags */
3166 /* unsigned long */
3167 STRUCT_FLD(flags, 0UL),
3168 };
3169
3170 /*******************************************************************//**
3171 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
3172 @return 0 on success, 1 on failure */
3173 static
3174 int
i_s_fts_being_deleted_fill(THD * thd,TABLE_LIST * tables,Item *)3175 i_s_fts_being_deleted_fill(
3176 /*=======================*/
3177 THD* thd, /*!< in: thread */
3178 TABLE_LIST* tables, /*!< in/out: tables to fill */
3179 Item* ) /*!< in: condition (ignored) */
3180 {
3181 DBUG_ENTER("i_s_fts_being_deleted_fill");
3182
3183 DBUG_RETURN(i_s_fts_deleted_generic_fill(thd, tables, TRUE));
3184 }
3185
3186 /*******************************************************************//**
3187 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
3188 @return 0 on success */
3189 static
3190 int
i_s_fts_being_deleted_init(void * p)3191 i_s_fts_being_deleted_init(
3192 /*=======================*/
3193 void* p) /*!< in/out: table schema object */
3194 {
3195 DBUG_ENTER("i_s_fts_deleted_init");
3196 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3197
3198 schema->fields_info = i_s_fts_doc_fields_info;
3199 schema->fill_table = i_s_fts_being_deleted_fill;
3200
3201 DBUG_RETURN(0);
3202 }
3203
3204 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_being_deleted =
3205 {
3206 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3207 /* int */
3208 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3209
3210 /* pointer to type-specific plugin descriptor */
3211 /* void* */
3212 STRUCT_FLD(info, &i_s_info),
3213
3214 /* plugin name */
3215 /* const char* */
3216 STRUCT_FLD(name, "INNODB_FT_BEING_DELETED"),
3217
3218 /* plugin author (for SHOW PLUGINS) */
3219 /* const char* */
3220 STRUCT_FLD(author, plugin_author),
3221
3222 /* general descriptive text (for SHOW PLUGINS) */
3223 /* const char* */
3224 STRUCT_FLD(descr, "INNODB AUXILIARY FTS BEING DELETED TABLE"),
3225
3226 /* the plugin license (PLUGIN_LICENSE_XXX) */
3227 /* int */
3228 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3229
3230 /* the function to invoke when plugin is loaded */
3231 /* int (*)(void*); */
3232 STRUCT_FLD(init, i_s_fts_being_deleted_init),
3233
3234 /* the function to invoke when plugin is unloaded */
3235 /* int (*)(void*); */
3236 STRUCT_FLD(deinit, i_s_common_deinit),
3237
3238 /* plugin version (for SHOW PLUGINS) */
3239 /* unsigned int */
3240 STRUCT_FLD(version, INNODB_VERSION_SHORT),
3241
3242 /* struct st_mysql_show_var* */
3243 STRUCT_FLD(status_vars, NULL),
3244
3245 /* struct st_mysql_sys_var** */
3246 STRUCT_FLD(system_vars, NULL),
3247
3248 /* reserved for dependency checking */
3249 /* void* */
3250 STRUCT_FLD(__reserved1, NULL),
3251
3252 /* Plugin flags */
3253 /* unsigned long */
3254 STRUCT_FLD(flags, 0UL),
3255 };
3256
3257 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED and
3258 INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE */
3259 static ST_FIELD_INFO i_s_fts_index_fields_info[] =
3260 {
3261 #define I_S_FTS_WORD 0
3262 {STRUCT_FLD(field_name, "WORD"),
3263 STRUCT_FLD(field_length, FTS_MAX_WORD_LEN + 1),
3264 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
3265 STRUCT_FLD(value, 0),
3266 STRUCT_FLD(field_flags, 0),
3267 STRUCT_FLD(old_name, ""),
3268 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3269
3270 #define I_S_FTS_FIRST_DOC_ID 1
3271 {STRUCT_FLD(field_name, "FIRST_DOC_ID"),
3272 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
3273 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
3274 STRUCT_FLD(value, 0),
3275 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
3276 STRUCT_FLD(old_name, ""),
3277 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3278
3279 #define I_S_FTS_LAST_DOC_ID 2
3280 {STRUCT_FLD(field_name, "LAST_DOC_ID"),
3281 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
3282 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
3283 STRUCT_FLD(value, 0),
3284 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
3285 STRUCT_FLD(old_name, ""),
3286 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3287
3288 #define I_S_FTS_DOC_COUNT 3
3289 {STRUCT_FLD(field_name, "DOC_COUNT"),
3290 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
3291 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
3292 STRUCT_FLD(value, 0),
3293 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
3294 STRUCT_FLD(old_name, ""),
3295 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3296
3297 #define I_S_FTS_ILIST_DOC_ID 4
3298 {STRUCT_FLD(field_name, "DOC_ID"),
3299 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
3300 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
3301 STRUCT_FLD(value, 0),
3302 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
3303 STRUCT_FLD(old_name, ""),
3304 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3305
3306 #define I_S_FTS_ILIST_DOC_POS 5
3307 {STRUCT_FLD(field_name, "POSITION"),
3308 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
3309 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
3310 STRUCT_FLD(value, 0),
3311 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
3312 STRUCT_FLD(old_name, ""),
3313 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
3314
3315 END_OF_ST_FIELD_INFO
3316 };
3317
3318 /*******************************************************************//**
3319 Go through the Doc Node and its ilist, fill the dynamic table
3320 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED for one FTS index on the table.
3321 @return 0 on success, 1 on failure */
3322 static
3323 int
i_s_fts_index_cache_fill_one_index(fts_index_cache_t * index_cache,THD * thd,TABLE_LIST * tables)3324 i_s_fts_index_cache_fill_one_index(
3325 /*===============================*/
3326 fts_index_cache_t* index_cache, /*!< in: FTS index cache */
3327 THD* thd, /*!< in: thread */
3328 TABLE_LIST* tables) /*!< in/out: tables to fill */
3329 {
3330 TABLE* table = (TABLE*) tables->table;
3331 Field** fields;
3332 CHARSET_INFO* index_charset;
3333 const ib_rbt_node_t* rbt_node;
3334 fts_string_t conv_str;
3335 uint dummy_errors;
3336 char* word_str;
3337
3338 DBUG_ENTER("i_s_fts_index_cache_fill_one_index");
3339
3340 fields = table->field;
3341
3342 index_charset = index_cache->charset;
3343 conv_str.f_len = system_charset_info->mbmaxlen
3344 * FTS_MAX_WORD_LEN_IN_CHAR;
3345 conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len));
3346 conv_str.f_n_char = 0;
3347
3348 /* Go through each word in the index cache */
3349 for (rbt_node = rbt_first(index_cache->words);
3350 rbt_node;
3351 rbt_node = rbt_next(index_cache->words, rbt_node)) {
3352 fts_tokenizer_word_t* word;
3353
3354 word = rbt_value(fts_tokenizer_word_t, rbt_node);
3355
3356 /* Convert word from index charset to system_charset_info */
3357 if (index_charset->cset != system_charset_info->cset) {
3358 conv_str.f_n_char = my_convert(
3359 reinterpret_cast<char*>(conv_str.f_str),
3360 static_cast<uint32>(conv_str.f_len),
3361 system_charset_info,
3362 reinterpret_cast<char*>(word->text.f_str),
3363 static_cast<uint32>(word->text.f_len),
3364 index_charset, &dummy_errors);
3365 ut_ad(conv_str.f_n_char <= conv_str.f_len);
3366 conv_str.f_str[conv_str.f_n_char] = 0;
3367 word_str = reinterpret_cast<char*>(conv_str.f_str);
3368 } else {
3369 word_str = reinterpret_cast<char*>(word->text.f_str);
3370 }
3371
3372 /* Decrypt the ilist, and display Dod ID and word position */
3373 for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3374 fts_node_t* node;
3375 byte* ptr;
3376 ulint decoded = 0;
3377 doc_id_t doc_id = 0;
3378
3379 node = static_cast<fts_node_t*> (ib_vector_get(
3380 word->nodes, i));
3381
3382 ptr = node->ilist;
3383
3384 while (decoded < node->ilist_size) {
3385 ulint pos = fts_decode_vlc(&ptr);
3386
3387 doc_id += pos;
3388
3389 /* Get position info */
3390 while (*ptr) {
3391 pos = fts_decode_vlc(&ptr);
3392
3393 OK(field_store_string(
3394 fields[I_S_FTS_WORD],
3395 word_str));
3396
3397 OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3398 (longlong) node->first_doc_id,
3399 true));
3400
3401 OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3402 (longlong) node->last_doc_id,
3403 true));
3404
3405 OK(fields[I_S_FTS_DOC_COUNT]->store(
3406 static_cast<double>(node->doc_count)));
3407
3408 OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3409 (longlong) doc_id, true));
3410
3411 OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3412 static_cast<double>(pos)));
3413
3414 OK(schema_table_store_record(
3415 thd, table));
3416 }
3417
3418 ++ptr;
3419
3420 decoded = ptr - (byte*) node->ilist;
3421 }
3422 }
3423 }
3424
3425 ut_free(conv_str.f_str);
3426
3427 DBUG_RETURN(0);
3428 }
3429 /*******************************************************************//**
3430 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED
3431 @return 0 on success, 1 on failure */
3432 static
3433 int
i_s_fts_index_cache_fill(THD * thd,TABLE_LIST * tables,Item *)3434 i_s_fts_index_cache_fill(
3435 /*=====================*/
3436 THD* thd, /*!< in: thread */
3437 TABLE_LIST* tables, /*!< in/out: tables to fill */
3438 Item* ) /*!< in: condition (ignored) */
3439 {
3440 dict_table_t* user_table;
3441 fts_cache_t* cache;
3442
3443 DBUG_ENTER("i_s_fts_index_cache_fill");
3444
3445 /* deny access to non-superusers */
3446 if (check_global_access(thd, PROCESS_ACL)) {
3447 DBUG_RETURN(0);
3448 }
3449
3450 mysql_mutex_lock(&LOCK_global_system_variables);
3451
3452 if (!fts_internal_tbl_name) {
3453 mysql_mutex_unlock(&LOCK_global_system_variables);
3454 DBUG_RETURN(0);
3455 }
3456
3457 std::string fts_table_name(fts_internal_tbl_name);
3458 mysql_mutex_unlock(&LOCK_global_system_variables);
3459
3460 if(!fts_table_name.c_str()) {
3461 DBUG_RETURN(0);
3462 }
3463
3464 user_table = dict_table_open_on_name(
3465 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3466
3467 if (!user_table) {
3468 DBUG_RETURN(0);
3469 }
3470
3471 if (user_table->fts == NULL || user_table->fts->cache == NULL) {
3472 dict_table_close(user_table, FALSE, FALSE);
3473
3474 DBUG_RETURN(0);
3475 }
3476
3477 cache = user_table->fts->cache;
3478
3479 ut_a(cache);
3480
3481 /* Check if cache is being synced.
3482 Note: we wait till cache is being synced. */
3483 while (cache->sync->in_progress) {
3484 os_event_wait(cache->sync->event);
3485 }
3486 for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) {
3487 fts_index_cache_t* index_cache;
3488
3489 index_cache = static_cast<fts_index_cache_t*> (
3490 ib_vector_get(cache->indexes, i));
3491
3492 i_s_fts_index_cache_fill_one_index(index_cache, thd, tables);
3493 }
3494
3495 dict_table_close(user_table, FALSE, FALSE);
3496
3497 DBUG_RETURN(0);
3498 }
3499
3500 /*******************************************************************//**
3501 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
3502 @return 0 on success */
3503 static
3504 int
i_s_fts_index_cache_init(void * p)3505 i_s_fts_index_cache_init(
3506 /*=====================*/
3507 void* p) /*!< in/out: table schema object */
3508 {
3509 DBUG_ENTER("i_s_fts_index_cache_init");
3510 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3511
3512 schema->fields_info = i_s_fts_index_fields_info;
3513 schema->fill_table = i_s_fts_index_cache_fill;
3514
3515 DBUG_RETURN(0);
3516 }
3517
3518 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_cache =
3519 {
3520 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3521 /* int */
3522 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3523
3524 /* pointer to type-specific plugin descriptor */
3525 /* void* */
3526 STRUCT_FLD(info, &i_s_info),
3527
3528 /* plugin name */
3529 /* const char* */
3530 STRUCT_FLD(name, "INNODB_FT_INDEX_CACHE"),
3531
3532 /* plugin author (for SHOW PLUGINS) */
3533 /* const char* */
3534 STRUCT_FLD(author, plugin_author),
3535
3536 /* general descriptive text (for SHOW PLUGINS) */
3537 /* const char* */
3538 STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX CACHED"),
3539
3540 /* the plugin license (PLUGIN_LICENSE_XXX) */
3541 /* int */
3542 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3543
3544 /* the function to invoke when plugin is loaded */
3545 /* int (*)(void*); */
3546 STRUCT_FLD(init, i_s_fts_index_cache_init),
3547
3548 /* the function to invoke when plugin is unloaded */
3549 /* int (*)(void*); */
3550 STRUCT_FLD(deinit, i_s_common_deinit),
3551
3552 /* plugin version (for SHOW PLUGINS) */
3553 /* unsigned int */
3554 STRUCT_FLD(version, INNODB_VERSION_SHORT),
3555
3556 /* struct st_mysql_show_var* */
3557 STRUCT_FLD(status_vars, NULL),
3558
3559 /* struct st_mysql_sys_var** */
3560 STRUCT_FLD(system_vars, NULL),
3561
3562 /* reserved for dependency checking */
3563 /* void* */
3564 STRUCT_FLD(__reserved1, NULL),
3565
3566 /* Plugin flags */
3567 /* unsigned long */
3568 STRUCT_FLD(flags, 0UL),
3569 };
3570
3571 /*******************************************************************//**
3572 Go through a FTS index auxiliary table, fetch its rows and fill
3573 FTS word cache structure.
3574 @return DB_SUCCESS on success, otherwise error code */
3575 static
3576 dberr_t
i_s_fts_index_table_fill_selected(dict_index_t * index,ib_vector_t * words,ulint selected,fts_string_t * word)3577 i_s_fts_index_table_fill_selected(
3578 /*==============================*/
3579 dict_index_t* index, /*!< in: FTS index */
3580 ib_vector_t* words, /*!< in/out: vector to hold
3581 fetched words */
3582 ulint selected, /*!< in: selected FTS index */
3583 fts_string_t* word) /*!< in: word to select */
3584 {
3585 pars_info_t* info;
3586 fts_table_t fts_table;
3587 trx_t* trx;
3588 que_t* graph;
3589 dberr_t error;
3590 fts_fetch_t fetch;
3591
3592 info = pars_info_create();
3593
3594 fetch.read_arg = words;
3595 fetch.read_record = fts_optimize_index_fetch_node;
3596 fetch.total_memory = 0;
3597
3598 DBUG_EXECUTE_IF("fts_instrument_result_cache_limit",
3599 fts_result_cache_limit = 8192;
3600 );
3601
3602 trx = trx_allocate_for_background();
3603
3604 trx->op_info = "fetching FTS index nodes";
3605
3606 pars_info_bind_function(info, "my_func", fetch.read_record, &fetch);
3607 pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
3608
3609 FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
3610 FTS_INDEX_TABLE, index);
3611
3612 graph = fts_parse_sql(
3613 &fts_table, info,
3614 "DECLARE FUNCTION my_func;\n"
3615 "DECLARE CURSOR c IS"
3616 " SELECT word, doc_count, first_doc_id, last_doc_id, "
3617 "ilist\n"
3618 " FROM %s WHERE word >= :word;\n"
3619 "BEGIN\n"
3620 "\n"
3621 "OPEN c;\n"
3622 "WHILE 1 = 1 LOOP\n"
3623 " FETCH c INTO my_func();\n"
3624 " IF c % NOTFOUND THEN\n"
3625 " EXIT;\n"
3626 " END IF;\n"
3627 "END LOOP;\n"
3628 "CLOSE c;");
3629
3630 for(;;) {
3631 error = fts_eval_sql(trx, graph);
3632
3633 if (error == DB_SUCCESS) {
3634 fts_sql_commit(trx);
3635
3636 break;
3637 } else {
3638 fts_sql_rollback(trx);
3639
3640 ut_print_timestamp(stderr);
3641
3642 if (error == DB_LOCK_WAIT_TIMEOUT) {
3643 fprintf(stderr, " InnoDB: Warning: "
3644 "lock wait timeout reading "
3645 "FTS index. Retrying!\n");
3646
3647 trx->error_state = DB_SUCCESS;
3648 } else {
3649 fprintf(stderr, " InnoDB: Error: %d "
3650 "while reading FTS index.\n", error);
3651 break;
3652 }
3653 }
3654 }
3655
3656 mutex_enter(&dict_sys->mutex);
3657 que_graph_free(graph);
3658 mutex_exit(&dict_sys->mutex);
3659
3660 trx_free_for_background(trx);
3661
3662 if (fetch.total_memory >= fts_result_cache_limit) {
3663 error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
3664 }
3665
3666 return(error);
3667 }
3668
3669 /*******************************************************************//**
3670 Free words. */
3671 static
3672 void
i_s_fts_index_table_free_one_fetch(ib_vector_t * words)3673 i_s_fts_index_table_free_one_fetch(
3674 /*===============================*/
3675 ib_vector_t* words) /*!< in: words fetched */
3676 {
3677 for (ulint i = 0; i < ib_vector_size(words); i++) {
3678 fts_word_t* word;
3679
3680 word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3681
3682 for (ulint j = 0; j < ib_vector_size(word->nodes); j++) {
3683 fts_node_t* node;
3684
3685 node = static_cast<fts_node_t*> (ib_vector_get(
3686 word->nodes, j));
3687 ut_free(node->ilist);
3688 }
3689
3690 fts_word_free(word);
3691 }
3692
3693 ib_vector_reset(words);
3694 }
3695
3696 /*******************************************************************//**
3697 Go through words, fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3698 @return 0 on success, 1 on failure */
3699 static
3700 int
i_s_fts_index_table_fill_one_fetch(CHARSET_INFO * index_charset,THD * thd,TABLE_LIST * tables,ib_vector_t * words,fts_string_t * conv_str,bool has_more)3701 i_s_fts_index_table_fill_one_fetch(
3702 /*===============================*/
3703 CHARSET_INFO* index_charset, /*!< in: FTS index charset */
3704 THD* thd, /*!< in: thread */
3705 TABLE_LIST* tables, /*!< in/out: tables to fill */
3706 ib_vector_t* words, /*!< in: words fetched */
3707 fts_string_t* conv_str, /*!< in: string for conversion*/
3708 bool has_more) /*!< in: has more to fetch */
3709 {
3710 TABLE* table = (TABLE*) tables->table;
3711 Field** fields;
3712 uint dummy_errors;
3713 char* word_str;
3714 ulint words_size;
3715 int ret = 0;
3716
3717 DBUG_ENTER("i_s_fts_index_table_fill_one_fetch");
3718
3719 fields = table->field;
3720
3721 words_size = ib_vector_size(words);
3722 if (has_more) {
3723 /* the last word is not fetched completely. */
3724 ut_ad(words_size > 1);
3725 words_size -= 1;
3726 }
3727
3728 /* Go through each word in the index cache */
3729 for (ulint i = 0; i < words_size; i++) {
3730 fts_word_t* word;
3731
3732 word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3733
3734 word->text.f_str[word->text.f_len] = 0;
3735
3736 /* Convert word from index charset to system_charset_info */
3737 if (index_charset->cset != system_charset_info->cset) {
3738 conv_str->f_n_char = my_convert(
3739 reinterpret_cast<char*>(conv_str->f_str),
3740 static_cast<uint32>(conv_str->f_len),
3741 system_charset_info,
3742 reinterpret_cast<char*>(word->text.f_str),
3743 static_cast<uint32>(word->text.f_len),
3744 index_charset, &dummy_errors);
3745 ut_ad(conv_str->f_n_char <= conv_str->f_len);
3746 conv_str->f_str[conv_str->f_n_char] = 0;
3747 word_str = reinterpret_cast<char*>(conv_str->f_str);
3748 } else {
3749 word_str = reinterpret_cast<char*>(word->text.f_str);
3750 }
3751
3752 /* Decrypt the ilist, and display Dod ID and word position */
3753 for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3754 fts_node_t* node;
3755 byte* ptr;
3756 ulint decoded = 0;
3757 doc_id_t doc_id = 0;
3758
3759 node = static_cast<fts_node_t*> (ib_vector_get(
3760 word->nodes, i));
3761
3762 ptr = node->ilist;
3763
3764 while (decoded < node->ilist_size) {
3765 ulint pos = fts_decode_vlc(&ptr);
3766
3767 doc_id += pos;
3768
3769 /* Get position info */
3770 while (*ptr) {
3771 pos = fts_decode_vlc(&ptr);
3772
3773 OK(field_store_string(
3774 fields[I_S_FTS_WORD],
3775 word_str));
3776
3777 OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3778 (longlong) node->first_doc_id,
3779 true));
3780
3781 OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3782 (longlong) node->last_doc_id,
3783 true));
3784
3785 OK(fields[I_S_FTS_DOC_COUNT]->store(
3786 static_cast<double>(node->doc_count)));
3787
3788 OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3789 (longlong) doc_id, true));
3790
3791 OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3792 static_cast<double>(pos)));
3793
3794 OK(schema_table_store_record(
3795 thd, table));
3796 }
3797
3798 ++ptr;
3799
3800 decoded = ptr - (byte*) node->ilist;
3801 }
3802 }
3803 }
3804
3805 i_s_fts_index_table_free_one_fetch(words);
3806
3807 DBUG_RETURN(ret);
3808 }
3809
3810 /*******************************************************************//**
3811 Go through a FTS index and its auxiliary tables, fetch rows in each table
3812 and fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3813 @return 0 on success, 1 on failure */
3814 static
3815 int
i_s_fts_index_table_fill_one_index(dict_index_t * index,THD * thd,TABLE_LIST * tables)3816 i_s_fts_index_table_fill_one_index(
3817 /*===============================*/
3818 dict_index_t* index, /*!< in: FTS index */
3819 THD* thd, /*!< in: thread */
3820 TABLE_LIST* tables) /*!< in/out: tables to fill */
3821 {
3822 ib_vector_t* words;
3823 mem_heap_t* heap;
3824 fts_string_t word;
3825 CHARSET_INFO* index_charset;
3826 fts_string_t conv_str;
3827 dberr_t error;
3828 int ret = 0;
3829
3830 DBUG_ENTER("i_s_fts_index_table_fill_one_index");
3831 DBUG_ASSERT(!dict_index_is_online_ddl(index));
3832
3833 heap = mem_heap_create(1024);
3834
3835 words = ib_vector_create(ib_heap_allocator_create(heap),
3836 sizeof(fts_word_t), 256);
3837
3838 word.f_str = NULL;
3839 word.f_len = 0;
3840 word.f_n_char = 0;
3841
3842 index_charset = fts_index_get_charset(index);
3843 conv_str.f_len = system_charset_info->mbmaxlen
3844 * FTS_MAX_WORD_LEN_IN_CHAR;
3845 conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len));
3846 conv_str.f_n_char = 0;
3847
3848 /* Iterate through each auxiliary table as described in
3849 fts_index_selector */
3850 for (ulint selected = 0; fts_index_selector[selected].value;
3851 selected++) {
3852 bool has_more = false;
3853
3854 do {
3855 /* Fetch from index */
3856 error = i_s_fts_index_table_fill_selected(
3857 index, words, selected, &word);
3858
3859 if (error == DB_SUCCESS) {
3860 has_more = false;
3861 } else if (error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT) {
3862 has_more = true;
3863 } else {
3864 i_s_fts_index_table_free_one_fetch(words);
3865 ret = 1;
3866 goto func_exit;
3867 }
3868
3869 if (has_more) {
3870 fts_word_t* last_word;
3871
3872 /* Prepare start point for next fetch */
3873 last_word = static_cast<fts_word_t*>(ib_vector_last(words));
3874 ut_ad(last_word != NULL);
3875 fts_utf8_string_dup(&word, &last_word->text, heap);
3876 }
3877
3878 /* Fill into tables */
3879 ret = i_s_fts_index_table_fill_one_fetch(
3880 index_charset, thd, tables, words, &conv_str, has_more);
3881
3882 if (ret != 0) {
3883 i_s_fts_index_table_free_one_fetch(words);
3884 goto func_exit;
3885 }
3886 } while (has_more);
3887 }
3888
3889 func_exit:
3890 ut_free(conv_str.f_str);
3891 mem_heap_free(heap);
3892
3893 DBUG_RETURN(ret);
3894 }
3895 /*******************************************************************//**
3896 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3897 @return 0 on success, 1 on failure */
3898 static
3899 int
i_s_fts_index_table_fill(THD * thd,TABLE_LIST * tables,Item *)3900 i_s_fts_index_table_fill(
3901 /*=====================*/
3902 THD* thd, /*!< in: thread */
3903 TABLE_LIST* tables, /*!< in/out: tables to fill */
3904 Item* ) /*!< in: condition (ignored) */
3905 {
3906 dict_table_t* user_table;
3907 dict_index_t* index;
3908
3909 DBUG_ENTER("i_s_fts_index_table_fill");
3910
3911 /* deny access to non-superusers */
3912 if (check_global_access(thd, PROCESS_ACL)) {
3913 DBUG_RETURN(0);
3914 }
3915
3916 mysql_mutex_lock(&LOCK_global_system_variables);
3917
3918 if (!fts_internal_tbl_name) {
3919 mysql_mutex_unlock(&LOCK_global_system_variables);
3920 DBUG_RETURN(0);
3921 }
3922
3923 std::string fts_table_name(fts_internal_tbl_name);
3924 mysql_mutex_unlock(&LOCK_global_system_variables);
3925
3926 if(!fts_table_name.c_str()) {
3927 DBUG_RETURN(0);
3928 }
3929
3930 /* Prevent DDL to drop fts aux tables. */
3931 rw_lock_s_lock(&dict_operation_lock);
3932
3933 user_table = dict_table_open_on_name(
3934 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3935
3936 if (!user_table) {
3937 rw_lock_s_unlock(&dict_operation_lock);
3938
3939 DBUG_RETURN(0);
3940 }
3941
3942 for (index = dict_table_get_first_index(user_table);
3943 index; index = dict_table_get_next_index(index)) {
3944 if (index->type & DICT_FTS) {
3945 i_s_fts_index_table_fill_one_index(index, thd, tables);
3946 }
3947 }
3948
3949 dict_table_close(user_table, FALSE, FALSE);
3950
3951 rw_lock_s_unlock(&dict_operation_lock);
3952
3953 DBUG_RETURN(0);
3954 }
3955
3956 /*******************************************************************//**
3957 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3958 @return 0 on success */
3959 static
3960 int
i_s_fts_index_table_init(void * p)3961 i_s_fts_index_table_init(
3962 /*=====================*/
3963 void* p) /*!< in/out: table schema object */
3964 {
3965 DBUG_ENTER("i_s_fts_index_table_init");
3966 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3967
3968 schema->fields_info = i_s_fts_index_fields_info;
3969 schema->fill_table = i_s_fts_index_table_fill;
3970
3971 DBUG_RETURN(0);
3972 }
3973
3974 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_index_table =
3975 {
3976 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3977 /* int */
3978 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3979
3980 /* pointer to type-specific plugin descriptor */
3981 /* void* */
3982 STRUCT_FLD(info, &i_s_info),
3983
3984 /* plugin name */
3985 /* const char* */
3986 STRUCT_FLD(name, "INNODB_FT_INDEX_TABLE"),
3987
3988 /* plugin author (for SHOW PLUGINS) */
3989 /* const char* */
3990 STRUCT_FLD(author, plugin_author),
3991
3992 /* general descriptive text (for SHOW PLUGINS) */
3993 /* const char* */
3994 STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX TABLE"),
3995
3996 /* the plugin license (PLUGIN_LICENSE_XXX) */
3997 /* int */
3998 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3999
4000 /* the function to invoke when plugin is loaded */
4001 /* int (*)(void*); */
4002 STRUCT_FLD(init, i_s_fts_index_table_init),
4003
4004 /* the function to invoke when plugin is unloaded */
4005 /* int (*)(void*); */
4006 STRUCT_FLD(deinit, i_s_common_deinit),
4007
4008 /* plugin version (for SHOW PLUGINS) */
4009 /* unsigned int */
4010 STRUCT_FLD(version, INNODB_VERSION_SHORT),
4011
4012 /* struct st_mysql_show_var* */
4013 STRUCT_FLD(status_vars, NULL),
4014
4015 /* struct st_mysql_sys_var** */
4016 STRUCT_FLD(system_vars, NULL),
4017
4018 /* reserved for dependency checking */
4019 /* void* */
4020 STRUCT_FLD(__reserved1, NULL),
4021
4022 /* Plugin flags */
4023 /* unsigned long */
4024 STRUCT_FLD(flags, 0UL),
4025 };
4026
4027 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */
4028 static ST_FIELD_INFO i_s_fts_config_fields_info[] =
4029 {
4030 #define FTS_CONFIG_KEY 0
4031 {STRUCT_FLD(field_name, "KEY"),
4032 STRUCT_FLD(field_length, NAME_LEN + 1),
4033 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4034 STRUCT_FLD(value, 0),
4035 STRUCT_FLD(field_flags, 0),
4036 STRUCT_FLD(old_name, ""),
4037 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4038
4039 #define FTS_CONFIG_VALUE 1
4040 {STRUCT_FLD(field_name, "VALUE"),
4041 STRUCT_FLD(field_length, NAME_LEN + 1),
4042 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4043 STRUCT_FLD(value, 0),
4044 STRUCT_FLD(field_flags, 0),
4045 STRUCT_FLD(old_name, ""),
4046 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4047
4048 END_OF_ST_FIELD_INFO
4049 };
4050
4051 static const char* fts_config_key[] = {
4052 FTS_OPTIMIZE_LIMIT_IN_SECS,
4053 FTS_SYNCED_DOC_ID,
4054 FTS_STOPWORD_TABLE_NAME,
4055 FTS_USE_STOPWORD,
4056 NULL
4057 };
4058
4059 /*******************************************************************//**
4060 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4061 @return 0 on success, 1 on failure */
4062 static
4063 int
i_s_fts_config_fill(THD * thd,TABLE_LIST * tables,Item *)4064 i_s_fts_config_fill(
4065 /*================*/
4066 THD* thd, /*!< in: thread */
4067 TABLE_LIST* tables, /*!< in/out: tables to fill */
4068 Item* ) /*!< in: condition (ignored) */
4069 {
4070 Field** fields;
4071 TABLE* table = (TABLE*) tables->table;
4072 trx_t* trx;
4073 fts_table_t fts_table;
4074 dict_table_t* user_table;
4075 ulint i = 0;
4076 dict_index_t* index = NULL;
4077 unsigned char str[FTS_MAX_CONFIG_VALUE_LEN + 1];
4078
4079 DBUG_ENTER("i_s_fts_config_fill");
4080
4081 /* deny access to non-superusers */
4082 if (check_global_access(thd, PROCESS_ACL)) {
4083 DBUG_RETURN(0);
4084 }
4085
4086 mysql_mutex_lock(&LOCK_global_system_variables);
4087
4088 if (!fts_internal_tbl_name) {
4089 mysql_mutex_unlock(&LOCK_global_system_variables);
4090 DBUG_RETURN(0);
4091 }
4092
4093 std::string fts_table_name(fts_internal_tbl_name);
4094 mysql_mutex_unlock(&LOCK_global_system_variables);
4095
4096 if(!fts_table_name.c_str()) {
4097 DBUG_RETURN(0);
4098 }
4099
4100 DEBUG_SYNC_C("i_s_fts_config_fille_check");
4101
4102 fields = table->field;
4103
4104 /* Prevent DDL to drop fts aux tables. */
4105 rw_lock_s_lock(&dict_operation_lock);
4106
4107 user_table = dict_table_open_on_name(
4108 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
4109
4110 if (!user_table) {
4111 rw_lock_s_unlock(&dict_operation_lock);
4112
4113 DBUG_RETURN(0);
4114 } else if (!dict_table_has_fts_index(user_table)) {
4115 dict_table_close(user_table, FALSE, FALSE);
4116
4117 rw_lock_s_unlock(&dict_operation_lock);
4118
4119 DBUG_RETURN(0);
4120 }
4121
4122 trx = trx_allocate_for_background();
4123 trx->op_info = "Select for FTS CONFIG TABLE";
4124
4125 FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table);
4126
4127 if (!ib_vector_is_empty(user_table->fts->indexes)) {
4128 index = (dict_index_t*) ib_vector_getp_const(
4129 user_table->fts->indexes, 0);
4130 DBUG_ASSERT(!dict_index_is_online_ddl(index));
4131 }
4132
4133 while (fts_config_key[i]) {
4134 fts_string_t value;
4135 char* key_name;
4136 ulint allocated = FALSE;
4137
4138 value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
4139
4140 value.f_str = str;
4141
4142 if (index
4143 && strcmp(fts_config_key[i], FTS_TOTAL_WORD_COUNT) == 0) {
4144 key_name = fts_config_create_index_param_name(
4145 fts_config_key[i], index);
4146 allocated = TRUE;
4147 } else {
4148 key_name = (char*) fts_config_key[i];
4149 }
4150
4151 fts_config_get_value(trx, &fts_table, key_name, &value);
4152
4153 if (allocated) {
4154 ut_free(key_name);
4155 }
4156
4157 OK(field_store_string(
4158 fields[FTS_CONFIG_KEY], fts_config_key[i]));
4159
4160 OK(field_store_string(
4161 fields[FTS_CONFIG_VALUE], (const char*) value.f_str));
4162
4163 OK(schema_table_store_record(thd, table));
4164
4165 i++;
4166 }
4167
4168 fts_sql_commit(trx);
4169
4170 trx_free_for_background(trx);
4171
4172 dict_table_close(user_table, FALSE, FALSE);
4173
4174 rw_lock_s_unlock(&dict_operation_lock);
4175
4176 DBUG_RETURN(0);
4177 }
4178
4179 /*******************************************************************//**
4180 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4181 @return 0 on success */
4182 static
4183 int
i_s_fts_config_init(void * p)4184 i_s_fts_config_init(
4185 /*=================*/
4186 void* p) /*!< in/out: table schema object */
4187 {
4188 DBUG_ENTER("i_s_fts_config_init");
4189 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
4190
4191 schema->fields_info = i_s_fts_config_fields_info;
4192 schema->fill_table = i_s_fts_config_fill;
4193
4194 DBUG_RETURN(0);
4195 }
4196
4197 UNIV_INTERN struct st_mysql_plugin i_s_innodb_ft_config =
4198 {
4199 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
4200 /* int */
4201 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4202
4203 /* pointer to type-specific plugin descriptor */
4204 /* void* */
4205 STRUCT_FLD(info, &i_s_info),
4206
4207 /* plugin name */
4208 /* const char* */
4209 STRUCT_FLD(name, "INNODB_FT_CONFIG"),
4210
4211 /* plugin author (for SHOW PLUGINS) */
4212 /* const char* */
4213 STRUCT_FLD(author, plugin_author),
4214
4215 /* general descriptive text (for SHOW PLUGINS) */
4216 /* const char* */
4217 STRUCT_FLD(descr, "INNODB AUXILIARY FTS CONFIG TABLE"),
4218
4219 /* the plugin license (PLUGIN_LICENSE_XXX) */
4220 /* int */
4221 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4222
4223 /* the function to invoke when plugin is loaded */
4224 /* int (*)(void*); */
4225 STRUCT_FLD(init, i_s_fts_config_init),
4226
4227 /* the function to invoke when plugin is unloaded */
4228 /* int (*)(void*); */
4229 STRUCT_FLD(deinit, i_s_common_deinit),
4230
4231 /* plugin version (for SHOW PLUGINS) */
4232 /* unsigned int */
4233 STRUCT_FLD(version, INNODB_VERSION_SHORT),
4234
4235 /* struct st_mysql_show_var* */
4236 STRUCT_FLD(status_vars, NULL),
4237
4238 /* struct st_mysql_sys_var** */
4239 STRUCT_FLD(system_vars, NULL),
4240
4241 /* reserved for dependency checking */
4242 /* void* */
4243 STRUCT_FLD(__reserved1, NULL),
4244
4245 /* Plugin flags */
4246 /* unsigned long */
4247 STRUCT_FLD(flags, 0UL),
4248 };
4249
4250 /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
4251 static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] =
4252 {
4253 #define IDX_BUF_STATS_POOL_ID 0
4254 {STRUCT_FLD(field_name, "POOL_ID"),
4255 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4256 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4257 STRUCT_FLD(value, 0),
4258 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4259 STRUCT_FLD(old_name, ""),
4260 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4261
4262 #define IDX_BUF_STATS_POOL_SIZE 1
4263 {STRUCT_FLD(field_name, "POOL_SIZE"),
4264 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4265 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4266 STRUCT_FLD(value, 0),
4267 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4268 STRUCT_FLD(old_name, ""),
4269 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4270
4271 #define IDX_BUF_STATS_FREE_BUFFERS 2
4272 {STRUCT_FLD(field_name, "FREE_BUFFERS"),
4273 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4274 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4275 STRUCT_FLD(value, 0),
4276 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4277 STRUCT_FLD(old_name, ""),
4278 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4279
4280 #define IDX_BUF_STATS_LRU_LEN 3
4281 {STRUCT_FLD(field_name, "DATABASE_PAGES"),
4282 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4283 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4284 STRUCT_FLD(value, 0),
4285 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4286 STRUCT_FLD(old_name, ""),
4287 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4288
4289 #define IDX_BUF_STATS_OLD_LRU_LEN 4
4290 {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"),
4291 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4292 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4293 STRUCT_FLD(value, 0),
4294 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4295 STRUCT_FLD(old_name, ""),
4296 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4297
4298 #define IDX_BUF_STATS_FLUSH_LIST_LEN 5
4299 {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"),
4300 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4301 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4302 STRUCT_FLD(value, 0),
4303 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4304 STRUCT_FLD(old_name, ""),
4305 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4306
4307 #define IDX_BUF_STATS_PENDING_ZIP 6
4308 {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"),
4309 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4310 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4311 STRUCT_FLD(value, 0),
4312 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4313 STRUCT_FLD(old_name, ""),
4314 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4315
4316 #define IDX_BUF_STATS_PENDING_READ 7
4317 {STRUCT_FLD(field_name, "PENDING_READS"),
4318 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4319 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4320 STRUCT_FLD(value, 0),
4321 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4322 STRUCT_FLD(old_name, ""),
4323 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4324
4325 #define IDX_BUF_STATS_FLUSH_LRU 8
4326 {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"),
4327 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4328 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4329 STRUCT_FLD(value, 0),
4330 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4331 STRUCT_FLD(old_name, ""),
4332 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4333
4334 #define IDX_BUF_STATS_FLUSH_LIST 9
4335 {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"),
4336 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4337 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4338 STRUCT_FLD(value, 0),
4339 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4340 STRUCT_FLD(old_name, ""),
4341 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4342
4343 #define IDX_BUF_STATS_PAGE_YOUNG 10
4344 {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"),
4345 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4346 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4347 STRUCT_FLD(value, 0),
4348 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4349 STRUCT_FLD(old_name, ""),
4350 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4351
4352 #define IDX_BUF_STATS_PAGE_NOT_YOUNG 11
4353 {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"),
4354 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4355 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4356 STRUCT_FLD(value, 0),
4357 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4358 STRUCT_FLD(old_name, ""),
4359 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4360
4361 #define IDX_BUF_STATS_PAGE_YOUNG_RATE 12
4362 {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"),
4363 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4364 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4365 STRUCT_FLD(value, 0),
4366 STRUCT_FLD(field_flags, 0),
4367 STRUCT_FLD(old_name, ""),
4368 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4369
4370 #define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
4371 {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"),
4372 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4373 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4374 STRUCT_FLD(value, 0),
4375 STRUCT_FLD(field_flags, 0),
4376 STRUCT_FLD(old_name, ""),
4377 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4378
4379 #define IDX_BUF_STATS_PAGE_READ 14
4380 {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"),
4381 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4382 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4383 STRUCT_FLD(value, 0),
4384 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4385 STRUCT_FLD(old_name, ""),
4386 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4387
4388 #define IDX_BUF_STATS_PAGE_CREATED 15
4389 {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"),
4390 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4391 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4392 STRUCT_FLD(value, 0),
4393 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4394 STRUCT_FLD(old_name, ""),
4395 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4396
4397 #define IDX_BUF_STATS_PAGE_WRITTEN 16
4398 {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"),
4399 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4400 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4401 STRUCT_FLD(value, 0),
4402 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4403 STRUCT_FLD(old_name, ""),
4404 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4405
4406 #define IDX_BUF_STATS_PAGE_READ_RATE 17
4407 {STRUCT_FLD(field_name, "PAGES_READ_RATE"),
4408 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4409 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4410 STRUCT_FLD(value, 0),
4411 STRUCT_FLD(field_flags, 0),
4412 STRUCT_FLD(old_name, ""),
4413 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4414
4415 #define IDX_BUF_STATS_PAGE_CREATE_RATE 18
4416 {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"),
4417 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4418 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4419 STRUCT_FLD(value, 0),
4420 STRUCT_FLD(field_flags, 0),
4421 STRUCT_FLD(old_name, ""),
4422 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4423
4424 #define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19
4425 {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"),
4426 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4427 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4428 STRUCT_FLD(value, 0),
4429 STRUCT_FLD(field_flags, 0),
4430 STRUCT_FLD(old_name, ""),
4431 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4432
4433 #define IDX_BUF_STATS_GET 20
4434 {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"),
4435 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4436 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4437 STRUCT_FLD(value, 0),
4438 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4439 STRUCT_FLD(old_name, ""),
4440 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4441
4442 #define IDX_BUF_STATS_HIT_RATE 21
4443 {STRUCT_FLD(field_name, "HIT_RATE"),
4444 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4445 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4446 STRUCT_FLD(value, 0),
4447 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4448 STRUCT_FLD(old_name, ""),
4449 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4450
4451 #define IDX_BUF_STATS_MADE_YOUNG_PCT 22
4452 {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"),
4453 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4454 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4455 STRUCT_FLD(value, 0),
4456 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4457 STRUCT_FLD(old_name, ""),
4458 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4459
4460 #define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
4461 {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
4462 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4463 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4464 STRUCT_FLD(value, 0),
4465 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4466 STRUCT_FLD(old_name, ""),
4467 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4468
4469 #define IDX_BUF_STATS_READ_AHREAD 24
4470 {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"),
4471 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4472 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4473 STRUCT_FLD(value, 0),
4474 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4475 STRUCT_FLD(old_name, ""),
4476 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4477
4478 #define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
4479 {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"),
4480 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4481 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4482 STRUCT_FLD(value, 0),
4483 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4484 STRUCT_FLD(old_name, ""),
4485 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4486
4487 #define IDX_BUF_STATS_READ_AHEAD_RATE 26
4488 {STRUCT_FLD(field_name, "READ_AHEAD_RATE"),
4489 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4490 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4491 STRUCT_FLD(value, 0),
4492 STRUCT_FLD(field_flags, 0),
4493 STRUCT_FLD(old_name, ""),
4494 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4495
4496 #define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
4497 {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"),
4498 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4499 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4500 STRUCT_FLD(value, 0),
4501 STRUCT_FLD(field_flags, 0),
4502 STRUCT_FLD(old_name, ""),
4503 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4504
4505 #define IDX_BUF_STATS_LRU_IO_SUM 28
4506 {STRUCT_FLD(field_name, "LRU_IO_TOTAL"),
4507 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4508 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4509 STRUCT_FLD(value, 0),
4510 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4511 STRUCT_FLD(old_name, ""),
4512 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4513
4514 #define IDX_BUF_STATS_LRU_IO_CUR 29
4515 {STRUCT_FLD(field_name, "LRU_IO_CURRENT"),
4516 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4517 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4518 STRUCT_FLD(value, 0),
4519 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4520 STRUCT_FLD(old_name, ""),
4521 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4522
4523 #define IDX_BUF_STATS_UNZIP_SUM 30
4524 {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"),
4525 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4526 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4527 STRUCT_FLD(value, 0),
4528 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4529 STRUCT_FLD(old_name, ""),
4530 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4531
4532 #define IDX_BUF_STATS_UNZIP_CUR 31
4533 {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"),
4534 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4535 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4536 STRUCT_FLD(value, 0),
4537 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4538 STRUCT_FLD(old_name, ""),
4539 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4540
4541 END_OF_ST_FIELD_INFO
4542 };
4543
4544 /*******************************************************************//**
4545 Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
4546 buffer pool
4547 @return 0 on success, 1 on failure */
4548 static
4549 int
i_s_innodb_stats_fill(THD * thd,TABLE_LIST * tables,const buf_pool_info_t * info)4550 i_s_innodb_stats_fill(
4551 /*==================*/
4552 THD* thd, /*!< in: thread */
4553 TABLE_LIST* tables, /*!< in/out: tables to fill */
4554 const buf_pool_info_t* info) /*!< in: buffer pool
4555 information */
4556 {
4557 TABLE* table;
4558 Field** fields;
4559
4560 DBUG_ENTER("i_s_innodb_stats_fill");
4561
4562 table = tables->table;
4563
4564 fields = table->field;
4565
4566 OK(fields[IDX_BUF_STATS_POOL_ID]->store(
4567 static_cast<double>(info->pool_unique_id)));
4568
4569 OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(
4570 static_cast<double>(info->pool_size)));
4571
4572 OK(fields[IDX_BUF_STATS_LRU_LEN]->store(
4573 static_cast<double>(info->lru_len)));
4574
4575 OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(
4576 static_cast<double>(info->old_lru_len)));
4577
4578 OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(
4579 static_cast<double>(info->free_list_len)));
4580
4581 OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
4582 static_cast<double>(info->flush_list_len)));
4583
4584 OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(
4585 static_cast<double>(info->n_pend_unzip)));
4586
4587 OK(fields[IDX_BUF_STATS_PENDING_READ]->store(
4588 static_cast<double>(info->n_pend_reads)));
4589
4590 OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(
4591 static_cast<double>(info->n_pending_flush_lru)));
4592
4593 OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(
4594 static_cast<double>(info->n_pending_flush_list)));
4595
4596 OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(
4597 static_cast<double>(info->n_pages_made_young)));
4598
4599 OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
4600 static_cast<double>(info->n_pages_not_made_young)));
4601
4602 OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
4603 info->page_made_young_rate));
4604
4605 OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
4606 info->page_not_made_young_rate));
4607
4608 OK(fields[IDX_BUF_STATS_PAGE_READ]->store(
4609 static_cast<double>(info->n_pages_read)));
4610
4611 OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(
4612 static_cast<double>(info->n_pages_created)));
4613
4614 OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(
4615 static_cast<double>(info->n_pages_written)));
4616
4617 OK(fields[IDX_BUF_STATS_GET]->store(
4618 static_cast<double>(info->n_page_gets)));
4619
4620 OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(
4621 info->pages_read_rate));
4622
4623 OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(
4624 info->pages_created_rate));
4625
4626 OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(
4627 info->pages_written_rate));
4628
4629 if (info->n_page_get_delta) {
4630 OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
4631 static_cast<double>(
4632 1000 - (1000 * info->page_read_delta
4633 / info->n_page_get_delta))));
4634
4635 OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
4636 static_cast<double>(
4637 1000 * info->young_making_delta
4638 / info->n_page_get_delta)));
4639
4640 OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
4641 static_cast<double>(
4642 1000 * info->not_young_making_delta
4643 / info->n_page_get_delta)));
4644 } else {
4645 OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
4646 OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
4647 OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
4648 }
4649
4650 OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(
4651 static_cast<double>(info->n_ra_pages_read)));
4652
4653 OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
4654 static_cast<double>(info->n_ra_pages_evicted)));
4655
4656 OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
4657 info->pages_readahead_rate));
4658
4659 OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
4660 info->pages_evicted_rate));
4661
4662 OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(
4663 static_cast<double>(info->io_sum)));
4664
4665 OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(
4666 static_cast<double>(info->io_cur)));
4667
4668 OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(
4669 static_cast<double>(info->unzip_sum)));
4670
4671 OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store(
4672 static_cast<double>(info->unzip_cur)));
4673
4674 DBUG_RETURN(schema_table_store_record(thd, table));
4675 }
4676
4677 /*******************************************************************//**
4678 This is the function that loops through each buffer pool and fetch buffer
4679 pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS
4680 @return 0 on success, 1 on failure */
4681 static
4682 int
i_s_innodb_buffer_stats_fill_table(THD * thd,TABLE_LIST * tables,Item *)4683 i_s_innodb_buffer_stats_fill_table(
4684 /*===============================*/
4685 THD* thd, /*!< in: thread */
4686 TABLE_LIST* tables, /*!< in/out: tables to fill */
4687 Item* ) /*!< in: condition (ignored) */
4688 {
4689 int status = 0;
4690 buf_pool_info_t* pool_info;
4691
4692 DBUG_ENTER("i_s_innodb_buffer_fill_general");
4693 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
4694
4695 /* Only allow the PROCESS privilege holder to access the stats */
4696 if (check_global_access(thd, PROCESS_ACL)) {
4697 DBUG_RETURN(0);
4698 }
4699
4700 pool_info = (buf_pool_info_t*) mem_zalloc(
4701 srv_buf_pool_instances * sizeof *pool_info);
4702
4703 /* Walk through each buffer pool */
4704 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
4705 buf_pool_t* buf_pool;
4706
4707 buf_pool = buf_pool_from_array(i);
4708
4709 /* Fetch individual buffer pool info */
4710 buf_stats_get_pool_info(buf_pool, i, pool_info);
4711
4712 status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
4713
4714 /* If something goes wrong, break and return */
4715 if (status) {
4716 break;
4717 }
4718 }
4719
4720 mem_free(pool_info);
4721
4722 DBUG_RETURN(status);
4723 }
4724
4725 /*******************************************************************//**
4726 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
4727 @return 0 on success, 1 on failure */
4728 static
4729 int
i_s_innodb_buffer_pool_stats_init(void * p)4730 i_s_innodb_buffer_pool_stats_init(
4731 /*==============================*/
4732 void* p) /*!< in/out: table schema object */
4733 {
4734 ST_SCHEMA_TABLE* schema;
4735
4736 DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
4737
4738 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
4739
4740 schema->fields_info = i_s_innodb_buffer_stats_fields_info;
4741 schema->fill_table = i_s_innodb_buffer_stats_fill_table;
4742
4743 DBUG_RETURN(0);
4744 }
4745
4746 UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats =
4747 {
4748 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
4749 /* int */
4750 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4751
4752 /* pointer to type-specific plugin descriptor */
4753 /* void* */
4754 STRUCT_FLD(info, &i_s_info),
4755
4756 /* plugin name */
4757 /* const char* */
4758 STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
4759
4760 /* plugin author (for SHOW PLUGINS) */
4761 /* const char* */
4762 STRUCT_FLD(author, plugin_author),
4763
4764 /* general descriptive text (for SHOW PLUGINS) */
4765 /* const char* */
4766 STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
4767
4768 /* the plugin license (PLUGIN_LICENSE_XXX) */
4769 /* int */
4770 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4771
4772 /* the function to invoke when plugin is loaded */
4773 /* int (*)(void*); */
4774 STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
4775
4776 /* the function to invoke when plugin is unloaded */
4777 /* int (*)(void*); */
4778 STRUCT_FLD(deinit, i_s_common_deinit),
4779
4780 /* plugin version (for SHOW PLUGINS) */
4781 /* unsigned int */
4782 STRUCT_FLD(version, INNODB_VERSION_SHORT),
4783
4784 /* struct st_mysql_show_var* */
4785 STRUCT_FLD(status_vars, NULL),
4786
4787 /* struct st_mysql_sys_var** */
4788 STRUCT_FLD(system_vars, NULL),
4789
4790 /* reserved for dependency checking */
4791 /* void* */
4792 STRUCT_FLD(__reserved1, NULL),
4793
4794 /* Plugin flags */
4795 /* unsigned long */
4796 STRUCT_FLD(flags, 0UL),
4797 };
4798
4799 /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
4800 static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] =
4801 {
4802 #define IDX_BUFFER_POOL_ID 0
4803 {STRUCT_FLD(field_name, "POOL_ID"),
4804 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4805 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4806 STRUCT_FLD(value, 0),
4807 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4808 STRUCT_FLD(old_name, ""),
4809 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4810
4811 #define IDX_BUFFER_BLOCK_ID 1
4812 {STRUCT_FLD(field_name, "BLOCK_ID"),
4813 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4814 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4815 STRUCT_FLD(value, 0),
4816 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4817 STRUCT_FLD(old_name, ""),
4818 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4819
4820 #define IDX_BUFFER_PAGE_SPACE 2
4821 {STRUCT_FLD(field_name, "SPACE"),
4822 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4823 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4824 STRUCT_FLD(value, 0),
4825 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4826 STRUCT_FLD(old_name, ""),
4827 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4828
4829 #define IDX_BUFFER_PAGE_NUM 3
4830 {STRUCT_FLD(field_name, "PAGE_NUMBER"),
4831 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4832 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4833 STRUCT_FLD(value, 0),
4834 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4835 STRUCT_FLD(old_name, ""),
4836 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4837
4838 #define IDX_BUFFER_PAGE_TYPE 4
4839 {STRUCT_FLD(field_name, "PAGE_TYPE"),
4840 STRUCT_FLD(field_length, 64),
4841 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4842 STRUCT_FLD(value, 0),
4843 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4844 STRUCT_FLD(old_name, ""),
4845 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4846
4847 #define IDX_BUFFER_PAGE_FLUSH_TYPE 5
4848 {STRUCT_FLD(field_name, "FLUSH_TYPE"),
4849 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4850 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4851 STRUCT_FLD(value, 0),
4852 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4853 STRUCT_FLD(old_name, ""),
4854 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4855
4856 #define IDX_BUFFER_PAGE_FIX_COUNT 6
4857 {STRUCT_FLD(field_name, "FIX_COUNT"),
4858 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4859 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4860 STRUCT_FLD(value, 0),
4861 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4862 STRUCT_FLD(old_name, ""),
4863 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4864
4865 #define IDX_BUFFER_PAGE_HASHED 7
4866 {STRUCT_FLD(field_name, "IS_HASHED"),
4867 STRUCT_FLD(field_length, 3),
4868 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4869 STRUCT_FLD(value, 0),
4870 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4871 STRUCT_FLD(old_name, ""),
4872 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4873
4874 #define IDX_BUFFER_PAGE_NEWEST_MOD 8
4875 {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
4876 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4877 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4878 STRUCT_FLD(value, 0),
4879 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4880 STRUCT_FLD(old_name, ""),
4881 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4882
4883 #define IDX_BUFFER_PAGE_OLDEST_MOD 9
4884 {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
4885 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4886 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4887 STRUCT_FLD(value, 0),
4888 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4889 STRUCT_FLD(old_name, ""),
4890 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4891
4892 #define IDX_BUFFER_PAGE_ACCESS_TIME 10
4893 {STRUCT_FLD(field_name, "ACCESS_TIME"),
4894 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4895 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4896 STRUCT_FLD(value, 0),
4897 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4898 STRUCT_FLD(old_name, ""),
4899 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4900
4901 #define IDX_BUFFER_PAGE_TABLE_NAME 11
4902 {STRUCT_FLD(field_name, "TABLE_NAME"),
4903 STRUCT_FLD(field_length, 1024),
4904 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4905 STRUCT_FLD(value, 0),
4906 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4907 STRUCT_FLD(old_name, ""),
4908 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4909
4910 #define IDX_BUFFER_PAGE_INDEX_NAME 12
4911 {STRUCT_FLD(field_name, "INDEX_NAME"),
4912 STRUCT_FLD(field_length, 1024),
4913 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4914 STRUCT_FLD(value, 0),
4915 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4916 STRUCT_FLD(old_name, ""),
4917 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4918
4919 #define IDX_BUFFER_PAGE_NUM_RECS 13
4920 {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
4921 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4922 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4923 STRUCT_FLD(value, 0),
4924 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4925 STRUCT_FLD(old_name, ""),
4926 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4927
4928 #define IDX_BUFFER_PAGE_DATA_SIZE 14
4929 {STRUCT_FLD(field_name, "DATA_SIZE"),
4930 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4931 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4932 STRUCT_FLD(value, 0),
4933 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4934 STRUCT_FLD(old_name, ""),
4935 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4936
4937 #define IDX_BUFFER_PAGE_ZIP_SIZE 15
4938 {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
4939 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4940 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4941 STRUCT_FLD(value, 0),
4942 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4943 STRUCT_FLD(old_name, ""),
4944 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4945
4946 #define IDX_BUFFER_PAGE_STATE 16
4947 {STRUCT_FLD(field_name, "PAGE_STATE"),
4948 STRUCT_FLD(field_length, 64),
4949 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4950 STRUCT_FLD(value, 0),
4951 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4952 STRUCT_FLD(old_name, ""),
4953 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4954
4955 #define IDX_BUFFER_PAGE_IO_FIX 17
4956 {STRUCT_FLD(field_name, "IO_FIX"),
4957 STRUCT_FLD(field_length, 64),
4958 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4959 STRUCT_FLD(value, 0),
4960 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4961 STRUCT_FLD(old_name, ""),
4962 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4963
4964 #define IDX_BUFFER_PAGE_IS_OLD 18
4965 {STRUCT_FLD(field_name, "IS_OLD"),
4966 STRUCT_FLD(field_length, 3),
4967 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4968 STRUCT_FLD(value, 0),
4969 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4970 STRUCT_FLD(old_name, ""),
4971 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4972
4973 #define IDX_BUFFER_PAGE_FREE_CLOCK 19
4974 {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
4975 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4976 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4977 STRUCT_FLD(value, 0),
4978 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4979 STRUCT_FLD(old_name, ""),
4980 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4981
4982 END_OF_ST_FIELD_INFO
4983 };
4984
4985 /*******************************************************************//**
4986 Fill Information Schema table INNODB_BUFFER_PAGE with information
4987 cached in the buf_page_info_t array
4988 @return 0 on success, 1 on failure */
4989 static
4990 int
i_s_innodb_buffer_page_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)4991 i_s_innodb_buffer_page_fill(
4992 /*========================*/
4993 THD* thd, /*!< in: thread */
4994 TABLE_LIST* tables, /*!< in/out: tables to fill */
4995 const buf_page_info_t* info_array, /*!< in: array cached page
4996 info */
4997 ulint num_page) /*!< in: number of page info
4998 cached */
4999 {
5000 TABLE* table;
5001 Field** fields;
5002
5003 DBUG_ENTER("i_s_innodb_buffer_page_fill");
5004
5005 table = tables->table;
5006
5007 fields = table->field;
5008
5009 /* Iterate through the cached array and fill the I_S table rows */
5010 for (ulint i = 0; i < num_page; i++) {
5011 const buf_page_info_t* page_info;
5012 char table_name[MAX_FULL_NAME_LEN + 1];
5013 const char* table_name_end = NULL;
5014 const char* state_str;
5015 enum buf_page_state state;
5016
5017 page_info = info_array + i;
5018
5019 state_str = NULL;
5020
5021 OK(fields[IDX_BUFFER_POOL_ID]->store(
5022 static_cast<double>(page_info->pool_id)));
5023
5024 OK(fields[IDX_BUFFER_BLOCK_ID]->store(
5025 static_cast<double>(page_info->block_id)));
5026
5027 OK(fields[IDX_BUFFER_PAGE_SPACE]->store(
5028 static_cast<double>(page_info->space_id)));
5029
5030 OK(fields[IDX_BUFFER_PAGE_NUM]->store(
5031 static_cast<double>(page_info->page_num)));
5032
5033 OK(field_store_string(
5034 fields[IDX_BUFFER_PAGE_TYPE],
5035 i_s_page_type[page_info->page_type].type_str));
5036
5037 OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
5038 page_info->flush_type));
5039
5040 OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
5041 page_info->fix_count));
5042
5043 if (page_info->hashed) {
5044 OK(field_store_string(
5045 fields[IDX_BUFFER_PAGE_HASHED], "YES"));
5046 } else {
5047 OK(field_store_string(
5048 fields[IDX_BUFFER_PAGE_HASHED], "NO"));
5049 }
5050
5051 OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
5052 (longlong) page_info->newest_mod, true));
5053
5054 OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
5055 (longlong) page_info->oldest_mod, true));
5056
5057 OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
5058 page_info->access_time));
5059
5060 fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null();
5061
5062 fields[IDX_BUFFER_PAGE_INDEX_NAME]->set_null();
5063
5064 /* If this is an index page, fetch the index name
5065 and table name */
5066 if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5067 const dict_index_t* index;
5068
5069 mutex_enter(&dict_sys->mutex);
5070 index = dict_index_get_if_in_cache_low(
5071 page_info->index_id);
5072
5073 if (index) {
5074
5075 table_name_end = innobase_convert_name(
5076 table_name, sizeof(table_name),
5077 index->table_name,
5078 strlen(index->table_name),
5079 thd, TRUE);
5080
5081 OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store(
5082 table_name,
5083 static_cast<uint>(table_name_end - table_name),
5084 system_charset_info));
5085 fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull();
5086
5087 OK(field_store_index_name(
5088 fields[IDX_BUFFER_PAGE_INDEX_NAME],
5089 index->name));
5090 }
5091
5092 mutex_exit(&dict_sys->mutex);
5093 }
5094
5095 OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
5096 page_info->num_recs));
5097
5098 OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
5099 page_info->data_size));
5100
5101 OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
5102 page_info->zip_ssize
5103 ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize
5104 : 0));
5105
5106 #if BUF_PAGE_STATE_BITS > 3
5107 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
5108 #endif
5109 state = static_cast<enum buf_page_state>(page_info->page_state);
5110
5111 switch (state) {
5112 /* First three states are for compression pages and
5113 are not states we would get as we scan pages through
5114 buffer blocks */
5115 case BUF_BLOCK_POOL_WATCH:
5116 case BUF_BLOCK_ZIP_PAGE:
5117 case BUF_BLOCK_ZIP_DIRTY:
5118 state_str = NULL;
5119 break;
5120 case BUF_BLOCK_NOT_USED:
5121 state_str = "NOT_USED";
5122 break;
5123 case BUF_BLOCK_READY_FOR_USE:
5124 state_str = "READY_FOR_USE";
5125 break;
5126 case BUF_BLOCK_FILE_PAGE:
5127 state_str = "FILE_PAGE";
5128 break;
5129 case BUF_BLOCK_MEMORY:
5130 state_str = "MEMORY";
5131 break;
5132 case BUF_BLOCK_REMOVE_HASH:
5133 state_str = "REMOVE_HASH";
5134 break;
5135 };
5136
5137 OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
5138 state_str));
5139
5140 switch (page_info->io_fix) {
5141 case BUF_IO_NONE:
5142 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5143 "IO_NONE"));
5144 break;
5145 case BUF_IO_READ:
5146 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5147 "IO_READ"));
5148 break;
5149 case BUF_IO_WRITE:
5150 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5151 "IO_WRITE"));
5152 break;
5153 case BUF_IO_PIN:
5154 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5155 "IO_PIN"));
5156 break;
5157 }
5158
5159 OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
5160 (page_info->is_old) ? "YES" : "NO"));
5161
5162 OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
5163 page_info->freed_page_clock));
5164
5165 if (schema_table_store_record(thd, table)) {
5166 DBUG_RETURN(1);
5167 }
5168 }
5169
5170 DBUG_RETURN(0);
5171 }
5172
5173 /*******************************************************************//**
5174 Set appropriate page type to a buf_page_info_t structure */
5175 static
5176 void
i_s_innodb_set_page_type(buf_page_info_t * page_info,ulint page_type,const byte * frame)5177 i_s_innodb_set_page_type(
5178 /*=====================*/
5179 buf_page_info_t*page_info, /*!< in/out: structure to fill with
5180 scanned info */
5181 ulint page_type, /*!< in: page type */
5182 const byte* frame) /*!< in: buffer frame */
5183 {
5184 if (page_type == FIL_PAGE_INDEX) {
5185 const page_t* page = (const page_t*) frame;
5186
5187 page_info->index_id = btr_page_get_index_id(page);
5188
5189 /* FIL_PAGE_INDEX is a bit special, its value
5190 is defined as 17855, so we cannot use FIL_PAGE_INDEX
5191 to index into i_s_page_type[] array, its array index
5192 in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
5193 (1) for index pages or I_S_PAGE_TYPE_IBUF for
5194 change buffer index pages */
5195 if (page_info->index_id
5196 == static_cast<index_id_t>(DICT_IBUF_ID_MIN
5197 + IBUF_SPACE_ID)) {
5198 page_info->page_type = I_S_PAGE_TYPE_IBUF;
5199 } else {
5200 page_info->page_type = I_S_PAGE_TYPE_INDEX;
5201 }
5202
5203 page_info->data_size = (ulint)(page_header_get_field(
5204 page, PAGE_HEAP_TOP) - (page_is_comp(page)
5205 ? PAGE_NEW_SUPREMUM_END
5206 : PAGE_OLD_SUPREMUM_END)
5207 - page_header_get_field(page, PAGE_GARBAGE));
5208
5209 page_info->num_recs = page_get_n_recs(page);
5210 } else if (page_type > FIL_PAGE_TYPE_LAST) {
5211 /* Encountered an unknown page type */
5212 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5213 } else {
5214 /* Make sure we get the right index into the
5215 i_s_page_type[] array */
5216 ut_a(page_type == i_s_page_type[page_type].type_value);
5217
5218 page_info->page_type = page_type;
5219 }
5220
5221 if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
5222 || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
5223 page_info->page_num = mach_read_from_4(
5224 frame + FIL_PAGE_OFFSET);
5225 page_info->space_id = mach_read_from_4(
5226 frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
5227 }
5228 }
5229 /*******************************************************************//**
5230 Scans pages in the buffer cache, and collect their general information
5231 into the buf_page_info_t array which is zero-filled. So any fields
5232 that are not initialized in the function will default to 0 */
5233 static
5234 void
i_s_innodb_buffer_page_get_info(const buf_page_t * bpage,ulint pool_id,ulint pos,buf_page_info_t * page_info)5235 i_s_innodb_buffer_page_get_info(
5236 /*============================*/
5237 const buf_page_t*bpage, /*!< in: buffer pool page to scan */
5238 ulint pool_id, /*!< in: buffer pool id */
5239 ulint pos, /*!< in: buffer block position in
5240 buffer pool or in the LRU list */
5241 buf_page_info_t*page_info) /*!< in: zero filled info structure;
5242 out: structure filled with scanned
5243 info */
5244 {
5245 ut_ad(pool_id < MAX_BUFFER_POOLS);
5246
5247 page_info->pool_id = pool_id;
5248
5249 page_info->block_id = pos;
5250
5251 page_info->page_state = buf_page_get_state(bpage);
5252
5253 /* Only fetch information for buffers that map to a tablespace,
5254 that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
5255 BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
5256 if (buf_page_in_file(bpage)) {
5257 const byte* frame;
5258 ulint page_type;
5259
5260 page_info->space_id = buf_page_get_space(bpage);
5261
5262 page_info->page_num = buf_page_get_page_no(bpage);
5263
5264 page_info->flush_type = bpage->flush_type;
5265
5266 page_info->fix_count = bpage->buf_fix_count;
5267
5268 page_info->newest_mod = bpage->newest_modification;
5269
5270 page_info->oldest_mod = bpage->oldest_modification;
5271
5272 page_info->access_time = bpage->access_time;
5273
5274 page_info->zip_ssize = bpage->zip.ssize;
5275
5276 page_info->io_fix = bpage->io_fix;
5277
5278 page_info->is_old = bpage->old;
5279
5280 page_info->freed_page_clock = bpage->freed_page_clock;
5281
5282 switch (buf_page_get_io_fix(bpage)) {
5283 case BUF_IO_NONE:
5284 case BUF_IO_WRITE:
5285 case BUF_IO_PIN:
5286 break;
5287 case BUF_IO_READ:
5288 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5289 return;
5290 }
5291
5292 if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
5293 const buf_block_t*block;
5294
5295 block = reinterpret_cast<const buf_block_t*>(bpage);
5296 frame = block->frame;
5297 page_info->hashed = (block->index != NULL);
5298 } else {
5299 ut_ad(page_info->zip_ssize);
5300 frame = bpage->zip.data;
5301 }
5302
5303 page_type = fil_page_get_type(frame);
5304
5305 i_s_innodb_set_page_type(page_info, page_type, frame);
5306 } else {
5307 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5308 }
5309 }
5310
5311 /*******************************************************************//**
5312 This is the function that goes through each block of the buffer pool
5313 and fetch information to information schema tables: INNODB_BUFFER_PAGE.
5314 @return 0 on success, 1 on failure */
5315 static
5316 int
i_s_innodb_fill_buffer_pool(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5317 i_s_innodb_fill_buffer_pool(
5318 /*========================*/
5319 THD* thd, /*!< in: thread */
5320 TABLE_LIST* tables, /*!< in/out: tables to fill */
5321 buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
5322 const ulint pool_id) /*!< in: buffer pool id */
5323 {
5324 int status = 0;
5325 mem_heap_t* heap;
5326
5327 DBUG_ENTER("i_s_innodb_fill_buffer_pool");
5328 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5329
5330 heap = mem_heap_create(10000);
5331
5332 /* Go through each chunk of buffer pool. Currently, we only
5333 have one single chunk for each buffer pool */
5334 for (ulint n = 0; n < buf_pool->n_chunks; n++) {
5335 const buf_block_t* block;
5336 ulint n_blocks;
5337 buf_page_info_t* info_buffer;
5338 ulint num_page;
5339 ulint mem_size;
5340 ulint chunk_size;
5341 ulint num_to_process = 0;
5342 ulint block_id = 0;
5343
5344 /* Get buffer block of the nth chunk */
5345 block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
5346 num_page = 0;
5347
5348 while (chunk_size > 0) {
5349 /* we cache maximum MAX_BUF_INFO_CACHED number of
5350 buffer page info */
5351 num_to_process = ut_min(chunk_size,
5352 MAX_BUF_INFO_CACHED);
5353
5354 mem_size = num_to_process * sizeof(buf_page_info_t);
5355
5356 /* For each chunk, we'll pre-allocate information
5357 structures to cache the page information read from
5358 the buffer pool. Doing so before obtain any mutex */
5359 info_buffer = (buf_page_info_t*) mem_heap_zalloc(
5360 heap, mem_size);
5361
5362 /* Obtain appropriate mutexes. Since this is diagnostic
5363 buffer pool info printout, we are not required to
5364 preserve the overall consistency, so we can
5365 release mutex periodically */
5366 buf_pool_mutex_enter(buf_pool);
5367
5368 /* GO through each block in the chunk */
5369 for (n_blocks = num_to_process; n_blocks--; block++) {
5370 i_s_innodb_buffer_page_get_info(
5371 &block->page, pool_id, block_id,
5372 info_buffer + num_page);
5373 block_id++;
5374 num_page++;
5375 }
5376
5377 buf_pool_mutex_exit(buf_pool);
5378
5379 /* Fill in information schema table with information
5380 just collected from the buffer chunk scan */
5381 status = i_s_innodb_buffer_page_fill(
5382 thd, tables, info_buffer,
5383 num_page);
5384
5385 /* If something goes wrong, break and return */
5386 if (status) {
5387 break;
5388 }
5389
5390 mem_heap_empty(heap);
5391 chunk_size -= num_to_process;
5392 num_page = 0;
5393 }
5394 }
5395
5396 mem_heap_free(heap);
5397
5398 DBUG_RETURN(status);
5399 }
5400
5401 /*******************************************************************//**
5402 Fill page information for pages in InnoDB buffer pool to the
5403 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
5404 @return 0 on success, 1 on failure */
5405 static
5406 int
i_s_innodb_buffer_page_fill_table(THD * thd,TABLE_LIST * tables,Item *)5407 i_s_innodb_buffer_page_fill_table(
5408 /*==============================*/
5409 THD* thd, /*!< in: thread */
5410 TABLE_LIST* tables, /*!< in/out: tables to fill */
5411 Item* ) /*!< in: condition (ignored) */
5412 {
5413 int status = 0;
5414
5415 DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
5416
5417 /* deny access to user without PROCESS privilege */
5418 if (check_global_access(thd, PROCESS_ACL)) {
5419 DBUG_RETURN(0);
5420 }
5421
5422 /* Walk through each buffer pool */
5423 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5424 buf_pool_t* buf_pool;
5425
5426 buf_pool = buf_pool_from_array(i);
5427
5428 /* Fetch information from pages in this buffer pool,
5429 and fill the corresponding I_S table */
5430 status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
5431
5432 /* If something wrong, break and return */
5433 if (status) {
5434 break;
5435 }
5436 }
5437
5438 DBUG_RETURN(status);
5439 }
5440
5441 /*******************************************************************//**
5442 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
5443 @return 0 on success, 1 on failure */
5444 static
5445 int
i_s_innodb_buffer_page_init(void * p)5446 i_s_innodb_buffer_page_init(
5447 /*========================*/
5448 void* p) /*!< in/out: table schema object */
5449 {
5450 ST_SCHEMA_TABLE* schema;
5451
5452 DBUG_ENTER("i_s_innodb_buffer_page_init");
5453
5454 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5455
5456 schema->fields_info = i_s_innodb_buffer_page_fields_info;
5457 schema->fill_table = i_s_innodb_buffer_page_fill_table;
5458
5459 DBUG_RETURN(0);
5460 }
5461
5462 UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page =
5463 {
5464 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
5465 /* int */
5466 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5467
5468 /* pointer to type-specific plugin descriptor */
5469 /* void* */
5470 STRUCT_FLD(info, &i_s_info),
5471
5472 /* plugin name */
5473 /* const char* */
5474 STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
5475
5476 /* plugin author (for SHOW PLUGINS) */
5477 /* const char* */
5478 STRUCT_FLD(author, plugin_author),
5479
5480 /* general descriptive text (for SHOW PLUGINS) */
5481 /* const char* */
5482 STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
5483
5484 /* the plugin license (PLUGIN_LICENSE_XXX) */
5485 /* int */
5486 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5487
5488 /* the function to invoke when plugin is loaded */
5489 /* int (*)(void*); */
5490 STRUCT_FLD(init, i_s_innodb_buffer_page_init),
5491
5492 /* the function to invoke when plugin is unloaded */
5493 /* int (*)(void*); */
5494 STRUCT_FLD(deinit, i_s_common_deinit),
5495
5496 /* plugin version (for SHOW PLUGINS) */
5497 /* unsigned int */
5498 STRUCT_FLD(version, INNODB_VERSION_SHORT),
5499
5500 /* struct st_mysql_show_var* */
5501 STRUCT_FLD(status_vars, NULL),
5502
5503 /* struct st_mysql_sys_var** */
5504 STRUCT_FLD(system_vars, NULL),
5505
5506 /* reserved for dependency checking */
5507 /* void* */
5508 STRUCT_FLD(__reserved1, NULL),
5509
5510 /* Plugin flags */
5511 /* unsigned long */
5512 STRUCT_FLD(flags, 0UL),
5513 };
5514
5515 static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] =
5516 {
5517 #define IDX_BUF_LRU_POOL_ID 0
5518 {STRUCT_FLD(field_name, "POOL_ID"),
5519 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5520 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5521 STRUCT_FLD(value, 0),
5522 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5523 STRUCT_FLD(old_name, ""),
5524 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5525
5526 #define IDX_BUF_LRU_POS 1
5527 {STRUCT_FLD(field_name, "LRU_POSITION"),
5528 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5529 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5530 STRUCT_FLD(value, 0),
5531 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5532 STRUCT_FLD(old_name, ""),
5533 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5534
5535 #define IDX_BUF_LRU_PAGE_SPACE 2
5536 {STRUCT_FLD(field_name, "SPACE"),
5537 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5538 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5539 STRUCT_FLD(value, 0),
5540 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5541 STRUCT_FLD(old_name, ""),
5542 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5543
5544 #define IDX_BUF_LRU_PAGE_NUM 3
5545 {STRUCT_FLD(field_name, "PAGE_NUMBER"),
5546 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5547 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5548 STRUCT_FLD(value, 0),
5549 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5550 STRUCT_FLD(old_name, ""),
5551 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5552
5553 #define IDX_BUF_LRU_PAGE_TYPE 4
5554 {STRUCT_FLD(field_name, "PAGE_TYPE"),
5555 STRUCT_FLD(field_length, 64),
5556 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5557 STRUCT_FLD(value, 0),
5558 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5559 STRUCT_FLD(old_name, ""),
5560 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5561
5562 #define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5
5563 {STRUCT_FLD(field_name, "FLUSH_TYPE"),
5564 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5565 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5566 STRUCT_FLD(value, 0),
5567 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5568 STRUCT_FLD(old_name, ""),
5569 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5570
5571 #define IDX_BUF_LRU_PAGE_FIX_COUNT 6
5572 {STRUCT_FLD(field_name, "FIX_COUNT"),
5573 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5574 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5575 STRUCT_FLD(value, 0),
5576 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5577 STRUCT_FLD(old_name, ""),
5578 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5579
5580 #define IDX_BUF_LRU_PAGE_HASHED 7
5581 {STRUCT_FLD(field_name, "IS_HASHED"),
5582 STRUCT_FLD(field_length, 3),
5583 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5584 STRUCT_FLD(value, 0),
5585 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5586 STRUCT_FLD(old_name, ""),
5587 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5588
5589 #define IDX_BUF_LRU_PAGE_NEWEST_MOD 8
5590 {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
5591 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5592 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5593 STRUCT_FLD(value, 0),
5594 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5595 STRUCT_FLD(old_name, ""),
5596 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5597
5598 #define IDX_BUF_LRU_PAGE_OLDEST_MOD 9
5599 {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
5600 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5601 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5602 STRUCT_FLD(value, 0),
5603 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5604 STRUCT_FLD(old_name, ""),
5605 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5606
5607 #define IDX_BUF_LRU_PAGE_ACCESS_TIME 10
5608 {STRUCT_FLD(field_name, "ACCESS_TIME"),
5609 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5610 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5611 STRUCT_FLD(value, 0),
5612 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5613 STRUCT_FLD(old_name, ""),
5614 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5615
5616 #define IDX_BUF_LRU_PAGE_TABLE_NAME 11
5617 {STRUCT_FLD(field_name, "TABLE_NAME"),
5618 STRUCT_FLD(field_length, 1024),
5619 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5620 STRUCT_FLD(value, 0),
5621 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5622 STRUCT_FLD(old_name, ""),
5623 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5624
5625 #define IDX_BUF_LRU_PAGE_INDEX_NAME 12
5626 {STRUCT_FLD(field_name, "INDEX_NAME"),
5627 STRUCT_FLD(field_length, 1024),
5628 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5629 STRUCT_FLD(value, 0),
5630 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5631 STRUCT_FLD(old_name, ""),
5632 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5633
5634 #define IDX_BUF_LRU_PAGE_NUM_RECS 13
5635 {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
5636 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5637 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5638 STRUCT_FLD(value, 0),
5639 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5640 STRUCT_FLD(old_name, ""),
5641 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5642
5643 #define IDX_BUF_LRU_PAGE_DATA_SIZE 14
5644 {STRUCT_FLD(field_name, "DATA_SIZE"),
5645 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5646 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5647 STRUCT_FLD(value, 0),
5648 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5649 STRUCT_FLD(old_name, ""),
5650 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5651
5652 #define IDX_BUF_LRU_PAGE_ZIP_SIZE 15
5653 {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
5654 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5655 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5656 STRUCT_FLD(value, 0),
5657 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5658 STRUCT_FLD(old_name, ""),
5659 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5660
5661 #define IDX_BUF_LRU_PAGE_STATE 16
5662 {STRUCT_FLD(field_name, "COMPRESSED"),
5663 STRUCT_FLD(field_length, 3),
5664 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5665 STRUCT_FLD(value, 0),
5666 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5667 STRUCT_FLD(old_name, ""),
5668 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5669
5670 #define IDX_BUF_LRU_PAGE_IO_FIX 17
5671 {STRUCT_FLD(field_name, "IO_FIX"),
5672 STRUCT_FLD(field_length, 64),
5673 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5674 STRUCT_FLD(value, 0),
5675 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5676 STRUCT_FLD(old_name, ""),
5677 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5678
5679 #define IDX_BUF_LRU_PAGE_IS_OLD 18
5680 {STRUCT_FLD(field_name, "IS_OLD"),
5681 STRUCT_FLD(field_length, 3),
5682 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5683 STRUCT_FLD(value, 0),
5684 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5685 STRUCT_FLD(old_name, ""),
5686 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5687
5688 #define IDX_BUF_LRU_PAGE_FREE_CLOCK 19
5689 {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
5690 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5691 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5692 STRUCT_FLD(value, 0),
5693 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5694 STRUCT_FLD(old_name, ""),
5695 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5696
5697 END_OF_ST_FIELD_INFO
5698 };
5699
5700 /*******************************************************************//**
5701 Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
5702 cached in the buf_page_info_t array
5703 @return 0 on success, 1 on failure */
5704 static
5705 int
i_s_innodb_buf_page_lru_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5706 i_s_innodb_buf_page_lru_fill(
5707 /*=========================*/
5708 THD* thd, /*!< in: thread */
5709 TABLE_LIST* tables, /*!< in/out: tables to fill */
5710 const buf_page_info_t* info_array, /*!< in: array cached page
5711 info */
5712 ulint num_page) /*!< in: number of page info
5713 cached */
5714 {
5715 TABLE* table;
5716 Field** fields;
5717 mem_heap_t* heap;
5718
5719 DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
5720
5721 table = tables->table;
5722
5723 fields = table->field;
5724
5725 heap = mem_heap_create(1000);
5726
5727 /* Iterate through the cached array and fill the I_S table rows */
5728 for (ulint i = 0; i < num_page; i++) {
5729 const buf_page_info_t* page_info;
5730 char table_name[MAX_FULL_NAME_LEN + 1];
5731 const char* table_name_end = NULL;
5732 const char* state_str;
5733 enum buf_page_state state;
5734
5735 state_str = NULL;
5736
5737 page_info = info_array + i;
5738
5739 OK(fields[IDX_BUF_LRU_POOL_ID]->store(
5740 static_cast<double>(page_info->pool_id)));
5741
5742 OK(fields[IDX_BUF_LRU_POS]->store(
5743 static_cast<double>(page_info->block_id)));
5744
5745 OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(
5746 static_cast<double>(page_info->space_id)));
5747
5748 OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(
5749 static_cast<double>(page_info->page_num)));
5750
5751 OK(field_store_string(
5752 fields[IDX_BUF_LRU_PAGE_TYPE],
5753 i_s_page_type[page_info->page_type].type_str));
5754
5755 OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
5756 static_cast<double>(page_info->flush_type)));
5757
5758 OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
5759 static_cast<double>(page_info->fix_count)));
5760
5761 if (page_info->hashed) {
5762 OK(field_store_string(
5763 fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
5764 } else {
5765 OK(field_store_string(
5766 fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
5767 }
5768
5769 OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
5770 page_info->newest_mod, true));
5771
5772 OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
5773 page_info->oldest_mod, true));
5774
5775 OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
5776 page_info->access_time));
5777
5778 fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null();
5779
5780 fields[IDX_BUF_LRU_PAGE_INDEX_NAME]->set_null();
5781
5782 /* If this is an index page, fetch the index name
5783 and table name */
5784 if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5785 const dict_index_t* index;
5786
5787 mutex_enter(&dict_sys->mutex);
5788 index = dict_index_get_if_in_cache_low(
5789 page_info->index_id);
5790
5791 if (index) {
5792
5793 table_name_end = innobase_convert_name(
5794 table_name, sizeof(table_name),
5795 index->table_name,
5796 strlen(index->table_name),
5797 thd, TRUE);
5798
5799 OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store(
5800 table_name,
5801 static_cast<uint>(table_name_end - table_name),
5802 system_charset_info));
5803 fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull();
5804
5805 OK(field_store_index_name(
5806 fields[IDX_BUF_LRU_PAGE_INDEX_NAME],
5807 index->name));
5808 }
5809
5810 mutex_exit(&dict_sys->mutex);
5811 }
5812
5813 OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
5814 page_info->num_recs));
5815
5816 OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
5817 page_info->data_size));
5818
5819 OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
5820 page_info->zip_ssize ?
5821 512 << page_info->zip_ssize : 0));
5822
5823 state = static_cast<enum buf_page_state>(page_info->page_state);
5824
5825 switch (state) {
5826 /* Compressed page */
5827 case BUF_BLOCK_ZIP_PAGE:
5828 case BUF_BLOCK_ZIP_DIRTY:
5829 state_str = "YES";
5830 break;
5831 /* Uncompressed page */
5832 case BUF_BLOCK_FILE_PAGE:
5833 state_str = "NO";
5834 break;
5835 /* We should not see following states */
5836 case BUF_BLOCK_POOL_WATCH:
5837 case BUF_BLOCK_READY_FOR_USE:
5838 case BUF_BLOCK_NOT_USED:
5839 case BUF_BLOCK_MEMORY:
5840 case BUF_BLOCK_REMOVE_HASH:
5841 state_str = NULL;
5842 break;
5843 };
5844
5845 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
5846 state_str));
5847
5848 switch (page_info->io_fix) {
5849 case BUF_IO_NONE:
5850 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5851 "IO_NONE"));
5852 break;
5853 case BUF_IO_READ:
5854 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5855 "IO_READ"));
5856 break;
5857 case BUF_IO_WRITE:
5858 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5859 "IO_WRITE"));
5860 break;
5861 }
5862
5863 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
5864 (page_info->is_old) ? "YES" : "NO"));
5865
5866 OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
5867 page_info->freed_page_clock));
5868
5869 if (schema_table_store_record(thd, table)) {
5870 mem_heap_free(heap);
5871 DBUG_RETURN(1);
5872 }
5873
5874 mem_heap_empty(heap);
5875 }
5876
5877 mem_heap_free(heap);
5878
5879 DBUG_RETURN(0);
5880 }
5881
5882 /*******************************************************************//**
5883 This is the function that goes through buffer pool's LRU list
5884 and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
5885 @return 0 on success, 1 on failure */
5886 static
5887 int
i_s_innodb_fill_buffer_lru(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5888 i_s_innodb_fill_buffer_lru(
5889 /*=======================*/
5890 THD* thd, /*!< in: thread */
5891 TABLE_LIST* tables, /*!< in/out: tables to fill */
5892 buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
5893 const ulint pool_id) /*!< in: buffer pool id */
5894 {
5895 int status = 0;
5896 buf_page_info_t* info_buffer;
5897 ulint lru_pos = 0;
5898 const buf_page_t* bpage;
5899 ulint lru_len;
5900
5901 DBUG_ENTER("i_s_innodb_fill_buffer_lru");
5902 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5903
5904 /* Obtain buf_pool mutex before allocate info_buffer, since
5905 UT_LIST_GET_LEN(buf_pool->LRU) could change */
5906 buf_pool_mutex_enter(buf_pool);
5907
5908 lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
5909
5910 /* Print error message if malloc fail */
5911 info_buffer = (buf_page_info_t*) my_malloc(
5912 lru_len * sizeof *info_buffer, MYF(MY_WME));
5913
5914 if (!info_buffer) {
5915 status = 1;
5916 goto exit;
5917 }
5918
5919 memset(info_buffer, 0, lru_len * sizeof *info_buffer);
5920
5921 /* Walk through Pool's LRU list and print the buffer page
5922 information */
5923 bpage = UT_LIST_GET_LAST(buf_pool->LRU);
5924
5925 while (bpage != NULL) {
5926 /* Use the same function that collect buffer info for
5927 INNODB_BUFFER_PAGE to get buffer page info */
5928 i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
5929 (info_buffer + lru_pos));
5930
5931 bpage = UT_LIST_GET_PREV(LRU, bpage);
5932
5933 lru_pos++;
5934 }
5935
5936 ut_ad(lru_pos == lru_len);
5937 ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
5938
5939 exit:
5940 buf_pool_mutex_exit(buf_pool);
5941
5942 if (info_buffer) {
5943 status = i_s_innodb_buf_page_lru_fill(
5944 thd, tables, info_buffer, lru_len);
5945
5946 my_free(info_buffer);
5947 }
5948
5949 DBUG_RETURN(status);
5950 }
5951
5952 /*******************************************************************//**
5953 Fill page information for pages in InnoDB buffer pool to the
5954 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
5955 @return 0 on success, 1 on failure */
5956 static
5957 int
i_s_innodb_buf_page_lru_fill_table(THD * thd,TABLE_LIST * tables,Item *)5958 i_s_innodb_buf_page_lru_fill_table(
5959 /*===============================*/
5960 THD* thd, /*!< in: thread */
5961 TABLE_LIST* tables, /*!< in/out: tables to fill */
5962 Item* ) /*!< in: condition (ignored) */
5963 {
5964 int status = 0;
5965
5966 DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
5967
5968 /* deny access to any users that do not hold PROCESS_ACL */
5969 if (check_global_access(thd, PROCESS_ACL)) {
5970 DBUG_RETURN(0);
5971 }
5972
5973 /* Walk through each buffer pool */
5974 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5975 buf_pool_t* buf_pool;
5976
5977 buf_pool = buf_pool_from_array(i);
5978
5979 /* Fetch information from pages in this buffer pool's LRU list,
5980 and fill the corresponding I_S table */
5981 status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
5982
5983 /* If something wrong, break and return */
5984 if (status) {
5985 break;
5986 }
5987 }
5988
5989 DBUG_RETURN(status);
5990 }
5991
5992 /*******************************************************************//**
5993 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
5994 @return 0 on success, 1 on failure */
5995 static
5996 int
i_s_innodb_buffer_page_lru_init(void * p)5997 i_s_innodb_buffer_page_lru_init(
5998 /*============================*/
5999 void* p) /*!< in/out: table schema object */
6000 {
6001 ST_SCHEMA_TABLE* schema;
6002
6003 DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
6004
6005 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
6006
6007 schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
6008 schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
6009
6010 DBUG_RETURN(0);
6011 }
6012
6013 UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru =
6014 {
6015 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6016 /* int */
6017 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6018
6019 /* pointer to type-specific plugin descriptor */
6020 /* void* */
6021 STRUCT_FLD(info, &i_s_info),
6022
6023 /* plugin name */
6024 /* const char* */
6025 STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
6026
6027 /* plugin author (for SHOW PLUGINS) */
6028 /* const char* */
6029 STRUCT_FLD(author, plugin_author),
6030
6031 /* general descriptive text (for SHOW PLUGINS) */
6032 /* const char* */
6033 STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
6034
6035 /* the plugin license (PLUGIN_LICENSE_XXX) */
6036 /* int */
6037 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6038
6039 /* the function to invoke when plugin is loaded */
6040 /* int (*)(void*); */
6041 STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
6042
6043 /* the function to invoke when plugin is unloaded */
6044 /* int (*)(void*); */
6045 STRUCT_FLD(deinit, i_s_common_deinit),
6046
6047 /* plugin version (for SHOW PLUGINS) */
6048 /* unsigned int */
6049 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6050
6051 /* struct st_mysql_show_var* */
6052 STRUCT_FLD(status_vars, NULL),
6053
6054 /* struct st_mysql_sys_var** */
6055 STRUCT_FLD(system_vars, NULL),
6056
6057 /* reserved for dependency checking */
6058 /* void* */
6059 STRUCT_FLD(__reserved1, NULL),
6060
6061 /* Plugin flags */
6062 /* unsigned long */
6063 STRUCT_FLD(flags, 0UL),
6064 };
6065
6066 /*******************************************************************//**
6067 Unbind a dynamic INFORMATION_SCHEMA table.
6068 @return 0 on success */
6069 static
6070 int
i_s_common_deinit(void * p)6071 i_s_common_deinit(
6072 /*==============*/
6073 void* p) /*!< in/out: table schema object */
6074 {
6075 DBUG_ENTER("i_s_common_deinit");
6076
6077 /* Do nothing */
6078
6079 DBUG_RETURN(0);
6080 }
6081
6082 /** SYS_TABLES ***************************************************/
6083 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
6084 static ST_FIELD_INFO innodb_sys_tables_fields_info[] =
6085 {
6086 #define SYS_TABLES_ID 0
6087 {STRUCT_FLD(field_name, "TABLE_ID"),
6088 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6089 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6090 STRUCT_FLD(value, 0),
6091 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6092 STRUCT_FLD(old_name, ""),
6093 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6094
6095 #define SYS_TABLES_NAME 1
6096 {STRUCT_FLD(field_name, "NAME"),
6097 STRUCT_FLD(field_length, MAX_FULL_NAME_LEN + 1),
6098 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6099 STRUCT_FLD(value, 0),
6100 STRUCT_FLD(field_flags, 0),
6101 STRUCT_FLD(old_name, ""),
6102 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6103
6104 #define SYS_TABLES_FLAG 2
6105 {STRUCT_FLD(field_name, "FLAG"),
6106 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6107 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6108 STRUCT_FLD(value, 0),
6109 STRUCT_FLD(field_flags, 0),
6110 STRUCT_FLD(old_name, ""),
6111 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6112
6113 #define SYS_TABLES_NUM_COLUMN 3
6114 {STRUCT_FLD(field_name, "N_COLS"),
6115 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6116 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6117 STRUCT_FLD(value, 0),
6118 STRUCT_FLD(field_flags, 0),
6119 STRUCT_FLD(old_name, ""),
6120 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6121
6122 #define SYS_TABLES_SPACE 4
6123 {STRUCT_FLD(field_name, "SPACE"),
6124 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6125 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6126 STRUCT_FLD(value, 0),
6127 STRUCT_FLD(field_flags, 0),
6128 STRUCT_FLD(old_name, ""),
6129 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6130
6131 #define SYS_TABLES_FILE_FORMAT 5
6132 {STRUCT_FLD(field_name, "FILE_FORMAT"),
6133 STRUCT_FLD(field_length, 10),
6134 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6135 STRUCT_FLD(value, 0),
6136 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
6137 STRUCT_FLD(old_name, ""),
6138 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6139
6140 #define SYS_TABLES_ROW_FORMAT 6
6141 {STRUCT_FLD(field_name, "ROW_FORMAT"),
6142 STRUCT_FLD(field_length, 12),
6143 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6144 STRUCT_FLD(value, 0),
6145 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
6146 STRUCT_FLD(old_name, ""),
6147 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6148
6149 #define SYS_TABLES_ZIP_PAGE_SIZE 7
6150 {STRUCT_FLD(field_name, "ZIP_PAGE_SIZE"),
6151 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6152 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6153 STRUCT_FLD(value, 0),
6154 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6155 STRUCT_FLD(old_name, ""),
6156 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6157
6158 END_OF_ST_FIELD_INFO
6159 };
6160
6161 /**********************************************************************//**
6162 Populate information_schema.innodb_sys_tables table with information
6163 from SYS_TABLES.
6164 @return 0 on success */
6165 static
6166 int
i_s_dict_fill_sys_tables(THD * thd,dict_table_t * table,TABLE * table_to_fill)6167 i_s_dict_fill_sys_tables(
6168 /*=====================*/
6169 THD* thd, /*!< in: thread */
6170 dict_table_t* table, /*!< in: table */
6171 TABLE* table_to_fill) /*!< in/out: fill this table */
6172 {
6173 Field** fields;
6174 ulint compact = DICT_TF_GET_COMPACT(table->flags);
6175 ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(table->flags);
6176 ulint zip_size = dict_tf_get_zip_size(table->flags);
6177 const char* file_format;
6178 const char* row_format;
6179
6180 file_format = trx_sys_file_format_id_to_name(atomic_blobs);
6181 if (!compact) {
6182 row_format = "Redundant";
6183 } else if (!atomic_blobs) {
6184 row_format = "Compact";
6185 } else if DICT_TF_GET_ZIP_SSIZE(table->flags) {
6186 row_format = "Compressed";
6187 } else {
6188 row_format = "Dynamic";
6189 }
6190
6191 DBUG_ENTER("i_s_dict_fill_sys_tables");
6192
6193 fields = table_to_fill->field;
6194
6195 OK(fields[SYS_TABLES_ID]->store(longlong(table->id), TRUE));
6196
6197 OK(field_store_string(fields[SYS_TABLES_NAME], table->name));
6198
6199 OK(fields[SYS_TABLES_FLAG]->store(table->flags));
6200
6201 OK(fields[SYS_TABLES_NUM_COLUMN]->store(table->n_cols));
6202
6203 OK(fields[SYS_TABLES_SPACE]->store(table->space));
6204
6205 OK(field_store_string(fields[SYS_TABLES_FILE_FORMAT], file_format));
6206
6207 OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
6208
6209 OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(
6210 static_cast<double>(zip_size)));
6211
6212 OK(schema_table_store_record(thd, table_to_fill));
6213
6214 DBUG_RETURN(0);
6215 }
6216 /*******************************************************************//**
6217 Function to go through each record in SYS_TABLES table, and fill the
6218 information_schema.innodb_sys_tables table with related table information
6219 @return 0 on success */
6220 static
6221 int
i_s_sys_tables_fill_table(THD * thd,TABLE_LIST * tables,Item *)6222 i_s_sys_tables_fill_table(
6223 /*======================*/
6224 THD* thd, /*!< in: thread */
6225 TABLE_LIST* tables, /*!< in/out: tables to fill */
6226 Item* ) /*!< in: condition (not used) */
6227 {
6228 btr_pcur_t pcur;
6229 const rec_t* rec;
6230 mem_heap_t* heap;
6231 mtr_t mtr;
6232
6233 DBUG_ENTER("i_s_sys_tables_fill_table");
6234 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6235
6236 /* deny access to user without PROCESS_ACL privilege */
6237 if (check_global_access(thd, PROCESS_ACL)) {
6238 DBUG_RETURN(0);
6239 }
6240
6241 heap = mem_heap_create(1000);
6242 mutex_enter(&(dict_sys->mutex));
6243 mtr_start(&mtr);
6244
6245 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6246
6247 while (rec) {
6248 const char* err_msg;
6249 dict_table_t* table_rec;
6250
6251 /* Create and populate a dict_table_t structure with
6252 information from SYS_TABLES row */
6253 err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6254 heap, rec, &table_rec,
6255 DICT_TABLE_LOAD_FROM_RECORD, &mtr);
6256
6257 mutex_exit(&dict_sys->mutex);
6258
6259 if (!err_msg) {
6260 i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
6261 } else {
6262 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6263 ER_CANT_FIND_SYSTEM_REC, "%s",
6264 err_msg);
6265 }
6266
6267 /* Since dict_process_sys_tables_rec_and_mtr_commit()
6268 is called with DICT_TABLE_LOAD_FROM_RECORD, the table_rec
6269 is created in dict_process_sys_tables_rec(), we will
6270 need to free it */
6271 if (table_rec) {
6272 dict_mem_table_free(table_rec);
6273 }
6274
6275 mem_heap_empty(heap);
6276
6277 /* Get the next record */
6278 mutex_enter(&dict_sys->mutex);
6279 mtr_start(&mtr);
6280 rec = dict_getnext_system(&pcur, &mtr);
6281 }
6282
6283 mtr_commit(&mtr);
6284 mutex_exit(&dict_sys->mutex);
6285 mem_heap_free(heap);
6286
6287 DBUG_RETURN(0);
6288 }
6289
6290 /*******************************************************************//**
6291 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
6292 @return 0 on success */
6293 static
6294 int
innodb_sys_tables_init(void * p)6295 innodb_sys_tables_init(
6296 /*===================*/
6297 void* p) /*!< in/out: table schema object */
6298 {
6299 ST_SCHEMA_TABLE* schema;
6300
6301 DBUG_ENTER("innodb_sys_tables_init");
6302
6303 schema = (ST_SCHEMA_TABLE*) p;
6304
6305 schema->fields_info = innodb_sys_tables_fields_info;
6306 schema->fill_table = i_s_sys_tables_fill_table;
6307
6308 DBUG_RETURN(0);
6309 }
6310
6311 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
6312 {
6313 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6314 /* int */
6315 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6316
6317 /* pointer to type-specific plugin descriptor */
6318 /* void* */
6319 STRUCT_FLD(info, &i_s_info),
6320
6321 /* plugin name */
6322 /* const char* */
6323 STRUCT_FLD(name, "INNODB_SYS_TABLES"),
6324
6325 /* plugin author (for SHOW PLUGINS) */
6326 /* const char* */
6327 STRUCT_FLD(author, plugin_author),
6328
6329 /* general descriptive text (for SHOW PLUGINS) */
6330 /* const char* */
6331 STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
6332
6333 /* the plugin license (PLUGIN_LICENSE_XXX) */
6334 /* int */
6335 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6336
6337 /* the function to invoke when plugin is loaded */
6338 /* int (*)(void*); */
6339 STRUCT_FLD(init, innodb_sys_tables_init),
6340
6341 /* the function to invoke when plugin is unloaded */
6342 /* int (*)(void*); */
6343 STRUCT_FLD(deinit, i_s_common_deinit),
6344
6345 /* plugin version (for SHOW PLUGINS) */
6346 /* unsigned int */
6347 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6348
6349 /* struct st_mysql_show_var* */
6350 STRUCT_FLD(status_vars, NULL),
6351
6352 /* struct st_mysql_sys_var** */
6353 STRUCT_FLD(system_vars, NULL),
6354
6355 /* reserved for dependency checking */
6356 /* void* */
6357 STRUCT_FLD(__reserved1, NULL),
6358
6359 /* Plugin flags */
6360 /* unsigned long */
6361 STRUCT_FLD(flags, 0UL),
6362 };
6363
6364 /** SYS_TABLESTATS ***********************************************/
6365 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
6366 static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
6367 {
6368 #define SYS_TABLESTATS_ID 0
6369 {STRUCT_FLD(field_name, "TABLE_ID"),
6370 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6371 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6372 STRUCT_FLD(value, 0),
6373 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6374 STRUCT_FLD(old_name, ""),
6375 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6376
6377 #define SYS_TABLESTATS_NAME 1
6378 {STRUCT_FLD(field_name, "NAME"),
6379 STRUCT_FLD(field_length, NAME_LEN + 1),
6380 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6381 STRUCT_FLD(value, 0),
6382 STRUCT_FLD(field_flags, 0),
6383 STRUCT_FLD(old_name, ""),
6384 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6385
6386 #define SYS_TABLESTATS_INIT 2
6387 {STRUCT_FLD(field_name, "STATS_INITIALIZED"),
6388 STRUCT_FLD(field_length, NAME_LEN + 1),
6389 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6390 STRUCT_FLD(value, 0),
6391 STRUCT_FLD(field_flags, 0),
6392 STRUCT_FLD(old_name, ""),
6393 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6394
6395 #define SYS_TABLESTATS_NROW 3
6396 {STRUCT_FLD(field_name, "NUM_ROWS"),
6397 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6398 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6399 STRUCT_FLD(value, 0),
6400 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6401 STRUCT_FLD(old_name, ""),
6402 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6403
6404 #define SYS_TABLESTATS_CLUST_SIZE 4
6405 {STRUCT_FLD(field_name, "CLUST_INDEX_SIZE"),
6406 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6407 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6408 STRUCT_FLD(value, 0),
6409 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6410 STRUCT_FLD(old_name, ""),
6411 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6412
6413 #define SYS_TABLESTATS_INDEX_SIZE 5
6414 {STRUCT_FLD(field_name, "OTHER_INDEX_SIZE"),
6415 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6416 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6417 STRUCT_FLD(value, 0),
6418 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6419 STRUCT_FLD(old_name, ""),
6420 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6421
6422 #define SYS_TABLESTATS_MODIFIED 6
6423 {STRUCT_FLD(field_name, "MODIFIED_COUNTER"),
6424 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6425 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6426 STRUCT_FLD(value, 0),
6427 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6428 STRUCT_FLD(old_name, ""),
6429 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6430
6431 #define SYS_TABLESTATS_AUTONINC 7
6432 {STRUCT_FLD(field_name, "AUTOINC"),
6433 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6434 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6435 STRUCT_FLD(value, 0),
6436 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6437 STRUCT_FLD(old_name, ""),
6438 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6439
6440 #define SYS_TABLESTATS_TABLE_REF_COUNT 8
6441 {STRUCT_FLD(field_name, "REF_COUNT"),
6442 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6443 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6444 STRUCT_FLD(value, 0),
6445 STRUCT_FLD(field_flags, 0),
6446 STRUCT_FLD(old_name, ""),
6447 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6448
6449 END_OF_ST_FIELD_INFO
6450 };
6451
6452 /**********************************************************************//**
6453 Populate information_schema.innodb_sys_tablestats table with information
6454 from SYS_TABLES.
6455 @return 0 on success */
6456 static
6457 int
i_s_dict_fill_sys_tablestats(THD * thd,dict_table_t * table,TABLE * table_to_fill)6458 i_s_dict_fill_sys_tablestats(
6459 /*=========================*/
6460 THD* thd, /*!< in: thread */
6461 dict_table_t* table, /*!< in: table */
6462 TABLE* table_to_fill) /*!< in/out: fill this table */
6463 {
6464 Field** fields;
6465
6466 DBUG_ENTER("i_s_dict_fill_sys_tablestats");
6467
6468 fields = table_to_fill->field;
6469
6470 OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
6471
6472 OK(field_store_string(fields[SYS_TABLESTATS_NAME], table->name));
6473
6474 dict_table_stats_lock(table, RW_S_LATCH);
6475
6476 if (table->stat_initialized) {
6477 OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6478 "Initialized"));
6479
6480 OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows,
6481 TRUE));
6482
6483 OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
6484 static_cast<double>(table->stat_clustered_index_size)));
6485
6486 OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
6487 static_cast<double>(table->stat_sum_of_other_index_sizes)));
6488
6489 OK(fields[SYS_TABLESTATS_MODIFIED]->store(
6490 static_cast<double>(table->stat_modified_counter)));
6491 } else {
6492 OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6493 "Uninitialized"));
6494
6495 OK(fields[SYS_TABLESTATS_NROW]->store(0, TRUE));
6496
6497 OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0));
6498
6499 OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0));
6500
6501 OK(fields[SYS_TABLESTATS_MODIFIED]->store(0));
6502 }
6503
6504 dict_table_stats_unlock(table, RW_S_LATCH);
6505
6506 OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, TRUE));
6507
6508 OK(fields[SYS_TABLESTATS_TABLE_REF_COUNT]->store(
6509 static_cast<double>(table->n_ref_count)));
6510
6511 OK(schema_table_store_record(thd, table_to_fill));
6512
6513 DBUG_RETURN(0);
6514 }
6515
6516 /*******************************************************************//**
6517 Function to go through each record in SYS_TABLES table, and fill the
6518 information_schema.innodb_sys_tablestats table with table statistics
6519 related information
6520 @return 0 on success */
6521 static
6522 int
i_s_sys_tables_fill_table_stats(THD * thd,TABLE_LIST * tables,Item *)6523 i_s_sys_tables_fill_table_stats(
6524 /*============================*/
6525 THD* thd, /*!< in: thread */
6526 TABLE_LIST* tables, /*!< in/out: tables to fill */
6527 Item* ) /*!< in: condition (not used) */
6528 {
6529 btr_pcur_t pcur;
6530 const rec_t* rec;
6531 mem_heap_t* heap;
6532 mtr_t mtr;
6533
6534 DBUG_ENTER("i_s_sys_tables_fill_table_stats");
6535 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6536
6537 /* deny access to user without PROCESS_ACL privilege */
6538 if (check_global_access(thd, PROCESS_ACL)) {
6539 DBUG_RETURN(0);
6540 }
6541
6542 heap = mem_heap_create(1000);
6543 mutex_enter(&dict_sys->mutex);
6544 mtr_start(&mtr);
6545
6546 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6547
6548 while (rec) {
6549 const char* err_msg;
6550 dict_table_t* table_rec;
6551
6552 /* Fetch the dict_table_t structure corresponding to
6553 this SYS_TABLES record */
6554 err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6555 heap, rec, &table_rec,
6556 DICT_TABLE_LOAD_FROM_CACHE, &mtr);
6557
6558 mutex_exit(&dict_sys->mutex);
6559
6560 if (!err_msg) {
6561 i_s_dict_fill_sys_tablestats(thd, table_rec,
6562 tables->table);
6563 } else {
6564 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6565 ER_CANT_FIND_SYSTEM_REC, "%s",
6566 err_msg);
6567 }
6568
6569 mem_heap_empty(heap);
6570
6571 /* Get the next record */
6572 mutex_enter(&dict_sys->mutex);
6573 mtr_start(&mtr);
6574 rec = dict_getnext_system(&pcur, &mtr);
6575 }
6576
6577 mtr_commit(&mtr);
6578 mutex_exit(&dict_sys->mutex);
6579 mem_heap_free(heap);
6580
6581 DBUG_RETURN(0);
6582 }
6583
6584 /*******************************************************************//**
6585 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
6586 @return 0 on success */
6587 static
6588 int
innodb_sys_tablestats_init(void * p)6589 innodb_sys_tablestats_init(
6590 /*=======================*/
6591 void* p) /*!< in/out: table schema object */
6592 {
6593 ST_SCHEMA_TABLE* schema;
6594
6595 DBUG_ENTER("innodb_sys_tablestats_init");
6596
6597 schema = (ST_SCHEMA_TABLE*) p;
6598
6599 schema->fields_info = innodb_sys_tablestats_fields_info;
6600 schema->fill_table = i_s_sys_tables_fill_table_stats;
6601
6602 DBUG_RETURN(0);
6603 }
6604
6605 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats =
6606 {
6607 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6608 /* int */
6609 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6610
6611 /* pointer to type-specific plugin descriptor */
6612 /* void* */
6613 STRUCT_FLD(info, &i_s_info),
6614
6615 /* plugin name */
6616 /* const char* */
6617 STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
6618
6619 /* plugin author (for SHOW PLUGINS) */
6620 /* const char* */
6621 STRUCT_FLD(author, plugin_author),
6622
6623 /* general descriptive text (for SHOW PLUGINS) */
6624 /* const char* */
6625 STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
6626
6627 /* the plugin license (PLUGIN_LICENSE_XXX) */
6628 /* int */
6629 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6630
6631 /* the function to invoke when plugin is loaded */
6632 /* int (*)(void*); */
6633 STRUCT_FLD(init, innodb_sys_tablestats_init),
6634
6635 /* the function to invoke when plugin is unloaded */
6636 /* int (*)(void*); */
6637 STRUCT_FLD(deinit, i_s_common_deinit),
6638
6639 /* plugin version (for SHOW PLUGINS) */
6640 /* unsigned int */
6641 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6642
6643 /* struct st_mysql_show_var* */
6644 STRUCT_FLD(status_vars, NULL),
6645
6646 /* struct st_mysql_sys_var** */
6647 STRUCT_FLD(system_vars, NULL),
6648
6649 /* reserved for dependency checking */
6650 /* void* */
6651 STRUCT_FLD(__reserved1, NULL),
6652
6653 /* Plugin flags */
6654 /* unsigned long */
6655 STRUCT_FLD(flags, 0UL),
6656 };
6657
6658 /** SYS_INDEXES **************************************************/
6659 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
6660 static ST_FIELD_INFO innodb_sysindex_fields_info[] =
6661 {
6662 #define SYS_INDEX_ID 0
6663 {STRUCT_FLD(field_name, "INDEX_ID"),
6664 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6665 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6666 STRUCT_FLD(value, 0),
6667 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6668 STRUCT_FLD(old_name, ""),
6669 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6670
6671 #define SYS_INDEX_NAME 1
6672 {STRUCT_FLD(field_name, "NAME"),
6673 STRUCT_FLD(field_length, NAME_LEN + 1),
6674 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6675 STRUCT_FLD(value, 0),
6676 STRUCT_FLD(field_flags, 0),
6677 STRUCT_FLD(old_name, ""),
6678 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6679
6680 #define SYS_INDEX_TABLE_ID 2
6681 {STRUCT_FLD(field_name, "TABLE_ID"),
6682 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6683 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6684 STRUCT_FLD(value, 0),
6685 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6686 STRUCT_FLD(old_name, ""),
6687 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6688
6689 #define SYS_INDEX_TYPE 3
6690 {STRUCT_FLD(field_name, "TYPE"),
6691 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6692 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6693 STRUCT_FLD(value, 0),
6694 STRUCT_FLD(field_flags, 0),
6695 STRUCT_FLD(old_name, ""),
6696 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6697
6698 #define SYS_INDEX_NUM_FIELDS 4
6699 {STRUCT_FLD(field_name, "N_FIELDS"),
6700 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6701 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6702 STRUCT_FLD(value, 0),
6703 STRUCT_FLD(field_flags, 0),
6704 STRUCT_FLD(old_name, ""),
6705 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6706
6707 #define SYS_INDEX_PAGE_NO 5
6708 {STRUCT_FLD(field_name, "PAGE_NO"),
6709 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6710 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6711 STRUCT_FLD(value, 0),
6712 STRUCT_FLD(field_flags, 0),
6713 STRUCT_FLD(old_name, ""),
6714 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6715
6716 #define SYS_INDEX_SPACE 6
6717 {STRUCT_FLD(field_name, "SPACE"),
6718 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6719 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6720 STRUCT_FLD(value, 0),
6721 STRUCT_FLD(field_flags, 0),
6722 STRUCT_FLD(old_name, ""),
6723 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6724
6725 END_OF_ST_FIELD_INFO
6726 };
6727
6728 /**********************************************************************//**
6729 Function to populate the information_schema.innodb_sys_indexes table with
6730 collected index information
6731 @return 0 on success */
6732 static
6733 int
i_s_dict_fill_sys_indexes(THD * thd,table_id_t table_id,dict_index_t * index,TABLE * table_to_fill)6734 i_s_dict_fill_sys_indexes(
6735 /*======================*/
6736 THD* thd, /*!< in: thread */
6737 table_id_t table_id, /*!< in: table id */
6738 dict_index_t* index, /*!< in: populated dict_index_t
6739 struct with index info */
6740 TABLE* table_to_fill) /*!< in/out: fill this table */
6741 {
6742 Field** fields;
6743
6744 DBUG_ENTER("i_s_dict_fill_sys_indexes");
6745
6746 fields = table_to_fill->field;
6747
6748 OK(field_store_index_name(fields[SYS_INDEX_NAME], index->name));
6749
6750 OK(fields[SYS_INDEX_ID]->store(longlong(index->id), TRUE));
6751
6752 OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), TRUE));
6753
6754 OK(fields[SYS_INDEX_TYPE]->store(index->type));
6755
6756 OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
6757
6758 /* FIL_NULL is ULINT32_UNDEFINED */
6759 if (index->page == FIL_NULL) {
6760 OK(fields[SYS_INDEX_PAGE_NO]->store(-1));
6761 } else {
6762 OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
6763 }
6764
6765 OK(fields[SYS_INDEX_SPACE]->store(index->space));
6766
6767 OK(schema_table_store_record(thd, table_to_fill));
6768
6769 DBUG_RETURN(0);
6770 }
6771 /*******************************************************************//**
6772 Function to go through each record in SYS_INDEXES table, and fill the
6773 information_schema.innodb_sys_indexes table with related index information
6774 @return 0 on success */
6775 static
6776 int
i_s_sys_indexes_fill_table(THD * thd,TABLE_LIST * tables,Item *)6777 i_s_sys_indexes_fill_table(
6778 /*=======================*/
6779 THD* thd, /*!< in: thread */
6780 TABLE_LIST* tables, /*!< in/out: tables to fill */
6781 Item* ) /*!< in: condition (not used) */
6782 {
6783 btr_pcur_t pcur;
6784 const rec_t* rec;
6785 mem_heap_t* heap;
6786 mtr_t mtr;
6787
6788 DBUG_ENTER("i_s_sys_indexes_fill_table");
6789 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6790
6791 /* deny access to user without PROCESS_ACL privilege */
6792 if (check_global_access(thd, PROCESS_ACL)) {
6793 DBUG_RETURN(0);
6794 }
6795
6796 heap = mem_heap_create(1000);
6797 mutex_enter(&dict_sys->mutex);
6798 mtr_start(&mtr);
6799
6800 /* Start scan the SYS_INDEXES table */
6801 rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
6802
6803 /* Process each record in the table */
6804 while (rec) {
6805 const char* err_msg;
6806 table_id_t table_id;
6807 dict_index_t index_rec;
6808
6809 /* Populate a dict_index_t structure with information from
6810 a SYS_INDEXES row */
6811 err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
6812 &table_id);
6813
6814 mtr_commit(&mtr);
6815 mutex_exit(&dict_sys->mutex);
6816
6817 if (!err_msg) {
6818 i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
6819 tables->table);
6820 } else {
6821 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6822 ER_CANT_FIND_SYSTEM_REC, "%s",
6823 err_msg);
6824 }
6825
6826 mem_heap_empty(heap);
6827
6828 /* Get the next record */
6829 mutex_enter(&dict_sys->mutex);
6830 mtr_start(&mtr);
6831 rec = dict_getnext_system(&pcur, &mtr);
6832 }
6833
6834 mtr_commit(&mtr);
6835 mutex_exit(&dict_sys->mutex);
6836 mem_heap_free(heap);
6837
6838 DBUG_RETURN(0);
6839 }
6840 /*******************************************************************//**
6841 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
6842 @return 0 on success */
6843 static
6844 int
innodb_sys_indexes_init(void * p)6845 innodb_sys_indexes_init(
6846 /*====================*/
6847 void* p) /*!< in/out: table schema object */
6848 {
6849 ST_SCHEMA_TABLE* schema;
6850
6851 DBUG_ENTER("innodb_sys_indexes_init");
6852
6853 schema = (ST_SCHEMA_TABLE*) p;
6854
6855 schema->fields_info = innodb_sysindex_fields_info;
6856 schema->fill_table = i_s_sys_indexes_fill_table;
6857
6858 DBUG_RETURN(0);
6859 }
6860
6861 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
6862 {
6863 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6864 /* int */
6865 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6866
6867 /* pointer to type-specific plugin descriptor */
6868 /* void* */
6869 STRUCT_FLD(info, &i_s_info),
6870
6871 /* plugin name */
6872 /* const char* */
6873 STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
6874
6875 /* plugin author (for SHOW PLUGINS) */
6876 /* const char* */
6877 STRUCT_FLD(author, plugin_author),
6878
6879 /* general descriptive text (for SHOW PLUGINS) */
6880 /* const char* */
6881 STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
6882
6883 /* the plugin license (PLUGIN_LICENSE_XXX) */
6884 /* int */
6885 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6886
6887 /* the function to invoke when plugin is loaded */
6888 /* int (*)(void*); */
6889 STRUCT_FLD(init, innodb_sys_indexes_init),
6890
6891 /* the function to invoke when plugin is unloaded */
6892 /* int (*)(void*); */
6893 STRUCT_FLD(deinit, i_s_common_deinit),
6894
6895 /* plugin version (for SHOW PLUGINS) */
6896 /* unsigned int */
6897 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6898
6899 /* struct st_mysql_show_var* */
6900 STRUCT_FLD(status_vars, NULL),
6901
6902 /* struct st_mysql_sys_var** */
6903 STRUCT_FLD(system_vars, NULL),
6904
6905 /* reserved for dependency checking */
6906 /* void* */
6907 STRUCT_FLD(__reserved1, NULL),
6908
6909 /* Plugin flags */
6910 /* unsigned long */
6911 STRUCT_FLD(flags, 0UL),
6912 };
6913
6914 /** SYS_COLUMNS **************************************************/
6915 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_COLUMNS */
6916 static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
6917 {
6918 #define SYS_COLUMN_TABLE_ID 0
6919 {STRUCT_FLD(field_name, "TABLE_ID"),
6920 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6921 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6922 STRUCT_FLD(value, 0),
6923 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6924 STRUCT_FLD(old_name, ""),
6925 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6926
6927 #define SYS_COLUMN_NAME 1
6928 {STRUCT_FLD(field_name, "NAME"),
6929 STRUCT_FLD(field_length, NAME_LEN + 1),
6930 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6931 STRUCT_FLD(value, 0),
6932 STRUCT_FLD(field_flags, 0),
6933 STRUCT_FLD(old_name, ""),
6934 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6935
6936 #define SYS_COLUMN_POSITION 2
6937 {STRUCT_FLD(field_name, "POS"),
6938 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6939 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6940 STRUCT_FLD(value, 0),
6941 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6942 STRUCT_FLD(old_name, ""),
6943 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6944
6945 #define SYS_COLUMN_MTYPE 3
6946 {STRUCT_FLD(field_name, "MTYPE"),
6947 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6948 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6949 STRUCT_FLD(value, 0),
6950 STRUCT_FLD(field_flags, 0),
6951 STRUCT_FLD(old_name, ""),
6952 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6953
6954 #define SYS_COLUMN__PRTYPE 4
6955 {STRUCT_FLD(field_name, "PRTYPE"),
6956 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6957 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6958 STRUCT_FLD(value, 0),
6959 STRUCT_FLD(field_flags, 0),
6960 STRUCT_FLD(old_name, ""),
6961 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6962
6963 #define SYS_COLUMN_COLUMN_LEN 5
6964 {STRUCT_FLD(field_name, "LEN"),
6965 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6966 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6967 STRUCT_FLD(value, 0),
6968 STRUCT_FLD(field_flags, 0),
6969 STRUCT_FLD(old_name, ""),
6970 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6971
6972 END_OF_ST_FIELD_INFO
6973 };
6974
6975 /**********************************************************************//**
6976 Function to populate the information_schema.innodb_sys_columns with
6977 related column information
6978 @return 0 on success */
6979 static
6980 int
i_s_dict_fill_sys_columns(THD * thd,table_id_t table_id,const char * col_name,dict_col_t * column,TABLE * table_to_fill)6981 i_s_dict_fill_sys_columns(
6982 /*======================*/
6983 THD* thd, /*!< in: thread */
6984 table_id_t table_id, /*!< in: table ID */
6985 const char* col_name, /*!< in: column name */
6986 dict_col_t* column, /*!< in: dict_col_t struct holding
6987 more column information */
6988 TABLE* table_to_fill) /*!< in/out: fill this table */
6989 {
6990 Field** fields;
6991
6992 DBUG_ENTER("i_s_dict_fill_sys_columns");
6993
6994 fields = table_to_fill->field;
6995
6996 OK(fields[SYS_COLUMN_TABLE_ID]->store(longlong(table_id), TRUE));
6997
6998 OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
6999
7000 OK(fields[SYS_COLUMN_POSITION]->store(column->ind));
7001
7002 OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
7003
7004 OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
7005
7006 OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
7007
7008 OK(schema_table_store_record(thd, table_to_fill));
7009
7010 DBUG_RETURN(0);
7011 }
7012 /*******************************************************************//**
7013 Function to fill information_schema.innodb_sys_columns with information
7014 collected by scanning SYS_COLUMNS table.
7015 @return 0 on success */
7016 static
7017 int
i_s_sys_columns_fill_table(THD * thd,TABLE_LIST * tables,Item *)7018 i_s_sys_columns_fill_table(
7019 /*=======================*/
7020 THD* thd, /*!< in: thread */
7021 TABLE_LIST* tables, /*!< in/out: tables to fill */
7022 Item* ) /*!< in: condition (not used) */
7023 {
7024 btr_pcur_t pcur;
7025 const rec_t* rec;
7026 const char* col_name;
7027 mem_heap_t* heap;
7028 mtr_t mtr;
7029
7030 DBUG_ENTER("i_s_sys_columns_fill_table");
7031 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7032
7033 /* deny access to user without PROCESS_ACL privilege */
7034 if (check_global_access(thd, PROCESS_ACL)) {
7035 DBUG_RETURN(0);
7036 }
7037
7038 heap = mem_heap_create(1000);
7039 mutex_enter(&dict_sys->mutex);
7040 mtr_start(&mtr);
7041
7042 rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
7043
7044 while (rec) {
7045 const char* err_msg;
7046 dict_col_t column_rec;
7047 table_id_t table_id;
7048
7049 /* populate a dict_col_t structure with information from
7050 a SYS_COLUMNS row */
7051 err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
7052 &table_id, &col_name);
7053
7054 mtr_commit(&mtr);
7055 mutex_exit(&dict_sys->mutex);
7056
7057 if (!err_msg) {
7058 i_s_dict_fill_sys_columns(thd, table_id, col_name,
7059 &column_rec,
7060 tables->table);
7061 } else {
7062 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7063 ER_CANT_FIND_SYSTEM_REC, "%s",
7064 err_msg);
7065 }
7066
7067 mem_heap_empty(heap);
7068
7069 /* Get the next record */
7070 mutex_enter(&dict_sys->mutex);
7071 mtr_start(&mtr);
7072 rec = dict_getnext_system(&pcur, &mtr);
7073 }
7074
7075 mtr_commit(&mtr);
7076 mutex_exit(&dict_sys->mutex);
7077 mem_heap_free(heap);
7078
7079 DBUG_RETURN(0);
7080 }
7081 /*******************************************************************//**
7082 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
7083 @return 0 on success */
7084 static
7085 int
innodb_sys_columns_init(void * p)7086 innodb_sys_columns_init(
7087 /*====================*/
7088 void* p) /*!< in/out: table schema object */
7089 {
7090 ST_SCHEMA_TABLE* schema;
7091
7092 DBUG_ENTER("innodb_sys_columns_init");
7093
7094 schema = (ST_SCHEMA_TABLE*) p;
7095
7096 schema->fields_info = innodb_sys_columns_fields_info;
7097 schema->fill_table = i_s_sys_columns_fill_table;
7098
7099 DBUG_RETURN(0);
7100 }
7101
7102 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns =
7103 {
7104 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7105 /* int */
7106 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7107
7108 /* pointer to type-specific plugin descriptor */
7109 /* void* */
7110 STRUCT_FLD(info, &i_s_info),
7111
7112 /* plugin name */
7113 /* const char* */
7114 STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
7115
7116 /* plugin author (for SHOW PLUGINS) */
7117 /* const char* */
7118 STRUCT_FLD(author, plugin_author),
7119
7120 /* general descriptive text (for SHOW PLUGINS) */
7121 /* const char* */
7122 STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
7123
7124 /* the plugin license (PLUGIN_LICENSE_XXX) */
7125 /* int */
7126 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7127
7128 /* the function to invoke when plugin is loaded */
7129 /* int (*)(void*); */
7130 STRUCT_FLD(init, innodb_sys_columns_init),
7131
7132 /* the function to invoke when plugin is unloaded */
7133 /* int (*)(void*); */
7134 STRUCT_FLD(deinit, i_s_common_deinit),
7135
7136 /* plugin version (for SHOW PLUGINS) */
7137 /* unsigned int */
7138 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7139
7140 /* struct st_mysql_show_var* */
7141 STRUCT_FLD(status_vars, NULL),
7142
7143 /* struct st_mysql_sys_var** */
7144 STRUCT_FLD(system_vars, NULL),
7145
7146 /* reserved for dependency checking */
7147 /* void* */
7148 STRUCT_FLD(__reserved1, NULL),
7149
7150 /* Plugin flags */
7151 /* unsigned long */
7152 STRUCT_FLD(flags, 0UL),
7153 };
7154
7155 /** SYS_FIELDS ***************************************************/
7156 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FIELDS */
7157 static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
7158 {
7159 #define SYS_FIELD_INDEX_ID 0
7160 {STRUCT_FLD(field_name, "INDEX_ID"),
7161 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7162 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7163 STRUCT_FLD(value, 0),
7164 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7165 STRUCT_FLD(old_name, ""),
7166 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7167
7168 #define SYS_FIELD_NAME 1
7169 {STRUCT_FLD(field_name, "NAME"),
7170 STRUCT_FLD(field_length, NAME_LEN + 1),
7171 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7172 STRUCT_FLD(value, 0),
7173 STRUCT_FLD(field_flags, 0),
7174 STRUCT_FLD(old_name, ""),
7175 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7176
7177 #define SYS_FIELD_POS 2
7178 {STRUCT_FLD(field_name, "POS"),
7179 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7180 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7181 STRUCT_FLD(value, 0),
7182 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7183 STRUCT_FLD(old_name, ""),
7184 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7185
7186 END_OF_ST_FIELD_INFO
7187 };
7188
7189 /**********************************************************************//**
7190 Function to fill information_schema.innodb_sys_fields with information
7191 collected by scanning SYS_FIELDS table.
7192 @return 0 on success */
7193 static
7194 int
i_s_dict_fill_sys_fields(THD * thd,index_id_t index_id,dict_field_t * field,ulint pos,TABLE * table_to_fill)7195 i_s_dict_fill_sys_fields(
7196 /*=====================*/
7197 THD* thd, /*!< in: thread */
7198 index_id_t index_id, /*!< in: index id for the field */
7199 dict_field_t* field, /*!< in: table */
7200 ulint pos, /*!< in: Field position */
7201 TABLE* table_to_fill) /*!< in/out: fill this table */
7202 {
7203 Field** fields;
7204
7205 DBUG_ENTER("i_s_dict_fill_sys_fields");
7206
7207 fields = table_to_fill->field;
7208
7209 OK(fields[SYS_FIELD_INDEX_ID]->store(longlong(index_id), TRUE));
7210
7211 OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
7212
7213 OK(fields[SYS_FIELD_POS]->store(static_cast<double>(pos)));
7214
7215 OK(schema_table_store_record(thd, table_to_fill));
7216
7217 DBUG_RETURN(0);
7218 }
7219 /*******************************************************************//**
7220 Function to go through each record in SYS_FIELDS table, and fill the
7221 information_schema.innodb_sys_fields table with related index field
7222 information
7223 @return 0 on success */
7224 static
7225 int
i_s_sys_fields_fill_table(THD * thd,TABLE_LIST * tables,Item *)7226 i_s_sys_fields_fill_table(
7227 /*======================*/
7228 THD* thd, /*!< in: thread */
7229 TABLE_LIST* tables, /*!< in/out: tables to fill */
7230 Item* ) /*!< in: condition (not used) */
7231 {
7232 btr_pcur_t pcur;
7233 const rec_t* rec;
7234 mem_heap_t* heap;
7235 index_id_t last_id;
7236 mtr_t mtr;
7237
7238 DBUG_ENTER("i_s_sys_fields_fill_table");
7239 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7240
7241 /* deny access to user without PROCESS_ACL privilege */
7242 if (check_global_access(thd, PROCESS_ACL)) {
7243
7244 DBUG_RETURN(0);
7245 }
7246
7247 heap = mem_heap_create(1000);
7248 mutex_enter(&dict_sys->mutex);
7249 mtr_start(&mtr);
7250
7251 /* will save last index id so that we know whether we move to
7252 the next index. This is used to calculate prefix length */
7253 last_id = 0;
7254
7255 rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
7256
7257 while (rec) {
7258 ulint pos;
7259 const char* err_msg;
7260 index_id_t index_id;
7261 dict_field_t field_rec;
7262
7263 /* Populate a dict_field_t structure with information from
7264 a SYS_FIELDS row */
7265 err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
7266 &pos, &index_id, last_id);
7267
7268 mtr_commit(&mtr);
7269 mutex_exit(&dict_sys->mutex);
7270
7271 if (!err_msg) {
7272 i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
7273 pos, tables->table);
7274 last_id = index_id;
7275 } else {
7276 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7277 ER_CANT_FIND_SYSTEM_REC, "%s",
7278 err_msg);
7279 }
7280
7281 mem_heap_empty(heap);
7282
7283 /* Get the next record */
7284 mutex_enter(&dict_sys->mutex);
7285 mtr_start(&mtr);
7286 rec = dict_getnext_system(&pcur, &mtr);
7287 }
7288
7289 mtr_commit(&mtr);
7290 mutex_exit(&dict_sys->mutex);
7291 mem_heap_free(heap);
7292
7293 DBUG_RETURN(0);
7294 }
7295 /*******************************************************************//**
7296 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
7297 @return 0 on success */
7298 static
7299 int
innodb_sys_fields_init(void * p)7300 innodb_sys_fields_init(
7301 /*===================*/
7302 void* p) /*!< in/out: table schema object */
7303 {
7304 ST_SCHEMA_TABLE* schema;
7305
7306 DBUG_ENTER("innodb_sys_field_init");
7307
7308 schema = (ST_SCHEMA_TABLE*) p;
7309
7310 schema->fields_info = innodb_sys_fields_fields_info;
7311 schema->fill_table = i_s_sys_fields_fill_table;
7312
7313 DBUG_RETURN(0);
7314 }
7315
7316 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields =
7317 {
7318 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7319 /* int */
7320 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7321
7322 /* pointer to type-specific plugin descriptor */
7323 /* void* */
7324 STRUCT_FLD(info, &i_s_info),
7325
7326 /* plugin name */
7327 /* const char* */
7328 STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
7329
7330 /* plugin author (for SHOW PLUGINS) */
7331 /* const char* */
7332 STRUCT_FLD(author, plugin_author),
7333
7334 /* general descriptive text (for SHOW PLUGINS) */
7335 /* const char* */
7336 STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
7337
7338 /* the plugin license (PLUGIN_LICENSE_XXX) */
7339 /* int */
7340 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7341
7342 /* the function to invoke when plugin is loaded */
7343 /* int (*)(void*); */
7344 STRUCT_FLD(init, innodb_sys_fields_init),
7345
7346 /* the function to invoke when plugin is unloaded */
7347 /* int (*)(void*); */
7348 STRUCT_FLD(deinit, i_s_common_deinit),
7349
7350 /* plugin version (for SHOW PLUGINS) */
7351 /* unsigned int */
7352 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7353
7354 /* struct st_mysql_show_var* */
7355 STRUCT_FLD(status_vars, NULL),
7356
7357 /* struct st_mysql_sys_var** */
7358 STRUCT_FLD(system_vars, NULL),
7359
7360 /* reserved for dependency checking */
7361 /* void* */
7362 STRUCT_FLD(__reserved1, NULL),
7363
7364 /* Plugin flags */
7365 /* unsigned long */
7366 STRUCT_FLD(flags, 0UL),
7367 };
7368
7369 /** SYS_FOREIGN ********************************************/
7370 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN */
7371 static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
7372 {
7373 #define SYS_FOREIGN_ID 0
7374 {STRUCT_FLD(field_name, "ID"),
7375 STRUCT_FLD(field_length, NAME_LEN + 1),
7376 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7377 STRUCT_FLD(value, 0),
7378 STRUCT_FLD(field_flags, 0),
7379 STRUCT_FLD(old_name, ""),
7380 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7381
7382 #define SYS_FOREIGN_FOR_NAME 1
7383 {STRUCT_FLD(field_name, "FOR_NAME"),
7384 STRUCT_FLD(field_length, NAME_LEN + 1),
7385 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7386 STRUCT_FLD(value, 0),
7387 STRUCT_FLD(field_flags, 0),
7388 STRUCT_FLD(old_name, ""),
7389 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7390
7391 #define SYS_FOREIGN_REF_NAME 2
7392 {STRUCT_FLD(field_name, "REF_NAME"),
7393 STRUCT_FLD(field_length, NAME_LEN + 1),
7394 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7395 STRUCT_FLD(value, 0),
7396 STRUCT_FLD(field_flags, 0),
7397 STRUCT_FLD(old_name, ""),
7398 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7399
7400 #define SYS_FOREIGN_NUM_COL 3
7401 {STRUCT_FLD(field_name, "N_COLS"),
7402 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7403 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7404 STRUCT_FLD(value, 0),
7405 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7406 STRUCT_FLD(old_name, ""),
7407 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7408
7409 #define SYS_FOREIGN_TYPE 4
7410 {STRUCT_FLD(field_name, "TYPE"),
7411 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7412 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7413 STRUCT_FLD(value, 0),
7414 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7415 STRUCT_FLD(old_name, ""),
7416 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7417
7418 END_OF_ST_FIELD_INFO
7419 };
7420
7421 /**********************************************************************//**
7422 Function to fill information_schema.innodb_sys_foreign with information
7423 collected by scanning SYS_FOREIGN table.
7424 @return 0 on success */
7425 static
7426 int
i_s_dict_fill_sys_foreign(THD * thd,dict_foreign_t * foreign,TABLE * table_to_fill)7427 i_s_dict_fill_sys_foreign(
7428 /*======================*/
7429 THD* thd, /*!< in: thread */
7430 dict_foreign_t* foreign, /*!< in: table */
7431 TABLE* table_to_fill) /*!< in/out: fill this table */
7432 {
7433 Field** fields;
7434
7435 DBUG_ENTER("i_s_dict_fill_sys_foreign");
7436
7437 fields = table_to_fill->field;
7438
7439 OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
7440
7441 OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
7442 foreign->foreign_table_name));
7443
7444 OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
7445 foreign->referenced_table_name));
7446
7447 OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
7448
7449 OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
7450
7451 OK(schema_table_store_record(thd, table_to_fill));
7452
7453 DBUG_RETURN(0);
7454 }
7455
7456 /*******************************************************************//**
7457 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
7458 through each record in SYS_FOREIGN, and extract the foreign key
7459 information.
7460 @return 0 on success */
7461 static
7462 int
i_s_sys_foreign_fill_table(THD * thd,TABLE_LIST * tables,Item *)7463 i_s_sys_foreign_fill_table(
7464 /*=======================*/
7465 THD* thd, /*!< in: thread */
7466 TABLE_LIST* tables, /*!< in/out: tables to fill */
7467 Item* ) /*!< in: condition (not used) */
7468 {
7469 btr_pcur_t pcur;
7470 const rec_t* rec;
7471 mem_heap_t* heap;
7472 mtr_t mtr;
7473
7474 DBUG_ENTER("i_s_sys_foreign_fill_table");
7475 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7476
7477 /* deny access to user without PROCESS_ACL privilege */
7478 if (check_global_access(thd, PROCESS_ACL)) {
7479
7480 DBUG_RETURN(0);
7481 }
7482
7483 heap = mem_heap_create(1000);
7484 mutex_enter(&dict_sys->mutex);
7485 mtr_start(&mtr);
7486
7487 rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
7488
7489 while (rec) {
7490 const char* err_msg;
7491 dict_foreign_t foreign_rec;
7492
7493 /* Populate a dict_foreign_t structure with information from
7494 a SYS_FOREIGN row */
7495 err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
7496
7497 mtr_commit(&mtr);
7498 mutex_exit(&dict_sys->mutex);
7499
7500 if (!err_msg) {
7501 i_s_dict_fill_sys_foreign(thd, &foreign_rec,
7502 tables->table);
7503 } else {
7504 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7505 ER_CANT_FIND_SYSTEM_REC, "%s",
7506 err_msg);
7507 }
7508
7509 mem_heap_empty(heap);
7510
7511 /* Get the next record */
7512 mtr_start(&mtr);
7513 mutex_enter(&dict_sys->mutex);
7514 rec = dict_getnext_system(&pcur, &mtr);
7515 }
7516
7517 mtr_commit(&mtr);
7518 mutex_exit(&dict_sys->mutex);
7519 mem_heap_free(heap);
7520
7521 DBUG_RETURN(0);
7522 }
7523
7524 /*******************************************************************//**
7525 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
7526 @return 0 on success */
7527 static
7528 int
innodb_sys_foreign_init(void * p)7529 innodb_sys_foreign_init(
7530 /*====================*/
7531 void* p) /*!< in/out: table schema object */
7532 {
7533 ST_SCHEMA_TABLE* schema;
7534
7535 DBUG_ENTER("innodb_sys_foreign_init");
7536
7537 schema = (ST_SCHEMA_TABLE*) p;
7538
7539 schema->fields_info = innodb_sys_foreign_fields_info;
7540 schema->fill_table = i_s_sys_foreign_fill_table;
7541
7542 DBUG_RETURN(0);
7543 }
7544
7545 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign =
7546 {
7547 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7548 /* int */
7549 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7550
7551 /* pointer to type-specific plugin descriptor */
7552 /* void* */
7553 STRUCT_FLD(info, &i_s_info),
7554
7555 /* plugin name */
7556 /* const char* */
7557 STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
7558
7559 /* plugin author (for SHOW PLUGINS) */
7560 /* const char* */
7561 STRUCT_FLD(author, plugin_author),
7562
7563 /* general descriptive text (for SHOW PLUGINS) */
7564 /* const char* */
7565 STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
7566
7567 /* the plugin license (PLUGIN_LICENSE_XXX) */
7568 /* int */
7569 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7570
7571 /* the function to invoke when plugin is loaded */
7572 /* int (*)(void*); */
7573 STRUCT_FLD(init, innodb_sys_foreign_init),
7574
7575 /* the function to invoke when plugin is unloaded */
7576 /* int (*)(void*); */
7577 STRUCT_FLD(deinit, i_s_common_deinit),
7578
7579 /* plugin version (for SHOW PLUGINS) */
7580 /* unsigned int */
7581 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7582
7583 /* struct st_mysql_show_var* */
7584 STRUCT_FLD(status_vars, NULL),
7585
7586 /* struct st_mysql_sys_var** */
7587 STRUCT_FLD(system_vars, NULL),
7588
7589 /* reserved for dependency checking */
7590 /* void* */
7591 STRUCT_FLD(__reserved1, NULL),
7592
7593 /* Plugin flags */
7594 /* unsigned long */
7595 STRUCT_FLD(flags, 0UL),
7596 };
7597
7598 /** SYS_FOREIGN_COLS ********************************************/
7599 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS */
7600 static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
7601 {
7602 #define SYS_FOREIGN_COL_ID 0
7603 {STRUCT_FLD(field_name, "ID"),
7604 STRUCT_FLD(field_length, NAME_LEN + 1),
7605 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7606 STRUCT_FLD(value, 0),
7607 STRUCT_FLD(field_flags, 0),
7608 STRUCT_FLD(old_name, ""),
7609 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7610
7611 #define SYS_FOREIGN_COL_FOR_NAME 1
7612 {STRUCT_FLD(field_name, "FOR_COL_NAME"),
7613 STRUCT_FLD(field_length, NAME_LEN + 1),
7614 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7615 STRUCT_FLD(value, 0),
7616 STRUCT_FLD(field_flags, 0),
7617 STRUCT_FLD(old_name, ""),
7618 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7619
7620 #define SYS_FOREIGN_COL_REF_NAME 2
7621 {STRUCT_FLD(field_name, "REF_COL_NAME"),
7622 STRUCT_FLD(field_length, NAME_LEN + 1),
7623 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7624 STRUCT_FLD(value, 0),
7625 STRUCT_FLD(field_flags, 0),
7626 STRUCT_FLD(old_name, ""),
7627 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7628
7629 #define SYS_FOREIGN_COL_POS 3
7630 {STRUCT_FLD(field_name, "POS"),
7631 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7632 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7633 STRUCT_FLD(value, 0),
7634 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7635 STRUCT_FLD(old_name, ""),
7636 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7637
7638 END_OF_ST_FIELD_INFO
7639 };
7640
7641 /**********************************************************************//**
7642 Function to fill information_schema.innodb_sys_foreign_cols with information
7643 collected by scanning SYS_FOREIGN_COLS table.
7644 @return 0 on success */
7645 static
7646 int
i_s_dict_fill_sys_foreign_cols(THD * thd,const char * name,const char * for_col_name,const char * ref_col_name,ulint pos,TABLE * table_to_fill)7647 i_s_dict_fill_sys_foreign_cols(
7648 /*==========================*/
7649 THD* thd, /*!< in: thread */
7650 const char* name, /*!< in: foreign key constraint name */
7651 const char* for_col_name, /*!< in: referencing column name*/
7652 const char* ref_col_name, /*!< in: referenced column
7653 name */
7654 ulint pos, /*!< in: column position */
7655 TABLE* table_to_fill) /*!< in/out: fill this table */
7656 {
7657 Field** fields;
7658
7659 DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
7660
7661 fields = table_to_fill->field;
7662
7663 OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
7664
7665 OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
7666
7667 OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
7668
7669 OK(fields[SYS_FOREIGN_COL_POS]->store(static_cast<double>(pos)));
7670
7671 OK(schema_table_store_record(thd, table_to_fill));
7672
7673 DBUG_RETURN(0);
7674 }
7675 /*******************************************************************//**
7676 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
7677 through each record in SYS_FOREIGN_COLS, and extract the foreign key column
7678 information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
7679 @return 0 on success */
7680 static
7681 int
i_s_sys_foreign_cols_fill_table(THD * thd,TABLE_LIST * tables,Item *)7682 i_s_sys_foreign_cols_fill_table(
7683 /*============================*/
7684 THD* thd, /*!< in: thread */
7685 TABLE_LIST* tables, /*!< in/out: tables to fill */
7686 Item* ) /*!< in: condition (not used) */
7687 {
7688 btr_pcur_t pcur;
7689 const rec_t* rec;
7690 mem_heap_t* heap;
7691 mtr_t mtr;
7692
7693 DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
7694 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7695
7696 /* deny access to user without PROCESS_ACL privilege */
7697 if (check_global_access(thd, PROCESS_ACL)) {
7698 DBUG_RETURN(0);
7699 }
7700
7701 heap = mem_heap_create(1000);
7702 mutex_enter(&dict_sys->mutex);
7703 mtr_start(&mtr);
7704
7705 rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
7706
7707 while (rec) {
7708 const char* err_msg;
7709 const char* name;
7710 const char* for_col_name;
7711 const char* ref_col_name;
7712 ulint pos;
7713
7714 /* Extract necessary information from a SYS_FOREIGN_COLS row */
7715 err_msg = dict_process_sys_foreign_col_rec(
7716 heap, rec, &name, &for_col_name, &ref_col_name, &pos);
7717
7718 mtr_commit(&mtr);
7719 mutex_exit(&dict_sys->mutex);
7720
7721 if (!err_msg) {
7722 i_s_dict_fill_sys_foreign_cols(
7723 thd, name, for_col_name, ref_col_name, pos,
7724 tables->table);
7725 } else {
7726 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7727 ER_CANT_FIND_SYSTEM_REC, "%s",
7728 err_msg);
7729 }
7730
7731 mem_heap_empty(heap);
7732
7733 /* Get the next record */
7734 mutex_enter(&dict_sys->mutex);
7735 mtr_start(&mtr);
7736 rec = dict_getnext_system(&pcur, &mtr);
7737 }
7738
7739 mtr_commit(&mtr);
7740 mutex_exit(&dict_sys->mutex);
7741 mem_heap_free(heap);
7742
7743 DBUG_RETURN(0);
7744 }
7745 /*******************************************************************//**
7746 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
7747 @return 0 on success */
7748 static
7749 int
innodb_sys_foreign_cols_init(void * p)7750 innodb_sys_foreign_cols_init(
7751 /*========================*/
7752 void* p) /*!< in/out: table schema object */
7753 {
7754 ST_SCHEMA_TABLE* schema;
7755
7756 DBUG_ENTER("innodb_sys_foreign_cols_init");
7757
7758 schema = (ST_SCHEMA_TABLE*) p;
7759
7760 schema->fields_info = innodb_sys_foreign_cols_fields_info;
7761 schema->fill_table = i_s_sys_foreign_cols_fill_table;
7762
7763 DBUG_RETURN(0);
7764 }
7765
7766 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols =
7767 {
7768 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7769 /* int */
7770 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7771
7772 /* pointer to type-specific plugin descriptor */
7773 /* void* */
7774 STRUCT_FLD(info, &i_s_info),
7775
7776 /* plugin name */
7777 /* const char* */
7778 STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
7779
7780 /* plugin author (for SHOW PLUGINS) */
7781 /* const char* */
7782 STRUCT_FLD(author, plugin_author),
7783
7784 /* general descriptive text (for SHOW PLUGINS) */
7785 /* const char* */
7786 STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
7787
7788 /* the plugin license (PLUGIN_LICENSE_XXX) */
7789 /* int */
7790 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7791
7792 /* the function to invoke when plugin is loaded */
7793 /* int (*)(void*); */
7794 STRUCT_FLD(init, innodb_sys_foreign_cols_init),
7795
7796 /* the function to invoke when plugin is unloaded */
7797 /* int (*)(void*); */
7798 STRUCT_FLD(deinit, i_s_common_deinit),
7799
7800 /* plugin version (for SHOW PLUGINS) */
7801 /* unsigned int */
7802 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7803
7804 /* struct st_mysql_show_var* */
7805 STRUCT_FLD(status_vars, NULL),
7806
7807 /* struct st_mysql_sys_var** */
7808 STRUCT_FLD(system_vars, NULL),
7809
7810 /* reserved for dependency checking */
7811 /* void* */
7812 STRUCT_FLD(__reserved1, NULL),
7813
7814 /* Plugin flags */
7815 /* unsigned long */
7816 STRUCT_FLD(flags, 0UL),
7817 };
7818
7819 /** SYS_TABLESPACES ********************************************/
7820 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES */
7821 static ST_FIELD_INFO innodb_sys_tablespaces_fields_info[] =
7822 {
7823 #define SYS_TABLESPACES_SPACE 0
7824 {STRUCT_FLD(field_name, "SPACE"),
7825 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7826 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7827 STRUCT_FLD(value, 0),
7828 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7829 STRUCT_FLD(old_name, ""),
7830 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7831
7832 #define SYS_TABLESPACES_NAME 1
7833 {STRUCT_FLD(field_name, "NAME"),
7834 STRUCT_FLD(field_length, MAX_FULL_NAME_LEN + 1),
7835 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7836 STRUCT_FLD(value, 0),
7837 STRUCT_FLD(field_flags, 0),
7838 STRUCT_FLD(old_name, ""),
7839 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7840
7841 #define SYS_TABLESPACES_FLAGS 2
7842 {STRUCT_FLD(field_name, "FLAG"),
7843 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7844 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7845 STRUCT_FLD(value, 0),
7846 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7847 STRUCT_FLD(old_name, ""),
7848 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7849
7850 #define SYS_TABLESPACES_FILE_FORMAT 3
7851 {STRUCT_FLD(field_name, "FILE_FORMAT"),
7852 STRUCT_FLD(field_length, 10),
7853 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7854 STRUCT_FLD(value, 0),
7855 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
7856 STRUCT_FLD(old_name, ""),
7857 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7858
7859 #define SYS_TABLESPACES_ROW_FORMAT 4
7860 {STRUCT_FLD(field_name, "ROW_FORMAT"),
7861 STRUCT_FLD(field_length, 22),
7862 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7863 STRUCT_FLD(value, 0),
7864 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
7865 STRUCT_FLD(old_name, ""),
7866 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7867
7868 #define SYS_TABLESPACES_PAGE_SIZE 5
7869 {STRUCT_FLD(field_name, "PAGE_SIZE"),
7870 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7871 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7872 STRUCT_FLD(value, 0),
7873 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7874 STRUCT_FLD(old_name, ""),
7875 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7876
7877 #define SYS_TABLESPACES_ZIP_PAGE_SIZE 6
7878 {STRUCT_FLD(field_name, "ZIP_PAGE_SIZE"),
7879 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7880 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7881 STRUCT_FLD(value, 0),
7882 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7883 STRUCT_FLD(old_name, ""),
7884 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7885
7886 END_OF_ST_FIELD_INFO
7887
7888 };
7889
7890 /**********************************************************************//**
7891 Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information
7892 collected by scanning SYS_TABLESPACESS table.
7893 @return 0 on success */
7894 static
7895 int
i_s_dict_fill_sys_tablespaces(THD * thd,ulint space,const char * name,ulint flags,TABLE * table_to_fill)7896 i_s_dict_fill_sys_tablespaces(
7897 /*==========================*/
7898 THD* thd, /*!< in: thread */
7899 ulint space, /*!< in: space ID */
7900 const char* name, /*!< in: tablespace name */
7901 ulint flags, /*!< in: tablespace flags */
7902 TABLE* table_to_fill) /*!< in/out: fill this table */
7903 {
7904 Field** fields;
7905 ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
7906 ulint page_size = fsp_flags_get_page_size(flags);;
7907 ulint zip_size = fsp_flags_get_zip_size(flags);
7908 const char* file_format;
7909 const char* row_format;
7910
7911 DBUG_ENTER("i_s_dict_fill_sys_tablespaces");
7912
7913 file_format = trx_sys_file_format_id_to_name(atomic_blobs);
7914 if (!atomic_blobs) {
7915 row_format = "Compact or Redundant";
7916 } else if DICT_TF_GET_ZIP_SSIZE(flags) {
7917 row_format = "Compressed";
7918 } else {
7919 row_format = "Dynamic";
7920 }
7921
7922 fields = table_to_fill->field;
7923
7924 OK(fields[SYS_TABLESPACES_SPACE]->store(
7925 static_cast<double>(space)));
7926
7927 OK(field_store_string(fields[SYS_TABLESPACES_NAME], name));
7928
7929 OK(fields[SYS_TABLESPACES_FLAGS]->store(
7930 static_cast<double>(flags)));
7931
7932 OK(field_store_string(fields[SYS_TABLESPACES_FILE_FORMAT],
7933 file_format));
7934
7935 OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT],
7936 row_format));
7937
7938 OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
7939 static_cast<double>(page_size)));
7940
7941 OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
7942 static_cast<double>(zip_size)));
7943
7944 OK(schema_table_store_record(thd, table_to_fill));
7945
7946 DBUG_RETURN(0);
7947 }
7948 /*******************************************************************//**
7949 Function to populate INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
7950 Loop through each record in SYS_TABLESPACES, and extract the column
7951 information and fill the INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
7952 @return 0 on success */
7953 static
7954 int
i_s_sys_tablespaces_fill_table(THD * thd,TABLE_LIST * tables,Item *)7955 i_s_sys_tablespaces_fill_table(
7956 /*===========================*/
7957 THD* thd, /*!< in: thread */
7958 TABLE_LIST* tables, /*!< in/out: tables to fill */
7959 Item* ) /*!< in: condition (not used) */
7960 {
7961 btr_pcur_t pcur;
7962 const rec_t* rec;
7963 mem_heap_t* heap;
7964 mtr_t mtr;
7965
7966 DBUG_ENTER("i_s_sys_tablespaces_fill_table");
7967 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7968
7969 /* deny access to user without PROCESS_ACL privilege */
7970 if (check_global_access(thd, PROCESS_ACL)) {
7971 DBUG_RETURN(0);
7972 }
7973
7974 heap = mem_heap_create(1000);
7975 mutex_enter(&dict_sys->mutex);
7976 mtr_start(&mtr);
7977
7978 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
7979
7980 while (rec) {
7981 const char* err_msg;
7982 ulint space;
7983 const char* name;
7984 ulint flags;
7985
7986 /* Extract necessary information from a SYS_TABLESPACES row */
7987 err_msg = dict_process_sys_tablespaces(
7988 heap, rec, &space, &name, &flags);
7989
7990 mtr_commit(&mtr);
7991 mutex_exit(&dict_sys->mutex);
7992
7993 if (!err_msg) {
7994 i_s_dict_fill_sys_tablespaces(
7995 thd, space, name, flags,
7996 tables->table);
7997 } else {
7998 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7999 ER_CANT_FIND_SYSTEM_REC, "%s",
8000 err_msg);
8001 }
8002
8003 mem_heap_empty(heap);
8004
8005 /* Get the next record */
8006 mutex_enter(&dict_sys->mutex);
8007 mtr_start(&mtr);
8008 rec = dict_getnext_system(&pcur, &mtr);
8009 }
8010
8011 mtr_commit(&mtr);
8012 mutex_exit(&dict_sys->mutex);
8013 mem_heap_free(heap);
8014
8015 DBUG_RETURN(0);
8016 }
8017 /*******************************************************************//**
8018 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
8019 @return 0 on success */
8020 static
8021 int
innodb_sys_tablespaces_init(void * p)8022 innodb_sys_tablespaces_init(
8023 /*========================*/
8024 void* p) /*!< in/out: table schema object */
8025 {
8026 ST_SCHEMA_TABLE* schema;
8027
8028 DBUG_ENTER("innodb_sys_tablespaces_init");
8029
8030 schema = (ST_SCHEMA_TABLE*) p;
8031
8032 schema->fields_info = innodb_sys_tablespaces_fields_info;
8033 schema->fill_table = i_s_sys_tablespaces_fill_table;
8034
8035 DBUG_RETURN(0);
8036 }
8037
8038 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablespaces =
8039 {
8040 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8041 /* int */
8042 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8043
8044 /* pointer to type-specific plugin descriptor */
8045 /* void* */
8046 STRUCT_FLD(info, &i_s_info),
8047
8048 /* plugin name */
8049 /* const char* */
8050 STRUCT_FLD(name, "INNODB_SYS_TABLESPACES"),
8051
8052 /* plugin author (for SHOW PLUGINS) */
8053 /* const char* */
8054 STRUCT_FLD(author, plugin_author),
8055
8056 /* general descriptive text (for SHOW PLUGINS) */
8057 /* const char* */
8058 STRUCT_FLD(descr, "InnoDB SYS_TABLESPACES"),
8059
8060 /* the plugin license (PLUGIN_LICENSE_XXX) */
8061 /* int */
8062 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8063
8064 /* the function to invoke when plugin is loaded */
8065 /* int (*)(void*); */
8066 STRUCT_FLD(init, innodb_sys_tablespaces_init),
8067
8068 /* the function to invoke when plugin is unloaded */
8069 /* int (*)(void*); */
8070 STRUCT_FLD(deinit, i_s_common_deinit),
8071
8072 /* plugin version (for SHOW PLUGINS) */
8073 /* unsigned int */
8074 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8075
8076 /* struct st_mysql_show_var* */
8077 STRUCT_FLD(status_vars, NULL),
8078
8079 /* struct st_mysql_sys_var** */
8080 STRUCT_FLD(system_vars, NULL),
8081
8082 /* reserved for dependency checking */
8083 /* void* */
8084 STRUCT_FLD(__reserved1, NULL),
8085
8086 /* Plugin flags */
8087 /* unsigned long */
8088 STRUCT_FLD(flags, 0UL),
8089 };
8090
8091 /** SYS_DATAFILES ************************************************/
8092 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES */
8093 static ST_FIELD_INFO innodb_sys_datafiles_fields_info[] =
8094 {
8095 #define SYS_DATAFILES_SPACE 0
8096 {STRUCT_FLD(field_name, "SPACE"),
8097 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8098 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8099 STRUCT_FLD(value, 0),
8100 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8101 STRUCT_FLD(old_name, ""),
8102 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8103
8104 #define SYS_DATAFILES_PATH 1
8105 {STRUCT_FLD(field_name, "PATH"),
8106 STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
8107 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8108 STRUCT_FLD(value, 0),
8109 STRUCT_FLD(field_flags, 0),
8110 STRUCT_FLD(old_name, ""),
8111 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8112
8113 END_OF_ST_FIELD_INFO
8114 };
8115
8116 /**********************************************************************//**
8117 Function to fill INFORMATION_SCHEMA.INNODB_SYS_DATAFILES with information
8118 collected by scanning SYS_DATAFILESS table.
8119 @return 0 on success */
8120 static
8121 int
i_s_dict_fill_sys_datafiles(THD * thd,ulint space,const char * path,TABLE * table_to_fill)8122 i_s_dict_fill_sys_datafiles(
8123 /*========================*/
8124 THD* thd, /*!< in: thread */
8125 ulint space, /*!< in: space ID */
8126 const char* path, /*!< in: absolute path */
8127 TABLE* table_to_fill) /*!< in/out: fill this table */
8128 {
8129 Field** fields;
8130
8131 DBUG_ENTER("i_s_dict_fill_sys_datafiles");
8132
8133 fields = table_to_fill->field;
8134
8135 OK(field_store_ulint(fields[SYS_DATAFILES_SPACE], space));
8136
8137 OK(field_store_string(fields[SYS_DATAFILES_PATH], path));
8138
8139 OK(schema_table_store_record(thd, table_to_fill));
8140
8141 DBUG_RETURN(0);
8142 }
8143 /*******************************************************************//**
8144 Function to populate INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8145 Loop through each record in SYS_DATAFILES, and extract the column
8146 information and fill the INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8147 @return 0 on success */
8148 static
8149 int
i_s_sys_datafiles_fill_table(THD * thd,TABLE_LIST * tables,Item *)8150 i_s_sys_datafiles_fill_table(
8151 /*=========================*/
8152 THD* thd, /*!< in: thread */
8153 TABLE_LIST* tables, /*!< in/out: tables to fill */
8154 Item* ) /*!< in: condition (not used) */
8155 {
8156 btr_pcur_t pcur;
8157 const rec_t* rec;
8158 mem_heap_t* heap;
8159 mtr_t mtr;
8160
8161 DBUG_ENTER("i_s_sys_datafiles_fill_table");
8162 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8163
8164 /* deny access to user without PROCESS_ACL privilege */
8165 if (check_global_access(thd, PROCESS_ACL)) {
8166 DBUG_RETURN(0);
8167 }
8168
8169 heap = mem_heap_create(1000);
8170 mutex_enter(&dict_sys->mutex);
8171 mtr_start(&mtr);
8172
8173 rec = dict_startscan_system(&pcur, &mtr, SYS_DATAFILES);
8174
8175 while (rec) {
8176 const char* err_msg;
8177 ulint space;
8178 const char* path;
8179
8180 /* Extract necessary information from a SYS_DATAFILES row */
8181 err_msg = dict_process_sys_datafiles(
8182 heap, rec, &space, &path);
8183
8184 mtr_commit(&mtr);
8185 mutex_exit(&dict_sys->mutex);
8186
8187 if (!err_msg) {
8188 i_s_dict_fill_sys_datafiles(
8189 thd, space, path, tables->table);
8190 } else {
8191 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
8192 ER_CANT_FIND_SYSTEM_REC, "%s",
8193 err_msg);
8194 }
8195
8196 mem_heap_empty(heap);
8197
8198 /* Get the next record */
8199 mutex_enter(&dict_sys->mutex);
8200 mtr_start(&mtr);
8201 rec = dict_getnext_system(&pcur, &mtr);
8202 }
8203
8204 mtr_commit(&mtr);
8205 mutex_exit(&dict_sys->mutex);
8206 mem_heap_free(heap);
8207
8208 DBUG_RETURN(0);
8209 }
8210 /*******************************************************************//**
8211 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES
8212 @return 0 on success */
8213 static
8214 int
innodb_sys_datafiles_init(void * p)8215 innodb_sys_datafiles_init(
8216 /*======================*/
8217 void* p) /*!< in/out: table schema object */
8218 {
8219 ST_SCHEMA_TABLE* schema;
8220
8221 DBUG_ENTER("innodb_sys_datafiles_init");
8222
8223 schema = (ST_SCHEMA_TABLE*) p;
8224
8225 schema->fields_info = innodb_sys_datafiles_fields_info;
8226 schema->fill_table = i_s_sys_datafiles_fill_table;
8227
8228 DBUG_RETURN(0);
8229 }
8230
8231 UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_datafiles =
8232 {
8233 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8234 /* int */
8235 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8236
8237 /* pointer to type-specific plugin descriptor */
8238 /* void* */
8239 STRUCT_FLD(info, &i_s_info),
8240
8241 /* plugin name */
8242 /* const char* */
8243 STRUCT_FLD(name, "INNODB_SYS_DATAFILES"),
8244
8245 /* plugin author (for SHOW PLUGINS) */
8246 /* const char* */
8247 STRUCT_FLD(author, plugin_author),
8248
8249 /* general descriptive text (for SHOW PLUGINS) */
8250 /* const char* */
8251 STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
8252
8253 /* the plugin license (PLUGIN_LICENSE_XXX) */
8254 /* int */
8255 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8256
8257 /* the function to invoke when plugin is loaded */
8258 /* int (*)(void*); */
8259 STRUCT_FLD(init, innodb_sys_datafiles_init),
8260
8261 /* the function to invoke when plugin is unloaded */
8262 /* int (*)(void*); */
8263 STRUCT_FLD(deinit, i_s_common_deinit),
8264
8265 /* plugin version (for SHOW PLUGINS) */
8266 /* unsigned int */
8267 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8268
8269 /* struct st_mysql_show_var* */
8270 STRUCT_FLD(status_vars, NULL),
8271
8272 /* struct st_mysql_sys_var** */
8273 STRUCT_FLD(system_vars, NULL),
8274
8275 /* reserved for dependency checking */
8276 /* void* */
8277 STRUCT_FLD(__reserved1, NULL),
8278
8279 /* Plugin flags */
8280 /* unsigned long */
8281 STRUCT_FLD(flags, 0UL),
8282 };
8283