summaryrefslogtreecommitdiff
path: root/sql/sql_show.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r--sql/sql_show.cc435
1 files changed, 285 insertions, 150 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ac1825d7c84..f500e3bf481 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -47,7 +47,7 @@ static void store_key_options(THD *thd, String *packet, TABLE *table,
KEY *key_info);
/***************************************************************************
-** List all table types supported
+** List all table types supported
***************************************************************************/
static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
@@ -55,25 +55,26 @@ static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
{
handlerton *default_type= (handlerton *) arg;
Protocol *protocol= thd->protocol;
- handlerton *hton= (handlerton *) plugin->plugin->info;
+ handlerton *hton= (handlerton *)plugin->data;
if (!(hton->flags & HTON_HIDDEN))
{
protocol->prepare_for_resend();
- protocol->store(hton->name, system_charset_info);
+ protocol->store(plugin->name.str, plugin->name.length,
+ system_charset_info);
const char *option_name= show_comp_option_name[(int) hton->state];
if (hton->state == SHOW_OPTION_YES && default_type == hton)
option_name= "DEFAULT";
protocol->store(option_name, system_charset_info);
- protocol->store(hton->comment, system_charset_info);
+ protocol->store(plugin->plugin->descr, system_charset_info);
protocol->store(hton->commit ? "YES" : "NO", system_charset_info);
protocol->store(hton->prepare ? "YES" : "NO", system_charset_info);
protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info);
-
+
return protocol->write() ? 1 : 0;
}
- return 0;
+ return 0;
}
bool mysqld_show_storage_engines(THD *thd)
@@ -93,7 +94,7 @@ bool mysqld_show_storage_engines(THD *thd)
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- if (plugin_foreach(thd, show_handlerton,
+ if (plugin_foreach(thd, show_handlerton,
MYSQL_STORAGE_ENGINE_PLUGIN, thd->variables.table_type))
DBUG_RETURN(TRUE);
@@ -740,6 +741,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
field_list.push_back(new Item_field(field));
}
restore_record(table, s->default_values); // Get empty record
+ table->use_all_columns();
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
Protocol::SEND_EOF))
DBUG_VOID_RETURN;
@@ -953,9 +955,9 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
RETURN
0 OK
*/
-int
-store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
- HA_CREATE_INFO *create_info_arg)
+
+int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
+ HA_CREATE_INFO *create_info_arg)
{
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, uname[NAME_LEN*3+1];
@@ -968,6 +970,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
handler *file= table->file;
TABLE_SHARE *share= table->s;
HA_CREATE_INFO create_info;
+ bool show_table_options= FALSE;
bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
MODE_ORACLE |
MODE_MSSQL |
@@ -977,6 +980,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS |
MODE_MYSQL323 |
MODE_MYSQL40)) != 0;
+ my_bitmap_map *old_map;
DBUG_ENTER("store_create_info");
DBUG_PRINT("enter",("table: %s", table->s->table_name.str));
@@ -999,6 +1003,12 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
}
append_identifier(thd, packet, alias, strlen(alias));
packet->append(STRING_WITH_LEN(" (\n"));
+ /*
+ We need this to get default values from the table
+ We have to restore the read_set if we are called from insert in case
+ of row based replication.
+ */
+ old_map= tmp_use_all_columns(table, table->read_set);
for (ptr=table->field ; (field= *ptr); ptr++)
{
@@ -1153,10 +1163,11 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
table->field[key_part->fieldnr-1]->key_length() &&
!(key_info->flags & HA_FULLTEXT)))
{
+ char *end;
buff[0] = '(';
- char* end=int10_to_str((long) key_part->length /
- key_part->field->charset()->mbmaxlen,
- buff + 1,10);
+ end= int10_to_str((long) key_part->length /
+ key_part->field->charset()->mbmaxlen,
+ buff + 1,10);
*end++ = ')';
packet->append(buff,(uint) (end-buff));
}
@@ -1185,6 +1196,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
packet->append(STRING_WITH_LEN("\n)"));
if (!(thd->variables.sql_mode & MODE_NO_TABLE_OPTIONS) && !foreign_db_mode)
{
+ show_table_options= TRUE;
/*
Get possible table space definitions and append them
to the CREATE TABLE statement
@@ -1325,13 +1337,15 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
(!table->part_info->is_auto_partitioned) &&
((part_syntax= generate_partition_syntax(table->part_info,
&part_syntax_len,
- FALSE,FALSE))))
+ FALSE,
+ show_table_options))))
{
packet->append(part_syntax, part_syntax_len);
my_free(part_syntax, MYF(0));
}
}
#endif
+ tmp_restore_column_map(table->read_set, old_map);
DBUG_RETURN(0);
}
@@ -2375,7 +2389,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
TABLE *table= tables->table;
SELECT_LEX *select_lex= &lex->select_lex;
SELECT_LEX *old_all_select_lex= lex->all_selects_list;
- TABLE_LIST **save_query_tables_last= lex->query_tables_last;
enum_sql_command save_sql_command= lex->sql_command;
SELECT_LEX *lsel= tables->schema_select_lex;
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
@@ -2394,6 +2407,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
enum legacy_db_type not_used;
Open_tables_state open_tables_state_backup;
bool save_view_prepare_mode= lex->view_prepare_mode;
+ Query_tables_list query_tables_list_backup;
lex->view_prepare_mode= TRUE;
DBUG_ENTER("get_all_tables");
@@ -2406,6 +2420,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
+ lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
+
/*
We should not introduce deadlocks even if we already have some
tables open and locked, since we won't lock tables which we will
@@ -2446,8 +2462,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
show_table_list->db),
show_table_list->alias));
thd->temporary_tables= 0;
- close_thread_tables(thd);
- show_table_list->table= 0;
+ close_tables_for_reopen(thd, &show_table_list);
goto err;
}
@@ -2539,8 +2554,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
int res;
/*
- Set the parent lex of 'sel' because it is needed by sel.init_query()
- which is called inside make_table_list.
+ Set the parent lex of 'sel' because it is needed by
+ sel.init_query() which is called inside make_table_list.
*/
sel.parent_lex= lex;
if (make_table_list(thd, &sel, base_name, file_name))
@@ -2558,9 +2573,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
in this case.
*/
res= schema_table->process_table(thd, show_table_list, table,
- res, base_name,
- show_table_list->alias);
- close_thread_tables(thd);
+ res, base_name,
+ show_table_list->alias);
+ close_tables_for_reopen(thd, &show_table_list);
+ DBUG_ASSERT(!lex->query_tables_own_last);
if (res)
goto err;
}
@@ -2577,11 +2593,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
error= 0;
err:
thd->restore_backup_open_tables_state(&open_tables_state_backup);
+ lex->restore_backup_query_tables_list(&query_tables_list_backup);
lex->derived_tables= derived_tables;
lex->all_selects_list= old_all_select_lex;
- lex->query_tables_last= save_query_tables_last;
lex->view_prepare_mode= save_view_prepare_mode;
- *save_query_tables_last= 0;
lex->sql_command= save_sql_command;
DBUG_RETURN(error);
}
@@ -2735,50 +2750,55 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
case ROW_TYPE_COMPACT:
tmp_buff= "Compact";
break;
+ case ROW_TYPE_PAGES:
+ tmp_buff= "Paged";
+ break;
}
table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
if (!tables->schema_table)
{
- table->field[7]->store((longlong) file->records, TRUE);
+ table->field[7]->store((longlong) file->stats.records, TRUE);
table->field[7]->set_notnull();
}
- table->field[8]->store((longlong) file->mean_rec_length, TRUE);
- table->field[9]->store((longlong) file->data_file_length, TRUE);
- if (file->max_data_file_length)
+ table->field[8]->store((longlong) file->stats.mean_rec_length, TRUE);
+ table->field[9]->store((longlong) file->stats.data_file_length, TRUE);
+ if (file->stats.max_data_file_length)
{
- table->field[10]->store((longlong) file->max_data_file_length, TRUE);
+ table->field[10]->store((longlong) file->stats.max_data_file_length,
+ TRUE);
}
- table->field[11]->store((longlong) file->index_file_length, TRUE);
- table->field[12]->store((longlong) file->delete_length, TRUE);
+ table->field[11]->store((longlong) file->stats.index_file_length, TRUE);
+ table->field[12]->store((longlong) file->stats.delete_length, TRUE);
if (show_table->found_next_number_field)
{
- table->field[13]->store((longlong) file->auto_increment_value, TRUE);
+ table->field[13]->store((longlong) file->stats.auto_increment_value,
+ TRUE);
table->field[13]->set_notnull();
}
- if (file->create_time)
+ if (file->stats.create_time)
{
thd->variables.time_zone->gmt_sec_to_TIME(&time,
- file->create_time);
+ file->stats.create_time);
table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
table->field[14]->set_notnull();
}
- if (file->update_time)
+ if (file->stats.update_time)
{
thd->variables.time_zone->gmt_sec_to_TIME(&time,
- file->update_time);
+ file->stats.update_time);
table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
table->field[15]->set_notnull();
}
- if (file->check_time)
+ if (file->stats.check_time)
{
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->stats.check_time);
table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
table->field[16]->set_notnull();
}
tmp_buff= (share->table_charset ?
share->table_charset->name : "default");
table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
- if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
+ if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
{
table->field[18]->store((longlong) file->checksum(), TRUE);
table->field[18]->set_notnull();
@@ -2875,6 +2895,7 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables,
restore_record(show_table, s->default_values);
base_name_length= strlen(base_name);
file_name_length= strlen(file_name);
+ show_table->use_all_columns(); // Required for default
for (ptr=show_table->field; (field= *ptr) ; ptr++)
{
@@ -3091,7 +3112,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin,
void *ptable)
{
TABLE *table= (TABLE *) ptable;
- handlerton *hton= (handlerton *) plugin->plugin->info;
+ handlerton *hton= (handlerton *)plugin->data;
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
CHARSET_INFO *scs= system_charset_info;
DBUG_ENTER("iter_schema_engines");
@@ -3099,21 +3120,26 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin,
if (!(hton->flags & HTON_HIDDEN))
{
if (!(wild && wild[0] &&
- wild_case_compare(scs, hton->name,wild)))
+ wild_case_compare(scs, plugin->name.str,wild)))
{
- const char *tmp;
+ LEX_STRING state[2]= {{(char*) STRING_WITH_LEN("ENABLED")},
+ {(char*) STRING_WITH_LEN("DISABLED")}};
+ LEX_STRING yesno[2]= {{(char*) STRING_WITH_LEN("NO")},
+ {(char*) STRING_WITH_LEN("YES")}};
+ LEX_STRING *tmp;
restore_record(table, s->default_values);
- table->field[0]->store(hton->name, strlen(hton->name), scs);
- tmp= hton->state ? "DISABLED" : "ENABLED";
- table->field[1]->store( tmp, strlen(tmp), scs);
- table->field[2]->store(hton->comment, strlen(hton->comment), scs);
- tmp= hton->commit ? "YES" : "NO";
- table->field[3]->store( tmp, strlen(tmp), scs);
- tmp= hton->prepare ? "YES" : "NO";
- table->field[4]->store( tmp, strlen(tmp), scs);
- tmp= hton->savepoint_set ? "YES" : "NO";
- table->field[5]->store( tmp, strlen(tmp), scs);
+ table->field[0]->store(plugin->name.str, plugin->name.length, scs);
+ tmp= &state[test(hton->state)];
+ table->field[1]->store(tmp->str, tmp->length, scs);
+ table->field[2]->store(plugin->plugin->descr,
+ strlen(plugin->plugin->descr), scs);
+ tmp= &yesno[test(hton->commit)];
+ table->field[3]->store(tmp->str, tmp->length, scs);
+ tmp= &yesno[test(hton->prepare)];
+ table->field[4]->store(tmp->str, tmp->length, scs);
+ tmp= &yesno[test(hton->savepoint_set)];
+ table->field[5]->store(tmp->str, tmp->length, scs);
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
@@ -3125,7 +3151,7 @@ static my_bool iter_schema_engines(THD *thd, st_plugin_int *plugin,
int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond)
{
- return plugin_foreach(thd, iter_schema_engines,
+ return plugin_foreach(thd, iter_schema_engines,
MYSQL_STORAGE_ENGINE_PLUGIN, tables->table);
}
@@ -3140,7 +3166,7 @@ int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
{
CHARSET_INFO **cl;
CHARSET_INFO *tmp_cs= cs[0];
- if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
(tmp_cs->state & MY_CS_HIDDEN) ||
!(tmp_cs->state & MY_CS_PRIMARY))
continue;
@@ -3382,7 +3408,7 @@ static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
KEY *key=show_table->key_info+i;
if (key->rec_per_key[j])
{
- ha_rows records=(show_table->file->records /
+ ha_rows records=(show_table->file->stats.records /
key->rec_per_key[j]);
table->field[9]->store((longlong) records, TRUE);
table->field[9]->set_notnull();
@@ -3809,7 +3835,7 @@ static void store_schema_partitions_record(THD *thd, TABLE *table,
table->field[20]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
table->field[20]->set_notnull();
}
- if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
+ if (file->ha_table_flags() & (ulong) HA_HAS_CHECKSUM)
{
table->field[21]->store((longlong) stat_info.check_sum, TRUE);
table->field[21]->set_notnull();
@@ -3911,24 +3937,28 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
{
table->field[9]->store(part_info->part_func_string,
part_info->part_func_len, cs);
- table->field[9]->set_notnull();
}
else if (part_info->list_of_part_fields)
{
collect_partition_expr(part_info->part_field_list, &tmp_str);
table->field[9]->store(tmp_str.ptr(), tmp_str.length(), cs);
- table->field[9]->set_notnull();
}
+ table->field[9]->set_notnull();
if (part_info->is_sub_partitioned())
{
/* Subpartition method */
+ tmp_res.length(0);
+ if (part_info->linear_hash_ind)
+ tmp_res.append(partition_keywords[PKW_LINEAR].str,
+ partition_keywords[PKW_LINEAR].length);
if (part_info->list_of_subpart_fields)
- table->field[8]->store(partition_keywords[PKW_KEY].str,
- partition_keywords[PKW_KEY].length, cs);
+ tmp_res.append(partition_keywords[PKW_KEY].str,
+ partition_keywords[PKW_KEY].length);
else
- table->field[8]->store(partition_keywords[PKW_HASH].str,
- partition_keywords[PKW_HASH].length, cs);
+ tmp_res.append(partition_keywords[PKW_HASH].str,
+ partition_keywords[PKW_HASH].length);
+ table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs);
table->field[8]->set_notnull();
/* Subpartition expression */
@@ -3936,14 +3966,13 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
{
table->field[10]->store(part_info->subpart_func_string,
part_info->subpart_func_len, cs);
- table->field[10]->set_notnull();
}
else if (part_info->list_of_subpart_fields)
{
collect_partition_expr(part_info->subpart_field_list, &tmp_str);
table->field[10]->store(tmp_str.ptr(), tmp_str.length(), cs);
- table->field[10]->set_notnull();
}
+ table->field[10]->set_notnull();
}
while ((part_elem= part_it++))
@@ -4078,8 +4107,24 @@ static interval_type get_real_interval_type(interval_type i_type)
extern LEX_STRING interval_type_to_name[];
+
+/*
+ Loads an event from mysql.event and copies it's data to a row of
+ I_S.EVENTS
+
+ Synopsis
+ copy_event_to_schema_table()
+ thd Thread
+ sch_table The schema table (information_schema.event)
+ event_table The event table to use for loading (mysql.event).
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
static int
-fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
+copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
CHARSET_INFO *scs= system_charset_info;
@@ -4097,9 +4142,19 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
DBUG_RETURN(0);
-
+
+ /*
+ Skip events in schemas one does not have access to. The check is
+ optimized. It's guaranteed in case of SHOW EVENTS that the user
+ has access.
+ */
+ if (thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS &&
+ check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
+ is_schema_db(et.dbname.str)))
+ DBUG_RETURN(0);
+
/* ->field[0] is EVENT_CATALOG and is by default NULL */
-
+
sch_table->field[1]->store(et.dbname.str, et.dbname.length, scs);
sch_table->field[2]->store(et.name.str, et.name.length, scs);
sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
@@ -4111,29 +4166,28 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
ulong sql_mode_len=0;
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
- &sql_mode_len);
+ &sql_mode_len);
sch_table->field[9]->store((const char*)sql_mode_str, sql_mode_len, scs);
}
-
+
if (et.expression)
{
String show_str;
/* type */
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
- if (Events::reconstruct_interval_expression(&show_str,
- et.interval,
- et.expression))
+ if (Events::reconstruct_interval_expression(&show_str, et.interval,
+ et.expression))
DBUG_RETURN(1);
sch_table->field[7]->set_notnull();
- sch_table->field[7]->store(show_str.c_ptr(), show_str.length(), scs);
+ sch_table->field[7]->store(show_str.ptr(), show_str.length(), scs);
LEX_STRING *ival= &interval_type_to_name[et.interval];
sch_table->field[8]->set_notnull();
sch_table->field[8]->store(ival->str, ival->length, scs);
- //starts & ends
+ /* starts & ends */
sch_table->field[10]->set_notnull();
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
@@ -4152,13 +4206,13 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
}
- //status
+ /* status */
if (et.status == Event_timed::ENABLED)
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
else
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
- //on_completion
+ /* on_completion */
if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
else
@@ -4188,98 +4242,179 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
-int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
+/*
+ Performs an index scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ events_table_index_read_for_db()
+ thd Thread
+ schema_table The I_S.EVENTS table
+ event_table The event table to use for loading (mysql.event)
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+static
+int events_table_index_read_for_db(THD *thd, TABLE *schema_table,
+ TABLE *event_table)
{
- TABLE *table= tables->table;
- CHARSET_INFO *scs= system_charset_info;
- TABLE *event_table= NULL;
- Open_tables_state backup;
int ret=0;
- bool verbose= false;
- char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
- bool use_prefix_scanning= true;
- uint key_len= 0;
+ CHARSET_INFO *scs= system_charset_info;
+ KEY *key_info;
+ uint key_len;
byte *key_buf= NULL;
LINT_INIT(key_buf);
- DBUG_ENTER("fill_schema_events");
-
- strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host,
- NullS);
-
- DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer));
+ DBUG_ENTER("schema_events_do_index_scan");
- thd->reset_n_backup_open_tables_state(&backup);
+ DBUG_PRINT("info", ("Using prefix scanning on PK"));
+ event_table->file->ha_index_init(0, 1);
+ event_table->field[Events::FIELD_DB]->
+ store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
+ key_info= event_table->key_info;
+ key_len= key_info->key_part[0].store_length;
- if ((ret= Events::open_event_table(thd, TL_READ, &event_table)))
+ if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
{
- sql_print_error("Table mysql.event is damaged.");
ret= 1;
- goto err;
- }
-
- event_table->file->ha_index_init(0, 1);
-
- /* see others' events only if you have PROCESS_ACL !! */
- verbose= ((thd->lex->verbose ||
- thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS) &&
- (thd->security_ctx->master_access & PROCESS_ACL));
-
- if (verbose && thd->security_ctx->user)
- {
- ret= event_table->file->index_first(event_table->record[0]);
- use_prefix_scanning= false;
+ /* don't send error, it would be done by sql_alloc_error_handler() */
}
else
{
- event_table->field[Events::FIELD_DEFINER]->
- store(definer, strlen(definer), scs);
- key_len= event_table->key_info->key_part[0].store_length;
-
- if (thd->lex->select_lex.db)
+ key_copy(key_buf, event_table->record[0], key_info, key_len);
+ if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
+ key_len, HA_READ_PREFIX)))
{
- event_table->field[Events::FIELD_DB]->
- store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
- key_len+= event_table->key_info->key_part[1].store_length;
- }
- if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
- {
- ret= 1;
- goto err;
+ DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
+ do
+ {
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
+ if (ret == 0)
+ ret= event_table->file->index_next_same(event_table->record[0],
+ key_buf, key_len);
+ } while (ret == 0);
}
-
- key_copy(key_buf, event_table->record[0], event_table->key_info, key_len);
- ret= event_table->file->index_read(event_table->record[0], key_buf, key_len,
- HA_READ_PREFIX);
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
}
+ event_table->file->ha_index_end();
+ /* ret is guaranteed to be != 0 */
+ if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(0);
+ DBUG_RETURN(1);
+}
- if (ret)
+
+/*
+ Performs a table scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ events_table_scan_all()
+ thd Thread
+ schema_table The I_S.EVENTS in memory table
+ event_table The event table to use for loading.
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+static
+int events_table_scan_all(THD *thd, TABLE *schema_table,
+ TABLE *event_table)
+{
+ int ret;
+ READ_RECORD read_record_info;
+
+ DBUG_ENTER("schema_events_do_table_scan");
+ init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
+
+ /*
+ rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
+ but rr_handle_error returns -1 for that reason. Thus, read_record()
+ returns -1 eventually.
+ */
+ do
{
- ret= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1;
- goto err;
+ ret= read_record_info.read_record(&read_record_info);
+ if (ret == 0)
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
}
+ while (ret == 0);
- while (!ret)
- {
- if ((ret= fill_events_copy_to_schema_table(thd, table, event_table)))
- goto err;
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
+ end_read_record(&read_record_info);
- if (use_prefix_scanning)
- ret= event_table->file->
- index_next_same(event_table->record[0], key_buf, key_len);
- else
- ret= event_table->file->index_next(event_table->record[0]);
+ /* ret is guaranteed to be != 0 */
+ DBUG_RETURN(ret == -1? 0:1);
+}
+
+
+/*
+ Fills I_S.EVENTS with data loaded from mysql.event. Also used by
+ SHOW EVENTS
+
+ Synopsis
+ fill_schema_events()
+ thd Thread
+ tables The schema table
+ cond Unused
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
+{
+ TABLE *schema_table= tables->table;
+ TABLE *event_table= NULL;
+ Open_tables_state backup;
+ int ret= 0;
+
+ DBUG_ENTER("fill_schema_events");
+ /*
+ If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
+ be NULL. Let's do an assert anyway.
+ */
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+ {
+ DBUG_ASSERT(thd->lex->select_lex.db);
+ if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
+ is_schema_db(thd->lex->select_lex.db)))
+ DBUG_RETURN(1);
}
- // ret is guaranteed to be != 0
- ret= (ret != HA_ERR_END_OF_FILE);
-err:
- if (event_table)
+
+ DBUG_PRINT("info",("db=%s", thd->lex->select_lex.db?
+ thd->lex->select_lex.db:"(null)"));
+
+ thd->reset_n_backup_open_tables_state(&backup);
+ if (Events::open_event_table(thd, TL_READ, &event_table))
{
- event_table->file->ha_index_end();
- close_thread_tables(thd);
+ sql_print_error("Table mysql.event is damaged.");
+ thd->restore_backup_open_tables_state(&backup);
+ DBUG_RETURN(1);
}
+ /*
+ 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
+ thus we won't order it. OTOH, SHOW EVENTS will be
+ ordered.
+ 2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
+ Reasoning: Events are per schema, therefore a scan over an index
+ will save use from doing a table scan and comparing
+ every single row's `db` with the schema which we show.
+ */
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+ ret= events_table_index_read_for_db(thd, schema_table, event_table);
+ else
+ ret= events_table_scan_all(thd, schema_table, event_table);
+
+ close_thread_tables(thd);
thd->restore_backup_open_tables_state(&backup);
+
+ DBUG_PRINT("info", ("Return code=%d", ret));
DBUG_RETURN(ret);
}
@@ -4502,7 +4637,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
field_count++;
}
TMP_TABLE_PARAM *tmp_table_param =
- (TMP_TABLE_PARAM*) (thd->calloc(sizeof(TMP_TABLE_PARAM)));
+ (TMP_TABLE_PARAM*) (thd->alloc(sizeof(TMP_TABLE_PARAM)));
tmp_table_param->init();
tmp_table_param->table_charset= cs;
tmp_table_param->field_count= field_count;
@@ -4874,7 +5009,7 @@ bool get_schema_tables_result(JOIN *join)
filesort_free_buffers(table_list->table);
}
else
- table_list->table->file->records= 0;
+ table_list->table->file->stats.records= 0;
if (table_list->schema_table->fill_table(thd, table_list,
tab->select_cond))
@@ -4897,7 +5032,7 @@ static my_bool run_hton_fill_schema_files(THD *thd, st_plugin_int *plugin,
{
struct run_hton_fill_schema_files_args *args=
(run_hton_fill_schema_files_args *) arg;
- handlerton *hton= (handlerton *) plugin->plugin->info;
+ handlerton *hton= (handlerton *)plugin->data;
if(hton->fill_files_table)
hton->fill_files_table(thd, args->tables, args->cond);
return false;
@@ -5241,7 +5376,7 @@ ST_FIELD_INFO partitions_fields_info[]=
{"PARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
{"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
{"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0},
- {"SUBPARTITION_METHOD", 5, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0},
{"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
{"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
{"PARTITION_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 1, 0},
@@ -5316,9 +5451,9 @@ ST_FIELD_INFO files_fields_info[]=
{"FREE_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0},
{"TOTAL_EXTENTS", 4, MYSQL_TYPE_LONG, 0, 0, 0},
{"EXTENT_SIZE", 4, MYSQL_TYPE_LONG, 0, 0, 0},
- {"INITIAL_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
- {"MAXIMUM_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
- {"AUTOEXTEND_SIZE", 8, MYSQL_TYPE_LONGLONG, 0, 0, 0},
+ {"INITIAL_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0},
+ {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0},
+ {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONG, 0, 0, 0},
{"CREATION_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},
{"LAST_ACCESS_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, 0},