summaryrefslogtreecommitdiff
path: root/sql/sp.cc
diff options
context:
space:
mode:
authorunknown <cmiller@zippy.cornsilk.net>2008-05-15 19:13:24 -0400
committerunknown <cmiller@zippy.cornsilk.net>2008-05-15 19:13:24 -0400
commit55012e427bc4b3b6a5ffa070e229c519c8cd0b98 (patch)
tree9d471bf2b51fee92b75f3377d183d2a680bb91c9 /sql/sp.cc
parentab6e91cf3af9ef3d69e80420eef1ada05d66b9f7 (diff)
downloadmariadb-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.cc62
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(')');