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