1 /*****************************************************************************
2
3 Copyright (c) 2007, 2020, Oracle and/or its affiliates. All Rights Reserved.
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 for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) {
3476 fts_index_cache_t* index_cache;
3477
3478 index_cache = static_cast<fts_index_cache_t*> (
3479 ib_vector_get(cache->indexes, i));
3480
3481 i_s_fts_index_cache_fill_one_index(index_cache, thd, tables);
3482 }
3483
3484 dict_table_close(user_table, FALSE, FALSE);
3485
3486 DBUG_RETURN(0);
3487 }
3488
3489 /*******************************************************************//**
3490 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
3491 @return 0 on success */
3492 static
3493 int
i_s_fts_index_cache_init(void * p)3494 i_s_fts_index_cache_init(
3495 /*=====================*/
3496 void* p) /*!< in/out: table schema object */
3497 {
3498 DBUG_ENTER("i_s_fts_index_cache_init");
3499 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3500
3501 schema->fields_info = i_s_fts_index_fields_info;
3502 schema->fill_table = i_s_fts_index_cache_fill;
3503
3504 DBUG_RETURN(0);
3505 }
3506
3507 struct st_mysql_plugin i_s_innodb_ft_index_cache =
3508 {
3509 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3510 /* int */
3511 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3512
3513 /* pointer to type-specific plugin descriptor */
3514 /* void* */
3515 STRUCT_FLD(info, &i_s_info),
3516
3517 /* plugin name */
3518 /* const char* */
3519 STRUCT_FLD(name, "INNODB_FT_INDEX_CACHE"),
3520
3521 /* plugin author (for SHOW PLUGINS) */
3522 /* const char* */
3523 STRUCT_FLD(author, plugin_author),
3524
3525 /* general descriptive text (for SHOW PLUGINS) */
3526 /* const char* */
3527 STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX CACHED"),
3528
3529 /* the plugin license (PLUGIN_LICENSE_XXX) */
3530 /* int */
3531 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3532
3533 /* the function to invoke when plugin is loaded */
3534 /* int (*)(void*); */
3535 STRUCT_FLD(init, i_s_fts_index_cache_init),
3536
3537 /* the function to invoke when plugin is unloaded */
3538 /* int (*)(void*); */
3539 STRUCT_FLD(deinit, i_s_common_deinit),
3540
3541 /* plugin version (for SHOW PLUGINS) */
3542 /* unsigned int */
3543 STRUCT_FLD(version, INNODB_VERSION_SHORT),
3544
3545 /* struct st_mysql_show_var* */
3546 STRUCT_FLD(status_vars, NULL),
3547
3548 /* struct st_mysql_sys_var** */
3549 STRUCT_FLD(system_vars, NULL),
3550
3551 /* reserved for dependency checking */
3552 /* void* */
3553 STRUCT_FLD(__reserved1, NULL),
3554
3555 /* Plugin flags */
3556 /* unsigned long */
3557 STRUCT_FLD(flags, 0UL),
3558 };
3559
3560 /*******************************************************************//**
3561 Go through a FTS index auxiliary table, fetch its rows and fill
3562 FTS word cache structure.
3563 @return DB_SUCCESS on success, otherwise error code */
3564 static
3565 dberr_t
i_s_fts_index_table_fill_selected(dict_index_t * index,ib_vector_t * words,ulint selected,fts_string_t * word)3566 i_s_fts_index_table_fill_selected(
3567 /*==============================*/
3568 dict_index_t* index, /*!< in: FTS index */
3569 ib_vector_t* words, /*!< in/out: vector to hold
3570 fetched words */
3571 ulint selected, /*!< in: selected FTS index */
3572 fts_string_t* word) /*!< in: word to select */
3573 {
3574 pars_info_t* info;
3575 fts_table_t fts_table;
3576 trx_t* trx;
3577 que_t* graph;
3578 dberr_t error;
3579 fts_fetch_t fetch;
3580 char table_name[MAX_FULL_NAME_LEN];
3581
3582 info = pars_info_create();
3583
3584 fetch.read_arg = words;
3585 fetch.read_record = fts_optimize_index_fetch_node;
3586 fetch.total_memory = 0;
3587
3588 DBUG_EXECUTE_IF("fts_instrument_result_cache_limit",
3589 fts_result_cache_limit = 8192;
3590 );
3591
3592 trx = trx_allocate_for_background();
3593
3594 trx->op_info = "fetching FTS index nodes";
3595
3596 pars_info_bind_function(info, "my_func", fetch.read_record, &fetch);
3597 pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
3598
3599 FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
3600 FTS_INDEX_TABLE, index);
3601 fts_get_table_name(&fts_table, table_name);
3602 pars_info_bind_id(info, true, "table_name", table_name);
3603
3604 graph = fts_parse_sql(
3605 &fts_table, info,
3606 "DECLARE FUNCTION my_func;\n"
3607 "DECLARE CURSOR c IS"
3608 " SELECT word, doc_count, first_doc_id, last_doc_id,"
3609 " ilist\n"
3610 " FROM $table_name WHERE word >= :word;\n"
3611 "BEGIN\n"
3612 "\n"
3613 "OPEN c;\n"
3614 "WHILE 1 = 1 LOOP\n"
3615 " FETCH c INTO my_func();\n"
3616 " IF c % NOTFOUND THEN\n"
3617 " EXIT;\n"
3618 " END IF;\n"
3619 "END LOOP;\n"
3620 "CLOSE c;");
3621
3622 for (;;) {
3623 error = fts_eval_sql(trx, graph);
3624
3625 if (error == DB_SUCCESS) {
3626 fts_sql_commit(trx);
3627
3628 break;
3629 } else {
3630 fts_sql_rollback(trx);
3631
3632 if (error == DB_LOCK_WAIT_TIMEOUT) {
3633 ib::warn() << "Lock wait timeout reading"
3634 " FTS index. Retrying!";
3635
3636 trx->error_state = DB_SUCCESS;
3637 } else {
3638 ib::error() << "Error occurred while reading"
3639 " FTS index: " << ut_strerr(error);
3640 break;
3641 }
3642 }
3643 }
3644
3645 mutex_enter(&dict_sys->mutex);
3646 que_graph_free(graph);
3647 mutex_exit(&dict_sys->mutex);
3648
3649 trx_free_for_background(trx);
3650
3651 if (fetch.total_memory >= fts_result_cache_limit) {
3652 error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
3653 }
3654
3655 return(error);
3656 }
3657
3658 /*******************************************************************//**
3659 Free words. */
3660 static
3661 void
i_s_fts_index_table_free_one_fetch(ib_vector_t * words)3662 i_s_fts_index_table_free_one_fetch(
3663 /*===============================*/
3664 ib_vector_t* words) /*!< in: words fetched */
3665 {
3666 for (ulint i = 0; i < ib_vector_size(words); i++) {
3667 fts_word_t* word;
3668
3669 word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3670
3671 for (ulint j = 0; j < ib_vector_size(word->nodes); j++) {
3672 fts_node_t* node;
3673
3674 node = static_cast<fts_node_t*> (ib_vector_get(
3675 word->nodes, j));
3676 ut_free(node->ilist);
3677 }
3678
3679 fts_word_free(word);
3680 }
3681
3682 ib_vector_reset(words);
3683 }
3684
3685 /*******************************************************************//**
3686 Go through words, fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3687 @return 0 on success, 1 on failure */
3688 static
3689 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)3690 i_s_fts_index_table_fill_one_fetch(
3691 /*===============================*/
3692 CHARSET_INFO* index_charset, /*!< in: FTS index charset */
3693 THD* thd, /*!< in: thread */
3694 TABLE_LIST* tables, /*!< in/out: tables to fill */
3695 ib_vector_t* words, /*!< in: words fetched */
3696 fts_string_t* conv_str, /*!< in: string for conversion*/
3697 bool has_more) /*!< in: has more to fetch */
3698 {
3699 TABLE* table = (TABLE*) tables->table;
3700 Field** fields;
3701 uint dummy_errors;
3702 char* word_str;
3703 ulint words_size;
3704 int ret = 0;
3705
3706 DBUG_ENTER("i_s_fts_index_table_fill_one_fetch");
3707
3708 fields = table->field;
3709
3710 words_size = ib_vector_size(words);
3711 if (has_more) {
3712 /* the last word is not fetched completely. */
3713 ut_ad(words_size > 1);
3714 words_size -= 1;
3715 }
3716
3717 /* Go through each word in the index cache */
3718 for (ulint i = 0; i < words_size; i++) {
3719 fts_word_t* word;
3720
3721 word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3722
3723 word->text.f_str[word->text.f_len] = 0;
3724
3725 /* Convert word from index charset to system_charset_info */
3726 if (index_charset->cset != system_charset_info->cset) {
3727 conv_str->f_n_char = my_convert(
3728 reinterpret_cast<char*>(conv_str->f_str),
3729 static_cast<uint32>(conv_str->f_len),
3730 system_charset_info,
3731 reinterpret_cast<char*>(word->text.f_str),
3732 static_cast<uint32>(word->text.f_len),
3733 index_charset, &dummy_errors);
3734 ut_ad(conv_str->f_n_char <= conv_str->f_len);
3735 conv_str->f_str[conv_str->f_n_char] = 0;
3736 word_str = reinterpret_cast<char*>(conv_str->f_str);
3737 } else {
3738 word_str = reinterpret_cast<char*>(word->text.f_str);
3739 }
3740
3741 /* Decrypt the ilist, and display Dod ID and word position */
3742 for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3743 fts_node_t* node;
3744 byte* ptr;
3745 ulint decoded = 0;
3746 doc_id_t doc_id = 0;
3747
3748 node = static_cast<fts_node_t*> (ib_vector_get(
3749 word->nodes, i));
3750
3751 ptr = node->ilist;
3752
3753 while (decoded < node->ilist_size) {
3754 ulint pos = fts_decode_vlc(&ptr);
3755
3756 doc_id += pos;
3757
3758 /* Get position info */
3759 while (*ptr) {
3760 pos = fts_decode_vlc(&ptr);
3761
3762 OK(field_store_string(
3763 fields[I_S_FTS_WORD],
3764 word_str));
3765
3766 OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3767 node->first_doc_id, true));
3768
3769 OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3770 node->last_doc_id, true));
3771
3772 OK(fields[I_S_FTS_DOC_COUNT]->store(
3773 node->doc_count, true));
3774
3775 OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3776 doc_id, true));
3777
3778 OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3779 pos, true));
3780
3781 OK(schema_table_store_record(
3782 thd, table));
3783 }
3784
3785 ++ptr;
3786
3787 decoded = ptr - (byte*) node->ilist;
3788 }
3789 }
3790 }
3791
3792 i_s_fts_index_table_free_one_fetch(words);
3793
3794 DBUG_RETURN(ret);
3795 }
3796
3797 /*******************************************************************//**
3798 Go through a FTS index and its auxiliary tables, fetch rows in each table
3799 and fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3800 @return 0 on success, 1 on failure */
3801 static
3802 int
i_s_fts_index_table_fill_one_index(dict_index_t * index,THD * thd,TABLE_LIST * tables)3803 i_s_fts_index_table_fill_one_index(
3804 /*===============================*/
3805 dict_index_t* index, /*!< in: FTS index */
3806 THD* thd, /*!< in: thread */
3807 TABLE_LIST* tables) /*!< in/out: tables to fill */
3808 {
3809 ib_vector_t* words;
3810 mem_heap_t* heap;
3811 CHARSET_INFO* index_charset;
3812 fts_string_t conv_str;
3813 dberr_t error;
3814 int ret = 0;
3815
3816 DBUG_ENTER("i_s_fts_index_table_fill_one_index");
3817 DBUG_ASSERT(!dict_index_is_online_ddl(index));
3818
3819 heap = mem_heap_create(1024);
3820
3821 words = ib_vector_create(ib_heap_allocator_create(heap),
3822 sizeof(fts_word_t), 256);
3823
3824 index_charset = fts_index_get_charset(index);
3825 conv_str.f_len = system_charset_info->mbmaxlen
3826 * FTS_MAX_WORD_LEN_IN_CHAR;
3827 conv_str.f_str = static_cast<byte*>(ut_malloc_nokey(conv_str.f_len));
3828 conv_str.f_n_char = 0;
3829
3830 /* Iterate through each auxiliary table as described in
3831 fts_index_selector */
3832 for (ulint selected = 0; selected < FTS_NUM_AUX_INDEX; selected++) {
3833 fts_string_t word;
3834 bool has_more = false;
3835
3836 word.f_str = NULL;
3837 word.f_len = 0;
3838 word.f_n_char = 0;
3839
3840 do {
3841 /* Fetch from index */
3842 error = i_s_fts_index_table_fill_selected(
3843 index, words, selected, &word);
3844
3845 if (error == DB_SUCCESS) {
3846 has_more = false;
3847 } else if (error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT) {
3848 has_more = true;
3849 } else {
3850 i_s_fts_index_table_free_one_fetch(words);
3851 ret = 1;
3852 goto func_exit;
3853 }
3854
3855 if (has_more) {
3856 fts_word_t* last_word;
3857
3858 /* Prepare start point for next fetch */
3859 last_word = static_cast<fts_word_t*>(ib_vector_last(words));
3860 ut_ad(last_word != NULL);
3861 fts_string_dup(&word, &last_word->text, heap);
3862 }
3863
3864 /* Fill into tables */
3865 ret = i_s_fts_index_table_fill_one_fetch(
3866 index_charset, thd, tables, words, &conv_str, has_more);
3867
3868 if (ret != 0) {
3869 i_s_fts_index_table_free_one_fetch(words);
3870 goto func_exit;
3871 }
3872 } while (has_more);
3873 }
3874
3875 func_exit:
3876 ut_free(conv_str.f_str);
3877 mem_heap_free(heap);
3878
3879 DBUG_RETURN(ret);
3880 }
3881 /*******************************************************************//**
3882 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3883 @return 0 on success, 1 on failure */
3884 static
3885 int
i_s_fts_index_table_fill(THD * thd,TABLE_LIST * tables,Item *)3886 i_s_fts_index_table_fill(
3887 /*=====================*/
3888 THD* thd, /*!< in: thread */
3889 TABLE_LIST* tables, /*!< in/out: tables to fill */
3890 Item* ) /*!< in: condition (ignored) */
3891 {
3892 dict_table_t* user_table;
3893 dict_index_t* index;
3894
3895 DBUG_ENTER("i_s_fts_index_table_fill");
3896
3897 /* deny access to non-superusers */
3898 if (check_global_access(thd, PROCESS_ACL)) {
3899 DBUG_RETURN(0);
3900 }
3901
3902 mysql_mutex_lock(&LOCK_global_system_variables);
3903
3904 if (!fts_internal_tbl_name) {
3905 mysql_mutex_unlock(&LOCK_global_system_variables);
3906 DBUG_RETURN(0);
3907 }
3908
3909 std::string fts_table_name(fts_internal_tbl_name);
3910 mysql_mutex_unlock(&LOCK_global_system_variables);
3911
3912 if(!fts_table_name.c_str()) {
3913 DBUG_RETURN(0);
3914 }
3915
3916 /* Prevent DDL to drop fts aux tables. */
3917 rw_lock_s_lock(dict_operation_lock);
3918
3919 user_table = dict_table_open_on_name(
3920 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3921
3922 if (!user_table) {
3923 rw_lock_s_unlock(dict_operation_lock);
3924
3925 DBUG_RETURN(0);
3926 }
3927
3928 for (index = dict_table_get_first_index(user_table);
3929 index; index = dict_table_get_next_index(index)) {
3930 if (index->type & DICT_FTS) {
3931 i_s_fts_index_table_fill_one_index(index, thd, tables);
3932 }
3933 }
3934
3935 dict_table_close(user_table, FALSE, FALSE);
3936
3937 rw_lock_s_unlock(dict_operation_lock);
3938
3939 DBUG_RETURN(0);
3940 }
3941
3942 /*******************************************************************//**
3943 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3944 @return 0 on success */
3945 static
3946 int
i_s_fts_index_table_init(void * p)3947 i_s_fts_index_table_init(
3948 /*=====================*/
3949 void* p) /*!< in/out: table schema object */
3950 {
3951 DBUG_ENTER("i_s_fts_index_table_init");
3952 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3953
3954 schema->fields_info = i_s_fts_index_fields_info;
3955 schema->fill_table = i_s_fts_index_table_fill;
3956
3957 DBUG_RETURN(0);
3958 }
3959
3960 struct st_mysql_plugin i_s_innodb_ft_index_table =
3961 {
3962 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
3963 /* int */
3964 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3965
3966 /* pointer to type-specific plugin descriptor */
3967 /* void* */
3968 STRUCT_FLD(info, &i_s_info),
3969
3970 /* plugin name */
3971 /* const char* */
3972 STRUCT_FLD(name, "INNODB_FT_INDEX_TABLE"),
3973
3974 /* plugin author (for SHOW PLUGINS) */
3975 /* const char* */
3976 STRUCT_FLD(author, plugin_author),
3977
3978 /* general descriptive text (for SHOW PLUGINS) */
3979 /* const char* */
3980 STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX TABLE"),
3981
3982 /* the plugin license (PLUGIN_LICENSE_XXX) */
3983 /* int */
3984 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3985
3986 /* the function to invoke when plugin is loaded */
3987 /* int (*)(void*); */
3988 STRUCT_FLD(init, i_s_fts_index_table_init),
3989
3990 /* the function to invoke when plugin is unloaded */
3991 /* int (*)(void*); */
3992 STRUCT_FLD(deinit, i_s_common_deinit),
3993
3994 /* plugin version (for SHOW PLUGINS) */
3995 /* unsigned int */
3996 STRUCT_FLD(version, INNODB_VERSION_SHORT),
3997
3998 /* struct st_mysql_show_var* */
3999 STRUCT_FLD(status_vars, NULL),
4000
4001 /* struct st_mysql_sys_var** */
4002 STRUCT_FLD(system_vars, NULL),
4003
4004 /* reserved for dependency checking */
4005 /* void* */
4006 STRUCT_FLD(__reserved1, NULL),
4007
4008 /* Plugin flags */
4009 /* unsigned long */
4010 STRUCT_FLD(flags, 0UL),
4011 };
4012
4013 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */
4014 static ST_FIELD_INFO i_s_fts_config_fields_info[] =
4015 {
4016 #define FTS_CONFIG_KEY 0
4017 {STRUCT_FLD(field_name, "KEY"),
4018 STRUCT_FLD(field_length, NAME_LEN + 1),
4019 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4020 STRUCT_FLD(value, 0),
4021 STRUCT_FLD(field_flags, 0),
4022 STRUCT_FLD(old_name, ""),
4023 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4024
4025 #define FTS_CONFIG_VALUE 1
4026 {STRUCT_FLD(field_name, "VALUE"),
4027 STRUCT_FLD(field_length, NAME_LEN + 1),
4028 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4029 STRUCT_FLD(value, 0),
4030 STRUCT_FLD(field_flags, 0),
4031 STRUCT_FLD(old_name, ""),
4032 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4033
4034 END_OF_ST_FIELD_INFO
4035 };
4036
4037 static const char* fts_config_key[] = {
4038 FTS_OPTIMIZE_LIMIT_IN_SECS,
4039 FTS_SYNCED_DOC_ID,
4040 FTS_STOPWORD_TABLE_NAME,
4041 FTS_USE_STOPWORD,
4042 NULL
4043 };
4044
4045 /*******************************************************************//**
4046 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4047 @return 0 on success, 1 on failure */
4048 static
4049 int
i_s_fts_config_fill(THD * thd,TABLE_LIST * tables,Item *)4050 i_s_fts_config_fill(
4051 /*================*/
4052 THD* thd, /*!< in: thread */
4053 TABLE_LIST* tables, /*!< in/out: tables to fill */
4054 Item* ) /*!< in: condition (ignored) */
4055 {
4056 Field** fields;
4057 TABLE* table = (TABLE*) tables->table;
4058 trx_t* trx;
4059 fts_table_t fts_table;
4060 dict_table_t* user_table;
4061 ulint i = 0;
4062 dict_index_t* index = NULL;
4063 unsigned char str[FTS_MAX_CONFIG_VALUE_LEN + 1];
4064
4065 DBUG_ENTER("i_s_fts_config_fill");
4066
4067 /* deny access to non-superusers */
4068 if (check_global_access(thd, PROCESS_ACL)) {
4069 DBUG_RETURN(0);
4070 }
4071
4072 mysql_mutex_lock(&LOCK_global_system_variables);
4073
4074 if (!fts_internal_tbl_name) {
4075 mysql_mutex_unlock(&LOCK_global_system_variables);
4076 DBUG_RETURN(0);
4077 }
4078
4079 std::string fts_table_name(fts_internal_tbl_name);
4080 mysql_mutex_unlock(&LOCK_global_system_variables);
4081
4082 if(!fts_table_name.c_str()) {
4083 DBUG_RETURN(0);
4084 }
4085
4086 DEBUG_SYNC_C("i_s_fts_config_fille_check");
4087
4088 fields = table->field;
4089
4090 /* Prevent DDL to drop fts aux tables. */
4091 rw_lock_s_lock(dict_operation_lock);
4092
4093 user_table = dict_table_open_on_name(
4094 fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
4095
4096 if (!user_table) {
4097 rw_lock_s_unlock(dict_operation_lock);
4098
4099 DBUG_RETURN(0);
4100 } else if (!dict_table_has_fts_index(user_table)) {
4101 dict_table_close(user_table, FALSE, FALSE);
4102
4103 rw_lock_s_unlock(dict_operation_lock);
4104
4105 DBUG_RETURN(0);
4106 }
4107
4108 trx = trx_allocate_for_background();
4109 trx->op_info = "Select for FTS CONFIG TABLE";
4110
4111 FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table);
4112
4113 if (!ib_vector_is_empty(user_table->fts->indexes)) {
4114 index = (dict_index_t*) ib_vector_getp_const(
4115 user_table->fts->indexes, 0);
4116 DBUG_ASSERT(!dict_index_is_online_ddl(index));
4117 }
4118
4119 while (fts_config_key[i]) {
4120 fts_string_t value;
4121 char* key_name;
4122 ulint allocated = FALSE;
4123
4124 value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
4125
4126 value.f_str = str;
4127
4128 if (index
4129 && strcmp(fts_config_key[i], FTS_TOTAL_WORD_COUNT) == 0) {
4130 key_name = fts_config_create_index_param_name(
4131 fts_config_key[i], index);
4132 allocated = TRUE;
4133 } else {
4134 key_name = (char*) fts_config_key[i];
4135 }
4136
4137 fts_config_get_value(trx, &fts_table, key_name, &value);
4138
4139 if (allocated) {
4140 ut_free(key_name);
4141 }
4142
4143 OK(field_store_string(
4144 fields[FTS_CONFIG_KEY], fts_config_key[i]));
4145
4146 OK(field_store_string(
4147 fields[FTS_CONFIG_VALUE], (const char*) value.f_str));
4148
4149 OK(schema_table_store_record(thd, table));
4150
4151 i++;
4152 }
4153
4154 fts_sql_commit(trx);
4155
4156 trx_free_for_background(trx);
4157
4158 dict_table_close(user_table, FALSE, FALSE);
4159
4160 rw_lock_s_unlock(dict_operation_lock);
4161
4162 DBUG_RETURN(0);
4163 }
4164
4165 /*******************************************************************//**
4166 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4167 @return 0 on success */
4168 static
4169 int
i_s_fts_config_init(void * p)4170 i_s_fts_config_init(
4171 /*=================*/
4172 void* p) /*!< in/out: table schema object */
4173 {
4174 DBUG_ENTER("i_s_fts_config_init");
4175 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
4176
4177 schema->fields_info = i_s_fts_config_fields_info;
4178 schema->fill_table = i_s_fts_config_fill;
4179
4180 DBUG_RETURN(0);
4181 }
4182
4183 struct st_mysql_plugin i_s_innodb_ft_config =
4184 {
4185 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
4186 /* int */
4187 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4188
4189 /* pointer to type-specific plugin descriptor */
4190 /* void* */
4191 STRUCT_FLD(info, &i_s_info),
4192
4193 /* plugin name */
4194 /* const char* */
4195 STRUCT_FLD(name, "INNODB_FT_CONFIG"),
4196
4197 /* plugin author (for SHOW PLUGINS) */
4198 /* const char* */
4199 STRUCT_FLD(author, plugin_author),
4200
4201 /* general descriptive text (for SHOW PLUGINS) */
4202 /* const char* */
4203 STRUCT_FLD(descr, "INNODB AUXILIARY FTS CONFIG TABLE"),
4204
4205 /* the plugin license (PLUGIN_LICENSE_XXX) */
4206 /* int */
4207 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4208
4209 /* the function to invoke when plugin is loaded */
4210 /* int (*)(void*); */
4211 STRUCT_FLD(init, i_s_fts_config_init),
4212
4213 /* the function to invoke when plugin is unloaded */
4214 /* int (*)(void*); */
4215 STRUCT_FLD(deinit, i_s_common_deinit),
4216
4217 /* plugin version (for SHOW PLUGINS) */
4218 /* unsigned int */
4219 STRUCT_FLD(version, INNODB_VERSION_SHORT),
4220
4221 /* struct st_mysql_show_var* */
4222 STRUCT_FLD(status_vars, NULL),
4223
4224 /* struct st_mysql_sys_var** */
4225 STRUCT_FLD(system_vars, NULL),
4226
4227 /* reserved for dependency checking */
4228 /* void* */
4229 STRUCT_FLD(__reserved1, NULL),
4230
4231 /* Plugin flags */
4232 /* unsigned long */
4233 STRUCT_FLD(flags, 0UL),
4234 };
4235
4236 /* Fields of the dynamic table INNODB_TEMP_TABLE_INFO. */
4237 static ST_FIELD_INFO i_s_innodb_temp_table_info_fields_info[] =
4238 {
4239 #define IDX_TEMP_TABLE_ID 0
4240 {STRUCT_FLD(field_name, "TABLE_ID"),
4241 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4242 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4243 STRUCT_FLD(value, 0),
4244 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4245 STRUCT_FLD(old_name, ""),
4246 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4247
4248 #define IDX_TEMP_TABLE_NAME 1
4249 {STRUCT_FLD(field_name, "NAME"),
4250 STRUCT_FLD(field_length, MAX_TABLE_UTF8_LEN),
4251 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4252 STRUCT_FLD(value, 0),
4253 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4254 STRUCT_FLD(old_name, ""),
4255 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4256
4257 #define IDX_TEMP_TABLE_N_COLS 2
4258 {STRUCT_FLD(field_name, "N_COLS"),
4259 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
4260 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
4261 STRUCT_FLD(value, 0),
4262 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4263 STRUCT_FLD(old_name, ""),
4264 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4265
4266 #define IDX_TEMP_TABLE_SPACE_ID 3
4267 {STRUCT_FLD(field_name, "SPACE"),
4268 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
4269 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
4270 STRUCT_FLD(value, 0),
4271 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4272 STRUCT_FLD(old_name, ""),
4273 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4274
4275 #define IDX_TEMP_TABLE_PTT 4
4276 {STRUCT_FLD(field_name, "PER_TABLE_TABLESPACE"),
4277 STRUCT_FLD(field_length, 64),
4278 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4279 STRUCT_FLD(value, 0),
4280 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4281 STRUCT_FLD(old_name, ""),
4282 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4283
4284 #define IDX_TEMP_TABLE_IS_COMPRESSED 5
4285 {STRUCT_FLD(field_name, "IS_COMPRESSED"),
4286 STRUCT_FLD(field_length, 64),
4287 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
4288 STRUCT_FLD(value, 0),
4289 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
4290 STRUCT_FLD(old_name, ""),
4291 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4292 END_OF_ST_FIELD_INFO
4293 };
4294
4295 struct temp_table_info_t{
4296 table_id_t m_table_id;
4297 char m_table_name[MAX_TABLE_UTF8_LEN];
4298 unsigned m_n_cols;
4299 unsigned m_space_id;
4300 char m_per_table_tablespace[64];
4301 char m_is_compressed[64];
4302 };
4303
4304 typedef std::vector<temp_table_info_t, ut_allocator<temp_table_info_t> >
4305 temp_table_info_cache_t;
4306
4307 /*******************************************************************//**
4308 Fill Information Schema table INNODB_TEMP_TABLE_INFO for a particular
4309 temp-table
4310 @return 0 on success, 1 on failure */
4311 static
4312 int
i_s_innodb_temp_table_info_fill(THD * thd,TABLE_LIST * tables,const temp_table_info_t * info)4313 i_s_innodb_temp_table_info_fill(
4314 /*=============================*/
4315 THD* thd, /*!< in: thread */
4316 TABLE_LIST* tables, /*!< in/out: tables
4317 to fill */
4318 const temp_table_info_t* info) /*!< in: temp-table
4319 information */
4320 {
4321 TABLE* table;
4322 Field** fields;
4323
4324 DBUG_ENTER("i_s_innodb_temp_table_info_fill");
4325
4326 table = tables->table;
4327
4328 fields = table->field;
4329
4330 OK(fields[IDX_TEMP_TABLE_ID]->store(info->m_table_id, true));
4331
4332 OK(field_store_string(
4333 fields[IDX_TEMP_TABLE_NAME], info->m_table_name));
4334
4335 OK(fields[IDX_TEMP_TABLE_N_COLS]->store(info->m_n_cols));
4336
4337 OK(fields[IDX_TEMP_TABLE_SPACE_ID]->store(info->m_space_id));
4338
4339 OK(field_store_string(
4340 fields[IDX_TEMP_TABLE_PTT], info->m_per_table_tablespace));
4341
4342 OK(field_store_string(
4343 fields[IDX_TEMP_TABLE_IS_COMPRESSED], info->m_is_compressed));
4344
4345 DBUG_RETURN(schema_table_store_record(thd, table));
4346 }
4347
4348 /*******************************************************************//**
4349 Populate current table information to cache */
4350 static
4351 void
innodb_temp_table_populate_cache(const dict_table_t * table,temp_table_info_t * cache)4352 innodb_temp_table_populate_cache(
4353 /*=============================*/
4354 const dict_table_t* table, /*! in: table */
4355 temp_table_info_t* cache) /*! in/out: populate data in this
4356 cache */
4357 {
4358 cache->m_table_id = table->id;
4359
4360 char db_utf8[MAX_DB_UTF8_LEN];
4361 char table_utf8[MAX_TABLE_UTF8_LEN];
4362
4363 dict_fs2utf8(table->name.m_name,
4364 db_utf8, sizeof(db_utf8),
4365 table_utf8, sizeof(table_utf8));
4366 strcpy(cache->m_table_name, table_utf8);
4367
4368 cache->m_n_cols = table->n_cols;
4369
4370 cache->m_space_id = table->space;
4371
4372 if (fsp_is_system_temporary(table->space)) {
4373 strcpy(cache->m_per_table_tablespace, "FALSE");
4374 } else {
4375 strcpy(cache->m_per_table_tablespace, "TRUE");
4376 }
4377
4378 if (dict_table_page_size(table).is_compressed()) {
4379 strcpy(cache->m_is_compressed, "TRUE");
4380 } else {
4381 strcpy(cache->m_is_compressed, "FALSE");
4382 }
4383 }
4384
4385 /*******************************************************************//**
4386 This function will iterate over all available table and will fill
4387 stats for temp-tables to INNODB_TEMP_TABLE_INFO.
4388 @return 0 on success, 1 on failure */
4389 static
4390 int
i_s_innodb_temp_table_info_fill_table(THD * thd,TABLE_LIST * tables,Item *)4391 i_s_innodb_temp_table_info_fill_table(
4392 /*===================================*/
4393 THD* thd, /*!< in: thread */
4394 TABLE_LIST* tables, /*!< in/out: tables to fill */
4395 Item* ) /*!< in: condition (ignored) */
4396 {
4397 int status = 0;
4398 dict_table_t* table = NULL;
4399
4400 DBUG_ENTER("i_s_innodb_temp_table_info_fill_table");
4401
4402 /* Only allow the PROCESS privilege holder to access the stats */
4403 if (check_global_access(thd, PROCESS_ACL)) {
4404 DBUG_RETURN(0);
4405 }
4406
4407 /* First populate all temp-table info by acquiring dict_sys->mutex.
4408 Note: Scan is being done on NON-LRU list which mainly has system
4409 table entries and temp-table entries. This means 2 things: list
4410 is smaller so processing would be faster and most of the data
4411 is relevant */
4412 temp_table_info_cache_t all_temp_info_cache;
4413 all_temp_info_cache.reserve(UT_LIST_GET_LEN(dict_sys->table_non_LRU));
4414
4415 mutex_enter(&dict_sys->mutex);
4416 for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
4417 table != NULL;
4418 table = UT_LIST_GET_NEXT(table_LRU, table)) {
4419
4420 if (!dict_table_is_temporary(table)) {
4421 continue;
4422 }
4423
4424 temp_table_info_t current_temp_table_info;
4425
4426 innodb_temp_table_populate_cache(
4427 table, ¤t_temp_table_info);
4428
4429 all_temp_info_cache.push_back(current_temp_table_info);
4430 }
4431 mutex_exit(&dict_sys->mutex);
4432
4433 /* Now populate the info to MySQL table */
4434 temp_table_info_cache_t::const_iterator end = all_temp_info_cache.end();
4435 for (temp_table_info_cache_t::const_iterator it
4436 = all_temp_info_cache.begin();
4437 it != end;
4438 it++) {
4439 status = i_s_innodb_temp_table_info_fill(thd, tables, &(*it));
4440 if (status) {
4441 break;
4442 }
4443 }
4444
4445 DBUG_RETURN(status);
4446 }
4447
4448 /*******************************************************************//**
4449 Bind the dynamic table INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO.
4450 @return 0 on success, 1 on failure */
4451 static
4452 int
i_s_innodb_temp_table_info_init(void * p)4453 i_s_innodb_temp_table_info_init(
4454 /*=============================*/
4455 void* p) /*!< in/out: table schema object */
4456 {
4457 ST_SCHEMA_TABLE* schema;
4458
4459 DBUG_ENTER("i_s_innodb_temp_table_info_init");
4460
4461 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
4462
4463 schema->fields_info = i_s_innodb_temp_table_info_fields_info;
4464 schema->fill_table = i_s_innodb_temp_table_info_fill_table;
4465
4466 DBUG_RETURN(0);
4467 }
4468
4469 struct st_mysql_plugin i_s_innodb_temp_table_info =
4470 {
4471 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
4472 /* int */
4473 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4474
4475 /* pointer to type-specific plugin descriptor */
4476 /* void* */
4477 STRUCT_FLD(info, &i_s_info),
4478
4479 /* plugin name */
4480 /* const char* */
4481 STRUCT_FLD(name, "INNODB_TEMP_TABLE_INFO"),
4482
4483 /* plugin author (for SHOW PLUGINS) */
4484 /* const char* */
4485 STRUCT_FLD(author, plugin_author),
4486
4487 /* general descriptive text (for SHOW PLUGINS) */
4488 /* const char* */
4489 STRUCT_FLD(descr, "InnoDB Temp Table Stats"),
4490
4491 /* the plugin license (PLUGIN_LICENSE_XXX) */
4492 /* int */
4493 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4494
4495 /* the function to invoke when plugin is loaded */
4496 /* int (*)(void*); */
4497 STRUCT_FLD(init, i_s_innodb_temp_table_info_init),
4498
4499 /* the function to invoke when plugin is unloaded */
4500 /* int (*)(void*); */
4501 STRUCT_FLD(deinit, i_s_common_deinit),
4502
4503 /* plugin version (for SHOW PLUGINS) */
4504 /* unsigned int */
4505 STRUCT_FLD(version, INNODB_VERSION_SHORT),
4506
4507 /* struct st_mysql_show_var* */
4508 STRUCT_FLD(status_vars, NULL),
4509
4510 /* struct st_mysql_sys_var** */
4511 STRUCT_FLD(system_vars, NULL),
4512
4513 /* reserved for dependency checking */
4514 /* void* */
4515 STRUCT_FLD(__reserved1, NULL),
4516
4517 /* Plugin flags */
4518 /* unsigned long */
4519 STRUCT_FLD(flags, 0UL),
4520 };
4521
4522 /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
4523 static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] =
4524 {
4525 #define IDX_BUF_STATS_POOL_ID 0
4526 {STRUCT_FLD(field_name, "POOL_ID"),
4527 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4528 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4529 STRUCT_FLD(value, 0),
4530 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4531 STRUCT_FLD(old_name, ""),
4532 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4533
4534 #define IDX_BUF_STATS_POOL_SIZE 1
4535 {STRUCT_FLD(field_name, "POOL_SIZE"),
4536 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4537 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4538 STRUCT_FLD(value, 0),
4539 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4540 STRUCT_FLD(old_name, ""),
4541 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4542
4543 #define IDX_BUF_STATS_FREE_BUFFERS 2
4544 {STRUCT_FLD(field_name, "FREE_BUFFERS"),
4545 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4546 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4547 STRUCT_FLD(value, 0),
4548 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4549 STRUCT_FLD(old_name, ""),
4550 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4551
4552 #define IDX_BUF_STATS_LRU_LEN 3
4553 {STRUCT_FLD(field_name, "DATABASE_PAGES"),
4554 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4555 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4556 STRUCT_FLD(value, 0),
4557 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4558 STRUCT_FLD(old_name, ""),
4559 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4560
4561 #define IDX_BUF_STATS_OLD_LRU_LEN 4
4562 {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"),
4563 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4564 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4565 STRUCT_FLD(value, 0),
4566 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4567 STRUCT_FLD(old_name, ""),
4568 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4569
4570 #define IDX_BUF_STATS_FLUSH_LIST_LEN 5
4571 {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"),
4572 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4573 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4574 STRUCT_FLD(value, 0),
4575 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4576 STRUCT_FLD(old_name, ""),
4577 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4578
4579 #define IDX_BUF_STATS_PENDING_ZIP 6
4580 {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"),
4581 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4582 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4583 STRUCT_FLD(value, 0),
4584 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4585 STRUCT_FLD(old_name, ""),
4586 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4587
4588 #define IDX_BUF_STATS_PENDING_READ 7
4589 {STRUCT_FLD(field_name, "PENDING_READS"),
4590 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4591 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4592 STRUCT_FLD(value, 0),
4593 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4594 STRUCT_FLD(old_name, ""),
4595 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4596
4597 #define IDX_BUF_STATS_FLUSH_LRU 8
4598 {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"),
4599 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4600 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4601 STRUCT_FLD(value, 0),
4602 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4603 STRUCT_FLD(old_name, ""),
4604 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4605
4606 #define IDX_BUF_STATS_FLUSH_LIST 9
4607 {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"),
4608 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4609 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4610 STRUCT_FLD(value, 0),
4611 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4612 STRUCT_FLD(old_name, ""),
4613 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4614
4615 #define IDX_BUF_STATS_PAGE_YOUNG 10
4616 {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"),
4617 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4618 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4619 STRUCT_FLD(value, 0),
4620 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4621 STRUCT_FLD(old_name, ""),
4622 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4623
4624 #define IDX_BUF_STATS_PAGE_NOT_YOUNG 11
4625 {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"),
4626 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4627 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4628 STRUCT_FLD(value, 0),
4629 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4630 STRUCT_FLD(old_name, ""),
4631 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4632
4633 #define IDX_BUF_STATS_PAGE_YOUNG_RATE 12
4634 {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"),
4635 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4636 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4637 STRUCT_FLD(value, 0),
4638 STRUCT_FLD(field_flags, 0),
4639 STRUCT_FLD(old_name, ""),
4640 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4641
4642 #define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
4643 {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"),
4644 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4645 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4646 STRUCT_FLD(value, 0),
4647 STRUCT_FLD(field_flags, 0),
4648 STRUCT_FLD(old_name, ""),
4649 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4650
4651 #define IDX_BUF_STATS_PAGE_READ 14
4652 {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"),
4653 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4654 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4655 STRUCT_FLD(value, 0),
4656 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4657 STRUCT_FLD(old_name, ""),
4658 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4659
4660 #define IDX_BUF_STATS_PAGE_CREATED 15
4661 {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"),
4662 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4663 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4664 STRUCT_FLD(value, 0),
4665 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4666 STRUCT_FLD(old_name, ""),
4667 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4668
4669 #define IDX_BUF_STATS_PAGE_WRITTEN 16
4670 {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"),
4671 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4672 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4673 STRUCT_FLD(value, 0),
4674 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4675 STRUCT_FLD(old_name, ""),
4676 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4677
4678 #define IDX_BUF_STATS_PAGE_READ_RATE 17
4679 {STRUCT_FLD(field_name, "PAGES_READ_RATE"),
4680 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4681 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4682 STRUCT_FLD(value, 0),
4683 STRUCT_FLD(field_flags, 0),
4684 STRUCT_FLD(old_name, ""),
4685 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4686
4687 #define IDX_BUF_STATS_PAGE_CREATE_RATE 18
4688 {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"),
4689 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4690 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4691 STRUCT_FLD(value, 0),
4692 STRUCT_FLD(field_flags, 0),
4693 STRUCT_FLD(old_name, ""),
4694 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4695
4696 #define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19
4697 {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"),
4698 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4699 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4700 STRUCT_FLD(value, 0),
4701 STRUCT_FLD(field_flags, 0),
4702 STRUCT_FLD(old_name, ""),
4703 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4704
4705 #define IDX_BUF_STATS_GET 20
4706 {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"),
4707 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4708 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4709 STRUCT_FLD(value, 0),
4710 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4711 STRUCT_FLD(old_name, ""),
4712 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4713
4714 #define IDX_BUF_STATS_HIT_RATE 21
4715 {STRUCT_FLD(field_name, "HIT_RATE"),
4716 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4717 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4718 STRUCT_FLD(value, 0),
4719 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4720 STRUCT_FLD(old_name, ""),
4721 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4722
4723 #define IDX_BUF_STATS_MADE_YOUNG_PCT 22
4724 {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"),
4725 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4726 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4727 STRUCT_FLD(value, 0),
4728 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4729 STRUCT_FLD(old_name, ""),
4730 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4731
4732 #define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
4733 {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
4734 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4735 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4736 STRUCT_FLD(value, 0),
4737 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4738 STRUCT_FLD(old_name, ""),
4739 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4740
4741 #define IDX_BUF_STATS_READ_AHREAD 24
4742 {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"),
4743 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4744 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4745 STRUCT_FLD(value, 0),
4746 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4747 STRUCT_FLD(old_name, ""),
4748 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4749
4750 #define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
4751 {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"),
4752 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4753 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4754 STRUCT_FLD(value, 0),
4755 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4756 STRUCT_FLD(old_name, ""),
4757 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4758
4759 #define IDX_BUF_STATS_READ_AHEAD_RATE 26
4760 {STRUCT_FLD(field_name, "READ_AHEAD_RATE"),
4761 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4762 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4763 STRUCT_FLD(value, 0),
4764 STRUCT_FLD(field_flags, 0),
4765 STRUCT_FLD(old_name, ""),
4766 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4767
4768 #define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
4769 {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"),
4770 STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH),
4771 STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT),
4772 STRUCT_FLD(value, 0),
4773 STRUCT_FLD(field_flags, 0),
4774 STRUCT_FLD(old_name, ""),
4775 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4776
4777 #define IDX_BUF_STATS_LRU_IO_SUM 28
4778 {STRUCT_FLD(field_name, "LRU_IO_TOTAL"),
4779 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4780 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4781 STRUCT_FLD(value, 0),
4782 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4783 STRUCT_FLD(old_name, ""),
4784 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4785
4786 #define IDX_BUF_STATS_LRU_IO_CUR 29
4787 {STRUCT_FLD(field_name, "LRU_IO_CURRENT"),
4788 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4789 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4790 STRUCT_FLD(value, 0),
4791 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4792 STRUCT_FLD(old_name, ""),
4793 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4794
4795 #define IDX_BUF_STATS_UNZIP_SUM 30
4796 {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"),
4797 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4798 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4799 STRUCT_FLD(value, 0),
4800 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4801 STRUCT_FLD(old_name, ""),
4802 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4803
4804 #define IDX_BUF_STATS_UNZIP_CUR 31
4805 {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"),
4806 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
4807 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
4808 STRUCT_FLD(value, 0),
4809 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
4810 STRUCT_FLD(old_name, ""),
4811 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
4812
4813 END_OF_ST_FIELD_INFO
4814 };
4815
4816 /*******************************************************************//**
4817 Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
4818 buffer pool
4819 @return 0 on success, 1 on failure */
4820 static
4821 int
i_s_innodb_stats_fill(THD * thd,TABLE_LIST * tables,const buf_pool_info_t * info)4822 i_s_innodb_stats_fill(
4823 /*==================*/
4824 THD* thd, /*!< in: thread */
4825 TABLE_LIST* tables, /*!< in/out: tables to fill */
4826 const buf_pool_info_t* info) /*!< in: buffer pool
4827 information */
4828 {
4829 TABLE* table;
4830 Field** fields;
4831
4832 DBUG_ENTER("i_s_innodb_stats_fill");
4833
4834 table = tables->table;
4835
4836 fields = table->field;
4837
4838 OK(fields[IDX_BUF_STATS_POOL_ID]->store(
4839 info->pool_unique_id, true));
4840
4841 OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(
4842 info->pool_size, true));
4843
4844 OK(fields[IDX_BUF_STATS_LRU_LEN]->store(
4845 info->lru_len, true));
4846
4847 OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(
4848 info->old_lru_len, true));
4849
4850 OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(
4851 info->free_list_len, true));
4852
4853 OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
4854 info->flush_list_len, true));
4855
4856 OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(
4857 info->n_pend_unzip, true));
4858
4859 OK(fields[IDX_BUF_STATS_PENDING_READ]->store(
4860 info->n_pend_reads, true));
4861
4862 OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(
4863 info->n_pending_flush_lru, true));
4864
4865 OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(
4866 info->n_pending_flush_list, true));
4867
4868 OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(
4869 info->n_pages_made_young, true));
4870
4871 OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
4872 info->n_pages_not_made_young, true));
4873
4874 OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
4875 info->page_made_young_rate));
4876
4877 OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
4878 info->page_not_made_young_rate));
4879
4880 OK(fields[IDX_BUF_STATS_PAGE_READ]->store(
4881 info->n_pages_read, true));
4882
4883 OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(
4884 info->n_pages_created, true));
4885
4886 OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(
4887 info->n_pages_written, true));
4888
4889 OK(fields[IDX_BUF_STATS_GET]->store(
4890 info->n_page_gets, true));
4891
4892 OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(
4893 info->pages_read_rate));
4894
4895 OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(
4896 info->pages_created_rate));
4897
4898 OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(
4899 info->pages_written_rate));
4900
4901 if (info->n_page_get_delta) {
4902 OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
4903 1000 - (1000 * info->page_read_delta
4904 / info->n_page_get_delta), true));
4905
4906 OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
4907 1000 * info->young_making_delta
4908 / info->n_page_get_delta, true));
4909
4910 OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
4911 1000 * info->not_young_making_delta
4912 / info->n_page_get_delta, true));
4913 } else {
4914 OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0, true));
4915 OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0, true));
4916 OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0, true));
4917 }
4918
4919 OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(
4920 info->n_ra_pages_read, true));
4921
4922 OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
4923 info->n_ra_pages_evicted, true));
4924
4925 OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
4926 info->pages_readahead_rate));
4927
4928 OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
4929 info->pages_evicted_rate));
4930
4931 OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(
4932 info->io_sum, true));
4933
4934 OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(
4935 info->io_cur, true));
4936
4937 OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(
4938 info->unzip_sum, true));
4939
4940 OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store(
4941 info->unzip_cur, true));
4942
4943 DBUG_RETURN(schema_table_store_record(thd, table));
4944 }
4945
4946 /*******************************************************************//**
4947 This is the function that loops through each buffer pool and fetch buffer
4948 pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS
4949 @return 0 on success, 1 on failure */
4950 static
4951 int
i_s_innodb_buffer_stats_fill_table(THD * thd,TABLE_LIST * tables,Item *)4952 i_s_innodb_buffer_stats_fill_table(
4953 /*===============================*/
4954 THD* thd, /*!< in: thread */
4955 TABLE_LIST* tables, /*!< in/out: tables to fill */
4956 Item* ) /*!< in: condition (ignored) */
4957 {
4958 int status = 0;
4959 buf_pool_info_t* pool_info;
4960
4961 DBUG_ENTER("i_s_innodb_buffer_fill_general");
4962 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
4963
4964 /* Only allow the PROCESS privilege holder to access the stats */
4965 if (check_global_access(thd, PROCESS_ACL)) {
4966 DBUG_RETURN(0);
4967 }
4968
4969 pool_info = (buf_pool_info_t*) ut_zalloc_nokey(
4970 srv_buf_pool_instances * sizeof *pool_info);
4971
4972 /* Walk through each buffer pool */
4973 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
4974 buf_pool_t* buf_pool;
4975
4976 buf_pool = buf_pool_from_array(i);
4977
4978 /* Fetch individual buffer pool info */
4979 buf_stats_get_pool_info(buf_pool, i, pool_info);
4980
4981 status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
4982
4983 /* If something goes wrong, break and return */
4984 if (status) {
4985 break;
4986 }
4987 }
4988
4989 ut_free(pool_info);
4990
4991 DBUG_RETURN(status);
4992 }
4993
4994 /*******************************************************************//**
4995 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
4996 @return 0 on success, 1 on failure */
4997 static
4998 int
i_s_innodb_buffer_pool_stats_init(void * p)4999 i_s_innodb_buffer_pool_stats_init(
5000 /*==============================*/
5001 void* p) /*!< in/out: table schema object */
5002 {
5003 ST_SCHEMA_TABLE* schema;
5004
5005 DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
5006
5007 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5008
5009 schema->fields_info = i_s_innodb_buffer_stats_fields_info;
5010 schema->fill_table = i_s_innodb_buffer_stats_fill_table;
5011
5012 DBUG_RETURN(0);
5013 }
5014
5015 struct st_mysql_plugin i_s_innodb_buffer_stats =
5016 {
5017 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
5018 /* int */
5019 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5020
5021 /* pointer to type-specific plugin descriptor */
5022 /* void* */
5023 STRUCT_FLD(info, &i_s_info),
5024
5025 /* plugin name */
5026 /* const char* */
5027 STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
5028
5029 /* plugin author (for SHOW PLUGINS) */
5030 /* const char* */
5031 STRUCT_FLD(author, plugin_author),
5032
5033 /* general descriptive text (for SHOW PLUGINS) */
5034 /* const char* */
5035 STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
5036
5037 /* the plugin license (PLUGIN_LICENSE_XXX) */
5038 /* int */
5039 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5040
5041 /* the function to invoke when plugin is loaded */
5042 /* int (*)(void*); */
5043 STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
5044
5045 /* the function to invoke when plugin is unloaded */
5046 /* int (*)(void*); */
5047 STRUCT_FLD(deinit, i_s_common_deinit),
5048
5049 /* plugin version (for SHOW PLUGINS) */
5050 /* unsigned int */
5051 STRUCT_FLD(version, INNODB_VERSION_SHORT),
5052
5053 /* struct st_mysql_show_var* */
5054 STRUCT_FLD(status_vars, NULL),
5055
5056 /* struct st_mysql_sys_var** */
5057 STRUCT_FLD(system_vars, NULL),
5058
5059 /* reserved for dependency checking */
5060 /* void* */
5061 STRUCT_FLD(__reserved1, NULL),
5062
5063 /* Plugin flags */
5064 /* unsigned long */
5065 STRUCT_FLD(flags, 0UL),
5066 };
5067
5068 /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
5069 static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] =
5070 {
5071 #define IDX_BUFFER_POOL_ID 0
5072 {STRUCT_FLD(field_name, "POOL_ID"),
5073 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5074 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5075 STRUCT_FLD(value, 0),
5076 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5077 STRUCT_FLD(old_name, ""),
5078 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5079
5080 #define IDX_BUFFER_BLOCK_ID 1
5081 {STRUCT_FLD(field_name, "BLOCK_ID"),
5082 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5083 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5084 STRUCT_FLD(value, 0),
5085 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5086 STRUCT_FLD(old_name, ""),
5087 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5088
5089 #define IDX_BUFFER_PAGE_SPACE 2
5090 {STRUCT_FLD(field_name, "SPACE"),
5091 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5092 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5093 STRUCT_FLD(value, 0),
5094 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5095 STRUCT_FLD(old_name, ""),
5096 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5097
5098 #define IDX_BUFFER_PAGE_NUM 3
5099 {STRUCT_FLD(field_name, "PAGE_NUMBER"),
5100 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5101 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5102 STRUCT_FLD(value, 0),
5103 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5104 STRUCT_FLD(old_name, ""),
5105 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5106
5107 #define IDX_BUFFER_PAGE_TYPE 4
5108 {STRUCT_FLD(field_name, "PAGE_TYPE"),
5109 STRUCT_FLD(field_length, 64),
5110 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5111 STRUCT_FLD(value, 0),
5112 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5113 STRUCT_FLD(old_name, ""),
5114 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5115
5116 #define IDX_BUFFER_PAGE_FLUSH_TYPE 5
5117 {STRUCT_FLD(field_name, "FLUSH_TYPE"),
5118 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5119 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5120 STRUCT_FLD(value, 0),
5121 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5122 STRUCT_FLD(old_name, ""),
5123 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5124
5125 #define IDX_BUFFER_PAGE_FIX_COUNT 6
5126 {STRUCT_FLD(field_name, "FIX_COUNT"),
5127 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5128 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5129 STRUCT_FLD(value, 0),
5130 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5131 STRUCT_FLD(old_name, ""),
5132 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5133
5134 #define IDX_BUFFER_PAGE_HASHED 7
5135 {STRUCT_FLD(field_name, "IS_HASHED"),
5136 STRUCT_FLD(field_length, 3),
5137 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5138 STRUCT_FLD(value, 0),
5139 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5140 STRUCT_FLD(old_name, ""),
5141 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5142
5143 #define IDX_BUFFER_PAGE_NEWEST_MOD 8
5144 {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
5145 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5146 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5147 STRUCT_FLD(value, 0),
5148 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5149 STRUCT_FLD(old_name, ""),
5150 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5151
5152 #define IDX_BUFFER_PAGE_OLDEST_MOD 9
5153 {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
5154 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5155 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5156 STRUCT_FLD(value, 0),
5157 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5158 STRUCT_FLD(old_name, ""),
5159 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5160
5161 #define IDX_BUFFER_PAGE_ACCESS_TIME 10
5162 {STRUCT_FLD(field_name, "ACCESS_TIME"),
5163 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5164 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5165 STRUCT_FLD(value, 0),
5166 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5167 STRUCT_FLD(old_name, ""),
5168 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5169
5170 #define IDX_BUFFER_PAGE_TABLE_NAME 11
5171 {STRUCT_FLD(field_name, "TABLE_NAME"),
5172 STRUCT_FLD(field_length, 1024),
5173 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5174 STRUCT_FLD(value, 0),
5175 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5176 STRUCT_FLD(old_name, ""),
5177 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5178
5179 #define IDX_BUFFER_PAGE_INDEX_NAME 12
5180 {STRUCT_FLD(field_name, "INDEX_NAME"),
5181 STRUCT_FLD(field_length, 1024),
5182 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5183 STRUCT_FLD(value, 0),
5184 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5185 STRUCT_FLD(old_name, ""),
5186 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5187
5188 #define IDX_BUFFER_PAGE_NUM_RECS 13
5189 {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
5190 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5191 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5192 STRUCT_FLD(value, 0),
5193 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5194 STRUCT_FLD(old_name, ""),
5195 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5196
5197 #define IDX_BUFFER_PAGE_DATA_SIZE 14
5198 {STRUCT_FLD(field_name, "DATA_SIZE"),
5199 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5200 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5201 STRUCT_FLD(value, 0),
5202 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5203 STRUCT_FLD(old_name, ""),
5204 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5205
5206 #define IDX_BUFFER_PAGE_ZIP_SIZE 15
5207 {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
5208 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5209 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5210 STRUCT_FLD(value, 0),
5211 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5212 STRUCT_FLD(old_name, ""),
5213 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5214
5215 #define IDX_BUFFER_PAGE_STATE 16
5216 {STRUCT_FLD(field_name, "PAGE_STATE"),
5217 STRUCT_FLD(field_length, 64),
5218 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5219 STRUCT_FLD(value, 0),
5220 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5221 STRUCT_FLD(old_name, ""),
5222 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5223
5224 #define IDX_BUFFER_PAGE_IO_FIX 17
5225 {STRUCT_FLD(field_name, "IO_FIX"),
5226 STRUCT_FLD(field_length, 64),
5227 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5228 STRUCT_FLD(value, 0),
5229 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5230 STRUCT_FLD(old_name, ""),
5231 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5232
5233 #define IDX_BUFFER_PAGE_IS_OLD 18
5234 {STRUCT_FLD(field_name, "IS_OLD"),
5235 STRUCT_FLD(field_length, 3),
5236 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5237 STRUCT_FLD(value, 0),
5238 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5239 STRUCT_FLD(old_name, ""),
5240 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5241
5242 #define IDX_BUFFER_PAGE_FREE_CLOCK 19
5243 {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
5244 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5245 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5246 STRUCT_FLD(value, 0),
5247 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5248 STRUCT_FLD(old_name, ""),
5249 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5250
5251 END_OF_ST_FIELD_INFO
5252 };
5253
5254 /*******************************************************************//**
5255 Fill Information Schema table INNODB_BUFFER_PAGE with information
5256 cached in the buf_page_info_t array
5257 @return 0 on success, 1 on failure */
5258 static
5259 int
i_s_innodb_buffer_page_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5260 i_s_innodb_buffer_page_fill(
5261 /*========================*/
5262 THD* thd, /*!< in: thread */
5263 TABLE_LIST* tables, /*!< in/out: tables to fill */
5264 const buf_page_info_t* info_array, /*!< in: array cached page
5265 info */
5266 ulint num_page) /*!< in: number of page info
5267 cached */
5268 {
5269 TABLE* table;
5270 Field** fields;
5271
5272 DBUG_ENTER("i_s_innodb_buffer_page_fill");
5273
5274 table = tables->table;
5275
5276 fields = table->field;
5277
5278 /* Iterate through the cached array and fill the I_S table rows */
5279 for (ulint i = 0; i < num_page; i++) {
5280 const buf_page_info_t* page_info;
5281 char table_name[MAX_FULL_NAME_LEN + 1];
5282 const char* table_name_end = NULL;
5283 const char* state_str;
5284 enum buf_page_state state;
5285
5286 page_info = info_array + i;
5287
5288 state_str = NULL;
5289
5290 OK(fields[IDX_BUFFER_POOL_ID]->store(
5291 page_info->pool_id, true));
5292
5293 OK(fields[IDX_BUFFER_BLOCK_ID]->store(
5294 page_info->block_id, true));
5295
5296 OK(fields[IDX_BUFFER_PAGE_SPACE]->store(
5297 page_info->space_id, true));
5298
5299 OK(fields[IDX_BUFFER_PAGE_NUM]->store(
5300 page_info->page_num, true));
5301
5302 OK(field_store_string(
5303 fields[IDX_BUFFER_PAGE_TYPE],
5304 i_s_page_type[page_info->page_type].type_str));
5305
5306 OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
5307 page_info->flush_type));
5308
5309 OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
5310 page_info->fix_count));
5311
5312 if (page_info->hashed) {
5313 OK(field_store_string(
5314 fields[IDX_BUFFER_PAGE_HASHED], "YES"));
5315 } else {
5316 OK(field_store_string(
5317 fields[IDX_BUFFER_PAGE_HASHED], "NO"));
5318 }
5319
5320 OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
5321 page_info->newest_mod, true));
5322
5323 OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
5324 page_info->oldest_mod, true));
5325
5326 OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
5327 page_info->access_time));
5328
5329 fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null();
5330
5331 fields[IDX_BUFFER_PAGE_INDEX_NAME]->set_null();
5332
5333 /* If this is an index page, fetch the index name
5334 and table name */
5335 if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5336 const dict_index_t* index;
5337
5338 mutex_enter(&dict_sys->mutex);
5339 index = dict_index_get_if_in_cache_low(
5340 page_info->index_id);
5341
5342 if (index) {
5343
5344 table_name_end = innobase_convert_name(
5345 table_name, sizeof(table_name),
5346 index->table_name,
5347 strlen(index->table_name),
5348 thd);
5349
5350 OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store(
5351 table_name,
5352 static_cast<size_t>(table_name_end - table_name),
5353 system_charset_info));
5354 fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull();
5355
5356 OK(field_store_index_name(
5357 fields[IDX_BUFFER_PAGE_INDEX_NAME],
5358 index->name));
5359 }
5360
5361 mutex_exit(&dict_sys->mutex);
5362 }
5363
5364 OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
5365 page_info->num_recs, true));
5366
5367 OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
5368 page_info->data_size, true));
5369
5370 OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
5371 page_info->zip_ssize
5372 ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize
5373 : 0, true));
5374
5375 #if BUF_PAGE_STATE_BITS > 3
5376 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
5377 #endif
5378 state = static_cast<enum buf_page_state>(page_info->page_state);
5379
5380 switch (state) {
5381 /* First three states are for compression pages and
5382 are not states we would get as we scan pages through
5383 buffer blocks */
5384 case BUF_BLOCK_POOL_WATCH:
5385 case BUF_BLOCK_ZIP_PAGE:
5386 case BUF_BLOCK_ZIP_DIRTY:
5387 state_str = NULL;
5388 break;
5389 case BUF_BLOCK_NOT_USED:
5390 state_str = "NOT_USED";
5391 break;
5392 case BUF_BLOCK_READY_FOR_USE:
5393 state_str = "READY_FOR_USE";
5394 break;
5395 case BUF_BLOCK_FILE_PAGE:
5396 state_str = "FILE_PAGE";
5397 break;
5398 case BUF_BLOCK_MEMORY:
5399 state_str = "MEMORY";
5400 break;
5401 case BUF_BLOCK_REMOVE_HASH:
5402 state_str = "REMOVE_HASH";
5403 break;
5404 };
5405
5406 OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
5407 state_str));
5408
5409 switch (page_info->io_fix) {
5410 case BUF_IO_NONE:
5411 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5412 "IO_NONE"));
5413 break;
5414 case BUF_IO_READ:
5415 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5416 "IO_READ"));
5417 break;
5418 case BUF_IO_WRITE:
5419 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5420 "IO_WRITE"));
5421 break;
5422 case BUF_IO_PIN:
5423 OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5424 "IO_PIN"));
5425 break;
5426 }
5427
5428 OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
5429 (page_info->is_old) ? "YES" : "NO"));
5430
5431 OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
5432 page_info->freed_page_clock, true));
5433
5434 if (schema_table_store_record(thd, table)) {
5435 DBUG_RETURN(1);
5436 }
5437 }
5438
5439 DBUG_RETURN(0);
5440 }
5441
5442 /*******************************************************************//**
5443 Set appropriate page type to a buf_page_info_t structure */
5444 static
5445 void
i_s_innodb_set_page_type(buf_page_info_t * page_info,ulint page_type,const byte * frame)5446 i_s_innodb_set_page_type(
5447 /*=====================*/
5448 buf_page_info_t*page_info, /*!< in/out: structure to fill with
5449 scanned info */
5450 ulint page_type, /*!< in: page type */
5451 const byte* frame) /*!< in: buffer frame */
5452 {
5453 if (fil_page_type_is_index(page_type)) {
5454 const page_t* page = (const page_t*) frame;
5455
5456 page_info->index_id = btr_page_get_index_id(page);
5457
5458 /* FIL_PAGE_INDEX and FIL_PAGE_RTREE are a bit special,
5459 their values are defined as 17855 and 17854, so we cannot
5460 use them to index into i_s_page_type[] array, its array index
5461 in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
5462 (1) for index pages or I_S_PAGE_TYPE_IBUF for
5463 change buffer index pages */
5464 if (page_info->index_id
5465 == static_cast<index_id_t>(DICT_IBUF_ID_MIN
5466 + IBUF_SPACE_ID)) {
5467 page_info->page_type = I_S_PAGE_TYPE_IBUF;
5468 } else if (page_type == FIL_PAGE_RTREE) {
5469 page_info->page_type = I_S_PAGE_TYPE_RTREE;
5470 } else {
5471 page_info->page_type = I_S_PAGE_TYPE_INDEX;
5472 }
5473
5474 page_info->data_size = (ulint)(page_header_get_field(
5475 page, PAGE_HEAP_TOP) - (page_is_comp(page)
5476 ? PAGE_NEW_SUPREMUM_END
5477 : PAGE_OLD_SUPREMUM_END)
5478 - page_header_get_field(page, PAGE_GARBAGE));
5479
5480 page_info->num_recs = page_get_n_recs(page);
5481 } else if (page_type > FIL_PAGE_TYPE_LAST) {
5482 /* Encountered an unknown page type */
5483 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5484 } else {
5485 /* Make sure we get the right index into the
5486 i_s_page_type[] array */
5487 ut_a(page_type == i_s_page_type[page_type].type_value);
5488
5489 page_info->page_type = page_type;
5490 }
5491
5492 if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
5493 || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
5494 page_info->page_num = mach_read_from_4(
5495 frame + FIL_PAGE_OFFSET);
5496 page_info->space_id = mach_read_from_4(
5497 frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
5498 }
5499 }
5500 /*******************************************************************//**
5501 Scans pages in the buffer cache, and collect their general information
5502 into the buf_page_info_t array which is zero-filled. So any fields
5503 that are not initialized in the function will default to 0 */
5504 static
5505 void
i_s_innodb_buffer_page_get_info(const buf_page_t * bpage,ulint pool_id,ulint pos,buf_page_info_t * page_info)5506 i_s_innodb_buffer_page_get_info(
5507 /*============================*/
5508 const buf_page_t*bpage, /*!< in: buffer pool page to scan */
5509 ulint pool_id, /*!< in: buffer pool id */
5510 ulint pos, /*!< in: buffer block position in
5511 buffer pool or in the LRU list */
5512 buf_page_info_t*page_info) /*!< in: zero filled info structure;
5513 out: structure filled with scanned
5514 info */
5515 {
5516 ut_ad(pool_id < MAX_BUFFER_POOLS);
5517
5518 page_info->pool_id = pool_id;
5519
5520 page_info->block_id = pos;
5521
5522 page_info->page_state = buf_page_get_state(bpage);
5523
5524 /* Only fetch information for buffers that map to a tablespace,
5525 that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
5526 BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
5527 if (buf_page_in_file(bpage)) {
5528 const byte* frame;
5529 ulint page_type;
5530
5531 page_info->space_id = bpage->id.space();
5532
5533 page_info->page_num = bpage->id.page_no();
5534
5535 page_info->flush_type = bpage->flush_type;
5536
5537 page_info->fix_count = bpage->buf_fix_count;
5538
5539 page_info->newest_mod = bpage->newest_modification;
5540
5541 page_info->oldest_mod = bpage->oldest_modification;
5542
5543 page_info->access_time = bpage->access_time;
5544
5545 page_info->zip_ssize = bpage->zip.ssize;
5546
5547 page_info->io_fix = bpage->io_fix;
5548
5549 page_info->is_old = bpage->old;
5550
5551 page_info->freed_page_clock = bpage->freed_page_clock;
5552
5553 switch (buf_page_get_io_fix(bpage)) {
5554 case BUF_IO_NONE:
5555 case BUF_IO_WRITE:
5556 case BUF_IO_PIN:
5557 break;
5558 case BUF_IO_READ:
5559 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5560 return;
5561 }
5562
5563 if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
5564 const buf_block_t*block;
5565
5566 block = reinterpret_cast<const buf_block_t*>(bpage);
5567 frame = block->frame;
5568 /* Note: this may be a false positive, that
5569 is, block->index will not always be set to
5570 NULL when the last adaptive hash index
5571 reference is dropped. */
5572 page_info->hashed = (block->index != NULL);
5573 } else {
5574 ut_ad(page_info->zip_ssize);
5575 frame = bpage->zip.data;
5576 }
5577
5578 page_type = fil_page_get_type(frame);
5579
5580 i_s_innodb_set_page_type(page_info, page_type, frame);
5581 } else {
5582 page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5583 }
5584 }
5585
5586 /*******************************************************************//**
5587 This is the function that goes through each block of the buffer pool
5588 and fetch information to information schema tables: INNODB_BUFFER_PAGE.
5589 @return 0 on success, 1 on failure */
5590 static
5591 int
i_s_innodb_fill_buffer_pool(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5592 i_s_innodb_fill_buffer_pool(
5593 /*========================*/
5594 THD* thd, /*!< in: thread */
5595 TABLE_LIST* tables, /*!< in/out: tables to fill */
5596 buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
5597 const ulint pool_id) /*!< in: buffer pool id */
5598 {
5599 int status = 0;
5600 mem_heap_t* heap;
5601
5602 DBUG_ENTER("i_s_innodb_fill_buffer_pool");
5603
5604 heap = mem_heap_create(10000);
5605
5606 /* Go through each chunk of buffer pool. Currently, we only
5607 have one single chunk for each buffer pool */
5608 for (ulint n = 0;
5609 n < ut_min(buf_pool->n_chunks, buf_pool->n_chunks_new); n++) {
5610 const buf_block_t* block;
5611 ulint n_blocks;
5612 buf_page_info_t* info_buffer;
5613 ulint num_page;
5614 ulint mem_size;
5615 ulint chunk_size;
5616 ulint num_to_process = 0;
5617 ulint block_id = 0;
5618
5619 /* Get buffer block of the nth chunk */
5620 block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
5621 num_page = 0;
5622
5623 while (chunk_size > 0) {
5624 /* we cache maximum MAX_BUF_INFO_CACHED number of
5625 buffer page info */
5626 num_to_process = ut_min(chunk_size,
5627 MAX_BUF_INFO_CACHED);
5628
5629 mem_size = num_to_process * sizeof(buf_page_info_t);
5630
5631 /* For each chunk, we'll pre-allocate information
5632 structures to cache the page information read from
5633 the buffer pool. Doing so before obtain any mutex */
5634 info_buffer = (buf_page_info_t*) mem_heap_zalloc(
5635 heap, mem_size);
5636
5637 /* Obtain appropriate mutexes. Since this is diagnostic
5638 buffer pool info printout, we are not required to
5639 preserve the overall consistency, so we can
5640 release mutex periodically */
5641 buf_pool_mutex_enter(buf_pool);
5642
5643 /* GO through each block in the chunk */
5644 for (n_blocks = num_to_process; n_blocks--; block++) {
5645 i_s_innodb_buffer_page_get_info(
5646 &block->page, pool_id, block_id,
5647 info_buffer + num_page);
5648 block_id++;
5649 num_page++;
5650 }
5651
5652 buf_pool_mutex_exit(buf_pool);
5653
5654 /* Fill in information schema table with information
5655 just collected from the buffer chunk scan */
5656 status = i_s_innodb_buffer_page_fill(
5657 thd, tables, info_buffer,
5658 num_page);
5659
5660 /* If something goes wrong, break and return */
5661 if (status) {
5662 break;
5663 }
5664
5665 mem_heap_empty(heap);
5666 chunk_size -= num_to_process;
5667 num_page = 0;
5668 }
5669 }
5670
5671 mem_heap_free(heap);
5672
5673 DBUG_RETURN(status);
5674 }
5675
5676 /*******************************************************************//**
5677 Fill page information for pages in InnoDB buffer pool to the
5678 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
5679 @return 0 on success, 1 on failure */
5680 static
5681 int
i_s_innodb_buffer_page_fill_table(THD * thd,TABLE_LIST * tables,Item *)5682 i_s_innodb_buffer_page_fill_table(
5683 /*==============================*/
5684 THD* thd, /*!< in: thread */
5685 TABLE_LIST* tables, /*!< in/out: tables to fill */
5686 Item* ) /*!< in: condition (ignored) */
5687 {
5688 int status = 0;
5689
5690 DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
5691
5692 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5693
5694 /* deny access to user without PROCESS privilege */
5695 if (check_global_access(thd, PROCESS_ACL)) {
5696 DBUG_RETURN(0);
5697 }
5698
5699 /* Walk through each buffer pool */
5700 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5701 buf_pool_t* buf_pool;
5702
5703 buf_pool = buf_pool_from_array(i);
5704
5705 /* Fetch information from pages in this buffer pool,
5706 and fill the corresponding I_S table */
5707 status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
5708
5709 /* If something wrong, break and return */
5710 if (status) {
5711 break;
5712 }
5713 }
5714
5715 DBUG_RETURN(status);
5716 }
5717
5718 /*******************************************************************//**
5719 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
5720 @return 0 on success, 1 on failure */
5721 static
5722 int
i_s_innodb_buffer_page_init(void * p)5723 i_s_innodb_buffer_page_init(
5724 /*========================*/
5725 void* p) /*!< in/out: table schema object */
5726 {
5727 ST_SCHEMA_TABLE* schema;
5728
5729 DBUG_ENTER("i_s_innodb_buffer_page_init");
5730
5731 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5732
5733 schema->fields_info = i_s_innodb_buffer_page_fields_info;
5734 schema->fill_table = i_s_innodb_buffer_page_fill_table;
5735
5736 DBUG_RETURN(0);
5737 }
5738
5739 struct st_mysql_plugin i_s_innodb_buffer_page =
5740 {
5741 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
5742 /* int */
5743 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5744
5745 /* pointer to type-specific plugin descriptor */
5746 /* void* */
5747 STRUCT_FLD(info, &i_s_info),
5748
5749 /* plugin name */
5750 /* const char* */
5751 STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
5752
5753 /* plugin author (for SHOW PLUGINS) */
5754 /* const char* */
5755 STRUCT_FLD(author, plugin_author),
5756
5757 /* general descriptive text (for SHOW PLUGINS) */
5758 /* const char* */
5759 STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
5760
5761 /* the plugin license (PLUGIN_LICENSE_XXX) */
5762 /* int */
5763 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5764
5765 /* the function to invoke when plugin is loaded */
5766 /* int (*)(void*); */
5767 STRUCT_FLD(init, i_s_innodb_buffer_page_init),
5768
5769 /* the function to invoke when plugin is unloaded */
5770 /* int (*)(void*); */
5771 STRUCT_FLD(deinit, i_s_common_deinit),
5772
5773 /* plugin version (for SHOW PLUGINS) */
5774 /* unsigned int */
5775 STRUCT_FLD(version, INNODB_VERSION_SHORT),
5776
5777 /* struct st_mysql_show_var* */
5778 STRUCT_FLD(status_vars, NULL),
5779
5780 /* struct st_mysql_sys_var** */
5781 STRUCT_FLD(system_vars, NULL),
5782
5783 /* reserved for dependency checking */
5784 /* void* */
5785 STRUCT_FLD(__reserved1, NULL),
5786
5787 /* Plugin flags */
5788 /* unsigned long */
5789 STRUCT_FLD(flags, 0UL),
5790 };
5791
5792 static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] =
5793 {
5794 #define IDX_BUF_LRU_POOL_ID 0
5795 {STRUCT_FLD(field_name, "POOL_ID"),
5796 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5797 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5798 STRUCT_FLD(value, 0),
5799 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5800 STRUCT_FLD(old_name, ""),
5801 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5802
5803 #define IDX_BUF_LRU_POS 1
5804 {STRUCT_FLD(field_name, "LRU_POSITION"),
5805 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5806 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5807 STRUCT_FLD(value, 0),
5808 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5809 STRUCT_FLD(old_name, ""),
5810 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5811
5812 #define IDX_BUF_LRU_PAGE_SPACE 2
5813 {STRUCT_FLD(field_name, "SPACE"),
5814 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5815 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5816 STRUCT_FLD(value, 0),
5817 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5818 STRUCT_FLD(old_name, ""),
5819 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5820
5821 #define IDX_BUF_LRU_PAGE_NUM 3
5822 {STRUCT_FLD(field_name, "PAGE_NUMBER"),
5823 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5824 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5825 STRUCT_FLD(value, 0),
5826 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5827 STRUCT_FLD(old_name, ""),
5828 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5829
5830 #define IDX_BUF_LRU_PAGE_TYPE 4
5831 {STRUCT_FLD(field_name, "PAGE_TYPE"),
5832 STRUCT_FLD(field_length, 64),
5833 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5834 STRUCT_FLD(value, 0),
5835 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5836 STRUCT_FLD(old_name, ""),
5837 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5838
5839 #define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5
5840 {STRUCT_FLD(field_name, "FLUSH_TYPE"),
5841 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5842 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5843 STRUCT_FLD(value, 0),
5844 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5845 STRUCT_FLD(old_name, ""),
5846 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5847
5848 #define IDX_BUF_LRU_PAGE_FIX_COUNT 6
5849 {STRUCT_FLD(field_name, "FIX_COUNT"),
5850 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5851 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5852 STRUCT_FLD(value, 0),
5853 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5854 STRUCT_FLD(old_name, ""),
5855 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5856
5857 #define IDX_BUF_LRU_PAGE_HASHED 7
5858 {STRUCT_FLD(field_name, "IS_HASHED"),
5859 STRUCT_FLD(field_length, 3),
5860 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5861 STRUCT_FLD(value, 0),
5862 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5863 STRUCT_FLD(old_name, ""),
5864 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5865
5866 #define IDX_BUF_LRU_PAGE_NEWEST_MOD 8
5867 {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"),
5868 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5869 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5870 STRUCT_FLD(value, 0),
5871 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5872 STRUCT_FLD(old_name, ""),
5873 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5874
5875 #define IDX_BUF_LRU_PAGE_OLDEST_MOD 9
5876 {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"),
5877 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5878 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5879 STRUCT_FLD(value, 0),
5880 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5881 STRUCT_FLD(old_name, ""),
5882 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5883
5884 #define IDX_BUF_LRU_PAGE_ACCESS_TIME 10
5885 {STRUCT_FLD(field_name, "ACCESS_TIME"),
5886 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5887 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5888 STRUCT_FLD(value, 0),
5889 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5890 STRUCT_FLD(old_name, ""),
5891 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5892
5893 #define IDX_BUF_LRU_PAGE_TABLE_NAME 11
5894 {STRUCT_FLD(field_name, "TABLE_NAME"),
5895 STRUCT_FLD(field_length, 1024),
5896 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5897 STRUCT_FLD(value, 0),
5898 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5899 STRUCT_FLD(old_name, ""),
5900 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5901
5902 #define IDX_BUF_LRU_PAGE_INDEX_NAME 12
5903 {STRUCT_FLD(field_name, "INDEX_NAME"),
5904 STRUCT_FLD(field_length, 1024),
5905 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5906 STRUCT_FLD(value, 0),
5907 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5908 STRUCT_FLD(old_name, ""),
5909 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5910
5911 #define IDX_BUF_LRU_PAGE_NUM_RECS 13
5912 {STRUCT_FLD(field_name, "NUMBER_RECORDS"),
5913 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5914 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5915 STRUCT_FLD(value, 0),
5916 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5917 STRUCT_FLD(old_name, ""),
5918 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5919
5920 #define IDX_BUF_LRU_PAGE_DATA_SIZE 14
5921 {STRUCT_FLD(field_name, "DATA_SIZE"),
5922 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5923 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5924 STRUCT_FLD(value, 0),
5925 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5926 STRUCT_FLD(old_name, ""),
5927 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5928
5929 #define IDX_BUF_LRU_PAGE_ZIP_SIZE 15
5930 {STRUCT_FLD(field_name, "COMPRESSED_SIZE"),
5931 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5932 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5933 STRUCT_FLD(value, 0),
5934 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5935 STRUCT_FLD(old_name, ""),
5936 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5937
5938 #define IDX_BUF_LRU_PAGE_STATE 16
5939 {STRUCT_FLD(field_name, "COMPRESSED"),
5940 STRUCT_FLD(field_length, 3),
5941 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5942 STRUCT_FLD(value, 0),
5943 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5944 STRUCT_FLD(old_name, ""),
5945 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5946
5947 #define IDX_BUF_LRU_PAGE_IO_FIX 17
5948 {STRUCT_FLD(field_name, "IO_FIX"),
5949 STRUCT_FLD(field_length, 64),
5950 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5951 STRUCT_FLD(value, 0),
5952 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5953 STRUCT_FLD(old_name, ""),
5954 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5955
5956 #define IDX_BUF_LRU_PAGE_IS_OLD 18
5957 {STRUCT_FLD(field_name, "IS_OLD"),
5958 STRUCT_FLD(field_length, 3),
5959 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
5960 STRUCT_FLD(value, 0),
5961 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
5962 STRUCT_FLD(old_name, ""),
5963 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5964
5965 #define IDX_BUF_LRU_PAGE_FREE_CLOCK 19
5966 {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"),
5967 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
5968 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
5969 STRUCT_FLD(value, 0),
5970 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
5971 STRUCT_FLD(old_name, ""),
5972 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
5973
5974 END_OF_ST_FIELD_INFO
5975 };
5976
5977 /*******************************************************************//**
5978 Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
5979 cached in the buf_page_info_t array
5980 @return 0 on success, 1 on failure */
5981 static
5982 int
i_s_innodb_buf_page_lru_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5983 i_s_innodb_buf_page_lru_fill(
5984 /*=========================*/
5985 THD* thd, /*!< in: thread */
5986 TABLE_LIST* tables, /*!< in/out: tables to fill */
5987 const buf_page_info_t* info_array, /*!< in: array cached page
5988 info */
5989 ulint num_page) /*!< in: number of page info
5990 cached */
5991 {
5992 TABLE* table;
5993 Field** fields;
5994 mem_heap_t* heap;
5995
5996 DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
5997
5998 table = tables->table;
5999
6000 fields = table->field;
6001
6002 heap = mem_heap_create(1000);
6003
6004 /* Iterate through the cached array and fill the I_S table rows */
6005 for (ulint i = 0; i < num_page; i++) {
6006 const buf_page_info_t* page_info;
6007 char table_name[MAX_FULL_NAME_LEN + 1];
6008 const char* table_name_end = NULL;
6009 const char* state_str;
6010 enum buf_page_state state;
6011
6012 state_str = NULL;
6013
6014 page_info = info_array + i;
6015
6016 OK(fields[IDX_BUF_LRU_POOL_ID]->store(
6017 page_info->pool_id, true));
6018
6019 OK(fields[IDX_BUF_LRU_POS]->store(
6020 page_info->block_id, true));
6021
6022 OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(
6023 page_info->space_id, true));
6024
6025 OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(
6026 page_info->page_num, true));
6027
6028 OK(field_store_string(
6029 fields[IDX_BUF_LRU_PAGE_TYPE],
6030 i_s_page_type[page_info->page_type].type_str));
6031
6032 OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
6033 page_info->flush_type, true));
6034
6035 OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
6036 page_info->fix_count, true));
6037
6038 if (page_info->hashed) {
6039 OK(field_store_string(
6040 fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
6041 } else {
6042 OK(field_store_string(
6043 fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
6044 }
6045
6046 OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
6047 page_info->newest_mod, true));
6048
6049 OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
6050 page_info->oldest_mod, true));
6051
6052 OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
6053 page_info->access_time, true));
6054
6055 fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null();
6056
6057 fields[IDX_BUF_LRU_PAGE_INDEX_NAME]->set_null();
6058
6059 /* If this is an index page, fetch the index name
6060 and table name */
6061 if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
6062 const dict_index_t* index;
6063
6064 mutex_enter(&dict_sys->mutex);
6065 index = dict_index_get_if_in_cache_low(
6066 page_info->index_id);
6067
6068 if (index) {
6069
6070 table_name_end = innobase_convert_name(
6071 table_name, sizeof(table_name),
6072 index->table_name,
6073 strlen(index->table_name),
6074 thd);
6075
6076 OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store(
6077 table_name,
6078 static_cast<size_t>(table_name_end - table_name),
6079 system_charset_info));
6080 fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull();
6081
6082 OK(field_store_index_name(
6083 fields[IDX_BUF_LRU_PAGE_INDEX_NAME],
6084 index->name));
6085 }
6086
6087 mutex_exit(&dict_sys->mutex);
6088 }
6089
6090 OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
6091 page_info->num_recs, true));
6092
6093 OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
6094 page_info->data_size, true));
6095
6096 OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
6097 page_info->zip_ssize ?
6098 512 << page_info->zip_ssize : 0, true));
6099
6100 state = static_cast<enum buf_page_state>(page_info->page_state);
6101
6102 switch (state) {
6103 /* Compressed page */
6104 case BUF_BLOCK_ZIP_PAGE:
6105 case BUF_BLOCK_ZIP_DIRTY:
6106 state_str = "YES";
6107 break;
6108 /* Uncompressed page */
6109 case BUF_BLOCK_FILE_PAGE:
6110 state_str = "NO";
6111 break;
6112 /* We should not see following states */
6113 case BUF_BLOCK_POOL_WATCH:
6114 case BUF_BLOCK_READY_FOR_USE:
6115 case BUF_BLOCK_NOT_USED:
6116 case BUF_BLOCK_MEMORY:
6117 case BUF_BLOCK_REMOVE_HASH:
6118 state_str = NULL;
6119 break;
6120 };
6121
6122 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
6123 state_str));
6124
6125 switch (page_info->io_fix) {
6126 case BUF_IO_NONE:
6127 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6128 "IO_NONE"));
6129 break;
6130 case BUF_IO_READ:
6131 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6132 "IO_READ"));
6133 break;
6134 case BUF_IO_WRITE:
6135 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6136 "IO_WRITE"));
6137 break;
6138 }
6139
6140 OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
6141 (page_info->is_old) ? "YES" : "NO"));
6142
6143 OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
6144 page_info->freed_page_clock, true));
6145
6146 if (schema_table_store_record(thd, table)) {
6147 mem_heap_free(heap);
6148 DBUG_RETURN(1);
6149 }
6150
6151 mem_heap_empty(heap);
6152 }
6153
6154 mem_heap_free(heap);
6155
6156 DBUG_RETURN(0);
6157 }
6158
6159 /*******************************************************************//**
6160 This is the function that goes through buffer pool's LRU list
6161 and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
6162 @return 0 on success, 1 on failure */
6163 static
6164 int
i_s_innodb_fill_buffer_lru(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)6165 i_s_innodb_fill_buffer_lru(
6166 /*=======================*/
6167 THD* thd, /*!< in: thread */
6168 TABLE_LIST* tables, /*!< in/out: tables to fill */
6169 buf_pool_t* buf_pool, /*!< in: buffer pool to scan */
6170 const ulint pool_id) /*!< in: buffer pool id */
6171 {
6172 int status = 0;
6173 buf_page_info_t* info_buffer;
6174 ulint lru_pos = 0;
6175 const buf_page_t* bpage;
6176 ulint lru_len;
6177
6178 DBUG_ENTER("i_s_innodb_fill_buffer_lru");
6179
6180 /* Obtain buf_pool mutex before allocate info_buffer, since
6181 UT_LIST_GET_LEN(buf_pool->LRU) could change */
6182 buf_pool_mutex_enter(buf_pool);
6183
6184 lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
6185
6186 /* Print error message if malloc fail */
6187 info_buffer = (buf_page_info_t*) my_malloc(PSI_INSTRUMENT_ME,
6188 lru_len * sizeof *info_buffer, MYF(MY_WME));
6189
6190 if (!info_buffer) {
6191 status = 1;
6192 goto exit;
6193 }
6194
6195 memset(info_buffer, 0, lru_len * sizeof *info_buffer);
6196
6197 /* Walk through Pool's LRU list and print the buffer page
6198 information */
6199 bpage = UT_LIST_GET_LAST(buf_pool->LRU);
6200
6201 while (bpage != NULL) {
6202 /* Use the same function that collect buffer info for
6203 INNODB_BUFFER_PAGE to get buffer page info */
6204 i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
6205 (info_buffer + lru_pos));
6206
6207 bpage = UT_LIST_GET_PREV(LRU, bpage);
6208
6209 lru_pos++;
6210 }
6211
6212 ut_ad(lru_pos == lru_len);
6213 ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
6214
6215 exit:
6216 buf_pool_mutex_exit(buf_pool);
6217
6218 if (info_buffer) {
6219 status = i_s_innodb_buf_page_lru_fill(
6220 thd, tables, info_buffer, lru_len);
6221
6222 my_free(info_buffer);
6223 }
6224
6225 DBUG_RETURN(status);
6226 }
6227
6228 /*******************************************************************//**
6229 Fill page information for pages in InnoDB buffer pool to the
6230 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
6231 @return 0 on success, 1 on failure */
6232 static
6233 int
i_s_innodb_buf_page_lru_fill_table(THD * thd,TABLE_LIST * tables,Item *)6234 i_s_innodb_buf_page_lru_fill_table(
6235 /*===============================*/
6236 THD* thd, /*!< in: thread */
6237 TABLE_LIST* tables, /*!< in/out: tables to fill */
6238 Item* ) /*!< in: condition (ignored) */
6239 {
6240 int status = 0;
6241
6242 DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
6243
6244 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6245
6246 /* deny access to any users that do not hold PROCESS_ACL */
6247 if (check_global_access(thd, PROCESS_ACL)) {
6248 DBUG_RETURN(0);
6249 }
6250
6251 /* Walk through each buffer pool */
6252 for (ulint i = 0; i < srv_buf_pool_instances; i++) {
6253 buf_pool_t* buf_pool;
6254
6255 buf_pool = buf_pool_from_array(i);
6256
6257 /* Fetch information from pages in this buffer pool's LRU list,
6258 and fill the corresponding I_S table */
6259 status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
6260
6261 /* If something wrong, break and return */
6262 if (status) {
6263 break;
6264 }
6265 }
6266
6267 DBUG_RETURN(status);
6268 }
6269
6270 /*******************************************************************//**
6271 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
6272 @return 0 on success, 1 on failure */
6273 static
6274 int
i_s_innodb_buffer_page_lru_init(void * p)6275 i_s_innodb_buffer_page_lru_init(
6276 /*============================*/
6277 void* p) /*!< in/out: table schema object */
6278 {
6279 ST_SCHEMA_TABLE* schema;
6280
6281 DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
6282
6283 schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
6284
6285 schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
6286 schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
6287
6288 DBUG_RETURN(0);
6289 }
6290
6291 struct st_mysql_plugin i_s_innodb_buffer_page_lru =
6292 {
6293 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6294 /* int */
6295 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6296
6297 /* pointer to type-specific plugin descriptor */
6298 /* void* */
6299 STRUCT_FLD(info, &i_s_info),
6300
6301 /* plugin name */
6302 /* const char* */
6303 STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
6304
6305 /* plugin author (for SHOW PLUGINS) */
6306 /* const char* */
6307 STRUCT_FLD(author, plugin_author),
6308
6309 /* general descriptive text (for SHOW PLUGINS) */
6310 /* const char* */
6311 STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
6312
6313 /* the plugin license (PLUGIN_LICENSE_XXX) */
6314 /* int */
6315 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6316
6317 /* the function to invoke when plugin is loaded */
6318 /* int (*)(void*); */
6319 STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
6320
6321 /* the function to invoke when plugin is unloaded */
6322 /* int (*)(void*); */
6323 STRUCT_FLD(deinit, i_s_common_deinit),
6324
6325 /* plugin version (for SHOW PLUGINS) */
6326 /* unsigned int */
6327 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6328
6329 /* struct st_mysql_show_var* */
6330 STRUCT_FLD(status_vars, NULL),
6331
6332 /* struct st_mysql_sys_var** */
6333 STRUCT_FLD(system_vars, NULL),
6334
6335 /* reserved for dependency checking */
6336 /* void* */
6337 STRUCT_FLD(__reserved1, NULL),
6338
6339 /* Plugin flags */
6340 /* unsigned long */
6341 STRUCT_FLD(flags, 0UL),
6342 };
6343
6344 /*******************************************************************//**
6345 Unbind a dynamic INFORMATION_SCHEMA table.
6346 @return 0 on success */
6347 static
6348 int
i_s_common_deinit(void * p)6349 i_s_common_deinit(
6350 /*==============*/
6351 void* p) /*!< in/out: table schema object */
6352 {
6353 DBUG_ENTER("i_s_common_deinit");
6354
6355 /* Do nothing */
6356
6357 DBUG_RETURN(0);
6358 }
6359
6360 /** SYS_TABLES ***************************************************/
6361 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
6362 static ST_FIELD_INFO innodb_sys_tables_fields_info[] =
6363 {
6364 #define SYS_TABLES_ID 0
6365 {STRUCT_FLD(field_name, "TABLE_ID"),
6366 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6367 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6368 STRUCT_FLD(value, 0),
6369 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6370 STRUCT_FLD(old_name, ""),
6371 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6372
6373 #define SYS_TABLES_NAME 1
6374 {STRUCT_FLD(field_name, "NAME"),
6375 STRUCT_FLD(field_length, MAX_FULL_NAME_LEN + 1),
6376 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6377 STRUCT_FLD(value, 0),
6378 STRUCT_FLD(field_flags, 0),
6379 STRUCT_FLD(old_name, ""),
6380 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6381
6382 #define SYS_TABLES_FLAG 2
6383 {STRUCT_FLD(field_name, "FLAG"),
6384 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6385 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6386 STRUCT_FLD(value, 0),
6387 STRUCT_FLD(field_flags, 0),
6388 STRUCT_FLD(old_name, ""),
6389 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6390
6391 #define SYS_TABLES_NUM_COLUMN 3
6392 {STRUCT_FLD(field_name, "N_COLS"),
6393 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6394 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6395 STRUCT_FLD(value, 0),
6396 STRUCT_FLD(field_flags, 0),
6397 STRUCT_FLD(old_name, ""),
6398 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6399
6400 #define SYS_TABLES_SPACE 4
6401 {STRUCT_FLD(field_name, "SPACE"),
6402 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6403 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6404 STRUCT_FLD(value, 0),
6405 STRUCT_FLD(field_flags, 0),
6406 STRUCT_FLD(old_name, ""),
6407 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6408
6409 #define SYS_TABLES_FILE_FORMAT 5
6410 {STRUCT_FLD(field_name, "FILE_FORMAT"),
6411 STRUCT_FLD(field_length, 10),
6412 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6413 STRUCT_FLD(value, 0),
6414 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
6415 STRUCT_FLD(old_name, ""),
6416 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6417
6418 #define SYS_TABLES_ROW_FORMAT 6
6419 {STRUCT_FLD(field_name, "ROW_FORMAT"),
6420 STRUCT_FLD(field_length, 12),
6421 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6422 STRUCT_FLD(value, 0),
6423 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
6424 STRUCT_FLD(old_name, ""),
6425 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6426
6427 #define SYS_TABLES_ZIP_PAGE_SIZE 7
6428 {STRUCT_FLD(field_name, "ZIP_PAGE_SIZE"),
6429 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6430 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6431 STRUCT_FLD(value, 0),
6432 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6433 STRUCT_FLD(old_name, ""),
6434 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6435
6436 #define SYS_TABLES_SPACE_TYPE 8
6437 {STRUCT_FLD(field_name, "SPACE_TYPE"),
6438 STRUCT_FLD(field_length, 10),
6439 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6440 STRUCT_FLD(value, 0),
6441 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
6442 STRUCT_FLD(old_name, ""),
6443 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6444
6445 END_OF_ST_FIELD_INFO
6446 };
6447
6448 /**********************************************************************//**
6449 Populate information_schema.innodb_sys_tables table with information
6450 from SYS_TABLES.
6451 @return 0 on success */
6452 static
6453 int
i_s_dict_fill_sys_tables(THD * thd,dict_table_t * table,TABLE * table_to_fill)6454 i_s_dict_fill_sys_tables(
6455 /*=====================*/
6456 THD* thd, /*!< in: thread */
6457 dict_table_t* table, /*!< in: table */
6458 TABLE* table_to_fill) /*!< in/out: fill this table */
6459 {
6460 Field** fields;
6461 ulint compact = DICT_TF_GET_COMPACT(table->flags);
6462 ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(
6463 table->flags);
6464 const page_size_t& page_size = dict_tf_get_page_size(table->flags);
6465 const char* file_format;
6466 const char* row_format;
6467 const char* space_type;
6468
6469 file_format = trx_sys_file_format_id_to_name(atomic_blobs);
6470 if (!compact) {
6471 row_format = "Redundant";
6472 } else if (!atomic_blobs) {
6473 row_format = "Compact";
6474 } else if (DICT_TF_GET_ZIP_SSIZE(table->flags)) {
6475 row_format = "Compressed";
6476 } else {
6477 row_format = "Dynamic";
6478 }
6479
6480 if (is_system_tablespace(table->space)) {
6481 space_type = "System";
6482 } else if (DICT_TF_HAS_SHARED_SPACE(table->flags)) {
6483 space_type = "General";
6484 } else {
6485 space_type = "Single";
6486 }
6487
6488 DBUG_ENTER("i_s_dict_fill_sys_tables");
6489
6490 fields = table_to_fill->field;
6491
6492 OK(fields[SYS_TABLES_ID]->store(longlong(table->id), TRUE));
6493
6494 OK(field_store_string(fields[SYS_TABLES_NAME], table->name.m_name));
6495
6496 OK(fields[SYS_TABLES_FLAG]->store(table->flags));
6497
6498 OK(fields[SYS_TABLES_NUM_COLUMN]->store(table->n_cols));
6499
6500 OK(fields[SYS_TABLES_SPACE]->store(table->space));
6501
6502 OK(field_store_string(fields[SYS_TABLES_FILE_FORMAT], file_format));
6503
6504 OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
6505
6506 OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(page_size.is_compressed()
6507 ? page_size.physical()
6508 : 0, true));
6509
6510 OK(field_store_string(fields[SYS_TABLES_SPACE_TYPE], space_type));
6511
6512 OK(schema_table_store_record(thd, table_to_fill));
6513
6514 DBUG_RETURN(0);
6515 }
6516 /*******************************************************************//**
6517 Function to go through each record in SYS_TABLES table, and fill the
6518 information_schema.innodb_sys_tables table with related table information
6519 @return 0 on success */
6520 static
6521 int
i_s_sys_tables_fill_table(THD * thd,TABLE_LIST * tables,Item *)6522 i_s_sys_tables_fill_table(
6523 /*======================*/
6524 THD* thd, /*!< in: thread */
6525 TABLE_LIST* tables, /*!< in/out: tables to fill */
6526 Item* ) /*!< in: condition (not used) */
6527 {
6528 btr_pcur_t pcur;
6529 const rec_t* rec;
6530 mem_heap_t* heap;
6531 mtr_t mtr;
6532
6533 DBUG_ENTER("i_s_sys_tables_fill_table");
6534 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6535
6536 /* deny access to user without PROCESS_ACL privilege */
6537 if (check_global_access(thd, PROCESS_ACL)) {
6538 DBUG_RETURN(0);
6539 }
6540
6541 heap = mem_heap_create(1000);
6542 mutex_enter(&dict_sys->mutex);
6543 mtr_start(&mtr);
6544
6545 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6546
6547 while (rec) {
6548 const char* err_msg;
6549 dict_table_t* table_rec;
6550
6551 /* Create and populate a dict_table_t structure with
6552 information from SYS_TABLES row */
6553 err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6554 heap, rec, &table_rec,
6555 DICT_TABLE_LOAD_FROM_RECORD, &mtr);
6556
6557 mutex_exit(&dict_sys->mutex);
6558
6559 if (!err_msg) {
6560 i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
6561 } else {
6562 push_warning_printf(thd, Sql_condition::SL_WARNING,
6563 ER_CANT_FIND_SYSTEM_REC, "%s",
6564 err_msg);
6565 }
6566
6567 /* Since dict_process_sys_tables_rec_and_mtr_commit()
6568 is called with DICT_TABLE_LOAD_FROM_RECORD, the table_rec
6569 is created in dict_process_sys_tables_rec(), we will
6570 need to free it */
6571 if (table_rec) {
6572 dict_mem_table_free(table_rec);
6573 }
6574
6575 mem_heap_empty(heap);
6576
6577 /* Get the next record */
6578 mutex_enter(&dict_sys->mutex);
6579 mtr_start(&mtr);
6580 rec = dict_getnext_system(&pcur, &mtr);
6581 }
6582
6583 mtr_commit(&mtr);
6584 mutex_exit(&dict_sys->mutex);
6585 mem_heap_free(heap);
6586
6587 DBUG_RETURN(0);
6588 }
6589
6590 /*******************************************************************//**
6591 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
6592 @return 0 on success */
6593 static
6594 int
innodb_sys_tables_init(void * p)6595 innodb_sys_tables_init(
6596 /*===================*/
6597 void* p) /*!< in/out: table schema object */
6598 {
6599 ST_SCHEMA_TABLE* schema;
6600
6601 DBUG_ENTER("innodb_sys_tables_init");
6602
6603 schema = (ST_SCHEMA_TABLE*) p;
6604
6605 schema->fields_info = innodb_sys_tables_fields_info;
6606 schema->fill_table = i_s_sys_tables_fill_table;
6607
6608 DBUG_RETURN(0);
6609 }
6610
6611 struct st_mysql_plugin i_s_innodb_sys_tables =
6612 {
6613 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6614 /* int */
6615 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6616
6617 /* pointer to type-specific plugin descriptor */
6618 /* void* */
6619 STRUCT_FLD(info, &i_s_info),
6620
6621 /* plugin name */
6622 /* const char* */
6623 STRUCT_FLD(name, "INNODB_SYS_TABLES"),
6624
6625 /* plugin author (for SHOW PLUGINS) */
6626 /* const char* */
6627 STRUCT_FLD(author, plugin_author),
6628
6629 /* general descriptive text (for SHOW PLUGINS) */
6630 /* const char* */
6631 STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
6632
6633 /* the plugin license (PLUGIN_LICENSE_XXX) */
6634 /* int */
6635 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6636
6637 /* the function to invoke when plugin is loaded */
6638 /* int (*)(void*); */
6639 STRUCT_FLD(init, innodb_sys_tables_init),
6640
6641 /* the function to invoke when plugin is unloaded */
6642 /* int (*)(void*); */
6643 STRUCT_FLD(deinit, i_s_common_deinit),
6644
6645 /* plugin version (for SHOW PLUGINS) */
6646 /* unsigned int */
6647 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6648
6649 /* struct st_mysql_show_var* */
6650 STRUCT_FLD(status_vars, NULL),
6651
6652 /* struct st_mysql_sys_var** */
6653 STRUCT_FLD(system_vars, NULL),
6654
6655 /* reserved for dependency checking */
6656 /* void* */
6657 STRUCT_FLD(__reserved1, NULL),
6658
6659 /* Plugin flags */
6660 /* unsigned long */
6661 STRUCT_FLD(flags, 0UL),
6662 };
6663
6664 /** SYS_TABLESTATS ***********************************************/
6665 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
6666 static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
6667 {
6668 #define SYS_TABLESTATS_ID 0
6669 {STRUCT_FLD(field_name, "TABLE_ID"),
6670 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6671 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6672 STRUCT_FLD(value, 0),
6673 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6674 STRUCT_FLD(old_name, ""),
6675 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6676
6677 #define SYS_TABLESTATS_NAME 1
6678 {STRUCT_FLD(field_name, "NAME"),
6679 STRUCT_FLD(field_length, NAME_LEN + 1),
6680 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6681 STRUCT_FLD(value, 0),
6682 STRUCT_FLD(field_flags, 0),
6683 STRUCT_FLD(old_name, ""),
6684 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6685
6686 #define SYS_TABLESTATS_INIT 2
6687 {STRUCT_FLD(field_name, "STATS_INITIALIZED"),
6688 STRUCT_FLD(field_length, NAME_LEN + 1),
6689 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6690 STRUCT_FLD(value, 0),
6691 STRUCT_FLD(field_flags, 0),
6692 STRUCT_FLD(old_name, ""),
6693 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6694
6695 #define SYS_TABLESTATS_NROW 3
6696 {STRUCT_FLD(field_name, "NUM_ROWS"),
6697 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6698 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6699 STRUCT_FLD(value, 0),
6700 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6701 STRUCT_FLD(old_name, ""),
6702 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6703
6704 #define SYS_TABLESTATS_CLUST_SIZE 4
6705 {STRUCT_FLD(field_name, "CLUST_INDEX_SIZE"),
6706 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6707 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6708 STRUCT_FLD(value, 0),
6709 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6710 STRUCT_FLD(old_name, ""),
6711 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6712
6713 #define SYS_TABLESTATS_INDEX_SIZE 5
6714 {STRUCT_FLD(field_name, "OTHER_INDEX_SIZE"),
6715 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6716 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6717 STRUCT_FLD(value, 0),
6718 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6719 STRUCT_FLD(old_name, ""),
6720 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6721
6722 #define SYS_TABLESTATS_MODIFIED 6
6723 {STRUCT_FLD(field_name, "MODIFIED_COUNTER"),
6724 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6725 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6726 STRUCT_FLD(value, 0),
6727 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6728 STRUCT_FLD(old_name, ""),
6729 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6730
6731 #define SYS_TABLESTATS_AUTONINC 7
6732 {STRUCT_FLD(field_name, "AUTOINC"),
6733 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6734 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6735 STRUCT_FLD(value, 0),
6736 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6737 STRUCT_FLD(old_name, ""),
6738 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6739
6740 #define SYS_TABLESTATS_TABLE_REF_COUNT 8
6741 {STRUCT_FLD(field_name, "REF_COUNT"),
6742 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
6743 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
6744 STRUCT_FLD(value, 0),
6745 STRUCT_FLD(field_flags, 0),
6746 STRUCT_FLD(old_name, ""),
6747 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6748
6749 END_OF_ST_FIELD_INFO
6750 };
6751
6752 /** Populate information_schema.innodb_sys_tablestats table with information
6753 from SYS_TABLES.
6754 @param[in] thd thread ID
6755 @param[in,out] table table
6756 @param[in] ref_count table reference count
6757 @param[in,out] table_to_fill fill this table
6758 @return 0 on success */
6759 static
6760 int
i_s_dict_fill_sys_tablestats(THD * thd,dict_table_t * table,ulint ref_count,TABLE * table_to_fill)6761 i_s_dict_fill_sys_tablestats(
6762 THD* thd,
6763 dict_table_t* table,
6764 ulint ref_count,
6765 TABLE* table_to_fill)
6766 {
6767 Field** fields;
6768
6769 DBUG_ENTER("i_s_dict_fill_sys_tablestats");
6770
6771 fields = table_to_fill->field;
6772
6773 OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
6774
6775 OK(field_store_string(fields[SYS_TABLESTATS_NAME],
6776 table->name.m_name));
6777
6778 dict_table_stats_lock(table, RW_S_LATCH);
6779
6780 if (table->stat_initialized) {
6781 OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6782 "Initialized"));
6783
6784 OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows,
6785 true));
6786
6787 OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
6788 table->stat_clustered_index_size, true));
6789
6790 OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
6791 table->stat_sum_of_other_index_sizes, true));
6792
6793 OK(fields[SYS_TABLESTATS_MODIFIED]->store(
6794 table->stat_modified_counter, true));
6795 } else {
6796 OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6797 "Uninitialized"));
6798
6799 OK(fields[SYS_TABLESTATS_NROW]->store(0, true));
6800
6801 OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0, true));
6802
6803 OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0, true));
6804
6805 OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
6806 }
6807
6808 dict_table_stats_unlock(table, RW_S_LATCH);
6809
6810 OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, true));
6811
6812 OK(fields[SYS_TABLESTATS_TABLE_REF_COUNT]->store(ref_count, true));
6813
6814 OK(schema_table_store_record(thd, table_to_fill));
6815
6816 DBUG_RETURN(0);
6817 }
6818
6819 /*******************************************************************//**
6820 Function to go through each record in SYS_TABLES table, and fill the
6821 information_schema.innodb_sys_tablestats table with table statistics
6822 related information
6823 @return 0 on success */
6824 static
6825 int
i_s_sys_tables_fill_table_stats(THD * thd,TABLE_LIST * tables,Item *)6826 i_s_sys_tables_fill_table_stats(
6827 /*============================*/
6828 THD* thd, /*!< in: thread */
6829 TABLE_LIST* tables, /*!< in/out: tables to fill */
6830 Item* ) /*!< in: condition (not used) */
6831 {
6832 btr_pcur_t pcur;
6833 const rec_t* rec;
6834 mem_heap_t* heap;
6835 mtr_t mtr;
6836
6837 DBUG_ENTER("i_s_sys_tables_fill_table_stats");
6838 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6839
6840 /* deny access to user without PROCESS_ACL privilege */
6841 if (check_global_access(thd, PROCESS_ACL)) {
6842 DBUG_RETURN(0);
6843 }
6844
6845 heap = mem_heap_create(1000);
6846 mutex_enter(&dict_sys->mutex);
6847 mtr_start(&mtr);
6848
6849 rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6850
6851 while (rec) {
6852 const char* err_msg;
6853 dict_table_t* table_rec;
6854 ulint ref_count = 0;
6855
6856 /* Fetch the dict_table_t structure corresponding to
6857 this SYS_TABLES record */
6858 err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6859 heap, rec, &table_rec,
6860 DICT_TABLE_LOAD_FROM_CACHE, &mtr);
6861
6862 if (table_rec != NULL) {
6863 ut_ad(err_msg == NULL);
6864
6865 ref_count = table_rec->get_ref_count();
6866
6867 /* Protect the dict_table_t object by incrementing
6868 the reference count. */
6869 table_rec->acquire();
6870 }
6871
6872 mutex_exit(&dict_sys->mutex);
6873
6874 DBUG_EXECUTE_IF("test_sys_tablestats", {
6875 if (strcmp("test/t1", table_rec->name.m_name) == 0 ) {
6876 DEBUG_SYNC_C("dict_table_not_protected");
6877 }});
6878
6879 if (table_rec != NULL) {
6880 i_s_dict_fill_sys_tablestats(thd, table_rec, ref_count,
6881 tables->table);
6882 } else {
6883 push_warning_printf(thd, Sql_condition::SL_WARNING,
6884 ER_CANT_FIND_SYSTEM_REC, "%s",
6885 err_msg);
6886 }
6887
6888 mem_heap_empty(heap);
6889
6890 /* Get the next record */
6891 mutex_enter(&dict_sys->mutex);
6892
6893 if (table_rec != NULL) {
6894 table_rec->release();
6895 }
6896
6897 mtr_start(&mtr);
6898 rec = dict_getnext_system(&pcur, &mtr);
6899 }
6900
6901 mtr_commit(&mtr);
6902 mutex_exit(&dict_sys->mutex);
6903 mem_heap_free(heap);
6904
6905 DBUG_RETURN(0);
6906 }
6907
6908 /*******************************************************************//**
6909 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
6910 @return 0 on success */
6911 static
6912 int
innodb_sys_tablestats_init(void * p)6913 innodb_sys_tablestats_init(
6914 /*=======================*/
6915 void* p) /*!< in/out: table schema object */
6916 {
6917 ST_SCHEMA_TABLE* schema;
6918
6919 DBUG_ENTER("innodb_sys_tablestats_init");
6920
6921 schema = (ST_SCHEMA_TABLE*) p;
6922
6923 schema->fields_info = innodb_sys_tablestats_fields_info;
6924 schema->fill_table = i_s_sys_tables_fill_table_stats;
6925
6926 DBUG_RETURN(0);
6927 }
6928
6929 struct st_mysql_plugin i_s_innodb_sys_tablestats =
6930 {
6931 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
6932 /* int */
6933 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6934
6935 /* pointer to type-specific plugin descriptor */
6936 /* void* */
6937 STRUCT_FLD(info, &i_s_info),
6938
6939 /* plugin name */
6940 /* const char* */
6941 STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
6942
6943 /* plugin author (for SHOW PLUGINS) */
6944 /* const char* */
6945 STRUCT_FLD(author, plugin_author),
6946
6947 /* general descriptive text (for SHOW PLUGINS) */
6948 /* const char* */
6949 STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
6950
6951 /* the plugin license (PLUGIN_LICENSE_XXX) */
6952 /* int */
6953 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6954
6955 /* the function to invoke when plugin is loaded */
6956 /* int (*)(void*); */
6957 STRUCT_FLD(init, innodb_sys_tablestats_init),
6958
6959 /* the function to invoke when plugin is unloaded */
6960 /* int (*)(void*); */
6961 STRUCT_FLD(deinit, i_s_common_deinit),
6962
6963 /* plugin version (for SHOW PLUGINS) */
6964 /* unsigned int */
6965 STRUCT_FLD(version, INNODB_VERSION_SHORT),
6966
6967 /* struct st_mysql_show_var* */
6968 STRUCT_FLD(status_vars, NULL),
6969
6970 /* struct st_mysql_sys_var** */
6971 STRUCT_FLD(system_vars, NULL),
6972
6973 /* reserved for dependency checking */
6974 /* void* */
6975 STRUCT_FLD(__reserved1, NULL),
6976
6977 /* Plugin flags */
6978 /* unsigned long */
6979 STRUCT_FLD(flags, 0UL),
6980 };
6981
6982 /** SYS_INDEXES **************************************************/
6983 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
6984 static ST_FIELD_INFO innodb_sysindex_fields_info[] =
6985 {
6986 #define SYS_INDEX_ID 0
6987 {STRUCT_FLD(field_name, "INDEX_ID"),
6988 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
6989 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
6990 STRUCT_FLD(value, 0),
6991 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
6992 STRUCT_FLD(old_name, ""),
6993 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
6994
6995 #define SYS_INDEX_NAME 1
6996 {STRUCT_FLD(field_name, "NAME"),
6997 STRUCT_FLD(field_length, NAME_LEN + 1),
6998 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
6999 STRUCT_FLD(value, 0),
7000 STRUCT_FLD(field_flags, 0),
7001 STRUCT_FLD(old_name, ""),
7002 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7003
7004 #define SYS_INDEX_TABLE_ID 2
7005 {STRUCT_FLD(field_name, "TABLE_ID"),
7006 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7007 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7008 STRUCT_FLD(value, 0),
7009 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7010 STRUCT_FLD(old_name, ""),
7011 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7012
7013 #define SYS_INDEX_TYPE 3
7014 {STRUCT_FLD(field_name, "TYPE"),
7015 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7016 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7017 STRUCT_FLD(value, 0),
7018 STRUCT_FLD(field_flags, 0),
7019 STRUCT_FLD(old_name, ""),
7020 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7021
7022 #define SYS_INDEX_NUM_FIELDS 4
7023 {STRUCT_FLD(field_name, "N_FIELDS"),
7024 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7025 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7026 STRUCT_FLD(value, 0),
7027 STRUCT_FLD(field_flags, 0),
7028 STRUCT_FLD(old_name, ""),
7029 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7030
7031 #define SYS_INDEX_PAGE_NO 5
7032 {STRUCT_FLD(field_name, "PAGE_NO"),
7033 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7034 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7035 STRUCT_FLD(value, 0),
7036 STRUCT_FLD(field_flags, 0),
7037 STRUCT_FLD(old_name, ""),
7038 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7039
7040 #define SYS_INDEX_SPACE 6
7041 {STRUCT_FLD(field_name, "SPACE"),
7042 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7043 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7044 STRUCT_FLD(value, 0),
7045 STRUCT_FLD(field_flags, 0),
7046 STRUCT_FLD(old_name, ""),
7047 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7048
7049 #define SYS_INDEX_MERGE_THRESHOLD 7
7050 {STRUCT_FLD(field_name, "MERGE_THRESHOLD"),
7051 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7052 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7053 STRUCT_FLD(value, 0),
7054 STRUCT_FLD(field_flags, 0),
7055 STRUCT_FLD(old_name, ""),
7056 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7057
7058 END_OF_ST_FIELD_INFO
7059 };
7060
7061 /**********************************************************************//**
7062 Function to populate the information_schema.innodb_sys_indexes table with
7063 collected index information
7064 @return 0 on success */
7065 static
7066 int
i_s_dict_fill_sys_indexes(THD * thd,table_id_t table_id,dict_index_t * index,TABLE * table_to_fill)7067 i_s_dict_fill_sys_indexes(
7068 /*======================*/
7069 THD* thd, /*!< in: thread */
7070 table_id_t table_id, /*!< in: table id */
7071 dict_index_t* index, /*!< in: populated dict_index_t
7072 struct with index info */
7073 TABLE* table_to_fill) /*!< in/out: fill this table */
7074 {
7075 Field** fields;
7076
7077 DBUG_ENTER("i_s_dict_fill_sys_indexes");
7078
7079 fields = table_to_fill->field;
7080
7081 OK(field_store_index_name(fields[SYS_INDEX_NAME], index->name));
7082
7083 OK(fields[SYS_INDEX_ID]->store(longlong(index->id), true));
7084
7085 OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), true));
7086
7087 OK(fields[SYS_INDEX_TYPE]->store(index->type));
7088
7089 OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
7090
7091 /* FIL_NULL is ULINT32_UNDEFINED */
7092 if (index->page == FIL_NULL) {
7093 OK(fields[SYS_INDEX_PAGE_NO]->store(-1));
7094 } else {
7095 OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
7096 }
7097
7098 OK(fields[SYS_INDEX_SPACE]->store(index->space));
7099
7100 OK(fields[SYS_INDEX_MERGE_THRESHOLD]->store(index->merge_threshold));
7101
7102 OK(schema_table_store_record(thd, table_to_fill));
7103
7104 DBUG_RETURN(0);
7105 }
7106 /*******************************************************************//**
7107 Function to go through each record in SYS_INDEXES table, and fill the
7108 information_schema.innodb_sys_indexes table with related index information
7109 @return 0 on success */
7110 static
7111 int
i_s_sys_indexes_fill_table(THD * thd,TABLE_LIST * tables,Item *)7112 i_s_sys_indexes_fill_table(
7113 /*=======================*/
7114 THD* thd, /*!< in: thread */
7115 TABLE_LIST* tables, /*!< in/out: tables to fill */
7116 Item* ) /*!< in: condition (not used) */
7117 {
7118 btr_pcur_t pcur;
7119 const rec_t* rec;
7120 mem_heap_t* heap;
7121 mtr_t mtr;
7122
7123 DBUG_ENTER("i_s_sys_indexes_fill_table");
7124 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7125
7126 /* deny access to user without PROCESS_ACL privilege */
7127 if (check_global_access(thd, PROCESS_ACL)) {
7128 DBUG_RETURN(0);
7129 }
7130
7131 heap = mem_heap_create(1000);
7132 mutex_enter(&dict_sys->mutex);
7133 mtr_start(&mtr);
7134
7135 /* Start scan the SYS_INDEXES table */
7136 rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
7137
7138 /* Process each record in the table */
7139 while (rec) {
7140 const char* err_msg;
7141 table_id_t table_id;
7142 dict_index_t index_rec;
7143
7144 /* Populate a dict_index_t structure with information from
7145 a SYS_INDEXES row */
7146 err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
7147 &table_id);
7148
7149 mtr_commit(&mtr);
7150 mutex_exit(&dict_sys->mutex);
7151
7152 if (!err_msg) {
7153 i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
7154 tables->table);
7155 } else {
7156 push_warning_printf(thd, Sql_condition::SL_WARNING,
7157 ER_CANT_FIND_SYSTEM_REC, "%s",
7158 err_msg);
7159 }
7160
7161 mem_heap_empty(heap);
7162
7163 /* Get the next record */
7164 mutex_enter(&dict_sys->mutex);
7165 mtr_start(&mtr);
7166 rec = dict_getnext_system(&pcur, &mtr);
7167 }
7168
7169 mtr_commit(&mtr);
7170 mutex_exit(&dict_sys->mutex);
7171 mem_heap_free(heap);
7172
7173 DBUG_RETURN(0);
7174 }
7175 /*******************************************************************//**
7176 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
7177 @return 0 on success */
7178 static
7179 int
innodb_sys_indexes_init(void * p)7180 innodb_sys_indexes_init(
7181 /*====================*/
7182 void* p) /*!< in/out: table schema object */
7183 {
7184 ST_SCHEMA_TABLE* schema;
7185
7186 DBUG_ENTER("innodb_sys_indexes_init");
7187
7188 schema = (ST_SCHEMA_TABLE*) p;
7189
7190 schema->fields_info = innodb_sysindex_fields_info;
7191 schema->fill_table = i_s_sys_indexes_fill_table;
7192
7193 DBUG_RETURN(0);
7194 }
7195
7196 struct st_mysql_plugin i_s_innodb_sys_indexes =
7197 {
7198 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7199 /* int */
7200 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7201
7202 /* pointer to type-specific plugin descriptor */
7203 /* void* */
7204 STRUCT_FLD(info, &i_s_info),
7205
7206 /* plugin name */
7207 /* const char* */
7208 STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
7209
7210 /* plugin author (for SHOW PLUGINS) */
7211 /* const char* */
7212 STRUCT_FLD(author, plugin_author),
7213
7214 /* general descriptive text (for SHOW PLUGINS) */
7215 /* const char* */
7216 STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
7217
7218 /* the plugin license (PLUGIN_LICENSE_XXX) */
7219 /* int */
7220 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7221
7222 /* the function to invoke when plugin is loaded */
7223 /* int (*)(void*); */
7224 STRUCT_FLD(init, innodb_sys_indexes_init),
7225
7226 /* the function to invoke when plugin is unloaded */
7227 /* int (*)(void*); */
7228 STRUCT_FLD(deinit, i_s_common_deinit),
7229
7230 /* plugin version (for SHOW PLUGINS) */
7231 /* unsigned int */
7232 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7233
7234 /* struct st_mysql_show_var* */
7235 STRUCT_FLD(status_vars, NULL),
7236
7237 /* struct st_mysql_sys_var** */
7238 STRUCT_FLD(system_vars, NULL),
7239
7240 /* reserved for dependency checking */
7241 /* void* */
7242 STRUCT_FLD(__reserved1, NULL),
7243
7244 /* Plugin flags */
7245 /* unsigned long */
7246 STRUCT_FLD(flags, 0UL),
7247 };
7248
7249 /** SYS_COLUMNS **************************************************/
7250 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_COLUMNS */
7251 static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
7252 {
7253 #define SYS_COLUMN_TABLE_ID 0
7254 {STRUCT_FLD(field_name, "TABLE_ID"),
7255 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7256 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7257 STRUCT_FLD(value, 0),
7258 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7259 STRUCT_FLD(old_name, ""),
7260 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7261
7262 #define SYS_COLUMN_NAME 1
7263 {STRUCT_FLD(field_name, "NAME"),
7264 STRUCT_FLD(field_length, NAME_LEN + 1),
7265 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7266 STRUCT_FLD(value, 0),
7267 STRUCT_FLD(field_flags, 0),
7268 STRUCT_FLD(old_name, ""),
7269 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7270
7271 #define SYS_COLUMN_POSITION 2
7272 {STRUCT_FLD(field_name, "POS"),
7273 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7274 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7275 STRUCT_FLD(value, 0),
7276 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7277 STRUCT_FLD(old_name, ""),
7278 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7279
7280 #define SYS_COLUMN_MTYPE 3
7281 {STRUCT_FLD(field_name, "MTYPE"),
7282 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7283 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7284 STRUCT_FLD(value, 0),
7285 STRUCT_FLD(field_flags, 0),
7286 STRUCT_FLD(old_name, ""),
7287 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7288
7289 #define SYS_COLUMN__PRTYPE 4
7290 {STRUCT_FLD(field_name, "PRTYPE"),
7291 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7292 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7293 STRUCT_FLD(value, 0),
7294 STRUCT_FLD(field_flags, 0),
7295 STRUCT_FLD(old_name, ""),
7296 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7297
7298 #define SYS_COLUMN_COLUMN_LEN 5
7299 {STRUCT_FLD(field_name, "LEN"),
7300 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7301 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7302 STRUCT_FLD(value, 0),
7303 STRUCT_FLD(field_flags, 0),
7304 STRUCT_FLD(old_name, ""),
7305 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7306
7307 END_OF_ST_FIELD_INFO
7308 };
7309
7310 /**********************************************************************//**
7311 Function to populate the information_schema.innodb_sys_columns with
7312 related column information
7313 @return 0 on success */
7314 static
7315 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)7316 i_s_dict_fill_sys_columns(
7317 /*======================*/
7318 THD* thd, /*!< in: thread */
7319 table_id_t table_id, /*!< in: table ID */
7320 const char* col_name, /*!< in: column name */
7321 dict_col_t* column, /*!< in: dict_col_t struct holding
7322 more column information */
7323 ulint nth_v_col, /*!< in: virtual column, its
7324 sequence number (nth virtual col) */
7325 TABLE* table_to_fill) /*!< in/out: fill this table */
7326 {
7327 Field** fields;
7328
7329 DBUG_ENTER("i_s_dict_fill_sys_columns");
7330
7331 fields = table_to_fill->field;
7332
7333 OK(fields[SYS_COLUMN_TABLE_ID]->store((longlong)table_id, true));
7334
7335 OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
7336
7337 if (dict_col_is_virtual(column)) {
7338 ulint pos = dict_create_v_col_pos(nth_v_col, column->ind);
7339 OK(fields[SYS_COLUMN_POSITION]->store(pos, true));
7340 } else {
7341 OK(fields[SYS_COLUMN_POSITION]->store(column->ind, true));
7342 }
7343
7344 OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
7345
7346 OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
7347
7348 OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
7349
7350 OK(schema_table_store_record(thd, table_to_fill));
7351
7352 DBUG_RETURN(0);
7353 }
7354 /*******************************************************************//**
7355 Function to fill information_schema.innodb_sys_columns with information
7356 collected by scanning SYS_COLUMNS table.
7357 @return 0 on success */
7358 static
7359 int
i_s_sys_columns_fill_table(THD * thd,TABLE_LIST * tables,Item *)7360 i_s_sys_columns_fill_table(
7361 /*=======================*/
7362 THD* thd, /*!< in: thread */
7363 TABLE_LIST* tables, /*!< in/out: tables to fill */
7364 Item* ) /*!< in: condition (not used) */
7365 {
7366 btr_pcur_t pcur;
7367 const rec_t* rec;
7368 const char* col_name;
7369 mem_heap_t* heap;
7370 mtr_t mtr;
7371
7372 DBUG_ENTER("i_s_sys_columns_fill_table");
7373 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7374
7375 /* deny access to user without PROCESS_ACL privilege */
7376 if (check_global_access(thd, PROCESS_ACL)) {
7377 DBUG_RETURN(0);
7378 }
7379
7380 heap = mem_heap_create(1000);
7381 mutex_enter(&dict_sys->mutex);
7382 mtr_start(&mtr);
7383
7384 rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
7385
7386 while (rec) {
7387 const char* err_msg;
7388 dict_col_t column_rec;
7389 table_id_t table_id;
7390 ulint nth_v_col;
7391
7392 /* populate a dict_col_t structure with information from
7393 a SYS_COLUMNS row */
7394 err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
7395 &table_id, &col_name,
7396 &nth_v_col);
7397
7398 mtr_commit(&mtr);
7399 mutex_exit(&dict_sys->mutex);
7400
7401 if (!err_msg) {
7402 i_s_dict_fill_sys_columns(thd, table_id, col_name,
7403 &column_rec, nth_v_col,
7404 tables->table);
7405 } else {
7406 push_warning_printf(thd, Sql_condition::SL_WARNING,
7407 ER_CANT_FIND_SYSTEM_REC, "%s",
7408 err_msg);
7409 }
7410
7411 mem_heap_empty(heap);
7412
7413 /* Get the next record */
7414 mutex_enter(&dict_sys->mutex);
7415 mtr_start(&mtr);
7416 rec = dict_getnext_system(&pcur, &mtr);
7417 }
7418
7419 mtr_commit(&mtr);
7420 mutex_exit(&dict_sys->mutex);
7421 mem_heap_free(heap);
7422
7423 DBUG_RETURN(0);
7424 }
7425 /*******************************************************************//**
7426 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
7427 @return 0 on success */
7428 static
7429 int
innodb_sys_columns_init(void * p)7430 innodb_sys_columns_init(
7431 /*====================*/
7432 void* p) /*!< in/out: table schema object */
7433 {
7434 ST_SCHEMA_TABLE* schema;
7435
7436 DBUG_ENTER("innodb_sys_columns_init");
7437
7438 schema = (ST_SCHEMA_TABLE*) p;
7439
7440 schema->fields_info = innodb_sys_columns_fields_info;
7441 schema->fill_table = i_s_sys_columns_fill_table;
7442
7443 DBUG_RETURN(0);
7444 }
7445
7446 struct st_mysql_plugin i_s_innodb_sys_columns =
7447 {
7448 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7449 /* int */
7450 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7451
7452 /* pointer to type-specific plugin descriptor */
7453 /* void* */
7454 STRUCT_FLD(info, &i_s_info),
7455
7456 /* plugin name */
7457 /* const char* */
7458 STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
7459
7460 /* plugin author (for SHOW PLUGINS) */
7461 /* const char* */
7462 STRUCT_FLD(author, plugin_author),
7463
7464 /* general descriptive text (for SHOW PLUGINS) */
7465 /* const char* */
7466 STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
7467
7468 /* the plugin license (PLUGIN_LICENSE_XXX) */
7469 /* int */
7470 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7471
7472 /* the function to invoke when plugin is loaded */
7473 /* int (*)(void*); */
7474 STRUCT_FLD(init, innodb_sys_columns_init),
7475
7476 /* the function to invoke when plugin is unloaded */
7477 /* int (*)(void*); */
7478 STRUCT_FLD(deinit, i_s_common_deinit),
7479
7480 /* plugin version (for SHOW PLUGINS) */
7481 /* unsigned int */
7482 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7483
7484 /* struct st_mysql_show_var* */
7485 STRUCT_FLD(status_vars, NULL),
7486
7487 /* struct st_mysql_sys_var** */
7488 STRUCT_FLD(system_vars, NULL),
7489
7490 /* reserved for dependency checking */
7491 /* void* */
7492 STRUCT_FLD(__reserved1, NULL),
7493
7494 /* Plugin flags */
7495 /* unsigned long */
7496 STRUCT_FLD(flags, 0UL),
7497 };
7498
7499 /** SYS_VIRTUAL **************************************************/
7500 /** Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL */
7501 static ST_FIELD_INFO innodb_sys_virtual_fields_info[] =
7502 {
7503 #define SYS_VIRTUAL_TABLE_ID 0
7504 {STRUCT_FLD(field_name, "TABLE_ID"),
7505 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7506 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7507 STRUCT_FLD(value, 0),
7508 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7509 STRUCT_FLD(old_name, ""),
7510 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7511
7512 #define SYS_VIRTUAL_POS 1
7513 {STRUCT_FLD(field_name, "POS"),
7514 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7515 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7516 STRUCT_FLD(value, 0),
7517 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7518 STRUCT_FLD(old_name, ""),
7519 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7520
7521 #define SYS_VIRTUAL_BASE_POS 2
7522 {STRUCT_FLD(field_name, "BASE_POS"),
7523 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7524 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7525 STRUCT_FLD(value, 0),
7526 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7527 STRUCT_FLD(old_name, ""),
7528 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7529
7530 END_OF_ST_FIELD_INFO
7531 };
7532
7533 /** Function to populate the information_schema.innodb_sys_virtual with
7534 related information
7535 param[in] thd thread
7536 param[in] table_id table ID
7537 param[in] pos virtual column position
7538 param[in] base_pos base column position
7539 param[in,out] table_to_fill fill this table
7540 @return 0 on success */
7541 static
7542 int
i_s_dict_fill_sys_virtual(THD * thd,table_id_t table_id,ulint pos,ulint base_pos,TABLE * table_to_fill)7543 i_s_dict_fill_sys_virtual(
7544 THD* thd,
7545 table_id_t table_id,
7546 ulint pos,
7547 ulint base_pos,
7548 TABLE* table_to_fill)
7549 {
7550 Field** fields;
7551
7552 DBUG_ENTER("i_s_dict_fill_sys_virtual");
7553
7554 fields = table_to_fill->field;
7555
7556 OK(fields[SYS_VIRTUAL_TABLE_ID]->store(table_id, true));
7557
7558 OK(fields[SYS_VIRTUAL_POS]->store(pos, true));
7559
7560 OK(fields[SYS_VIRTUAL_BASE_POS]->store(base_pos, true));
7561
7562 OK(schema_table_store_record(thd, table_to_fill));
7563
7564 DBUG_RETURN(0);
7565 }
7566
7567 /** Function to fill information_schema.innodb_sys_virtual with information
7568 collected by scanning SYS_VIRTUAL table.
7569 param[in] thd thread
7570 param[in,out] tables tables to fill
7571 param[in] item condition (not used)
7572 @return 0 on success */
7573 static
7574 int
i_s_sys_virtual_fill_table(THD * thd,TABLE_LIST * tables,Item *)7575 i_s_sys_virtual_fill_table(
7576 THD* thd,
7577 TABLE_LIST* tables,
7578 Item* )
7579 {
7580 btr_pcur_t pcur;
7581 const rec_t* rec;
7582 ulint pos;
7583 ulint base_pos;
7584 mem_heap_t* heap;
7585 mtr_t mtr;
7586
7587 DBUG_ENTER("i_s_sys_virtual_fill_table");
7588 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7589
7590 /* deny access to user without PROCESS_ACL privilege */
7591 if (check_global_access(thd, PROCESS_ACL)) {
7592 DBUG_RETURN(0);
7593 }
7594
7595 heap = mem_heap_create(1000);
7596 mutex_enter(&dict_sys->mutex);
7597 mtr_start(&mtr);
7598
7599 rec = dict_startscan_system(&pcur, &mtr, SYS_VIRTUAL);
7600
7601 while (rec) {
7602 const char* err_msg;
7603 table_id_t table_id;
7604
7605 /* populate a dict_col_t structure with information from
7606 a SYS_VIRTUAL row */
7607 err_msg = dict_process_sys_virtual_rec(heap, rec,
7608 &table_id, &pos,
7609 &base_pos);
7610
7611 mtr_commit(&mtr);
7612 mutex_exit(&dict_sys->mutex);
7613
7614 if (!err_msg) {
7615 i_s_dict_fill_sys_virtual(thd, table_id, pos, base_pos,
7616 tables->table);
7617 } else {
7618 push_warning_printf(thd, Sql_condition::SL_WARNING,
7619 ER_CANT_FIND_SYSTEM_REC, "%s",
7620 err_msg);
7621 }
7622
7623 mem_heap_empty(heap);
7624
7625 /* Get the next record */
7626 mutex_enter(&dict_sys->mutex);
7627 mtr_start(&mtr);
7628 rec = dict_getnext_system(&pcur, &mtr);
7629 }
7630
7631 mtr_commit(&mtr);
7632 mutex_exit(&dict_sys->mutex);
7633 mem_heap_free(heap);
7634
7635 DBUG_RETURN(0);
7636 }
7637
7638 /** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_virtual
7639 param[in,out] p table schema object
7640 @return 0 on success */
7641 static
7642 int
innodb_sys_virtual_init(void * p)7643 innodb_sys_virtual_init(
7644 void* p)
7645 {
7646 ST_SCHEMA_TABLE* schema;
7647
7648 DBUG_ENTER("innodb_sys_virtual_init");
7649
7650 schema = (ST_SCHEMA_TABLE*) p;
7651
7652 schema->fields_info = innodb_sys_virtual_fields_info;
7653 schema->fill_table = i_s_sys_virtual_fill_table;
7654
7655 DBUG_RETURN(0);
7656 }
7657
7658 struct st_mysql_plugin i_s_innodb_sys_virtual =
7659 {
7660 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7661 /* int */
7662 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7663
7664 /* pointer to type-specific plugin descriptor */
7665 /* void* */
7666 STRUCT_FLD(info, &i_s_info),
7667
7668 /* plugin name */
7669 /* const char* */
7670 STRUCT_FLD(name, "INNODB_SYS_VIRTUAL"),
7671
7672 /* plugin author (for SHOW PLUGINS) */
7673 /* const char* */
7674 STRUCT_FLD(author, plugin_author),
7675
7676 /* general descriptive text (for SHOW PLUGINS) */
7677 /* const char* */
7678 STRUCT_FLD(descr, "InnoDB SYS_VIRTUAL"),
7679
7680 /* the plugin license (PLUGIN_LICENSE_XXX) */
7681 /* int */
7682 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7683
7684 /* the function to invoke when plugin is loaded */
7685 /* int (*)(void*); */
7686 STRUCT_FLD(init, innodb_sys_virtual_init),
7687
7688 /* the function to invoke when plugin is unloaded */
7689 /* int (*)(void*); */
7690 STRUCT_FLD(deinit, i_s_common_deinit),
7691
7692 /* plugin version (for SHOW PLUGINS) */
7693 /* unsigned int */
7694 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7695
7696 /* struct st_mysql_show_var* */
7697 STRUCT_FLD(status_vars, NULL),
7698
7699 /* struct st_mysql_sys_var** */
7700 STRUCT_FLD(system_vars, NULL),
7701
7702 /* reserved for dependency checking */
7703 /* void* */
7704 STRUCT_FLD(__reserved1, NULL),
7705
7706 /* Plugin flags */
7707 /* unsigned long */
7708 STRUCT_FLD(flags, 0UL),
7709 };
7710 /** SYS_FIELDS ***************************************************/
7711 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FIELDS */
7712 static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
7713 {
7714 #define SYS_FIELD_INDEX_ID 0
7715 {STRUCT_FLD(field_name, "INDEX_ID"),
7716 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
7717 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
7718 STRUCT_FLD(value, 0),
7719 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7720 STRUCT_FLD(old_name, ""),
7721 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7722
7723 #define SYS_FIELD_NAME 1
7724 {STRUCT_FLD(field_name, "NAME"),
7725 STRUCT_FLD(field_length, NAME_LEN + 1),
7726 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7727 STRUCT_FLD(value, 0),
7728 STRUCT_FLD(field_flags, 0),
7729 STRUCT_FLD(old_name, ""),
7730 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7731
7732 #define SYS_FIELD_POS 2
7733 {STRUCT_FLD(field_name, "POS"),
7734 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7735 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7736 STRUCT_FLD(value, 0),
7737 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7738 STRUCT_FLD(old_name, ""),
7739 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7740
7741 END_OF_ST_FIELD_INFO
7742 };
7743
7744 /**********************************************************************//**
7745 Function to fill information_schema.innodb_sys_fields with information
7746 collected by scanning SYS_FIELDS table.
7747 @return 0 on success */
7748 static
7749 int
i_s_dict_fill_sys_fields(THD * thd,index_id_t index_id,dict_field_t * field,ulint pos,TABLE * table_to_fill)7750 i_s_dict_fill_sys_fields(
7751 /*=====================*/
7752 THD* thd, /*!< in: thread */
7753 index_id_t index_id, /*!< in: index id for the field */
7754 dict_field_t* field, /*!< in: table */
7755 ulint pos, /*!< in: Field position */
7756 TABLE* table_to_fill) /*!< in/out: fill this table */
7757 {
7758 Field** fields;
7759
7760 DBUG_ENTER("i_s_dict_fill_sys_fields");
7761
7762 fields = table_to_fill->field;
7763
7764 OK(fields[SYS_FIELD_INDEX_ID]->store(index_id, true));
7765
7766 OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
7767
7768 OK(fields[SYS_FIELD_POS]->store(pos, true));
7769
7770 OK(schema_table_store_record(thd, table_to_fill));
7771
7772 DBUG_RETURN(0);
7773 }
7774 /*******************************************************************//**
7775 Function to go through each record in SYS_FIELDS table, and fill the
7776 information_schema.innodb_sys_fields table with related index field
7777 information
7778 @return 0 on success */
7779 static
7780 int
i_s_sys_fields_fill_table(THD * thd,TABLE_LIST * tables,Item *)7781 i_s_sys_fields_fill_table(
7782 /*======================*/
7783 THD* thd, /*!< in: thread */
7784 TABLE_LIST* tables, /*!< in/out: tables to fill */
7785 Item* ) /*!< in: condition (not used) */
7786 {
7787 btr_pcur_t pcur;
7788 const rec_t* rec;
7789 mem_heap_t* heap;
7790 index_id_t last_id;
7791 mtr_t mtr;
7792
7793 DBUG_ENTER("i_s_sys_fields_fill_table");
7794 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7795
7796 /* deny access to user without PROCESS_ACL privilege */
7797 if (check_global_access(thd, PROCESS_ACL)) {
7798
7799 DBUG_RETURN(0);
7800 }
7801
7802 heap = mem_heap_create(1000);
7803 mutex_enter(&dict_sys->mutex);
7804 mtr_start(&mtr);
7805
7806 /* will save last index id so that we know whether we move to
7807 the next index. This is used to calculate prefix length */
7808 last_id = 0;
7809
7810 rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
7811
7812 while (rec) {
7813 ulint pos;
7814 const char* err_msg;
7815 index_id_t index_id;
7816 dict_field_t field_rec;
7817
7818 /* Populate a dict_field_t structure with information from
7819 a SYS_FIELDS row */
7820 err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
7821 &pos, &index_id, last_id);
7822
7823 mtr_commit(&mtr);
7824 mutex_exit(&dict_sys->mutex);
7825
7826 if (!err_msg) {
7827 i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
7828 pos, tables->table);
7829 last_id = index_id;
7830 } else {
7831 push_warning_printf(thd, Sql_condition::SL_WARNING,
7832 ER_CANT_FIND_SYSTEM_REC, "%s",
7833 err_msg);
7834 }
7835
7836 mem_heap_empty(heap);
7837
7838 /* Get the next record */
7839 mutex_enter(&dict_sys->mutex);
7840 mtr_start(&mtr);
7841 rec = dict_getnext_system(&pcur, &mtr);
7842 }
7843
7844 mtr_commit(&mtr);
7845 mutex_exit(&dict_sys->mutex);
7846 mem_heap_free(heap);
7847
7848 DBUG_RETURN(0);
7849 }
7850 /*******************************************************************//**
7851 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
7852 @return 0 on success */
7853 static
7854 int
innodb_sys_fields_init(void * p)7855 innodb_sys_fields_init(
7856 /*===================*/
7857 void* p) /*!< in/out: table schema object */
7858 {
7859 ST_SCHEMA_TABLE* schema;
7860
7861 DBUG_ENTER("innodb_sys_field_init");
7862
7863 schema = (ST_SCHEMA_TABLE*) p;
7864
7865 schema->fields_info = innodb_sys_fields_fields_info;
7866 schema->fill_table = i_s_sys_fields_fill_table;
7867
7868 DBUG_RETURN(0);
7869 }
7870
7871 struct st_mysql_plugin i_s_innodb_sys_fields =
7872 {
7873 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
7874 /* int */
7875 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7876
7877 /* pointer to type-specific plugin descriptor */
7878 /* void* */
7879 STRUCT_FLD(info, &i_s_info),
7880
7881 /* plugin name */
7882 /* const char* */
7883 STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
7884
7885 /* plugin author (for SHOW PLUGINS) */
7886 /* const char* */
7887 STRUCT_FLD(author, plugin_author),
7888
7889 /* general descriptive text (for SHOW PLUGINS) */
7890 /* const char* */
7891 STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
7892
7893 /* the plugin license (PLUGIN_LICENSE_XXX) */
7894 /* int */
7895 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7896
7897 /* the function to invoke when plugin is loaded */
7898 /* int (*)(void*); */
7899 STRUCT_FLD(init, innodb_sys_fields_init),
7900
7901 /* the function to invoke when plugin is unloaded */
7902 /* int (*)(void*); */
7903 STRUCT_FLD(deinit, i_s_common_deinit),
7904
7905 /* plugin version (for SHOW PLUGINS) */
7906 /* unsigned int */
7907 STRUCT_FLD(version, INNODB_VERSION_SHORT),
7908
7909 /* struct st_mysql_show_var* */
7910 STRUCT_FLD(status_vars, NULL),
7911
7912 /* struct st_mysql_sys_var** */
7913 STRUCT_FLD(system_vars, NULL),
7914
7915 /* reserved for dependency checking */
7916 /* void* */
7917 STRUCT_FLD(__reserved1, NULL),
7918
7919 /* Plugin flags */
7920 /* unsigned long */
7921 STRUCT_FLD(flags, 0UL),
7922 };
7923
7924 /** SYS_FOREIGN ********************************************/
7925 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN */
7926 static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
7927 {
7928 #define SYS_FOREIGN_ID 0
7929 {STRUCT_FLD(field_name, "ID"),
7930 STRUCT_FLD(field_length, NAME_LEN + 1),
7931 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7932 STRUCT_FLD(value, 0),
7933 STRUCT_FLD(field_flags, 0),
7934 STRUCT_FLD(old_name, ""),
7935 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7936
7937 #define SYS_FOREIGN_FOR_NAME 1
7938 {STRUCT_FLD(field_name, "FOR_NAME"),
7939 STRUCT_FLD(field_length, NAME_LEN + 1),
7940 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7941 STRUCT_FLD(value, 0),
7942 STRUCT_FLD(field_flags, 0),
7943 STRUCT_FLD(old_name, ""),
7944 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7945
7946 #define SYS_FOREIGN_REF_NAME 2
7947 {STRUCT_FLD(field_name, "REF_NAME"),
7948 STRUCT_FLD(field_length, NAME_LEN + 1),
7949 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
7950 STRUCT_FLD(value, 0),
7951 STRUCT_FLD(field_flags, 0),
7952 STRUCT_FLD(old_name, ""),
7953 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7954
7955 #define SYS_FOREIGN_NUM_COL 3
7956 {STRUCT_FLD(field_name, "N_COLS"),
7957 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7958 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7959 STRUCT_FLD(value, 0),
7960 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7961 STRUCT_FLD(old_name, ""),
7962 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7963
7964 #define SYS_FOREIGN_TYPE 4
7965 {STRUCT_FLD(field_name, "TYPE"),
7966 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
7967 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
7968 STRUCT_FLD(value, 0),
7969 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
7970 STRUCT_FLD(old_name, ""),
7971 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
7972
7973 END_OF_ST_FIELD_INFO
7974 };
7975
7976 /**********************************************************************//**
7977 Function to fill information_schema.innodb_sys_foreign with information
7978 collected by scanning SYS_FOREIGN table.
7979 @return 0 on success */
7980 static
7981 int
i_s_dict_fill_sys_foreign(THD * thd,dict_foreign_t * foreign,TABLE * table_to_fill)7982 i_s_dict_fill_sys_foreign(
7983 /*======================*/
7984 THD* thd, /*!< in: thread */
7985 dict_foreign_t* foreign, /*!< in: table */
7986 TABLE* table_to_fill) /*!< in/out: fill this table */
7987 {
7988 Field** fields;
7989
7990 DBUG_ENTER("i_s_dict_fill_sys_foreign");
7991
7992 fields = table_to_fill->field;
7993
7994 OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
7995
7996 OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
7997 foreign->foreign_table_name));
7998
7999 OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
8000 foreign->referenced_table_name));
8001
8002 OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
8003
8004 OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
8005
8006 OK(schema_table_store_record(thd, table_to_fill));
8007
8008 DBUG_RETURN(0);
8009 }
8010
8011 /*******************************************************************//**
8012 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
8013 through each record in SYS_FOREIGN, and extract the foreign key
8014 information.
8015 @return 0 on success */
8016 static
8017 int
i_s_sys_foreign_fill_table(THD * thd,TABLE_LIST * tables,Item *)8018 i_s_sys_foreign_fill_table(
8019 /*=======================*/
8020 THD* thd, /*!< in: thread */
8021 TABLE_LIST* tables, /*!< in/out: tables to fill */
8022 Item* ) /*!< in: condition (not used) */
8023 {
8024 btr_pcur_t pcur;
8025 const rec_t* rec;
8026 mem_heap_t* heap;
8027 mtr_t mtr;
8028
8029 DBUG_ENTER("i_s_sys_foreign_fill_table");
8030 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8031
8032 /* deny access to user without PROCESS_ACL privilege */
8033 if (check_global_access(thd, PROCESS_ACL)) {
8034
8035 DBUG_RETURN(0);
8036 }
8037
8038 heap = mem_heap_create(1000);
8039 mutex_enter(&dict_sys->mutex);
8040 mtr_start(&mtr);
8041
8042 rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
8043
8044 while (rec) {
8045 const char* err_msg;
8046 dict_foreign_t foreign_rec;
8047
8048 /* Populate a dict_foreign_t structure with information from
8049 a SYS_FOREIGN row */
8050 err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
8051
8052 mtr_commit(&mtr);
8053 mutex_exit(&dict_sys->mutex);
8054
8055 if (!err_msg) {
8056 i_s_dict_fill_sys_foreign(thd, &foreign_rec,
8057 tables->table);
8058 } else {
8059 push_warning_printf(thd, Sql_condition::SL_WARNING,
8060 ER_CANT_FIND_SYSTEM_REC, "%s",
8061 err_msg);
8062 }
8063
8064 mem_heap_empty(heap);
8065
8066 /* Get the next record */
8067 mtr_start(&mtr);
8068 mutex_enter(&dict_sys->mutex);
8069 rec = dict_getnext_system(&pcur, &mtr);
8070 }
8071
8072 mtr_commit(&mtr);
8073 mutex_exit(&dict_sys->mutex);
8074 mem_heap_free(heap);
8075
8076 DBUG_RETURN(0);
8077 }
8078
8079 /*******************************************************************//**
8080 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
8081 @return 0 on success */
8082 static
8083 int
innodb_sys_foreign_init(void * p)8084 innodb_sys_foreign_init(
8085 /*====================*/
8086 void* p) /*!< in/out: table schema object */
8087 {
8088 ST_SCHEMA_TABLE* schema;
8089
8090 DBUG_ENTER("innodb_sys_foreign_init");
8091
8092 schema = (ST_SCHEMA_TABLE*) p;
8093
8094 schema->fields_info = innodb_sys_foreign_fields_info;
8095 schema->fill_table = i_s_sys_foreign_fill_table;
8096
8097 DBUG_RETURN(0);
8098 }
8099
8100 struct st_mysql_plugin i_s_innodb_sys_foreign =
8101 {
8102 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8103 /* int */
8104 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8105
8106 /* pointer to type-specific plugin descriptor */
8107 /* void* */
8108 STRUCT_FLD(info, &i_s_info),
8109
8110 /* plugin name */
8111 /* const char* */
8112 STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
8113
8114 /* plugin author (for SHOW PLUGINS) */
8115 /* const char* */
8116 STRUCT_FLD(author, plugin_author),
8117
8118 /* general descriptive text (for SHOW PLUGINS) */
8119 /* const char* */
8120 STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
8121
8122 /* the plugin license (PLUGIN_LICENSE_XXX) */
8123 /* int */
8124 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8125
8126 /* the function to invoke when plugin is loaded */
8127 /* int (*)(void*); */
8128 STRUCT_FLD(init, innodb_sys_foreign_init),
8129
8130 /* the function to invoke when plugin is unloaded */
8131 /* int (*)(void*); */
8132 STRUCT_FLD(deinit, i_s_common_deinit),
8133
8134 /* plugin version (for SHOW PLUGINS) */
8135 /* unsigned int */
8136 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8137
8138 /* struct st_mysql_show_var* */
8139 STRUCT_FLD(status_vars, NULL),
8140
8141 /* struct st_mysql_sys_var** */
8142 STRUCT_FLD(system_vars, NULL),
8143
8144 /* reserved for dependency checking */
8145 /* void* */
8146 STRUCT_FLD(__reserved1, NULL),
8147
8148 /* Plugin flags */
8149 /* unsigned long */
8150 STRUCT_FLD(flags, 0UL),
8151 };
8152
8153 /** SYS_FOREIGN_COLS ********************************************/
8154 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS */
8155 static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
8156 {
8157 #define SYS_FOREIGN_COL_ID 0
8158 {STRUCT_FLD(field_name, "ID"),
8159 STRUCT_FLD(field_length, NAME_LEN + 1),
8160 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8161 STRUCT_FLD(value, 0),
8162 STRUCT_FLD(field_flags, 0),
8163 STRUCT_FLD(old_name, ""),
8164 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8165
8166 #define SYS_FOREIGN_COL_FOR_NAME 1
8167 {STRUCT_FLD(field_name, "FOR_COL_NAME"),
8168 STRUCT_FLD(field_length, NAME_LEN + 1),
8169 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8170 STRUCT_FLD(value, 0),
8171 STRUCT_FLD(field_flags, 0),
8172 STRUCT_FLD(old_name, ""),
8173 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8174
8175 #define SYS_FOREIGN_COL_REF_NAME 2
8176 {STRUCT_FLD(field_name, "REF_COL_NAME"),
8177 STRUCT_FLD(field_length, NAME_LEN + 1),
8178 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8179 STRUCT_FLD(value, 0),
8180 STRUCT_FLD(field_flags, 0),
8181 STRUCT_FLD(old_name, ""),
8182 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8183
8184 #define SYS_FOREIGN_COL_POS 3
8185 {STRUCT_FLD(field_name, "POS"),
8186 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8187 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8188 STRUCT_FLD(value, 0),
8189 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8190 STRUCT_FLD(old_name, ""),
8191 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8192
8193 END_OF_ST_FIELD_INFO
8194 };
8195
8196 /**********************************************************************//**
8197 Function to fill information_schema.innodb_sys_foreign_cols with information
8198 collected by scanning SYS_FOREIGN_COLS table.
8199 @return 0 on success */
8200 static
8201 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)8202 i_s_dict_fill_sys_foreign_cols(
8203 /*==========================*/
8204 THD* thd, /*!< in: thread */
8205 const char* name, /*!< in: foreign key constraint name */
8206 const char* for_col_name, /*!< in: referencing column name*/
8207 const char* ref_col_name, /*!< in: referenced column
8208 name */
8209 ulint pos, /*!< in: column position */
8210 TABLE* table_to_fill) /*!< in/out: fill this table */
8211 {
8212 Field** fields;
8213
8214 DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
8215
8216 fields = table_to_fill->field;
8217
8218 OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
8219
8220 OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
8221
8222 OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
8223
8224 OK(fields[SYS_FOREIGN_COL_POS]->store(pos, true));
8225
8226 OK(schema_table_store_record(thd, table_to_fill));
8227
8228 DBUG_RETURN(0);
8229 }
8230 /*******************************************************************//**
8231 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
8232 through each record in SYS_FOREIGN_COLS, and extract the foreign key column
8233 information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
8234 @return 0 on success */
8235 static
8236 int
i_s_sys_foreign_cols_fill_table(THD * thd,TABLE_LIST * tables,Item *)8237 i_s_sys_foreign_cols_fill_table(
8238 /*============================*/
8239 THD* thd, /*!< in: thread */
8240 TABLE_LIST* tables, /*!< in/out: tables to fill */
8241 Item* ) /*!< in: condition (not used) */
8242 {
8243 btr_pcur_t pcur;
8244 const rec_t* rec;
8245 mem_heap_t* heap;
8246 mtr_t mtr;
8247
8248 DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
8249 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8250
8251 /* deny access to user without PROCESS_ACL privilege */
8252 if (check_global_access(thd, PROCESS_ACL)) {
8253 DBUG_RETURN(0);
8254 }
8255
8256 heap = mem_heap_create(1000);
8257 mutex_enter(&dict_sys->mutex);
8258 mtr_start(&mtr);
8259
8260 rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
8261
8262 while (rec) {
8263 const char* err_msg;
8264 const char* name;
8265 const char* for_col_name;
8266 const char* ref_col_name;
8267 ulint pos;
8268
8269 /* Extract necessary information from a SYS_FOREIGN_COLS row */
8270 err_msg = dict_process_sys_foreign_col_rec(
8271 heap, rec, &name, &for_col_name, &ref_col_name, &pos);
8272
8273 mtr_commit(&mtr);
8274 mutex_exit(&dict_sys->mutex);
8275
8276 if (!err_msg) {
8277 i_s_dict_fill_sys_foreign_cols(
8278 thd, name, for_col_name, ref_col_name, pos,
8279 tables->table);
8280 } else {
8281 push_warning_printf(thd, Sql_condition::SL_WARNING,
8282 ER_CANT_FIND_SYSTEM_REC, "%s",
8283 err_msg);
8284 }
8285
8286 mem_heap_empty(heap);
8287
8288 /* Get the next record */
8289 mutex_enter(&dict_sys->mutex);
8290 mtr_start(&mtr);
8291 rec = dict_getnext_system(&pcur, &mtr);
8292 }
8293
8294 mtr_commit(&mtr);
8295 mutex_exit(&dict_sys->mutex);
8296 mem_heap_free(heap);
8297
8298 DBUG_RETURN(0);
8299 }
8300 /*******************************************************************//**
8301 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
8302 @return 0 on success */
8303 static
8304 int
innodb_sys_foreign_cols_init(void * p)8305 innodb_sys_foreign_cols_init(
8306 /*========================*/
8307 void* p) /*!< in/out: table schema object */
8308 {
8309 ST_SCHEMA_TABLE* schema;
8310
8311 DBUG_ENTER("innodb_sys_foreign_cols_init");
8312
8313 schema = (ST_SCHEMA_TABLE*) p;
8314
8315 schema->fields_info = innodb_sys_foreign_cols_fields_info;
8316 schema->fill_table = i_s_sys_foreign_cols_fill_table;
8317
8318 DBUG_RETURN(0);
8319 }
8320
8321 struct st_mysql_plugin i_s_innodb_sys_foreign_cols =
8322 {
8323 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8324 /* int */
8325 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8326
8327 /* pointer to type-specific plugin descriptor */
8328 /* void* */
8329 STRUCT_FLD(info, &i_s_info),
8330
8331 /* plugin name */
8332 /* const char* */
8333 STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
8334
8335 /* plugin author (for SHOW PLUGINS) */
8336 /* const char* */
8337 STRUCT_FLD(author, plugin_author),
8338
8339 /* general descriptive text (for SHOW PLUGINS) */
8340 /* const char* */
8341 STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
8342
8343 /* the plugin license (PLUGIN_LICENSE_XXX) */
8344 /* int */
8345 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8346
8347 /* the function to invoke when plugin is loaded */
8348 /* int (*)(void*); */
8349 STRUCT_FLD(init, innodb_sys_foreign_cols_init),
8350
8351 /* the function to invoke when plugin is unloaded */
8352 /* int (*)(void*); */
8353 STRUCT_FLD(deinit, i_s_common_deinit),
8354
8355 /* plugin version (for SHOW PLUGINS) */
8356 /* unsigned int */
8357 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8358
8359 /* struct st_mysql_show_var* */
8360 STRUCT_FLD(status_vars, NULL),
8361
8362 /* struct st_mysql_sys_var** */
8363 STRUCT_FLD(system_vars, NULL),
8364
8365 /* reserved for dependency checking */
8366 /* void* */
8367 STRUCT_FLD(__reserved1, NULL),
8368
8369 /* Plugin flags */
8370 /* unsigned long */
8371 STRUCT_FLD(flags, 0UL),
8372 };
8373
8374 /** SYS_TABLESPACES ********************************************/
8375 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES */
8376 static ST_FIELD_INFO innodb_sys_tablespaces_fields_info[] =
8377 {
8378 #define SYS_TABLESPACES_SPACE 0
8379 {STRUCT_FLD(field_name, "SPACE"),
8380 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8381 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8382 STRUCT_FLD(value, 0),
8383 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8384 STRUCT_FLD(old_name, ""),
8385 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8386
8387 #define SYS_TABLESPACES_NAME 1
8388 {STRUCT_FLD(field_name, "NAME"),
8389 STRUCT_FLD(field_length, MAX_FULL_NAME_LEN + 1),
8390 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8391 STRUCT_FLD(value, 0),
8392 STRUCT_FLD(field_flags, 0),
8393 STRUCT_FLD(old_name, ""),
8394 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8395
8396 #define SYS_TABLESPACES_FLAGS 2
8397 {STRUCT_FLD(field_name, "FLAG"),
8398 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8399 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8400 STRUCT_FLD(value, 0),
8401 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8402 STRUCT_FLD(old_name, ""),
8403 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8404
8405 #define SYS_TABLESPACES_FILE_FORMAT 3
8406 {STRUCT_FLD(field_name, "FILE_FORMAT"),
8407 STRUCT_FLD(field_length, 10),
8408 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8409 STRUCT_FLD(value, 0),
8410 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
8411 STRUCT_FLD(old_name, ""),
8412 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8413
8414 #define SYS_TABLESPACES_ROW_FORMAT 4
8415 {STRUCT_FLD(field_name, "ROW_FORMAT"),
8416 STRUCT_FLD(field_length, 22),
8417 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8418 STRUCT_FLD(value, 0),
8419 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
8420 STRUCT_FLD(old_name, ""),
8421 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8422
8423 #define SYS_TABLESPACES_PAGE_SIZE 5
8424 {STRUCT_FLD(field_name, "PAGE_SIZE"),
8425 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8426 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8427 STRUCT_FLD(value, 0),
8428 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8429 STRUCT_FLD(old_name, ""),
8430 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8431
8432 #define SYS_TABLESPACES_ZIP_PAGE_SIZE 6
8433 {STRUCT_FLD(field_name, "ZIP_PAGE_SIZE"),
8434 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8435 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8436 STRUCT_FLD(value, 0),
8437 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8438 STRUCT_FLD(old_name, ""),
8439 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8440
8441 #define SYS_TABLESPACES_SPACE_TYPE 7
8442 {STRUCT_FLD(field_name, "SPACE_TYPE"),
8443 STRUCT_FLD(field_length, 10),
8444 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8445 STRUCT_FLD(value, 0),
8446 STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
8447 STRUCT_FLD(old_name, ""),
8448 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8449
8450 #define SYS_TABLESPACES_FS_BLOCK_SIZE 8
8451 {STRUCT_FLD(field_name, "FS_BLOCK_SIZE"),
8452 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8453 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8454 STRUCT_FLD(value, 0),
8455 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8456 STRUCT_FLD(old_name, ""),
8457 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8458
8459 #define SYS_TABLESPACES_FILE_SIZE 9
8460 {STRUCT_FLD(field_name, "FILE_SIZE"),
8461 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
8462 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
8463 STRUCT_FLD(value, 0),
8464 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8465 STRUCT_FLD(old_name, ""),
8466 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8467
8468 #define SYS_TABLESPACES_ALLOC_SIZE 10
8469 {STRUCT_FLD(field_name, "ALLOCATED_SIZE"),
8470 STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
8471 STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
8472 STRUCT_FLD(value, 0),
8473 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8474 STRUCT_FLD(old_name, ""),
8475 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8476
8477 END_OF_ST_FIELD_INFO
8478
8479 };
8480
8481 /**********************************************************************//**
8482 Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information
8483 collected by scanning SYS_TABLESPACESS table.
8484 @return 0 on success */
8485 static
8486 int
i_s_dict_fill_sys_tablespaces(THD * thd,ulint space,const char * name,ulint flags,TABLE * table_to_fill)8487 i_s_dict_fill_sys_tablespaces(
8488 /*==========================*/
8489 THD* thd, /*!< in: thread */
8490 ulint space, /*!< in: space ID */
8491 const char* name, /*!< in: tablespace name */
8492 ulint flags, /*!< in: tablespace flags */
8493 TABLE* table_to_fill) /*!< in/out: fill this table */
8494 {
8495 Field** fields;
8496 ulint atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
8497 bool is_compressed = FSP_FLAGS_GET_ZIP_SSIZE(flags);
8498 const char* file_format;
8499 const char* row_format;
8500 const page_size_t page_size(flags);
8501 const char* space_type;
8502
8503 DBUG_ENTER("i_s_dict_fill_sys_tablespaces");
8504
8505 file_format = trx_sys_file_format_id_to_name(atomic_blobs);
8506 if (is_system_tablespace(space)) {
8507 row_format = "Compact or Redundant";
8508 } else if (fsp_is_shared_tablespace(flags) && !is_compressed) {
8509 file_format = "Any";
8510 row_format = "Any";
8511 } else if (is_compressed) {
8512 row_format = "Compressed";
8513 } else if (atomic_blobs) {
8514 row_format = "Dynamic";
8515 } else {
8516 row_format = "Compact or Redundant";
8517 }
8518
8519 if (is_system_tablespace(space)) {
8520 space_type = "System";
8521 } else if (fsp_is_shared_tablespace(flags)) {
8522 space_type = "General";
8523 } else {
8524 space_type = "Single";
8525 }
8526
8527 fields = table_to_fill->field;
8528
8529 OK(fields[SYS_TABLESPACES_SPACE]->store(space, true));
8530
8531 OK(field_store_string(fields[SYS_TABLESPACES_NAME], name));
8532
8533 OK(fields[SYS_TABLESPACES_FLAGS]->store(flags, true));
8534
8535 OK(field_store_string(fields[SYS_TABLESPACES_FILE_FORMAT],
8536 file_format));
8537
8538 OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT], row_format));
8539
8540 OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
8541 univ_page_size.physical(), true));
8542
8543 OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
8544 page_size.is_compressed()
8545 ? page_size.physical()
8546 : 0, true));
8547
8548 OK(field_store_string(fields[SYS_TABLESPACES_SPACE_TYPE],
8549 space_type));
8550
8551 char* filepath = NULL;
8552 if (FSP_FLAGS_HAS_DATA_DIR(flags)
8553 || FSP_FLAGS_GET_SHARED(flags)) {
8554 mutex_enter(&dict_sys->mutex);
8555 filepath = dict_get_first_path(space);
8556 mutex_exit(&dict_sys->mutex);
8557 }
8558
8559 if (filepath == NULL) {
8560 filepath = fil_make_filepath(NULL, name, IBD, false);
8561 }
8562
8563 os_file_stat_t stat;
8564 os_file_size_t file;
8565
8566 memset(&file, 0xff, sizeof(file));
8567 memset(&stat, 0x0, sizeof(stat));
8568
8569 if (filepath != NULL) {
8570
8571 file = os_file_get_size(filepath);
8572
8573 /* Get the file system (or Volume) block size. */
8574 dberr_t err = os_file_get_status(filepath, &stat, false, false);
8575
8576 switch(err) {
8577 case DB_FAIL:
8578 ib::warn()
8579 << "File '" << filepath << "', failed to get "
8580 << "stats";
8581 break;
8582
8583 case DB_SUCCESS:
8584 case DB_NOT_FOUND:
8585 break;
8586
8587 default:
8588 ib::error()
8589 << "File '" << filepath << "' "
8590 << ut_strerr(err);
8591 break;
8592 }
8593
8594 ut_free(filepath);
8595 }
8596
8597 if (file.m_total_size == static_cast<os_offset_t>(~0)) {
8598 stat.block_size = 0;
8599 file.m_total_size = 0;
8600 file.m_alloc_size = 0;
8601 }
8602
8603 OK(fields[SYS_TABLESPACES_FS_BLOCK_SIZE]->store(stat.block_size, true));
8604
8605 OK(fields[SYS_TABLESPACES_FILE_SIZE]->store(file.m_total_size, true));
8606
8607 OK(fields[SYS_TABLESPACES_ALLOC_SIZE]->store(file.m_alloc_size, true));
8608
8609 OK(schema_table_store_record(thd, table_to_fill));
8610
8611 DBUG_RETURN(0);
8612 }
8613
8614 /*******************************************************************//**
8615 Function to populate INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
8616 Loop through each record in SYS_TABLESPACES, and extract the column
8617 information and fill the INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
8618 @return 0 on success */
8619 static
8620 int
i_s_sys_tablespaces_fill_table(THD * thd,TABLE_LIST * tables,Item *)8621 i_s_sys_tablespaces_fill_table(
8622 /*===========================*/
8623 THD* thd, /*!< in: thread */
8624 TABLE_LIST* tables, /*!< in/out: tables to fill */
8625 Item* ) /*!< in: condition (not used) */
8626 {
8627 btr_pcur_t pcur;
8628 const rec_t* rec;
8629 mem_heap_t* heap;
8630 mtr_t mtr;
8631
8632 DBUG_ENTER("i_s_sys_tablespaces_fill_table");
8633 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8634
8635 /* deny access to user without PROCESS_ACL privilege */
8636 if (check_global_access(thd, PROCESS_ACL)) {
8637 DBUG_RETURN(0);
8638 }
8639
8640 heap = mem_heap_create(1000);
8641 mutex_enter(&dict_sys->mutex);
8642 mtr_start(&mtr);
8643
8644 for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
8645 rec != NULL;
8646 rec = dict_getnext_system(&pcur, &mtr)) {
8647
8648 const char* err_msg;
8649 ulint space;
8650 const char* name;
8651 ulint flags;
8652
8653 /* Extract necessary information from a SYS_TABLESPACES row */
8654 err_msg = dict_process_sys_tablespaces(
8655 heap, rec, &space, &name, &flags);
8656
8657 mtr_commit(&mtr);
8658 mutex_exit(&dict_sys->mutex);
8659
8660 if (!err_msg) {
8661 i_s_dict_fill_sys_tablespaces(
8662 thd, space, name, flags,
8663 tables->table);
8664 } else {
8665 push_warning_printf(thd, Sql_condition::SL_WARNING,
8666 ER_CANT_FIND_SYSTEM_REC, "%s",
8667 err_msg);
8668 }
8669
8670 mem_heap_empty(heap);
8671
8672 /* Get the next record */
8673 mutex_enter(&dict_sys->mutex);
8674 mtr_start(&mtr);
8675 }
8676
8677 mtr_commit(&mtr);
8678 mutex_exit(&dict_sys->mutex);
8679 mem_heap_free(heap);
8680
8681 DBUG_RETURN(0);
8682 }
8683 /*******************************************************************//**
8684 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
8685 @return 0 on success */
8686 static
8687 int
innodb_sys_tablespaces_init(void * p)8688 innodb_sys_tablespaces_init(
8689 /*========================*/
8690 void* p) /*!< in/out: table schema object */
8691 {
8692 ST_SCHEMA_TABLE* schema;
8693
8694 DBUG_ENTER("innodb_sys_tablespaces_init");
8695
8696 schema = (ST_SCHEMA_TABLE*) p;
8697
8698 schema->fields_info = innodb_sys_tablespaces_fields_info;
8699 schema->fill_table = i_s_sys_tablespaces_fill_table;
8700
8701 DBUG_RETURN(0);
8702 }
8703
8704 struct st_mysql_plugin i_s_innodb_sys_tablespaces =
8705 {
8706 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8707 /* int */
8708 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8709
8710 /* pointer to type-specific plugin descriptor */
8711 /* void* */
8712 STRUCT_FLD(info, &i_s_info),
8713
8714 /* plugin name */
8715 /* const char* */
8716 STRUCT_FLD(name, "INNODB_SYS_TABLESPACES"),
8717
8718 /* plugin author (for SHOW PLUGINS) */
8719 /* const char* */
8720 STRUCT_FLD(author, plugin_author),
8721
8722 /* general descriptive text (for SHOW PLUGINS) */
8723 /* const char* */
8724 STRUCT_FLD(descr, "InnoDB SYS_TABLESPACES"),
8725
8726 /* the plugin license (PLUGIN_LICENSE_XXX) */
8727 /* int */
8728 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8729
8730 /* the function to invoke when plugin is loaded */
8731 /* int (*)(void*); */
8732 STRUCT_FLD(init, innodb_sys_tablespaces_init),
8733
8734 /* the function to invoke when plugin is unloaded */
8735 /* int (*)(void*); */
8736 STRUCT_FLD(deinit, i_s_common_deinit),
8737
8738 /* plugin version (for SHOW PLUGINS) */
8739 /* unsigned int */
8740 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8741
8742 /* struct st_mysql_show_var* */
8743 STRUCT_FLD(status_vars, NULL),
8744
8745 /* struct st_mysql_sys_var** */
8746 STRUCT_FLD(system_vars, NULL),
8747
8748 /* reserved for dependency checking */
8749 /* void* */
8750 STRUCT_FLD(__reserved1, NULL),
8751
8752 /* Plugin flags */
8753 /* unsigned long */
8754 STRUCT_FLD(flags, 0UL),
8755 };
8756
8757 /** SYS_DATAFILES ************************************************/
8758 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES */
8759 static ST_FIELD_INFO innodb_sys_datafiles_fields_info[] =
8760 {
8761 #define SYS_DATAFILES_SPACE 0
8762 {STRUCT_FLD(field_name, "SPACE"),
8763 STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
8764 STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
8765 STRUCT_FLD(value, 0),
8766 STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
8767 STRUCT_FLD(old_name, ""),
8768 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8769
8770 #define SYS_DATAFILES_PATH 1
8771 {STRUCT_FLD(field_name, "PATH"),
8772 STRUCT_FLD(field_length, OS_FILE_MAX_PATH),
8773 STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
8774 STRUCT_FLD(value, 0),
8775 STRUCT_FLD(field_flags, 0),
8776 STRUCT_FLD(old_name, ""),
8777 STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
8778
8779 END_OF_ST_FIELD_INFO
8780 };
8781
8782 /**********************************************************************//**
8783 Function to fill INFORMATION_SCHEMA.INNODB_SYS_DATAFILES with information
8784 collected by scanning SYS_DATAFILESS table.
8785 @return 0 on success */
8786 static
8787 int
i_s_dict_fill_sys_datafiles(THD * thd,ulint space,const char * path,TABLE * table_to_fill)8788 i_s_dict_fill_sys_datafiles(
8789 /*========================*/
8790 THD* thd, /*!< in: thread */
8791 ulint space, /*!< in: space ID */
8792 const char* path, /*!< in: absolute path */
8793 TABLE* table_to_fill) /*!< in/out: fill this table */
8794 {
8795 Field** fields;
8796
8797 DBUG_ENTER("i_s_dict_fill_sys_datafiles");
8798
8799 fields = table_to_fill->field;
8800
8801 OK(field_store_ulint(fields[SYS_DATAFILES_SPACE], space));
8802
8803 OK(field_store_string(fields[SYS_DATAFILES_PATH], path));
8804
8805 OK(schema_table_store_record(thd, table_to_fill));
8806
8807 DBUG_RETURN(0);
8808 }
8809 /*******************************************************************//**
8810 Function to populate INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8811 Loop through each record in SYS_DATAFILES, and extract the column
8812 information and fill the INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8813 @return 0 on success */
8814 static
8815 int
i_s_sys_datafiles_fill_table(THD * thd,TABLE_LIST * tables,Item *)8816 i_s_sys_datafiles_fill_table(
8817 /*=========================*/
8818 THD* thd, /*!< in: thread */
8819 TABLE_LIST* tables, /*!< in/out: tables to fill */
8820 Item* ) /*!< in: condition (not used) */
8821 {
8822 btr_pcur_t pcur;
8823 const rec_t* rec;
8824 mem_heap_t* heap;
8825 mtr_t mtr;
8826
8827 DBUG_ENTER("i_s_sys_datafiles_fill_table");
8828 RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8829
8830 /* deny access to user without PROCESS_ACL privilege */
8831 if (check_global_access(thd, PROCESS_ACL)) {
8832 DBUG_RETURN(0);
8833 }
8834
8835 heap = mem_heap_create(1000);
8836 mutex_enter(&dict_sys->mutex);
8837 mtr_start(&mtr);
8838
8839 rec = dict_startscan_system(&pcur, &mtr, SYS_DATAFILES);
8840
8841 while (rec) {
8842 const char* err_msg;
8843 ulint space;
8844 const char* path;
8845
8846 /* Extract necessary information from a SYS_DATAFILES row */
8847 err_msg = dict_process_sys_datafiles(
8848 heap, rec, &space, &path);
8849
8850 mtr_commit(&mtr);
8851 mutex_exit(&dict_sys->mutex);
8852
8853 if (!err_msg) {
8854 i_s_dict_fill_sys_datafiles(
8855 thd, space, path, tables->table);
8856 } else {
8857 push_warning_printf(thd, Sql_condition::SL_WARNING,
8858 ER_CANT_FIND_SYSTEM_REC, "%s",
8859 err_msg);
8860 }
8861
8862 mem_heap_empty(heap);
8863
8864 /* Get the next record */
8865 mutex_enter(&dict_sys->mutex);
8866 mtr_start(&mtr);
8867 rec = dict_getnext_system(&pcur, &mtr);
8868 }
8869
8870 mtr_commit(&mtr);
8871 mutex_exit(&dict_sys->mutex);
8872 mem_heap_free(heap);
8873
8874 DBUG_RETURN(0);
8875 }
8876 /*******************************************************************//**
8877 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES
8878 @return 0 on success */
8879 static
8880 int
innodb_sys_datafiles_init(void * p)8881 innodb_sys_datafiles_init(
8882 /*======================*/
8883 void* p) /*!< in/out: table schema object */
8884 {
8885 ST_SCHEMA_TABLE* schema;
8886
8887 DBUG_ENTER("innodb_sys_datafiles_init");
8888
8889 schema = (ST_SCHEMA_TABLE*) p;
8890
8891 schema->fields_info = innodb_sys_datafiles_fields_info;
8892 schema->fill_table = i_s_sys_datafiles_fill_table;
8893
8894 DBUG_RETURN(0);
8895 }
8896
8897 struct st_mysql_plugin i_s_innodb_sys_datafiles =
8898 {
8899 /* the plugin type (a MYSQL_XXX_PLUGIN value) */
8900 /* int */
8901 STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8902
8903 /* pointer to type-specific plugin descriptor */
8904 /* void* */
8905 STRUCT_FLD(info, &i_s_info),
8906
8907 /* plugin name */
8908 /* const char* */
8909 STRUCT_FLD(name, "INNODB_SYS_DATAFILES"),
8910
8911 /* plugin author (for SHOW PLUGINS) */
8912 /* const char* */
8913 STRUCT_FLD(author, plugin_author),
8914
8915 /* general descriptive text (for SHOW PLUGINS) */
8916 /* const char* */
8917 STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
8918
8919 /* the plugin license (PLUGIN_LICENSE_XXX) */
8920 /* int */
8921 STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8922
8923 /* the function to invoke when plugin is loaded */
8924 /* int (*)(void*); */
8925 STRUCT_FLD(init, innodb_sys_datafiles_init),
8926
8927 /* the function to invoke when plugin is unloaded */
8928 /* int (*)(void*); */
8929 STRUCT_FLD(deinit, i_s_common_deinit),
8930
8931 /* plugin version (for SHOW PLUGINS) */
8932 /* unsigned int */
8933 STRUCT_FLD(version, INNODB_VERSION_SHORT),
8934
8935 /* struct st_mysql_show_var* */
8936 STRUCT_FLD(status_vars, NULL),
8937
8938 /* struct st_mysql_sys_var** */
8939 STRUCT_FLD(system_vars, NULL),
8940
8941 /* reserved for dependency checking */
8942 /* void* */
8943 STRUCT_FLD(__reserved1, NULL),
8944
8945 /* Plugin flags */
8946 /* unsigned long */
8947 STRUCT_FLD(flags, 0UL),
8948 };
8949
8950 /** Fill handlerton based INFORMATION_SCHEMA.FILES table.
8951 @param[in,out] thd thread/connection descriptor
8952 @param[in,out] tables information schema tables to fill
8953 @retval 0 for success
8954 @retval HA_ERR_OUT_OF_MEM when running out of memory
8955 @return nonzero for failure */
8956 int
i_s_files_table_fill(THD * thd,TABLE_LIST * tables)8957 i_s_files_table_fill(
8958 THD* thd,
8959 TABLE_LIST* tables)
8960 {
8961 TABLE* table_to_fill = tables->table;
8962 Field** fields = table_to_fill->field;
8963 /* Use this class so that if the OK() macro returns,
8964 fil_space_release() is called. */
8965 FilSpace space;
8966
8967 DBUG_ENTER("i_s_files_table_fill");
8968
8969 /* Gather information reportable to information_schema.files
8970 for the first or next file in fil_system. */
8971 for (const fil_node_t* node = fil_node_next(NULL);
8972 node != NULL;
8973 node = fil_node_next(node)) {
8974 const char* type = "TABLESPACE";
8975 const char* space_name;
8976 /** Buffer to build file-per-table tablespace names.
8977 Even though a space_id is often stored in a ulint, it cannot
8978 be larger than 1<<32-1, which is 10 numeric characters. */
8979 char file_per_table_name[
8980 sizeof("innodb_file_per_table_1234567890")];
8981 uintmax_t avail_space;
8982 ulint extent_pages;
8983 ulint extend_pages;
8984
8985 space = node->space;
8986 fil_type_t purpose = space()->purpose;
8987
8988 switch (purpose) {
8989 case FIL_TYPE_LOG:
8990 /* Do not report REDO LOGs to I_S.FILES */
8991 space = NULL;
8992 continue;
8993 case FIL_TYPE_TABLESPACE:
8994 if (srv_is_undo_tablespace(space()->id)) {
8995 type = "UNDO LOG";
8996 break;
8997 } /* else fall through for TABLESPACE */
8998 case FIL_TYPE_IMPORT:
8999 /* 'IMPORTING'is a status. The type is TABLESPACE. */
9000 break;
9001 case FIL_TYPE_TEMPORARY:
9002 type = "TEMPORARY";
9003 break;
9004 };
9005
9006 page_size_t page_size(space()->flags);
9007
9008 /* Single-table tablespaces are assigned to a schema. */
9009 if (!is_predefined_tablespace(space()->id)
9010 && !FSP_FLAGS_GET_SHARED(space()->flags)) {
9011 /* Their names will be like "test/t1" */
9012 ut_ad(NULL != strchr(space()->name, '/'));
9013
9014 /* File-per-table tablespace names are generated
9015 internally and certain non-file-system-allowed
9016 characters are expanded which can make the space
9017 name too long. In order to avoid that problem,
9018 use a modified tablespace name.
9019 Since we are not returning dbname and tablename,
9020 the user must match the space_id to i_s_table.space
9021 in order find the single table that is in it or the
9022 schema it belongs to. */
9023 ut_snprintf(
9024 file_per_table_name,
9025 sizeof(file_per_table_name),
9026 "innodb_file_per_table_" ULINTPF,
9027 space()->id);
9028 space_name = file_per_table_name;
9029 } else {
9030 /* Only file-per-table space names contain '/'.
9031 This is not file-per-table . */
9032 ut_ad(NULL == strchr(space()->name, '/'));
9033
9034 space_name = space()->name;
9035 }
9036
9037 init_fill_schema_files_row(table_to_fill);
9038
9039 OK(field_store_ulint(fields[IS_FILES_FILE_ID],
9040 space()->id));
9041 OK(field_store_string(fields[IS_FILES_FILE_NAME],
9042 node->name));
9043 OK(field_store_string(fields[IS_FILES_FILE_TYPE],
9044 type));
9045 OK(field_store_string(fields[IS_FILES_TABLESPACE_NAME],
9046 space_name));
9047 OK(field_store_string(fields[IS_FILES_ENGINE],
9048 "InnoDB"));
9049 OK(field_store_ulint(fields[IS_FILES_FREE_EXTENTS],
9050 space()->free_len));
9051
9052 extent_pages = fsp_get_extent_size_in_pages(page_size);
9053
9054 OK(field_store_ulint(fields[IS_FILES_TOTAL_EXTENTS],
9055 space()->size_in_header / extent_pages));
9056 OK(field_store_ulint(fields[IS_FILES_EXTENT_SIZE],
9057 extent_pages * page_size.physical()));
9058 OK(field_store_ulint(fields[IS_FILES_INITIAL_SIZE],
9059 node->init_size * page_size.physical()));
9060
9061 if (node->max_size >= ULINT_MAX) {
9062 fields[IS_FILES_MAXIMUM_SIZE]->set_null();
9063 } else {
9064 OK(field_store_ulint(fields[IS_FILES_MAXIMUM_SIZE],
9065 node->max_size * page_size.physical()));
9066 }
9067 if (space()->id == srv_sys_space.space_id()) {
9068 extend_pages = srv_sys_space.get_increment();
9069 } else if (space()->id == srv_tmp_space.space_id()) {
9070 extend_pages = srv_tmp_space.get_increment();
9071 } else {
9072 extend_pages = fsp_get_pages_to_extend_ibd(
9073 page_size, node->size);
9074 }
9075
9076 OK(field_store_ulint(fields[IS_FILES_AUTOEXTEND_SIZE],
9077 extend_pages * page_size.physical()));
9078
9079 avail_space = fsp_get_available_space_in_free_extents(space());
9080 OK(field_store_ulint(fields[IS_FILES_DATA_FREE],
9081 static_cast<ulint>(avail_space * 1024)));
9082 OK(field_store_string(fields[IS_FILES_STATUS],
9083 (purpose == FIL_TYPE_IMPORT)
9084 ? "IMPORTING" : "NORMAL"));
9085
9086 schema_table_store_record(thd, table_to_fill);
9087 space = NULL;
9088 }
9089
9090 DBUG_RETURN(0);
9091 }
9092