From fb0d88619a6983444b5ef4fdb90944861a2e8190 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 May 2008 19:23:54 -0400 Subject: Bug#36570: Parse error of CREATE PROCEDURE stmt with comments on \ slave The stored-routine code took the contents of the (lowest) parser and copied it directly to the binlog, which causes problems if there is a special case of interpretation at the parser level -- which there is, in the "/*!VER */" comments. The trailing "*/" caused errors on the slave, naturally. Now, since by that point we have /properly/ created parse-tree (as the rest of the server should do!) for the stored-routine CREATE, we can construct a perfect statement from that information, instead of writing uncertain information from an unknown parser state. Fortunately, there's already a function nearby that does exactly that. mysql-test/r/binlog_innodb.result: Offsets changed due to quoting. mysql-test/r/ctype_cp932_binlog.result: Offsets changed due to quoting. mysql-test/r/mysqlbinlog.result: Case changed in result due to interpretation of data instead of literal recitation. mysql-test/r/rpl_sp.result: Offsets changed due to quoting. Added tests. mysql-test/t/rpl_sp.test: Add version-limiting quotes to exercise bug#36570. Test that backtick-quoted identifiers and labels work also. sql/sp.cc: In create_string, we may not have a sp_name parameter yet, so instead pass the char* and length of the only member we'd get out of it. Having done that, we can use the same function to write the CREATE (FUNC|TRIG|PROC) statement to the binlog as we always used to display the statement to the user. --- sql/sp.cc | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'sql/sp.cc') diff --git a/sql/sp.cc b/sql/sp.cc index 7224d3c4f0e..390a23b91b1 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -25,7 +25,7 @@ static bool create_string(THD *thd, String *buf, int sp_type, - sp_name *name, + const char *name, ulong namelen, const char *params, ulong paramslen, const char *returns, ulong returnslen, const char *body, ulong bodylen, @@ -427,7 +427,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, if (!create_string(thd, &defstr, type, - name, + name->m_name.str, name->m_name.length, params, strlen(params), returns, strlen(returns), body, strlen(body), @@ -518,6 +518,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) DBUG_ENTER("db_create_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s",type,sp->m_name.length, sp->m_name.str)); + String retstr(64); if (!(table= open_proc_table_for_update(thd))) ret= SP_OPEN_TABLE_FAILED; @@ -568,7 +569,6 @@ db_create_routine(THD *thd, int type, sp_head *sp) store(sp->m_params.str, sp->m_params.length, system_charset_info); if (sp->m_type == TYPE_ENUM_FUNCTION) { - String retstr(64); sp_returns_type(thd, retstr, sp); table->field[MYSQL_PROC_FIELD_RETURNS]-> store(retstr.ptr(), retstr.length(), system_charset_info); @@ -625,13 +625,19 @@ db_create_routine(THD *thd, int type, sp_head *sp) String log_query; log_query.set_charset(system_charset_info); - log_query.append(STRING_WITH_LEN("CREATE ")); - append_definer(thd, &log_query, &thd->lex->definer->user, - &thd->lex->definer->host); - log_query.append(thd->lex->stmt_definition_begin, - (char *)sp->m_body_begin - - thd->lex->stmt_definition_begin + - sp->m_body.length); + + if (!create_string(thd, &log_query, + sp->m_type, + 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->m_chistics, &(thd->lex->definer->user), + &(thd->lex->definer->host))) + { + ret= SP_INTERNAL_ERROR; + goto done; + } /* Such a statement can always go directly to binlog, no trans cache */ Query_log_event qinfo(thd, log_query.c_ptr(), log_query.length(), 0, @@ -1798,7 +1804,7 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, static bool create_string(THD *thd, String *buf, int type, - sp_name *name, + const char *name, ulong namelen, const char *params, ulong paramslen, const char *returns, ulong returnslen, const char *body, ulong bodylen, @@ -1807,7 +1813,7 @@ create_string(THD *thd, String *buf, const LEX_STRING *definer_host) { /* Make some room to begin with */ - if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen + + if (buf->alloc(100 + namelen + paramslen + returnslen + bodylen + chistics->comment.length + 10 /* length of " DEFINER= "*/ + USER_HOST_BUFF_SIZE)) return FALSE; @@ -1818,7 +1824,7 @@ create_string(THD *thd, String *buf, buf->append(STRING_WITH_LEN("FUNCTION ")); else buf->append(STRING_WITH_LEN("PROCEDURE ")); - append_identifier(thd, buf, name->m_name.str, name->m_name.length); + append_identifier(thd, buf, name, namelen); buf->append('('); buf->append(params, paramslen); buf->append(')'); -- cgit v1.2.1