# 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! --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -442,7 +442,7 @@ } -#ifdef FOREIGN_NOT_USED +//#ifdef FOREIGN_NOT_USED /********************************************************************//** This function parses a SYS_FOREIGN record and populate a dict_foreign_t structure with the information from the record. For detail information @@ -518,9 +518,9 @@ return(NULL); } -#endif /* FOREIGN_NOT_USED */ +//#endif /* FOREIGN_NOT_USED */ -#ifdef FOREIGN_NOT_USED +//#ifdef FOREIGN_NOT_USED /********************************************************************//** This function parses a SYS_FOREIGN_COLS record and extract necessary information from the record and return to caller. @@ -584,7 +584,7 @@ return(NULL); } -#endif /* FOREIGN_NOT_USED */ +//#endif /* FOREIGN_NOT_USED */ /********************************************************************//** Determine the flags of a table described in SYS_TABLES. --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11950,7 +11950,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. --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -36,9 +36,11 @@ #include 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() */ @@ -1812,6 +1814,1703 @@ 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; + +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; + +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; + +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; + +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; +/* 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, "Percona"), + + /* 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), + + /* flags for plugin */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL) +}; + /*********************************************************************** */ static ST_FIELD_INFO i_s_innodb_rseg_fields_info[] = --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -35,6 +35,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 */