diff options
Diffstat (limited to 'sql/sql_show.cc')
-rw-r--r-- | sql/sql_show.cc | 902 |
1 files changed, 548 insertions, 354 deletions
diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 4f217159e5c..4e37b53b87e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -39,7 +39,6 @@ #include "tztime.h" // struct Time_zone #include "sql_acl.h" // TABLE_ACLS, check_grant, DB_ACLS, acl_get, // check_grant_db -#include "filesort.h" // filesort_free_buffers #include "sp.h" #include "sp_head.h" #include "sp_pcontext.h" @@ -93,6 +92,20 @@ 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[]= +{ + { C_STRING_WITH_LEN("BEFORE") }, + { C_STRING_WITH_LEN("AFTER") } +}; + +static const LEX_STRING trg_event_type_names[]= +{ + { C_STRING_WITH_LEN("INSERT") }, + { C_STRING_WITH_LEN("UPDATE") }, + { C_STRING_WITH_LEN("DELETE") } +}; + #ifndef NO_EMBEDDED_ACCESS_CHECKS static const char *grant_names[]={ "select","insert","update","delete","create","drop","reload","shutdown", @@ -774,6 +787,57 @@ static void dispose_db_dir(void *ptr) } +/* + Append an element into @@ignore_db_dirs + + This is a function to be called after regular option processing has been + finalized. +*/ + +void ignore_db_dirs_append(const char *dirname_arg) +{ + char *new_entry_buf; + LEX_STRING *new_entry; + size_t len= strlen(dirname_arg); + + if (!my_multi_malloc(0, + &new_entry, sizeof(LEX_STRING), + &new_entry_buf, len + 1, + NullS)) + return; + + memcpy(new_entry_buf, dirname_arg, len+1); + new_entry->str = new_entry_buf; + new_entry->length= len; + + if (my_hash_insert(&ignore_db_dirs_hash, (uchar *)new_entry)) + { + // Either the name is already there or out-of-memory. + my_free(new_entry); + return; + } + + // Append the name to the option string. + size_t curlen= strlen(opt_ignore_db_dirs); + // Add one for comma and one for \0. + size_t newlen= curlen + len + 1 + 1; + char *new_db_dirs; + if (!(new_db_dirs= (char*)my_malloc(newlen ,MYF(0)))) + { + // This is not a critical condition + return; + } + + memcpy(new_db_dirs, opt_ignore_db_dirs, curlen); + if (curlen != 0) + new_db_dirs[curlen]=','; + memcpy(new_db_dirs + (curlen + ((curlen!=0)?1:0)), dirname_arg, len+1); + + if (opt_ignore_db_dirs) + my_free(opt_ignore_db_dirs); + opt_ignore_db_dirs= new_db_dirs; +} + bool ignore_db_dirs_process_additions() { @@ -1069,7 +1133,7 @@ public: } bool handle_condition(THD *thd, uint sql_errno, const char * /* sqlstate */, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char *message, Sql_condition ** /* cond_hdl */) { /* @@ -1169,7 +1233,7 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, Temporary tables should be opened for SHOW CREATE TABLE, but not for SHOW CREATE VIEW. */ - if (open_temporary_tables(thd, table_list)) + if (thd->open_temporary_tables(table_list)) goto exit; /* @@ -1206,7 +1270,7 @@ mysqld_show_create_get_fields(THD *thd, TABLE_LIST *table_list, bool open_error= open_tables(thd, &table_list, &counter, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL) || - mysql_handle_derived(lex, DT_PREPARE); + mysql_handle_derived(lex, DT_INIT | DT_PREPARE); thd->pop_internal_handler(); if (open_error && (thd->killed || thd->is_error())) goto exit; @@ -1464,7 +1528,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) if (open_normal_and_derived_tables(thd, table_list, MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL, - DT_PREPARE | DT_CREATE)) + DT_INIT | DT_PREPARE | DT_CREATE)) DBUG_VOID_RETURN; table= table_list->table; @@ -1511,14 +1575,13 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) static const char *require_quotes(const char *name, uint name_length) { - uint length; bool pure_digit= TRUE; const char *end= name + name_length; for (; name < end ; name++) { uchar chr= (uchar) *name; - length= my_mbcharlen(system_charset_info, chr); + int length= my_charlen(system_charset_info, name, end); if (length == 1 && !system_charset_info->ident_map[chr]) return name; if (length == 1 && (chr < '0' || chr > '9')) @@ -1576,24 +1639,25 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) if (packet->append("e_char, 1, quote_charset)) return true; - for (name_end= name+length ; name < name_end ; name+= length) + for (name_end= name+length ; name < name_end ; ) { uchar chr= (uchar) *name; - length= my_mbcharlen(system_charset_info, chr); + int char_length= my_charlen(system_charset_info, name, name_end); /* - my_mbcharlen can return 0 on a wrong multibyte + charlen can return 0 and negative numbers on a wrong multibyte sequence. It is possible when upgrading from 4.0, and identifier contains some accented characters. The manual says it does not work. So we'll just - change length to 1 not to hang in the endless loop. + change char_length to 1 not to hang in the endless loop. */ - if (!length) - length= 1; - if (length == 1 && chr == (uchar) quote_char && + if (char_length <= 0) + char_length= 1; + if (char_length == 1 && chr == (uchar) quote_char && packet->append("e_char, 1, quote_charset)) return true; - if (packet->append(name, length, system_charset_info)) + if (packet->append(name, char_length, system_charset_info)) return true; + name+= char_length; } return packet->append("e_char, 1, quote_charset); } @@ -1684,9 +1748,11 @@ static bool print_on_update_clause(Field *field, String *val, bool lcase) val->append(STRING_WITH_LEN("on update ")); else val->append(STRING_WITH_LEN("ON UPDATE ")); - val->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); + val->append(STRING_WITH_LEN("current_timestamp")); if (field->decimals() > 0) val->append_parenthesized(field->decimals()); + else + val->append(STRING_WITH_LEN("()")); return true; } return false; @@ -1697,64 +1763,62 @@ static bool get_field_default_value(THD *thd, Field *field, String *def_value, bool quoted) { bool has_default; - bool has_now_default; enum enum_field_types field_type= field->type(); - /* - We are using CURRENT_TIMESTAMP instead of NOW because it is - more standard - */ - has_now_default= field->has_insert_default_function(); - - has_default= (field_type != FIELD_TYPE_BLOB && - !(field->flags & NO_DEFAULT_VALUE_FLAG) && - field->unireg_check != Field::NEXT_NUMBER && - !((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) - && has_now_default)); + has_default= (field->default_value || + (!(field->flags & NO_DEFAULT_VALUE_FLAG) && + field->unireg_check != Field::NEXT_NUMBER)); def_value->length(0); if (has_default) { - if (has_now_default) + StringBuffer<MAX_FIELD_WIDTH> str(field->charset()); + if (field->default_value) { - def_value->append(STRING_WITH_LEN("CURRENT_TIMESTAMP")); - if (field->decimals() > 0) - def_value->append_parenthesized(field->decimals()); + field->default_value->print(&str); + if (field->default_value->expr->need_parentheses_in_default()) + { + def_value->set_charset(&my_charset_utf8mb4_general_ci); + def_value->append('('); + def_value->append(str); + def_value->append(')'); + } + else + def_value->append(str); } else if (!field->is_null()) { // Not null by default - char tmp[MAX_FIELD_WIDTH]; - String type(tmp, sizeof(tmp), field->charset()); if (field_type == MYSQL_TYPE_BIT) { - longlong dec= field->val_int(); - char *ptr= longlong2str(dec, tmp + 2, 2); - uint32 length= (uint32) (ptr - tmp); - tmp[0]= 'b'; - tmp[1]= '\''; - tmp[length]= '\''; - type.length(length + 1); + str.qs_append('b'); + str.qs_append('\''); + str.qs_append(field->val_int(), 2); + str.qs_append('\''); quoted= 0; } else - field->val_str(&type); - if (type.length()) { - String def_val; + field->val_str(&str); + if (!field->str_needs_quotes()) + quoted= 0; + } + if (str.length()) + { + StringBuffer<MAX_FIELD_WIDTH> def_val; uint dummy_errors; /* convert to system_charset_info == utf8 */ - def_val.copy(type.ptr(), type.length(), field->charset(), + def_val.copy(str.ptr(), str.length(), field->charset(), system_charset_info, &dummy_errors); if (quoted) append_unescaped(def_value, def_val.ptr(), def_val.length()); else - def_value->append(def_val.ptr(), def_val.length()); + def_value->append(def_val); } else if (quoted) - def_value->append(STRING_WITH_LEN("''")); + def_value->set(STRING_WITH_LEN("''"), system_charset_info); } else if (field->maybe_null() && quoted) - def_value->append(STRING_WITH_LEN("NULL")); // Null as default + def_value->set(STRING_WITH_LEN("NULL"), system_charset_info); // Null as default else return 0; @@ -1841,8 +1905,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, List<Item> field_list; char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH]; const char *alias; - String type(tmp, sizeof(tmp), system_charset_info); - String def_value(def_value_buf, sizeof(def_value_buf), system_charset_info); + String type; + String def_value; Field **ptr,*field; uint primary_key; KEY *key_info; @@ -1935,12 +1999,8 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" ")); append_identifier(thd,packet,field->field_name, strlen(field->field_name)); packet->append(' '); - // check for surprises from the previous call to Field::sql_type() - if (type.ptr() != tmp) - type.set(tmp, sizeof(tmp), system_charset_info); - else - type.set_charset(system_charset_info); + type.set(tmp, sizeof(tmp), system_charset_info); field->sql_type(type); packet->append(type.ptr(), type.length(), system_charset_info); @@ -1964,13 +2024,13 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, if (field->vcol_info) { - packet->append(STRING_WITH_LEN(" AS (")); - packet->append(field->vcol_info->expr_str.str, - field->vcol_info->expr_str.length, - system_charset_info); + StringBuffer<MAX_FIELD_WIDTH> str(&my_charset_utf8mb4_general_ci); + field->vcol_info->print(&str); + packet->append(STRING_WITH_LEN(" GENERATED ALWAYS AS (")); + packet->append(str); packet->append(STRING_WITH_LEN(")")); - if (field->stored_in_db) - packet->append(STRING_WITH_LEN(" PERSISTENT")); + if (field->vcol_info->stored_in_db) + packet->append(STRING_WITH_LEN(" STORED")); else packet->append(STRING_WITH_LEN(" VIRTUAL")); } @@ -1987,6 +2047,7 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" NULL")); } + def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info); if (get_field_default_value(thd, field, &def_value, 1)) { packet->append(STRING_WITH_LEN(" DEFAULT ")); @@ -2010,8 +2071,19 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" COMMENT ")); append_unescaped(packet, field->comment.str, field->comment.length); } + append_create_options(thd, packet, field->option_list, check_options, hton->field_options); + + if (field->check_constraint) + { + StringBuffer<MAX_FIELD_WIDTH> str(&my_charset_utf8mb4_general_ci); + field->check_constraint->print(&str); + packet->append(STRING_WITH_LEN(" CHECK (")); + packet->append(str); + packet->append(STRING_WITH_LEN(")")); + } + } key_info= table->key_info; @@ -2093,6 +2165,28 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, file->free_foreign_key_create_info(for_str); } + /* Add table level check constraints */ + if (share->table_check_constraints) + { + for (uint i= share->field_check_constraints; + i < share->table_check_constraints ; i++) + { + StringBuffer<MAX_FIELD_WIDTH> str(&my_charset_utf8mb4_general_ci); + Virtual_column_info *check= table->check_constraints[i]; + check->print(&str); + + packet->append(STRING_WITH_LEN(",\n ")); + if (check->name.length) + { + packet->append(STRING_WITH_LEN("CONSTRAINT ")); + append_identifier(thd, packet, check->name.str, check->name.length); + } + packet->append(STRING_WITH_LEN(" CHECK (")); + packet->append(str); + packet->append(STRING_WITH_LEN(")")); + } + } + packet->append(STRING_WITH_LEN("\n)")); if (show_table_options) { @@ -2246,20 +2340,14 @@ int show_create_table(THD *thd, TABLE_LIST *table_list, String *packet, */ uint part_syntax_len; char *part_syntax; - String comment_start; - table->part_info->set_show_version_string(&comment_start); - if ((part_syntax= generate_partition_syntax(table->part_info, + if ((part_syntax= generate_partition_syntax(thd, table->part_info, &part_syntax_len, - FALSE, show_table_options, - NULL, NULL, - comment_start.c_ptr()))) + NULL, NULL))) { - packet->append(comment_start); - if (packet->append(part_syntax, part_syntax_len) || - packet->append(STRING_WITH_LEN(" */"))) + packet->append('\n'); + if (packet->append(part_syntax, part_syntax_len)) error= 1; - my_free(part_syntax); } } } @@ -2459,7 +2547,7 @@ public: size_t size __attribute__((unused))) { TRASH_FREE(ptr, size); } - ulong thread_id; + my_thread_id thread_id; uint32 os_thread_id; ulonglong start_time; uint command; @@ -2633,7 +2721,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) while ((thd_info=thread_infos.get())) { protocol->prepare_for_resend(); - protocol->store((ulonglong) thd_info->thread_id); + protocol->store(thd_info->thread_id); protocol->store(thd_info->user, system_charset_info); protocol->store(thd_info->host, system_charset_info); protocol->store(thd_info->db, system_charset_info); @@ -2709,7 +2797,7 @@ int select_result_explain_buffer::send_data(List<Item> &items) DBUG_ENTER("select_result_explain_buffer::send_data"); /* - Switch to the recieveing thread, so that we correctly count memory used + Switch to the receiveing thread, so that we correctly count memory used by it. This is needed as it's the receiving thread that will free the memory. */ @@ -2911,7 +2999,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) } else { - my_error(ER_NO_SUCH_THREAD, MYF(0), thread_id); + my_error(ER_NO_SUCH_THREAD, MYF(0), (ulong) thread_id); DBUG_RETURN(1); } } @@ -3128,7 +3216,7 @@ int add_status_vars(SHOW_VAR *list) if (status_vars_inited) mysql_mutex_lock(&LOCK_show_status); if (!all_status_vars.buffer && // array is not allocated yet - do it now - my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20, MYF(0))) + my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 250, 50, MYF(0))) { res= 1; goto err; @@ -3245,6 +3333,132 @@ void remove_status_vars(SHOW_VAR *list) } +/** + @brief Returns the value of a system or a status variable. + + @param thd [in] The handle of the current THD. + @param variable [in] Details of the variable. + @param value_type [in] Variable type. + @param show_type [in] Variable show type. + @param charset [out] Character set of the value. + @param buff [in,out] Buffer to store the value. + (Needs to have enough memory + to hold the value of variable.) + @param length [out] Length of the value. + + @return Pointer to the value buffer. +*/ + +const char* get_one_variable(THD *thd, + const SHOW_VAR *variable, + enum_var_type value_type, SHOW_TYPE show_type, + system_status_var *status_var, + const CHARSET_INFO **charset, char *buff, + size_t *length) +{ + void *value= variable->value; + const char *pos= buff; + const char *end= buff; + + + if (show_type == SHOW_SYS) + { + sys_var *var= (sys_var *) value; + show_type= var->show_type(); + value= var->value_ptr(thd, value_type, &null_lex_str); + *charset= var->charset(thd); + } + + /* + note that value may be == buff. All SHOW_xxx code below + should still work in this case + */ + switch (show_type) { + case SHOW_DOUBLE_STATUS: + value= ((char *) status_var + (intptr) value); + /* fall through */ + case SHOW_DOUBLE: + /* 6 is the default precision for '%f' in sprintf() */ + end= buff + my_fcvt(*(double *) value, 6, buff, NULL); + break; + case SHOW_LONG_STATUS: + value= ((char *) status_var + (intptr) value); + /* fall through */ + case SHOW_ULONG: + case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() + end= int10_to_str(*(long*) value, buff, 10); + break; + case SHOW_LONGLONG_STATUS: + value= ((char *) status_var + (intptr) value); + /* fall through */ + case SHOW_ULONGLONG: + end= longlong10_to_str(*(longlong*) value, buff, 10); + break; + case SHOW_HA_ROWS: + end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); + break; + case SHOW_BOOL: + end= strmov(buff, *(bool*) value ? "ON" : "OFF"); + break; + case SHOW_MY_BOOL: + end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); + break; + case SHOW_UINT: + end= int10_to_str((long) *(uint*) value, buff, 10); + break; + case SHOW_SINT: + end= int10_to_str((long) *(int*) value, buff, -10); + break; + case SHOW_SLONG: + end= int10_to_str(*(long*) value, buff, -10); + break; + case SHOW_SLONGLONG: + end= longlong10_to_str(*(longlong*) value, buff, -10); + break; + case SHOW_HAVE: + { + SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; + pos= show_comp_option_name[(int) tmp]; + end= strend(pos); + break; + } + case SHOW_CHAR: + { + if (!(pos= (char*)value)) + pos= ""; + end= strend(pos); + break; + } + case SHOW_CHAR_PTR: + { + if (!(pos= *(char**) value)) + pos= ""; + + end= strend(pos); + break; + } + case SHOW_LEX_STRING: + { + LEX_STRING *ls=(LEX_STRING*)value; + if (!(pos= ls->str)) + end= pos= ""; + else + end= pos + ls->length; + break; + } + case SHOW_UNDEF: + break; // Return empty string + case SHOW_SYS: // Cannot happen + default: + DBUG_ASSERT(0); + break; + } + + *length= (size_t) (end - pos); + return pos; +} + + static bool show_status_array(THD *thd, const char *wild, SHOW_VAR *variables, enum enum_var_type scope, @@ -3269,7 +3483,7 @@ static bool show_status_array(THD *thd, const char *wild, prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); if (*prefix) *prefix_end++= '_'; - len=name_buffer + sizeof(name_buffer) - prefix_end; + len=(int)(name_buffer + sizeof(name_buffer) - prefix_end); #ifdef WITH_WSREP bool is_wsrep_var= FALSE; @@ -3287,7 +3501,7 @@ static bool show_status_array(THD *thd, const char *wild, for (; variables->name; variables++) { - bool wild_checked= 0; + bool wild_checked= false; strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ @@ -3353,113 +3567,25 @@ static bool show_status_array(THD *thd, const char *wild, else { if ((wild_checked || - (wild && wild[0] && wild_case_compare(system_charset_info, - name_buffer, wild))) && + !(wild && wild[0] && wild_case_compare(system_charset_info, + name_buffer, wild))) && (!cond || cond->val_int())) { - void *value=var->value; - const char *pos, *end; // We assign a lot of const's + const char *pos; // We assign a lot of const's + size_t length; if (show_type == SHOW_SYS) - { - sys_var *var= (sys_var *) value; - show_type= var->show_type(); mysql_mutex_lock(&LOCK_global_system_variables); - value= var->value_ptr(thd, scope, &null_lex_str); - charset= var->charset(thd); - } - - pos= end= buff; - /* - note that value may be == buff. All SHOW_xxx code below - should still work in this case - */ - switch (show_type) { - case SHOW_DOUBLE_STATUS: - value= ((char *) status_var + (intptr) value); - /* fall through */ - case SHOW_DOUBLE: - /* 6 is the default precision for '%f' in sprintf() */ - end= buff + my_fcvt(*(double *) value, 6, buff, NULL); - break; - case SHOW_LONG_STATUS: - value= ((char *) status_var + (intptr) value); - /* fall through */ - case SHOW_ULONG: - case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status() - end= int10_to_str(*(long*) value, buff, 10); - break; - case SHOW_LONGLONG_STATUS: - value= ((char *) status_var + (intptr) value); - /* fall through */ - case SHOW_ULONGLONG: - end= longlong10_to_str(*(longlong*) value, buff, 10); - break; - case SHOW_HA_ROWS: - end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10); - break; - case SHOW_BOOL: - end= strmov(buff, *(bool*) value ? "ON" : "OFF"); - break; - case SHOW_MY_BOOL: - end= strmov(buff, *(my_bool*) value ? "ON" : "OFF"); - break; - case SHOW_UINT: - end= int10_to_str((long) *(uint*) value, buff, 10); - break; - case SHOW_SINT: - end= int10_to_str((long) *(int*) value, buff, -10); - break; - case SHOW_SLONG: - end= int10_to_str(*(long*) value, buff, -10); - break; - case SHOW_SLONGLONG: - end= longlong10_to_str(*(longlong*) value, buff, -10); - break; - case SHOW_HAVE: - { - SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value; - pos= show_comp_option_name[(int) tmp]; - end= strend(pos); - break; - } - case SHOW_CHAR: - { - if (!(pos= (char*)value)) - pos= ""; - end= strend(pos); - break; - } - case SHOW_CHAR_PTR: - { - if (!(pos= *(char**) value)) - pos= ""; + pos= get_one_variable(thd, var, scope, show_type, status_var, + &charset, buff, &length); - end= strend(pos); - break; - } - case SHOW_LEX_STRING: - { - LEX_STRING *ls=(LEX_STRING*)value; - if (!(pos= ls->str)) - end= pos= ""; - else - end= pos + ls->length; - break; - } - case SHOW_UNDEF: - break; // Return empty string - case SHOW_SYS: // Cannot happen - default: - DBUG_ASSERT(0); - break; - } - table->field[1]->store(pos, (uint32) (end - pos), charset); + table->field[1]->store(pos, (uint32) length, charset); + thd->count_cuted_fields= CHECK_FIELD_IGNORE; table->field[1]->set_notnull(); - - if (var->type == SHOW_SYS) + if (show_type == SHOW_SYS) mysql_mutex_unlock(&LOCK_global_system_variables); + if (schema_table_store_record(thd, table)) { res= TRUE; @@ -3625,7 +3751,7 @@ 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), 0)) + strlen(item_field->field_name))) { thd->make_lex_string(&lookup_field_vals->db_value, tmp_str->ptr(), tmp_str->length()); @@ -3634,7 +3760,7 @@ bool get_lookup_value(THD *thd, Item_func *item_func, else if (!cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), (uchar *) item_field->field_name, - strlen(item_field->field_name), 0)) + strlen(item_field->field_name))) { thd->make_lex_string(&lookup_field_vals->table_value, tmp_str->ptr(), tmp_str->length()); @@ -3729,10 +3855,10 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) 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), 0) && + strlen(item_field->field_name)) && cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2), (uchar *) item_field->field_name, - strlen(item_field->field_name), 0))) + strlen(item_field->field_name)))) return 0; } else if (item->type() == Item::EXPR_CACHE_ITEM) @@ -4277,13 +4403,14 @@ fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys, 'only_view_structure()'. */ lex->sql_command= SQLCOM_SHOW_FIELDS; - result= (open_temporary_tables(thd, table_list) || + 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_PREPARE | DT_CREATE)); + DT_INIT | DT_PREPARE | DT_CREATE)); + /* Restore old value of sql_command back as it is being looked at in process_table() function. @@ -4344,6 +4471,7 @@ end: all tables open within this Open_tables_state. */ thd->temporary_tables= NULL; + close_thread_tables(thd); /* Release metadata lock we might have acquired. @@ -4622,7 +4750,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, goto end; } - share= tdc_acquire_share_shortlived(thd, &table_list, GTS_TABLE | GTS_VIEW); + share= tdc_acquire_share(thd, &table_list, GTS_TABLE | GTS_VIEW); if (!share) { if (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE || @@ -4676,7 +4804,7 @@ static int fill_schema_table_from_frm(THD *thd, TABLE *table, table_list.view= (LEX*) share->is_view; res= schema_table->process_table(thd, &table_list, table, res, db_name, table_name); - free_root(&tbl.mem_root, MYF(0)); + closefrm(&tbl); } @@ -4714,16 +4842,14 @@ public: bool handle_condition(THD *thd, uint sql_errno, const char* sqlstate, - Sql_condition::enum_warning_level level, + Sql_condition::enum_warning_level *level, const char* msg, Sql_condition ** cond_hdl) { - if (sql_errno == ER_PARSE_ERROR || - sql_errno == ER_TRG_NO_DEFINER || - sql_errno == ER_TRG_NO_CREATION_CTX) + if (sql_errno == ER_TRG_NO_DEFINER || sql_errno == ER_TRG_NO_CREATION_CTX) return true; - if (level != Sql_condition::WARN_LEVEL_ERROR) + if (*level != Sql_condition::WARN_LEVEL_ERROR) return false; if (!thd->get_stmt_da()->is_error()) @@ -5077,10 +5203,11 @@ 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->tmp_table) - table->field[3]->store(STRING_WITH_LEN("LOCAL TEMPORARY"), cs); else + { + DBUG_ASSERT(share->tmp_table == NO_TMP_TABLE); table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); + } for (int i= 4; i < 20; i++) { @@ -5357,7 +5484,7 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, */ tmp_buff= strchr(column_type.c_ptr_safe(), ' '); table->field[offset]->store(column_type.ptr(), - (tmp_buff ? tmp_buff - column_type.ptr() : + (tmp_buff ? (uint)(tmp_buff - column_type.ptr()) : column_type.length()), cs); is_blob= (field->type() == MYSQL_TYPE_BLOB); @@ -5462,6 +5589,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, TABLE *show_table; Field **ptr, *field; int count; + bool quoted_defaults= lex->sql_command != SQLCOM_SHOW_FIELDS; DBUG_ENTER("get_schema_column_record"); if (res) @@ -5531,7 +5659,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, cs); table->field[4]->store((longlong) count, TRUE); - if (get_field_default_value(thd, field, &type, 0)) + if (get_field_default_value(thd, field, &type, quoted_defaults)) { table->field[5]->store(type.ptr(), type.length(), cs); table->field[5]->set_notnull(); @@ -5550,13 +5678,24 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, table->field[17]->store(STRING_WITH_LEN("auto_increment"), cs); if (print_on_update_clause(field, &type, true)) table->field[17]->store(type.ptr(), type.length(), cs); + if (field->vcol_info) { - if (field->stored_in_db) - table->field[17]->store(STRING_WITH_LEN("PERSISTENT"), cs); + String gen_s(tmp,sizeof(tmp), system_charset_info); + gen_s.length(0); + field->vcol_info->print(&gen_s); + table->field[21]->store(gen_s.ptr(), gen_s.length(), cs); + table->field[21]->set_notnull(); + 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); else - table->field[17]->store(STRING_WITH_LEN("VIRTUAL"), cs); + table->field[17]->store(STRING_WITH_LEN("VIRTUAL GENERATED"), cs); } + else + table->field[20]->store(STRING_WITH_LEN("NEVER"), cs); + table->field[19]->store(field->comment.str, field->comment.length, cs); if (schema_table_store_record(thd, table)) DBUG_RETURN(1); @@ -5836,7 +5975,6 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, if (sp) { Field *field; - Create_field *field_def; String tmp_string; if (routine_type == TYPE_ENUM_FUNCTION) { @@ -5848,14 +5986,7 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, 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_def= &sp->m_return_field_def; - field= make_field(&share, thd->mem_root, - (uchar*) 0, field_def->length, - (uchar*) "", 0, field_def->pack_flag, - field_def->sql_type, field_def->charset, - field_def->geom_type, field_def->srid, Field::NONE, - field_def->interval, ""); - + field= sp->m_return_field_def.make_field(&share, thd->mem_root, ""); field->table= &tbl; tbl.in_use= thd; store_column_type(table, field, cs, 6); @@ -5874,7 +6005,6 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, { const char *tmp_buff; sp_variable *spvar= spcont->find_variable(i); - field_def= &spvar->field_def; switch (spvar->mode) { case sp_variable::MODE_IN: tmp_buff= "IN"; @@ -5903,12 +6033,8 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, &tmp_string); table->field[15]->store(tmp_string.ptr(), tmp_string.length(), cs); - field= make_field(&share, thd->mem_root, (uchar*) 0, field_def->length, - (uchar*) "", 0, field_def->pack_flag, - field_def->sql_type, field_def->charset, - field_def->geom_type, field_def->srid, Field::NONE, - field_def->interval, spvar->name.str); - + 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); @@ -5995,18 +6121,11 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, TABLE_SHARE share; TABLE tbl; Field *field; - Create_field *field_def= &sp->m_return_field_def; bzero((char*) &tbl, sizeof(TABLE)); (void) build_table_filename(path, sizeof(path), "", "", "", 0); init_tmp_table_share(thd, &share, "", 0, "", path); - field= make_field(&share, thd->mem_root, (uchar*) 0, - field_def->length, - (uchar*) "", 0, field_def->pack_flag, - field_def->sql_type, field_def->charset, - field_def->geom_type, field_def->srid, Field::NONE, - field_def->interval, ""); - + field= sp->m_return_field_def.make_field(&share, thd->mem_root, ""); field->table= &tbl; tbl.in_use= thd; store_column_type(table, field, cs, 5); @@ -6354,7 +6473,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, table->field[5]->store(STRING_WITH_LEN("NO"), cs); } - definer_len= (strxmov(definer, tables->definer.user.str, "@", + definer_len= (uint)(strxmov(definer, tables->definer.user.str, "@", tables->definer.host.str, NullS) - definer); table->field[6]->store(definer, definer_len, cs); if (tables->view_suid) @@ -6401,6 +6520,56 @@ bool store_constraints(THD *thd, TABLE *table, LEX_STRING *db_name, return schema_table_store_record(thd, table); } +static int get_check_constraints_record(THD *thd, TABLE_LIST *tables, + TABLE *table, bool res, + LEX_STRING *db_name, + LEX_STRING *table_name) +{ + DBUG_ENTER("get_check_constraints_record"); + if (res) + { + if (thd->is_error()) + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + thd->get_stmt_da()->sql_errno(), + thd->get_stmt_da()->message()); + thd->clear_error(); + DBUG_RETURN(0); + } + if (!tables->view) + { + StringBuffer<MAX_FIELD_WIDTH> str(system_charset_info); +#ifndef NO_EMBEDDED_ACCESS_CHECKS + TABLE_LIST table_acl_check; + bzero((char*) &table_acl_check, sizeof(table_acl_check)); +#endif + for (uint i= 0; i < tables->table->s->table_check_constraints; i++) + { +#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.grant.privilege= thd->col_access; + if (check_grant(thd, TABLE_ACLS, &table_acl_check, FALSE, 1, TRUE)) + continue; + } +#endif + Virtual_column_info *check= tables->table->check_constraints[i]; + table->field[0]->store(STRING_WITH_LEN("def"), system_charset_info); + table->field[3]->store(check->name.str, check->name.length, + system_charset_info); + /* Make sure the string is empty between each print. */ + str.length(0); + check->print(&str); + table->field[4]->store(str.ptr(), str.length(), system_charset_info); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + } + } + DBUG_RETURN(res); +} static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, @@ -6447,6 +6616,19 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, } } + // Table check constraints + for ( uint i = 0; i < show_table->s->table_check_constraints; i++ ) + { + Virtual_column_info *check = show_table->check_constraints[ i ]; + + if ( store_constraints( thd, table, db_name, table_name, check->name.str, + check->name.length, + STRING_WITH_LEN( "CHECK" ) ) ) + { + DBUG_RETURN( 1 ); + } + } + show_table->file->get_foreign_key_list(thd, &f_key_list); FOREIGN_KEY_INFO *f_key_info; List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list); @@ -6463,43 +6645,56 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables, } -static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name, - LEX_STRING *table_name, LEX_STRING *trigger_name, - enum trg_event_type event, - enum trg_action_time_type timing, - LEX_STRING *trigger_stmt, - ulong sql_mode, - LEX_STRING *definer_buffer, - LEX_STRING *client_cs_name, - LEX_STRING *connection_cl_name, - LEX_STRING *db_cl_name) +static bool store_trigger(THD *thd, Trigger *trigger, + TABLE *table, LEX_STRING *db_name, + LEX_STRING *table_name) { CHARSET_INFO *cs= system_charset_info; LEX_STRING sql_mode_rep; + MYSQL_TIME timestamp; + char definer_holder[USER_HOST_BUFF_SIZE]; + LEX_STRING definer_buffer, trigger_stmt, trigger_body; + definer_buffer.str= definer_holder; + + trigger->get_trigger_info(&trigger_stmt, &trigger_body, &definer_buffer); restore_record(table, s->default_values); table->field[0]->store(STRING_WITH_LEN("def"), cs); table->field[1]->store(db_name->str, db_name->length, cs); - table->field[2]->store(trigger_name->str, trigger_name->length, cs); - table->field[3]->store(trg_event_type_names[event].str, - trg_event_type_names[event].length, cs); + table->field[2]->store(trigger->name.str, trigger->name.length, cs); + table->field[3]->store(trg_event_type_names[trigger->event].str, + trg_event_type_names[trigger->event].length, cs); table->field[4]->store(STRING_WITH_LEN("def"), cs); table->field[5]->store(db_name->str, db_name->length, cs); table->field[6]->store(table_name->str, table_name->length, cs); - table->field[9]->store(trigger_stmt->str, trigger_stmt->length, cs); + table->field[7]->store(trigger->action_order); + table->field[9]->store(trigger_body.str, trigger_body.length, cs); table->field[10]->store(STRING_WITH_LEN("ROW"), cs); - table->field[11]->store(trg_action_time_type_names[timing].str, - trg_action_time_type_names[timing].length, cs); + table->field[11]->store(trg_action_time_type_names[trigger->action_time].str, + trg_action_time_type_names[trigger->action_time].length, cs); table->field[14]->store(STRING_WITH_LEN("OLD"), cs); table->field[15]->store(STRING_WITH_LEN("NEW"), cs); - sql_mode_string_representation(thd, sql_mode, &sql_mode_rep); + if (trigger->create_time) + { + table->field[16]->set_notnull(); + thd->variables.time_zone->gmt_sec_to_TIME(×tamp, + (my_time_t)(trigger->create_time/100)); + /* timestamp is with 6 digits */ + timestamp.second_part= (trigger->create_time % 100) * 10000; + ((Field_temporal_with_date*) table->field[16])->store_time_dec(×tamp, + 2); + } + + sql_mode_string_representation(thd, trigger->sql_mode, &sql_mode_rep); table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs); - table->field[18]->store(definer_buffer->str, definer_buffer->length, cs); - table->field[19]->store(client_cs_name->str, client_cs_name->length, cs); - table->field[20]->store(connection_cl_name->str, - connection_cl_name->length, cs); - table->field[21]->store(db_cl_name->str, db_cl_name->length, cs); + table->field[18]->store(definer_buffer.str, definer_buffer.length, cs); + table->field[19]->store(trigger->client_cs_name.str, + trigger->client_cs_name.length, cs); + table->field[20]->store(trigger->connection_cl_name.str, + trigger->connection_cl_name.length, cs); + table->field[21]->store(trigger->db_cl_name.str, + trigger->db_cl_name.length, cs); return schema_table_store_record(thd, table); } @@ -6536,35 +6731,16 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables, { for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++) { - LEX_STRING trigger_name; - LEX_STRING trigger_stmt; - ulong sql_mode; - char definer_holder[USER_HOST_BUFF_SIZE]; - LEX_STRING definer_buffer; - LEX_STRING client_cs_name; - LEX_STRING connection_cl_name; - LEX_STRING db_cl_name; - - definer_buffer.str= definer_holder; - if (triggers->get_trigger_info(thd, (enum trg_event_type) event, - (enum trg_action_time_type)timing, - &trigger_name, &trigger_stmt, - &sql_mode, - &definer_buffer, - &client_cs_name, - &connection_cl_name, - &db_cl_name)) - continue; - - if (store_trigger(thd, table, db_name, table_name, &trigger_name, - (enum trg_event_type) event, - (enum trg_action_time_type) timing, &trigger_stmt, - sql_mode, - &definer_buffer, - &client_cs_name, - &connection_cl_name, - &db_cl_name)) - DBUG_RETURN(1); + Trigger *trigger; + for (trigger= triggers-> + get_trigger((enum trg_event_type) event, + (enum trg_action_time_type) timing) ; + trigger; + trigger= trigger->next) + { + if (store_trigger(thd, trigger, table, db_name, table_name)) + DBUG_RETURN(1); + } } } } @@ -6841,7 +7017,7 @@ get_partition_column_description(THD *thd, { part_column_list_val *col_val= &list_value->col_val_array[i]; if (col_val->max_value) - tmp_str.append(partition_keywords[PKW_MAXVALUE].str); + tmp_str.append(STRING_WITH_LEN("MAXVALUE")); else if (col_val->null_value) tmp_str.append("NULL"); else @@ -6918,27 +7094,21 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, case LIST_PARTITION: tmp_res.length(0); if (part_info->part_type == RANGE_PARTITION) - tmp_res.append(partition_keywords[PKW_RANGE].str, - partition_keywords[PKW_RANGE].length); + tmp_res.append(STRING_WITH_LEN("RANGE")); else - tmp_res.append(partition_keywords[PKW_LIST].str, - partition_keywords[PKW_LIST].length); + tmp_res.append(STRING_WITH_LEN("LIST")); if (part_info->column_list) - tmp_res.append(partition_keywords[PKW_COLUMNS].str, - partition_keywords[PKW_COLUMNS].length); + tmp_res.append(STRING_WITH_LEN(" COLUMNS")); table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); break; case HASH_PARTITION: tmp_res.length(0); if (part_info->linear_hash_ind) - tmp_res.append(partition_keywords[PKW_LINEAR].str, - partition_keywords[PKW_LINEAR].length); + tmp_res.append(STRING_WITH_LEN("LINEAR ")); if (part_info->list_of_part_fields) - tmp_res.append(partition_keywords[PKW_KEY].str, - partition_keywords[PKW_KEY].length); + tmp_res.append(STRING_WITH_LEN("KEY")); else - tmp_res.append(partition_keywords[PKW_HASH].str, - partition_keywords[PKW_HASH].length); + tmp_res.append(STRING_WITH_LEN("HASH")); table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs); break; default: @@ -6951,8 +7121,9 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, /* Partition expression */ if (part_info->part_expr) { - table->field[9]->store(part_info->part_func_string, - part_info->part_func_len, cs); + StringBuffer<STRING_BUFFER_USUAL_SIZE> str(cs); + part_info->part_expr->print_for_table_def(&str); + table->field[9]->store(str.ptr(), str.length(), str.charset()); } else if (part_info->list_of_part_fields) { @@ -6966,22 +7137,20 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, /* Subpartition method */ tmp_res.length(0); if (part_info->linear_hash_ind) - tmp_res.append(partition_keywords[PKW_LINEAR].str, - partition_keywords[PKW_LINEAR].length); + tmp_res.append(STRING_WITH_LEN("LINEAR ")); if (part_info->list_of_subpart_fields) - tmp_res.append(partition_keywords[PKW_KEY].str, - partition_keywords[PKW_KEY].length); + tmp_res.append(STRING_WITH_LEN("KEY")); else - tmp_res.append(partition_keywords[PKW_HASH].str, - partition_keywords[PKW_HASH].length); + tmp_res.append(STRING_WITH_LEN("HASH")); table->field[8]->store(tmp_res.ptr(), tmp_res.length(), cs); table->field[8]->set_notnull(); /* Subpartition expression */ if (part_info->subpart_expr) { - table->field[10]->store(part_info->subpart_func_string, - part_info->subpart_func_len, cs); + StringBuffer<STRING_BUFFER_USUAL_SIZE> str(cs); + part_info->subpart_expr->print_for_table_def(&str); + table->field[10]->store(str.ptr(), str.length(), str.charset()); } else if (part_info->list_of_subpart_fields) { @@ -7022,8 +7191,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, if (part_elem->range_value != LONGLONG_MAX) table->field[11]->store((longlong) part_elem->range_value, FALSE); else - table->field[11]->store(partition_keywords[PKW_MAXVALUE].str, - partition_keywords[PKW_MAXVALUE].length, cs); + table->field[11]->store(STRING_WITH_LEN("MAXVALUE"), cs); } table->field[11]->set_notnull(); } @@ -7338,7 +7506,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) COND *partial_cond= make_cond_for_info_schema(thd, cond, tables); - mysql_rwlock_rdlock(&LOCK_system_variables_hash); + mysql_prlock_rdlock(&LOCK_system_variables_hash); /* Avoid recursive LOCK_system_variables_hash acquisition in @@ -7353,7 +7521,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, scope), scope, NULL, "", tables->table, upper_case_names, partial_cond); - mysql_rwlock_unlock(&LOCK_system_variables_hash); + mysql_prlock_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); } @@ -7648,6 +7816,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) strlen(fields_info->field_name), fields_info->field_type))) DBUG_RETURN(0); + item->decimals= fields_info->field_length; break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: @@ -7677,7 +7846,7 @@ 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(fields_info->field_name, + item->set_name(thd, fields_info->field_name, strlen(fields_info->field_name), cs); break; case MYSQL_TYPE_TINY_BLOB: @@ -7700,7 +7869,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) { DBUG_RETURN(0); } - item->set_name(fields_info->field_name, + item->set_name(thd, fields_info->field_name, strlen(fields_info->field_name), cs); break; } @@ -7759,7 +7928,7 @@ static int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) Item_field(thd, context, NullS, NullS, field_info->field_name); if (field) { - field->set_name(field_info->old_name, + field->set_name(thd, field_info->old_name, strlen(field_info->old_name), system_charset_info); if (add_item_to_list(thd, field)) @@ -7794,7 +7963,7 @@ int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) buffer.append(lex->wild->ptr()); buffer.append(')'); } - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info); } return 0; } @@ -7821,15 +7990,15 @@ int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + field->set_name(thd, buffer.ptr(), buffer.length(), system_charset_info); if (thd->lex->verbose) { - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + 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); if (add_item_to_list(thd, field)) return 1; - field->set_name(field_info->old_name, strlen(field_info->old_name), + field->set_name(thd, field_info->old_name, strlen(field_info->old_name), system_charset_info); } return 0; @@ -7854,7 +8023,7 @@ int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) NullS, NullS, field_info->field_name); if (field) { - field->set_name(field_info->old_name, + field->set_name(thd, field_info->old_name, strlen(field_info->old_name), system_charset_info); if (add_item_to_list(thd, field)) @@ -7879,7 +8048,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) NullS, NullS, field_info->field_name); if (field) { - field->set_name(field_info->old_name, + field->set_name(thd, field_info->old_name, strlen(field_info->old_name), system_charset_info); if (add_item_to_list(thd, field)) @@ -7904,7 +8073,7 @@ int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) NullS, NullS, field_info->field_name); if (field) { - field->set_name(field_info->old_name, + field->set_name(thd, field_info->old_name, strlen(field_info->old_name), system_charset_info); if (add_item_to_list(thd, field)) @@ -8130,7 +8299,6 @@ end: bool optimize_schema_tables_reads(JOIN *join) { THD *thd= join->thd; - bool result= 0; DBUG_ENTER("optimize_schema_tables_reads"); JOIN_TAB *tab; @@ -8165,11 +8333,11 @@ bool optimize_schema_tables_reads(JOIN *join) */ cond= tab->cache_select->cond; } - - optimize_for_get_all_tables(thd, table_list, cond); + if (optimize_for_get_all_tables(thd, table_list, cond)) + DBUG_RETURN(TRUE); // Handle OOM } } - DBUG_RETURN(result); + DBUG_RETURN(FALSE); } @@ -8256,8 +8424,6 @@ bool get_schema_tables_result(JOIN *join, table_list->table->file->extra(HA_EXTRA_NO_CACHE); table_list->table->file->extra(HA_EXTRA_RESET_STATE); table_list->table->file->ha_delete_all_rows(); - free_io_cache(table_list->table); - filesort_free_buffers(table_list->table,1); table_list->table->null_row= 0; } else @@ -8277,6 +8443,7 @@ bool get_schema_tables_result(JOIN *join, cond= tab->cache_select->cond; } + Switch_to_definer_security_ctx backup_ctx(thd, table_list); if (table_list->schema_table->fill_table(thd, table_list, cond)) { result= 1; @@ -8516,10 +8683,13 @@ ST_FIELD_INFO columns_fields_info[]= OPEN_FRM_ONLY}, {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type", OPEN_FRM_ONLY}, {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key", OPEN_FRM_ONLY}, - {"EXTRA", 27, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY}, + {"EXTRA", 30, MYSQL_TYPE_STRING, 0, 0, "Extra", OPEN_FRM_ONLY}, {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges", OPEN_FRM_ONLY}, {"COLUMN_COMMENT", COLUMN_COMMENT_MAXLEN, MYSQL_TYPE_STRING, 0, 0, "Comment", OPEN_FRM_ONLY}, + {"IS_GENERATED", 6, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"GENERATION_EXPRESSION", MAX_FIELD_VARCHARLENGTH, MYSQL_TYPE_STRING, 0, 1, + 0, OPEN_FRM_ONLY}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -8854,7 +9024,8 @@ ST_FIELD_INFO triggers_fields_info[]= OPEN_FRM_ONLY}, {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, - {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FRM_ONLY}, + /* 2 here indicates 2 decimals */ + {"CREATED", 2, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FRM_ONLY}, {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FRM_ONLY}, {"DEFINER", DEFINER_CHAR_LENGTH, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FRM_ONLY}, {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, @@ -8958,7 +9129,7 @@ ST_FIELD_INFO processlist_fields_info[]= {"MAX_STAGE", 2, MYSQL_TYPE_TINY, 0, 0, "Max_stage", SKIP_OPEN_TABLE}, {"PROGRESS", 703, MYSQL_TYPE_DECIMAL, 0, 0, "Progress", SKIP_OPEN_TABLE}, - {"MEMORY_USED", 7, MYSQL_TYPE_LONG, 0, 0, "Memory_used", SKIP_OPEN_TABLE}, + {"MEMORY_USED", 7, MYSQL_TYPE_LONGLONG, 0, 0, "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, @@ -8991,7 +9162,7 @@ ST_FIELD_INFO plugin_fields_info[]= ST_FIELD_INFO files_fields_info[]= { {"FILE_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE}, - {"FILE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, + {"FILE_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, {"FILE_TYPE", 20, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, @@ -9211,6 +9382,18 @@ 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}, + {"CONSTRAINT_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {"CHECK_CLAUSE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} +}; /* Description of ST_FIELD_INFO in table.h @@ -9227,6 +9410,8 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_applicable_roles, 0, 0, -1, -1, 0, 0}, {"CHARACTER_SETS", charsets_fields_info, 0, fill_schema_charsets, make_character_sets_old_format, 0, -1, -1, 0, 0}, + {"CHECK_CONSTRAINTS", check_constraints_fields_info, 0, get_all_tables, 0, + get_check_constraints_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"COLLATIONS", collation_fields_info, 0, fill_schema_collation, make_old_format, 0, -1, -1, 0, 0}, {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info, @@ -9385,35 +9570,35 @@ int finalize_schema_table(st_plugin_int *plugin) DBUG_RETURN(0); } +/* + This is used to create a timestamp field +*/ + +MYSQL_TIME zero_time={ 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_TIME }; /** Output trigger information (SHOW CREATE TRIGGER) to the client. @param thd Thread context. - @param triggers List of triggers for the table. - @param trigger_idx Index of the trigger to dump. + @param trigger Trigger to dump @return Operation status @retval TRUE Error. @retval FALSE Success. */ -static bool show_create_trigger_impl(THD *thd, - Table_triggers_list *triggers, - int trigger_idx) +static bool show_create_trigger_impl(THD *thd, Trigger *trigger) { int ret_code; Protocol *p= thd->protocol; List<Item> fields; - LEX_STRING trg_name; - ulonglong trg_sql_mode; - LEX_STRING trg_sql_mode_str; + LEX_STRING trg_sql_mode_str, trg_body; LEX_STRING trg_sql_original_stmt; - LEX_STRING trg_client_cs_name; - LEX_STRING trg_connection_cl_name; - LEX_STRING trg_db_cl_name; + LEX_STRING trg_definer; CHARSET_INFO *trg_client_cs; MEM_ROOT *mem_root= thd->mem_root; + char definer_holder[USER_HOST_BUFF_SIZE]; + trg_definer.str= definer_holder; /* TODO: Check privileges here. This functionality will be added by @@ -9427,20 +9612,12 @@ static bool show_create_trigger_impl(THD *thd, /* Prepare trigger "object". */ - triggers->get_trigger_info(thd, - trigger_idx, - &trg_name, - &trg_sql_mode, - &trg_sql_original_stmt, - &trg_client_cs_name, - &trg_connection_cl_name, - &trg_db_cl_name); - - sql_mode_string_representation(thd, trg_sql_mode, &trg_sql_mode_str); + trigger->get_trigger_info(&trg_sql_original_stmt, &trg_body, &trg_definer); + sql_mode_string_representation(thd, trigger->sql_mode, &trg_sql_mode_str); /* Resolve trigger client character set. */ - if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs)) + if (resolve_charset(trigger->client_cs_name.str, NULL, &trg_client_cs)) return TRUE; /* Send header. */ @@ -9482,6 +9659,11 @@ static bool show_create_trigger_impl(THD *thd, MY_CS_NAME_SIZE), mem_root); + Item_datetime_literal *tmp= (new (mem_root) + Item_datetime_literal(thd, &zero_time, 2)); + tmp->set_name(thd, STRING_WITH_LEN("Created"), system_charset_info); + fields.push_back(tmp, mem_root); + if (p->send_result_set_metadata(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -9491,8 +9673,8 @@ static bool show_create_trigger_impl(THD *thd, p->prepare_for_resend(); - p->store(trg_name.str, - trg_name.length, + p->store(trigger->name.str, + trigger->name.length, system_charset_info); p->store(trg_sql_mode_str.str, @@ -9503,18 +9685,30 @@ static bool show_create_trigger_impl(THD *thd, trg_sql_original_stmt.length, trg_client_cs); - p->store(trg_client_cs_name.str, - trg_client_cs_name.length, + p->store(trigger->client_cs_name.str, + trigger->client_cs_name.length, system_charset_info); - p->store(trg_connection_cl_name.str, - trg_connection_cl_name.length, + p->store(trigger->connection_cl_name.str, + trigger->connection_cl_name.length, system_charset_info); - p->store(trg_db_cl_name.str, - trg_db_cl_name.length, + p->store(trigger->db_cl_name.str, + trigger->db_cl_name.length, system_charset_info); + if (trigger->create_time) + { + MYSQL_TIME timestamp; + thd->variables.time_zone->gmt_sec_to_TIME(×tamp, + (my_time_t)(trigger->create_time/100)); + timestamp.second_part= (trigger->create_time % 100) * 10000; + p->store(×tamp, 2); + } + else + p->store_null(); + + ret_code= p->write(); if (!ret_code) @@ -9606,7 +9800,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) TABLE_LIST *lst= get_trigger_table(thd, trg_name); uint num_tables; /* NOTE: unused, only to pass to open_tables(). */ Table_triggers_list *triggers; - int trigger_idx; + Trigger *trigger; bool error= TRUE; if (!lst) @@ -9647,9 +9841,9 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) goto exit; } - trigger_idx= triggers->find_trigger_by_name(&trg_name->m_name); + trigger= triggers->find_trigger(&trg_name->m_name, 0); - if (trigger_idx < 0) + if (!trigger) { my_error(ER_TRG_CORRUPTED_FILE, MYF(0), (const char *) trg_name->m_db.str, @@ -9658,7 +9852,7 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) goto exit; } - error= show_create_trigger_impl(thd, triggers, trigger_idx); + error= show_create_trigger_impl(thd, trigger); /* NOTE: if show_create_trigger_impl() failed, that means we could not @@ -9840,7 +10034,7 @@ char *thd_get_error_context_description(THD *thd, char *buffer, int len; len= my_snprintf(header, sizeof(header), - "MySQL thread id %lu, OS thread handle 0x%lx, query id %lu", + "MySQL thread id %lu, OS thread handle %lu, query id %lu", thd->thread_id, (ulong) thd->real_id, (ulong) thd->query_id); str.length(0); str.append(header, len); |