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