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