--- /dev/null
+# name : innodb_show_sys_tables.patch
+# introduced : 13?
+# maintainer : Yasufumi
+# (It is revived from mysql-5.5.6-rc)
+#!!! notice !!!
+# Any small change to this file in the main branch
+# should be done or reviewed by the maintainer!
+diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
+--- a/storage/innobase/handler/ha_innodb.cc 2010-12-03 15:53:54.615040167 +0900
++++ b/storage/innobase/handler/ha_innodb.cc 2010-12-03 16:07:26.851357007 +0900
+@@ -11673,7 +11673,14 @@
+ i_s_innodb_cmp,
+ i_s_innodb_cmp_reset,
+ i_s_innodb_cmpmem,
+-i_s_innodb_cmpmem_reset
++i_s_innodb_cmpmem_reset,
++i_s_innodb_sys_tables,
++i_s_innodb_sys_tablestats,
++i_s_innodb_sys_indexes,
++i_s_innodb_sys_columns,
++i_s_innodb_sys_fields,
++i_s_innodb_sys_foreign,
++i_s_innodb_sys_foreign_cols
+ mysql_declare_plugin_end;
+
+ /** @brief Initialize the default value of innodb_commit_concurrency.
+diff -ruN a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
+--- a/storage/innobase/handler/i_s.cc 2010-12-03 15:49:59.207956807 +0900
++++ b/storage/innobase/handler/i_s.cc 2010-12-03 17:10:02.719210529 +0900
+@@ -36,9 +36,11 @@
+ #include <mysql/innodb_priv.h>
+
+ extern "C" {
++#include "btr0pcur.h" /* for file sys_tables related info. */
+ #include "btr0types.h"
+ #include "buf0buddy.h" /* for i_s_cmpmem */
+ #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
++#include "dict0load.h" /* for file sys_tables related info. */
+ #include "dict0mem.h"
+ #include "dict0types.h"
+ #include "ha_prototypes.h" /* for innobase_convert_name() */
+@@ -1787,6 +1789,1675 @@
+ DBUG_RETURN(0);
+ }
+
++/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
++static ST_FIELD_INFO innodb_sys_tables_fields_info[] =
++{
++#define SYS_TABLE_ID 0
++ {STRUCT_FLD(field_name, "TABLE_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLE_SCHEMA 1
++ {STRUCT_FLD(field_name, "SCHEMA"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLE_NAME 2
++ {STRUCT_FLD(field_name, "NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLE_FLAG 3
++ {STRUCT_FLD(field_name, "FLAG"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLE_NUM_COLUMN 4
++ {STRUCT_FLD(field_name, "N_COLS"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLE_SPACE 5
++ {STRUCT_FLD(field_name, "SPACE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Populate information_schema.innodb_sys_tables table with information
++from SYS_TABLES.
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_tables(
++/*=====================*/
++ THD* thd, /*!< in: thread */
++ dict_table_t* table, /*!< in: table */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++ char buf[NAME_LEN * 2 + 2];
++ char* ptr;
++
++ DBUG_ENTER("i_s_dict_fill_sys_tables");
++
++ fields = table_to_fill->field;
++
++ OK(fields[SYS_TABLE_ID]->store(longlong(table->id), TRUE));
++
++ strncpy(buf, table->name, NAME_LEN * 2 + 2);
++ ptr = strchr(buf, '/');
++ if (ptr) {
++ *ptr = '\0';
++ ++ptr;
++
++ OK(field_store_string(fields[SYS_TABLE_SCHEMA], buf));
++ OK(field_store_string(fields[SYS_TABLE_NAME], ptr));
++ } else {
++ fields[SYS_TABLE_SCHEMA]->set_null();
++ OK(field_store_string(fields[SYS_TABLE_NAME], buf));
++ }
++
++ OK(fields[SYS_TABLE_FLAG]->store(table->flags));
++
++ OK(fields[SYS_TABLE_NUM_COLUMN]->store(table->n_cols));
++
++ OK(fields[SYS_TABLE_SPACE]->store(table->space));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to go through each record in SYS_TABLES table, and fill the
++information_schema.innodb_sys_tables table with related table information
++@return 0 on success */
++static
++int
++i_s_sys_tables_fill_table(
++/*======================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_tables_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&(dict_sys->mutex));
++ mtr_start(&mtr);
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
++
++ while (rec) {
++ const char* err_msg;
++ dict_table_t* table_rec;
++
++ /* Create and populate a dict_table_t structure with
++ information from SYS_TABLES row */
++ err_msg = dict_process_sys_tables_rec(
++ heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_RECORD);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ /* Since dict_process_sys_tables_rec() is called with
++ DICT_TABLE_LOAD_FROM_RECORD, the table_rec is created in
++ dict_process_sys_tables_rec(), we will need to free it */
++ if (table_rec) {
++ dict_mem_table_free(table_rec);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
++@return 0 on success */
++static
++int
++innodb_sys_tables_init(
++/*===================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_tables_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_tables_fields_info;
++ schema->fill_table = i_s_sys_tables_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tables =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_TABLES"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_tables_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
++static ST_FIELD_INFO innodb_sys_tablestats_fields_info[] =
++{
++#define SYS_TABLESTATS_ID 0
++ {STRUCT_FLD(field_name, "TABLE_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_SCHEMA 1
++ {STRUCT_FLD(field_name, "SCHEMA"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_NAME 2
++ {STRUCT_FLD(field_name, "NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_INIT 3
++ {STRUCT_FLD(field_name, "STATS_INITIALIZED"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_NROW 4
++ {STRUCT_FLD(field_name, "NUM_ROWS"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_CLUST_SIZE 5
++ {STRUCT_FLD(field_name, "CLUST_INDEX_SIZE"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_INDEX_SIZE 6
++ {STRUCT_FLD(field_name, "OTHER_INDEX_SIZE"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_MODIFIED 7
++ {STRUCT_FLD(field_name, "MODIFIED_COUNTER"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_AUTONINC 8
++ {STRUCT_FLD(field_name, "AUTOINC"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_TABLESTATS_MYSQL_OPEN_HANDLE 9
++ {STRUCT_FLD(field_name, "MYSQL_HANDLES_OPENED"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Populate information_schema.innodb_sys_tablestats table with information
++from SYS_TABLES.
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_tablestats(
++/*=========================*/
++ THD* thd, /*!< in: thread */
++ dict_table_t* table, /*!< in: table */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++ char buf[NAME_LEN * 2 + 2];
++ char* ptr;
++
++ DBUG_ENTER("i_s_dict_fill_sys_tablestats");
++
++ fields = table_to_fill->field;
++
++ OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
++
++ strncpy(buf, table->name, NAME_LEN * 2 + 2);
++ ptr = strchr(buf, '/');
++ if (ptr) {
++ *ptr = '\0';
++ ++ptr;
++
++ OK(field_store_string(fields[SYS_TABLESTATS_SCHEMA], buf));
++ OK(field_store_string(fields[SYS_TABLESTATS_NAME], ptr));
++ } else {
++ fields[SYS_TABLESTATS_SCHEMA]->set_null();
++ OK(field_store_string(fields[SYS_TABLESTATS_NAME], buf));
++ }
++
++ if (table->stat_initialized) {
++ OK(field_store_string(fields[SYS_TABLESTATS_INIT],
++ "Initialized"));
++ } else {
++ OK(field_store_string(fields[SYS_TABLESTATS_INIT],
++ "Uninitialized"));
++ }
++
++ OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows, TRUE));
++
++ OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
++ table->stat_clustered_index_size));
++
++ OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
++ table->stat_sum_of_other_index_sizes));
++
++ OK(fields[SYS_TABLESTATS_MODIFIED]->store(
++ table->stat_modified_counter));
++
++ OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, TRUE));
++
++ OK(fields[SYS_TABLESTATS_MYSQL_OPEN_HANDLE]->store(
++ table->n_mysql_handles_opened));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to go through each record in SYS_TABLES table, and fill the
++information_schema.innodb_sys_tablestats table with table statistics
++related information
++@return 0 on success */
++static
++int
++i_s_sys_tables_fill_table_stats(
++/*============================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_tables_fill_table_stats");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
++
++ while (rec) {
++ const char* err_msg;
++ dict_table_t* table_rec;
++
++ /* Fetch the dict_table_t structure corresponding to
++ this SYS_TABLES record */
++ err_msg = dict_process_sys_tables_rec(
++ heap, rec, &table_rec, DICT_TABLE_LOAD_FROM_CACHE);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_tablestats(thd, table_rec,
++ tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
++@return 0 on success */
++static
++int
++innodb_sys_tablestats_init(
++/*=======================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_tablestats_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_tablestats_fields_info;
++ schema->fill_table = i_s_sys_tables_fill_table_stats;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_tablestats =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_tablestats_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
++static ST_FIELD_INFO innodb_sysindex_fields_info[] =
++{
++#define SYS_INDEX_ID 0
++ {STRUCT_FLD(field_name, "INDEX_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_NAME 1
++ {STRUCT_FLD(field_name, "NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_TABLE_ID 2
++ {STRUCT_FLD(field_name, "TABLE_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_TYPE 3
++ {STRUCT_FLD(field_name, "TYPE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_NUM_FIELDS 4
++ {STRUCT_FLD(field_name, "N_FIELDS"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_PAGE_NO 5
++ {STRUCT_FLD(field_name, "PAGE_NO"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_INDEX_SPACE 6
++ {STRUCT_FLD(field_name, "SPACE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Function to populate the information_schema.innodb_sys_indexes table with
++collected index information
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_indexes(
++/*======================*/
++ THD* thd, /*!< in: thread */
++ table_id_t table_id, /*!< in: table id */
++ dict_index_t* index, /*!< in: populated dict_index_t
++ struct with index info */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++
++ DBUG_ENTER("i_s_dict_fill_sys_indexes");
++
++ fields = table_to_fill->field;
++
++ OK(fields[SYS_INDEX_ID]->store(longlong(index->id), TRUE));
++
++ OK(field_store_string(fields[SYS_INDEX_NAME], index->name));
++
++ OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), TRUE));
++
++ OK(fields[SYS_INDEX_TYPE]->store(index->type));
++
++ OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
++
++ OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
++
++ OK(fields[SYS_INDEX_SPACE]->store(index->space));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to go through each record in SYS_INDEXES table, and fill the
++information_schema.innodb_sys_indexes table with related index information
++@return 0 on success */
++static
++int
++i_s_sys_indexes_fill_table(
++/*=======================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_indexes_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ /* Start scan the SYS_INDEXES table */
++ rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
++
++ /* Process each record in the table */
++ while (rec) {
++ const char* err_msg;;
++ table_id_t table_id;
++ dict_index_t index_rec;
++
++ /* Populate a dict_index_t structure with information from
++ a SYS_INDEXES row */
++ err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
++ &table_id);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
++ tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
++@return 0 on success */
++static
++int
++innodb_sys_indexes_init(
++/*====================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_index_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sysindex_fields_info;
++ schema->fill_table = i_s_sys_indexes_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_indexes =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_indexes_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++/* Fields of the dynamic table INFORMATION_SCHEMA.SYS_COLUMNS */
++static ST_FIELD_INFO innodb_sys_columns_fields_info[] =
++{
++#define SYS_COLUMN_TABLE_ID 0
++ {STRUCT_FLD(field_name, "TABLE_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_COLUMN_NAME 1
++ {STRUCT_FLD(field_name, "NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_COLUMN_POSITION 2
++ {STRUCT_FLD(field_name, "POS"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_COLUMN_MTYPE 3
++ {STRUCT_FLD(field_name, "MTYPE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_COLUMN__PRTYPE 4
++ {STRUCT_FLD(field_name, "PRTYPE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_COLUMN_COLUMN_LEN 5
++ {STRUCT_FLD(field_name, "LEN"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Function to populate the information_schema.innodb_sys_columns with
++related column information
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_columns(
++/*======================*/
++ THD* thd, /*!< in: thread */
++ table_id_t table_id, /*!< in: table ID */
++ const char* col_name, /*!< in: column name */
++ dict_col_t* column, /*!< in: dict_col_t struct holding
++ more column information */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++
++ DBUG_ENTER("i_s_dict_fill_sys_columns");
++
++ fields = table_to_fill->field;
++
++ OK(fields[SYS_COLUMN_TABLE_ID]->store(longlong(table_id), TRUE));
++
++ OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
++
++ OK(fields[SYS_COLUMN_POSITION]->store(column->ind));
++
++ OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
++
++ OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
++
++ OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to fill information_schema.innodb_sys_columns with information
++collected by scanning SYS_COLUMNS table.
++@return 0 on success */
++static
++int
++i_s_sys_columns_fill_table(
++/*=======================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ const char* col_name;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_columns_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
++
++ while (rec) {
++ const char* err_msg;
++ dict_col_t column_rec;
++ table_id_t table_id;
++
++ /* populate a dict_col_t structure with information from
++ a SYS_COLUMNS row */
++ err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
++ &table_id, &col_name);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_columns(thd, table_id, col_name,
++ &column_rec,
++ tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
++@return 0 on success */
++static
++int
++innodb_sys_columns_init(
++/*====================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_columns_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_columns_fields_info;
++ schema->fill_table = i_s_sys_columns_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_columns =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_columns_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_fields */
++static ST_FIELD_INFO innodb_sys_fields_fields_info[] =
++{
++#define SYS_FIELD_INDEX_ID 0
++ {STRUCT_FLD(field_name, "INDEX_ID"),
++ STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FIELD_NAME 1
++ {STRUCT_FLD(field_name, "NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FIELD_POS 2
++ {STRUCT_FLD(field_name, "POS"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Function to fill information_schema.innodb_sys_fields with information
++collected by scanning SYS_FIELDS table.
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_fields(
++/*=====================*/
++ THD* thd, /*!< in: thread */
++ index_id_t index_id, /*!< in: index id for the field */
++ dict_field_t* field, /*!< in: table */
++ ulint pos, /*!< in: Field position */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++
++ DBUG_ENTER("i_s_dict_fill_sys_fields");
++
++ fields = table_to_fill->field;
++
++ OK(fields[SYS_FIELD_INDEX_ID]->store(longlong(index_id), TRUE));
++
++ OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
++
++ OK(fields[SYS_FIELD_POS]->store(pos));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to go through each record in SYS_FIELDS table, and fill the
++information_schema.innodb_sys_fields table with related index field
++information
++@return 0 on success */
++static
++int
++i_s_sys_fields_fill_table(
++/*======================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ index_id_t last_id;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_fields_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ /* will save last index id so that we know whether we move to
++ the next index. This is used to calculate prefix length */
++ last_id = 0;
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
++
++ while (rec) {
++ ulint pos;
++ const char* err_msg;
++ index_id_t index_id;
++ dict_field_t field_rec;
++
++ /* Populate a dict_field_t structure with information from
++ a SYS_FIELDS row */
++ err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
++ &pos, &index_id, last_id);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
++ pos, tables->table);
++ last_id = index_id;
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
++@return 0 on success */
++static
++int
++innodb_sys_fields_init(
++/*===================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_field_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_fields_fields_info;
++ schema->fill_table = i_s_sys_fields_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_fields =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_fields_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
++/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign */
++static ST_FIELD_INFO innodb_sys_foreign_fields_info[] =
++{
++#define SYS_FOREIGN_ID 0
++ {STRUCT_FLD(field_name, "ID"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_FOR_NAME 1
++ {STRUCT_FLD(field_name, "FOR_NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_REF_NAME 2
++ {STRUCT_FLD(field_name, "REF_NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_NUM_COL 3
++ {STRUCT_FLD(field_name, "N_COLS"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_TYPE 4
++ {STRUCT_FLD(field_name, "TYPE"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Function to fill information_schema.innodb_sys_foreign with information
++collected by scanning SYS_FOREIGN table.
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_foreign(
++/*======================*/
++ THD* thd, /*!< in: thread */
++ dict_foreign_t* foreign, /*!< in: table */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++
++ DBUG_ENTER("i_s_dict_fill_sys_foreign");
++
++ fields = table_to_fill->field;
++
++ OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
++
++ OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
++ foreign->foreign_table_name));
++
++ OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
++ foreign->referenced_table_name));
++
++ OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
++
++ OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
++through each record in SYS_FOREIGN, and extract the foreign key
++information.
++@return 0 on success */
++static
++int
++i_s_sys_foreign_fill_table(
++/*=======================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_foreign_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
++
++ while (rec) {
++ const char* err_msg;
++ dict_foreign_t foreign_rec;
++
++ /* Populate a dict_foreign_t structure with information from
++ a SYS_FOREIGN row */
++ err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_foreign(thd, &foreign_rec,
++ tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mtr_start(&mtr);
++ mutex_enter(&dict_sys->mutex);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
++@return 0 on success */
++static
++int
++innodb_sys_foreign_init(
++/*====================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_foreign_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_foreign_fields_info;
++ schema->fill_table = i_s_sys_foreign_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_foreign_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++/* Fields of the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols */
++static ST_FIELD_INFO innodb_sys_foreign_cols_fields_info[] =
++{
++#define SYS_FOREIGN_COL_ID 0
++ {STRUCT_FLD(field_name, "ID"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_COL_FOR_NAME 1
++ {STRUCT_FLD(field_name, "FOR_COL_NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_COL_REF_NAME 2
++ {STRUCT_FLD(field_name, "REF_COL_NAME"),
++ STRUCT_FLD(field_length, NAME_LEN + 1),
++ STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, 0),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++#define SYS_FOREIGN_COL_POS 3
++ {STRUCT_FLD(field_name, "POS"),
++ STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
++ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
++ STRUCT_FLD(value, 0),
++ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
++ STRUCT_FLD(old_name, ""),
++ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
++
++ END_OF_ST_FIELD_INFO
++};
++
++/**********************************************************************//**
++Function to fill information_schema.innodb_sys_foreign_cols with information
++collected by scanning SYS_FOREIGN_COLS table.
++@return 0 on success */
++static
++int
++i_s_dict_fill_sys_foreign_cols(
++/*==========================*/
++ THD* thd, /*!< in: thread */
++ const char* name, /*!< in: foreign key constraint name */
++ const char* for_col_name, /*!< in: referencing column name*/
++ const char* ref_col_name, /*!< in: referenced column
++ name */
++ ulint pos, /*!< in: column position */
++ TABLE* table_to_fill) /*!< in/out: fill this table */
++{
++ Field** fields;
++
++ DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
++
++ fields = table_to_fill->field;
++
++ OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
++
++ OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
++
++ OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
++
++ OK(fields[SYS_FOREIGN_COL_POS]->store(pos));
++
++ OK(schema_table_store_record(thd, table_to_fill));
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
++through each record in SYS_FOREIGN_COLS, and extract the foreign key column
++information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
++@return 0 on success */
++static
++int
++i_s_sys_foreign_cols_fill_table(
++/*============================*/
++ THD* thd, /*!< in: thread */
++ TABLE_LIST* tables, /*!< in/out: tables to fill */
++ COND* cond) /*!< in: condition (not used) */
++{
++ btr_pcur_t pcur;
++ const rec_t* rec;
++ mem_heap_t* heap;
++ mtr_t mtr;
++
++ DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
++
++ /* deny access to non-superusers */
++ if (check_global_access(thd, PROCESS_ACL)) {
++ DBUG_RETURN(0);
++ }
++
++ heap = mem_heap_create(1000);
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++
++ rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
++
++ while (rec) {
++ const char* err_msg;
++ const char* name;
++ const char* for_col_name;
++ const char* ref_col_name;
++ ulint pos;
++
++ /* Extract necessary information from a SYS_FOREIGN_COLS row */
++ err_msg = dict_process_sys_foreign_col_rec(
++ heap, rec, &name, &for_col_name, &ref_col_name, &pos);
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++
++ if (!err_msg) {
++ i_s_dict_fill_sys_foreign_cols(
++ thd, name, for_col_name, ref_col_name, pos,
++ tables->table);
++ } else {
++ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
++ ER_CANT_FIND_SYSTEM_REC,
++ err_msg);
++ }
++
++ mem_heap_empty(heap);
++
++ /* Get the next record */
++ mutex_enter(&dict_sys->mutex);
++ mtr_start(&mtr);
++ rec = dict_getnext_system(&pcur, &mtr);
++ }
++
++ mtr_commit(&mtr);
++ mutex_exit(&dict_sys->mutex);
++ mem_heap_free(heap);
++
++ DBUG_RETURN(0);
++}
++/*******************************************************************//**
++Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
++@return 0 on success */
++static
++int
++innodb_sys_foreign_cols_init(
++/*========================*/
++ void* p) /*!< in/out: table schema object */
++{
++ ST_SCHEMA_TABLE* schema;
++
++ DBUG_ENTER("innodb_sys_foreign_cols_init");
++
++ schema = (ST_SCHEMA_TABLE*) p;
++
++ schema->fields_info = innodb_sys_foreign_cols_fields_info;
++ schema->fill_table = i_s_sys_foreign_cols_fill_table;
++
++ DBUG_RETURN(0);
++}
++
++UNIV_INTERN struct st_mysql_plugin i_s_innodb_sys_foreign_cols =
++{
++ /* the plugin type (a MYSQL_XXX_PLUGIN value) */
++ /* int */
++ STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
++
++ /* pointer to type-specific plugin descriptor */
++ /* void* */
++ STRUCT_FLD(info, &i_s_info),
++
++ /* plugin name */
++ /* const char* */
++ STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
++
++ /* plugin author (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(author, plugin_author),
++
++ /* general descriptive text (for SHOW PLUGINS) */
++ /* const char* */
++ STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
++
++ /* the plugin license (PLUGIN_LICENSE_XXX) */
++ /* int */
++ STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
++
++ /* the function to invoke when plugin is loaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(init, innodb_sys_foreign_cols_init),
++
++ /* the function to invoke when plugin is unloaded */
++ /* int (*)(void*); */
++ STRUCT_FLD(deinit, i_s_common_deinit),
++
++ /* plugin version (for SHOW PLUGINS) */
++ /* unsigned int */
++ STRUCT_FLD(version, INNODB_VERSION_SHORT),
++
++ /* struct st_mysql_show_var* */
++ STRUCT_FLD(status_vars, NULL),
++
++ /* struct st_mysql_sys_var** */
++ STRUCT_FLD(system_vars, NULL),
++
++ /* reserved for dependency checking */
++ /* void* */
++ STRUCT_FLD(__reserved1, NULL)
++};
++
+ /***********************************************************************
+ */
+ static ST_FIELD_INFO i_s_innodb_rseg_fields_info[] =
+diff -ruN a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h
+--- a/storage/innobase/handler/i_s.h 2010-12-03 15:37:45.540456499 +0900
++++ b/storage/innobase/handler/i_s.h 2010-12-03 16:08:57.596941207 +0900
+@@ -33,6 +33,13 @@
+ extern struct st_mysql_plugin i_s_innodb_cmp_reset;
+ extern struct st_mysql_plugin i_s_innodb_cmpmem;
+ extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
++extern struct st_mysql_plugin i_s_innodb_sys_tables;
++extern struct st_mysql_plugin i_s_innodb_sys_tablestats;
++extern struct st_mysql_plugin i_s_innodb_sys_indexes;
++extern struct st_mysql_plugin i_s_innodb_sys_columns;
++extern struct st_mysql_plugin i_s_innodb_sys_fields;
++extern struct st_mysql_plugin i_s_innodb_sys_foreign;
++extern struct st_mysql_plugin i_s_innodb_sys_foreign_cols;
+ extern struct st_mysql_plugin i_s_innodb_rseg;
+
+ #endif /* i_s_h */