diff --git a/mysql-test/r/func_digest.result b/mysql-test/r/func_digest.result index bd0c43f4cfe..0070fdc6933 100644 --- a/mysql-test/r/func_digest.result +++ b/mysql-test/r/func_digest.result @@ -2008,3 +2008,18 @@ SHOW variables LIKE 'character_set_client'; Variable_name Value character_set_client latin1 SET NAMES DEFAULT; +# +# Bug STATEMENT_DIGEST() adds trailing semicolon to digest +# +SELECT statement_digest('select 1;'); +statement_digest('select 1;') +d1b44b0c19af710b5a679907e284acd2ddc285201794bc69a2389d77baedddae +SELECT statement_digest('select 1'); +statement_digest('select 1') +d1b44b0c19af710b5a679907e284acd2ddc285201794bc69a2389d77baedddae +SELECT statement_digest_text('select 1;'); +statement_digest_text('select 1;') +SELECT ? +SELECT statement_digest_text('select 1'); +statement_digest_text('select 1') +SELECT ? diff --git a/mysql-test/t/func_digest.test b/mysql-test/t/func_digest.test index 5fef2810b12..6ab50acbcde 100644 --- a/mysql-test/t/func_digest.test +++ b/mysql-test/t/func_digest.test @@ -786,3 +786,11 @@ SELECT substr(hex(statement_digest_text(CONVERT(@v USING latin1))), -6, 4); SHOW variables LIKE 'character_set_client'; SET NAMES DEFAULT; + +--echo # +--echo # Bug STATEMENT_DIGEST() adds trailing semicolon to digest +--echo # +SELECT statement_digest('select 1;'); +SELECT statement_digest('select 1'); +SELECT statement_digest_text('select 1;'); +SELECT statement_digest_text('select 1'); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 84a3d6edd0b..eb92aae978e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -993,12 +993,27 @@ bool parse(THD *thd, Item *statement_expr, String *statement_string) { thd->variables.character_set_client = cs; thd->update_charset(); - Parser_state ps; - // The lexer needs null-terminated strings, despite boasting the below // interface. Hence the use of c_ptr_safe(). - if (ps.init(thd, statement_string->c_ptr_safe(), statement_string->length())) - return true; + char *query = statement_string->c_ptr_safe(); + size_t length = statement_string->length(); + + /* Remove garbage at start and end of query. See also alloc_query(). */ + while (length > 0 && my_isspace(cs, query[0])) { + query++; + length--; + } + const char *pos = query + length; // Point at end null + while (length > 0 && + (pos[-1] == ';' || my_isspace(cs, pos[-1]))) { + pos--; + length--; + } + query[length] = '\0'; + + Parser_state ps; + + if (ps.init(thd, query, length)) return true; ps.m_lip.multi_statements = false; ps.m_lip.m_digest = thd->m_digest;