diff options
-rw-r--r-- | sql/field.cc | 19 | ||||
-rw-r--r-- | sql/field.h | 15 | ||||
-rw-r--r-- | sql/sp.cc | 298 | ||||
-rw-r--r-- | sql/sp.h | 28 | ||||
-rw-r--r-- | sql/sp_head.cc | 21 | ||||
-rw-r--r-- | sql/sp_head.h | 7 | ||||
-rw-r--r-- | sql/sql_class.cc | 30 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_show.cc | 98 | ||||
-rw-r--r-- | sql/sql_string.h | 1 | ||||
-rw-r--r-- | sql/structs.h | 2 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 17 |
12 files changed, 281 insertions, 256 deletions
diff --git a/sql/field.cc b/sql/field.cc index 6320121d1c3..fbb2ad79ba9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10773,3 +10773,22 @@ void Field::register_field_in_read_map() } bitmap_set_bit(table->read_set, field_index); } + + +bool Field::val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to) +{ + StringBuffer<MAX_FIELD_WIDTH> str; + bool rc= false; + THD *thd= get_thd(); + sql_mode_t sql_mode_backup= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + + val_str(&str); + if (!(to->length= str.length())) + *to= empty_clex_str; + else if ((rc= !(to->str= strmake_root(mem_root, str.ptr(), str.length())))) + to->length= 0; + + thd->variables.sql_mode= sql_mode_backup; + return rc; +} diff --git a/sql/field.h b/sql/field.h index 208941b3daa..cb8ade55090 100644 --- a/sql/field.h +++ b/sql/field.h @@ -839,6 +839,21 @@ public: */ virtual String *val_str(String*,String *)=0; String *val_int_as_str(String *val_buffer, bool unsigned_flag); + /* + 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). + + In case of an empty value, to[0] is assigned to empty_clex_string, + memory is not allocated. + In case of a non-empty value, the memory is allocated on mem_root. + In case of a memory allocation failure, to[0] is assigned to {NULL,0}. + + @param [IN] mem_root store non-empty values here + @param [OUT to return the string here + @retval false (success) + @retval true (EOM) + */ + bool val_str_nopad(MEM_ROOT *mem_root, LEX_CSTRING *to); fast_field_copier get_fast_field_copier(const Field *from); /* str_needs_quotes() returns TRUE if the value returned by val_str() needs diff --git a/sql/sp.cc b/sql/sp.cc index c80078ebe19..2059c1ac508 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -40,10 +40,12 @@ static int db_load_routine(THD *thd, stored_procedure_type type, const sp_name *name, sp_head **sphp, - sql_mode_t sql_mode, const char *params, const char *returns, - const char *body, const st_sp_chistics &chistics, - LEX_CSTRING *definer_user_name, - LEX_CSTRING *definer_host_name, + sql_mode_t sql_mode, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + const LEX_CSTRING &body, + const st_sp_chistics &chistics, + const AUTHID &definer, longlong created, longlong modified, Stored_program_creation_ctx *creation_ctx); @@ -214,15 +216,16 @@ bool load_charset(MEM_ROOT *mem_root, CHARSET_INFO *dflt_cs, CHARSET_INFO **cs) { - String cs_name; + LEX_CSTRING cs_name; - if (get_field(mem_root, field, &cs_name)) + if (field->val_str_nopad(mem_root, &cs_name)) { *cs= dflt_cs; return TRUE; } - *cs= get_charset_by_csname(cs_name.c_ptr(), MY_CS_PRIMARY, MYF(0)); + DBUG_ASSERT(cs_name.str[cs_name.length] == 0); + *cs= get_charset_by_csname(cs_name.str, MY_CS_PRIMARY, MYF(0)); if (*cs == NULL) { @@ -240,15 +243,16 @@ bool load_collation(MEM_ROOT *mem_root, CHARSET_INFO *dflt_cl, CHARSET_INFO **cl) { - String cl_name; + LEX_CSTRING cl_name; - if (get_field(mem_root, field, &cl_name)) + if (field->val_str_nopad(mem_root, &cl_name)) { *cl= dflt_cl; return TRUE; } - *cl= get_charset_by_name(cl_name.c_ptr(), MYF(0)); + DBUG_ASSERT(cl_name.str[cl_name.length] == 0); + *cl= get_charset_by_name(cl_name.str, MYF(0)); if (*cl == NULL) { @@ -503,6 +507,62 @@ db_find_routine_aux(THD *thd, stored_procedure_type type, } +bool st_sp_chistics::read_from_mysql_proc_row(THD *thd, TABLE *table) +{ + LEX_CSTRING str; + + if (table->field[MYSQL_PROC_FIELD_ACCESS]->val_str_nopad(thd->mem_root, + &str)) + return true; + + switch (str.str[0]) { + case 'N': + daccess= SP_NO_SQL; + break; + case 'C': + daccess= SP_CONTAINS_SQL; + break; + case 'R': + daccess= SP_READS_SQL_DATA; + break; + case 'M': + daccess= SP_MODIFIES_SQL_DATA; + break; + default: + daccess= SP_DEFAULT_ACCESS_MAPPING; + } + + if (table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->val_str_nopad(thd->mem_root, + &str)) + return true; + detistic= str.str[0] == 'N' ? false : true; + + if (table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->val_str_nopad(thd->mem_root, + &str)) + return true; + suid= str.str[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID; + + if (table->field[MYSQL_PROC_FIELD_COMMENT]->val_str_nopad(thd->mem_root, + &comment)) + return true; + + return false; +} + + +bool AUTHID::read_from_mysql_proc_row(THD *thd, TABLE *table) +{ + LEX_CSTRING str; + if (table->field[MYSQL_PROC_FIELD_DEFINER]->val_str_nopad(thd->mem_root, + &str)) + return true; + parse(str.str, str.length); + if (user.str[user.length]) + ((char *) user.str)[user.length]= '\0'; // 0-terminate if was truncated + return false; +} + + /** Find routine definition in mysql.proc table and create corresponding sp_head object for it. @@ -528,24 +588,16 @@ db_find_routine(THD *thd, stored_procedure_type type, const sp_name *name, sp_head **sphp) { TABLE *table; - const char *params, *returns, *body; + LEX_CSTRING params, returns, body; int ret; - const char *definer; longlong created; longlong modified; Sp_chistics chistics; - char *ptr; - uint length; - char buff[65]; - String str(buff, sizeof(buff), &my_charset_bin); bool saved_time_zone_used= thd->time_zone_used; sql_mode_t sql_mode, saved_mode= thd->variables.sql_mode; Open_tables_backup open_tables_state_backup; Stored_program_creation_ctx *creation_ctx; - char definer_user_name_holder[USERNAME_LENGTH + 1]; - LEX_CSTRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH }; - char definer_host_name_holder[HOSTNAME_LENGTH + 1]; - LEX_CSTRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH }; + AUTHID definer; DBUG_ENTER("db_find_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s", @@ -567,106 +619,43 @@ db_find_routine(THD *thd, stored_procedure_type type, const sp_name *name, goto done; } - if ((ptr= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL) + if (chistics.read_from_mysql_proc_row(thd, table) || + definer.read_from_mysql_proc_row(thd, table)) { ret= SP_GET_FIELD_FAILED; goto done; } - switch (ptr[0]) { - case 'N': - chistics.daccess= SP_NO_SQL; - break; - case 'C': - chistics.daccess= SP_CONTAINS_SQL; - break; - case 'R': - chistics.daccess= SP_READS_SQL_DATA; - break; - case 'M': - chistics.daccess= SP_MODIFIES_SQL_DATA; - break; - default: - chistics.daccess= SP_DEFAULT_ACCESS_MAPPING; - } - - if ((ptr= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL) - { - ret= SP_GET_FIELD_FAILED; - goto done; - } - chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE); - - if ((ptr= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL) - { - ret= SP_GET_FIELD_FAILED; - goto done; - } - chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID); - - if ((params= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL) - { - params= ""; - } + table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root, + ¶ms); if (type == TYPE_ENUM_PROCEDURE) - returns= ""; - else if ((returns= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL) + returns= empty_clex_str; + else if (table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root, + &returns)) { ret= SP_GET_FIELD_FAILED; goto done; } - if ((body= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_BODY])) == NULL) + if (table->field[MYSQL_PROC_FIELD_BODY]->val_str_nopad(thd->mem_root, + &body)) { ret= SP_GET_FIELD_FAILED; goto done; } // Get additional information - if ((definer= get_field(thd->mem_root, - table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL) - { - ret= SP_GET_FIELD_FAILED; - goto done; - } - modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int(); created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int(); - sql_mode= (ulong) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); - table->field[MYSQL_PROC_FIELD_COMMENT]->val_str(&str, &str); - - ptr= 0; - if ((length= str.length())) - ptr= thd->strmake(str.ptr(), length); - chistics.comment.str= ptr; - chistics.comment.length= length; - creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table); close_system_tables(thd, &open_tables_state_backup); table= 0; - /* It's ok to cast to char* here as the pointers are to local buffers */ - if (parse_user(definer, strlen(definer), - (char*) definer_user_name.str, &definer_user_name.length, - (char*) definer_host_name.str, &definer_host_name.length) && - definer_user_name.length && !definer_host_name.length) - { - // 'user@' -> 'user@%' - definer_host_name= host_not_specified; - } - ret= db_load_routine(thd, type, name, sphp, - sql_mode, params, returns, body, chistics, - &definer_user_name, &definer_host_name, + sql_mode, params, returns, body, chistics, definer, created, modified, creation_ctx); done: /* @@ -811,10 +800,12 @@ Bad_db_error_handler::handle_condition(THD *thd, static int db_load_routine(THD *thd, stored_procedure_type type, const sp_name *name, sp_head **sphp, - sql_mode_t sql_mode, const char *params, const char *returns, - const char *body, const st_sp_chistics &chistics, - LEX_CSTRING *definer_user_name, - LEX_CSTRING *definer_host_name, + sql_mode_t sql_mode, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + const LEX_CSTRING &body, + const st_sp_chistics &chistics, + const AUTHID &definer, longlong created, longlong modified, Stored_program_creation_ctx *creation_ctx) { @@ -843,13 +834,9 @@ db_load_routine(THD *thd, stored_procedure_type type, if (!show_create_sp(thd, &defstr, type, - NULL, 0, - name->m_name.str, name->m_name.length, - params, strlen(params), - returns, strlen(returns), - body, strlen(body), - chistics, definer_user_name, definer_host_name, - sql_mode)) + null_clex_str, name->m_name, + params, returns, body, + chistics, definer, sql_mode)) { ret= SP_INTERNAL_ERROR; goto end; @@ -900,7 +887,7 @@ db_load_routine(THD *thd, stored_procedure_type type, goto end; } - (*sphp)->set_definer(definer_user_name, definer_host_name); + (*sphp)->set_definer(&definer.user, &definer.host); (*sphp)->set_info(created, modified, chistics, sql_mode); (*sphp)->set_creation_ctx(creation_ctx); (*sphp)->optimize(); @@ -1041,6 +1028,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) DBUG_PRINT("enter", ("type: %d name: %.*s", (int) type, (int) sp->m_name.length, sp->m_name.str)); + LEX_CSTRING returns= empty_clex_str; String retstr(64); retstr.set_charset(system_charset_info); @@ -1099,7 +1087,10 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) // Setting retstr as it is used for logging. if (sp->m_type == TYPE_ENUM_FUNCTION) + { sp_returns_type(thd, retstr, sp); + returns= retstr.lex_cstring(); + } goto log; } else @@ -1177,6 +1168,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp) if (sp->m_type == TYPE_ENUM_FUNCTION) { sp_returns_type(thd, retstr, sp); + returns= retstr.lex_cstring(); store_failed= store_failed || table->field[MYSQL_PROC_FIELD_RETURNS]-> @@ -1282,16 +1274,12 @@ log: log_query.set_charset(system_charset_info); if (!show_create_sp(thd, &log_query, - sp->m_type, - (sp->m_explicit_name ? sp->m_db.str : NULL), - (sp->m_explicit_name ? sp->m_db.length : 0), - sp->m_name.str, sp->m_name.length, - sp->m_params.str, sp->m_params.length, - retstr.ptr(), retstr.length(), - sp->m_body.str, sp->m_body.length, - sp->chistics(), &(thd->lex->definer->user), - &(thd->lex->definer->host), - saved_mode)) + sp->m_type, + sp->m_explicit_name ? sp->m_db : null_clex_str, + sp->m_name, + sp->m_params, returns, sp->m_body, + sp->chistics(), thd->lex->definer[0], + saved_mode)) { my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto done; @@ -1745,7 +1733,7 @@ sp_find_routine(THD *thd, stored_procedure_type type, const sp_name *name, { ulong level; sp_head *new_sp; - const char *returns= ""; + LEX_CSTRING returns= empty_clex_str; /* String buffer for RETURNS data type must have system charset; @@ -1785,12 +1773,12 @@ sp_find_routine(THD *thd, stored_procedure_type type, const sp_name *name, if (type == TYPE_ENUM_FUNCTION) { sp_returns_type(thd, retstr, sp); - returns= retstr.ptr(); + returns= retstr.lex_cstring(); } if (db_load_routine(thd, type, name, &new_sp, - sp->m_sql_mode, sp->m_params.str, returns, - sp->m_body.str, sp->chistics(), - &sp->m_definer.user, &sp->m_definer.host, + sp->m_sql_mode, sp->m_params, returns, + sp->m_body, sp->chistics(), + sp->m_definer, sp->m_created, sp->m_modified, sp->get_creation_ctx()) == SP_OK) { @@ -2193,19 +2181,19 @@ int sp_cache_routine(THD *thd, enum stored_procedure_type type, bool show_create_sp(THD *thd, String *buf, stored_procedure_type type, - const char *db, ulong dblen, - const char *name, ulong namelen, - const char *params, ulong paramslen, - const char *returns, ulong returnslen, - const char *body, ulong bodylen, + const LEX_CSTRING &db, + const LEX_CSTRING &name, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + const LEX_CSTRING &body, const st_sp_chistics &chistics, - const LEX_CSTRING *definer_user, - const LEX_CSTRING *definer_host, + const AUTHID &definer, sql_mode_t sql_mode) { sql_mode_t old_sql_mode= thd->variables.sql_mode; /* Make some room to begin with */ - if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen + + if (buf->alloc(100 + db.length + 1 + name.length + + params.length + returns.length + chistics.comment.length + 10 /* length of " DEFINER= "*/ + USER_HOST_BUFF_SIZE)) return FALSE; @@ -2214,7 +2202,7 @@ show_create_sp(THD *thd, String *buf, buf->append(STRING_WITH_LEN("CREATE ")); if (thd->lex->create_info.or_replace()) buf->append(STRING_WITH_LEN("OR REPLACE ")); - append_definer(thd, buf, definer_user, definer_host); + append_definer(thd, buf, &definer.user, &definer.host); if (type == TYPE_ENUM_FUNCTION) buf->append(STRING_WITH_LEN("FUNCTION ")); else @@ -2222,14 +2210,14 @@ show_create_sp(THD *thd, String *buf, if (thd->lex->create_info.if_not_exists()) buf->append(STRING_WITH_LEN("IF NOT EXISTS ")); - if (dblen > 0) + if (db.length > 0) { - append_identifier(thd, buf, db, dblen); + append_identifier(thd, buf, db.str, db.length); buf->append('.'); } - append_identifier(thd, buf, name, namelen); + append_identifier(thd, buf, name.str, name.length); buf->append('('); - buf->append(params, paramslen); + buf->append(params); buf->append(')'); if (type == TYPE_ENUM_FUNCTION) { @@ -2237,7 +2225,7 @@ show_create_sp(THD *thd, String *buf, buf->append(STRING_WITH_LEN(" RETURN ")); else buf->append(STRING_WITH_LEN(" RETURNS ")); - buf->append(returns, returnslen); + buf->append(returns); } buf->append('\n'); switch (chistics.daccess) { @@ -2265,12 +2253,21 @@ show_create_sp(THD *thd, String *buf, append_unescaped(buf, chistics.comment.str, chistics.comment.length); buf->append('\n'); } - buf->append(body, bodylen); + buf->append(body); thd->variables.sql_mode= old_sql_mode; return TRUE; } +static LEX_CSTRING empty_body_lex_cstring(stored_procedure_type type) +{ + static LEX_CSTRING empty_body_func= {C_STRING_WITH_LEN("RETURN NULL")}; + static LEX_CSTRING empty_body_proc= {C_STRING_WITH_LEN("BEGIN END")}; + return type == TYPE_ENUM_FUNCTION ? empty_body_func : + empty_body_proc; +} + + /** @brief The function loads sp_head struct for information schema purposes (used for I_S ROUTINES & PARAMETERS tables). @@ -2292,26 +2289,21 @@ show_create_sp(THD *thd, String *buf, */ sp_head * -sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, - String *name, sql_mode_t sql_mode, +sp_load_for_information_schema(THD *thd, TABLE *proc_table, stored_procedure_type type, - const char *returns, const char *params, + const LEX_CSTRING &db, + const LEX_CSTRING &name, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + sql_mode_t sql_mode, bool *free_sp_head) { - const char *sp_body; String defstr; - const LEX_CSTRING definer_user= {STRING_WITH_LEN("")}; - const LEX_CSTRING definer_host= {STRING_WITH_LEN("")}; - LEX_CSTRING sp_db_str; - LEX_CSTRING sp_name_str; + const AUTHID definer= {{STRING_WITH_LEN("")}, {STRING_WITH_LEN("")}}; sp_head *sp; sp_cache **spc= ((type == TYPE_ENUM_PROCEDURE) ? &thd->sp_proc_cache : &thd->sp_func_cache); - sp_db_str.str= db->c_ptr(); - sp_db_str.length= db->length(); - sp_name_str.str= name->c_ptr(); - sp_name_str.length= name->length(); - sp_name sp_name_obj(&sp_db_str, &sp_name_str, true); + sp_name sp_name_obj(&db, &name, true); *free_sp_head= 0; if ((sp= sp_cache_lookup(spc, &sp_name_obj))) { @@ -2321,15 +2313,11 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, LEX *old_lex= thd->lex, newlex; Stored_program_creation_ctx *creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table); - sp_body= (type == TYPE_ENUM_FUNCTION ? "RETURN NULL" : "BEGIN END"); defstr.set_charset(creation_ctx->get_client_cs()); if (!show_create_sp(thd, &defstr, type, - sp_db_str.str, sp_db_str.length, - sp_name_obj.m_name.str, sp_name_obj.m_name.length, - params, strlen(params), - returns, strlen(returns), - sp_body, strlen(sp_body), - Sp_chistics(), &definer_user, &definer_host, sql_mode)) + sp_name_obj.m_db, sp_name_obj.m_name, + params, returns, empty_body_lex_cstring(type), + Sp_chistics(), definer, sql_mode)) return 0; thd->lex= &newlex; @@ -213,10 +213,13 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, TABLE *open_proc_table_for_read(THD *thd, Open_tables_backup *backup); sp_head * -sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, - String *name, sql_mode_t sql_mode, +sp_load_for_information_schema(THD *thd, TABLE *proc_table, stored_procedure_type type, - const char *returns, const char *params, + const LEX_CSTRING &db, + const LEX_CSTRING &name, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + sql_mode_t sql_mode, bool *free_sp_head); bool load_charset(MEM_ROOT *mem_root, @@ -234,14 +237,13 @@ void sp_returns_type(THD *thd, sp_head *sp); bool show_create_sp(THD *thd, String *buf, - stored_procedure_type type, - const char *db, ulong dblen, - const char *name, ulong namelen, - const char *params, ulong paramslen, - const char *returns, ulong returnslen, - const char *body, ulong bodylen, - const st_sp_chistics &chistics, - const LEX_CSTRING *definer_user, - const LEX_CSTRING *definer_host, - sql_mode_t sql_mode); + stored_procedure_type type, + const LEX_CSTRING &db, + const LEX_CSTRING &name, + const LEX_CSTRING ¶ms, + const LEX_CSTRING &returns, + const LEX_CSTRING &body, + const st_sp_chistics &chistics, + const AUTHID &definer, + sql_mode_t sql_mode); #endif /* _SP_H_ */ diff --git a/sql/sp_head.cc b/sql/sp_head.cc index bb3275316cc..ad45ccdc92e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2459,27 +2459,6 @@ sp_head::set_info(longlong created, longlong modified, void -sp_head::set_definer(const char *definer, uint definerlen) -{ - char user_name_holder[USERNAME_LENGTH + 1]; - LEX_CSTRING user_name= { user_name_holder, USERNAME_LENGTH }; - - char host_name_holder[HOSTNAME_LENGTH + 1]; - LEX_CSTRING host_name= { host_name_holder, HOSTNAME_LENGTH }; - - if (parse_user(definer, definerlen, user_name_holder, &user_name.length, - host_name_holder, &host_name.length) && - user_name.length && !host_name.length) - { - // 'user@' -> 'user@%' - host_name= host_not_specified; - } - - set_definer(&user_name, &host_name); -} - - -void sp_head::reset_thd_mem_root(THD *thd) { DBUG_ENTER("sp_head::reset_thd_mem_root"); diff --git a/sql/sp_head.h b/sql/sp_head.h index 1435bb460c3..f17a918cf50 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -689,7 +689,12 @@ public: void set_info(longlong created, longlong modified, const st_sp_chistics &chistics, sql_mode_t sql_mode); - void set_definer(const char *definer, uint definerlen); + void set_definer(const char *definer, uint definerlen) + { + AUTHID tmp; + tmp.parse(definer, definerlen); + m_definer.copy(mem_root, &tmp.user, &tmp.host); + } void set_definer(const LEX_CSTRING *user_name, const LEX_CSTRING *host_name) { m_definer.copy(mem_root, user_name, host_name); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c33f01d0084..55742f7aaec 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -7475,4 +7475,34 @@ void AUTHID::copy(MEM_ROOT *mem_root, const LEX_CSTRING *user_name, } +/* + Set from a string in 'user@host' format. + This method resebmles parse_user(), + but does not need temporary buffers. +*/ +void AUTHID::parse(const char *str, size_t length) +{ + const char *p= strrchr(str, '@'); + if (!p) + { + user.str= str; + user.length= length; + host= null_clex_str; + } + else + { + user.str= str; + user.length= (size_t) (p - str); + host.str= p + 1; + host.length= (size_t) (length - user.length - 1); + if (user.length && !host.length) + host= host_not_specified; // 'user@' -> 'user@%' + } + if (user.length > USERNAME_LENGTH) + user.length= USERNAME_LENGTH; + if (host.length > HOSTNAME_LENGTH) + host.length= HOSTNAME_LENGTH; +} + + #endif /* !defined(MYSQL_CLIENT) */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 3c7c99dff3d..c1351b110f6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1287,6 +1287,7 @@ struct st_sp_chistics enum enum_sp_data_access daccess; void init() { bzero(this, sizeof(*this)); } void set(const st_sp_chistics &other) { *this= other; } + bool read_from_mysql_proc_row(THD *thd, TABLE *table); }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index fd0d11bf1bb..de7f93ca901 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5876,14 +5876,9 @@ 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; bool free_sp_head; @@ -5894,48 +5889,44 @@ bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_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); + 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); routine_type= (stored_procedure_type) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int(); 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(), + check_some_routine_access(thd, db.str, name.str, routine_type == TYPE_ENUM_PROCEDURE)) DBUG_RETURN(0); - params.length(0); - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST], - ¶ms); - returns.length(0); + proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST]->val_str_nopad(thd->mem_root, + ¶ms); if (routine_type == TYPE_ENUM_FUNCTION) - get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_RETURNS], - &returns); + proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root, + &returns); - sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name, + sp= sp_load_for_information_schema(thd, proc_table, routine_type, db, name, + params, returns, (ulong) proc_table-> field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(), - routine_type, - returns.c_ptr_safe(), - params.c_ptr_safe(), &free_sp_head); if (sp) { Field *field; - String tmp_string; + LEX_CSTRING tmp_string; if (routine_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); + 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; @@ -5973,16 +5964,16 @@ 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); @@ -6009,23 +6000,16 @@ 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]; + LEX_CSTRING db, name, definer, returns= empty_clex_str; - 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); + 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); 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(), + check_some_routine_access(thd, db.str, name.str, proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> val_int() == TYPE_ENUM_PROCEDURE)) return 0; @@ -6040,15 +6024,15 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, { 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]); @@ -6057,14 +6041,16 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, { 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, + proc_table->field[MYSQL_PROC_FIELD_RETURNS]->val_str_nopad(thd->mem_root, + &returns); + sp= sp_load_for_information_schema(thd, proc_table, + TYPE_ENUM_FUNCTION, db, name, + empty_clex_str /*params*/, + returns, (ulong) proc_table-> field[MYSQL_PROC_FIELD_SQL_MODE]-> val_int(), - TYPE_ENUM_FUNCTION, - returns.c_ptr_safe(), - "", &free_sp_head); + &free_sp_head); if (sp) { @@ -6115,7 +6101,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]); diff --git a/sql/sql_string.h b/sql/sql_string.h index 845ed4c9746..adaef04fee4 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -471,6 +471,7 @@ public: bool append(const char *s); bool append(const LEX_STRING *ls) { return append(ls->str, ls->length); } bool append(const LEX_CSTRING *ls) { return append(ls->str, ls->length); } + bool append(const LEX_CSTRING &ls) { return append(ls.str, ls.length); } bool append(const char *s, uint32 arg_length); bool append(const char *s, uint32 arg_length, CHARSET_INFO *cs); bool append_ulonglong(ulonglong val); diff --git a/sql/structs.h b/sql/structs.h index 982eda99d30..97702e5727b 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -221,6 +221,8 @@ struct AUTHID l->length= strxmov(buf, user.str, "@", host.str, NullS) - buf; } } + void parse(const char *str, size_t length); + bool read_from_mysql_proc_row(THD *thd, TABLE *table); }; diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 87eb97e4fec..d3726cc86a5 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2236,6 +2236,7 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) sp_head *sp = thd->lex->sphead; sql_mode_t saved_mode= thd->variables.sql_mode; String retstr(64); + LEX_CSTRING returns= empty_clex_str; retstr.set_charset(system_charset_info); log_query.set_charset(system_charset_info); @@ -2243,19 +2244,15 @@ static int wsrep_create_sp(THD *thd, uchar** buf, size_t* buf_len) if (sp->m_type == TYPE_ENUM_FUNCTION) { sp_returns_type(thd, retstr, sp); + returns= retstr.lex_cstring(); } if (!show_create_sp(thd, &log_query, - sp->m_type, - (sp->m_explicit_name ? sp->m_db.str : NULL), - (sp->m_explicit_name ? sp->m_db.length : 0), - sp->m_name.str, sp->m_name.length, - sp->m_params.str, sp->m_params.length, - retstr.c_ptr(), retstr.length(), - sp->m_body.str, sp->m_body.length, - sp->chistics(), &(thd->lex->definer->user), - &(thd->lex->definer->host), - saved_mode)) + sp->m_type, + sp->m_explicit_name ? sp->m_db : null_clex_str, + sp->m_name, sp->m_params, returns, + sp->m_body, sp->chistics(), thd->lex->definer[0], + saved_mode)) { WSREP_WARN("SP create string failed: schema: %s, query: %s", (thd->db ? thd->db : "(null)"), thd->query()); |