diff options
-rw-r--r-- | Docs/sp-imp-spec.txt | 11 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 49 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 30 | ||||
-rw-r--r-- | scripts/mysql_create_system_tables.sh | 6 | ||||
-rw-r--r-- | scripts/mysql_fix_privilege_tables.sql | 6 | ||||
-rw-r--r-- | sql/sp.cc | 223 | ||||
-rw-r--r-- | sql/sp.h | 6 | ||||
-rw-r--r-- | sql/sp_head.cc | 57 | ||||
-rw-r--r-- | sql/sp_head.h | 33 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 39 |
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; +} @@ -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 {} |