diff --git a/sql/field.cc b/sql/field.cc index e95f3a6ae9c..27d6295200c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -11380,6 +11380,15 @@ void Field::register_field_in_read_map() } +LEX_STRING Field::val_lex_string_strmake(MEM_ROOT *mem) +{ + StringBuffer str; + val_str(&str); + char *to= strmake_root(mem, str.ptr(), str.length()); + return to ? LEX_STRING{to, str.length()} : LEX_STRING{NULL, 0}; +} + + bool Field::val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to) { StringBuffer str; diff --git a/sql/field.h b/sql/field.h index ed7ded2f5c1..77538e9292b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1055,6 +1055,20 @@ public: return to->copy((const char *) ptr, pack_length()); } String *val_int_as_str(String *val_buffer, bool unsigned_flag); + + /* + Copy the Field::val_str() value to MEM_ROOT as a 0x00-teminated string. + + @param mem_root The memory root to put the value to. + @returns {NULL,0} in case of EOM, or the field value otherwise. + + Only one 0x00 terminating byte is put in the end, even in case + of complex character sets like UCS2/UTF16/UTF32. + This is OK, since this method is used to read system tables, + which are in utf8. + */ + LEX_STRING val_lex_string_strmake(MEM_ROOT *mem_root); + /* Return the field value as a LEX_CSTRING, without padding to full length (MODE_PAD_CHAR_TO_FULL_LENGTH is temporarily suppressed during the call). diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 51fdd58b9c4..8f09211c0c6 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -69,6 +69,29 @@ enum enum_used_fields }; +/* + Allocate string field in MEM_ROOT and return it as String + + SYNOPSIS + get_field() + mem MEM_ROOT for allocating + field Field for retrieving of string + res result String +*/ + +static void get_field(MEM_ROOT *mem, Field *field, String *res) +{ + THD *thd= field->get_thd(); + Sql_mode_instant_remove sms(thd, MODE_PAD_CHAR_TO_FULL_LENGTH); + LEX_STRING ls= field->val_lex_string_strmake(mem); + DBUG_ASSERT((!ls.str && !ls.length) || ls.str[ls.length] == '\0'); + if (!ls.str) + res->length(0); // EOM + else + res->set((const char *) ls.str, ls.length, field->charset()); +} + + /* Fill st_find_field structure with pointers to fields diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 094ff52a4ea..ce43d3f7aad 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1883,12 +1883,11 @@ static void plugin_load(MEM_ROOT *tmp_root) while (!(error= read_record_info.read_record())) { DBUG_PRINT("info", ("init plugin record")); - String str_name, str_dl; - get_field(tmp_root, table->field[0], &str_name); - get_field(tmp_root, table->field[1], &str_dl); - - LEX_CSTRING name= {str_name.ptr(), str_name.length()}; - LEX_CSTRING dl= {str_dl.ptr(), str_dl.length()}; + DBUG_ASSERT(new_thd == table->field[0]->get_thd()); + DBUG_ASSERT(new_thd == table->field[1]->get_thd()); + DBUG_ASSERT(!(new_thd->variables.sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH)); + LEX_CSTRING name= table->field[0]->val_lex_string_strmake(tmp_root); + LEX_CSTRING dl= table->field[1]->val_lex_string_strmake(tmp_root); if (!name.length || !dl.length) continue; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 785ba2adccc..db7f6483309 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -208,10 +208,11 @@ void udf_init() while (!(error= read_record_info.read_record())) { DBUG_PRINT("info",("init udf record")); - LEX_CSTRING name; - name.str=get_field(&mem, table->field[0]); - name.length = (uint) safe_strlen(name.str); - char *dl_name= get_field(&mem, table->field[2]); + DBUG_ASSERT(!(new_thd->variables.sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH)); + DBUG_ASSERT(table->field[0]->get_thd() == new_thd); + DBUG_ASSERT(table->field[2]->get_thd() == new_thd); + LEX_CSTRING name= table->field[0]->val_lex_string_strmake(&mem); + LEX_CSTRING dl_name= table->field[2]->val_lex_string_strmake(&mem); bool new_dl=0; Item_udftype udftype=UDFTYPE_FUNCTION; if (table->s->fields >= 4) // New func table @@ -224,7 +225,8 @@ void udf_init() On windows we must check both FN_LIBCHAR and '/'. */ - if (!name.str || !dl_name || check_valid_path(dl_name, strlen(dl_name)) || + if (!name.length || !dl_name.length || + check_valid_path(dl_name.str, dl_name.length) || check_string_char_length(&name, 0, NAME_CHAR_LEN, system_charset_info, 1)) { @@ -234,7 +236,7 @@ void udf_init() } if (!(tmp= add_udf(&name,(Item_result) table->field[1]->val_int(), - dl_name, udftype))) + dl_name.str, udftype))) { sql_print_error("Can't alloc memory for udf function: '%.64s'", name.str); continue; diff --git a/sql/table.cc b/sql/table.cc index f66203d31ce..a365d64011e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5090,40 +5090,6 @@ rename_file_ext(const char * from,const char * to,const char * ext) } -/* - Allocate string field in MEM_ROOT and return it as String - - SYNOPSIS - get_field() - mem MEM_ROOT for allocating - field Field for retrieving of string - res result String - - RETURN VALUES - 1 string is empty - 0 all ok -*/ - -bool get_field(MEM_ROOT *mem, Field *field, String *res) -{ - const char *to; - StringBuffer str; - bool rc; - THD *thd= field->get_thd(); - Sql_mode_instant_remove sms(thd, MODE_PAD_CHAR_TO_FULL_LENGTH); - - field->val_str(&str); - if ((rc= !str.length() || - !(to= strmake_root(mem, str.ptr(), str.length())))) - { - res->length(0); - return rc; - } - res->set(to, str.length(), field->charset()); - return false; -} - - /* Allocate string field in MEM_ROOT and return it as NULL-terminated string @@ -5139,10 +5105,12 @@ bool get_field(MEM_ROOT *mem, Field *field, String *res) char *get_field(MEM_ROOT *mem, Field *field) { - String str; - bool rc= get_field(mem, field, &str); - DBUG_ASSERT(rc || str.ptr()[str.length()] == '\0'); - return rc ? NullS : (char *) str.ptr(); + THD *thd= field->get_thd(); + Sql_mode_instant_remove sms(thd, MODE_PAD_CHAR_TO_FULL_LENGTH); + LEX_STRING ls= field->val_lex_string_strmake(mem); + DBUG_ASSERT((!ls.str && !ls.length) || ls.str[ls.length] == '\0'); + // Empty string "" is intentionally returned as NullS + return ls.length == 0 ? NullS : ls.str; } /* diff --git a/sql/table.h b/sql/table.h index 309291a5e28..a0d25bc3002 100644 --- a/sql/table.h +++ b/sql/table.h @@ -3404,7 +3404,6 @@ bool check_period_name(const char *name); bool check_table_name(const char *name, size_t length, bool check_for_path_chars); int rename_file_ext(const char * from,const char * to,const char * ext); char *get_field(MEM_ROOT *mem, Field *field); -bool get_field(MEM_ROOT *mem, Field *field, class String *res); bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len, uint err_code, const char *name);