diff options
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r-- | sql/sql_show.cc | 1993 |
1 files changed, 1210 insertions, 783 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 4e37b53b87e..a920b236d4f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,7 +17,7 @@ /* Function with list databases, tables or fields */ -#include "sql_plugin.h" // Includes my_global.h +#include "sql_plugin.h" // SHOW_MY_BOOL #include "sql_priv.h" #include "unireg.h" #include "sql_acl.h" // fill_schema_*_privileges @@ -58,10 +58,12 @@ #include "lock.h" // MYSQL_OPEN_IGNORE_FLUSH #include "debug_sync.h" #include "keycaches.h" - +#include "ha_sequence.h" #ifdef WITH_PARTITION_STORAGE_ENGINE #include "ha_partition.h" #endif +#include "transaction.h" + enum enum_i_s_events_fields { ISE_EVENT_CATALOG= 0, @@ -92,18 +94,17 @@ enum enum_i_s_events_fields #define USERNAME_WITH_HOST_CHAR_LENGTH (USERNAME_CHAR_LENGTH + HOSTNAME_LENGTH + 2) - -static const LEX_STRING trg_action_time_type_names[]= +static const LEX_CSTRING trg_action_time_type_names[]= { - { C_STRING_WITH_LEN("BEFORE") }, - { C_STRING_WITH_LEN("AFTER") } + { STRING_WITH_LEN("BEFORE") }, + { STRING_WITH_LEN("AFTER") } }; -static const LEX_STRING trg_event_type_names[]= +static const LEX_CSTRING trg_event_type_names[]= { - { C_STRING_WITH_LEN("INSERT") }, - { C_STRING_WITH_LEN("UPDATE") }, - { C_STRING_WITH_LEN("DELETE") } + { STRING_WITH_LEN("INSERT") }, + { STRING_WITH_LEN("UPDATE") }, + { STRING_WITH_LEN("DELETE") } }; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -130,11 +131,36 @@ static void get_cs_converted_string_value(THD *thd, #endif static int show_create_view(THD *thd, TABLE_LIST *table, String *buff); +static int show_create_sequence(THD *thd, TABLE_LIST *table_list, + String *packet); -static const LEX_STRING *view_algorithm(TABLE_LIST *table); +static const LEX_CSTRING *view_algorithm(TABLE_LIST *table); bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *); +/** + Try to lock a mutex, but give up after a short while to not cause deadlocks + + The loop is short, as the mutex we are trying to lock are mutex the should + never be locked a long time, just over a few instructions. + + @return 0 ok + @return 1 error +*/ + +static bool trylock_short(mysql_mutex_t *mutex) +{ + uint i; + for (i= 0 ; i < 100 ; i++) + { + if (!mysql_mutex_trylock(mutex)) + return 0; + LF_BACKOFF(); + } + return 1; +} + + /*************************************************************************** ** List all table types supported ***************************************************************************/ @@ -147,17 +173,17 @@ static bool is_show_command(THD *thd) static int make_version_string(char *buf, int buf_length, uint version) { - return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); + return (int)my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); } -static const LEX_STRING maturity_name[]={ - { C_STRING_WITH_LEN("Unknown") }, - { C_STRING_WITH_LEN("Experimental") }, - { C_STRING_WITH_LEN("Alpha") }, - { C_STRING_WITH_LEN("Beta") }, - { C_STRING_WITH_LEN("Gamma") }, - { C_STRING_WITH_LEN("Stable") }}; +static const LEX_CSTRING maturity_name[]={ + { STRING_WITH_LEN("Unknown") }, + { STRING_WITH_LEN("Experimental") }, + { STRING_WITH_LEN("Alpha") }, + { STRING_WITH_LEN("Beta") }, + { STRING_WITH_LEN("Gamma") }, + { STRING_WITH_LEN("Stable") }}; static my_bool show_plugins(THD *thd, plugin_ref plugin, @@ -317,7 +343,7 @@ int fill_all_plugins(THD *thd, TABLE_LIST *tables, COND *cond) for (uint i=0; i < (uint) dirp->number_of_files; i++) { FILEINFO *file= dirp->dir_entry+i; - LEX_STRING dl= { file->name, strlen(file->name) }; + LEX_CSTRING dl= { file->name, strlen(file->name) }; const char *dlend= dl.str + dl.length; const size_t so_ext_len= sizeof(SO_EXT) - 1; @@ -390,8 +416,8 @@ exit: static int get_geometry_column_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; TABLE *show_table; @@ -445,7 +471,8 @@ static int get_geometry_column_record(THD *thd, TABLE_LIST *tables, /*G_TABLE_NAME*/ table->field[6]->store(table_name->str, table_name->length, cs); /*G_GEOMETRY_COLUMN*/ - table->field[7]->store(field->field_name, strlen(field->field_name), cs); + table->field[7]->store(field->field_name.str, field->field_name.length, + cs); /*STORAGE_TYPE*/ table->field[8]->store(1LL, TRUE); /*Always 1 (binary implementation)*/ /*GEOMETRY_TYPE*/ @@ -565,6 +592,7 @@ static struct show_privileges_st sys_privileges[]= {"Create view", "Tables", "To create new views"}, {"Create user", "Server Admin", "To create new users"}, {"Delete", "Tables", "To delete existing rows"}, + {"Delete history", "Tables", "To delete versioning table historical rows"}, {"Drop", "Databases,Tables", "To drop databases, tables, and views"}, #ifdef HAVE_EVENT_SCHEDULER {"Event","Server Admin","To create, alter, drop and execute events"}, @@ -670,7 +698,7 @@ static bool skip_ignored_dir_check= TRUE; bool ignore_db_dirs_init() { - return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *), + return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_CSTRING *), 0, 0, MYF(0)); } @@ -690,7 +718,7 @@ static uchar * db_dirs_hash_get_key(const uchar *data, size_t *len_ret, my_bool __attribute__((unused))) { - LEX_STRING *e= (LEX_STRING *) data; + LEX_CSTRING *e= (LEX_CSTRING *) data; *len_ret= e->length; return (uchar *) e->str; @@ -711,7 +739,7 @@ db_dirs_hash_get_key(const uchar *data, size_t *len_ret, bool push_ignored_db_dir(char *path) { - LEX_STRING *new_elt; + LEX_CSTRING *new_elt; char *new_elt_buffer; size_t path_len= strlen(path); @@ -720,7 +748,7 @@ push_ignored_db_dir(char *path) // No need to normalize, it's only a directory name, not a path. if (!my_multi_malloc(0, - &new_elt, sizeof(LEX_STRING), + &new_elt, sizeof(LEX_CSTRING), &new_elt_buffer, path_len + 1, NullS)) return true; @@ -742,8 +770,8 @@ push_ignored_db_dir(char *path) void ignore_db_dirs_reset() { - LEX_STRING **elt; - while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array))) + LEX_CSTRING **elt; + while (NULL!= (elt= (LEX_CSTRING **) pop_dynamic(&ignore_db_dirs_array))) if (elt && *elt) my_free(*elt); } @@ -844,8 +872,7 @@ ignore_db_dirs_process_additions() ulong i; size_t len; char *ptr; - LEX_STRING *dir; - + LEX_CSTRING *dir; skip_ignored_dir_check= TRUE; @@ -997,8 +1024,8 @@ enum find_files_result { static find_files_result -find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db, - const char *path, const LEX_STRING *wild) +find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db, + const char *path, const LEX_CSTRING *wild) { MY_DIR *dirp; Discovered_table_list tl(thd, files, wild); @@ -1049,14 +1076,19 @@ find_files(THD *thd, Dynamic_array<LEX_STRING*> *files, LEX_STRING *db, if (ha_discover_table_names(thd, db, dirp, &tl, false)) goto err; } -#if MYSQL_VERSION_ID < 100300 - /* incomplete optimization, but a less drastic change in GA version */ - if (!thd->lex->select_lex.order_list.elements && - !thd->lex->select_lex.group_list.elements) -#else if (is_show_command(thd)) -#endif tl.sort(); +#ifndef DBUG_OFF + else + { + /* + sort_desc() is used to find easier unstable mtr tests that query + INFORMATION_SCHEMA.{SCHEMATA|TABLES} without a proper ORDER BY. + This can be removed in some release after 10.3 (e.g. in 10.4). + */ + tl.sort_desc(); + } +#endif DBUG_PRINT("info",("found: %zu files", files->elements())); my_dirend(dirp); @@ -1209,17 +1241,17 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, LEX *lex= thd->lex; MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_show_create_get_fields"); - DBUG_PRINT("enter",("db: %s table: %s",table_list->db, - table_list->table_name)); + DBUG_PRINT("enter",("db: %s table: %s",table_list->db.str, + table_list->table_name.str)); - if (lex->only_view) + if (lex->table_type == TABLE_TYPE_VIEW) { if (check_table_access(thd, SELECT_ACL, table_list, FALSE, 1, FALSE)) { DBUG_PRINT("debug", ("check_table_access failed")); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "SHOW", thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias); + thd->security_ctx->host_or_ip, table_list->alias.str); goto exit; } DBUG_PRINT("debug", ("check_table_access succeeded")); @@ -1248,7 +1280,7 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "SHOW", thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias); + thd->security_ctx->host_or_ip, table_list->alias.str); goto exit; } } @@ -1272,15 +1304,23 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) || mysql_handle_derived(lex, DT_INIT | DT_PREPARE); thd->pop_internal_handler(); - if (open_error && (thd->killed || thd->is_error())) + if (unlikely(open_error && (thd->killed || thd->is_error()))) goto exit; } /* TODO: add environment variables show when it become possible */ - if (lex->only_view && !table_list->view) + if (lex->table_type == TABLE_TYPE_VIEW && !table_list->view) { my_error(ER_WRONG_OBJECT, MYF(0), - table_list->db, table_list->table_name, "VIEW"); + table_list->db.str, table_list->table_name.str, "VIEW"); + goto exit; + } + else if (lex->table_type == TABLE_TYPE_SEQUENCE && + (!table_list->table || + table_list->table->s->table_type != TABLE_TYPE_SEQUENCE)) + { + my_error(ER_NOT_SEQUENCE, MYF(0), + table_list->db.str, table_list->table_name.str); goto exit; } @@ -1291,6 +1331,8 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, if ((table_list->view ? show_create_view(thd, table_list, buffer) : + lex->table_type == TABLE_TYPE_SEQUENCE ? + show_create_sequence(thd, table_list, buffer) : show_create_table(thd, table_list, buffer, NULL, WITHOUT_DB_NAME))) goto exit; @@ -1354,8 +1396,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) List<Item> field_list; bool error= TRUE; DBUG_ENTER("mysqld_show_create"); - DBUG_PRINT("enter",("db: %s table: %s",table_list->db, - table_list->table_name)); + DBUG_PRINT("enter",("db: %s table: %s",table_list->db.str, + table_list->table_name.str)); /* Metadata locks taken during SHOW CREATE should be released when @@ -1363,6 +1405,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) */ MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint(); + TABLE_LIST archive; if (mysqld_show_create_get_fields(thd, table_list, &field_list, &buffer)) goto exit; @@ -1378,8 +1421,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) else { if (table_list->schema_table) - protocol->store(table_list->schema_table->table_name, - system_charset_info); + protocol->store(table_list->schema_table->table_name, system_charset_info); else protocol->store(table_list->table->alias.c_ptr(), system_charset_info); } @@ -1424,8 +1466,8 @@ void mysqld_show_create_db_get_fields(THD *thd, List<Item> *field_list) } -bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, - LEX_STRING *orig_dbname, +bool mysqld_show_create_db(THD *thd, LEX_CSTRING *dbname, + LEX_CSTRING *orig_dbname, const DDL_options_st &options) { char buff[2048]; @@ -1460,7 +1502,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, DBUG_RETURN(TRUE); } #endif - if (is_infoschema_db(dbname->str)) + if (is_infoschema_db(dbname)) { *dbname= INFORMATION_SCHEMA_NAME; create.default_table_charset= system_charset_info; @@ -1489,7 +1531,7 @@ bool mysqld_show_create_db(THD *thd, LEX_STRING *dbname, buffer.append(STRING_WITH_LEN("CREATE DATABASE ")); if (options.if_not_exists()) buffer.append(STRING_WITH_LEN("/*!32312 IF NOT EXISTS*/ ")); - append_identifier(thd, &buffer, dbname->str, dbname->length); + append_identifier(thd, &buffer, dbname); if (create.default_table_charset) { @@ -1524,7 +1566,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) TABLE *table; MEM_ROOT *mem_root= thd->mem_root; DBUG_ENTER("mysqld_list_fields"); - DBUG_PRINT("enter",("table: %s",table_list->table_name)); + DBUG_PRINT("enter",("table: %s", table_list->table_name.str)); if (open_normal_and_derived_tables(thd, table_list, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL, @@ -1538,7 +1580,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) for (ptr=table->field ; (field= *ptr); ptr++) { if (!wild || !wild[0] || - !wild_case_compare(system_charset_info, field->field_name,wild)) + !wild_case_compare(system_charset_info, field->field_name.str,wild)) { if (table_list->view) field_list.push_back(new (mem_root) @@ -1607,7 +1649,7 @@ static const char *require_quotes(const char *name, uint name_length) */ bool -append_identifier(THD *thd, String *packet, const char *name, uint length) +append_identifier(THD *thd, String *packet, const char *name, size_t length) { const char *name_end; char quote_char; @@ -1686,11 +1728,11 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) # Quote character */ -int get_quote_char_for_identifier(THD *thd, const char *name, uint length) +int get_quote_char_for_identifier(THD *thd, const char *name, size_t length) { if (length && - !is_keyword(name,length) && - !require_quotes(name, length) && + !is_keyword(name,(uint)length) && + !require_quotes(name, (uint)length) && !(thd->variables.option_bits & OPTION_QUOTE_SHOW_CREATE)) return EOF; if (thd->variables.sql_mode & MODE_ANSI_QUOTES) @@ -1706,7 +1748,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, { if (filename && !(thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)) { - uint length= dirname_length(filename); + size_t length= dirname_length(filename); packet->append(' '); packet->append(dir_type); packet->append(STRING_WITH_LEN(" DIRECTORY='")); @@ -1767,6 +1809,7 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, has_default= (field->default_value || (!(field->flags & NO_DEFAULT_VALUE_FLAG) && + !field->vers_sys_field() && field->unireg_check != Field::NEXT_NUMBER)); def_value->length(0); @@ -1863,17 +1906,190 @@ static void append_create_options(THD *thd, String *packet, DBUG_ASSERT(opt->value.str); packet->append(' '); - append_identifier(thd, packet, opt->name.str, opt->name.length); + append_identifier(thd, packet, &opt->name); packet->append('='); if (opt->quoted_value) append_unescaped(packet, opt->value.str, opt->value.length); else - packet->append(opt->value.str, opt->value.length); + packet->append(&opt->value); } if (in_comment) packet->append(STRING_WITH_LEN(" */")); } +/** + Add table options to end of CREATE statement + + @param schema_table 1 if schema table + @param sequence 1 if sequence. If sequence, we flush out options + not relevant for sequences. +*/ + +static void add_table_options(THD *thd, TABLE *table, + Table_specification_st *create_info_arg, + bool schema_table, bool sequence, + String *packet) +{ + sql_mode_t sql_mode= thd->variables.sql_mode; + TABLE_SHARE *share= table->s; + handlerton *hton; + HA_CREATE_INFO create_info; + bool check_options= (!(sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) && + !create_info_arg); + +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (table->part_info) + hton= table->part_info->default_engine_type; + else +#endif + hton= table->file->ht; + + bzero((char*) &create_info, sizeof(create_info)); + /* Allow update_create_info to update row type, page checksums and options */ + create_info.row_type= share->row_type; + create_info.page_checksum= share->page_checksum; + create_info.options= share->db_create_options; + table->file->update_create_info(&create_info); + + /* + IF check_create_info + THEN add ENGINE only if it was used when creating the table + */ + if (!create_info_arg || + (create_info_arg->used_fields & HA_CREATE_USED_ENGINE)) + { + LEX_CSTRING *engine_name= table->file->engine_name(); + + if (sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) + packet->append(STRING_WITH_LEN(" TYPE=")); + else + packet->append(STRING_WITH_LEN(" ENGINE=")); + + packet->append(engine_name->str, engine_name->length); + } + + if (sequence) + goto end_options; + + /* + Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column, + and NEXT_ID > 1 (the default). We must not print the clause + for engines that do not support this as it would break the + import of dumps, but as of this writing, the test for whether + AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=... + is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT)) + Because of that, we do not explicitly test for the feature, + but may extrapolate its existence from that of an AUTO_INCREMENT column. + */ + + if (create_info.auto_increment_value > 1) + { + packet->append(STRING_WITH_LEN(" AUTO_INCREMENT=")); + packet->append_ulonglong(create_info.auto_increment_value); + } + + if (share->table_charset && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) && + share->table_type != TABLE_TYPE_SEQUENCE) + { + /* + IF check_create_info + THEN add DEFAULT CHARSET only if it was used when creating the table + */ + if (!create_info_arg || + (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) + { + packet->append(STRING_WITH_LEN(" DEFAULT CHARSET=")); + packet->append(share->table_charset->csname); + if (!(share->table_charset->state & MY_CS_PRIMARY)) + { + packet->append(STRING_WITH_LEN(" COLLATE=")); + packet->append(table->s->table_charset->name); + } + } + } + + if (share->min_rows) + { + packet->append(STRING_WITH_LEN(" MIN_ROWS=")); + packet->append_ulonglong(share->min_rows); + } + + if (share->max_rows && !schema_table && !sequence) + { + packet->append(STRING_WITH_LEN(" MAX_ROWS=")); + packet->append_ulonglong(share->max_rows); + } + + if (share->avg_row_length) + { + packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH=")); + packet->append_ulonglong(share->avg_row_length); + } + + if (create_info.options & HA_OPTION_PACK_KEYS) + packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); + if (create_info.options & HA_OPTION_NO_PACK_KEYS) + packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); + if (share->db_create_options & HA_OPTION_STATS_PERSISTENT) + packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1")); + if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT) + packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0")); + if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON) + packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1")); + else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF) + packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0")); + if (share->stats_sample_pages != 0) + { + packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES=")); + packet->append_ulonglong(share->stats_sample_pages); + } + + /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ + if (create_info.options & HA_OPTION_CHECKSUM) + packet->append(STRING_WITH_LEN(" CHECKSUM=1")); + if (create_info.page_checksum != HA_CHOICE_UNDEF) + { + packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM=")); + packet->append(ha_choice_values[create_info.page_checksum], 1); + } + if (create_info.options & HA_OPTION_DELAY_KEY_WRITE) + packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1")); + if (create_info.row_type != ROW_TYPE_DEFAULT) + { + packet->append(STRING_WITH_LEN(" ROW_FORMAT=")); + packet->append(ha_row_type[(uint) create_info.row_type]); + } + if (share->transactional != HA_CHOICE_UNDEF) + { + packet->append(STRING_WITH_LEN(" TRANSACTIONAL=")); + packet->append(ha_choice_values[(uint) share->transactional], 1); + } + if (share->table_type == TABLE_TYPE_SEQUENCE) + packet->append(STRING_WITH_LEN(" SEQUENCE=1")); + if (table->s->key_block_size) + { + packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE=")); + packet->append_ulonglong(table->s->key_block_size); + } + table->file->append_create_info(packet); + +end_options: + if (share->comment.length) + { + packet->append(STRING_WITH_LEN(" COMMENT=")); + append_unescaped(packet, share->comment.str, share->comment.length); + } + if (share->connect_string.length) + { + packet->append(STRING_WITH_LEN(" CONNECTION=")); + append_unescaped(packet, share->connect_string.str, share->connect_string.length); + } + append_create_options(thd, packet, share->option_list, check_options, + hton->table_options); + append_directory(thd, packet, "DATA", create_info.data_file_name); + append_directory(thd, packet, "INDEX", create_info.index_file_name); +} + /* Build a CREATE TABLE statement for a table. @@ -1903,18 +2119,17 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, enum_with_db_name with_db_name) { List<Item> field_list; - char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH]; - const char *alias; + char tmp[MAX_FIELD_WIDTH], *for_str, def_value_buf[MAX_FIELD_WIDTH]; + LEX_CSTRING alias; String type; String def_value; Field **ptr,*field; uint primary_key; KEY *key_info; TABLE *table= table_list->table; - handler *file= table->file; TABLE_SHARE *share= table->s; - HA_CREATE_INFO create_info; sql_mode_t sql_mode= thd->variables.sql_mode; + bool explicit_fields= false; bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | MODE_DB2 | MODE_MAXDB | MODE_ANSI); @@ -1924,8 +2139,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, !foreign_db_mode; bool check_options= !(sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS) && !create_info_arg; - handlerton *hton; my_bitmap_map *old_map; + handlerton *hton; int error= 0; DBUG_ENTER("show_create_table"); DBUG_PRINT("enter",("table: %s", table->s->table_name.str)); @@ -1935,7 +2150,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, hton= table->part_info->default_engine_type; else #endif - hton= file->ht; + hton= table->file->ht; restore_record(table, s->default_values); // Get empty record @@ -1951,15 +2166,19 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, if (create_info_arg && create_info_arg->if_not_exists()) packet->append(STRING_WITH_LEN("IF NOT EXISTS ")); if (table_list->schema_table) - alias= table_list->schema_table->table_name; + { + alias.str= table_list->schema_table->table_name; + alias.length= strlen(alias.str); + } else { if (lower_case_table_names == 2) - alias= table->alias.c_ptr(); - else { - alias= share->table_name.str; + alias.str= table->alias.c_ptr(); + alias.length= table->alias.length(); } + else + alias= share->table_name; } /* @@ -1971,16 +2190,16 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, */ if (with_db_name == WITH_DB_NAME) { - const LEX_STRING *const db= + const LEX_CSTRING *const db= table_list->schema_table ? &INFORMATION_SCHEMA_NAME : &table->s->db; - if (!thd->db || strcmp(db->str, thd->db)) + if (!thd->db.str || cmp(db, &thd->db)) { - append_identifier(thd, packet, db->str, db->length); + append_identifier(thd, packet, db); packet->append(STRING_WITH_LEN(".")); } } - append_identifier(thd, packet, alias, strlen(alias)); + append_identifier(thd, packet, &alias); packet->append(STRING_WITH_LEN(" (\n")); /* We need this to get default values from the table @@ -1989,15 +2208,20 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, */ old_map= tmp_use_all_columns(table, table->read_set); + bool not_the_first_field= false; for (ptr=table->field ; (field= *ptr); ptr++) { + uint flags = field->flags; - if (ptr != table->field) + if (field->invisible > INVISIBLE_USER) + continue; + if (not_the_first_field) packet->append(STRING_WITH_LEN(",\n")); + not_the_first_field= true; packet->append(STRING_WITH_LEN(" ")); - append_identifier(thd,packet,field->field_name, strlen(field->field_name)); + append_identifier(thd, packet, &field->field_name); packet->append(' '); type.set(tmp, sizeof(tmp), system_charset_info); @@ -2033,10 +2257,22 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" STORED")); else packet->append(STRING_WITH_LEN(" VIRTUAL")); + if (field->invisible == INVISIBLE_USER) + { + packet->append(STRING_WITH_LEN(" INVISIBLE")); + } } else { - if (flags & NOT_NULL_FLAG) + if (field->flags & VERS_SYS_START_FLAG) + { + packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW START")); + } + else if (field->flags & VERS_SYS_END_FLAG) + { + packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS ROW END")); + } + else if (flags & NOT_NULL_FLAG) packet->append(STRING_WITH_LEN(" NOT NULL")); else if (field->type() == MYSQL_TYPE_TIMESTAMP) { @@ -2047,6 +2283,10 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" NULL")); } + if (field->invisible == INVISIBLE_USER) + { + packet->append(STRING_WITH_LEN(" INVISIBLE")); + } def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info); if (get_field_default_value(thd, field, &def_value, 1)) { @@ -2054,6 +2294,11 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(def_value.ptr(), def_value.length(), system_charset_info); } + if (field->vers_update_unversioned()) + { + packet->append(STRING_WITH_LEN(" WITHOUT SYSTEM VERSIONING")); + } + if (!limited_mysql_mode && print_on_update_clause(field, &def_value, false)) { @@ -2087,21 +2332,17 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, } key_info= table->key_info; - bzero((char*) &create_info, sizeof(create_info)); - /* Allow update_create_info to update row type, page checksums and options */ - create_info.row_type= share->row_type; - create_info.page_checksum= share->page_checksum; - create_info.options= share->db_create_options; - file->update_create_info(&create_info); primary_key= share->primary_key; for (uint i=0 ; i < share->keys ; i++,key_info++) { + if (key_info->flags & HA_INVISIBLE_KEY) + continue; KEY_PART_INFO *key_part= key_info->key_part; bool found_primary=0; packet->append(STRING_WITH_LEN(",\n ")); - if (i == primary_key && !strcmp(key_info->name, primary_key_name)) + if (i == primary_key && !strcmp(key_info->name.str, primary_key_name)) { found_primary=1; /* @@ -2120,18 +2361,21 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN("KEY ")); if (!found_primary) - append_identifier(thd, packet, key_info->name, strlen(key_info->name)); + append_identifier(thd, packet, &key_info->name); packet->append(STRING_WITH_LEN(" (")); for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { + Field *field= key_part->field; + if (field->invisible > INVISIBLE_USER) + continue; + if (j) packet->append(','); if (key_part->field) - append_identifier(thd,packet,key_part->field->field_name, - strlen(key_part->field->field_name)); + append_identifier(thd, packet, &key_part->field->field_name); if (key_part->field && (key_part->length != table->field[key_part->fieldnr-1]->key_length() && @@ -2145,24 +2389,47 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, store_key_options(thd, packet, table, key_info); if (key_info->parser) { - LEX_STRING *parser_name= plugin_name(key_info->parser); + LEX_CSTRING *parser_name= plugin_name(key_info->parser); packet->append(STRING_WITH_LEN(" /*!50100 WITH PARSER ")); - append_identifier(thd, packet, parser_name->str, parser_name->length); + append_identifier(thd, packet, parser_name); packet->append(STRING_WITH_LEN(" */ ")); } append_create_options(thd, packet, key_info->option_list, check_options, hton->index_options); } + if (table->versioned()) + { + const Field *fs = table->vers_start_field(); + const Field *fe = table->vers_end_field(); + DBUG_ASSERT(fs); + DBUG_ASSERT(fe); + explicit_fields= fs->invisible < INVISIBLE_SYSTEM; + DBUG_ASSERT(!explicit_fields || fe->invisible < INVISIBLE_SYSTEM); + if (explicit_fields) + { + packet->append(STRING_WITH_LEN(",\n PERIOD FOR SYSTEM_TIME (")); + append_identifier(thd,packet,fs->field_name.str, fs->field_name.length); + packet->append(STRING_WITH_LEN(", ")); + append_identifier(thd,packet,fe->field_name.str, fe->field_name.length); + packet->append(STRING_WITH_LEN(")")); + } + else + { + DBUG_ASSERT(fs->invisible == INVISIBLE_SYSTEM); + DBUG_ASSERT(fe->invisible == INVISIBLE_SYSTEM); + } + } + /* Get possible foreign key definitions stored in InnoDB and append them to the CREATE TABLE statement */ - if ((for_str= file->get_foreign_key_create_info())) + if ((for_str= table->file->get_foreign_key_create_info())) { packet->append(for_str, strlen(for_str)); - file->free_foreign_key_create_info(for_str); + table->file->free_foreign_key_create_info(for_str); } /* Add table level check constraints */ @@ -2176,10 +2443,10 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, check->print(&str); packet->append(STRING_WITH_LEN(",\n ")); - if (check->name.length) + if (check->name.str) { packet->append(STRING_WITH_LEN("CONSTRAINT ")); - append_identifier(thd, packet, check->name.str, check->name.length); + append_identifier(thd, packet, &check->name); } packet->append(STRING_WITH_LEN(" CHECK (")); packet->append(str); @@ -2189,146 +2456,12 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN("\n)")); if (show_table_options) - { - /* - IF check_create_info - THEN add ENGINE only if it was used when creating the table - */ - if (!create_info_arg || - (create_info_arg->used_fields & HA_CREATE_USED_ENGINE)) - { - if (sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) - packet->append(STRING_WITH_LEN(" TYPE=")); - else - packet->append(STRING_WITH_LEN(" ENGINE=")); - packet->append(hton_name(hton)); - } - - /* - Add AUTO_INCREMENT=... if there is an AUTO_INCREMENT column, - and NEXT_ID > 1 (the default). We must not print the clause - for engines that do not support this as it would break the - import of dumps, but as of this writing, the test for whether - AUTO_INCREMENT columns are allowed and wether AUTO_INCREMENT=... - is supported is identical, !(file->table_flags() & HA_NO_AUTO_INCREMENT)) - Because of that, we do not explicitly test for the feature, - but may extrapolate its existence from that of an AUTO_INCREMENT column. - */ - - if (create_info.auto_increment_value > 1) - { - char *end; - packet->append(STRING_WITH_LEN(" AUTO_INCREMENT=")); - end= longlong10_to_str(create_info.auto_increment_value, buff,10); - packet->append(buff, (uint) (end - buff)); - } - - if (share->table_charset && !(sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))) - { - /* - IF check_create_info - THEN add DEFAULT CHARSET only if it was used when creating the table - */ - if (!create_info_arg || - (create_info_arg->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)) - { - packet->append(STRING_WITH_LEN(" DEFAULT CHARSET=")); - packet->append(share->table_charset->csname); - if (!(share->table_charset->state & MY_CS_PRIMARY)) - { - packet->append(STRING_WITH_LEN(" COLLATE=")); - packet->append(table->s->table_charset->name); - } - } - } - - if (share->min_rows) - { - char *end; - packet->append(STRING_WITH_LEN(" MIN_ROWS=")); - end= longlong10_to_str(share->min_rows, buff, 10); - packet->append(buff, (uint) (end- buff)); - } - - if (share->max_rows && !table_list->schema_table) - { - char *end; - packet->append(STRING_WITH_LEN(" MAX_ROWS=")); - end= longlong10_to_str(share->max_rows, buff, 10); - packet->append(buff, (uint) (end - buff)); - } - - if (share->avg_row_length) - { - char *end; - packet->append(STRING_WITH_LEN(" AVG_ROW_LENGTH=")); - end= longlong10_to_str(share->avg_row_length, buff,10); - packet->append(buff, (uint) (end - buff)); - } + add_table_options(thd, table, create_info_arg, + table_list->schema_table != 0, 0, packet); - if (create_info.options & HA_OPTION_PACK_KEYS) - packet->append(STRING_WITH_LEN(" PACK_KEYS=1")); - if (create_info.options & HA_OPTION_NO_PACK_KEYS) - packet->append(STRING_WITH_LEN(" PACK_KEYS=0")); - if (share->db_create_options & HA_OPTION_STATS_PERSISTENT) - packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=1")); - if (share->db_create_options & HA_OPTION_NO_STATS_PERSISTENT) - packet->append(STRING_WITH_LEN(" STATS_PERSISTENT=0")); - if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_ON) - packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=1")); - else if (share->stats_auto_recalc == HA_STATS_AUTO_RECALC_OFF) - packet->append(STRING_WITH_LEN(" STATS_AUTO_RECALC=0")); - if (share->stats_sample_pages != 0) - { - char *end; - packet->append(STRING_WITH_LEN(" STATS_SAMPLE_PAGES=")); - end= longlong10_to_str(share->stats_sample_pages, buff, 10); - packet->append(buff, (uint) (end - buff)); - } + if (table->versioned()) + packet->append(STRING_WITH_LEN(" WITH SYSTEM VERSIONING")); - /* We use CHECKSUM, instead of TABLE_CHECKSUM, for backward compability */ - if (create_info.options & HA_OPTION_CHECKSUM) - packet->append(STRING_WITH_LEN(" CHECKSUM=1")); - if (create_info.page_checksum != HA_CHOICE_UNDEF) - { - packet->append(STRING_WITH_LEN(" PAGE_CHECKSUM=")); - packet->append(ha_choice_values[create_info.page_checksum], 1); - } - if (create_info.options & HA_OPTION_DELAY_KEY_WRITE) - packet->append(STRING_WITH_LEN(" DELAY_KEY_WRITE=1")); - if (create_info.row_type != ROW_TYPE_DEFAULT) - { - packet->append(STRING_WITH_LEN(" ROW_FORMAT=")); - packet->append(ha_row_type[(uint) create_info.row_type]); - } - if (share->transactional != HA_CHOICE_UNDEF) - { - packet->append(STRING_WITH_LEN(" TRANSACTIONAL=")); - packet->append(ha_choice_values[(uint) share->transactional], 1); - } - if (table->s->key_block_size) - { - char *end; - packet->append(STRING_WITH_LEN(" KEY_BLOCK_SIZE=")); - end= longlong10_to_str(table->s->key_block_size, buff, 10); - packet->append(buff, (uint) (end - buff)); - } - table->file->append_create_info(packet); - if (share->comment.length) - { - packet->append(STRING_WITH_LEN(" COMMENT=")); - append_unescaped(packet, share->comment.str, share->comment.length); - } - if (share->connect_string.length) - { - packet->append(STRING_WITH_LEN(" CONNECTION=")); - append_unescaped(packet, share->connect_string.str, share->connect_string.length); - } - append_create_options(thd, packet, share->option_list, check_options, - hton->table_options); - append_directory(thd, packet, "DATA", create_info.data_file_name); - append_directory(thd, packet, "INDEX", create_info.index_file_name); - } #ifdef WITH_PARTITION_STORAGE_ENGINE { if (table->part_info && @@ -2425,11 +2558,11 @@ void view_store_options(THD *thd, TABLE_LIST *table, String *buff) Returns ALGORITHM clause of a view */ -static const LEX_STRING *view_algorithm(TABLE_LIST *table) +static const LEX_CSTRING *view_algorithm(TABLE_LIST *table) { - static const LEX_STRING undefined= { C_STRING_WITH_LEN("UNDEFINED") }; - static const LEX_STRING merge= { C_STRING_WITH_LEN("MERGE") }; - static const LEX_STRING temptable= { C_STRING_WITH_LEN("TEMPTABLE") }; + static const LEX_CSTRING undefined= { STRING_WITH_LEN("UNDEFINED") }; + static const LEX_CSTRING merge= { STRING_WITH_LEN("MERGE") }; + static const LEX_CSTRING temptable= { STRING_WITH_LEN("TEMPTABLE") }; switch (table->algorithm) { case VIEW_ALGORITHM_TMPTABLE: return &temptable; @@ -2437,11 +2570,23 @@ static const LEX_STRING *view_algorithm(TABLE_LIST *table) return &merge; default: DBUG_ASSERT(0); // never should happen + /* fall through */ case VIEW_ALGORITHM_UNDEFINED: return &undefined; } } + +static bool append_at_host(THD *thd, String *buffer, const LEX_CSTRING *host) +{ + if (!host->str || !host->str[0]) + return false; + return + buffer->append('@') || + append_identifier(thd, buffer, host); +} + + /* Append DEFINER clause to the given buffer. @@ -2453,17 +2598,14 @@ static const LEX_STRING *view_algorithm(TABLE_LIST *table) definer_host [in] host name part of definer */ -void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, - const LEX_STRING *definer_host) +bool append_definer(THD *thd, String *buffer, const LEX_CSTRING *definer_user, + const LEX_CSTRING *definer_host) { - buffer->append(STRING_WITH_LEN("DEFINER=")); - append_identifier(thd, buffer, definer_user->str, definer_user->length); - if (definer_host->str && definer_host->str[0]) - { - buffer->append('@'); - append_identifier(thd, buffer, definer_host->str, definer_host->length); - } - buffer->append(' '); + return + buffer->append(STRING_WITH_LEN("DEFINER=")) || + append_identifier(thd, buffer, definer_user) || + append_at_host(thd, buffer, definer_host) || + buffer->append(' '); } @@ -2477,7 +2619,7 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) MODE_MAXDB | MODE_ANSI)) != 0; - if (!thd->db || strcmp(thd->db, table->view_db.str)) + if (!thd->db.str || cmp(&thd->db, &table->view_db)) /* print compact view name if the view belongs to the current database */ @@ -2494,7 +2636,7 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) tbl; tbl= tbl->next_global) { - if (strcmp(table->view_db.str, tbl->view ? tbl->view_db.str :tbl->db)!= 0) + if (cmp(&table->view_db, tbl->view ? &tbl->view_db : &tbl->db)) { table->compact_view_format= FALSE; break; @@ -2510,10 +2652,10 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) buff->append(STRING_WITH_LEN("VIEW ")); if (!compact_view_name) { - append_identifier(thd, buff, table->view_db.str, table->view_db.length); + append_identifier(thd, buff, &table->view_db); buff->append('.'); } - append_identifier(thd, buff, table->view_name.str, table->view_name.length); + append_identifier(thd, buff, &table->view_name); buff->append(STRING_WITH_LEN(" AS ")); /* @@ -2534,6 +2676,55 @@ static int show_create_view(THD *thd, TABLE_LIST *table, String *buff) } +static int show_create_sequence(THD *thd, TABLE_LIST *table_list, + String *packet) +{ + TABLE *table= table_list->table; + SEQUENCE *seq= table->s->sequence; + LEX_CSTRING alias; + sql_mode_t sql_mode= thd->variables.sql_mode; + bool foreign_db_mode= sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | + MODE_MSSQL | MODE_DB2 | + MODE_MAXDB | MODE_ANSI); + bool show_table_options= !(sql_mode & MODE_NO_TABLE_OPTIONS) && + !foreign_db_mode; + + if (lower_case_table_names == 2) + { + alias.str= table->alias.c_ptr(); + alias.length= table->alias.length(); + } + else + alias= table->s->table_name; + + packet->append(STRING_WITH_LEN("CREATE SEQUENCE ")); + append_identifier(thd, packet, &alias); + packet->append(STRING_WITH_LEN(" start with ")); + packet->append_longlong(seq->start); + packet->append(STRING_WITH_LEN(" minvalue ")); + packet->append_longlong(seq->min_value); + packet->append(STRING_WITH_LEN(" maxvalue ")); + packet->append_longlong(seq->max_value); + packet->append(STRING_WITH_LEN(" increment by ")); + packet->append_longlong(seq->increment); + if (seq->cache) + { + packet->append(STRING_WITH_LEN(" cache ")); + packet->append_longlong(seq->cache); + } + else + packet->append(STRING_WITH_LEN(" nocache")); + if (seq->cycle) + packet->append(STRING_WITH_LEN(" cycle")); + else + packet->append(STRING_WITH_LEN(" nocycle")); + + if (show_table_options) + add_table_options(thd, table, 0, 0, 1, packet); + return 0; +} + + /**************************************************************************** Return info about all processes returns for each thread: thread id, user, host, db, command, info @@ -2546,6 +2737,7 @@ public: static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) { TRASH_FREE(ptr, size); } + static void operator delete(void *, MEM_ROOT *){} my_thread_id thread_id; uint32 os_thread_id; @@ -2563,23 +2755,31 @@ static const char *thread_state_info(THD *tmp) { if (tmp->net.reading_or_writing == 2) return "Writing to net"; - else if (tmp->get_command() == COM_SLEEP) + if (tmp->get_command() == COM_SLEEP) return ""; - else - return "Reading from net"; + return "Reading from net"; } #else if (tmp->get_command() == COM_SLEEP) return ""; #endif + if (tmp->proc_info) return tmp->proc_info; - else if (tmp->mysys_var && tmp->mysys_var->current_cond) - return "Waiting on cond"; - else - return NULL; + + /* Check if we are waiting on a condition */ + if (!trylock_short(&tmp->LOCK_thd_kill)) + { + /* mysys_var is protected by above mutex */ + bool cond= tmp->mysys_var && tmp->mysys_var->current_cond; + mysql_mutex_unlock(&tmp->LOCK_thd_kill); + if (cond) + return "Waiting on cond"; + } + return NULL; } + void mysqld_list_processes(THD *thd,const char *user, bool verbose) { Item *field; @@ -2642,7 +2842,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) while ((tmp=it++)) { Security_context *tmp_sctx= tmp->security_ctx; - struct st_my_thread_var *mysys_var; + bool got_thd_data; if ((tmp->vio_ok() || tmp->system_thread) && (!user || (!tmp->system_thread && tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) @@ -2666,48 +2866,61 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) tmp_sctx->host_or_ip : tmp_sctx->host ? tmp_sctx->host : ""); thd_info->command=(int) tmp->get_command(); - mysql_mutex_lock(&tmp->LOCK_thd_data); - if ((thd_info->db= tmp->db)) // Safe test - thd_info->db= thd->strdup(thd_info->db); - if ((mysys_var= tmp->mysys_var)) - mysql_mutex_lock(&mysys_var->mutex); - thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ? - "Killed" : 0); - thd_info->state_info= thread_state_info(tmp); - if (mysys_var) - mysql_mutex_unlock(&mysys_var->mutex); - /* Lock THD mutex that protects its data when looking at it. */ - if (tmp->query()) + if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) { - uint length= MY_MIN(max_query_length, tmp->query_length()); - char *q= thd->strmake(tmp->query(),length); - /* Safety: in case strmake failed, we set length to 0. */ - thd_info->query_string= - CSET_STRING(q, q ? length : 0, tmp->query_charset()); - } + /* This is an approximation */ + thd_info->proc_info= (char*) (tmp->killed >= KILL_QUERY ? + "Killed" : 0); + /* + The following variables are only safe to access under a lock + */ - /* - Progress report. We need to do this under a lock to ensure that all - is from the same stage. - */ - if (tmp->progress.max_counter) - { - uint max_stage= MY_MAX(tmp->progress.max_stage, 1); - thd_info->progress= (((tmp->progress.stage / (double) max_stage) + - ((tmp->progress.counter / - (double) tmp->progress.max_counter) / - (double) max_stage)) * - 100.0); - set_if_smaller(thd_info->progress, 100); + thd_info->db= 0; + if (tmp->db.str) + thd_info->db= thd->strmake(tmp->db.str, tmp->db.length); + + if (tmp->query()) + { + uint length= MY_MIN(max_query_length, tmp->query_length()); + char *q= thd->strmake(tmp->query(),length); + /* Safety: in case strmake failed, we set length to 0. */ + thd_info->query_string= + CSET_STRING(q, q ? length : 0, tmp->query_charset()); + } + + /* + Progress report. We need to do this under a lock to ensure that all + is from the same stage. + */ + if (tmp->progress.max_counter) + { + uint max_stage= MY_MAX(tmp->progress.max_stage, 1); + thd_info->progress= (((tmp->progress.stage / (double) max_stage) + + ((tmp->progress.counter / + (double) tmp->progress.max_counter) / + (double) max_stage)) * + 100.0); + set_if_smaller(thd_info->progress, 100); + } + else + thd_info->progress= 0.0; } else + { + thd_info->proc_info= "Busy"; thd_info->progress= 0.0; + thd_info->db= ""; + } + + thd_info->state_info= thread_state_info(tmp); thd_info->start_time= tmp->start_utime; ulonglong utime_after_query_snapshot= tmp->utime_after_query; if (thd_info->start_time < utime_after_query_snapshot) thd_info->start_time= utime_after_query_snapshot; // COM_SLEEP - mysql_mutex_unlock(&tmp->LOCK_thd_data); + + if (got_thd_data) + mysql_mutex_unlock(&tmp->LOCK_thd_data); thread_infos.append(thd_info); } } @@ -2842,8 +3055,9 @@ int select_result_text_buffer::append_row(List<Item> &items, bool send_names) if (send_names) { - data_ptr= item->name; - data_len= strlen(item->name); + DBUG_ASSERT(strlen(item->name.str) == item->name.length); + data_ptr= item->name.str; + data_len= item->name.length; } else { @@ -2921,13 +3135,13 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) tmp_sctx->user))) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "PROCESS"); - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); DBUG_RETURN(1); } if (tmp == thd) { - mysql_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_kill); my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0)); DBUG_RETURN(1); } @@ -2935,7 +3149,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) bool bres; /* Ok we've found the thread of interest and it won't go away because - we're holding its LOCK_thd data. Post it a SHOW EXPLAIN request. + we're holding its LOCK_thd_kill. Post it a SHOW EXPLAIN request. */ bool timed_out; int timeout_sec= 30; @@ -2949,7 +3163,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) explain_req.request_thd= thd; explain_req.failed_to_produce= FALSE; - /* Ok, we have a lock on target->LOCK_thd_data, can call: */ + /* Ok, we have a lock on target->LOCK_thd_kill, can call: */ bres= tmp->apc_target.make_apc_call(thd, &explain_req, timeout_sec, &timed_out); if (bres || explain_req.failed_to_produce) @@ -3028,9 +3242,9 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) while ((tmp= it++)) { Security_context *tmp_sctx= tmp->security_ctx; - struct st_my_thread_var *mysys_var; - const char *val, *db; + const char *val; ulonglong max_counter; + bool got_thd_data; if ((!tmp->vio_ok() && !tmp->system_thread) || (user && (tmp->system_thread || !tmp_sctx->user || @@ -3056,23 +3270,26 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) else table->field[2]->store(tmp_sctx->host_or_ip, strlen(tmp_sctx->host_or_ip), cs); - /* DB */ - mysql_mutex_lock(&tmp->LOCK_thd_data); - if ((db= tmp->db)) + + if ((got_thd_data= !trylock_short(&tmp->LOCK_thd_data))) { - table->field[3]->store(db, strlen(db), cs); - table->field[3]->set_notnull(); + /* DB */ + if (tmp->db.str) + { + table->field[3]->store(tmp->db.str, tmp->db.length, cs); + table->field[3]->set_notnull(); + } } - if ((mysys_var= tmp->mysys_var)) - mysql_mutex_lock(&mysys_var->mutex); /* COMMAND */ - if ((val= (char *) ((tmp->killed >= KILL_QUERY ? + if ((val= (char *) (!got_thd_data ? "Busy" : + (tmp->killed >= KILL_QUERY ? "Killed" : 0)))) table->field[4]->store(val, strlen(val), cs); else table->field[4]->store(command_name[tmp->get_command()].str, command_name[tmp->get_command()].length, cs); + /* MYSQL_TIME */ ulonglong utime= tmp->start_utime; ulonglong utime_after_query_snapshot= tmp->utime_after_query; @@ -3081,6 +3298,38 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) utime= utime && utime < unow ? unow - utime : 0; table->field[5]->store(utime / HRTIME_RESOLUTION, TRUE); + + if (got_thd_data) + { + if (tmp->query()) + { + table->field[7]->store(tmp->query(), + MY_MIN(PROCESS_LIST_INFO_WIDTH, + tmp->query_length()), cs); + table->field[7]->set_notnull(); + + /* INFO_BINARY */ + table->field[16]->store(tmp->query(), + MY_MIN(PROCESS_LIST_INFO_WIDTH, + tmp->query_length()), + &my_charset_bin); + table->field[16]->set_notnull(); + } + + /* + Progress report. We need to do this under a lock to ensure that all + is from the same stage. + */ + if ((max_counter= tmp->progress.max_counter)) + { + table->field[9]->store((longlong) tmp->progress.stage + 1, 1); + table->field[10]->store((longlong) tmp->progress.max_stage, 1); + table->field[11]->store((double) tmp->progress.counter / + (double) max_counter*100.0); + } + mysql_mutex_unlock(&tmp->LOCK_thd_data); + } + /* STATE */ if ((val= thread_state_info(tmp))) { @@ -3088,46 +3337,9 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[6]->set_notnull(); } - if (mysys_var) - mysql_mutex_unlock(&mysys_var->mutex); - mysql_mutex_unlock(&tmp->LOCK_thd_data); - /* TIME_MS */ table->field[8]->store((double)(utime / (HRTIME_RESOLUTION / 1000.0))); - /* INFO */ - /* Lock THD mutex that protects its data when looking at it. */ - mysql_mutex_lock(&tmp->LOCK_thd_data); - if (tmp->query()) - { - table->field[7]->store(tmp->query(), - MY_MIN(PROCESS_LIST_INFO_WIDTH, - tmp->query_length()), cs); - table->field[7]->set_notnull(); - } - - /* INFO_BINARY */ - if (tmp->query()) - { - table->field[15]->store(tmp->query(), - MY_MIN(PROCESS_LIST_INFO_WIDTH, - tmp->query_length()), &my_charset_bin); - table->field[15]->set_notnull(); - } - - /* - Progress report. We need to do this under a lock to ensure that all - is from the same stage. - */ - if ((max_counter= tmp->progress.max_counter)) - { - table->field[9]->store((longlong) tmp->progress.stage + 1, 1); - table->field[10]->store((longlong) tmp->progress.max_stage, 1); - table->field[11]->store((double) tmp->progress.counter / - (double) max_counter*100.0); - } - mysql_mutex_unlock(&tmp->LOCK_thd_data); - /* This may become negative if we free a memory allocated by another thread in this thread. However it's better that we notice it eventually @@ -3135,14 +3347,14 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) */ table->field[12]->store((longlong) tmp->status_var.local_memory_used, FALSE); - table->field[12]->set_notnull(); - table->field[13]->store((longlong) tmp->get_examined_row_count(), TRUE); - table->field[13]->set_notnull(); + table->field[13]->store((longlong) tmp->status_var.max_local_memory_used, + FALSE); + table->field[14]->store((longlong) tmp->get_examined_row_count(), TRUE); /* QUERY_ID */ - table->field[14]->store(tmp->query_id, TRUE); + table->field[15]->store(tmp->query_id, TRUE); - table->field[16]->store(tmp->os_thread_id); + table->field[17]->store(tmp->os_thread_id); if (schema_table_store_record(thd, table)) { @@ -3365,7 +3577,7 @@ const char* get_one_variable(THD *thd, { sys_var *var= (sys_var *) value; show_type= var->show_type(); - value= var->value_ptr(thd, value_type, &null_lex_str); + value= var->value_ptr(thd, value_type, &null_clex_str); *charset= var->charset(thd); } @@ -3403,6 +3615,9 @@ const char* get_one_variable(THD *thd, case SHOW_MY_BOOL: end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); break; + case SHOW_UINT32_STATUS: + value= ((char *) status_var + (intptr) value); + /* fall through */ case SHOW_UINT: end= int10_to_str((long) *(uint*) value, buff, 10); break; @@ -3629,6 +3844,8 @@ uint calc_sum_of_all_status(STATUS_VAR *to) add_to_status(to, &tmp->status_var); to->local_memory_used+= tmp->status_var.local_memory_used; } + if (tmp->get_command() != COM_SLEEP) + to->threads_running++; } mysql_mutex_unlock(&LOCK_thread_count); @@ -3657,17 +3874,19 @@ bool schema_table_store_record(THD *thd, TABLE *table) { int error; - if (thd->killed) + if (unlikely(thd->killed)) { thd->send_kill_message(); return 1; } - if ((error= table->file->ha_write_tmp_row(table->record[0]))) + if (unlikely((error= table->file->ha_write_tmp_row(table->record[0])))) { TMP_TABLE_PARAM *param= table->pos_in_table_list->schema_table_param; - if (create_internal_tmp_table_from_heap(thd, table, param->start_recinfo, - ¶m->recinfo, error, 0, NULL)) + if (unlikely(create_internal_tmp_table_from_heap(thd, table, + param->start_recinfo, + ¶m->recinfo, error, 0, + NULL))) return 1; } @@ -3676,10 +3895,10 @@ bool schema_table_store_record(THD *thd, TABLE *table) static int make_table_list(THD *thd, SELECT_LEX *sel, - LEX_STRING *db_name, LEX_STRING *table_name) + LEX_CSTRING *db_name, LEX_CSTRING *table_name) { Table_ident *table_ident; - table_ident= new Table_ident(thd, *db_name, *table_name, 1); + table_ident= new Table_ident(thd, db_name, table_name, 1); if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, MDL_SHARED_READ)) return 1; return 0; @@ -3750,8 +3969,8 @@ bool get_lookup_value(THD *thd, Item_func *item_func, /* Lookup value is database name */ if (!cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1), - (uchar *) item_field->field_name, - strlen(item_field->field_name))) + (uchar *) item_field->field_name.str, + item_field->field_name.length)) { thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(), tmp_str->length()); @@ -3759,8 +3978,8 @@ bool get_lookup_value(THD *thd, Item_func *item_func, /* Lookup value is table name */ else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), - (uchar *) item_field->field_name, - strlen(item_field->field_name))) + (uchar *) item_field->field_name.str, + item_field->field_name.length)) { thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(), tmp_str->length()); @@ -3854,11 +4073,11 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) field_info[schema_table->idx_field2].field_name : ""; if (table->table != item_field->field->table || (cs->coll->strnncollsp(cs, (uchar *) field_name1, strlen(field_name1), - (uchar *) item_field->field_name, - strlen(item_field->field_name)) && + (uchar *) item_field->field_name.str, + item_field->field_name.length) && cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), - (uchar *) item_field->field_name, - strlen(item_field->field_name)))) + (uchar *) item_field->field_name.str, + item_field->field_name.length))) return 0; } else if (item->type() == Item::EXPR_CACHE_ITEM) @@ -3981,7 +4200,7 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, case SQLCOM_SHOW_TRIGGERS: case SQLCOM_SHOW_EVENTS: thd->make_lex_string(&lookup_field_values->db_value, - lex->select_lex.db, strlen(lex->select_lex.db)); + lex->select_lex.db.str, lex->select_lex.db.length); if (wild) { thd->make_lex_string(&lookup_field_values->table_value, @@ -4005,10 +4224,12 @@ bool get_lookup_field_values(THD *thd, COND *cond, TABLE_LIST *tables, are allocating a new memory buffer for these strings. */ if (lookup_field_values->db_value.str && lookup_field_values->db_value.str[0]) - my_casedn_str(system_charset_info, lookup_field_values->db_value.str); + my_casedn_str(system_charset_info, + (char*) lookup_field_values->db_value.str); if (lookup_field_values->table_value.str && lookup_field_values->table_value.str[0]) - my_casedn_str(system_charset_info, lookup_field_values->table_value.str); + my_casedn_str(system_charset_info, + (char*) lookup_field_values->table_value.str); } return rc; @@ -4037,8 +4258,8 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table) non-zero error */ -int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files, - LOOKUP_FIELD_VALUES *lookup_field_vals) +static int make_db_list(THD *thd, Dynamic_array<LEX_CSTRING*> *files, + LOOKUP_FIELD_VALUES *lookup_field_vals) { if (lookup_field_vals->wild_db_value) { @@ -4077,8 +4298,7 @@ int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files, return 0; } - if (is_infoschema_db(lookup_field_vals->db_value.str, - lookup_field_vals->db_value.length)) + if (is_infoschema_db(&lookup_field_vals->db_value)) { if (files->append_val(&INFORMATION_SCHEMA_NAME)) return 1; @@ -4095,13 +4315,13 @@ int make_db_list(THD *thd, Dynamic_array<LEX_STRING*> *files, */ if (files->append_val(&INFORMATION_SCHEMA_NAME)) return 1; - return find_files(thd, files, 0, mysql_data_home, &null_lex_str); + return find_files(thd, files, 0, mysql_data_home, &null_clex_str); } struct st_add_schema_table { - Dynamic_array<LEX_STRING*> *files; + Dynamic_array<LEX_CSTRING*> *files; const char *wild; }; @@ -4109,9 +4329,9 @@ struct st_add_schema_table static my_bool add_schema_table(THD *thd, plugin_ref plugin, void* p_data) { - LEX_STRING *file_name= 0; + LEX_CSTRING *file_name= 0; st_add_schema_table *data= (st_add_schema_table *)p_data; - Dynamic_array<LEX_STRING*> *file_list= data->files; + Dynamic_array<LEX_CSTRING*> *file_list= data->files; const char *wild= data->wild; ST_SCHEMA_TABLE *schema_table= plugin_data(plugin, ST_SCHEMA_TABLE *); DBUG_ENTER("add_schema_table"); @@ -4131,18 +4351,18 @@ static my_bool add_schema_table(THD *thd, plugin_ref plugin, DBUG_RETURN(0); } - if ((file_name= thd->make_lex_string(schema_table->table_name, - strlen(schema_table->table_name))) && + if ((file_name= thd->make_clex_string(schema_table->table_name, + strlen(schema_table->table_name))) && !file_list->append(file_name)) DBUG_RETURN(0); DBUG_RETURN(1); } -int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files, +int schema_tables_add(THD *thd, Dynamic_array<LEX_CSTRING*> *files, const char *wild) { - LEX_STRING *file_name= 0; + LEX_CSTRING *file_name; ST_SCHEMA_TABLE *tmp_schema_table= schema_tables; st_add_schema_table add_data; DBUG_ENTER("schema_tables_add"); @@ -4164,8 +4384,8 @@ int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files, continue; } if ((file_name= - thd->make_lex_string(tmp_schema_table->table_name, - strlen(tmp_schema_table->table_name))) && + thd->make_clex_string(tmp_schema_table->table_name, + strlen(tmp_schema_table->table_name))) && !files->append(file_name)) continue; DBUG_RETURN(1); @@ -4200,9 +4420,9 @@ int schema_tables_add(THD *thd, Dynamic_array<LEX_STRING*> *files, */ static int -make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names, +make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names, LEX *lex, LOOKUP_FIELD_VALUES *lookup_field_vals, - LEX_STRING *db_name) + LEX_CSTRING *db_name) { char path[FN_REFLEN + 1]; build_table_filename(path, sizeof(path) - 1, db_name->str, "", "", 0); @@ -4219,13 +4439,13 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names, } if (db_name == &INFORMATION_SCHEMA_NAME) { - LEX_STRING *name; + LEX_CSTRING *name; ST_SCHEMA_TABLE *schema_table= - find_schema_table(thd, lookup_field_vals->table_value.str); + find_schema_table(thd, &lookup_field_vals->table_value); if (schema_table && !schema_table->hidden) { - if (!(name= thd->make_lex_string(schema_table->table_name, - strlen(schema_table->table_name))) || + if (!(name= thd->make_clex_string(schema_table->table_name, + strlen(schema_table->table_name))) || table_names->append(name)) return 1; } @@ -4270,16 +4490,17 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_STRING*> *table_names, static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl, - LEX_STRING *db, LEX_STRING *table) + LEX_CSTRING *db, LEX_CSTRING *table) { - LEX_STRING engine_name= { buf, 0 }; + LEX_CSTRING engine_name= { buf, 0 }; if (thd->get_stmt_da()->sql_errno() == ER_UNKNOWN_STORAGE_ENGINE) { char path[FN_REFLEN]; build_table_filename(path, sizeof(path) - 1, db->str, table->str, reg_ext, 0); - if (dd_frm_type(thd, path, &engine_name) == FRMTYPE_TABLE) + bool is_sequence; + if (dd_frm_type(thd, path, &engine_name, &is_sequence) == TABLE_TYPE_NORMAL) tl->option= engine_name.str; } } @@ -4307,18 +4528,19 @@ static void get_table_engine_for_i_s(THD *thd, char *buf, TABLE_LIST *tl, @retval TRUE - Failure. */ static bool -fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, +fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root, + bool is_show_fields_or_keys, TABLE *table, ST_SCHEMA_TABLE *schema_table, - LEX_STRING *orig_db_name, - LEX_STRING *orig_table_name, + LEX_CSTRING *orig_db_name, + LEX_CSTRING *orig_table_name, Open_tables_backup *open_tables_state_backup, bool can_deadlock) { - Query_arena i_s_arena(thd->mem_root, + Query_arena i_s_arena(mem_root, Query_arena::STMT_CONVENTIONAL_EXECUTION), backup_arena, *old_arena; LEX *old_lex= thd->lex, temp_lex, *lex; - LEX_STRING db_name, table_name; + LEX_CSTRING db_name, table_name; TABLE_LIST *table_list; bool result= true; DBUG_ENTER("fill_schema_table_by_open"); @@ -4343,6 +4565,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, /* Prepare temporary LEX. */ thd->lex= lex= &temp_lex; lex_start(thd); + lex->sql_command= old_lex->sql_command; /* Disable constant subquery evaluation as we won't be locking tables. */ lex->context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW; @@ -4395,27 +4618,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, table_list->i_s_requested_object= schema_table->i_s_requested_object; } - /* - Let us set fake sql_command so views won't try to merge - themselves into main statement. If we don't do this, - SELECT * from information_schema.xxxx will cause problems. - SQLCOM_SHOW_FIELDS is used because it satisfies - 'only_view_structure()'. - */ - lex->sql_command= SQLCOM_SHOW_FIELDS; - result= (thd->open_temporary_tables(table_list) || - open_normal_and_derived_tables(thd, table_list, - (MYSQL_OPEN_IGNORE_FLUSH | - MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | - (can_deadlock ? - MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)), - DT_INIT | DT_PREPARE | DT_CREATE)); - - /* - Restore old value of sql_command back as it is being looked at in - process_table() function. - */ - lex->sql_command= old_lex->sql_command; + DBUG_ASSERT(thd->lex == lex); + result= open_tables_only_view_structure(thd, table_list, can_deadlock); DEBUG_SYNC(thd, "after_open_table_ignore_flush"); @@ -4432,7 +4636,8 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, */ if (!is_show_fields_or_keys && result && (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE || - thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT)) + thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT || + thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE)) { /* Hide error for a non-existing table. @@ -4446,7 +4651,7 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, else { char buf[NAME_CHAR_LEN + 1]; - if (thd->is_error()) + if (unlikely(thd->is_error())) get_table_engine_for_i_s(thd, buf, table_list, &db_name, &table_name); result= schema_table->process_table(thd, table_list, @@ -4502,7 +4707,8 @@ end: */ static int fill_schema_table_names(THD *thd, TABLE_LIST *tables, - LEX_STRING *db_name, LEX_STRING *table_name) + LEX_CSTRING *db_name, + LEX_CSTRING *table_name) { TABLE *table= tables->table; if (db_name == &INFORMATION_SCHEMA_NAME) @@ -4514,23 +4720,27 @@ static int fill_schema_table_names(THD *thd, TABLE_LIST *tables, { CHARSET_INFO *cs= system_charset_info; handlerton *hton; - if (ha_table_exists(thd, db_name->str, table_name->str, &hton)) + bool is_sequence; + if (ha_table_exists(thd, db_name, table_name, &hton, &is_sequence)) { if (hton == view_pseudo_hton) table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); + else if (is_sequence) + table->field[3]->store(STRING_WITH_LEN("SEQUENCE"), cs); else table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); } else table->field[3]->store(STRING_WITH_LEN("ERROR"), cs); - if (thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE) + if (unlikely(thd->is_error() && + thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE)) { thd->clear_error(); return 0; } } - if (schema_table_store_record(thd, table)) + if (unlikely(schema_table_store_record(thd, table))) return 1; return 0; } @@ -4614,7 +4824,7 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table, bool can_deadlock) { bool error; - table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name, + table->mdl_request.init(MDL_key::TABLE, table->db.str, table->table_name.str, MDL_SHARED_HIGH_PRIO, MDL_TRANSACTION); if (can_deadlock) @@ -4667,8 +4877,8 @@ try_acquire_high_prio_shared_mdl_lock(THD *thd, TABLE_LIST *table, static int fill_schema_table_from_frm(THD *thd, TABLE *table, ST_SCHEMA_TABLE *schema_table, - LEX_STRING *db_name, - LEX_STRING *table_name, + LEX_CSTRING *db_name, + LEX_CSTRING *table_name, Open_tables_backup *open_tables_state_backup, bool can_deadlock) { @@ -4693,15 +4903,15 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, */ strmov(db_name_buff, db_name->str); strmov(table_name_buff, table_name->str); - my_casedn_str(files_charset_info, db_name_buff); - my_casedn_str(files_charset_info, table_name_buff); - table_list.db= db_name_buff; - table_list.table_name= table_name_buff; + table_list.db.length= my_casedn_str(files_charset_info, db_name_buff); + table_list.table_name.length= my_casedn_str(files_charset_info, table_name_buff); + table_list.db.str= db_name_buff; + table_list.table_name.str= table_name_buff; } else { - table_list.table_name= table_name->str; - table_list.db= db_name->str; + table_list.table_name= *table_name; + table_list.db= *db_name; } /* @@ -4731,15 +4941,16 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_I_S_SKIPPED_TABLE, ER_THD(thd, ER_WARN_I_S_SKIPPED_TABLE), - table_list.db, table_list.table_name); + table_list.db.str, table_list.table_name.str); return 0; } if (schema_table->i_s_requested_object & OPEN_TRIGGER_ONLY) { - init_sql_alloc(&tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); - if (!Table_triggers_list::check_n_load(thd, db_name->str, - table_name->str, &tbl, 1)) + init_sql_alloc(&tbl.mem_root, "fill_schema_table_from_frm", + TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); + if (!Table_triggers_list::check_n_load(thd, db_name, + table_name, &tbl, 1)) { table_list.table= &tbl; res= schema_table->process_table(thd, &table_list, table, @@ -4754,7 +4965,8 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, if (!share) { if (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE || - thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT) + thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT || + thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE) { res= 0; } @@ -4795,7 +5007,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, goto end_share; } - if (!open_table_from_share(thd, share, table_name->str, 0, + if (!open_table_from_share(thd, share, table_name, 0, (EXTRA_RECORD | OPEN_FRM_FILE_ONLY), thd->open_options, &tbl, FALSE)) { @@ -4852,13 +5064,12 @@ public: if (*level != Sql_condition::WARN_LEVEL_ERROR) return false; - if (!thd->get_stmt_da()->is_error()) + if (likely(!thd->get_stmt_da()->is_error())) thd->get_stmt_da()->set_error_status(sql_errno, msg, sqlstate, *cond_hdl); return true; // handled! } }; - /** @brief Fill I_S tables whose data are retrieved from frm files and storage engine @@ -4891,7 +5102,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ST_SCHEMA_TABLE *schema_table= tables->schema_table; IS_table_read_plan *plan= tables->is_table_read_plan; enum enum_schema_tables schema_table_idx; - Dynamic_array<LEX_STRING*> db_names; + Dynamic_array<LEX_CSTRING*> db_names; Item *partial_cond= plan->partial_cond; int error= 1; Open_tables_backup open_tables_state_backup; @@ -4900,8 +5111,11 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) #endif uint table_open_method= tables->table_open_method; bool can_deadlock; + MEM_ROOT tmp_mem_root; DBUG_ENTER("get_all_tables"); + bzero(&tmp_mem_root, sizeof(tmp_mem_root)); + /* In cases when SELECT from I_S table being filled by this call is part of statement which also uses other tables or is being executed @@ -4929,17 +5143,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) */ if (lsel && lsel->table_list.first) { - LEX_STRING db_name, table_name; - - db_name.str= lsel->table_list.first->db; - db_name.length= lsel->table_list.first->db_length; - - table_name.str= lsel->table_list.first->table_name; - table_name.length= lsel->table_list.first->table_name_length; - - error= fill_schema_table_by_open(thd, TRUE, + error= fill_schema_table_by_open(thd, thd->mem_root, TRUE, table, schema_table, - &db_name, &table_name, + &lsel->table_list.first->db, + &lsel->table_list.first->table_name, &open_tables_state_backup, can_deadlock); goto err; @@ -4962,9 +5169,14 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) if (make_db_list(thd, &db_names, &plan->lookup_field_vals)) goto err; + + /* Use tmp_mem_root to allocate data for opened tables */ + init_alloc_root(&tmp_mem_root, "get_all_tables", SHOW_ALLOC_BLOCK_SIZE, + SHOW_ALLOC_BLOCK_SIZE, MY_THREAD_SPECIFIC); + for (size_t i=0; i < db_names.elements(); i++) { - LEX_STRING *db_name= db_names.at(i); + LEX_CSTRING *db_name= db_names.at(i); DBUG_ASSERT(db_name->length <= NAME_LEN); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!(check_access(thd, SELECT_ACL, db_name->str, @@ -4974,26 +5186,24 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0)) #endif { - Dynamic_array<LEX_STRING*> table_names; + Dynamic_array<LEX_CSTRING*> table_names; int res= make_table_name_list(thd, &table_names, lex, &plan->lookup_field_vals, db_name); - if (res == 2) /* Not fatal error, continue */ + if (unlikely(res == 2)) /* Not fatal error, continue */ continue; - if (res) + if (unlikely(res)) goto err; for (size_t i=0; i < table_names.elements(); i++) { - LEX_STRING *table_name= table_names.at(i); + LEX_CSTRING *table_name= table_names.at(i); DBUG_ASSERT(table_name->length <= NAME_LEN); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!(thd->col_access & TABLE_ACLS)) { - table_acl_check.db= db_name->str; - table_acl_check.db_length= db_name->length; - table_acl_check.table_name= table_name->str; - table_acl_check.table_name_length= table_name->length; + table_acl_check.db= *db_name; + table_acl_check.table_name= *table_name; table_acl_check.grant.privilege= thd->col_access; if (check_grant(thd, TABLE_ACLS, &table_acl_check, TRUE, 1, TRUE)) continue; @@ -5047,12 +5257,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) } DEBUG_SYNC(thd, "before_open_in_get_all_tables"); - if (fill_schema_table_by_open(thd, FALSE, + if (fill_schema_table_by_open(thd, &tmp_mem_root, FALSE, table, schema_table, db_name, table_name, &open_tables_state_backup, can_deadlock)) goto err; + free_root(&tmp_mem_root, MY_MARK_BLOCKS_FREE); } } } @@ -5062,12 +5273,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) error= 0; err: thd->restore_backup_open_tables_state(&open_tables_state_backup); + free_root(&tmp_mem_root, 0); DBUG_RETURN(error); } -bool store_schema_shemata(THD* thd, TABLE *table, LEX_STRING *db_name, +bool store_schema_shemata(THD* thd, TABLE *table, LEX_CSTRING *db_name, CHARSET_INFO *cs) { restore_record(table, s->default_values); @@ -5087,7 +5299,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) */ LOOKUP_FIELD_VALUES lookup_field_vals; - Dynamic_array<LEX_STRING*> db_names; + Dynamic_array<LEX_CSTRING*> db_names; Schema_specification_st create; TABLE *table= tables->table; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -5123,7 +5335,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) for (size_t i=0; i < db_names.elements(); i++) { - LEX_STRING *db_name= db_names.at(i); + LEX_CSTRING *db_name= db_names.at(i); DBUG_ASSERT(db_name->length <= NAME_LEN); if (db_name == &INFORMATION_SCHEMA_NAME) { @@ -5152,8 +5364,8 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { const char *tmp_buff; MYSQL_TIME time; @@ -5195,7 +5407,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, String str(option_buff,sizeof(option_buff), system_charset_info); TABLE *show_table= tables->table; TABLE_SHARE *share= show_table->s; - handler *file= show_table->file; + handler *file= show_table->db_stat ? show_table->file : 0; handlerton *tmp_db_type= share->db_type(); #ifdef WITH_PARTITION_STORAGE_ENGINE bool is_partitioned= FALSE; @@ -5203,13 +5415,18 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, if (share->tmp_table == SYSTEM_TMP_TABLE) table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); + else if (share->table_type == TABLE_TYPE_SEQUENCE) + table->field[3]->store(STRING_WITH_LEN("SEQUENCE"), cs); else { DBUG_ASSERT(share->tmp_table == NO_TMP_TABLE); - table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); + if (share->versioned) + table->field[3]->store(STRING_WITH_LEN("SYSTEM VERSIONED"), cs); + else + table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); } - for (int i= 4; i < 20; i++) + for (uint i= 4; i < table->s->fields; i++) { if (i == 7 || (i > 12 && i < 17) || i == 18) continue; @@ -5314,7 +5531,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, if (file) { HA_CREATE_INFO create_info; - memset(&create_info, 0, sizeof(create_info)); + create_info.init(); file->update_create_info(&create_info); append_directory(thd, &str, "DATA", create_info.data_file_name); append_directory(thd, &str, "INDEX", create_info.index_file_name); @@ -5333,13 +5550,13 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, /* Collect table info from the storage engine */ - if(file) + if (file) { /* If info() fails, then there's nothing else to do */ - if ((info_error= file->info(HA_STATUS_VARIABLE | - HA_STATUS_TIME | - HA_STATUS_VARIABLE_EXTRA | - HA_STATUS_AUTO)) != 0) + if (unlikely((info_error= file->info(HA_STATUS_VARIABLE | + HA_STATUS_TIME | + HA_STATUS_VARIABLE_EXTRA | + HA_STATUS_AUTO)) != 0)) { file->print_error(info_error, MYF(0)); goto err; @@ -5387,8 +5604,15 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, { table->field[10]->store((longlong) file->stats.max_data_file_length, TRUE); + table->field[10]->set_notnull(); } table->field[11]->store((longlong) file->stats.index_file_length, TRUE); + if (file->stats.max_index_file_length) + { + table->field[21]->store((longlong) file->stats.max_index_file_length, + TRUE); + table->field[21]->set_notnull(); + } table->field[12]->store((longlong) file->stats.delete_length, TRUE); if (show_table->found_next_number_field) { @@ -5419,14 +5643,19 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } if (file->ha_table_flags() & (HA_HAS_OLD_CHECKSUM | HA_HAS_NEW_CHECKSUM)) { - table->field[18]->store((longlong) file->checksum(), TRUE); + table->field[18]->store((longlong) file->stats.checksum, TRUE); table->field[18]->set_notnull(); } } + /* If table is a temporary table */ + LEX_CSTRING tmp= { STRING_WITH_LEN("N") }; + if (show_table->s->tmp_table != NO_TMP_TABLE) + tmp.str= "Y"; + table->field[22]->store(tmp.str, tmp.length, cs); } err: - if (res || info_error) + if (unlikely(res || info_error)) { /* If an error was encountered, push a warning, set the TABLE COMMENT @@ -5460,8 +5689,6 @@ err: static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, uint offset) { - bool is_blob; - int decimals, field_length; const char *tmp_buff; char column_type_buff[MAX_FIELD_WIDTH]; String column_type(column_type_buff, sizeof(column_type_buff), cs); @@ -5487,22 +5714,18 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, (tmp_buff ? (uint)(tmp_buff - column_type.ptr()) : column_type.length()), cs); - is_blob= (field->type() == MYSQL_TYPE_BLOB); - if (field->has_charset() || is_blob || - field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type - field->real_type() == MYSQL_TYPE_STRING) // For binary type - { - uint32 octet_max_length= field->max_display_length(); - if (is_blob && octet_max_length != (uint32) 4294967295U) - octet_max_length /= field->charset()->mbmaxlen; - longlong char_max_len= is_blob ? - (longlong) octet_max_length / field->charset()->mbminlen : - (longlong) octet_max_length / field->charset()->mbmaxlen; + Information_schema_character_attributes cattr= + field->information_schema_character_attributes(); + if (cattr.has_char_length()) + { /* CHARACTER_MAXIMUM_LENGTH column*/ - table->field[offset + 1]->store(char_max_len, TRUE); + table->field[offset + 1]->store((longlong) cattr.char_length(), true); table->field[offset + 1]->set_notnull(); + } + if (cattr.has_octet_length()) + { /* CHARACTER_OCTET_LENGTH column */ - table->field[offset + 2]->store((longlong) octet_max_length, TRUE); + table->field[offset + 2]->store((longlong) cattr.octet_length(), true); table->field[offset + 2]->set_notnull(); } @@ -5511,35 +5734,10 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, They are set to -1 if they should not be set (we should return NULL) */ - field_length= -1; - decimals= field->decimals(); + Information_schema_numeric_attributes num= + field->information_schema_numeric_attributes(); + switch (field->type()) { - case MYSQL_TYPE_NEWDECIMAL: - field_length= ((Field_new_decimal*) field)->precision; - break; - case MYSQL_TYPE_DECIMAL: - field_length= field->field_length - (decimals ? 2 : 1); - break; - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_INT24: - field_length= field->max_display_length() - 1; - break; - case MYSQL_TYPE_LONGLONG: - field_length= field->max_display_length() - - ((field->flags & UNSIGNED_FLAG) ? 0 : 1); - break; - case MYSQL_TYPE_BIT: - field_length= field->max_display_length(); - decimals= -1; // return NULL - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - field_length= field->field_length; - if (decimals == NOT_FIXED_DEC) - decimals= -1; // return NULL - break; case MYSQL_TYPE_TIME: case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATETIME: @@ -5552,15 +5750,15 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, } /* NUMERIC_PRECISION column */ - if (field_length >= 0) + if (num.has_precision()) { - table->field[offset + 3]->store((longlong) field_length, TRUE); + table->field[offset + 3]->store((longlong) num.precision(), true); table->field[offset + 3]->set_notnull(); /* NUMERIC_SCALE column */ - if (decimals >= 0) + if (num.has_scale()) { - table->field[offset + 4]->store((longlong) decimals, TRUE); + table->field[offset + 4]->store((longlong) num.scale(), true); table->field[offset + 4]->set_notnull(); } } @@ -5578,10 +5776,122 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, } +/* + Print DATA_TYPE independently from sql_mode. + It's only a brief human-readable description, without attributes, + so it should not be used by client programs to generate SQL scripts. +*/ +static bool print_anchor_data_type(const Spvar_definition *def, + String *data_type) +{ + if (def->column_type_ref()) + return data_type->append(STRING_WITH_LEN("TYPE OF")); + if (def->is_table_rowtype_ref()) + return data_type->append(STRING_WITH_LEN("ROW TYPE OF")); + /* + "ROW TYPE OF cursor" is not possible yet. + May become possible when we add package-wide cursors. + */ + DBUG_ASSERT(0); + return false; +} + + +/* + DTD_IDENTIFIER is the full data type description with attributes. + It can be used by client programs to generate SQL scripts. + Let's print it according to the current sql_mode. + It will make output in line with the value in mysql.proc.param_list, + so both I_S.XXX.DTD_IDENTIFIER and mysql.proc.param_list use the same notation: + default or Oracle, according to the sql_mode at the SP creation time. + The caller must make sure to set thd->variables.sql_mode to the routine sql_mode. +*/ +static bool print_anchor_dtd_identifier(THD *thd, const Spvar_definition *def, + String *dtd_identifier) +{ + if (def->column_type_ref()) + return (thd->variables.sql_mode & MODE_ORACLE) ? + def->column_type_ref()->append_to(thd, dtd_identifier) || + dtd_identifier->append(STRING_WITH_LEN("%TYPE")) : + dtd_identifier->append(STRING_WITH_LEN("TYPE OF ")) || + def->column_type_ref()->append_to(thd, dtd_identifier); + if (def->is_table_rowtype_ref()) + return (thd->variables.sql_mode & MODE_ORACLE) ? + def->table_rowtype_ref()->append_to(thd, dtd_identifier) || + dtd_identifier->append(STRING_WITH_LEN("%ROWTYPE")) : + dtd_identifier->append(STRING_WITH_LEN("ROW TYPE OF ")) || + def->table_rowtype_ref()->append_to(thd, dtd_identifier); + DBUG_ASSERT(0); // See comments in print_anchor_data_type() + return false; +} + + +/* + Set columns DATA_TYPE and DTD_IDENTIFIER from an SP variable definition +*/ +static void store_variable_type(THD *thd, const sp_variable *spvar, + TABLE *tmptbl, + TABLE_SHARE *tmpshare, + CHARSET_INFO *cs, + TABLE *table, uint offset) +{ + if (spvar->field_def.is_explicit_data_type()) + { + if (spvar->field_def.is_row()) + { + // Explicit ROW + table->field[offset]->store(STRING_WITH_LEN("ROW"), cs); + table->field[offset]->set_notnull(); + // Perhaps eventually we need to print all ROW elements in DTD_IDENTIFIER + table->field[offset + 8]->store(STRING_WITH_LEN("ROW"), cs); + table->field[offset + 8]->set_notnull(); + } + else + { + // Explicit scalar data type + Field *field= spvar->field_def.make_field(tmpshare, thd->mem_root, + &spvar->name); + field->table= tmptbl; + tmptbl->in_use= thd; + store_column_type(table, field, cs, offset); + } + } + else + { + StringBuffer<128> data_type(cs), dtd_identifier(cs); + + if (print_anchor_data_type(&spvar->field_def, &data_type)) + { + table->field[offset]->store(STRING_WITH_LEN("ERROR"), cs); // EOM? + table->field[offset]->set_notnull(); + } + else + { + DBUG_ASSERT(data_type.length()); + table->field[offset]->store(data_type.ptr(), data_type.length(), cs); + table->field[offset]->set_notnull(); + } + + if (print_anchor_dtd_identifier(thd, &spvar->field_def, &dtd_identifier)) + { + table->field[offset + 8]->store(STRING_WITH_LEN("ERROR"), cs); // EOM? + table->field[offset + 8]->set_notnull(); + } + else + { + DBUG_ASSERT(dtd_identifier.length()); + table->field[offset + 8]->store(dtd_identifier.ptr(), + dtd_identifier.length(), cs); + table->field[offset + 8]->set_notnull(); + } + } +} + + static int get_schema_column_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { LEX *lex= thd->lex; const char *wild= lex->wild ? lex->wild->ptr() : NullS; @@ -5617,6 +5927,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, for (; (field= *ptr) ; ptr++) { + if(field->invisible > INVISIBLE_USER) + continue; uchar *pos; char tmp[MAX_FIELD_WIDTH]; String type(tmp,sizeof(tmp), system_charset_info); @@ -5624,7 +5936,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, DEBUG_SYNC(thd, "get_schema_column"); if (wild && wild[0] && - wild_case_compare(system_charset_info, field->field_name,wild)) + wild_case_compare(system_charset_info, field->field_name.str, wild)) continue; count++; @@ -5637,7 +5949,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, &tables->grant.privilege, 0, 0, MY_TEST(tables->schema_table)); col_access= get_column_grant(thd, &tables->grant, db_name->str, table_name->str, - field->field_name) & COL_ACLS; + field->field_name.str) & COL_ACLS; if (!tables->schema_table && !col_access) continue; char *end= tmp; @@ -5655,7 +5967,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, table->field[0]->store(STRING_WITH_LEN("def"), cs); table->field[1]->store(db_name->str, db_name->length, cs); table->field[2]->store(table_name->str, table_name->length, cs); - table->field[3]->store(field->field_name, strlen(field->field_name), + table->field[3]->store(field->field_name.str, field->field_name.length, cs); table->field[4]->store((longlong) count, TRUE); @@ -5674,11 +5986,11 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, table->field[16]->store((const char*) pos, strlen((const char*) pos), cs); + StringBuffer<256> buf; if (field->unireg_check == Field::NEXT_NUMBER) - table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs); + buf.set(STRING_WITH_LEN("auto_increment"),cs); if (print_on_update_clause(field, &type, true)) - table->field[17]->store(type.ptr(), type.length(), cs); - + buf.set(type.ptr(), type.length(),cs); if (field->vcol_info) { String gen_s(tmp,sizeof(tmp), system_charset_info); @@ -5689,13 +6001,41 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, table->field[20]->store(STRING_WITH_LEN("ALWAYS"), cs); if (field->vcol_info->stored_in_db) - table->field[17]->store(STRING_WITH_LEN("STORED GENERATED"), cs); + buf.set(STRING_WITH_LEN("STORED GENERATED"), cs); else - table->field[17]->store(STRING_WITH_LEN("VIRTUAL GENERATED"), cs); + buf.set(STRING_WITH_LEN("VIRTUAL GENERATED"), cs); + } + else if (field->flags & VERS_SYSTEM_FIELD) + { + if (field->flags & VERS_SYS_START_FLAG) + { + table->field[21]->store(STRING_WITH_LEN("ROW START"), cs); + buf.set(STRING_WITH_LEN("STORED GENERATED"), cs); + } + else + { + table->field[21]->store(STRING_WITH_LEN("ROW END"), cs); + buf.set(STRING_WITH_LEN("STORED GENERATED"), cs); + } + table->field[21]->set_notnull(); + table->field[20]->store(STRING_WITH_LEN("ALWAYS"), cs); } else table->field[20]->store(STRING_WITH_LEN("NEVER"), cs); - + /*Invisible can coexist with auto_increment and virtual */ + if (field->invisible == INVISIBLE_USER) + { + if (buf.length()) + buf.append(STRING_WITH_LEN(", ")); + buf.append(STRING_WITH_LEN("INVISIBLE"),cs); + } + if (field->vers_update_unversioned()) + { + if (buf.length()) + buf.append(STRING_WITH_LEN(", ")); + buf.append(STRING_WITH_LEN("WITHOUT SYSTEM VERSIONING"), cs); + } + table->field[17]->store(buf.ptr(), buf.length(), cs); table->field[19]->store(field->comment.str, field->comment.length, cs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -5758,7 +6098,7 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, { restore_record(table, s->default_values); table->field[0]->store(plug->name, strlen(plug->name), scs); - table->field[1]->store(C_STRING_WITH_LEN("NO"), scs); + table->field[1]->store(STRING_WITH_LEN("NO"), scs); table->field[2]->store(plug->descr, strlen(plug->descr), scs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -5768,13 +6108,13 @@ static my_bool iter_schema_engines(THD *thd, plugin_ref plugin, if (!(hton->flags & HTON_HIDDEN)) { - LEX_STRING *name= plugin_name(plugin); + LEX_CSTRING *name= plugin_name(plugin); if (!(wild && wild[0] && wild_case_compare(scs, name->str,wild))) { - LEX_STRING yesno[2]= {{ C_STRING_WITH_LEN("NO") }, - { C_STRING_WITH_LEN("YES") }}; - LEX_STRING *tmp; + LEX_CSTRING yesno[2]= {{ STRING_WITH_LEN("NO") }, + { STRING_WITH_LEN("YES") }}; + LEX_CSTRING *tmp; const char *option_name= show_comp_option_name[(int) hton->state]; restore_record(table, s->default_values); @@ -5926,67 +6266,64 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, TABLE_SHARE share; TABLE tbl; CHARSET_INFO *cs= system_charset_info; - char params_buff[MAX_FIELD_WIDTH], returns_buff[MAX_FIELD_WIDTH], - sp_db_buff[NAME_LEN], sp_name_buff[NAME_LEN], path[FN_REFLEN], - definer_buff[DEFINER_LENGTH + 1]; - String params(params_buff, sizeof(params_buff), cs); - String returns(returns_buff, sizeof(returns_buff), cs); - String sp_db(sp_db_buff, sizeof(sp_db_buff), cs); - String sp_name(sp_name_buff, sizeof(sp_name_buff), cs); - String definer(definer_buff, sizeof(definer_buff), cs); + LEX_CSTRING definer, params, returns= empty_clex_str; + LEX_CSTRING db, name; + char path[FN_REFLEN]; sp_head *sp; - stored_procedure_type routine_type; + const Sp_handler *sph; bool free_sp_head; bool error= 0; + sql_mode_t sql_mode; DBUG_ENTER("store_schema_params"); bzero((char*) &tbl, sizeof(TABLE)); (void) build_table_filename(path, sizeof(path), "", "", "", 0); init_tmp_table_share(thd, &share, "", 0, "", path); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DB], &sp_db); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_NAME], &sp_name); - get_field(thd->mem_root,proc_table->field[MYSQL_PROC_FIELD_DEFINER],&definer); - routine_type= (stored_procedure_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int(); + proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db); + proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name); + proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer); + sql_mode= (sql_mode_t) proc_table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); + sph= Sp_handler::handler_mysql_proc((stored_procedure_type) + proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> + val_int()); + if (!sph || sph->type() == TYPE_ENUM_PACKAGE || + sph->type() == TYPE_ENUM_PACKAGE_BODY) + DBUG_RETURN(0); if (!full_access) - full_access= !strcmp(sp_user, definer.ptr()); + full_access= !strcmp(sp_user, definer.str); if (!full_access && - check_some_routine_access(thd, sp_db.ptr(),sp_name.ptr(), - routine_type == TYPE_ENUM_PROCEDURE)) + check_some_routine_access(thd, db.str, name.str, sph)) DBUG_RETURN(0); - params.length(0); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST], - ¶ms); - returns.length(0); - if (routine_type == TYPE_ENUM_FUNCTION) - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_RETURNS], - &returns); - - sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name, - (ulong) proc_table-> - field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(), - routine_type, - returns.c_ptr_safe(), - params.c_ptr_safe(), - &free_sp_head); - + proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root, + ¶ms); + if (sph->type() == TYPE_ENUM_FUNCTION) + proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root, + &returns); + sp= sph->sp_load_for_information_schema(thd, proc_table, db, name, + params, returns, sql_mode, + &free_sp_head); if (sp) { Field *field; - String tmp_string; - if (routine_type == TYPE_ENUM_FUNCTION) + LEX_CSTRING tmp_string; + Sql_mode_save sql_mode_backup(thd); + thd->variables.sql_mode= sql_mode; + + if (sph->type() == TYPE_ENUM_FUNCTION) { restore_record(table, s->default_values); table->field[0]->store(STRING_WITH_LEN("def"), cs); - table->field[1]->store(sp_db.ptr(), sp_db.length(), cs); - table->field[2]->store(sp_name.ptr(), sp_name.length(), cs); + table->field[1]->store(db, cs); + table->field[2]->store(name, cs); table->field[3]->store((longlong) 0, TRUE); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE], - &tmp_string); - table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs); - field= sp->m_return_field_def.make_field(&share, thd->mem_root, ""); + proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_str_nopad(thd->mem_root, + &tmp_string); + table->field[15]->store(tmp_string, cs); + field= sp->m_return_field_def.make_field(&share, thd->mem_root, + &empty_clex_str); field->table= &tbl; tbl.in_use= thd; store_column_type(table, field, cs, 6); @@ -6022,22 +6359,18 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, restore_record(table, s->default_values); table->field[0]->store(STRING_WITH_LEN("def"), cs); - table->field[1]->store(sp_db.ptr(), sp_db.length(), cs); - table->field[2]->store(sp_name.ptr(), sp_name.length(), cs); + table->field[1]->store(db, cs); + table->field[2]->store(name, cs); table->field[3]->store((longlong) i + 1, TRUE); table->field[4]->store(tmp_buff, strlen(tmp_buff), cs); table->field[4]->set_notnull(); table->field[5]->store(spvar->name.str, spvar->name.length, cs); table->field[5]->set_notnull(); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE], - &tmp_string); - table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs); + proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_str_nopad(thd->mem_root, + &tmp_string); + table->field[15]->store(tmp_string, cs); - field= spvar->field_def.make_field(&share, thd->mem_root, - spvar->name.str); - field->table= &tbl; - tbl.in_use= thd; - store_column_type(table, field, cs, 6); + store_variable_type(thd, spvar, &tbl, &share, cs, table, 6); if (schema_table_store_record(thd, table)) { error= 1; @@ -6058,63 +6391,55 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, MYSQL_TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; - char sp_db_buff[SAFE_NAME_LEN + 1], sp_name_buff[NAME_LEN + 1], - definer_buff[DEFINER_LENGTH + 1], - returns_buff[MAX_FIELD_WIDTH]; - - String sp_db(sp_db_buff, sizeof(sp_db_buff), cs); - String sp_name(sp_name_buff, sizeof(sp_name_buff), cs); - String definer(definer_buff, sizeof(definer_buff), cs); - String returns(returns_buff, sizeof(returns_buff), cs); - - proc_table->field[MYSQL_PROC_FIELD_DB]->val_str(&sp_db); - proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str(&sp_name); - proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str(&definer); + const Sp_handler *sph; + LEX_CSTRING db, name, definer, returns= empty_clex_str; + + proc_table->field[MYSQL_PROC_FIELD_DB]->val_str_nopad(thd->mem_root, &db); + proc_table->field[MYSQL_PROC_FIELD_NAME]->val_str_nopad(thd->mem_root, &name); + proc_table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, &definer); + sph= Sp_handler::handler_mysql_proc((stored_procedure_type) + proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> + val_int()); + if (!sph) + return 0; if (!full_access) - full_access= !strcmp(sp_user, definer.c_ptr_safe()); + full_access= !strcmp(sp_user, definer.str); if (!full_access && - check_some_routine_access(thd, sp_db.c_ptr_safe(), sp_name.c_ptr_safe(), - proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> - val_int() == TYPE_ENUM_PROCEDURE)) + check_some_routine_access(thd, db.str, name.str, sph)) return 0; if (!is_show_command(thd) || - (lex->sql_command == SQLCOM_SHOW_STATUS_PROC && - proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == - TYPE_ENUM_PROCEDURE) || - (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC && - proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == - TYPE_ENUM_FUNCTION)) + sph == Sp_handler::handler(lex->sql_command)) { restore_record(table, s->default_values); if (!wild || !wild[0] || !wild_case_compare(system_charset_info, - sp_name.c_ptr_safe(), wild)) + name.str, wild)) { int enum_idx= (int) proc_table->field[MYSQL_PROC_FIELD_ACCESS]->val_int(); - table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); + table->field[3]->store(name, cs); copy_field_as_string(table->field[0], proc_table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]); table->field[1]->store(STRING_WITH_LEN("def"), cs); - table->field[2]->store(sp_db.ptr(), sp_db.length(), cs); + table->field[2]->store(db, cs); copy_field_as_string(table->field[4], proc_table->field[MYSQL_PROC_MYSQL_TYPE]); - if (proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == - TYPE_ENUM_FUNCTION) + if (sph->type() == TYPE_ENUM_FUNCTION) { sp_head *sp; bool free_sp_head; - proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str(&returns); - sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name, - (ulong) proc_table-> - field[MYSQL_PROC_FIELD_SQL_MODE]-> - val_int(), - TYPE_ENUM_FUNCTION, - returns.c_ptr_safe(), - "", &free_sp_head); - + proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root, + &returns); + sp= sph->sp_load_for_information_schema(thd, proc_table, + db, name, + empty_clex_str /*params*/, + returns, + (ulong) proc_table-> + field[MYSQL_PROC_FIELD_SQL_MODE]-> + val_int(), + &free_sp_head); if (sp) { char path[FN_REFLEN]; @@ -6125,7 +6450,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, bzero((char*) &tbl, sizeof(TABLE)); (void) build_table_filename(path, sizeof(path), "", "", "", 0); init_tmp_table_share(thd, &share, "", 0, "", path); - field= sp->m_return_field_def.make_field(&share, thd->mem_root, ""); + field= sp->m_return_field_def.make_field(&share, thd->mem_root, + &empty_clex_str); field->table= &tbl; tbl.in_use= thd; store_column_type(table, field, cs, 5); @@ -6163,7 +6489,7 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, copy_field_as_string(table->field[26], proc_table->field[MYSQL_PROC_FIELD_COMMENT]); - table->field[27]->store(definer.ptr(), definer.length(), cs); + table->field[27]->store(definer, cs); copy_field_as_string(table->field[28], proc_table-> field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]); @@ -6198,10 +6524,9 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) thd->security_ctx->priv_host, NullS); /* We use this TABLE_LIST instance only for checking of privileges. */ bzero((char*) &proc_tables,sizeof(proc_tables)); - proc_tables.db= (char*) "mysql"; - proc_tables.db_length= 5; - proc_tables.table_name= proc_tables.alias= (char*) "proc"; - proc_tables.table_name_length= 4; + proc_tables.db= MYSQL_SCHEMA_NAME; + proc_tables.table_name= MYSQL_PROC_NAME; + proc_tables.alias= MYSQL_PROC_NAME; proc_tables.lock_type= TL_READ; full_access= !check_table_access(thd, SELECT_ACL, &proc_tables, FALSE, 1, TRUE); @@ -6256,8 +6581,8 @@ err: static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; DBUG_ENTER("get_schema_stat_record"); @@ -6269,7 +6594,7 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS rather than in SHOW KEYS */ - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -6292,8 +6617,12 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, } for (uint i=0 ; i < show_table->s->keys ; i++,key_info++) { + if ((key_info->flags & HA_INVISIBLE_KEY) && + DBUG_EVALUATE_IF("test_invisible_index", 0, 1)) + continue; KEY_PART_INFO *key_part= key_info->key_part; - const char *str; + LEX_CSTRING *str; + LEX_CSTRING unknown= {STRING_WITH_LEN("?unknown field?") }; for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++) { restore_record(table, s->default_values); @@ -6303,11 +6632,11 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, table->field[3]->store((longlong) ((key_info->flags & HA_NOSAME) ? 0 : 1), TRUE); table->field[4]->store(db_name->str, db_name->length, cs); - table->field[5]->store(key_info->name, strlen(key_info->name), cs); + table->field[5]->store(key_info->name.str, key_info->name.length, cs); table->field[6]->store((longlong) (j+1), TRUE); - str=(key_part->field ? key_part->field->field_name : - "?unknown field?"); - table->field[7]->store(str, strlen(str), cs); + str= (key_part->field ? &key_part->field->field_name : + &unknown); + table->field[7]->store(str->str, str->length, cs); if (show_table->file) { if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER) @@ -6325,8 +6654,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, table->field[9]->store((longlong) records, TRUE); table->field[9]->set_notnull(); } - str= show_table->file->index_type(i); - table->field[13]->store(str, strlen(str), cs); + const char *tmp= show_table->file->index_type(i); + table->field[13]->store(tmp, strlen(tmp), cs); } if (!(key_info->flags & HA_FULLTEXT) && (key_part->field && @@ -6361,8 +6690,8 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables, static int get_schema_views_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; char definer[USER_HOST_BUFF_SIZE]; @@ -6494,7 +6823,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, if (schema_table_store_record(thd, table)) DBUG_RETURN(1); - if (res && thd->is_error()) + if (unlikely(res && thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -6505,9 +6834,10 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, } -bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name, - LEX_STRING *table_name, const char *key_name, - uint key_len, const char *con_type, uint con_len) +static bool +store_constraints(THD *thd, TABLE *table, const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name, const char *key_name, + size_t key_len, const char *con_type, size_t con_len) { CHARSET_INFO *cs= system_charset_info; restore_record(table, s->default_values); @@ -6522,8 +6852,8 @@ bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name, static int get_check_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { DBUG_ENTER("get_check_constraints_record"); if (res) @@ -6547,10 +6877,8 @@ static int get_check_constraints_record(THD *thd, TABLE_LIST *tables, #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!(thd->col_access & TABLE_ACLS)) { - table_acl_check.db= db_name->str; - table_acl_check.db_length= db_name->length; - table_acl_check.table_name= table_name->str; - table_acl_check.table_name_length= table_name->length; + table_acl_check.db= *db_name; + table_acl_check.table_name= *table_name; table_acl_check.grant.privilege= thd->col_access; if (check_grant(thd, TABLE_ACLS, &table_acl_check, FALSE, 1, TRUE)) continue; @@ -6573,13 +6901,13 @@ static int get_check_constraints_record(THD *thd, TABLE_LIST *tables, static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { DBUG_ENTER("get_schema_constraints_record"); if (res) { - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -6600,17 +6928,17 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, if (i != primary_key && !(key_info->flags & HA_NOSAME)) continue; - if (i == primary_key && !strcmp(key_info->name, primary_key_name)) + if (i == primary_key && !strcmp(key_info->name.str, primary_key_name)) { - if (store_constraints(thd, table, db_name, table_name, key_info->name, - strlen(key_info->name), + if (store_constraints(thd, table, db_name, table_name, + key_info->name.str, key_info->name.length, STRING_WITH_LEN("PRIMARY KEY"))) DBUG_RETURN(1); } else if (key_info->flags & HA_NOSAME) { - if (store_constraints(thd, table, db_name, table_name, key_info->name, - strlen(key_info->name), + if (store_constraints(thd, table, db_name, table_name, + key_info->name.str, key_info->name.length, STRING_WITH_LEN("UNIQUE"))) DBUG_RETURN(1); } @@ -6646,14 +6974,15 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, static bool store_trigger(THD *thd, Trigger *trigger, - TABLE *table, LEX_STRING *db_name, - LEX_STRING *table_name) + TABLE *table, const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; - LEX_STRING sql_mode_rep; + LEX_CSTRING sql_mode_rep; MYSQL_TIME timestamp; char definer_holder[USER_HOST_BUFF_SIZE]; - LEX_STRING definer_buffer, trigger_stmt, trigger_body; + LEX_STRING definer_buffer; + LEX_CSTRING trigger_stmt, trigger_body; definer_buffer.str= definer_holder; trigger->get_trigger_info(&trigger_stmt, &trigger_body, &definer_buffer); @@ -6702,8 +7031,8 @@ static bool store_trigger(THD *thd, Trigger *trigger, static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { DBUG_ENTER("get_schema_triggers_record"); /* @@ -6712,7 +7041,7 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables, */ if (res) { - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -6749,10 +7078,11 @@ ret: } -void store_key_column_usage(TABLE *table, LEX_STRING *db_name, - LEX_STRING *table_name, const char *key_name, - uint key_len, const char *con_type, uint con_len, - longlong idx) +static void +store_key_column_usage(TABLE *table, const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name, const char *key_name, + size_t key_len, const char *con_type, size_t con_len, + longlong idx) { CHARSET_INFO *cs= system_charset_info; table->field[0]->store(STRING_WITH_LEN("def"), cs); @@ -6769,13 +7099,13 @@ void store_key_column_usage(TABLE *table, LEX_STRING *db_name, static int get_schema_key_column_usage_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { DBUG_ENTER("get_schema_key_column_usage_record"); if (res) { - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -6804,10 +7134,9 @@ static int get_schema_key_column_usage_record(THD *thd, f_idx++; restore_record(table, s->default_values); store_key_column_usage(table, db_name, table_name, - key_info->name, - strlen(key_info->name), - key_part->field->field_name, - strlen(key_part->field->field_name), + key_info->name.str, key_info->name.length, + key_part->field->field_name.str, + key_part->field->field_name.length, (longlong) f_idx); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -6820,9 +7149,9 @@ static int get_schema_key_column_usage_record(THD *thd, List_iterator_fast<FOREIGN_KEY_INFO> fkey_it(f_key_list); while ((f_key_info= fkey_it++)) { - LEX_STRING *f_info; - LEX_STRING *r_info; - List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields), + LEX_CSTRING *f_info; + LEX_CSTRING *r_info; + List_iterator_fast<LEX_CSTRING> it(f_key_info->foreign_fields), it1(f_key_info->referenced_fields); uint f_idx= 0; while ((f_info= it++)) @@ -6858,10 +7187,10 @@ static int get_schema_key_column_usage_record(THD *thd, #ifdef WITH_PARTITION_STORAGE_ENGINE -static void collect_partition_expr(THD *thd, List<char> &field_list, +static void collect_partition_expr(THD *thd, List<const char> &field_list, String *str) { - List_iterator<char> part_it(field_list); + List_iterator<const char> part_it(field_list); ulong no_fields= field_list.elements; const char *field_str; str->length(0); @@ -6992,22 +7321,15 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table, strlen(part_elem->tablespace_name), cs); else { - char *ts= showing_table->s->tablespace; - if(ts) - table->field[24]->store(ts, strlen(ts), cs); - else - table->field[24]->set_null(); + table->field[24]->set_null(); } } return; } #ifdef WITH_PARTITION_STORAGE_ENGINE -static int -get_partition_column_description(THD *thd, - partition_info *part_info, - part_elem_value *list_value, - String &tmp_str) +static int get_partition_column_description(THD *thd, partition_info *part_info, + part_elem_value *list_value, String &tmp_str) { uint num_elements= part_info->part_field_list.elements; uint i; @@ -7050,8 +7372,8 @@ get_partition_column_description(THD *thd, static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, - LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; char buff[61]; @@ -7066,7 +7388,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, if (res) { - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -7111,6 +7433,9 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, tmp_res.append(STRING_WITH_LEN("HASH")); table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); break; + case VERSIONING_PARTITION: + table->field[7]->store(STRING_WITH_LEN("SYSTEM_TIME"), cs); + break; default: DBUG_ASSERT(0); my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); @@ -7177,13 +7502,9 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, List_iterator<part_elem_value> list_val_it(part_elem->list_val_list); part_elem_value *list_value= list_val_it++; tmp_str.length(0); - if (get_partition_column_description(thd, - part_info, - list_value, + if (get_partition_column_description(thd, part_info, list_value, tmp_str)) - { DBUG_RETURN(1); - } table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs); } else @@ -7204,7 +7525,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, tmp_res.length(0); if (part_elem->has_null_value) { - tmp_str.append("NULL"); + tmp_str.append(STRING_WITH_LEN("NULL")); if (num_items > 0) tmp_str.append(","); } @@ -7213,14 +7534,10 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, if (part_info->column_list) { if (part_info->part_field_list.elements > 1U) - tmp_str.append("("); - if (get_partition_column_description(thd, - part_info, - list_value, + tmp_str.append(STRING_WITH_LEN("(")); + if (get_partition_column_description(thd, part_info, list_value, tmp_str)) - { DBUG_RETURN(1); - } if (part_info->part_field_list.elements > 1U) tmp_str.append(")"); } @@ -7238,6 +7555,19 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs); table->field[11]->set_notnull(); } + else if (part_info->part_type == VERSIONING_PARTITION) + { + if (part_elem == part_info->vers_info->now_part) + { + table->field[11]->store(STRING_WITH_LEN("CURRENT"), cs); + table->field[11]->set_notnull(); + } + else if (part_info->vers_info->interval.is_set()) + { + table->field[11]->store_timestamp((my_time_t)part_elem->range_value, 0); + table->field[11]->set_notnull(); + } + } if (part_elem->subpartitions.elements) { @@ -7345,7 +7675,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) /* SQL_MODE */ { - LEX_STRING sql_mode; + LEX_CSTRING sql_mode; sql_mode_string_representation(thd, et.sql_mode, &sql_mode); sch_table->field[ISE_SQL_MODE]-> store(sql_mode.str, sql_mode.length, scs); @@ -7367,7 +7697,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) sch_table->field[ISE_INTERVAL_VALUE]-> store(show_str.ptr(), show_str.length(), scs); - LEX_STRING *ival= &interval_type_to_name[et.interval]; + LEX_CSTRING *ival= &interval_type_to_name[et.interval]; sch_table->field[ISE_INTERVAL_FIELD]->set_notnull(); sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs); @@ -7470,8 +7800,9 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; OPEN_TABLE_LIST *open_list; - if (!(open_list=list_open_tables(thd,thd->lex->select_lex.db, wild)) - && thd->is_fatal_error) + if (unlikely(!(open_list= list_open_tables(thd, thd->lex->select_lex.db.str, + wild))) && + unlikely(thd->is_fatal_error)) DBUG_RETURN(1); for (; open_list ; open_list=open_list->next) @@ -7481,7 +7812,7 @@ int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond) table->field[1]->store(open_list->table, strlen(open_list->table), cs); table->field[2]->store((longlong) open_list->in_use, TRUE); table->field[3]->store((longlong) open_list->locked, TRUE); - if (schema_table_store_record(thd, table)) + if (unlikely(schema_table_store_record(thd, table))) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -7601,7 +7932,8 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) static int get_referential_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, - LEX_STRING *db_name, LEX_STRING *table_name) + const LEX_CSTRING *db_name, + const LEX_CSTRING *table_name) { CHARSET_INFO *cs= system_charset_info; LEX_CSTRING *s; @@ -7609,7 +7941,7 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables, if (res) { - if (thd->is_error()) + if (unlikely(thd->is_error())) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, thd->get_stmt_da()->sql_errno(), thd->get_stmt_da()->message()); @@ -7689,7 +8021,8 @@ static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, if (!my_strcasecmp(system_charset_info, schema_table->table_name, - table_name)) { + table_name)) + { my_plugin_lock(thd, plugin); p_schema_table->schema_table= schema_table; DBUG_RETURN(1); @@ -7700,7 +8033,7 @@ static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, /* - Find schema_tables elment by name + Find schema_tables element by name SYNOPSIS find_schema_table() @@ -7712,7 +8045,7 @@ static my_bool find_schema_table_in_plugin(THD *thd, plugin_ref plugin, # pointer to 'schema_tables' element */ -ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name, +ST_SCHEMA_TABLE *find_schema_table(THD *thd, const LEX_CSTRING *table_name, bool *in_plugin) { schema_table_ref schema_table_a; @@ -7724,12 +8057,12 @@ ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name, { if (!my_strcasecmp(system_charset_info, schema_table->table_name, - table_name)) + table_name->str)) DBUG_RETURN(schema_table); } *in_plugin= true; - schema_table_a.table_name= table_name; + schema_table_a.table_name= table_name->str; if (plugin_foreach(thd, find_schema_table_in_plugin, MYSQL_INFORMATION_SCHEMA_PLUGIN, &schema_table_a)) DBUG_RETURN(schema_table_a.schema_table); @@ -7743,6 +8076,50 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) return &schema_tables[schema_table_idx]; } +static void +mark_all_fields_used_in_query(THD *thd, + ST_FIELD_INFO *schema_fields, + MY_BITMAP *bitmap, + Item *all_items) +{ + Item *item; + DBUG_ENTER("mark_all_fields_used_in_query"); + + /* If not SELECT command, return all columns */ + if (thd->lex->sql_command != SQLCOM_SELECT && + thd->lex->sql_command != SQLCOM_SET_OPTION) + { + bitmap_set_all(bitmap); + DBUG_VOID_RETURN; + } + + for (item= all_items ; item ; item= item->next) + { + if (item->type() == Item::FIELD_ITEM) + { + ST_FIELD_INFO *fields= schema_fields; + uint count; + Item_field *item_field= (Item_field*) item; + + /* item_field can be '*' as this function is called before fix_fields */ + if (item_field->field_name.str == star_clex_str.str) + { + bitmap_set_all(bitmap); + break; + } + for (count=0; fields->field_name; fields++, count++) + { + if (!my_strcasecmp(system_charset_info, fields->field_name, + item_field->field_name.str)) + { + bitmap_set_bit(bitmap, count); + break; + } + } + } + } + DBUG_VOID_RETURN; +} /** Create information_schema table using schema_table data. @@ -7767,18 +8144,36 @@ ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx) TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) { - int field_count= 0; - Item *item; + uint field_count; + Item *item, *all_items; TABLE *table; List<Item> field_list; ST_SCHEMA_TABLE *schema_table= table_list->schema_table; ST_FIELD_INFO *fields_info= schema_table->fields_info; + ST_FIELD_INFO *fields; CHARSET_INFO *cs= system_charset_info; MEM_ROOT *mem_root= thd->mem_root; + MY_BITMAP bitmap; + my_bitmap_map *buf; DBUG_ENTER("create_schema_table"); - for (; fields_info->field_name; fields_info++) + for (field_count= 0, fields= fields_info; fields->field_name; fields++) + field_count++; + if (!(buf= (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count)))) + DBUG_RETURN(NULL); + my_bitmap_init(&bitmap, buf, field_count, 0); + + if (!thd->stmt_arena->is_conventional() && + thd->mem_root != thd->stmt_arena->mem_root) + all_items= thd->stmt_arena->free_list; + else + all_items= thd->free_list; + + mark_all_fields_used_in_query(thd, fields_info, &bitmap, all_items); + + for (field_count=0; fields_info->field_name; fields_info++) { + size_t field_name_length= strlen(fields_info->field_name); switch (fields_info->field_type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_LONG: @@ -7798,14 +8193,14 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) case MYSQL_TYPE_DATE: if (!(item=new (mem_root) Item_return_date_time(thd, fields_info->field_name, - strlen(fields_info->field_name), + (uint)field_name_length, fields_info->field_type))) DBUG_RETURN(0); break; case MYSQL_TYPE_TIME: if (!(item=new (mem_root) Item_return_date_time(thd, fields_info->field_name, - strlen(fields_info->field_name), + (uint)field_name_length, fields_info->field_type))) DBUG_RETURN(0); break; @@ -7813,8 +8208,9 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) case MYSQL_TYPE_DATETIME: if (!(item=new (mem_root) Item_return_date_time(thd, fields_info->field_name, - strlen(fields_info->field_name), - fields_info->field_type))) + (uint)field_name_length, + fields_info->field_type, + fields_info->field_length))) DBUG_RETURN(0); item->decimals= fields_info->field_length; break; @@ -7846,33 +8242,50 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) item->max_length+= 1; if (item->decimals > 0) item->max_length+= 1; - item->set_name(thd, fields_info->field_name, - strlen(fields_info->field_name), cs); + item->set_name(thd, fields_info->field_name, field_name_length, cs); break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: - if (!(item= new (mem_root) - Item_blob(thd, fields_info->field_name, - fields_info->field_length))) + if (bitmap_is_set(&bitmap, field_count)) { - DBUG_RETURN(0); + if (!(item= new (mem_root) + Item_blob(thd, fields_info->field_name, + fields_info->field_length))) + { + DBUG_RETURN(0); + } + } + else + { + if (!(item= new (mem_root) + Item_empty_string(thd, "", 0, cs))) + { + DBUG_RETURN(0); + } + item->set_name(thd, fields_info->field_name, + field_name_length, cs); } break; default: + { + bool show_field; /* Don't let unimplemented types pass through. Could be a grave error. */ DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING); + show_field= bitmap_is_set(&bitmap, field_count); if (!(item= new (mem_root) - Item_empty_string(thd, "", fields_info->field_length, cs))) + Item_empty_string(thd, "", + show_field ? fields_info->field_length : 0, cs))) { DBUG_RETURN(0); } item->set_name(thd, fields_info->field_name, - strlen(fields_info->field_name), cs); + field_name_length, cs); break; } + } field_list.push_back(item, thd->mem_root); item->maybe_null= (fields_info->field_flags & MY_I_S_MAYBE_NULL); field_count++; @@ -7888,7 +8301,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, - table_list->alias, false, keep_row_order))) + &table_list->alias, false, keep_row_order))) DBUG_RETURN(0); my_bitmap_map* bitmaps= (my_bitmap_map*) thd->alloc(bitmap_buffer_size(field_count)); @@ -7924,8 +8337,10 @@ static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { if (field_info->old_name) { + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name)}; Item_field *field= new (thd->mem_root) - Item_field(thd, context, NullS, NullS, field_info->field_name); + Item_field(thd, context, NullS, NullS, &field_name); if (field) { field->set_name(thd, field_info->old_name, @@ -7951,8 +8366,11 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { ST_FIELD_INFO *field_info= &schema_table->fields_info[1]; String buffer(tmp,sizeof(tmp), system_charset_info); + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name) }; + Item_field *field= new (thd->mem_root) Item_field(thd, context, - NullS, NullS, field_info->field_name); + NullS, NullS, &field_name); if (!field || add_item_to_list(thd, field)) return 1; buffer.length(0); @@ -7975,11 +8393,13 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) String buffer(tmp,sizeof(tmp), thd->charset()); LEX *lex= thd->lex; Name_resolution_context *context= &lex->select_lex.context; - ST_FIELD_INFO *field_info= &schema_table->fields_info[2]; + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name) }; + buffer.length(0); buffer.append(field_info->old_name); - buffer.append(lex->select_lex.db); + buffer.append(&lex->select_lex.db); if (lex->wild && lex->wild->ptr()) { buffer.append(STRING_WITH_LEN(" (")); @@ -7987,15 +8407,17 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(')'); } Item_field *field= new (thd->mem_root) Item_field(thd, context, - NullS, NullS, field_info->field_name); + NullS, NullS, &field_name); if (add_item_to_list(thd, field)) return 1; field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info); if (thd->lex->verbose) { - field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info); field_info= &schema_table->fields_info[3]; - field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, field_info->field_name); + LEX_CSTRING field_name2= {field_info->field_name, + strlen(field_info->field_name) }; + field= new (thd->mem_root) Item_field(thd, context, NullS, NullS, + &field_name2); if (add_item_to_list(thd, field)) return 1; field->set_name(thd, field_info->old_name, strlen(field_info->old_name), @@ -8015,12 +8437,14 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name)}; if (!thd->lex->verbose && (*field_num == 14 || *field_num == 18 || *field_num == 19)) continue; Item_field *field= new (thd->mem_root) Item_field(thd, context, - NullS, NullS, field_info->field_name); + NullS, NullS, &field_name); if (field) { field->set_name(thd, field_info->old_name, @@ -8044,8 +8468,10 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name)}; Item_field *field= new (thd->mem_root) Item_field(thd, context, - NullS, NullS, field_info->field_name); + NullS, NullS, &field_name); if (field) { field->set_name(thd, field_info->old_name, @@ -8069,8 +8495,10 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) for (; *field_num >= 0; field_num++) { field_info= &schema_table->fields_info[*field_num]; + LEX_CSTRING field_name= {field_info->field_name, + strlen(field_info->field_name)}; Item_field *field= new (thd->mem_root) Item_field(thd, context, - NullS, NullS, field_info->field_name); + NullS, NullS, &field_name); if (field) { field->set_name(thd, field_info->old_name, @@ -8113,10 +8541,10 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) views working correctly */ - if (table_list->schema_table_name) + if (table_list->schema_table_name.str) table->alias_name_used= my_strcasecmp(table_alias_charset, - table_list->schema_table_name, - table_list->alias); + table_list->schema_table_name.str, + table_list->alias.str); table_list->table= table; table->next= thd->derived_tables; thd->derived_tables= table; @@ -8134,8 +8562,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) Field_translator *end= table_list->field_translation_end; for (transl= table_list->field_translation; transl < end; transl++) { - if (!transl->item->fixed && - transl->item->fix_fields(thd, &transl->item)) + if (transl->item->fix_fields_if_needed(thd, &transl->item)) DBUG_RETURN(1); } DBUG_RETURN(0); @@ -8152,10 +8579,8 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) { transl->item= item; transl->name= item->name; - if (!item->fixed && item->fix_fields(thd, &transl->item)) - { + if (item->fix_fields_if_needed(thd, &transl->item)) DBUG_RETURN(1); - } } table_list->field_translation= org_transl; table_list->field_translation_end= transl; @@ -8182,7 +8607,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) int make_schema_select(THD *thd, SELECT_LEX *sel, ST_SCHEMA_TABLE *schema_table) { - LEX_STRING db, table; + LEX_CSTRING db, table; DBUG_ENTER("make_schema_select"); DBUG_PRINT("enter", ("mysql_schema_select: %s", schema_table->table_name)); /* @@ -8200,7 +8625,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel, if (schema_table->old_format(thd, schema_table)) DBUG_RETURN(1); - if (!sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0), + if (!sel->add_table_to_list(thd, new Table_ident(thd, &db, &table, 0), 0, 0, TL_READ, MDL_SHARED_READ)) DBUG_RETURN(1); @@ -8457,7 +8882,7 @@ bool get_schema_tables_result(JOIN *join, } } thd->pop_internal_handler(); - if (thd->is_error()) + if (unlikely(thd->is_error())) { /* This hack is here, because I_S code uses thd->clear_error() a lot. @@ -8517,7 +8942,7 @@ int hton_fill_schema_table(THD *thd, TABLE_LIST *tables, COND *cond) static int store_key_cache_table_record(THD *thd, TABLE *table, - const char *name, uint name_length, + const char *name, size_t name_length, KEY_CACHE *key_cache, uint partitions, uint partition_no) { @@ -8650,6 +9075,9 @@ ST_FIELD_INFO tables_fields_info[]= OPEN_FULL_TABLE}, {"TABLE_COMMENT", TABLE_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY}, + {"MAX_INDEX_LENGTH", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, + (MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), "Max_index_length", OPEN_FULL_TABLE}, + {"TEMPORARY", 1, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "Temporary", OPEN_FRM_ONLY}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -8807,7 +9235,7 @@ ST_FIELD_INFO proc_fields_info[]= SKIP_OPEN_TABLE}, {"ROUTINE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", SKIP_OPEN_TABLE}, - {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE}, + {"ROUTINE_TYPE", 13, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE}, {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, @@ -9130,6 +9558,7 @@ ST_FIELD_INFO processlist_fields_info[]= {"PROGRESS", 703, MYSQL_TYPE_DECIMAL, 0, 0, "Progress", SKIP_OPEN_TABLE}, {"MEMORY_USED", 7, MYSQL_TYPE_LONGLONG, 0, 0, "Memory_used", SKIP_OPEN_TABLE}, + {"MAX_MEMORY_USED", 7, MYSQL_TYPE_LONGLONG, 0, 0, "Max_memory_used", SKIP_OPEN_TABLE}, {"EXAMINED_ROWS", 7, MYSQL_TYPE_LONG, 0, 0, "Examined_rows", SKIP_OPEN_TABLE}, {"QUERY_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE}, {"INFO_BINARY", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_BLOB, 0, 1, @@ -9382,6 +9811,7 @@ ST_FIELD_INFO spatial_ref_sys_fields_info[]= }; #endif /*HAVE_SPATIAL*/ + ST_FIELD_INFO check_constraints_fields_info[]= { {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, @@ -9394,7 +9824,6 @@ ST_FIELD_INFO check_constraints_fields_info[]= OPEN_FULL_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; - /* Description of ST_FIELD_INFO in table.h @@ -9592,8 +10021,8 @@ static bool show_create_trigger_impl(THD *thd, Trigger *trigger) int ret_code; Protocol *p= thd->protocol; List<Item> fields; - LEX_STRING trg_sql_mode_str, trg_body; - LEX_STRING trg_sql_original_stmt; + LEX_CSTRING trg_sql_mode_str, trg_body; + LEX_CSTRING trg_sql_original_stmt; LEX_STRING trg_definer; CHARSET_INFO *trg_client_cs; MEM_ROOT *mem_root= thd->mem_root; @@ -9625,7 +10054,7 @@ static bool show_create_trigger_impl(THD *thd, Trigger *trigger) fields.push_back(new (mem_root) Item_empty_string(thd, "Trigger", NAME_LEN), mem_root); fields.push_back(new (mem_root) - Item_empty_string(thd, "sql_mode", trg_sql_mode_str.length), + Item_empty_string(thd, "sql_mode", (uint)trg_sql_mode_str.length), mem_root); { @@ -9636,7 +10065,7 @@ static bool show_create_trigger_impl(THD *thd, Trigger *trigger) Item_empty_string *stmt_fld= new (mem_root) Item_empty_string(thd, "SQL Original Statement", - MY_MAX(trg_sql_original_stmt.length, + (uint)MY_MAX(trg_sql_original_stmt.length, 1024)); stmt_fld->maybe_null= TRUE; @@ -9746,12 +10175,12 @@ static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) { char trn_path_buff[FN_REFLEN]; - LEX_STRING trn_path= { trn_path_buff, 0 }; - LEX_STRING db; - LEX_STRING tbl_name; + LEX_CSTRING trn_path= { trn_path_buff, 0 }; + LEX_CSTRING db; + LEX_CSTRING tbl_name; TABLE_LIST *table; - build_trn_path(thd, trg_name, &trn_path); + build_trn_path(thd, trg_name, (LEX_STRING*) &trn_path); if (check_trn_exists(&trn_path)) { @@ -9770,15 +10199,14 @@ TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) db.str= thd->strmake(db.str, db.length); if (lower_case_table_names) - db.length= my_casedn_str(files_charset_info, db.str); + db.length= my_casedn_str(files_charset_info, (char*) db.str); tbl_name.str= thd->strmake(tbl_name.str, tbl_name.length); if (db.str == NULL || tbl_name.str == NULL) return NULL; - table->init_one_table(db.str, db.length, tbl_name.str, tbl_name.length, - tbl_name.str, TL_IGNORE); + table->init_one_table(&db, &tbl_name, 0, TL_IGNORE); return table; } @@ -9826,7 +10254,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) { my_error(ER_TRG_CANT_OPEN_TABLE, MYF(0), (const char *) trg_name->m_db.str, - (const char *) lst->table_name); + (const char *) lst->table_name.str); goto exit; @@ -9847,8 +10275,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) { my_error(ER_TRG_CORRUPTED_FILE, MYF(0), (const char *) trg_name->m_db.str, - (const char *) lst->table_name); - + (const char *) lst->table_name.str); goto exit; } @@ -9968,14 +10395,14 @@ static void get_cs_converted_string_value(THD *thd, try_val.copy(input_str->ptr(), input_str->length(), cs, thd->variables.character_set_client, &try_conv_error); - if (!try_conv_error) + if (likely(!try_conv_error)) { String val; uint conv_error= 0; val.copy(input_str->ptr(), input_str->length(), cs, system_charset_info, &conv_error); - if (!conv_error) + if (likely(!conv_error)) { append_unescaped(output_str, val.ptr(), val.length()); return; @@ -10031,11 +10458,11 @@ char *thd_get_error_context_description(THD *thd, char *buffer, String str(buffer, length, &my_charset_latin1); const Security_context *sctx= &thd->main_security_ctx; char header[256]; - int len; + size_t len; len= my_snprintf(header, sizeof(header), - "MySQL thread id %lu, OS thread handle %lu, query id %lu", - thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id); + "MySQL thread id %u, OS thread handle %lu, query id %llu", + (uint)thd->thread_id, (ulong) thd->real_id, (ulonglong) thd->query_id); str.length(0); str.append(header, len); |