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
75b8d4fa
Commit
75b8d4fa
authored
Jul 09, 2005
by
dlenev@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/dlenev/src/mysql-5.0-bg8406
parents
94310faa
923fe817
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
666 additions
and
252 deletions
+666
-252
mysql-test/r/sp-error.result
mysql-test/r/sp-error.result
+16
-0
mysql-test/r/sp.result
mysql-test/r/sp.result
+1
-1
mysql-test/r/trigger.result
mysql-test/r/trigger.result
+92
-1
mysql-test/t/sp-error.test
mysql-test/t/sp-error.test
+23
-0
mysql-test/t/sp.test
mysql-test/t/sp.test
+3
-5
mysql-test/t/trigger.test
mysql-test/t/trigger.test
+82
-1
sql/item_func.cc
sql/item_func.cc
+1
-0
sql/sp.cc
sql/sp.cc
+263
-90
sql/sp.h
sql/sp.h
+13
-9
sql/sp_head.cc
sql/sp_head.cc
+24
-89
sql/sp_head.h
sql/sp_head.h
+42
-14
sql/sql_base.cc
sql/sql_base.cc
+9
-16
sql/sql_lex.cc
sql/sql_lex.cc
+25
-4
sql/sql_lex.h
sql/sql_lex.h
+10
-10
sql/sql_parse.cc
sql/sql_parse.cc
+1
-2
sql/sql_trigger.cc
sql/sql_trigger.cc
+29
-0
sql/sql_trigger.h
sql/sql_trigger.h
+27
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+5
-10
No files found.
mysql-test/r/sp-error.result
View file @
75b8d4fa
...
...
@@ -705,3 +705,19 @@ end|
call bug11394(2, 1)|
ERROR HY000: Recursive stored routines are not allowed.
drop procedure bug11394|
drop function if exists bug11834_1;
drop function if exists bug11834_2;
create function bug11834_1() returns int return 10;
create function bug11834_2() returns int return bug11834_1();
prepare stmt from "select bug11834_2()";
execute stmt;
bug11834_2()
10
execute stmt;
bug11834_2()
10
drop function bug11834_1;
execute stmt;
ERROR 42000: FUNCTION test.bug11834_1 does not exist
deallocate prepare stmt;
drop function bug11834_2;
mysql-test/r/sp.result
View file @
75b8d4fa
...
...
@@ -1088,7 +1088,7 @@ a
select * from v1|
a
3
select * from v1,
v2
|
select * from v1,
t1
|
ERROR HY000: Table 't1' was not locked with LOCK TABLES
select f4()|
ERROR HY000: Table 't2' was not locked with LOCK TABLES
...
...
mysql-test/r/trigger.result
View file @
75b8d4fa
drop table if exists t1, t2;
drop table if exists t1, t2
, t3
;
drop view if exists v1;
drop database if exists mysqltest;
drop function if exists f1;
create table t1 (i int);
create trigger trg before insert on t1 for each row set @a:=1;
set @a:=0;
...
...
@@ -182,6 +183,96 @@ select @log;
@log
(BEFORE_INSERT: new=(id=1, data=5))(BEFORE_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(AFTER_UPDATE: old=(id=1, data=4) new=(id=1, data=6))(BEFORE_INSERT: new=(id=3, data=3))(AFTER_INSERT: new=(id=3, data=3))
drop table t1;
create table t1 (id int primary key, data varchar(10), fk int);
create table t2 (event varchar(100));
create table t3 (id int primary key);
create trigger t1_ai after insert on t1 for each row
insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "'"));
insert into t1 (id, data) values (1, "one"), (2, "two");
select * from t1;
id data fk
1 one NULL
2 two NULL
select * from t2;
event
INSERT INTO t1 id=1 data='one'
INSERT INTO t1 id=2 data='two'
drop trigger t1.t1_ai;
create trigger t1_bi before insert on t1 for each row
begin
if exists (select id from t3 where id=new.fk) then
insert into t2 values (concat("INSERT INTO t1 id=", new.id, " data='", new.data, "' fk=", new.fk));
else
insert into t2 values (concat("INSERT INTO t1 FAILED id=", new.id, " data='", new.data, "' fk=", new.fk));
set new.id= NULL;
end if;
end|
insert into t3 values (1);
insert into t1 values (4, "four", 1), (5, "five", 2);
ERROR 23000: Column 'id' cannot be null
select * from t1;
id data fk
1 one NULL
2 two NULL
4 four 1
select * from t2;
event
INSERT INTO t1 id=1 data='one'
INSERT INTO t1 id=2 data='two'
INSERT INTO t1 id=4 data='four' fk=1
INSERT INTO t1 FAILED id=5 data='five' fk=2
drop table t1, t2, t3;
create table t1 (id int primary key, data varchar(10));
create table t2 (seq int);
insert into t2 values (10);
create function f1 () returns int return (select max(seq) from t2);
create trigger t1_bi before insert on t1 for each row
begin
if new.id > f1() then
set new.id:= f1();
end if;
end|
select f1();
f1()
10
insert into t1 values (1, "first");
insert into t1 values (f1(), "max");
select * from t1;
id data
1 first
10 max
drop table t1, t2;
drop function f1;
create table t1 (id int primary key, fk_t2 int);
create table t2 (id int primary key, fk_t3 int);
create table t3 (id int primary key);
insert into t1 values (1,1), (2,1), (3,2);
insert into t2 values (1,1), (2,2);
insert into t3 values (1), (2);
create trigger t3_ad after delete on t3 for each row
delete from t2 where fk_t3=old.id;
create trigger t2_ad after delete on t2 for each row
delete from t1 where fk_t2=old.id;
delete from t3 where id = 1;
select * from t1 left join (t2 left join t3 on t2.fk_t3 = t3.id) on t1.fk_t2 = t2.id;
id fk_t2 id fk_t3 id
3 2 2 2 2
drop table t1, t2, t3;
create table t1 (id int primary key, copy int);
create table t2 (id int primary key, data int);
insert into t2 values (1,1), (2,2);
create trigger t1_bi before insert on t1 for each row
set new.copy= (select data from t2 where id = new.id);
create trigger t1_bu before update on t1 for each row
set new.copy= (select data from t2 where id = new.id);
insert into t1 values (1,3), (2,4), (3,3);
update t1 set copy= 1 where id = 2;
select * from t1;
id copy
1 1
2 2
3 NULL
drop table t1, t2;
create table t1 (i int);
create trigger trg before insert on t1 for each row set @a:= old.i;
ERROR HY000: There is no OLD row in on INSERT trigger
...
...
mysql-test/t/sp-error.test
View file @
75b8d4fa
...
...
@@ -1026,3 +1026,26 @@ end|
call
bug11394
(
2
,
1
)
|
drop
procedure
bug11394
|
delimiter
|
;
#
# Bug#11834 "Re-execution of prepared statement with dropped function
# crashes server". Also tests handling of prepared stmts which use
# stored functions but does not require prelocking.
#
--
disable_warnings
drop
function
if
exists
bug11834_1
;
drop
function
if
exists
bug11834_2
;
--
enable_warnings
create
function
bug11834_1
()
returns
int
return
10
;
create
function
bug11834_2
()
returns
int
return
bug11834_1
();
prepare
stmt
from
"select bug11834_2()"
;
execute
stmt
;
# Re-execution of statement should not crash server.
execute
stmt
;
drop
function
bug11834_1
;
# Attempt to execute statement should return proper error and
# should not crash server.
--
error
ER_SP_DOES_NOT_EXIST
execute
stmt
;
deallocate
prepare
stmt
;
drop
function
bug11834_2
;
mysql-test/t/sp.test
View file @
75b8d4fa
...
...
@@ -1283,7 +1283,8 @@ select * from v1|
# views and functions ?
create
function
f1
()
returns
int
return
(
select
sum
(
data
)
from
t1
)
+
(
select
sum
(
data
)
from
v1
)
|
# FIXME All these just exceed file limit for me :)
# This queries will crash server because we can't use LEX in
# reenterable fashion yet. Patch disabling recursion will heal this.
#select f1()|
#select * from v1|
#select * from v2|
...
...
@@ -1328,15 +1329,12 @@ select * from v2|
select
*
from
v1
|
# These should not work as we have too little instances of tables locked
--
error
1100
select
*
from
v1
,
v2
|
select
*
from
v1
,
t1
|
--
error
1100
select
f4
()
|
unlock
tables
|
# TODO We also should test integration with triggers
# Cleanup
drop
function
f0
|
drop
function
f1
|
...
...
mysql-test/t/trigger.test
View file @
75b8d4fa
...
...
@@ -3,9 +3,10 @@
#
--
disable_warnings
drop
table
if
exists
t1
,
t2
;
drop
table
if
exists
t1
,
t2
,
t3
;
drop
view
if
exists
v1
;
drop
database
if
exists
mysqltest
;
drop
function
if
exists
f1
;
--
enable_warnings
create
table
t1
(
i
int
);
...
...
@@ -199,6 +200,86 @@ select @log;
drop
table
t1
;
#
# Let us test triggers which access other tables.
#
# Trivial trigger which inserts data into another table
create
table
t1
(
id
int
primary
key
,
data
varchar
(
10
),
fk
int
);
create
table
t2
(
event
varchar
(
100
));
create
table
t3
(
id
int
primary
key
);
create
trigger
t1_ai
after
insert
on
t1
for
each
row
insert
into
t2
values
(
concat
(
"INSERT INTO t1 id="
,
new
.
id
,
" data='"
,
new
.
data
,
"'"
));
insert
into
t1
(
id
,
data
)
values
(
1
,
"one"
),
(
2
,
"two"
);
select
*
from
t1
;
select
*
from
t2
;
drop
trigger
t1
.
t1_ai
;
# Trigger which uses couple of tables (and partially emulates FK constraint)
delimiter
|
;
create
trigger
t1_bi
before
insert
on
t1
for
each
row
begin
if
exists
(
select
id
from
t3
where
id
=
new
.
fk
)
then
insert
into
t2
values
(
concat
(
"INSERT INTO t1 id="
,
new
.
id
,
" data='"
,
new
.
data
,
"' fk="
,
new
.
fk
));
else
insert
into
t2
values
(
concat
(
"INSERT INTO t1 FAILED id="
,
new
.
id
,
" data='"
,
new
.
data
,
"' fk="
,
new
.
fk
));
set
new
.
id
=
NULL
;
end
if
;
end
|
delimiter
;
|
insert
into
t3
values
(
1
);
--
error
1048
insert
into
t1
values
(
4
,
"four"
,
1
),
(
5
,
"five"
,
2
);
select
*
from
t1
;
select
*
from
t2
;
drop
table
t1
,
t2
,
t3
;
# Trigger which invokes function
create
table
t1
(
id
int
primary
key
,
data
varchar
(
10
));
create
table
t2
(
seq
int
);
insert
into
t2
values
(
10
);
create
function
f1
()
returns
int
return
(
select
max
(
seq
)
from
t2
);
delimiter
|
;
create
trigger
t1_bi
before
insert
on
t1
for
each
row
begin
if
new
.
id
>
f1
()
then
set
new
.
id
:=
f1
();
end
if
;
end
|
delimiter
;
|
# Remove this once bug #11554 will be fixed.
select
f1
();
insert
into
t1
values
(
1
,
"first"
);
insert
into
t1
values
(
f1
(),
"max"
);
select
*
from
t1
;
drop
table
t1
,
t2
;
drop
function
f1
;
# Trigger which forces invocation of another trigger
# (emulation of FK on delete cascade policy)
create
table
t1
(
id
int
primary
key
,
fk_t2
int
);
create
table
t2
(
id
int
primary
key
,
fk_t3
int
);
create
table
t3
(
id
int
primary
key
);
insert
into
t1
values
(
1
,
1
),
(
2
,
1
),
(
3
,
2
);
insert
into
t2
values
(
1
,
1
),
(
2
,
2
);
insert
into
t3
values
(
1
),
(
2
);
create
trigger
t3_ad
after
delete
on
t3
for
each
row
delete
from
t2
where
fk_t3
=
old
.
id
;
create
trigger
t2_ad
after
delete
on
t2
for
each
row
delete
from
t1
where
fk_t2
=
old
.
id
;
delete
from
t3
where
id
=
1
;
select
*
from
t1
left
join
(
t2
left
join
t3
on
t2
.
fk_t3
=
t3
.
id
)
on
t1
.
fk_t2
=
t2
.
id
;
drop
table
t1
,
t2
,
t3
;
# Trigger which assigns value selected from table to field of row
# being inserted/updated.
create
table
t1
(
id
int
primary
key
,
copy
int
);
create
table
t2
(
id
int
primary
key
,
data
int
);
insert
into
t2
values
(
1
,
1
),
(
2
,
2
);
create
trigger
t1_bi
before
insert
on
t1
for
each
row
set
new
.
copy
=
(
select
data
from
t2
where
id
=
new
.
id
);
create
trigger
t1_bu
before
update
on
t1
for
each
row
set
new
.
copy
=
(
select
data
from
t2
where
id
=
new
.
id
);
insert
into
t1
values
(
1
,
3
),
(
2
,
4
),
(
3
,
3
);
update
t1
set
copy
=
1
where
id
=
2
;
select
*
from
t1
;
drop
table
t1
,
t2
;
#
# Test of wrong column specifiers in triggers
#
...
...
sql/item_func.cc
View file @
75b8d4fa
...
...
@@ -4725,6 +4725,7 @@ Item_func_sp::cleanup()
delete
result_field
;
result_field
=
NULL
;
}
m_sp
=
NULL
;
Item_func
::
cleanup
();
}
...
...
sql/sp.cc
View file @
75b8d4fa
This diff is collapsed.
Click to expand it.
sql/sp.h
View file @
75b8d4fa
...
...
@@ -79,15 +79,19 @@ sp_function_exists(THD *thd, sp_name *name);
/*
* For precaching of functions and procedures
*/
void
sp_add_to_hash
(
HASH
*
h
,
sp_name
*
fun
);
bool
sp_merge_hash
(
HASH
*
dst
,
HASH
*
src
);
void
sp_cache_routines
(
THD
*
thd
,
LEX
*
lex
);
Procedures for pre-caching of stored routines and building table list
for prelocking.
*/
void
sp_add_used_routine
(
LEX
*
lex
,
Item_arena
*
arena
,
sp_name
*
rt
,
char
rt_type
);
void
sp_update_sp_used_routines
(
HASH
*
dst
,
HASH
*
src
);
bool
sp_cache_routines_and_add_tables
(
THD
*
thd
,
LEX
*
lex
);
void
sp_cache_routines_and_add_tables_for_view
(
THD
*
thd
,
LEX
*
lex
,
LEX
*
aux_lex
);
void
sp_cache_routines_and_add_tables_for_triggers
(
THD
*
thd
,
LEX
*
lex
,
Table_triggers_list
*
triggers
);
extern
"C"
byte
*
sp_sroutine_key
(
const
byte
*
ptr
,
uint
*
plen
,
my_bool
first
);
//
// Utilities...
...
...
sql/sp_head.cc
View file @
75b8d4fa
...
...
@@ -242,8 +242,11 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
void
sp_name
::
init_qname
(
THD
*
thd
)
{
m_qname
.
length
=
m_db
.
length
+
m_name
.
length
+
1
;
m_qname
.
str
=
thd
->
alloc
(
m_qname
.
length
+
1
);
m_sroutines_key
.
length
=
m_db
.
length
+
m_name
.
length
+
2
;
if
(
!
(
m_sroutines_key
.
str
=
thd
->
alloc
(
m_sroutines_key
.
length
+
1
)))
return
;
m_qname
.
length
=
m_sroutines_key
.
length
-
1
;
m_qname
.
str
=
m_sroutines_key
.
str
+
1
;
sprintf
(
m_qname
.
str
,
"%*s.%*s"
,
m_db
.
length
,
(
m_db
.
length
?
m_db
.
str
:
""
),
m_name
.
length
,
m_name
.
str
);
...
...
@@ -317,15 +320,12 @@ sp_head::sp_head()
{
extern
byte
*
sp_table_key
(
const
byte
*
ptr
,
uint
*
plen
,
my_bool
first
);
extern
byte
*
sp_lex_sp_key
(
const
byte
*
ptr
,
uint
*
plen
,
my_bool
first
);
DBUG_ENTER
(
"sp_head::sp_head"
);
m_backpatch
.
empty
();
m_lex
.
empty
();
hash_init
(
&
m_sptabs
,
system_charset_info
,
0
,
0
,
0
,
sp_table_key
,
0
,
0
);
hash_init
(
&
m_spfuns
,
system_charset_info
,
0
,
0
,
0
,
sp_lex_sp_key
,
0
,
0
);
hash_init
(
&
m_spprocs
,
system_charset_info
,
0
,
0
,
0
,
sp_lex_sp_key
,
0
,
0
);
hash_init
(
&
m_sroutines
,
system_charset_info
,
0
,
0
,
0
,
sp_sroutine_key
,
0
,
0
);
DBUG_VOID_RETURN
;
}
...
...
@@ -528,8 +528,7 @@ sp_head::destroy()
}
hash_free
(
&
m_sptabs
);
hash_free
(
&
m_spfuns
);
hash_free
(
&
m_spprocs
);
hash_free
(
&
m_sroutines
);
DBUG_VOID_RETURN
;
}
...
...
@@ -1064,11 +1063,10 @@ sp_head::restore_lex(THD *thd)
oldlex
->
trg_table_fields
.
push_back
(
&
sublex
->
trg_table_fields
);
/*
Add routines which are used by statement to respective set
s
for
this routine
Add routines which are used by statement to respective set for
this routine
.
*/
sp_merge_hash
(
&
m_spfuns
,
&
sublex
->
spfuns
);
sp_merge_hash
(
&
m_spprocs
,
&
sublex
->
spprocs
);
sp_update_sp_used_routines
(
&
m_sroutines
,
&
sublex
->
sroutines
);
/*
Merge tables used by this statement (but not by its functions or
procedures) to multiset of tables used by this routine.
...
...
@@ -1605,16 +1603,22 @@ sp_instr_set::print(String *str)
int
sp_instr_set_trigger_field
::
execute
(
THD
*
thd
,
uint
*
nextp
)
{
int
res
=
0
;
DBUG_ENTER
(
"sp_instr_set_trigger_field::execute"
);
/* QQ: Still unsure what should we return in case of error 1 or -1 ? */
if
(
!
value
->
fixed
&&
value
->
fix_fields
(
thd
,
&
value
)
||
trigger_field
->
fix_fields
(
thd
,
0
)
||
(
value
->
save_in_field
(
trigger_field
->
field
,
0
)
<
0
))
DBUG_RETURN
(
m_lex_keeper
.
reset_lex_and_exec_core
(
thd
,
nextp
,
TRUE
,
this
));
}
int
sp_instr_set_trigger_field
::
exec_core
(
THD
*
thd
,
uint
*
nextp
)
{
int
res
=
0
;
Item
*
it
=
sp_prepare_func_item
(
thd
,
&
value
);
if
(
!
it
||
!
trigger_field
->
fixed
&&
trigger_field
->
fix_fields
(
thd
,
0
)
||
(
it
->
save_in_field
(
trigger_field
->
field
,
0
)
<
0
))
res
=
-
1
;
*
nextp
=
m_ip
+
1
;
DBUG_RETURN
(
res
)
;
*
nextp
=
m_ip
+
1
;
return
res
;
}
void
...
...
@@ -2438,72 +2442,3 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
return
table
;
}
/*
Auxilary function for adding tables used by routines used in query
to table lists.
SYNOPSIS
sp_add_sp_tables_to_table_list_aux()
thd - thread context
lex - LEX to which table list tables will be added
func_hash - routines for which tables should be added
func_cache- SP cache in which this routines should be looked up
NOTE
See sp_add_sp_tables_to_table_list() for more info.
RETURN VALUE
TRUE - some tables were added
FALSE - no tables were added.
*/
static
bool
sp_add_sp_tables_to_table_list_aux
(
THD
*
thd
,
LEX
*
lex
,
HASH
*
func_hash
,
sp_cache
**
func_cache
)
{
uint
i
;
bool
result
=
FALSE
;
for
(
i
=
0
;
i
<
func_hash
->
records
;
i
++
)
{
sp_head
*
sp
;
LEX_STRING
*
ls
=
(
LEX_STRING
*
)
hash_element
(
func_hash
,
i
);
sp_name
name
(
*
ls
);
name
.
m_qname
=
*
ls
;
if
((
sp
=
sp_cache_lookup
(
func_cache
,
&
name
)))
result
|=
sp
->
add_used_tables_to_table_list
(
thd
,
&
lex
->
query_tables_last
);
}
return
result
;
}
/*
Add tables used by routines used in query to table list.
SYNOPSIS
sp_add_sp_tables_to_table_list()
thd - thread context
lex - LEX to which table list tables will be added
func_lex - LEX for which functions we get tables
(useful for adding tables used by view routines)
NOTE
Elements of list will be allocated in PS memroot, so this
list will be persistent between PS execetutions.
RETURN VALUE
TRUE - some tables were added
FALSE - no tables were added.
*/
bool
sp_add_sp_tables_to_table_list
(
THD
*
thd
,
LEX
*
lex
,
LEX
*
func_lex
)
{
return
(
sp_add_sp_tables_to_table_list_aux
(
thd
,
lex
,
&
func_lex
->
spfuns
,
&
thd
->
sp_func_cache
)
|
sp_add_sp_tables_to_table_list_aux
(
thd
,
lex
,
&
func_lex
->
spprocs
,
&
thd
->
sp_proc_cache
));
}
sql/sp_head.h
View file @
75b8d4fa
...
...
@@ -48,24 +48,50 @@ public:
LEX_STRING
m_db
;
LEX_STRING
m_name
;
LEX_STRING
m_qname
;
/*
Key representing routine in the set of stored routines used by statement.
Consists of 1-byte routine type and m_qname (which usually refences to
same buffer). Note that one must complete initialization of the key by
calling set_routine_type().
*/
LEX_STRING
m_sroutines_key
;
sp_name
(
LEX_STRING
name
)
:
m_name
(
name
)
{
m_db
.
str
=
m_qname
.
str
=
0
;
m_db
.
length
=
m_qname
.
length
=
0
;
m_db
.
str
=
m_qname
.
str
=
m_sroutines_key
.
str
=
0
;
m_db
.
length
=
m_qname
.
length
=
m_sroutines_key
.
length
=
0
;
}
sp_name
(
LEX_STRING
db
,
LEX_STRING
name
)
:
m_db
(
db
),
m_name
(
name
)
{
m_qname
.
str
=
0
;
m_qname
.
length
=
0
;
m_qname
.
str
=
m_sroutines_key
.
str
=
0
;
m_qname
.
length
=
m_sroutines_key
.
length
=
0
;
}
/*
Creates temporary sp_name object from key, used mainly
for SP-cache lookups.
*/
sp_name
(
char
*
key
,
uint
key_len
)
{
m_sroutines_key
.
str
=
key
;
m_sroutines_key
.
length
=
key_len
;
m_name
.
str
=
m_qname
.
str
=
key
+
1
;
m_name
.
length
=
m_qname
.
length
=
key_len
-
1
;
m_db
.
str
=
0
;
m_db
.
length
=
0
;
}
// Init. the qualified name from the db and name.
void
init_qname
(
THD
*
thd
);
// thd for memroot allocation
void
set_routine_type
(
char
type
)
{
m_sroutines_key
.
str
[
0
]
=
type
;
}
~
sp_name
()
{}
};
...
...
@@ -107,13 +133,13 @@ public:
longlong
m_created
;
longlong
m_modified
;
/*
Set
s containing names of SP and SF
used by this routine.
TODO Probably we should combine these two hashes in one. It will
decrease memory overhead ans simplify algorithms using them. The
same applies to similar hashes in LEX
.
Set
containing names of stored routines
used by this routine.
Note that unlike elements of similar set for statement elements of this
set are not linked in one list. Because of this we are able save memory
by using for this set same objects that are used in 'sroutines' sets
for statements of which this stored routine consists
.
*/
HASH
m_s
pfuns
,
m_spproc
s
;
HASH
m_s
routine
s
;
// Pointers set during parsing
uchar
*
m_param_begin
,
*
m_param_end
,
*
m_body_begin
;
...
...
@@ -474,10 +500,11 @@ class sp_instr_set_trigger_field : public sp_instr
public:
sp_instr_set_trigger_field
(
uint
ip
,
sp_pcontext
*
ctx
,
Item_trigger_field
*
trg_fld
,
Item
*
val
)
Item_trigger_field
*
trg_fld
,
Item
*
val
,
LEX
*
lex
)
:
sp_instr
(
ip
,
ctx
),
trigger_field
(
trg_fld
),
value
(
val
)
value
(
val
)
,
m_lex_keeper
(
lex
,
TRUE
)
{}
virtual
~
sp_instr_set_trigger_field
()
...
...
@@ -485,11 +512,14 @@ public:
virtual
int
execute
(
THD
*
thd
,
uint
*
nextp
);
virtual
int
exec_core
(
THD
*
thd
,
uint
*
nextp
);
virtual
void
print
(
String
*
str
);
private:
Item_trigger_field
*
trigger_field
;
Item
*
value
;
sp_lex_keeper
m_lex_keeper
;
};
// class sp_instr_trigger_field : public sp_instr
...
...
@@ -954,7 +984,5 @@ TABLE_LIST *
sp_add_to_query_tables
(
THD
*
thd
,
LEX
*
lex
,
const
char
*
db
,
const
char
*
name
,
thr_lock_type
locktype
);
bool
sp_add_sp_tables_to_table_list
(
THD
*
thd
,
LEX
*
lex
,
LEX
*
func_lex
);
#endif
/* _SP_HEAD_H_ */
sql/sql_base.cc
View file @
75b8d4fa
...
...
@@ -1802,16 +1802,13 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter)
may be still zero for prelocked statement...
*/
if
(
!
thd
->
prelocked_mode
&&
!
thd
->
lex
->
requires_prelocking
()
&&
(
thd
->
lex
->
spfuns
.
records
||
thd
->
lex
->
spprocs
.
records
)
)
thd
->
lex
->
sroutines
.
records
)
{
TABLE_LIST
**
save_query_tables_last
;
sp_cache_routines
(
thd
,
thd
->
lex
);
save_query_tables_last
=
thd
->
lex
->
query_tables_last
;
TABLE_LIST
**
save_query_tables_last
=
thd
->
lex
->
query_tables_last
;
DBUG_ASSERT
(
thd
->
lex
->
query_tables
==
*
start
);
if
(
sp_
add_sp_tables_to_table_list
(
thd
,
thd
->
lex
,
thd
->
lex
)
||
if
(
sp_
cache_routines_and_add_tables
(
thd
,
thd
->
lex
)
||
*
start
)
{
query_tables_last_own
=
save_query_tables_last
;
...
...
@@ -1847,19 +1844,16 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter)
and add tables used by them to table list.
*/
if
(
!
thd
->
prelocked_mode
&&
!
thd
->
lex
->
requires_prelocking
()
&&
(
tables
->
view
->
spfuns
.
records
||
tables
->
view
->
spprocs
.
records
)
)
tables
->
view
->
sroutines
.
records
)
{
// FIXME We should catch recursion for both views and funcs here
sp_cache_routines
(
thd
,
tables
->
view
);
/* We have at least one table in TL here */
if
(
!
query_tables_last_own
)
query_tables_last_own
=
thd
->
lex
->
query_tables_last
;
sp_add_sp_tables_to_table_list
(
thd
,
thd
->
lex
,
tables
->
view
);
sp_cache_routines_and_add_tables_for_view
(
thd
,
thd
->
lex
,
tables
->
view
);
}
/* Cleanup hashes because destructo for this LEX is never called */
hash_free
(
&
tables
->
view
->
spfuns
);
hash_free
(
&
tables
->
view
->
spprocs
);
hash_free
(
&
tables
->
view
->
sroutines
);
continue
;
}
...
...
@@ -1914,9 +1908,6 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter)
prelocking list.
If we lock table for reading we won't update it so there is no need to
process its triggers since they never will be activated.
FIXME Now we are simply turning on prelocking. Proper integration
and testing is to be done later.
*/
if
(
!
thd
->
prelocked_mode
&&
!
thd
->
lex
->
requires_prelocking
()
&&
tables
->
table
->
triggers
&&
...
...
@@ -1924,6 +1915,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter)
{
if
(
!
query_tables_last_own
)
query_tables_last_own
=
thd
->
lex
->
query_tables_last
;
sp_cache_routines_and_add_tables_for_triggers
(
thd
,
thd
->
lex
,
tables
->
table
->
triggers
);
}
free_root
(
&
new_frm_mem
,
MYF
(
MY_KEEP_PREALLOC
));
}
...
...
sql/sql_lex.cc
View file @
75b8d4fa
...
...
@@ -172,10 +172,9 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex
->
proc_list
.
first
=
0
;
lex
->
query_tables_own_last
=
0
;
if
(
lex
->
spfuns
.
records
)
my_hash_reset
(
&
lex
->
spfuns
);
if
(
lex
->
spprocs
.
records
)
my_hash_reset
(
&
lex
->
spprocs
);
if
(
lex
->
sroutines
.
records
)
my_hash_reset
(
&
lex
->
sroutines
);
lex
->
sroutines_list
.
empty
();
DBUG_VOID_RETURN
;
}
...
...
@@ -1571,6 +1570,28 @@ void st_select_lex::print_limit(THD *thd, String *str)
}
/*
Initialize LEX object.
SYNOPSIS
st_lex::st_lex()
NOTE
LEX object initialized with this constructor can be used as part of
THD object for which one can safely call open_tables(), lock_tables()
and close_thread_tables() functions. But it is not yet ready for
statement parsing. On should use lex_start() function to prepare LEX
for this.
*/
st_lex
::
st_lex
()
:
result
(
0
),
sql_command
(
SQLCOM_END
),
query_tables_own_last
(
0
)
{
hash_init
(
&
sroutines
,
system_charset_info
,
0
,
0
,
0
,
sp_sroutine_key
,
0
,
0
);
sroutines_list
.
empty
();
}
/*
Check whether the merging algorithm can be used on this VIEW
...
...
sql/sql_lex.h
View file @
75b8d4fa
...
...
@@ -807,8 +807,14 @@ typedef struct st_lex
bool
sp_lex_in_use
;
/* Keep track on lex usage in SPs for error handling */
bool
all_privileges
;
sp_pcontext
*
spcont
;
HASH
spfuns
;
/* Called functions */
HASH
spprocs
;
/* Called procedures */
/* Set of stored routines called by statement. */
HASH
sroutines
;
/*
List linking elements of 'sroutines' set. Allows you to add new elements
to this set as you iterate through the list of existing elements.
*/
SQL_LIST
sroutines_list
;
st_sp_chistics
sp_chistics
;
bool
only_view
;
/* used for SHOW CREATE TABLE/VIEW */
/*
...
...
@@ -841,17 +847,11 @@ typedef struct st_lex
*/
uchar
*
fname_start
,
*
fname_end
;
st_lex
()
:
result
(
0
),
sql_command
(
SQLCOM_END
),
query_tables_own_last
(
0
)
{
extern
byte
*
sp_lex_sp_key
(
const
byte
*
ptr
,
uint
*
plen
,
my_bool
first
);
hash_init
(
&
spfuns
,
system_charset_info
,
0
,
0
,
0
,
sp_lex_sp_key
,
0
,
0
);
hash_init
(
&
spprocs
,
system_charset_info
,
0
,
0
,
0
,
sp_lex_sp_key
,
0
,
0
);
}
st_lex
();
virtual
~
st_lex
()
{
hash_free
(
&
spfuns
);
hash_free
(
&
spprocs
);
hash_free
(
&
sroutines
);
}
inline
void
uncacheable
(
uint8
cause
)
...
...
sql/sql_parse.cc
View file @
75b8d4fa
...
...
@@ -2302,8 +2302,7 @@ mysql_execute_command(THD *thd)
Don't reset warnings when executing a stored routine.
*/
if
((
all_tables
||
&
lex
->
select_lex
!=
lex
->
all_selects_list
||
lex
->
spfuns
.
records
||
lex
->
spprocs
.
records
)
&&
!
thd
->
spcont
)
lex
->
sroutines
.
records
)
&&
!
thd
->
spcont
)
mysql_reset_errors
(
thd
,
0
);
#ifdef HAVE_REPLICATION
...
...
sql/sql_trigger.cc
View file @
75b8d4fa
/* Copyright (C) 2004-2005 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#include "sp_head.h"
#include "sql_trigger.h"
...
...
@@ -417,6 +434,18 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
table
->
triggers
=
triggers
;
/*
Construct key that will represent triggers for this table in the set
of routines used by statement.
*/
triggers
->
sroutines_key
.
length
=
1
+
strlen
(
db
)
+
1
+
strlen
(
table_name
)
+
1
;
if
(
!
(
triggers
->
sroutines_key
.
str
=
alloc_root
(
&
table
->
mem_root
,
triggers
->
sroutines_key
.
length
)))
DBUG_RETURN
(
1
);
triggers
->
sroutines_key
.
str
[
0
]
=
TYPE_ENUM_TRIGGER
;
strmov
(
strmov
(
strmov
(
triggers
->
sroutines_key
.
str
+
1
,
db
),
"."
),
table_name
);
/*
TODO: This could be avoided if there is no triggers
for UPDATE and DELETE.
...
...
sql/sql_trigger.h
View file @
75b8d4fa
/* Copyright (C) 2004-2005 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
This class holds all information about triggers of table.
...
...
@@ -28,6 +45,14 @@ class Table_triggers_list: public Sql_alloc
used in CREATE/DROP TRIGGER for looking up trigger by name.
*/
List
<
LEX_STRING
>
names_list
;
/*
Key representing triggers for this table in set of all stored
routines used by statement.
TODO: We won't need this member once triggers namespace will be
database-wide instead of table-wide because then we will be able
to use key based on sp_name as for other stored routines.
*/
LEX_STRING
sroutines_key
;
public:
/*
...
...
@@ -112,6 +137,8 @@ public:
}
friend
class
Item_trigger_field
;
friend
void
sp_cache_routines_and_add_tables_for_triggers
(
THD
*
thd
,
LEX
*
lex
,
Table_triggers_list
*
triggers
);
private:
bool
prepare_record1_accessors
(
TABLE
*
table
);
...
...
sql/sql_yacc.yy
View file @
75b8d4fa
...
...
@@ -1531,7 +1531,7 @@ call:
lex->sql_command= SQLCOM_CALL;
lex->spname= $2;
lex->value_list.empty();
sp_add_
to_hash(&lex->spprocs, $2
);
sp_add_
used_routine(lex, YYTHD, $2, TYPE_ENUM_PROCEDURE
);
}
'(' sp_cparam_list ')' {}
;
...
...
@@ -4695,7 +4695,7 @@ simple_expr:
sp_name *name= new sp_name($1, $3);
name->init_qname(YYTHD);
sp_add_
to_hash(&lex->spfuns, name
);
sp_add_
used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION
);
if ($5)
$$= new Item_func_sp(&lex->current_select->context, name, *$5);
else
...
...
@@ -4785,7 +4785,7 @@ simple_expr:
LEX *lex= Lex;
sp_name *name= sp_name_current_db_new(YYTHD, $1);
sp_add_
to_hash(&lex->spfuns, name
);
sp_add_
used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION
);
if ($3)
$$= new Item_func_sp(&lex->current_select->context, name, *$3);
else
...
...
@@ -7723,12 +7723,6 @@ sys_option_value:
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (lex->query_tables)
{
my_message(ER_SP_SUBSELECT_NYI, ER(ER_SP_SUBSELECT_NYI),
MYF(0));
YYABORT;
}
if ($4)
it= $4;
else
...
...
@@ -7743,7 +7737,8 @@ sys_option_value:
$2.base_name.str)) ||
!(i= new sp_instr_set_trigger_field(lex->sphead->
instructions(),
lex->spcont, trg_fld, it)))
lex->spcont, trg_fld,
it, lex)))
YYABORT;
/*
...
...
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