Commit 7a20e528 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

In order to make ALTER PROCEDURE|FUNCTION work correctly, and in general to

make characteristics (and SHOW) work right, we had to separate the old
definition blob in the mysql.proc table into separate fields for parameters,
return type, and body, and handle the characteristics (like SQL SECURITY)
separately... and then reassemble the CREATE string for parsing, of course.
This is rather ugly, mostly the parser bit. (Hopefully that will be better
with the new parser.)
parent 7bfbfc30
...@@ -1063,8 +1063,10 @@ ...@@ -1063,8 +1063,10 @@
language enum('SQL') DEFAULT 'SQL' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL,
sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,
is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
definition blob DEFAULT '' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,
security_type enum('INVOKER','DEFINER') DEFAULT 'INVOKER' NOT NULL, param_list blob DEFAULT '' NOT NULL,
returns char(64) DEFAULT '' NOT NULL,
body blob DEFAULT '' NOT NULL,
definer char(77) binary DEFAULT '' NOT NULL, definer char(77) binary DEFAULT '' NOT NULL,
created timestamp, created timestamp,
modified timestamp, modified timestamp,
...@@ -1094,4 +1096,5 @@ ...@@ -1094,4 +1096,5 @@
PRIMARY KEY (schema,name,type) PRIMARY KEY (schema,name,type)
) comment='Stored Procedures'; ) comment='Stored Procedures';
-- --
\ No newline at end of file
...@@ -691,6 +691,43 @@ delete from t1; ...@@ -691,6 +691,43 @@ delete from t1;
delete from t2; delete from t2;
drop table t3; drop table t3;
drop procedure cur2; drop procedure cur2;
create procedure chistics()
language sql
not deterministic
sql security definer
comment 'Characteristics procedure test'
insert into t1 values ("chistics", 1);
call chistics();
select * from t1;
id data
chistics 1
delete from t1;
alter procedure chistics sql security invoker name chistics2;
show create procedure chistics2;
Procedure Create Procedure
chistics2 CREATE PROCEDURE chistics2()
SQL SECURITY INVOKER
COMMENT 'Characteristics procedure test'
insert into t1 values ("chistics", 1)
drop procedure chistics2;
create function chistics() returns int
language sql
deterministic
sql security invoker
comment 'Characteristics procedure test'
return 42;
select chistics();
chistics()
42
alter function chistics name chistics2 comment 'Characteristics function test';
show create function chistics2;
Function Create Function
chistics2 CREATE FUNCTION chistics2() RETURNS int
DETERMINISTIC
SQL SECURITY INVOKER
COMMENT 'Characteristics function test'
return 42
drop function chistics2;
insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3); insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3);
set @@sql_mode = 'ANSI'; set @@sql_mode = 'ANSI';
create procedure modes(out c1 int, out c2 int) create procedure modes(out c1 int, out c2 int)
...@@ -881,7 +918,7 @@ n f ...@@ -881,7 +918,7 @@ n f
drop table fac; drop table fac;
show function status like '%f%'; show function status like '%f%';
Name Type Definer Modified Created Security_type Comment Name Type Definer Modified Created Security_type Comment
fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER fac FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
drop procedure ifac; drop procedure ifac;
drop function fac; drop function fac;
show function status like '%f%'; show function status like '%f%';
...@@ -946,7 +983,7 @@ end while; ...@@ -946,7 +983,7 @@ end while;
end; end;
show create procedure opp; show create procedure opp;
Procedure Create Procedure Procedure Create Procedure
opp create procedure opp(n bigint unsigned, out pp bool) opp CREATE PROCEDURE opp(n bigint unsigned, out pp bool)
begin begin
declare r double; declare r double;
declare b, s bigint unsigned default 0; declare b, s bigint unsigned default 0;
...@@ -974,8 +1011,8 @@ end loop; ...@@ -974,8 +1011,8 @@ end loop;
end end
show procedure status like '%p%'; show procedure status like '%p%';
Name Type Definer Modified Created Security_type Comment Name Type Definer Modified Created Security_type Comment
ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER ip PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER opp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call ip(200); call ip(200);
select * from primes where i=45 or i=100 or i=199; select * from primes where i=45 or i=100 or i=199;
i p i p
...@@ -1043,8 +1080,8 @@ alter procedure bar2 name bar comment "3333333333"; ...@@ -1043,8 +1080,8 @@ 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 Create Procedure
bar create procedure bar(x char(16), y int) bar CREATE PROCEDURE bar(x char(16), y int)
comment "111111111111" sql security invoker COMMENT '3333333333'
insert into test.t1 values (x, y) insert into test.t1 values (x, y)
show procedure status like 'bar'; show procedure status like 'bar';
Name Type Definer Modified Created Security_type Comment Name Type Definer Modified Created Security_type Comment
......
...@@ -816,6 +816,36 @@ drop table t3| ...@@ -816,6 +816,36 @@ drop table t3|
drop procedure cur2| drop procedure cur2|
# The few characteristics we parse
create procedure chistics()
language sql
not deterministic
sql security definer
comment 'Characteristics procedure test'
insert into t1 values ("chistics", 1)|
# Call it, just to make sure.
call chistics()|
select * from t1|
delete from t1|
alter procedure chistics sql security invoker name chistics2|
show create procedure chistics2|
drop procedure chistics2|
create function chistics() returns int
language sql
deterministic
sql security invoker
comment 'Characteristics procedure test'
return 42|
# Call it, just to make sure.
select chistics()|
alter function chistics name chistics2 comment 'Characteristics function test'|
show create function chistics2|
drop function chistics2|
# Check mode settings # Check mode settings
insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)| insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)|
......
...@@ -296,8 +296,10 @@ then ...@@ -296,8 +296,10 @@ then
c_p="$c_p language enum('SQL') DEFAULT 'SQL' NOT NULL," c_p="$c_p language enum('SQL') DEFAULT 'SQL' NOT NULL,"
c_p="$c_p sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL," c_p="$c_p sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,"
c_p="$c_p is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL," c_p="$c_p is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,"
c_p="$c_p definition blob DEFAULT '' NOT NULL," c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,"
c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'INVOKER' NOT NULL," c_p="$c_p param_list blob DEFAULT '' NOT NULL,"
c_p="$c_p returns char(64) DEFAULT '' NOT NULL,"
c_p="$c_p body blob DEFAULT '' NOT NULL,"
c_p="$c_p definer char(77) binary DEFAULT '' NOT NULL," c_p="$c_p definer char(77) binary DEFAULT '' NOT NULL,"
c_p="$c_p created timestamp," c_p="$c_p created timestamp,"
c_p="$c_p modified timestamp," c_p="$c_p modified timestamp,"
......
...@@ -147,8 +147,10 @@ CREATE TABLE IF NOT EXISTS proc ( ...@@ -147,8 +147,10 @@ CREATE TABLE IF NOT EXISTS proc (
language enum('SQL') DEFAULT 'SQL' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL,
sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,
is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
definition blob DEFAULT '' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL,
security_type enum('INVOKER','DEFINER') DEFAULT 'INVOKER' NOT NULL, param_list blob DEFAULT '' NOT NULL,
returns char(64) DEFAULT '' NOT NULL,
body blob DEFAULT '' NOT NULL,
definer char(77) binary DEFAULT '' NOT NULL, definer char(77) binary DEFAULT '' NOT NULL,
created timestamp, created timestamp,
modified timestamp, modified timestamp,
......
...@@ -20,27 +20,41 @@ ...@@ -20,27 +20,41 @@
#include "sp_head.h" #include "sp_head.h"
#include "sp_cache.h" #include "sp_cache.h"
static char *
create_string(THD *thd, ulong *lenp,
int sp_type,
char *name, ulong namelen,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
st_sp_chistics *chistics);
/* /*
* *
* DB storage of Stored PROCEDUREs and FUNCTIONs * DB storage of Stored PROCEDUREs and FUNCTIONs
* *
*/ */
#define MYSQL_PROC_FIELD_SCHEMA 0 enum
#define MYSQL_PROC_FIELD_NAME 1 {
#define MYSQL_PROC_FIELD_TYPE 2 MYSQL_PROC_FIELD_SCHEMA = 0,
#define MYSQL_PROC_FIELD_SPECIFIC_NAME 3 MYSQL_PROC_FIELD_NAME,
#define MYSQL_PROC_FIELD_LANGUAGE 4 MYSQL_PROC_FIELD_TYPE,
#define MYSQL_PROC_FIELD_ACCESS 5 MYSQL_PROC_FIELD_SPECIFIC_NAME,
#define MYSQL_PROC_FIELD_DETERMINISTIC 6 MYSQL_PROC_FIELD_LANGUAGE,
#define MYSQL_PROC_FIELD_DEFINITION 7 MYSQL_PROC_FIELD_ACCESS,
#define MYSQL_PROC_FIELD_SECURITY_TYPE 8 MYSQL_PROC_FIELD_DETERMINISTIC,
#define MYSQL_PROC_FIELD_DEFINER 9 MYSQL_PROC_FIELD_SECURITY_TYPE,
#define MYSQL_PROC_FIELD_CREATED 10 MYSQL_PROC_FIELD_PARAM_LIST,
#define MYSQL_PROC_FIELD_MODIFIED 11 MYSQL_PROC_FIELD_RETURNS,
#define MYSQL_PROC_FIELD_SQL_MODE 12 MYSQL_PROC_FIELD_BODY,
#define MYSQL_PROC_FIELD_COMMENT 13 MYSQL_PROC_FIELD_DEFINER,
#define MYSQL_PROC_FIELD_COUNT 14 MYSQL_PROC_FIELD_CREATED,
MYSQL_PROC_FIELD_MODIFIED,
MYSQL_PROC_FIELD_SQL_MODE,
MYSQL_PROC_FIELD_COMMENT,
MYSQL_PROC_FIELD_COUNT
};
/* *opened=true means we opened ourselves */ /* *opened=true means we opened ourselves */
static int static int
...@@ -104,13 +118,13 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -104,13 +118,13 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name)); DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
extern int yyparse(void *thd); extern int yyparse(void *thd);
TABLE *table; TABLE *table;
const char *defstr; const char *params, *returns, *body;
int ret; int ret;
bool opened; bool opened;
const char *creator; const char *creator;
longlong created; longlong created;
longlong modified; longlong modified;
bool suid= 1; st_sp_chistics *chistics;
char *ptr; char *ptr;
uint length; uint length;
char buff[65]; char buff[65];
...@@ -127,32 +141,55 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -127,32 +141,55 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
goto done; goto done;
} }
if ((defstr= get_field(&thd->mem_root, if ((ptr= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_DEFINITION])) == NULL) table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
{ {
ret= SP_GET_FIELD_FAILED; ret= SP_GET_FIELD_FAILED;
goto done; goto done;
} }
chistics= (st_sp_chistics *)thd->alloc(sizeof(st_sp_chistics));
chistics->detistic= (ptr[0] == 'N' ? FALSE : TRUE);
// Get additional information if ((ptr= get_field(&thd->mem_root,
if ((creator= get_field(&thd->mem_root, table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
{ {
ret= SP_GET_FIELD_FAILED; ret= SP_GET_FIELD_FAILED;
goto done; goto done;
} }
chistics->suid= (ptr[0] == 'I' ? IS_NOT_SUID : IS_SUID);
modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int(); if ((params= get_field(&thd->mem_root,
created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int(); table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
{
params= "";
}
if ((ptr= get_field(&thd->mem_root, if (type == TYPE_ENUM_PROCEDURE)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL) returns= "";
else if ((returns= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
{ {
ret= SP_GET_FIELD_FAILED; ret= SP_GET_FIELD_FAILED;
goto done; goto done;
} }
if (ptr[0] == 'N')
suid= 0; if ((body= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
// Get additional information
if ((creator= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
sql_mode= table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); sql_mode= table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int();
...@@ -160,7 +197,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -160,7 +197,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
ptr= 0; ptr= 0;
if ((length= str.length())) if ((length= str.length()))
ptr= strmake_root(&thd->mem_root, str.ptr(), length); ptr= thd->strmake(str.ptr(), length);
chistics->comment.str= ptr;
chistics->comment.length= length;
if (opened) if (opened)
{ {
...@@ -169,6 +208,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -169,6 +208,8 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
} }
{ {
char *defstr;
ulong deflen;
LEX *oldlex= thd->lex; LEX *oldlex= thd->lex;
enum enum_sql_command oldcmd= thd->lex->sql_command; enum enum_sql_command oldcmd= thd->lex->sql_command;
ulong old_sql_mode= thd->variables.sql_mode; ulong old_sql_mode= thd->variables.sql_mode;
...@@ -177,7 +218,14 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -177,7 +218,14 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, 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;
lex_start(thd, (uchar*)defstr, strlen(defstr)); defstr= create_string(thd, &deflen,
type,
name, namelen,
params, strlen(params),
returns, strlen(returns),
body, strlen(body),
chistics);
lex_start(thd, (uchar*)defstr, deflen);
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL) if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
{ {
LEX *newlex= thd->lex; LEX *newlex= thd->lex;
...@@ -196,8 +244,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -196,8 +244,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
{ {
*sphp= thd->lex->sphead; *sphp= thd->lex->sphead;
(*sphp)->set_info((char *) creator, (uint) strlen(creator), (*sphp)->set_info((char *) creator, (uint) strlen(creator),
created, modified, suid, created, modified, chistics);
ptr, length);
} }
thd->lex->sql_command= oldcmd; thd->lex->sql_command= oldcmd;
thd->variables.sql_mode= old_sql_mode; thd->variables.sql_mode= old_sql_mode;
...@@ -211,12 +258,10 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -211,12 +258,10 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
} }
static int static int
db_create_routine(THD *thd, int type, db_create_routine(THD *thd, int type, sp_head *sp)
char *name, uint namelen, char *def, uint deflen,
st_sp_chistics *chistics)
{ {
DBUG_ENTER("db_create_routine"); DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %*s def: %*s", type, namelen, name, deflen, def)); DBUG_PRINT("enter", ("type: %d name: %*s",type,sp->m_name.length,sp->m_name.str));
int ret; int ret;
TABLE *table; TABLE *table;
TABLE_LIST tables; TABLE_LIST tables;
...@@ -238,26 +283,32 @@ db_create_routine(THD *thd, int type, ...@@ -238,26 +283,32 @@ db_create_routine(THD *thd, int type,
ret= SP_GET_FIELD_FAILED; ret= SP_GET_FIELD_FAILED;
goto done; goto done;
} }
table->field[MYSQL_PROC_FIELD_NAME]->store(name, namelen, table->field[MYSQL_PROC_FIELD_NAME]->
system_charset_info); store(sp->m_name.str, sp->m_name.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_TYPE]->store((longlong)type); table->field[MYSQL_PROC_FIELD_TYPE]->
table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->store(name, namelen, store((longlong)type);
system_charset_info); table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->
table->field[MYSQL_PROC_FIELD_DEFINITION]->store(def, deflen, store(sp->m_name.str, sp->m_name.length, system_charset_info);
system_charset_info); table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
table->field[MYSQL_PROC_FIELD_DEFINER]->store(creator, store((longlong)(sp->m_chistics->detistic ? 1 : 2));
(uint)strlen(creator), if (sp->m_chistics->suid != IS_DEFAULT_SUID)
system_charset_info); table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->
store((longlong)sp->m_chistics->suid);
table->field[MYSQL_PROC_FIELD_PARAM_LIST]->
store(sp->m_params.str, sp->m_params.length, system_charset_info);
if (sp->m_retstr.str)
table->field[MYSQL_PROC_FIELD_RETURNS]->
store(sp->m_retstr.str, sp->m_retstr.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_BODY]->
store(sp->m_body.str, sp->m_body.length, system_charset_info);
table->field[MYSQL_PROC_FIELD_DEFINER]->
store(creator, (uint)strlen(creator), system_charset_info);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time();
if (chistics->suid != IS_DEFAULT_SUID) table->field[MYSQL_PROC_FIELD_SQL_MODE]->
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store( store((longlong)thd->variables.sql_mode);
(longlong)chistics->suid); if (sp->m_chistics->comment.str)
table->field[MYSQL_PROC_FIELD_SQL_MODE]->store( table->field[MYSQL_PROC_FIELD_COMMENT]->
(longlong)thd->variables.sql_mode); store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
if (chistics->comment.str)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(
chistics->comment.str,
chistics->comment.length,
system_charset_info); system_charset_info);
if (table->file->write_row(table->record[0])) if (table->file->write_row(table->record[0]))
...@@ -308,7 +359,7 @@ db_update_routine(THD *thd, int type, char *name, uint namelen, ...@@ -308,7 +359,7 @@ db_update_routine(THD *thd, int type, char *name, uint namelen,
{ {
store_record(table,record[1]); store_record(table,record[1]);
((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time();
if (chistics->suid) if (chistics->suid != IS_DEFAULT_SUID)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store((longlong)chistics->suid); table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store((longlong)chistics->suid);
if (newname) if (newname)
table->field[MYSQL_PROC_FIELD_NAME]->store(newname, table->field[MYSQL_PROC_FIELD_NAME]->store(newname,
...@@ -516,15 +567,13 @@ sp_find_procedure(THD *thd, LEX_STRING *name) ...@@ -516,15 +567,13 @@ sp_find_procedure(THD *thd, LEX_STRING *name)
} }
int int
sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen, sp_create_procedure(THD *thd, sp_head *sp)
st_sp_chistics *chistics)
{ {
DBUG_ENTER("sp_create_procedure"); DBUG_ENTER("sp_create_procedure");
DBUG_PRINT("enter", ("name: %*s def: %*s", namelen, name, deflen, def)); DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
int ret; int ret;
ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, def, deflen, ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp);
chistics);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -611,15 +660,13 @@ sp_find_function(THD *thd, LEX_STRING *name) ...@@ -611,15 +660,13 @@ sp_find_function(THD *thd, LEX_STRING *name)
} }
int int
sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen, sp_create_function(THD *thd, sp_head *sp)
st_sp_chistics *chistics)
{ {
DBUG_ENTER("sp_create_function"); DBUG_ENTER("sp_create_function");
DBUG_PRINT("enter", ("name: %*s def: %*s", namelen, name, deflen, def)); DBUG_PRINT("enter", ("name: %*s", sp->m_name.length, sp->m_name.str));
int ret; int ret;
ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, def, deflen, ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, sp);
chistics);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -774,3 +821,45 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -774,3 +821,45 @@ sp_cache_functions(THD *thd, LEX *lex)
} }
return ret; return ret;
} }
static char *
create_string(THD *thd, ulong *lenp,
int type,
char *name, ulong namelen,
const char *params, ulong paramslen,
const char *returns, ulong returnslen,
const char *body, ulong bodylen,
st_sp_chistics *chistics)
{
char *buf, *ptr;
ulong buflen, pos;
buflen= 100 + namelen + paramslen + returnslen + bodylen +
chistics->comment.length;
ptr= buf= thd->alloc(buflen);
if (type == TYPE_ENUM_FUNCTION)
{
ptr+= my_sprintf(buf,
(buf, (char *)
"CREATE FUNCTION %s(%s) RETURNS %s\n",
name, params, returns));
}
else
{
ptr+= my_sprintf(buf,
(buf, (char *)
"CREATE PROCEDURE %s(%s)\n",
name, params));
}
if (chistics->detistic)
ptr+= my_sprintf(ptr, (ptr, (char *)" DETERMINISTIC\n"));
if (chistics->suid == IS_NOT_SUID)
ptr+= my_sprintf(ptr, (ptr, (char *)" SQL SECURITY INVOKER\n"));
if (chistics->comment.str)
ptr+= my_sprintf(ptr, (ptr, (char *)" COMMENT '%*s'\n",
chistics->comment.length,
chistics->comment.str));
strcpy(ptr, body);
*lenp= (ptr-buf)+bodylen;
return buf;
}
...@@ -32,8 +32,7 @@ sp_head * ...@@ -32,8 +32,7 @@ sp_head *
sp_find_procedure(THD *thd, LEX_STRING *name); sp_find_procedure(THD *thd, LEX_STRING *name);
int int
sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen, sp_create_procedure(THD *thd, sp_head *sp);
st_sp_chistics *chistics);
int int
sp_drop_procedure(THD *thd, char *name, uint namelen); sp_drop_procedure(THD *thd, char *name, uint namelen);
...@@ -54,8 +53,7 @@ sp_head * ...@@ -54,8 +53,7 @@ sp_head *
sp_find_function(THD *thd, LEX_STRING *name); sp_find_function(THD *thd, LEX_STRING *name);
int int
sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen, sp_create_function(THD *thd, sp_head *sp);
st_sp_chistics *chistics);
int int
sp_drop_function(THD *thd, char *name, uint namelen); sp_drop_function(THD *thd, char *name, uint namelen);
......
...@@ -163,18 +163,51 @@ sp_head::sp_head() ...@@ -163,18 +163,51 @@ sp_head::sp_head()
} }
void void
sp_head::init(LEX_STRING *name, LEX *lex) sp_head::init(LEX *lex)
{ {
DBUG_ENTER("sp_head::init"); DBUG_ENTER("sp_head::init");
const char *dstr = (const char*)lex->buf;
lex->spcont= m_pcont= new sp_pcontext();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
m_name.str= m_params.str= m_retstr.str= m_body.str= m_defstr.str= 0;
m_name.length= m_params.length= m_retstr.length= m_body.length=
m_defstr.length= 0;
DBUG_VOID_RETURN;
}
void
sp_head::init_strings(LEX_STRING *name, LEX *lex)
{
DBUG_ENTER("sp_head::init_strings");
DBUG_PRINT("info", ("name: %*s", name->length, name->str)); DBUG_PRINT("info", ("name: %*s", name->length, name->str));
m_name.length= name->length; m_name.length= name->length;
m_name.str= lex->thd->strmake(name->str, name->length); m_name.str= lex->thd->strmake(name->str, name->length);
m_params.length= m_param_end- m_param_begin;
m_params.str= lex->thd->strmake((char *)m_param_begin, m_params.length);
if (m_returns_begin && m_returns_end)
{
/* QQ KLUDGE: We can't seem to cut out just the type in the parser
(without the RETURNS), so we'll have to do it here. :-( */
char *p= (char *)m_returns_begin+strspn((char *)m_returns_begin,"\t\n\r ");
p+= strcspn(p, "\t\n\r ");
p+= strspn(p, "\t\n\r ");
if (p < (char *)m_returns_end)
m_returns_begin= (uchar *)p;
/* While we're at it, trim the end too. */
p= (char *)m_returns_end-1;
while (p > (char *)m_returns_begin &&
(*p == '\t' || *p == '\n' || *p == '\r' || *p == ' '))
p-= 1;
m_returns_end= (uchar *)p+1;
m_retstr.length= m_returns_end - m_returns_begin;
m_retstr.str= lex->thd->strmake((char *)m_returns_begin, m_retstr.length);
}
m_body.length= lex->end_of_query - m_body_begin;
m_body.str= lex->thd->strmake((char *)m_body_begin, m_body.length);
m_defstr.length= lex->end_of_query - lex->buf; m_defstr.length= lex->end_of_query - lex->buf;
m_defstr.str= lex->thd->strmake(dstr, m_defstr.length); m_defstr.str= lex->thd->strmake((char *)lex->buf, m_defstr.length);
lex->spcont= m_pcont= new sp_pcontext();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -184,18 +217,12 @@ sp_head::create(THD *thd) ...@@ -184,18 +217,12 @@ sp_head::create(THD *thd)
DBUG_ENTER("sp_head::create"); DBUG_ENTER("sp_head::create");
int ret; int ret;
DBUG_PRINT("info", ("type: %d name: %s def: %s", DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s",
m_type, m_name.str, m_defstr.str)); m_type, m_name.str, m_params.str, m_body.str));
if (m_type == TYPE_ENUM_FUNCTION) if (m_type == TYPE_ENUM_FUNCTION)
ret= sp_create_function(thd, ret= sp_create_function(thd, this);
m_name.str, m_name.length,
m_defstr.str, m_defstr.length,
m_chistics);
else else
ret= sp_create_procedure(thd, ret= sp_create_procedure(thd, this);
m_name.str, m_name.length,
m_defstr.str, m_defstr.length,
m_chistics);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
......
...@@ -56,6 +56,18 @@ class sp_head : public Sql_alloc ...@@ -56,6 +56,18 @@ class sp_head : public Sql_alloc
List<char *> m_calls; // Called procedures. List<char *> m_calls; // Called procedures.
List<char *> m_tables; // Used tables. List<char *> m_tables; // Used tables.
#endif #endif
LEX_STRING m_name;
LEX_STRING m_params;
LEX_STRING m_retstr; // For FUNCTIONs only
LEX_STRING m_body;
LEX_STRING m_defstr;
char *m_creator;
uint m_creatorlen;
longlong m_created;
longlong m_modified;
// Pointers set during parsing
uchar *m_param_begin, *m_param_end, *m_returns_begin, *m_returns_end,
*m_body_begin;
static void * static void *
operator new(size_t size); operator new(size_t size);
...@@ -67,7 +79,11 @@ class sp_head : public Sql_alloc ...@@ -67,7 +79,11 @@ class sp_head : public Sql_alloc
// Initialize after we have reset mem_root // Initialize after we have reset mem_root
void void
init(LEX_STRING *name, LEX *lex); init(LEX *lex);
// Initialize strings after parsing header
void
init_strings(LEX_STRING *name, LEX *lex);
int int
create(THD *thd); create(THD *thd);
...@@ -136,6 +152,8 @@ class sp_head : public Sql_alloc ...@@ -136,6 +152,8 @@ class sp_head : public Sql_alloc
return m_name.str; return m_name.str;
} }
char *create_string(THD *thd, ulong *lenp);
inline Item_result result() inline Item_result result()
{ {
return sp_map_result_type(m_returns); return sp_map_result_type(m_returns);
...@@ -143,15 +161,13 @@ class sp_head : public Sql_alloc ...@@ -143,15 +161,13 @@ class sp_head : public Sql_alloc
void set_info(char *creator, uint creatorlen, void set_info(char *creator, uint creatorlen,
longlong created, longlong modified, longlong created, longlong modified,
bool suid, char *comment, uint commentlen) st_sp_chistics *chistics)
{ {
m_creator= creator; m_creator= creator;
m_creatorlen= creatorlen; m_creatorlen= creatorlen;
m_created= created; m_created= created;
m_modified= modified; m_modified= modified;
m_chistics->comment.length= commentlen; m_chistics= chistics;
m_chistics->comment.str= comment;
m_chistics->suid= (suid ? IS_SUID : IS_NOT_SUID);
} }
inline void reset_thd_mem_root(THD *thd) inline void reset_thd_mem_root(THD *thd)
...@@ -180,13 +196,6 @@ class sp_head : public Sql_alloc ...@@ -180,13 +196,6 @@ class sp_head : public Sql_alloc
Item *m_free_list; // Where the items go Item *m_free_list; // Where the items go
THD *m_thd; // Set if we have reset mem_root THD *m_thd; // Set if we have reset mem_root
LEX_STRING m_name;
LEX_STRING m_defstr;
char *m_creator;
uint m_creatorlen;
longlong m_created;
longlong m_modified;
sp_pcontext *m_pcont; // Parse context sp_pcontext *m_pcont; // Parse context
List<LEX> m_lex; // Temp. store for the other lex List<LEX> m_lex; // Temp. store for the other lex
DYNAMIC_ARRAY m_instr; // The "instructions" DYNAMIC_ARRAY m_instr; // The "instructions"
......
...@@ -1040,7 +1040,7 @@ create: ...@@ -1040,7 +1040,7 @@ create:
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
sp->reset_thd_mem_root(YYTHD); sp->reset_thd_mem_root(YYTHD);
sp->init(&$3, lex); sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE; sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp; lex->sphead= sp;
...@@ -1052,10 +1052,18 @@ create: ...@@ -1052,10 +1052,18 @@ create:
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES); YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
} }
'(' sp_pdparam_list ')' '('
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->m_param_begin= lex->tok_start+1;
}
sp_pdparam_list
')'
{
LEX *lex= Lex;
lex->sphead->m_param_end= lex->tok_start;
lex->spcont->set_params(); lex->spcont->set_params();
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
...@@ -1064,11 +1072,13 @@ create: ...@@ -1064,11 +1072,13 @@ create:
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->tok_start;
} }
sp_proc_stmt sp_proc_stmt
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->init_strings(&$3, lex);
lex->sql_command= SQLCOM_CREATE_PROCEDURE; lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq) if (lex->sphead->m_old_cmq)
...@@ -1103,7 +1113,7 @@ create_function_tail: ...@@ -1103,7 +1113,7 @@ create_function_tail:
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
sp->reset_thd_mem_root(YYTHD); sp->reset_thd_mem_root(YYTHD);
sp->init(&lex->udf.name, lex); sp->init(lex);
sp->m_type= TYPE_ENUM_FUNCTION; sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp; lex->sphead= sp;
...@@ -1114,16 +1124,25 @@ create_function_tail: ...@@ -1114,16 +1124,25 @@ create_function_tail:
*/ */
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lex->tok_start+1;
} }
sp_fdparam_list ')' sp_fdparam_list ')'
{ {
Lex->spcont->set_params(); LEX *lex= Lex;
lex->spcont->set_params();
lex->sphead->m_param_end= lex->tok_start;
}
RETURNS_SYM
{
Lex->sphead->m_returns_begin= Lex->tok_start;
} }
RETURNS_SYM type type
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->m_returns= (enum enum_field_types)$7; lex->sphead->m_returns_end= lex->tok_start;
lex->sphead->m_returns= (enum enum_field_types)$8;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
sp_c_chistics sp_c_chistics
...@@ -1131,16 +1150,19 @@ create_function_tail: ...@@ -1131,16 +1150,19 @@ create_function_tail:
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->tok_start;
} }
sp_proc_stmt sp_proc_stmt
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION; lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(&lex->udf.name, lex);
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq) if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
lex->sphead->restore_thd_mem_root(YYTHD); sp->restore_thd_mem_root(YYTHD);
} }
; ;
...@@ -5884,6 +5906,7 @@ keyword: ...@@ -5884,6 +5906,7 @@ keyword:
| RESET_SYM {} | RESET_SYM {}
| RESOURCES {} | RESOURCES {}
| RESTORE_SYM {} | RESTORE_SYM {}
| RETURNS_SYM {}
| ROLLBACK_SYM {} | ROLLBACK_SYM {}
| ROLLUP_SYM {} | ROLLUP_SYM {}
| ROWS_SYM {} | ROWS_SYM {}
......
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