Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
e44a0c2a
Commit
e44a0c2a
authored
Nov 17, 2003
by
gluh@gluh.mysql.r18.ru
Browse files
Options
Browse Files
Download
Plain Diff
Merge sgluhov@bk-internal.mysql.com:/home/bk/mysql-5.0
into gluh.mysql.r18.ru:/home/gluh/mysql-5.0.sp
parents
34d76c93
ee4ed0c9
Changes
36
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
600 additions
and
32 deletions
+600
-32
include/mysqld_error.h
include/mysqld_error.h
+2
-1
mysql-test/r/sp-error.result
mysql-test/r/sp-error.result
+5
-0
mysql-test/r/sp.result
mysql-test/r/sp.result
+52
-0
mysql-test/t/sp-error.test
mysql-test/t/sp-error.test
+6
-0
mysql-test/t/sp.test
mysql-test/t/sp.test
+18
-0
sql/lex.h
sql/lex.h
+4
-0
sql/share/czech/errmsg.txt
sql/share/czech/errmsg.txt
+1
-0
sql/share/danish/errmsg.txt
sql/share/danish/errmsg.txt
+1
-0
sql/share/dutch/errmsg.txt
sql/share/dutch/errmsg.txt
+1
-0
sql/share/english/errmsg.txt
sql/share/english/errmsg.txt
+1
-0
sql/share/estonian/errmsg.txt
sql/share/estonian/errmsg.txt
+1
-0
sql/share/french/errmsg.txt
sql/share/french/errmsg.txt
+1
-0
sql/share/german/errmsg.txt
sql/share/german/errmsg.txt
+1
-0
sql/share/greek/errmsg.txt
sql/share/greek/errmsg.txt
+1
-0
sql/share/hungarian/errmsg.txt
sql/share/hungarian/errmsg.txt
+1
-0
sql/share/italian/errmsg.txt
sql/share/italian/errmsg.txt
+1
-0
sql/share/japanese/errmsg.txt
sql/share/japanese/errmsg.txt
+1
-0
sql/share/korean/errmsg.txt
sql/share/korean/errmsg.txt
+1
-0
sql/share/norwegian-ny/errmsg.txt
sql/share/norwegian-ny/errmsg.txt
+1
-0
sql/share/norwegian/errmsg.txt
sql/share/norwegian/errmsg.txt
+1
-0
sql/share/polish/errmsg.txt
sql/share/polish/errmsg.txt
+1
-0
sql/share/portuguese/errmsg.txt
sql/share/portuguese/errmsg.txt
+1
-0
sql/share/romanian/errmsg.txt
sql/share/romanian/errmsg.txt
+1
-0
sql/share/russian/errmsg.txt
sql/share/russian/errmsg.txt
+1
-0
sql/share/serbian/errmsg.txt
sql/share/serbian/errmsg.txt
+1
-0
sql/share/slovak/errmsg.txt
sql/share/slovak/errmsg.txt
+1
-0
sql/share/spanish/errmsg.txt
sql/share/spanish/errmsg.txt
+1
-0
sql/share/swedish/errmsg.txt
sql/share/swedish/errmsg.txt
+1
-0
sql/share/ukrainian/errmsg.txt
sql/share/ukrainian/errmsg.txt
+1
-0
sql/sp.cc
sql/sp.cc
+259
-2
sql/sp.h
sql/sp.h
+22
-0
sql/sp_head.cc
sql/sp_head.cc
+50
-11
sql/sp_head.h
sql/sp_head.h
+21
-1
sql/sql_lex.h
sql/sql_lex.h
+8
-0
sql/sql_parse.cc
sql/sql_parse.cc
+67
-10
sql/sql_yacc.yy
sql/sql_yacc.yy
+63
-7
No files found.
include/mysqld_error.h
View file @
e44a0c2a
...
...
@@ -327,4 +327,5 @@
#define ER_SP_DUP_VAR 1308
#define ER_SP_DUP_COND 1309
#define ER_SP_DUP_CURS 1310
#define ER_ERROR_MESSAGES 311
#define ER_SP_CANT_ALTER 1311
#define ER_ERROR_MESSAGES 312
mysql-test/r/sp-error.result
View file @
e44a0c2a
...
...
@@ -187,6 +187,11 @@ end;
call p();
ERROR HY000: Cursor is not open
drop procedure p;
alter procedure bar3 SECURITY INVOKER;
ERROR HY000: PROCEDURE bar3 does not exist
alter procedure bar3 name
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
ERROR 42000: Identifier name 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' is too long
drop table t1;
drop table if exists t1;
create table t1 (val int, x float);
...
...
mysql-test/r/sp.result
View file @
e44a0c2a
...
...
@@ -734,6 +734,9 @@ n f
19 121645100408832000
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
drop procedure ifac;
drop function fac;
drop table if exists primes;
...
...
@@ -794,6 +797,38 @@ set p = p+2;
end;
end while;
end;
show create procedure opp;
Procedure Create Procedure
opp create procedure opp(n bigint unsigned, out pp bool)
begin
declare r double;
declare b, s bigint unsigned default 0;
set r = sqrt(n);
again:
loop
if s = 45 then
set b = b+200, s = 0;
else
begin
declare p bigint unsigned;
select t.p into p from test.primes t where t.i = s;
if b+p > r then
set pp = 1;
leave again;
end if;
if mod(n, b+p) = 0 then
set pp = 0;
leave again;
end if;
set s = s+1;
end;
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
call ip(200);
select * from primes where i=45 or i=100 or i=199;
i p
...
...
@@ -803,5 +838,22 @@ i p
drop table primes;
drop procedure opp;
drop procedure ip;
create procedure bar(x char(16), y int)
comment "111111111111" 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
alter procedure bar name bar2 comment "2222222222" SECURITY DEFINER;
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" 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
drop table t1;
drop table t2;
mysql-test/t/sp-error.test
View file @
e44a0c2a
...
...
@@ -256,6 +256,12 @@ end|
call
p
()
|
drop
procedure
p
|
--
error
1282
alter
procedure
bar3
SECURITY
INVOKER
|
--
error
1059
alter
procedure
bar3
name
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
drop
table
t1
|
--
disable_warnings
...
...
mysql-test/t/sp.test
View file @
e44a0c2a
...
...
@@ -852,6 +852,8 @@ end|
call
ifac
(
20
)
|
select
*
from
fac
|
drop
table
fac
|
--
replace_column
4
'0000-00-00 00:00:00'
5
'0000-00-00 00:00:00'
show
function
status
like
'%f%'
|
drop
procedure
ifac
|
drop
function
fac
|
...
...
@@ -928,6 +930,9 @@ begin
end
;
end
while
;
end
|
show
create
procedure
opp
|
--
replace_column
4
'0000-00-00 00:00:00'
5
'0000-00-00 00:00:00'
show
procedure
status
like
'%p%'
|
# This isn't the fastest way in the world to compute prime numbers, so
# don't be too ambitious. ;-)
...
...
@@ -939,6 +944,19 @@ drop table primes|
drop
procedure
opp
|
drop
procedure
ip
|
# Comment & suid
create
procedure
bar
(
x
char
(
16
),
y
int
)
comment
"111111111111"
SECURITY
INVOKER
insert
into
test
.
t1
values
(
x
,
y
)
|
--
replace_column
4
'0000-00-00 00:00:00'
5
'0000-00-00 00:00:00'
show
procedure
status
like
'bar'
|
alter
procedure
bar
name
bar2
comment
"2222222222"
SECURITY
DEFINER
|
alter
procedure
bar2
name
bar
comment
"3333333333"
|
alter
procedure
bar
|
show
create
procedure
bar
|
--
replace_column
4
'0000-00-00 00:00:00'
5
'0000-00-00 00:00:00'
show
procedure
status
like
'bar'
|
delimiter
;
|
drop
table
t1
;
drop
table
t2
;
sql/lex.h
View file @
e44a0c2a
...
...
@@ -130,6 +130,7 @@ static SYMBOL symbols[] = {
{
"DECLARE"
,
SYM
(
DECLARE_SYM
),
0
,
0
},
{
"DES_KEY_FILE"
,
SYM
(
DES_KEY_FILE
),
0
,
0
},
{
"DEFAULT"
,
SYM
(
DEFAULT
),
0
,
0
},
{
"DEFINER"
,
SYM
(
DEFINER
),
0
,
0
},
{
"DELAYED"
,
SYM
(
DELAYED_SYM
),
0
,
0
},
{
"DELAY_KEY_WRITE"
,
SYM
(
DELAY_KEY_WRITE_SYM
),
0
,
0
},
{
"DELETE"
,
SYM
(
DELETE_SYM
),
0
,
0
},
...
...
@@ -232,6 +233,7 @@ static SYMBOL symbols[] = {
{
"ISOLATION"
,
SYM
(
ISOLATION
),
0
,
0
},
{
"ISSUER"
,
SYM
(
ISSUER_SYM
),
0
,
0
},
{
"ITERATE"
,
SYM
(
ITERATE_SYM
),
0
,
0
},
{
"INVOKER"
,
SYM
(
INVOKER
),
0
,
0
},
{
"JOIN"
,
SYM
(
JOIN_SYM
),
0
,
0
},
{
"KEY"
,
SYM
(
KEY_SYM
),
0
,
0
},
{
"KEYS"
,
SYM
(
KEYS
),
0
,
0
},
...
...
@@ -295,6 +297,7 @@ static SYMBOL symbols[] = {
{
"MULTILINESTRING"
,
SYM
(
MULTILINESTRING
),
0
,
0
},
{
"MULTIPOINT"
,
SYM
(
MULTIPOINT
),
0
,
0
},
{
"MULTIPOLYGON"
,
SYM
(
MULTIPOLYGON
),
0
,
0
},
{
"NAME"
,
SYM
(
NAME_SYM
),
0
,
0
},
{
"NAMES"
,
SYM
(
NAMES_SYM
),
0
,
0
},
{
"NATURAL"
,
SYM
(
NATURAL
),
0
,
0
},
{
"NATIONAL"
,
SYM
(
NATIONAL_SYM
),
0
,
0
},
...
...
@@ -367,6 +370,7 @@ static SYMBOL symbols[] = {
{
"SAVEPOINT"
,
SYM
(
SAVEPOINT_SYM
),
0
,
0
},
{
"SECOND"
,
SYM
(
SECOND_SYM
),
0
,
0
},
{
"SECOND_MICROSECOND"
,
SYM
(
SECOND_MICROSECOND_SYM
),
0
,
0
},
{
"SECURITY"
,
SYM
(
SECURITY
),
0
,
0
},
{
"SEPARATOR"
,
SYM
(
SEPARATOR_SYM
),
0
,
0
},
{
"SELECT"
,
SYM
(
SELECT_SYM
),
0
,
0
},
{
"SENSITIVE"
,
SYM
(
SENSITIVE_SYM
),
0
,
0
},
...
...
sql/share/czech/errmsg.txt
View file @
e44a0c2a
...
...
@@ -323,3 +323,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/danish/errmsg.txt
View file @
e44a0c2a
...
...
@@ -317,3 +317,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/dutch/errmsg.txt
View file @
e44a0c2a
...
...
@@ -325,3 +325,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/english/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/estonian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -319,3 +319,4 @@ character-set=latin7
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/french/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/german/errmsg.txt
View file @
e44a0c2a
...
...
@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/greek/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=greek
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/hungarian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/italian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/japanese/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=ujis
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/korean/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=euckr
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/norwegian-ny/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/norwegian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/polish/errmsg.txt
View file @
e44a0c2a
...
...
@@ -318,3 +318,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/portuguese/errmsg.txt
View file @
e44a0c2a
...
...
@@ -315,3 +315,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/romanian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -318,3 +318,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/russian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=koi8r
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/serbian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -309,3 +309,4 @@ character-set=cp1250
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/slovak/errmsg.txt
View file @
e44a0c2a
...
...
@@ -322,3 +322,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/spanish/errmsg.txt
View file @
e44a0c2a
...
...
@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/swedish/errmsg.txt
View file @
e44a0c2a
...
...
@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/share/ukrainian/errmsg.txt
View file @
e44a0c2a
...
...
@@ -319,3 +319,4 @@ character-set=koi8u
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
sql/sp.cc
View file @
e44a0c2a
...
...
@@ -230,8 +230,8 @@ db_create_routine(THD *thd, int type,
(
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
)
suid
);
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
);
...
...
@@ -268,6 +268,182 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen)
DBUG_RETURN
(
ret
);
}
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
)
{
DBUG_ENTER
(
"db_update_routine"
);
DBUG_PRINT
(
"enter"
,
(
"type: %d name: %*s"
,
type
,
namelen
,
name
));
TABLE
*
table
;
int
ret
;
bool
opened
;
ret
=
db_find_routine_aux
(
thd
,
type
,
name
,
namelen
,
TL_WRITE
,
&
table
,
&
opened
);
if
(
ret
==
SP_OK
)
{
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
(
newname
)
table
->
field
[
MYSQL_PROC_FIELD_NAME
]
->
store
(
newname
,
newnamelen
,
system_charset_info
);
if
(
comment
)
table
->
field
[
MYSQL_PROC_FIELD_COMMENT
]
->
store
(
comment
,
commentlen
,
system_charset_info
);
if
((
table
->
file
->
update_row
(
table
->
record
[
1
],
table
->
record
[
0
])))
ret
=
SP_WRITE_ROW_FAILED
;
}
if
(
opened
)
close_thread_tables
(
thd
);
DBUG_RETURN
(
ret
);
}
struct
st_used_field
{
const
char
*
field_name
;
uint
field_length
;
enum
enum_field_types
field_type
;
Field
*
field
;
};
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
},
{
"Modified"
,
0
,
MYSQL_TYPE_TIMESTAMP
,
0
},
{
"Created"
,
0
,
MYSQL_TYPE_TIMESTAMP
,
0
},
{
"Suid"
,
1
,
MYSQL_TYPE_STRING
,
0
},
{
"Comment"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
},
{
0
,
0
,
MYSQL_TYPE_STRING
,
0
}
};
int
print_field_values
(
THD
*
thd
,
TABLE
*
table
,
struct
st_used_field
*
used_fields
,
int
type
,
const
char
*
wild
)
{
Protocol
*
protocol
=
thd
->
protocol
;
if
(
table
->
field
[
MYSQL_PROC_FIELD_TYPE
]
->
val_int
()
==
type
)
{
String
*
tmp_string
=
new
String
();
struct
st_used_field
*
used_field
=
used_fields
;
get_field
(
&
thd
->
mem_root
,
used_field
->
field
,
tmp_string
);
if
(
!
wild
||
!
wild
[
0
]
||
!
wild_compare
(
tmp_string
->
ptr
(),
wild
,
0
))
{
protocol
->
prepare_for_resend
();
protocol
->
store
(
tmp_string
);
for
(
used_field
++
;
used_field
->
field_name
;
used_field
++
)
{
switch
(
used_field
->
field_type
)
{
case
MYSQL_TYPE_TIMESTAMP
:
{
TIME
tmp_time
;
((
Field_timestamp
*
)
used_field
->
field
)
->
get_time
(
&
tmp_time
);
protocol
->
store
(
&
tmp_time
);
}
break
;
default:
{
String
*
tmp_string1
=
new
String
();
get_field
(
&
thd
->
mem_root
,
used_field
->
field
,
tmp_string1
);
protocol
->
store
(
tmp_string1
);
}
break
;
}
}
if
(
protocol
->
write
())
return
1
;
}
}
return
0
;
}
int
db_show_routine_status
(
THD
*
thd
,
int
type
,
const
char
*
wild
)
{
DBUG_ENTER
(
"db_show_routine_status"
);
TABLE
*
table
;
TABLE_LIST
tables
;
memset
(
&
tables
,
0
,
sizeof
(
tables
));
tables
.
db
=
(
char
*
)
"mysql"
;
tables
.
real_name
=
tables
.
alias
=
(
char
*
)
"proc"
;
if
(
!
(
table
=
open_ltable
(
thd
,
&
tables
,
TL_READ
)))
{
DBUG_RETURN
(
1
);
}
else
{
Item
*
item
;
List
<
Item
>
field_list
;
struct
st_used_field
*
used_field
;
st_used_field
used_fields
[
array_elements
(
init_fields
)];
memcpy
((
char
*
)
used_fields
,
(
char
*
)
init_fields
,
sizeof
(
used_fields
));
/* Init header */
for
(
used_field
=
&
used_fields
[
0
];
used_field
->
field_name
;
used_field
++
)
{
switch
(
used_field
->
field_type
)
{
case
MYSQL_TYPE_TIMESTAMP
:
field_list
.
push_back
(
item
=
new
Item_datetime
(
used_field
->
field_name
));
break
;
default:
field_list
.
push_back
(
item
=
new
Item_empty_string
(
used_field
->
field_name
,
used_field
->
field_length
));
break
;
}
}
/* Print header */
if
(
thd
->
protocol
->
send_fields
(
&
field_list
,
1
))
goto
err_case
;
/* Init fields */
setup_tables
(
&
tables
);
for
(
used_field
=
&
used_fields
[
0
];
used_field
->
field_name
;
used_field
++
)
{
TABLE_LIST
*
not_used
;
Item_field
*
field
=
new
Item_field
(
"mysql"
,
"proc"
,
used_field
->
field_name
);
if
(
!
(
used_field
->
field
=
find_field_in_tables
(
thd
,
field
,
&
tables
,
&
not_used
,
TRUE
)))
goto
err_case1
;
}
table
->
file
->
index_init
(
0
);
table
->
file
->
index_first
(
table
->
record
[
0
]);
if
(
print_field_values
(
thd
,
table
,
used_fields
,
type
,
wild
))
goto
err_case1
;
while
(
!
table
->
file
->
index_next
(
table
->
record
[
0
]))
{
if
(
print_field_values
(
thd
,
table
,
used_fields
,
type
,
wild
))
goto
err_case1
;
}
send_eof
(
thd
);
close_thread_tables
(
thd
);
DBUG_RETURN
(
0
);
}
err_case1:
send_eof
(
thd
);
err_case:
close_thread_tables
(
thd
);
DBUG_RETURN
(
1
);
}
/*
*
...
...
@@ -326,6 +502,46 @@ sp_drop_procedure(THD *thd, char *name, uint namelen)
DBUG_RETURN
(
ret
);
}
int
sp_update_procedure
(
THD
*
thd
,
char
*
name
,
uint
namelen
,
char
*
newname
,
uint
newnamelen
,
char
*
comment
,
uint
commentlen
,
enum
suid_behaviour
suid
)
{
DBUG_ENTER
(
"sp_update_procedure"
);
DBUG_PRINT
(
"enter"
,
(
"name: %*s"
,
namelen
,
name
));
sp_head
*
sp
;
int
ret
;
sp
=
sp_cache_remove
(
&
thd
->
sp_proc_cache
,
name
,
namelen
);
if
(
sp
)
delete
sp
;
ret
=
db_update_routine
(
thd
,
TYPE_ENUM_PROCEDURE
,
name
,
namelen
,
newname
,
newnamelen
,
comment
,
commentlen
,
suid
);
DBUG_RETURN
(
ret
);
}
int
sp_show_create_procedure
(
THD
*
thd
,
LEX_STRING
*
name
)
{
DBUG_ENTER
(
"sp_show_create_procedure"
);
DBUG_PRINT
(
"enter"
,
(
"name: %*s"
,
name
->
length
,
name
->
str
));
sp_head
*
sp
;
sp
=
sp_find_procedure
(
thd
,
name
);
if
(
sp
)
DBUG_RETURN
(
sp
->
show_create_procedure
(
thd
));
DBUG_RETURN
(
1
);
}
int
db_show_status_procedure
(
THD
*
thd
,
const
char
*
wild
)
{
DBUG_ENTER
(
"db_show_status_procedure"
);
DBUG_RETURN
(
db_show_routine_status
(
thd
,
TYPE_ENUM_PROCEDURE
,
wild
));
}
/*
*
...
...
@@ -381,6 +597,47 @@ sp_drop_function(THD *thd, char *name, uint namelen)
DBUG_RETURN
(
ret
);
}
int
sp_update_function
(
THD
*
thd
,
char
*
name
,
uint
namelen
,
char
*
newname
,
uint
newnamelen
,
char
*
comment
,
uint
commentlen
,
enum
suid_behaviour
suid
)
{
DBUG_ENTER
(
"sp_update_procedure"
);
DBUG_PRINT
(
"enter"
,
(
"name: %*s"
,
namelen
,
name
));
sp_head
*
sp
;
int
ret
;
sp
=
sp_cache_remove
(
&
thd
->
sp_func_cache
,
name
,
namelen
);
if
(
sp
)
delete
sp
;
ret
=
db_update_routine
(
thd
,
TYPE_ENUM_FUNCTION
,
name
,
namelen
,
newname
,
newnamelen
,
comment
,
commentlen
,
suid
);
DBUG_RETURN
(
ret
);
}
int
sp_show_create_function
(
THD
*
thd
,
LEX_STRING
*
name
)
{
DBUG_ENTER
(
"sp_show_create_function"
);
DBUG_PRINT
(
"enter"
,
(
"name: %*s"
,
name
->
length
,
name
->
str
));
sp_head
*
sp
;
sp
=
sp_find_function
(
thd
,
name
);
if
(
sp
)
DBUG_RETURN
(
sp
->
show_create_function
(
thd
));
DBUG_RETURN
(
1
);
}
int
db_show_status_function
(
THD
*
thd
,
const
char
*
wild
)
{
DBUG_ENTER
(
"db_show_status_function"
);
DBUG_RETURN
(
db_show_routine_status
(
thd
,
TYPE_ENUM_FUNCTION
,
wild
));
}
// QQ Temporary until the function call detection in sql_lex has been reworked.
bool
sp_function_exists
(
THD
*
thd
,
LEX_STRING
*
name
)
...
...
sql/sp.h
View file @
e44a0c2a
...
...
@@ -38,6 +38,17 @@ int
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
);
int
sp_show_create_procedure
(
THD
*
thd
,
LEX_STRING
*
name
);
int
db_show_status_procedure
(
THD
*
thd
,
const
char
*
wild
);
sp_head
*
sp_find_function
(
THD
*
thd
,
LEX_STRING
*
name
);
...
...
@@ -48,6 +59,17 @@ sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen,
int
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
);
int
sp_show_create_function
(
THD
*
thd
,
LEX_STRING
*
name
);
int
db_show_status_function
(
THD
*
thd
,
const
char
*
wild
);
// QQ Temporary until the function call detection in sql_lex has been reworked.
bool
sp_function_exists
(
THD
*
thd
,
LEX_STRING
*
name
);
...
...
sql/sp_head.cc
View file @
e44a0c2a
...
...
@@ -131,7 +131,7 @@ sp_head::sp_head()
}
void
sp_head
::
init
(
LEX_STRING
*
name
,
LEX
*
lex
,
LEX_STRING
*
comment
,
char
suid
)
sp_head
::
init
(
LEX_STRING
*
name
,
LEX
*
lex
)
{
DBUG_ENTER
(
"sp_head::init"
);
const
char
*
dstr
=
(
const
char
*
)
lex
->
buf
;
...
...
@@ -141,16 +141,6 @@ sp_head::init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid)
m_name
.
str
=
lex
->
thd
->
strmake
(
name
->
str
,
name
->
length
);
m_defstr
.
length
=
lex
->
end_of_query
-
lex
->
buf
;
m_defstr
.
str
=
lex
->
thd
->
strmake
(
dstr
,
m_defstr
.
length
);
m_comment
.
length
=
0
;
m_comment
.
str
=
0
;
if
(
comment
)
{
m_comment
.
length
=
comment
->
length
;
m_comment
.
str
=
comment
->
str
;
}
m_suid
=
suid
;
lex
->
spcont
=
m_pcont
=
new
sp_pcontext
();
my_init_dynamic_array
(
&
m_instr
,
sizeof
(
sp_instr
*
),
16
,
8
);
DBUG_VOID_RETURN
;
...
...
@@ -605,7 +595,56 @@ sp_head::backpatch(sp_label_t *lab)
}
}
int
sp_head
::
show_create_procedure
(
THD
*
thd
)
{
Protocol
*
protocol
=
thd
->
protocol
;
char
buff
[
2048
];
String
buffer
(
buff
,
sizeof
(
buff
),
system_charset_info
);
int
res
;
List
<
Item
>
field_list
;
DBUG_ENTER
(
"sp_head::show_create_procedure"
);
DBUG_PRINT
(
"info"
,
(
"procedure %s"
,
m_name
.
str
));
field_list
.
push_back
(
new
Item_empty_string
(
"Procedure"
,
NAME_LEN
));
// 1024 is for not to confuse old clients
field_list
.
push_back
(
new
Item_empty_string
(
"Create Procedure"
,
max
(
buffer
.
length
(),
1024
)));
if
(
protocol
->
send_fields
(
&
field_list
,
1
))
DBUG_RETURN
(
1
);
protocol
->
prepare_for_resend
();
protocol
->
store
(
m_name
.
str
,
m_name
.
length
,
system_charset_info
);
protocol
->
store
(
m_defstr
.
str
,
m_defstr
.
length
,
system_charset_info
);
res
=
protocol
->
write
();
send_eof
(
thd
);
DBUG_RETURN
(
res
);
}
int
sp_head
::
show_create_function
(
THD
*
thd
)
{
Protocol
*
protocol
=
thd
->
protocol
;
char
buff
[
2048
];
String
buffer
(
buff
,
sizeof
(
buff
),
system_charset_info
);
int
res
;
List
<
Item
>
field_list
;
DBUG_ENTER
(
"sp_head::show_create_function"
);
DBUG_PRINT
(
"info"
,
(
"procedure %s"
,
m_name
.
str
));
field_list
.
push_back
(
new
Item_empty_string
(
"Function"
,
NAME_LEN
));
field_list
.
push_back
(
new
Item_empty_string
(
"Create Function"
,
max
(
buffer
.
length
(),
1024
)));
if
(
protocol
->
send_fields
(
&
field_list
,
1
))
DBUG_RETURN
(
1
);
protocol
->
prepare_for_resend
();
protocol
->
store
(
m_name
.
str
,
m_name
.
length
,
system_charset_info
);
protocol
->
store
(
m_defstr
.
str
,
m_defstr
.
length
,
system_charset_info
);
res
=
protocol
->
write
();
send_eof
(
thd
);
DBUG_RETURN
(
res
);
}
// ------------------------------------------------------------------
//
...
...
sql/sp_head.h
View file @
e44a0c2a
...
...
@@ -66,7 +66,21 @@ public:
// Initialize after we have reset mem_root
void
init
(
LEX_STRING
*
name
,
LEX
*
lex
,
LEX_STRING
*
comment
,
char
suid
);
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
);
...
...
@@ -83,6 +97,12 @@ public:
int
execute_procedure
(
THD
*
thd
,
List
<
Item
>
*
args
);
int
show_create_procedure
(
THD
*
thd
);
int
show_create_function
(
THD
*
thd
);
inline
void
add_instr
(
sp_instr
*
i
)
{
...
...
sql/sql_lex.h
View file @
e44a0c2a
...
...
@@ -79,11 +79,18 @@ enum enum_sql_command {
SQLCOM_HELP
,
SQLCOM_DROP_USER
,
SQLCOM_REVOKE_ALL
,
SQLCOM_CHECKSUM
,
SQLCOM_CREATE_PROCEDURE
,
SQLCOM_CREATE_SPFUNCTION
,
SQLCOM_CALL
,
SQLCOM_DROP_PROCEDURE
,
SQLCOM_ALTER_PROCEDURE
,
SQLCOM_ALTER_FUNCTION
,
SQLCOM_SHOW_CREATE_PROC
,
SQLCOM_SHOW_CREATE_FUNC
,
SQLCOM_SHOW_STATUS_PROC
,
SQLCOM_SHOW_STATUS_FUNC
,
/* This should be the last !!! */
SQLCOM_END
};
enum
suid_behaviour
{
IS_DEFAULT_SUID
=
0
,
IS_NOT_SUID
,
IS_SUID
};
typedef
List
<
Item
>
List_item
;
typedef
struct
st_lex_master_info
...
...
@@ -544,6 +551,7 @@ 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
;
...
...
sql/sql_parse.cc
View file @
e44a0c2a
...
...
@@ -3394,22 +3394,34 @@ mysql_execute_command(THD *thd)
case
SQLCOM_ALTER_PROCEDURE
:
case
SQLCOM_ALTER_FUNCTION
:
{
sp_head
*
sp
;
if
(
lex
->
sql_command
==
SQLCOM_ALTER_PROCEDURE
)
sp
=
sp_find_procedure
(
thd
,
&
lex
->
udf
.
name
);
else
sp
=
sp_find_function
(
thd
,
&
lex
->
udf
.
name
);
if
(
!
sp
)
res
=
-
1
;
uint
newname_len
=
0
;
if
(
lex
->
name
)
newname_len
=
strlen
(
lex
->
name
);
if
(
newname_len
>
NAME_LEN
)
{
net_printf
(
thd
,
ER_
SP_DOES_NOT_EXIST
,
SP_COM_STRING
(
lex
),
lex
->
udf
.
name
);
net_printf
(
thd
,
ER_
TOO_LONG_IDENT
,
lex
->
name
);
goto
error
;
}
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
);
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
);
switch
(
res
)
{
/* QQ This is an no-op right now, since we haven't
put the characteristics in yet. */
case
SP_OK
:
send_ok
(
thd
);
break
;
case
SP_KEY_NOT_FOUND
:
net_printf
(
thd
,
ER_SP_DOES_NOT_EXIST
,
SP_COM_STRING
(
lex
),
lex
->
udf
.
name
);
goto
error
;
default:
net_printf
(
thd
,
ER_SP_CANT_ALTER
,
SP_COM_STRING
(
lex
),
lex
->
udf
.
name
);
goto
error
;
}
break
;
}
...
...
@@ -3463,6 +3475,51 @@ mysql_execute_command(THD *thd)
}
break
;
}
case
SQLCOM_SHOW_CREATE_PROC
:
{
res
=
-
1
;
if
(
lex
->
udf
.
name
.
length
>
NAME_LEN
)
{
net_printf
(
thd
,
ER_TOO_LONG_IDENT
,
lex
->
udf
.
name
.
str
);
goto
error
;
}
res
=
sp_show_create_procedure
(
thd
,
&
lex
->
udf
.
name
);
if
(
res
==
SP_KEY_NOT_FOUND
)
{
net_printf
(
thd
,
ER_SP_DOES_NOT_EXIST
,
SP_COM_STRING
(
lex
),
lex
->
udf
.
name
.
str
);
goto
error
;
}
break
;
}
case
SQLCOM_SHOW_CREATE_FUNC
:
{
if
(
lex
->
udf
.
name
.
length
>
NAME_LEN
)
{
net_printf
(
thd
,
ER_TOO_LONG_IDENT
,
lex
->
udf
.
name
.
str
);
goto
error
;
}
res
=
sp_show_create_function
(
thd
,
&
lex
->
udf
.
name
);
if
(
res
==
SP_KEY_NOT_FOUND
)
{
net_printf
(
thd
,
ER_SP_DOES_NOT_EXIST
,
SP_COM_STRING
(
lex
),
lex
->
udf
.
name
.
str
);
goto
error
;
}
break
;
}
case
SQLCOM_SHOW_STATUS_PROC
:
{
res
=
db_show_status_procedure
(
thd
,
(
lex
->
wild
?
lex
->
wild
->
ptr
()
:
NullS
));
break
;
}
case
SQLCOM_SHOW_STATUS_FUNC
:
{
res
=
db_show_status_function
(
thd
,
(
lex
->
wild
?
lex
->
wild
->
ptr
()
:
NullS
));
break
;
}
default:
/* Impossible */
send_ok
(
thd
);
break
;
...
...
sql/sql_yacc.yy
View file @
e44a0c2a
...
...
@@ -137,6 +137,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token CREATE
%token CROSS
%token CUBE_SYM
%token DEFINER
%token DELETE_SYM
%token DUAL_SYM
%token DO_SYM
...
...
@@ -269,6 +270,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token INOUT_SYM
%token INTO
%token IN_SYM
%token INVOKER
%token ISOLATION
%token JOIN_SYM
%token KEYS
...
...
@@ -311,6 +313,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MEDIUM_SYM
%token MIN_ROWS
%token NAMES_SYM
%token NAME_SYM
%token NATIONAL_SYM
%token NATURAL
%token NEW_SYM
...
...
@@ -361,6 +364,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROW_FORMAT_SYM
%token ROW_SYM
%token RTREE_SYM
%token SECURITY
%token SET
%token SEPARATOR_SYM
%token SERIAL_SYM
...
...
@@ -619,7 +623,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component
SP_FUNC ident_or_spfunc sp_opt_label
SP_FUNC ident_or_spfunc sp_opt_label
sp_comment sp_newname
%type <lex_str_ptr>
opt_table_alias
...
...
@@ -745,7 +749,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
union_clause union_list union_option
precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help opt_len
statement
statement
sp_suid
END_OF_INPUT
%type <NONE> call sp_proc_stmts sp_proc_stmt
...
...
@@ -1021,7 +1025,7 @@ create:
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(YYTHD);
sp->init(&$3, lex
, 0, 0
);
sp->init(&$3, lex);
sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp;
...
...
@@ -1037,6 +1041,10 @@ create:
{
Lex->spcont->set_params();
}
sp_comment sp_suid
{
Lex->sphead->init_options(&$9, Lex->suid);
}
sp_proc_stmt
{
LEX *lex= Lex;
...
...
@@ -1075,7 +1083,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
, 0, 0
);
sp->init(&lex->udf.name, lex);
sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp;
...
...
@@ -1095,6 +1103,10 @@ create_function_tail:
{
Lex->sphead->m_returns= (enum enum_field_types)$7;
}
sp_comment sp_suid
{
Lex->sphead->init_options(&$9, Lex->suid);
}
sp_proc_stmt
{
LEX *lex= Lex;
...
...
@@ -1107,6 +1119,23 @@ create_function_tail:
}
;
sp_comment:
/* Empty */ { $$.str=0; }
| COMMENT_SYM TEXT_STRING_sys { $$= $2; }
;
sp_newname:
/* Empty */ { $$.str=0; }
| NAME_SYM ident { $$= $2; }
;
sp_suid:
/* Empty */ { Lex->suid= IS_DEFAULT_SUID; }
| SECURITY DEFINER { Lex->suid= IS_SUID; }
| SECURITY INVOKER { Lex->suid= IS_NOT_SUID; }
;
call:
CALL_SYM ident_or_spfunc
{
...
...
@@ -2573,7 +2602,7 @@ alter:
lex->sql_command=SQLCOM_ALTER_DB;
lex->name=$3.str;
}
| ALTER PROCEDURE ident
| ALTER PROCEDURE ident
sp_newname sp_comment sp_suid
/* QQ Characteristics missing for now */
opt_restrict
{
...
...
@@ -2583,8 +2612,10 @@ alter:
put the characteristics in yet. */
lex->sql_command= SQLCOM_ALTER_PROCEDURE;
lex->udf.name= $3;
lex->name= $4.str;
lex->comment= &$5;
}
| ALTER FUNCTION_SYM ident
| ALTER FUNCTION_SYM ident
sp_newname sp_comment sp_suid
/* QQ Characteristics missing for now */
opt_restrict
{
...
...
@@ -2594,6 +2625,8 @@ alter:
put the characteristics in yet. */
lex->sql_command= SQLCOM_ALTER_FUNCTION;
lex->udf.name= $3;
lex->name= $4.str;
lex->comment= &$5;
}
;
...
...
@@ -5012,7 +5045,26 @@ show_param:
| SLAVE STATUS_SYM
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
};
}
| CREATE PROCEDURE ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE_PROC;
Lex->udf.name= $3;
}
| CREATE FUNCTION_SYM ident
{
Lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
Lex->udf.name= $3;
}
| PROCEDURE STATUS_SYM wild
{
Lex->sql_command = SQLCOM_SHOW_STATUS_PROC;
}
| FUNCTION_SYM STATUS_SYM wild
{
Lex->sql_command = SQLCOM_SHOW_STATUS_FUNC;
};
master_or_binary:
MASTER_SYM
...
...
@@ -5560,6 +5612,7 @@ keyword:
| DATETIME {}
| DATE_SYM {}
| DAY_SYM {}
| DEFINER {}
| DELAY_KEY_WRITE_SYM {}
| DES_KEY_FILE {}
| DIRECTORY_SYM {}
...
...
@@ -5595,6 +5648,7 @@ keyword:
| HOSTS_SYM {}
| HOUR_SYM {}
| IDENTIFIED_SYM {}
| INVOKER {}
| IMPORT {}
| INDEXES {}
| ISOLATION {}
...
...
@@ -5637,6 +5691,7 @@ keyword:
| MULTILINESTRING {}
| MULTIPOINT {}
| MULTIPOLYGON {}
| NAME_SYM {}
| NAMES_SYM {}
| NATIONAL_SYM {}
| NCHAR_SYM {}
...
...
@@ -5680,6 +5735,7 @@ keyword:
| RTREE_SYM {}
| SAVEPOINT_SYM {}
| SECOND_SYM {}
| SECURITY {}
| SERIAL_SYM {}
| SERIALIZABLE_SYM {}
| SESSION_SYM {}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment