summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/sp-imp-spec.txt11
-rw-r--r--mysql-test/r/sp.result49
-rw-r--r--mysql-test/t/sp.test30
-rw-r--r--scripts/mysql_create_system_tables.sh6
-rw-r--r--scripts/mysql_fix_privilege_tables.sql6
-rw-r--r--sql/sp.cc223
-rw-r--r--sql/sp.h6
-rw-r--r--sql/sp_head.cc57
-rw-r--r--sql/sp_head.h33
-rw-r--r--sql/sql_yacc.yy39
10 files changed, 340 insertions, 120 deletions
diff --git a/Docs/sp-imp-spec.txt b/Docs/sp-imp-spec.txt
index b93416df2f7..ee9bc7a0e4f 100644
--- a/Docs/sp-imp-spec.txt
+++ b/Docs/sp-imp-spec.txt
@@ -1063,8 +1063,10 @@
language enum('SQL') DEFAULT 'SQL' NOT NULL,
sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,
is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
- definition blob DEFAULT '' NOT NULL,
- security_type enum('INVOKER','DEFINER') DEFAULT 'INVOKER' NOT NULL,
+ security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' 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,
created timestamp,
modified timestamp,
@@ -1093,5 +1095,6 @@
comment char(64) binary DEFAULT '' NOT NULL,
PRIMARY KEY (schema,name,type)
) comment='Stored Procedures';
-
---
+
+ --
+ \ No newline at end of file
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index e0d72a77832..851d56ba458 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -691,6 +691,43 @@ delete from t1;
delete from t2;
drop table t3;
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);
set @@sql_mode = 'ANSI';
create procedure modes(out c1 int, out c2 int)
@@ -881,7 +918,7 @@ n f
drop table fac;
show function status like '%f%';
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 function fac;
show function status like '%f%';
@@ -946,7 +983,7 @@ end while;
end;
show create procedure opp;
Procedure Create Procedure
-opp create procedure opp(n bigint unsigned, out pp bool)
+opp CREATE PROCEDURE opp(n bigint unsigned, out pp bool)
begin
declare r double;
declare b, s bigint unsigned default 0;
@@ -974,8 +1011,8 @@ end loop;
end
show procedure status like '%p%';
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
-opp 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 DEFINER
call ip(200);
select * from primes where i=45 or i=100 or i=199;
i p
@@ -1043,8 +1080,8 @@ alter procedure bar2 name bar comment "3333333333";
alter procedure bar;
show create procedure bar;
Procedure Create Procedure
-bar create procedure bar(x char(16), y int)
-comment "111111111111" sql security invoker
+bar CREATE PROCEDURE bar(x char(16), y int)
+ COMMENT '3333333333'
insert into test.t1 values (x, y)
show procedure status like 'bar';
Name Type Definer Modified Created Security_type Comment
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 933fe828440..3681d9a9517 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -816,6 +816,36 @@ drop table t3|
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
insert into t1 values ("foo", 1), ("bar", 2), ("zip", 3)|
diff --git a/scripts/mysql_create_system_tables.sh b/scripts/mysql_create_system_tables.sh
index 7ae6773c1cf..57198abd53a 100644
--- a/scripts/mysql_create_system_tables.sh
+++ b/scripts/mysql_create_system_tables.sh
@@ -296,8 +296,10 @@ then
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 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 'INVOKER' NOT NULL,"
+ c_p="$c_p security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' 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 created timestamp,"
c_p="$c_p modified timestamp,"
diff --git a/scripts/mysql_fix_privilege_tables.sql b/scripts/mysql_fix_privilege_tables.sql
index e342e08ea9d..788913fa38e 100644
--- a/scripts/mysql_fix_privilege_tables.sql
+++ b/scripts/mysql_fix_privilege_tables.sql
@@ -147,8 +147,10 @@ CREATE TABLE IF NOT EXISTS proc (
language enum('SQL') DEFAULT 'SQL' NOT NULL,
sql_data_access enum('CONTAINS_SQL') DEFAULT 'CONTAINS_SQL' NOT NULL,
is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL,
- definition blob DEFAULT '' NOT NULL,
- security_type enum('INVOKER','DEFINER') DEFAULT 'INVOKER' NOT NULL,
+ security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' 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,
created timestamp,
modified timestamp,
diff --git a/sql/sp.cc b/sql/sp.cc
index 42b0ba001a6..ded45102815 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -20,27 +20,41 @@
#include "sp_head.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
*
*/
-#define MYSQL_PROC_FIELD_SCHEMA 0
-#define MYSQL_PROC_FIELD_NAME 1
-#define MYSQL_PROC_FIELD_TYPE 2
-#define MYSQL_PROC_FIELD_SPECIFIC_NAME 3
-#define MYSQL_PROC_FIELD_LANGUAGE 4
-#define MYSQL_PROC_FIELD_ACCESS 5
-#define MYSQL_PROC_FIELD_DETERMINISTIC 6
-#define MYSQL_PROC_FIELD_DEFINITION 7
-#define MYSQL_PROC_FIELD_SECURITY_TYPE 8
-#define MYSQL_PROC_FIELD_DEFINER 9
-#define MYSQL_PROC_FIELD_CREATED 10
-#define MYSQL_PROC_FIELD_MODIFIED 11
-#define MYSQL_PROC_FIELD_SQL_MODE 12
-#define MYSQL_PROC_FIELD_COMMENT 13
-#define MYSQL_PROC_FIELD_COUNT 14
+enum
+{
+ MYSQL_PROC_FIELD_SCHEMA = 0,
+ MYSQL_PROC_FIELD_NAME,
+ MYSQL_PROC_FIELD_TYPE,
+ MYSQL_PROC_FIELD_SPECIFIC_NAME,
+ MYSQL_PROC_FIELD_LANGUAGE,
+ MYSQL_PROC_FIELD_ACCESS,
+ MYSQL_PROC_FIELD_DETERMINISTIC,
+ MYSQL_PROC_FIELD_SECURITY_TYPE,
+ MYSQL_PROC_FIELD_PARAM_LIST,
+ MYSQL_PROC_FIELD_RETURNS,
+ MYSQL_PROC_FIELD_BODY,
+ MYSQL_PROC_FIELD_DEFINER,
+ 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 */
static int
@@ -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));
extern int yyparse(void *thd);
TABLE *table;
- const char *defstr;
+ const char *params, *returns, *body;
int ret;
bool opened;
const char *creator;
longlong created;
longlong modified;
- bool suid= 1;
+ st_sp_chistics *chistics;
char *ptr;
uint length;
char buff[65];
@@ -127,32 +141,55 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
goto done;
}
- if ((defstr= get_field(&thd->mem_root,
- table->field[MYSQL_PROC_FIELD_DEFINITION])) == NULL)
+ if ((ptr= get_field(&thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
+ chistics= (st_sp_chistics *)thd->alloc(sizeof(st_sp_chistics));
+ chistics->detistic= (ptr[0] == 'N' ? FALSE : TRUE);
- // Get additional information
- if ((creator= get_field(&thd->mem_root,
- table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
+ if ((ptr= get_field(&thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
+ chistics->suid= (ptr[0] == 'I' ? IS_NOT_SUID : IS_SUID);
- modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int();
- created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
+ if ((params= get_field(&thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
+ {
+ params= "";
+ }
- if ((ptr= get_field(&thd->mem_root,
- table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
+ if (type == TYPE_ENUM_PROCEDURE)
+ returns= "";
+ else if ((returns= get_field(&thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
+ {
+ ret= SP_GET_FIELD_FAILED;
+ goto done;
+ }
+
+ if ((body= get_field(&thd->mem_root,
+ table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
- if (ptr[0] == 'N')
- suid= 0;
+
+ // 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();
@@ -160,7 +197,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
ptr= 0;
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)
{
@@ -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;
enum enum_sql_command oldcmd= thd->lex->sql_command;
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)
thd->variables.sql_mode= sql_mode;
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)
{
LEX *newlex= thd->lex;
@@ -196,8 +244,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
{
*sphp= thd->lex->sphead;
(*sphp)->set_info((char *) creator, (uint) strlen(creator),
- created, modified, suid,
- ptr, length);
+ created, modified, chistics);
}
thd->lex->sql_command= oldcmd;
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)
}
static int
-db_create_routine(THD *thd, int type,
- char *name, uint namelen, char *def, uint deflen,
- st_sp_chistics *chistics)
+db_create_routine(THD *thd, int type, sp_head *sp)
{
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;
TABLE *table;
TABLE_LIST tables;
@@ -238,27 +283,33 @@ db_create_routine(THD *thd, int type,
ret= SP_GET_FIELD_FAILED;
goto done;
}
- table->field[MYSQL_PROC_FIELD_NAME]->store(name, namelen,
- system_charset_info);
- table->field[MYSQL_PROC_FIELD_TYPE]->store((longlong)type);
- table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]->store(name, namelen,
- system_charset_info);
- table->field[MYSQL_PROC_FIELD_DEFINITION]->store(def, deflen,
- system_charset_info);
- table->field[MYSQL_PROC_FIELD_DEFINER]->store(creator,
- (uint)strlen(creator),
- system_charset_info);
+ table->field[MYSQL_PROC_FIELD_NAME]->
+ 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_SPECIFIC_NAME]->
+ store(sp->m_name.str, sp->m_name.length, system_charset_info);
+ table->field[MYSQL_PROC_FIELD_DETERMINISTIC]->
+ store((longlong)(sp->m_chistics->detistic ? 1 : 2));
+ if (sp->m_chistics->suid != IS_DEFAULT_SUID)
+ 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();
- if (chistics->suid != IS_DEFAULT_SUID)
- table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store(
- (longlong)chistics->suid);
- table->field[MYSQL_PROC_FIELD_SQL_MODE]->store(
- (longlong)thd->variables.sql_mode);
- if (chistics->comment.str)
- table->field[MYSQL_PROC_FIELD_COMMENT]->store(
- chistics->comment.str,
- chistics->comment.length,
- system_charset_info);
+ table->field[MYSQL_PROC_FIELD_SQL_MODE]->
+ store((longlong)thd->variables.sql_mode);
+ if (sp->m_chistics->comment.str)
+ table->field[MYSQL_PROC_FIELD_COMMENT]->
+ store(sp->m_chistics->comment.str, sp->m_chistics->comment.length,
+ system_charset_info);
if (table->file->write_row(table->record[0]))
ret= SP_WRITE_ROW_FAILED;
@@ -308,7 +359,7 @@ db_update_routine(THD *thd, int type, char *name, uint namelen,
{
store_record(table,record[1]);
((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);
if (newname)
table->field[MYSQL_PROC_FIELD_NAME]->store(newname,
@@ -516,15 +567,13 @@ sp_find_procedure(THD *thd, LEX_STRING *name)
}
int
-sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen,
- st_sp_chistics *chistics)
+sp_create_procedure(THD *thd, sp_head *sp)
{
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;
- ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, def, deflen,
- chistics);
+ ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, sp);
DBUG_RETURN(ret);
}
@@ -611,15 +660,13 @@ sp_find_function(THD *thd, LEX_STRING *name)
}
int
-sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen,
- st_sp_chistics *chistics)
+sp_create_function(THD *thd, sp_head *sp)
{
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;
- ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, def, deflen,
- chistics);
+ ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, sp);
DBUG_RETURN(ret);
}
@@ -774,3 +821,45 @@ sp_cache_functions(THD *thd, LEX *lex)
}
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;
+}
diff --git a/sql/sp.h b/sql/sp.h
index 9bce886336d..b9f29138de2 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -32,8 +32,7 @@ sp_head *
sp_find_procedure(THD *thd, LEX_STRING *name);
int
-sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen,
- st_sp_chistics *chistics);
+sp_create_procedure(THD *thd, sp_head *sp);
int
sp_drop_procedure(THD *thd, char *name, uint namelen);
@@ -54,8 +53,7 @@ sp_head *
sp_find_function(THD *thd, LEX_STRING *name);
int
-sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen,
- st_sp_chistics *chistics);
+sp_create_function(THD *thd, sp_head *sp);
int
sp_drop_function(THD *thd, char *name, uint namelen);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 39669c5b86f..cfaf08b7972 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -163,18 +163,51 @@ sp_head::sp_head()
}
void
-sp_head::init(LEX_STRING *name, LEX *lex)
+sp_head::init(LEX *lex)
{
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));
m_name.length= 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.str= lex->thd->strmake(dstr, m_defstr.length);
- lex->spcont= m_pcont= new sp_pcontext();
- my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
+ m_defstr.str= lex->thd->strmake((char *)lex->buf, m_defstr.length);
DBUG_VOID_RETURN;
}
@@ -184,18 +217,12 @@ sp_head::create(THD *thd)
DBUG_ENTER("sp_head::create");
int ret;
- DBUG_PRINT("info", ("type: %d name: %s def: %s",
- m_type, m_name.str, m_defstr.str));
+ DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s",
+ m_type, m_name.str, m_params.str, m_body.str));
if (m_type == TYPE_ENUM_FUNCTION)
- ret= sp_create_function(thd,
- m_name.str, m_name.length,
- m_defstr.str, m_defstr.length,
- m_chistics);
+ ret= sp_create_function(thd, this);
else
- ret= sp_create_procedure(thd,
- m_name.str, m_name.length,
- m_defstr.str, m_defstr.length,
- m_chistics);
+ ret= sp_create_procedure(thd, this);
DBUG_RETURN(ret);
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 0f0c618ffb4..33c6bd4fe38 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -56,6 +56,18 @@ public:
List<char *> m_calls; // Called procedures.
List<char *> m_tables; // Used tables.
#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 *
operator new(size_t size);
@@ -67,7 +79,11 @@ public:
// Initialize after we have reset mem_root
void
- init(LEX_STRING *name, LEX *lex);
+ init(LEX *lex);
+
+ // Initialize strings after parsing header
+ void
+ init_strings(LEX_STRING *name, LEX *lex);
int
create(THD *thd);
@@ -136,6 +152,8 @@ public:
return m_name.str;
}
+ char *create_string(THD *thd, ulong *lenp);
+
inline Item_result result()
{
return sp_map_result_type(m_returns);
@@ -143,15 +161,13 @@ public:
void set_info(char *creator, uint creatorlen,
longlong created, longlong modified,
- bool suid, char *comment, uint commentlen)
+ st_sp_chistics *chistics)
{
m_creator= creator;
m_creatorlen= creatorlen;
m_created= created;
m_modified= modified;
- m_chistics->comment.length= commentlen;
- m_chistics->comment.str= comment;
- m_chistics->suid= (suid ? IS_SUID : IS_NOT_SUID);
+ m_chistics= chistics;
}
inline void reset_thd_mem_root(THD *thd)
@@ -180,13 +196,6 @@ private:
Item *m_free_list; // Where the items go
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
List<LEX> m_lex; // Temp. store for the other lex
DYNAMIC_ARRAY m_instr; // The "instructions"
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 369880486f9..cbafd69b9ac 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1040,7 +1040,7 @@ create:
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(YYTHD);
- sp->init(&$3, lex);
+ sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp;
@@ -1052,10 +1052,18 @@ create:
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
}
- '(' sp_pdparam_list ')'
+ '('
{
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();
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
@@ -1064,11 +1072,13 @@ create:
LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics;
+ lex->sphead->m_body_begin= lex->tok_start;
}
sp_proc_stmt
{
LEX *lex= Lex;
+ lex->sphead->init_strings(&$3, lex);
lex->sql_command= SQLCOM_CREATE_PROCEDURE;
/* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq)
@@ -1103,7 +1113,7 @@ create_function_tail:
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(YYTHD);
- sp->init(&lex->udf.name, lex);
+ sp->init(lex);
sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp;
@@ -1114,16 +1124,25 @@ create_function_tail:
*/
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
+ lex->sphead->m_param_begin= lex->tok_start+1;
}
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->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));
}
sp_c_chistics
@@ -1131,16 +1150,19 @@ create_function_tail:
LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics;
+ lex->sphead->m_body_begin= lex->tok_start;
}
sp_proc_stmt
{
LEX *lex= Lex;
+ sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
+ sp->init_strings(&lex->udf.name, lex);
/* Restore flag if it was cleared above */
- if (lex->sphead->m_old_cmq)
+ if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
- lex->sphead->restore_thd_mem_root(YYTHD);
+ sp->restore_thd_mem_root(YYTHD);
}
;
@@ -5884,6 +5906,7 @@ keyword:
| RESET_SYM {}
| RESOURCES {}
| RESTORE_SYM {}
+ | RETURNS_SYM {}
| ROLLBACK_SYM {}
| ROLLUP_SYM {}
| ROWS_SYM {}