Commit 6762a651 authored by unknown's avatar unknown

Fixed BUG#2564: SHOW CREATE inconsistent W.R.T ANSI_QUOTES.

It's not possible to quote the definition according to the current sql_mode
setting, so instead we use the setting stored with the SP (that's how it's
parsed anyway), and show this setting in the SHOW CREATE output.


mysql-test/r/sp.result:
  Modifed SHOW CREATE FUNCTION|PROCEDURE output. Show the sql_mode used at
  creation as well.
  New test case for BUG#2564: SHOW CREATE inconsistent W.R.T ANSI_QUOTES.
mysql-test/t/sp.test:
  New test case for BUG#2564: SHOW CREATE inconsistent W.R.T ANSI_QUOTES.
sql/sp.cc:
  Rewrote create_string to quote things correctly according to the sql_mode
  used at creation time.
sql/sp_head.cc:
  Store sql_mode in sp_head and use it for SHOW CREATE.
sql/sp_head.h:
  Store sql_mode in sp_head and use it for SHOW CREATE.
parent 54e3909b
...@@ -734,7 +734,7 @@ chistics 1 ...@@ -734,7 +734,7 @@ chistics 1
delete from t1| delete from t1|
alter procedure chistics sql security invoker name chistics2| alter procedure chistics sql security invoker name chistics2|
show create procedure chistics2| show create procedure chistics2|
Procedure Create Procedure Procedure sql_mode Create Procedure
chistics2 CREATE PROCEDURE `test`.`chistics2`() chistics2 CREATE PROCEDURE `test`.`chistics2`()
SQL SECURITY INVOKER SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test' COMMENT 'Characteristics procedure test'
...@@ -751,7 +751,7 @@ chistics() ...@@ -751,7 +751,7 @@ chistics()
42 42
alter function chistics name chistics2 comment 'Characteristics function test'| alter function chistics name chistics2 comment 'Characteristics function test'|
show create function chistics2| show create function chistics2|
Function Create Function Function sql_mode Create Function
chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int chistics2 CREATE FUNCTION `test`.`chistics2`() RETURNS int
DETERMINISTIC DETERMINISTIC
SQL SECURITY INVOKER SQL SECURITY INVOKER
...@@ -980,13 +980,13 @@ call bug2267_2()| ...@@ -980,13 +980,13 @@ call bug2267_2()|
Db Name Type Definer Modified Created Security_type Comment Db Name Type Definer Modified Created Security_type Comment
test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER test fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call bug2267_3()| call bug2267_3()|
Procedure Create Procedure Procedure sql_mode Create Procedure
bug2267_1 CREATE PROCEDURE `test`.`bug2267_1`() bug2267_1 CREATE PROCEDURE `test`.`bug2267_1`()
begin begin
show procedure status; show procedure status;
end end
call bug2267_4()| call bug2267_4()|
Function Create Function Function sql_mode Create Function
fac CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint unsigned fac CREATE FUNCTION `test`.`fac`(n int unsigned) RETURNS bigint unsigned
begin begin
declare f bigint unsigned default 1; declare f bigint unsigned default 1;
...@@ -1318,6 +1318,41 @@ s1 ...@@ -1318,6 +1318,41 @@ s1
drop procedure bug2460_1| drop procedure bug2460_1|
drop procedure bug2460_2| drop procedure bug2460_2|
drop table t3| drop table t3|
set @@sql_mode = ''|
create procedure bug2564_1()
comment 'Joe''s procedure'
insert into `t1` values ("foo", 1)|
set @@sql_mode = 'ANSI_QUOTES'|
create procedure bug2564_2()
insert into "t1" values ('foo', 1)|
set @@sql_mode = ''$
create function bug2564_3(x int, y int) returns int
return x || y$
set @@sql_mode = 'ANSI'$
create function bug2564_4(x int, y int) returns int
return x || y$
set @@sql_mode = ''|
show create procedure bug2564_1|
Procedure sql_mode Create Procedure
bug2564_1 CREATE PROCEDURE `test`.`bug2564_1`()
COMMENT 'Joe''s procedure'
insert into `t1` values ("foo", 1)
show create procedure bug2564_2|
Procedure sql_mode Create Procedure
bug2564_2 ANSI_QUOTES CREATE PROCEDURE "test"."bug2564_2"()
insert into "t1" values ('foo', 1)
show create function bug2564_3|
Function sql_mode Create Function
bug2564_3 CREATE FUNCTION `test`.`bug2564_3`(x int, y int) RETURNS int
return x || y
show create function bug2564_4|
Function sql_mode Create Function
bug2564_4 REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI CREATE FUNCTION "test"."bug2564_4"(x int, y int) RETURNS int
return x || y
drop procedure bug2564_1|
drop procedure bug2564_2|
drop function bug2564_3|
drop function bug2564_4|
drop table if exists fac| drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)| create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned) create procedure ifac(n int unsigned)
...@@ -1423,7 +1458,7 @@ end; ...@@ -1423,7 +1458,7 @@ end;
end while; end while;
end| end|
show create procedure opp| show create procedure opp|
Procedure Create Procedure Procedure sql_mode Create Procedure
opp CREATE PROCEDURE `test`.`opp`(n bigint unsigned, out pp bool) opp CREATE PROCEDURE `test`.`opp`(n bigint unsigned, out pp bool)
begin begin
declare r double; declare r double;
...@@ -1520,7 +1555,7 @@ alter procedure bar name bar2 comment "2222222222" sql security definer| ...@@ -1520,7 +1555,7 @@ alter procedure bar name bar2 comment "2222222222" sql security definer|
alter procedure bar2 name bar comment "3333333333"| alter procedure bar2 name bar comment "3333333333"|
alter procedure bar| alter procedure bar|
show create procedure bar| show create procedure bar|
Procedure Create Procedure Procedure sql_mode Create Procedure
bar CREATE PROCEDURE `test`.`bar`(x char(16), y int) bar CREATE PROCEDURE `test`.`bar`(x char(16), y int)
COMMENT '3333333333' COMMENT '3333333333'
insert into test.t1 values (x, y) insert into test.t1 values (x, y)
......
...@@ -1518,6 +1518,40 @@ drop procedure bug2460_2| ...@@ -1518,6 +1518,40 @@ drop procedure bug2460_2|
drop table t3| drop table t3|
#
# BUG#2564
#
set @@sql_mode = ''|
create procedure bug2564_1()
comment 'Joe''s procedure'
insert into `t1` values ("foo", 1)|
set @@sql_mode = 'ANSI_QUOTES'|
create procedure bug2564_2()
insert into "t1" values ('foo', 1)|
delimiter $|
set @@sql_mode = ''$
create function bug2564_3(x int, y int) returns int
return x || y$
set @@sql_mode = 'ANSI'$
create function bug2564_4(x int, y int) returns int
return x || y$
delimiter |$
set @@sql_mode = ''|
show create procedure bug2564_1|
show create procedure bug2564_2|
show create function bug2564_3|
show create function bug2564_4|
drop procedure bug2564_1|
drop procedure bug2564_2|
drop function bug2564_3|
drop function bug2564_4|
# #
# Some "real" examples # Some "real" examples
# #
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include "sp_head.h" #include "sp_head.h"
#include "sp_cache.h" #include "sp_cache.h"
static char * static bool
create_string(THD *thd, ulong *lenp, create_string(THD *thd, String *buf,
int sp_type, int sp_type,
sp_name *name, sp_name *name,
const char *params, ulong paramslen, const char *params, ulong paramslen,
...@@ -215,8 +215,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -215,8 +215,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
} }
{ {
char *defstr; String defstr;
ulong deflen;
LEX *oldlex= thd->lex; LEX *oldlex= thd->lex;
char olddb[128]; char olddb[128];
bool dbchanged; bool dbchanged;
...@@ -227,13 +226,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -227,13 +226,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
thd->variables.sql_mode= sql_mode; thd->variables.sql_mode= sql_mode;
thd->variables.select_limit= HA_POS_ERROR; thd->variables.select_limit= HA_POS_ERROR;
if (!(defstr= create_string(thd, &deflen, defstr.set_charset(system_charset_info);
if (!create_string(thd, &defstr,
type, type,
name, name,
params, strlen(params), params, strlen(params),
returns, strlen(returns), returns, strlen(returns),
body, strlen(body), body, strlen(body),
&chistics))) &chistics))
{ {
ret= SP_INTERNAL_ERROR; ret= SP_INTERNAL_ERROR;
goto done; goto done;
...@@ -254,7 +254,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -254,7 +254,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
List<Item> vals= thd->lex->value_list; List<Item> vals= thd->lex->value_list;
mysql_init_query(thd, TRUE); mysql_init_query(thd, TRUE);
lex_start(thd, (uchar*)defstr, deflen); lex_start(thd, (uchar*)defstr.c_ptr(), defstr.length());
thd->lex->value_list= vals; thd->lex->value_list= vals;
} }
...@@ -280,7 +280,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -280,7 +280,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
goto done; goto done;
*sphp= thd->lex->sphead; *sphp= thd->lex->sphead;
(*sphp)->set_info((char *)definer, (uint)strlen(definer), (*sphp)->set_info((char *)definer, (uint)strlen(definer),
created, modified, &chistics); created, modified, &chistics, sql_mode);
} }
thd->lex->sql_command= oldcmd; thd->lex->sql_command= oldcmd;
thd->variables.sql_mode= old_sql_mode; thd->variables.sql_mode= old_sql_mode;
...@@ -941,9 +941,12 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -941,9 +941,12 @@ sp_cache_functions(THD *thd, LEX *lex)
return ret; return ret;
} }
/*
static char * * Generates the CREATE... string from the table information.
create_string(THD *thd, ulong *lenp, * Returns TRUE on success, FALSE on (alloc) failure.
*/
static bool
create_string(THD *thd, String *buf,
int type, int type,
sp_name *name, sp_name *name,
const char *params, ulong paramslen, const char *params, ulong paramslen,
...@@ -951,35 +954,40 @@ create_string(THD *thd, ulong *lenp, ...@@ -951,35 +954,40 @@ create_string(THD *thd, ulong *lenp,
const char *body, ulong bodylen, const char *body, ulong bodylen,
st_sp_chistics *chistics) st_sp_chistics *chistics)
{ {
char *buf, *ptr; /* Make some room to begin with */
ulong buflen; if (buf->alloc(100 + name->m_qname.length + paramslen + returnslen + bodylen +
chistics->comment.length))
buflen= 100 + name->m_qname.length + paramslen + returnslen + bodylen + return FALSE;
chistics->comment.length;
if (!(buf= thd->alloc(buflen)))
return 0;
ptr= strxmov(buf, "CREATE ",
(type == TYPE_ENUM_FUNCTION) ? "FUNCTION" : "PROCEDURE",
" `", name->m_db.str, "`.`", name->m_name.str, "`(", params, ")",
NullS);
buf->append("CREATE ", 7);
if (type == TYPE_ENUM_FUNCTION) if (type == TYPE_ENUM_FUNCTION)
ptr= strxmov(ptr, " RETURNS ", returns, NullS); buf->append("FUNCTION ", 9);
*ptr++= '\n'; else
buf->append("PROCEDURE ", 10);
append_identifier(thd, buf, name->m_db.str, name->m_db.length);
buf->append('.');
append_identifier(thd, buf, name->m_name.str, name->m_name.length);
buf->append('(');
buf->append(params, paramslen);
buf->append(')');
if (type == TYPE_ENUM_FUNCTION)
{
buf->append(" RETURNS ", 9);
buf->append(returns, returnslen);
}
buf->append('\n');
if (chistics->detistic) if (chistics->detistic)
ptr= strmov(ptr, " DETERMINISTIC\n"); buf->append( " DETERMINISTIC\n", 18);
if (chistics->suid == IS_NOT_SUID) if (chistics->suid == IS_NOT_SUID)
ptr= strmov(ptr, " SQL SECURITY INVOKER\n"); buf->append(" SQL SECURITY INVOKER\n", 25);
if (chistics->comment.length) if (chistics->comment.length)
{ {
ptr= strmov(strnmov(strmov(ptr, " COMMENT '"),chistics->comment.str, buf->append(" COMMENT ");
chistics->comment.length),"'\n"); append_unescaped(buf, chistics->comment.str, chistics->comment.length);
buf->append('\n');
} }
ptr= strmov(ptr, body); buf->append(body, bodylen);
*lenp= (ptr-buf); return TRUE;
return buf;
} }
......
...@@ -780,7 +780,7 @@ sp_head::backpatch(sp_label_t *lab) ...@@ -780,7 +780,7 @@ sp_head::backpatch(sp_label_t *lab)
void void
sp_head::set_info(char *definer, uint definerlen, sp_head::set_info(char *definer, uint definerlen,
longlong created, longlong modified, longlong created, longlong modified,
st_sp_chistics *chistics) st_sp_chistics *chistics, ulong sql_mode)
{ {
char *p= strchr(definer, '@'); char *p= strchr(definer, '@');
uint len; uint len;
...@@ -803,6 +803,7 @@ sp_head::set_info(char *definer, uint definerlen, ...@@ -803,6 +803,7 @@ sp_head::set_info(char *definer, uint definerlen,
m_chistics->comment.str= strmake_root(&mem_root, m_chistics->comment.str= strmake_root(&mem_root,
m_chistics->comment.str, m_chistics->comment.str,
m_chistics->comment.length); m_chistics->comment.length);
m_sql_mode= sql_mode;
} }
void void
...@@ -846,21 +847,44 @@ sp_head::show_create_procedure(THD *thd) ...@@ -846,21 +847,44 @@ sp_head::show_create_procedure(THD *thd)
String buffer(buff, sizeof(buff), system_charset_info); String buffer(buff, sizeof(buff), system_charset_info);
int res; int res;
List<Item> field_list; List<Item> field_list;
ulong old_sql_mode;
sys_var *sql_mode_var;
byte *sql_mode_str;
ulong sql_mode_len;
DBUG_ENTER("sp_head::show_create_procedure"); DBUG_ENTER("sp_head::show_create_procedure");
DBUG_PRINT("info", ("procedure %s", m_name.str)); DBUG_PRINT("info", ("procedure %s", m_name.str));
field_list.push_back(new Item_empty_string("Procedure",NAME_LEN)); old_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
sql_mode_var= find_sys_var("SQL_MODE", 8);
if (sql_mode_var)
{
sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
sql_mode_len= strlen(sql_mode_str);
}
field_list.push_back(new Item_empty_string("Procedure", NAME_LEN));
if (sql_mode_var)
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
// 1024 is for not to confuse old clients // 1024 is for not to confuse old clients
field_list.push_back(new Item_empty_string("Create Procedure", field_list.push_back(new Item_empty_string("Create Procedure",
max(buffer.length(),1024))); max(buffer.length(), 1024)));
if (protocol->send_fields(&field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1); {
res= 1;
goto done;
}
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info); protocol->store(m_name.str, m_name.length, system_charset_info);
if (sql_mode_var)
protocol->store(sql_mode_str, sql_mode_len, system_charset_info);
protocol->store(m_defstr.str, m_defstr.length, system_charset_info); protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
res= protocol->write(); res= protocol->write();
send_eof(thd); send_eof(thd);
done:
thd->variables.sql_mode= old_sql_mode;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
...@@ -889,20 +913,43 @@ sp_head::show_create_function(THD *thd) ...@@ -889,20 +913,43 @@ sp_head::show_create_function(THD *thd)
String buffer(buff, sizeof(buff), system_charset_info); String buffer(buff, sizeof(buff), system_charset_info);
int res; int res;
List<Item> field_list; List<Item> field_list;
ulong old_sql_mode;
sys_var *sql_mode_var;
byte *sql_mode_str;
ulong sql_mode_len;
DBUG_ENTER("sp_head::show_create_function"); DBUG_ENTER("sp_head::show_create_function");
DBUG_PRINT("info", ("procedure %s", m_name.str)); DBUG_PRINT("info", ("procedure %s", m_name.str));
old_sql_mode= thd->variables.sql_mode;
thd->variables.sql_mode= m_sql_mode;
sql_mode_var= find_sys_var("SQL_MODE", 8);
if (sql_mode_var)
{
sql_mode_str= sql_mode_var->value_ptr(thd, OPT_SESSION, 0);
sql_mode_len= strlen(sql_mode_str);
}
field_list.push_back(new Item_empty_string("Function",NAME_LEN)); field_list.push_back(new Item_empty_string("Function",NAME_LEN));
if (sql_mode_var)
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
field_list.push_back(new Item_empty_string("Create Function", field_list.push_back(new Item_empty_string("Create Function",
max(buffer.length(),1024))); max(buffer.length(),1024)));
if (protocol->send_fields(&field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1); {
res= 1;
goto done;
}
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info); protocol->store(m_name.str, m_name.length, system_charset_info);
if (sql_mode_var)
protocol->store(sql_mode_str, sql_mode_len, system_charset_info);
protocol->store(m_defstr.str, m_defstr.length, system_charset_info); protocol->store(m_defstr.str, m_defstr.length, system_charset_info);
res= protocol->write(); res= protocol->write();
send_eof(thd); send_eof(thd);
done:
thd->variables.sql_mode= old_sql_mode;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
......
...@@ -85,6 +85,7 @@ public: ...@@ -85,6 +85,7 @@ public:
my_bool m_multi_results; // TRUE if a procedure with SELECT(s) my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics; st_sp_chistics *m_chistics;
ulong m_sql_mode; // For SHOW CREATE
#if NOT_USED_NOW #if NOT_USED_NOW
// QQ We're not using this at the moment. // QQ We're not using this at the moment.
List<char *> m_calls; // Called procedures. List<char *> m_calls; // Called procedures.
...@@ -194,7 +195,7 @@ public: ...@@ -194,7 +195,7 @@ public:
void set_info(char *definer, uint definerlen, void set_info(char *definer, uint definerlen,
longlong created, longlong modified, longlong created, longlong modified,
st_sp_chistics *chistics); st_sp_chistics *chistics, ulong sql_mode);
void reset_thd_mem_root(THD *thd); void reset_thd_mem_root(THD *thd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment