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

WL#1363: Update the mysql.proc table and add new fields.

Also made the parsing and handling of SP characteristics
more general and extendable, and added a few ch:istics.
parent 2c3065c9
......@@ -1052,4 +1052,46 @@
/* Remove an SP from cache */
void sp_cache_remove(sp_cache **cp, sp_head *sp);
- The mysql.proc schema:
CREATE TABLE proc (
schema char(64) binary DEFAULT '' NOT NULL,
name char(64) binary DEFAULT '' NOT NULL,
type enum('FUNCTION','PROCEDURE') NOT NULL,
specific_name char(64) binary DEFAULT '' NOT NULL,
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,
definer char(77) binary DEFAULT '' NOT NULL,
created timestamp,
modified timestamp,
sql_mode set(
'REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
'NOT_USED',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
'POSTGRESQL',
'ORACLE',
'MSSQL',
'DB2',
'MAXDB',
'NO_KEY_OPTIONS',
'NO_TABLE_OPTIONS',
'NO_FIELD_OPTIONS',
'MYSQL323',
'MYSQL40',
'ANSI',
'NO_AUTO_VALUE_ON_ZERO'
) DEFAULT 0 NOT NULL,
comment char(64) binary DEFAULT '' NOT NULL,
PRIMARY KEY (schema,name,type)
) comment='Stored Procedures';
--
Stored Procedures implemented 2003-09-16:
Stored Procedures implemented 2003-12-10:
Summary of Not Yet Implemented:
- SQL queries (like SELECT, INSERT, UPDATE etc) in FUNCTION bodies
- SQL statements using table (like SELECT, INSERT, UPDATE etc)
in FUNCTIONs
- External languages
- Access control
- Routine characteristics (mostly used for external languages)
......@@ -25,18 +26,28 @@ Summary of what's implemented:
- Prepared SP caching
- CONDITIONs and HANDLERs
- Simple read-only CURSORs.
- SHOW DECLARE PROCEDURE/FUNCTION and SHOW PROCEDURE/FUNCTION STATUS
List of what's implemented:
- CREATE PROCEDURE|FUNCTION name ( args ) body
No routine characteristics yet.
List of what's implemented:
- ALTER PROCEDURE|FUNCTION name ...
Is parsed, but a no-op (as there are no characteristics implemented yet).
CASCADE/RESTRICT is not implemented (and CASCADE probably will not be).
- CREATE PROCEDURE|FUNCTION name ( args ) characteristics body
where characteristics is:
LANGUAGE SQL |
[NOT] DETERMINISTIC |
SQL SECURITY [DEFINER|INVOKER] |
COMMENT string
However the DETERMINISTIC setting is not currently used.
- ALTER PROCEDURE|FUNCTION name characteristics
CASCADE/RESTRICT is not implemented.
characteristics is:
COMMENT string |
SQL SECURITY [DEFINER|INVOKER] |
NAME newname
- DROP PROCEDURE|FUNCTION [IF EXISTS] name
CASCADE/RESTRICT is not implemented (and CASCADE probably will not be).
CASCADE/RESTRICT is not implemented.
- CALL name (args)
OUT and INOUT parameters are only supported for local variables, and
......@@ -92,23 +103,9 @@ List of what's implemented:
(The additional syntax will be added for completeness, but for the
most part unsupported with the current underlying cursor mechanism.)
Closed questions:
- What is the expected result when creating a procedure with a name that
already exists? An error or overwrite?
Answer: Error
- Do PROCEDUREs and FUNCTIONs share namespace or not? I think not, but the
we need to flag the type in the mysql.proc table and the name alone is
not a unique key any more, or, we have separate tables.
(Unfortunately, mysql.func is already taken. Use "sfunc" and maybe even
rename "proc" into "sproc" while we still can, for consistency?)
Answer: Same tables, with an additional key-field for the type.
Open questions/issues:
- SQL-99 variables and parameters are typed. For the present we don't do
any type checking, since this is the way MySQL works. I still don't know
if we should keep it this way, or implement type checking. Possibly we
should have optional, uset-settable, type checking.
- SHOW procedures and functions
SHOW DECLARE PROCEDURE|FUNCTION <name>
returns the definition of a routine.
SHOW PROCEDURE|FUNCTION STATUS [LIKE <pattern>]
returns characteristics of routines, like the name, type, creator,
creation and modification dates, etc.
......@@ -852,12 +852,12 @@ n f
20 2432902008176640000
drop table fac;
show function status like '%f%';
Name Type Creator Modified Created Suid Comment
fac function root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y
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
drop procedure ifac;
drop function fac;
show function status like '%f%';
Name Type Creator Modified Created Suid Comment
Name Type Definer Modified Created Security_type Comment
drop table if exists primes;
create table primes (
i int unsigned not null primary key,
......@@ -945,9 +945,9 @@ end if;
end loop;
end
show procedure status like '%p%';
Name Type Creator Modified Created Suid Comment
ip procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y
opp procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y
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
call ip(200);
select * from primes where i=45 or i=100 or i=199;
i p
......@@ -958,7 +958,7 @@ drop table primes;
drop procedure opp;
drop procedure ip;
show procedure status like '%p%';
Name Type Creator Modified Created Suid Comment
Name Type Definer Modified Created Security_type Comment
drop table if exists fib;
create table fib ( f bigint unsigned not null );
insert into fib values (1), (1);
......@@ -1008,8 +1008,8 @@ create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
insert into test.t1 values (x, y);
show procedure status like 'bar';
Name Type Creator Modified Created Suid Comment
bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 N 111111111111
Name Type Definer Modified Created Security_type Comment
bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER 111111111111
alter procedure bar name bar2 comment "2222222222" sql security definer;
alter procedure bar2 name bar comment "3333333333";
alter procedure bar;
......@@ -1019,8 +1019,8 @@ bar create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
insert into test.t1 values (x, y)
show procedure status like 'bar';
Name Type Creator Modified Created Suid Comment
bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y 3333333333
Name Type Definer Modified Created Security_type Comment
bar PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER 3333333333
drop procedure bar;
drop table t1;
drop table t2;
......@@ -289,19 +289,45 @@ fi
if test ! -f $mdata/proc.frm
then
c_p="$c_p CREATE TABLE proc ("
c_p="$c_p name char(64) binary DEFAULT '' NOT NULL,"
c_p="$c_p type enum('function','procedure') NOT NULL,"
c_p="$c_p body blob DEFAULT '' NOT NULL,"
c_p="$c_p creator char(77) binary DEFAULT '' NOT NULL,"
c_p="$c_p modified timestamp,"
c_p="$c_p created timestamp,"
c_p="$c_p suid enum ('N', 'Y') DEFAULT 'Y' NOT NULL,"
c_p="$c_p comment char(64) binary DEFAULT '' NOT NULL,"
c_p="$c_p PRIMARY KEY (name,type)"
c_p="$c_p )"
c_p="$c_p comment='Stored Procedures';"
c_p="$c_p schema char(64) binary DEFAULT '' NOT NULL,"
c_p="$c_p name char(64) binary DEFAULT '' NOT NULL,"
c_p="$c_p type enum('FUNCTION','PROCEDURE') NOT NULL,"
c_p="$c_p specific_name char(64) binary DEFAULT '' 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 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 definer char(77) binary DEFAULT '' NOT NULL,"
c_p="$c_p created timestamp,"
c_p="$c_p modified timestamp,"
c_p="$c_p sql_mode set("
c_p="$c_p 'REAL_AS_FLOAT',"
c_p="$c_p 'PIPES_AS_CONCAT',"
c_p="$c_p 'ANSI_QUOTES',"
c_p="$c_p 'IGNORE_SPACE',"
c_p="$c_p 'NOT_USED',"
c_p="$c_p 'ONLY_FULL_GROUP_BY',"
c_p="$c_p 'NO_UNSIGNED_SUBTRACTION',"
c_p="$c_p 'NO_DIR_IN_CREATE',"
c_p="$c_p 'POSTGRESQL',"
c_p="$c_p 'ORACLE',"
c_p="$c_p 'MSSQL',"
c_p="$c_p 'DB2',"
c_p="$c_p 'MAXDB',"
c_p="$c_p 'NO_KEY_OPTIONS',"
c_p="$c_p 'NO_TABLE_OPTIONS',"
c_p="$c_p 'NO_FIELD_OPTIONS',"
c_p="$c_p 'MYSQL323',"
c_p="$c_p 'MYSQL40',"
c_p="$c_p 'ANSI',"
c_p="$c_p 'NO_AUTO_VALUE_ON_ZERO'"
c_p="$c_p ) DEFAULT 0 NOT NULL,"
c_p="$c_p comment char(64) binary DEFAULT '' NOT NULL,"
c_p="$c_p PRIMARY KEY (schema,name,type)"
c_p="$c_p ) comment='Stored Procedures';"
fi
cat << END_OF_DATA
use mysql;
$c_d
......
......@@ -140,14 +140,40 @@ unique index (name)
#
CREATE TABLE IF NOT EXISTS proc (
name char(64) binary DEFAULT '' NOT NULL,
type enum('function','procedure') NOT NULL,
body blob DEFAULT '' NOT NULL,
creator char(77) binary DEFAULT '' NOT NULL,
modified timestamp,
created timestamp,
suid enum ('N', 'Y') DEFAULT 'Y' NOT NULL,
comment char(64) binary DEFAULT '' NOT NULL,
PRIMARY KEY (name,type)
schema char(64) binary DEFAULT '' NOT NULL,
name char(64) binary DEFAULT '' NOT NULL,
type enum('FUNCTION','PROCEDURE') NOT NULL,
specific_name char(64) binary DEFAULT '' NOT NULL,
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,
definer char(77) binary DEFAULT '' NOT NULL,
created timestamp,
modified timestamp,
sql_mode set(
'REAL_AS_FLOAT',
'PIPES_AS_CONCAT',
'ANSI_QUOTES',
'IGNORE_SPACE',
'NOT_USED',
'ONLY_FULL_GROUP_BY',
'NO_UNSIGNED_SUBTRACTION',
'NO_DIR_IN_CREATE',
'POSTGRESQL',
'ORACLE',
'MSSQL',
'DB2',
'MAXDB',
'NO_KEY_OPTIONS',
'NO_TABLE_OPTIONS',
'NO_FIELD_OPTIONS',
'MYSQL323',
'MYSQL40',
'ANSI',
'NO_AUTO_VALUE_ON_ZERO'
) DEFAULT 0 NOT NULL,
comment char(64) binary DEFAULT '' NOT NULL,
PRIMARY KEY (schema,name,type)
) comment='Stored Procedures';
......@@ -136,6 +136,7 @@ static SYMBOL symbols[] = {
{ "DELETE", SYM(DELETE_SYM),0,0},
{ "DESC", SYM(DESC),0,0},
{ "DESCRIBE", SYM(DESCRIBE),0,0},
{ "DETERMINISTIC", SYM(DETERMINISTIC_SYM),0,0},
{ "DIRECTORY", SYM(DIRECTORY_SYM),0,0},
{ "DISABLE", SYM(DISABLE_SYM),0,0},
{ "DISCARD", SYM(DISCARD),0,0},
......@@ -240,6 +241,7 @@ static SYMBOL symbols[] = {
{ "KEY", SYM(KEY_SYM),0,0},
{ "KEYS", SYM(KEYS),0,0},
{ "KILL", SYM(KILL_SYM),0,0},
{ "LANGUAGE", SYM(LANGUAGE_SYM),0,0},
{ "LAST", SYM(LAST_SYM),0,0},
{ "LEADING", SYM(LEADING),0,0},
{ "LEAVE", SYM(LEAVE_SYM),0,0},
......
......@@ -26,15 +26,21 @@
*
*/
#define MYSQL_PROC_FIELD_NAME 0
#define MYSQL_PROC_FIELD_TYPE 1
#define MYSQL_PROC_FIELD_DEFINITION 2
#define MYSQL_PROC_FIELD_CREATOR 3
#define MYSQL_PROC_FIELD_MODIFIED 4
#define MYSQL_PROC_FIELD_CREATED 5
#define MYSQL_PROC_FIELD_SUID 6
#define MYSQL_PROC_FIELD_COMMENT 7
#define MYSQL_PROC_FIELD_COUNT 8
#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
/* *opened=true means we opened ourselves */
static int
......@@ -44,17 +50,18 @@ db_find_routine_aux(THD *thd, int type, char *name, uint namelen,
DBUG_ENTER("db_find_routine_aux");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
TABLE *table;
byte key[65]; // We know name is 64 and the enum is 1 byte
byte key[64+64+1]; // schema, name, type
uint keylen;
int ret;
// Put the key together
memset(key, (int)' ', 64); // QQ Empty schema for now
keylen= namelen;
if (keylen > sizeof(key)-1)
keylen= sizeof(key)-1;
memcpy(key, name, keylen);
memset(key+keylen, (int)' ', sizeof(key)-1 - keylen); // Pad with space
key[sizeof(key)-1]= type;
if (keylen > 64)
keylen= 64;
memcpy(key+64, name, keylen);
memset(key+64+keylen, (int)' ', 64-keylen); // Pad with space
key[128]= type;
keylen= sizeof(key);
for (table= thd->open_tables ; table ; table= table->next)
......@@ -128,7 +135,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
// Get additional information
if ((creator= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_CREATOR])) == NULL)
table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
......@@ -138,7 +145,7 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int();
if ((ptr= get_field(&thd->mem_root,
table->field[MYSQL_PROC_FIELD_SUID])) == NULL)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
......@@ -180,9 +187,9 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
else
{
*sphp= thd->lex->sphead;
(*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
created, modified, suid,
ptr, length);
(*sphp)->set_info((char *) creator, (uint) strlen(creator),
created, modified, suid,
ptr, length);
}
thd->lex->sql_command= oldcmd;
}
......@@ -196,7 +203,7 @@ 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,
char *comment, uint commentlen, bool suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("db_create_routine");
DBUG_PRINT("enter", ("type: %d name: %*s def: %*s", type, namelen, name, deflen, def));
......@@ -224,17 +231,24 @@ db_create_routine(THD *thd, int type,
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_CREATOR]->store(creator,
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 (!suid)
table->field[MYSQL_PROC_FIELD_SUID]->store((longlong) 1);
if (comment)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(comment, commentlen,
system_charset_info);
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);
if (table->file->write_row(table->record[0]))
ret= SP_WRITE_ROW_FAILED;
......@@ -271,7 +285,7 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen)
static int
db_update_routine(THD *thd, int type, char *name, uint namelen,
char *newname, uint newnamelen,
char *comment, uint commentlen, enum suid_behaviour suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("db_update_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
......@@ -284,15 +298,15 @@ 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 (suid)
table->field[MYSQL_PROC_FIELD_SUID]->store((longlong) suid);
if (chistics->suid)
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]->store((longlong)chistics->suid);
if (newname)
table->field[MYSQL_PROC_FIELD_NAME]->store(newname,
newnamelen,
system_charset_info);
if (comment)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(comment,
commentlen,
if (chistics->comment.str)
table->field[MYSQL_PROC_FIELD_COMMENT]->store(chistics->comment.str,
chistics->comment.length,
system_charset_info);
if ((table->file->update_row(table->record[1],table->record[0])))
ret= SP_WRITE_ROW_FAILED;
......@@ -314,10 +328,10 @@ static struct st_used_field init_fields[]=
{
{ "Name", NAME_LEN, MYSQL_TYPE_STRING, 0},
{ "Type", 9, MYSQL_TYPE_STRING, 0},
{ "Creator", 77, MYSQL_TYPE_STRING, 0},
{ "Definer", 77, MYSQL_TYPE_STRING, 0},
{ "Modified", 0, MYSQL_TYPE_TIMESTAMP, 0},
{ "Created", 0, MYSQL_TYPE_TIMESTAMP, 0},
{ "Suid", 1, MYSQL_TYPE_STRING, 0},
{ "Security_type", 1, MYSQL_TYPE_STRING, 0},
{ "Comment", NAME_LEN, MYSQL_TYPE_STRING, 0},
{ 0, 0, MYSQL_TYPE_STRING, 0}
};
......@@ -347,6 +361,8 @@ print_field_values(THD *thd, TABLE *table,
case MYSQL_TYPE_TIMESTAMP:
{
TIME tmp_time;
bzero((char *)&tmp_time, sizeof(tmp_time));
((Field_timestamp *) used_field->field)->get_time(&tmp_time);
protocol->store(&tmp_time);
}
......@@ -354,6 +370,7 @@ print_field_values(THD *thd, TABLE *table,
default:
{
String *tmp_string1= new String();
get_field(&thd->mem_root, used_field->field, tmp_string1);
protocol->store(tmp_string1);
}
......@@ -490,14 +507,14 @@ sp_find_procedure(THD *thd, LEX_STRING *name)
int
sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen,
char *comment, uint commentlen, bool suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("sp_create_procedure");
DBUG_PRINT("enter", ("name: %*s def: %*s", namelen, name, deflen, def));
int ret;
ret= db_create_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, def, deflen,
comment, commentlen, suid);
chistics);
DBUG_RETURN(ret);
}
......@@ -521,7 +538,7 @@ sp_drop_procedure(THD *thd, char *name, uint namelen)
int
sp_update_procedure(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen,
char *comment, uint commentlen, enum suid_behaviour suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("sp_update_procedure");
DBUG_PRINT("enter", ("name: %*s", namelen, name));
......@@ -533,7 +550,7 @@ sp_update_procedure(THD *thd, char *name, uint namelen,
delete sp;
ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen,
newname, newnamelen,
comment, commentlen, suid);
chistics);
DBUG_RETURN(ret);
}
......@@ -585,14 +602,14 @@ sp_find_function(THD *thd, LEX_STRING *name)
int
sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen,
char *comment, uint commentlen, bool suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("sp_create_function");
DBUG_PRINT("enter", ("name: %*s def: %*s", namelen, name, deflen, def));
int ret;
ret= db_create_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, def, deflen,
comment, commentlen, suid);
chistics);
DBUG_RETURN(ret);
}
......@@ -616,7 +633,7 @@ sp_drop_function(THD *thd, char *name, uint namelen)
int
sp_update_function(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen,
char *comment, uint commentlen, enum suid_behaviour suid)
st_sp_chistics *chistics)
{
DBUG_ENTER("sp_update_procedure");
DBUG_PRINT("enter", ("name: %*s", namelen, name));
......@@ -628,7 +645,7 @@ sp_update_function(THD *thd, char *name, uint namelen,
delete sp;
ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen,
newname, newnamelen,
comment, commentlen, suid);
chistics);
DBUG_RETURN(ret);
}
......
......@@ -33,7 +33,7 @@ sp_find_procedure(THD *thd, LEX_STRING *name);
int
sp_create_procedure(THD *thd, char *name, uint namelen, char *def, uint deflen,
char *comment, uint commentlen, bool suid);
st_sp_chistics *chistics);
int
sp_drop_procedure(THD *thd, char *name, uint namelen);
......@@ -42,7 +42,7 @@ sp_drop_procedure(THD *thd, char *name, uint namelen);
int
sp_update_procedure(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen,
char *comment, uint commentlen, enum suid_behaviour suid);
st_sp_chistics *chistics);
int
sp_show_create_procedure(THD *thd, LEX_STRING *name);
......@@ -55,7 +55,7 @@ sp_find_function(THD *thd, LEX_STRING *name);
int
sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen,
char *comment, uint commentlen, bool suid);
st_sp_chistics *chistics);
int
sp_drop_function(THD *thd, char *name, uint namelen);
......@@ -63,7 +63,7 @@ sp_drop_function(THD *thd, char *name, uint namelen);
int
sp_update_function(THD *thd, char *name, uint namelen,
char *newname, uint newnamelen,
char *comment, uint commentlen, enum suid_behaviour suid);
st_sp_chistics *chistics);
int
sp_show_create_function(THD *thd, LEX_STRING *name);
......
......@@ -190,14 +190,12 @@ sp_head::create(THD *thd)
ret= sp_create_function(thd,
m_name.str, m_name.length,
m_defstr.str, m_defstr.length,
m_comment.str, m_comment.length,
m_suid);
m_chistics);
else
ret= sp_create_procedure(thd,
m_name.str, m_name.length,
m_defstr.str, m_defstr.length,
m_comment.str, m_comment.length,
m_suid);
m_chistics);
DBUG_RETURN(ret);
}
......
......@@ -50,6 +50,7 @@ public:
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics;
#if NOT_USED_NOW
// QQ We're not using this at the moment.
List<char *> m_calls; // Called procedures.
......@@ -68,20 +69,6 @@ public:
void
init(LEX_STRING *name, LEX *lex);
void
init_options(LEX_STRING *comment, enum suid_behaviour suid)
{
m_comment.length= 0;
m_comment.str= 0;
if (comment)
{
m_comment.length= comment->length;
m_comment.str= comment->str;
}
m_suid= suid ? suid - 1 : 1;
}
int
create(THD *thd);
......@@ -154,17 +141,17 @@ public:
return sp_map_result_type(m_returns);
}
void sp_set_info(char *creator, uint creatorlen,
longlong created, longlong modified,
bool suid, char *comment, uint commentlen)
void set_info(char *creator, uint creatorlen,
longlong created, longlong modified,
bool suid, char *comment, uint commentlen)
{
m_creator= creator;
m_creatorlen= creatorlen;
m_created= created;
m_modified= modified;
m_comment.length= commentlen;
m_comment.str= comment;
m_suid= suid;
m_chistics->comment.length= commentlen;
m_chistics->comment.str= comment;
m_chistics->suid= (suid ? IS_SUID : IS_NOT_SUID);
}
inline void reset_thd_mem_root(THD *thd)
......@@ -195,12 +182,10 @@ private:
LEX_STRING m_name;
LEX_STRING m_defstr;
LEX_STRING m_comment;
char *m_creator;
uint m_creatorlen;
longlong m_created;
longlong m_modified;
bool m_suid;
sp_pcontext *m_pcont; // Parse context
List<LEX> m_lex; // Temp. store for the other lex
......
......@@ -517,6 +517,13 @@ public:
typedef class st_select_lex SELECT_LEX;
struct st_sp_chistics
{
LEX_STRING comment;
enum suid_behaviour suid;
bool detistic;
};
/* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex
......@@ -583,7 +590,6 @@ typedef struct st_lex
enum enum_enable_or_disable alter_keys_onoff;
enum enum_var_type option_type;
enum tablespace_op_type tablespace_op;
enum suid_behaviour suid;
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
......@@ -598,6 +604,7 @@ typedef struct st_lex
bool sp_lex_in_use; /* Keep track on lex usage in SPs for error handling */
sp_pcontext *spcont;
HASH spfuns; /* Called functions */
st_sp_chistics sp_chistics;
st_lex()
{
......
......@@ -3558,12 +3558,10 @@ mysql_execute_command(THD *thd)
}
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
res= sp_update_procedure(thd, lex->udf.name.str, lex->udf.name.length,
lex->name, newname_len, lex->comment->str,
lex->comment->length, lex->suid);
lex->name, newname_len, &lex->sp_chistics);
else
res= sp_update_function(thd, lex->udf.name.str, lex->udf.name.length,
lex->name, newname_len, lex->comment->str,
lex->comment->length, lex->suid);
lex->name, newname_len, &lex->sp_chistics);
switch (res)
{
case SP_OK:
......
......@@ -139,6 +139,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CUBE_SYM
%token DEFINER_SYM
%token DELETE_SYM
%token DETERMINISTIC_SYM
%token DUAL_SYM
%token DO_SYM
%token DROP
......@@ -283,6 +284,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token LEAVES
%token LEVEL_SYM
%token LEX_HOSTNAME
%token LANGUAGE_SYM
%token LIKE
%token LINES
%token LOCAL_SYM
......@@ -630,7 +632,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
SP_FUNC ident_or_spfunc sp_opt_label sp_comment sp_newname
SP_FUNC ident_or_spfunc sp_opt_label
%type <lex_str_ptr>
opt_table_alias
......@@ -761,6 +763,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
subselect_end select_var_list select_var_list_init help opt_len
opt_extended_describe
statement sp_suid
sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic sp_a_chistic
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmt
......@@ -1051,11 +1054,16 @@ create:
}
'(' sp_pdparam_list ')'
{
Lex->spcont->set_params();
LEX *lex= Lex;
lex->spcont->set_params();
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_comment sp_suid
sp_c_chistics
{
Lex->sphead->init_options(&$9, Lex->suid);
LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics;
}
sp_proc_stmt
{
......@@ -1113,17 +1121,22 @@ create_function_tail:
}
RETURNS_SYM type
{
Lex->sphead->m_returns= (enum enum_field_types)$7;
LEX *lex= Lex;
lex->sphead->m_returns= (enum enum_field_types)$7;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_comment sp_suid
sp_c_chistics
{
Lex->sphead->init_options(&$9, Lex->suid);
}
LEX *lex= Lex;
lex->sphead->m_chistics= &lex->sp_chistics;
}
sp_proc_stmt
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_CREATE_SPFUNCTION;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
/* Restore flag if it was cleared above */
if (lex->sphead->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
......@@ -1131,21 +1144,45 @@ create_function_tail:
}
;
sp_comment:
/* Empty */ { $$.str= 0; $$.length= 0; }
| COMMENT_SYM TEXT_STRING_sys { $$= $2; }
sp_a_chistics:
/* Empty */ {}
| sp_a_chistics sp_a_chistic {}
;
sp_c_chistics:
/* Empty */ {}
| sp_c_chistics sp_c_chistic {}
;
/* Characteristics for both create and alter */
sp_chistic:
COMMENT_SYM TEXT_STRING_sys { Lex->sp_chistics.comment= $2; }
| sp_suid { }
;
sp_newname:
/* Empty */ { $$.str= 0; $$.length= 0; }
| NAME_SYM ident { $$= $2; }
/* Alter characteristics */
sp_a_chistic:
sp_chistic { }
| NAME_SYM ident { Lex->name= $2.str; }
;
/* Create characteristics */
sp_c_chistic:
sp_chistic { }
| LANGUAGE_SYM SQL_SYM { }
| DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; }
| NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
;
sp_suid:
/* Empty */ { Lex->suid= IS_DEFAULT_SUID; }
| SQL_SYM SECURITY_SYM DEFINER_SYM { Lex->suid= IS_SUID; }
| SQL_SYM SECURITY_SYM INVOKER_SYM { Lex->suid= IS_NOT_SUID; }
SQL_SYM SECURITY_SYM DEFINER_SYM
{
Lex->sp_chistics.suid= IS_SUID;
}
| SQL_SYM SECURITY_SYM INVOKER_SYM
{
Lex->sp_chistics.suid= IS_NOT_SUID;
}
;
call:
......@@ -2648,36 +2685,35 @@ alter:
lex->sql_command=SQLCOM_ALTER_DB;
lex->name=$3.str;
}
| ALTER PROCEDURE ident sp_newname sp_comment sp_suid
opt_restrict
| ALTER PROCEDURE ident
{
LEX *lex= Lex;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
Lex->name= 0;
}
sp_a_chistics
{
THD *thd= YYTHD;
LEX *lex=Lex;
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
lex->udf.name= $3;
lex->name= $4.str;
/* $5 is a yacc/bison internal struct, so we can't keep
the pointer to it for use outside the parser. */
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment->str= $5.str;
lex->comment->length= $5.length;
}
| ALTER FUNCTION_SYM ident sp_newname sp_comment sp_suid
opt_restrict
| ALTER FUNCTION_SYM ident
{
LEX *lex= Lex;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->name= 0;
}
sp_a_chistics
{
THD *thd= YYTHD;
LEX *lex=Lex;
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->udf.name= $3;
lex->name= $4.str;
/* $5 is a yacc/bison internal struct, so we can't keep
the pointer to it for use outside the parser. */
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
lex->comment->str= $5.str;
lex->comment->length= $5.length;
}
;
......@@ -5775,6 +5811,7 @@ keyword:
| INNOBASE_SYM {}
| INSERT_METHOD {}
| RELAY_THREAD {}
| LANGUAGE_SYM {}
| LAST_SYM {}
| LEAVES {}
| LEVEL_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