summaryrefslogtreecommitdiff
path: root/sql/sql_show.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r--sql/sql_show.cc1993
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,
- &param->recinfo, error, 0, NULL))
+ if (unlikely(create_internal_tmp_table_from_heap(thd, table,
+ param->start_recinfo,
+ &param->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],
- &params);
- 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,
+ &params);
+ 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);