diff options
author | unknown <cmiller@zippy.cornsilk.net> | 2008-05-15 19:13:24 -0400 |
---|---|---|
committer | unknown <cmiller@zippy.cornsilk.net> | 2008-05-15 19:13:24 -0400 |
commit | 55012e427bc4b3b6a5ffa070e229c519c8cd0b98 (patch) | |
tree | 9d471bf2b51fee92b75f3377d183d2a680bb91c9 /sql/sp.cc | |
parent | ab6e91cf3af9ef3d69e80420eef1ada05d66b9f7 (diff) | |
download | mariadb-git-55012e427bc4b3b6a5ffa070e229c519c8cd0b98.tar.gz |
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.
---
Update for Bug#36570. Qualify routine names with db name when
writing to the binlog ONLY if the source text is qualified.
mysql-test/r/binlog_innodb.result:
Offsets changed due to quoting.
---
New offset to account for db-qualified names.
mysql-test/r/ctype_cp932_binlog.result:
Offsets changed due to quoting.
---
Qualify routine names with DB. Offsets change also.
mysql-test/r/mysqlbinlog.result:
Case changed in result due to interpretation of data instead of
literal recitation.
---
Qualify procedure name with db.
mysql-test/r/rpl_sp.result:
Offsets changed due to quoting. Added tests.
---
Qualify routine names with DB if qualified in query. Offsets change also.
mysql-test/t/rpl_sp.test:
Add version-limiting quotes to exercise bug#36570. Test that
backtick-quoted identifiers and labels work also.
---
Use different db to show qualification works. Qualify routine names
with DB if qualified in query.
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.
---
Make the db name part of the CREATE string if it is specified.
Specify it in part of writing to the binlog when creating a new
routine.
sql/sp_head.cc:
Set the sp_head m_explicit_name member as the sp_name member is set.
We can not peek at this later, as the sp_name is gone by then.
sql/sp_head.h:
Add a member to track whether the name is qualified with the
database.
Diffstat (limited to 'sql/sp.cc')
-rw-r--r-- | sql/sp.cc | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/sql/sp.cc b/sql/sp.cc index 7224d3c4f0e..2392cabb220 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -25,7 +25,8 @@ static bool create_string(THD *thd, String *buf, int sp_type, - sp_name *name, + 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, @@ -426,12 +427,13 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, */ if (!create_string(thd, &defstr, - type, - name, - params, strlen(params), - returns, strlen(returns), - body, strlen(body), - &chistics, &definer_user_name, &definer_host_name)) + 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)) { ret= SP_INTERNAL_ERROR; goto end; @@ -518,6 +520,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 +571,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 +627,21 @@ 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_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->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, @@ -1797,17 +1807,18 @@ 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 *params, ulong paramslen, - const char *returns, ulong returnslen, - const char *body, ulong bodylen, - st_sp_chistics *chistics, + int 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, + st_sp_chistics *chistics, const LEX_STRING *definer_user, 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 + dblen + 1 + namelen + paramslen + returnslen + bodylen + chistics->comment.length + 10 /* length of " DEFINER= "*/ + USER_HOST_BUFF_SIZE)) return FALSE; @@ -1818,7 +1829,12 @@ 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); + if (dblen > 0) + { + append_identifier(thd, buf, db, dblen); + buf->append('.'); + } + append_identifier(thd, buf, name, namelen); buf->append('('); buf->append(params, paramslen); buf->append(')'); |