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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
722fb72a
Commit
722fb72a
authored
Mar 27, 2009
by
Staale Smedseng
Browse files
Options
Browse Files
Download
Plain Diff
Merge from 5.0-bugteam
parents
ad7e825d
50ed1ef7
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
87 additions
and
26 deletions
+87
-26
mysql-test/r/trigger.result
mysql-test/r/trigger.result
+20
-0
mysql-test/t/trigger.test
mysql-test/t/trigger.test
+33
-0
sql/sql_base.cc
sql/sql_base.cc
+34
-26
No files found.
mysql-test/r/trigger.result
View file @
722fb72a
...
@@ -1960,6 +1960,26 @@ select * from t2;
...
@@ -1960,6 +1960,26 @@ select * from t2;
s1
s1
drop table t1;
drop table t1;
drop temporary table t2;
drop temporary table t2;
#------------------------------------------------------------------------
# Bug#39953 Triggers are not working properly with multi table updates
#------------------------------------------------------------------------
DROP TABLE IF EXISTS t1;
DROP TRIGGER IF EXISTS t_insert;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1 (a int, date_insert timestamp, PRIMARY KEY (a));
INSERT INTO t1 (a) VALUES (2),(5);
CREATE TABLE t2 (a int, b int, PRIMARY KEY (a));
CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET
date_insert=NOW() WHERE t1.a=t2.b AND t2.a=NEW.a; END |
INSERT INTO t2 (a,b) VALUES (1,2);
DROP TRIGGER t_insert;
CREATE TRIGGER t_insert AFTER INSERT ON t2 FOR EACH ROW BEGIN UPDATE t1,t2 SET
date_insert=NOW(),b=b+1 WHERE t1.a=t2.b AND t2.a=NEW.a; END |
INSERT INTO t2 (a,b) VALUES (3,5);
ERROR HY000: Can't update table 't2' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
DROP TABLE t1;
DROP TRIGGER t_insert;
DROP TABLE t2;
End of 5.0 tests
End of 5.0 tests
drop table if exists table_25411_a;
drop table if exists table_25411_a;
drop table if exists table_25411_b;
drop table if exists table_25411_b;
...
...
mysql-test/t/trigger.test
View file @
722fb72a
...
@@ -2218,6 +2218,39 @@ select * from t1;
...
@@ -2218,6 +2218,39 @@ select * from t1;
select
*
from
t2
;
select
*
from
t2
;
drop
table
t1
;
drop
table
t1
;
drop
temporary
table
t2
;
drop
temporary
table
t2
;
--
echo
#------------------------------------------------------------------------
--
echo
# Bug#39953 Triggers are not working properly with multi table updates
--
echo
#------------------------------------------------------------------------
--
disable_warnings
DROP
TABLE
IF
EXISTS
t1
;
DROP
TRIGGER
IF
EXISTS
t_insert
;
DROP
TABLE
IF
EXISTS
t2
;
--
enable_warnings
CREATE
TABLE
t1
(
a
int
,
date_insert
timestamp
,
PRIMARY
KEY
(
a
));
INSERT
INTO
t1
(
a
)
VALUES
(
2
),(
5
);
CREATE
TABLE
t2
(
a
int
,
b
int
,
PRIMARY
KEY
(
a
));
DELIMITER
|
;
CREATE
TRIGGER
t_insert
AFTER
INSERT
ON
t2
FOR
EACH
ROW
BEGIN
UPDATE
t1
,
t2
SET
date_insert
=
NOW
()
WHERE
t1
.
a
=
t2
.
b
AND
t2
.
a
=
NEW
.
a
;
END
|
DELIMITER
;
|
INSERT
INTO
t2
(
a
,
b
)
VALUES
(
1
,
2
);
DROP
TRIGGER
t_insert
;
DELIMITER
|
;
CREATE
TRIGGER
t_insert
AFTER
INSERT
ON
t2
FOR
EACH
ROW
BEGIN
UPDATE
t1
,
t2
SET
date_insert
=
NOW
(),
b
=
b
+
1
WHERE
t1
.
a
=
t2
.
b
AND
t2
.
a
=
NEW
.
a
;
END
|
DELIMITER
;
|
--
error
ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
INSERT
INTO
t2
(
a
,
b
)
VALUES
(
3
,
5
);
DROP
TABLE
t1
;
DROP
TRIGGER
t_insert
;
DROP
TABLE
t2
;
--
echo
End
of
5.0
tests
--
echo
End
of
5.0
tests
#
#
...
...
sql/sql_base.cc
View file @
722fb72a
...
@@ -2600,27 +2600,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
...
@@ -2600,27 +2600,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{
// Using table locks
{
// Using table locks
TABLE
*
best_table
=
0
;
TABLE
*
best_table
=
0
;
int
best_distance
=
INT_MIN
;
int
best_distance
=
INT_MIN
;
bool
check_if_used
=
thd
->
prelocked_mode
&&
((
int
)
table_list
->
lock_type
>=
(
int
)
TL_WRITE_ALLOW_WRITE
);
for
(
table
=
thd
->
open_tables
;
table
;
table
=
table
->
next
)
for
(
table
=
thd
->
open_tables
;
table
;
table
=
table
->
next
)
{
{
if
(
table
->
s
->
table_cache_key
.
length
==
key_length
&&
if
(
table
->
s
->
table_cache_key
.
length
==
key_length
&&
!
memcmp
(
table
->
s
->
table_cache_key
.
str
,
key
,
key_length
))
!
memcmp
(
table
->
s
->
table_cache_key
.
str
,
key
,
key_length
))
{
{
if
(
check_if_used
&&
table
->
query_id
&&
table
->
query_id
!=
thd
->
query_id
)
{
/*
If we are in stored function or trigger we should ensure that
we won't change table that is already used by calling statement.
So if we are opening table for writing, we should check that it
is not already open by some calling stamement.
*/
my_error
(
ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
,
MYF
(
0
),
table
->
s
->
table_name
.
str
);
DBUG_RETURN
(
0
);
}
/*
/*
When looking for a usable TABLE, ignore MERGE children, as they
When looking for a usable TABLE, ignore MERGE children, as they
belong to their parent and cannot be used explicitly.
belong to their parent and cannot be used explicitly.
...
@@ -2649,13 +2633,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
...
@@ -2649,13 +2633,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{
{
best_distance
=
distance
;
best_distance
=
distance
;
best_table
=
table
;
best_table
=
table
;
if
(
best_distance
==
0
&&
!
check_if_used
)
if
(
best_distance
==
0
)
{
{
/*
/*
If we have found perfect match and we don't need to check that
We have found a perfect match and can finish iterating
t
able is not used by one of calling statements (assuming tha
t
t
hrough open tables list. Check for table use conflic
t
we are inside of function or trigger) we can finish iterating
between calling statement and SP/trigger is done in
through open tables list
.
lock_tables()
.
*/
*/
break
;
break
;
}
}
...
@@ -4888,9 +4872,9 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
...
@@ -4888,9 +4872,9 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l,
lock_flags Flags passed to mysql_lock_table
lock_flags Flags passed to mysql_lock_table
NOTE
NOTE
This function do
n't do anything like SP/SF/views/triggers analysis done
This function do
esn't do anything like SP/SF/views/triggers analysis done
in open_table
s(). It is intended for opening of only one concrete table.
in open_table
()/lock_tables(). It is intended for opening of only one
And used only in special contexts.
concrete table.
And used only in special contexts.
RETURN VALUES
RETURN VALUES
table Opened table
table Opened table
...
@@ -4908,6 +4892,9 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
...
@@ -4908,6 +4892,9 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type,
bool
refresh
;
bool
refresh
;
DBUG_ENTER
(
"open_ltable"
);
DBUG_ENTER
(
"open_ltable"
);
/* should not be used in a prelocked_mode context, see NOTE above */
DBUG_ASSERT
(
!
thd
->
prelocked_mode
);
thd_proc_info
(
thd
,
"Opening table"
);
thd_proc_info
(
thd
,
"Opening table"
);
thd
->
current_tablenr
=
0
;
thd
->
current_tablenr
=
0
;
/* open_ltable can be used only for BASIC TABLEs */
/* open_ltable can be used only for BASIC TABLEs */
...
@@ -5374,8 +5361,29 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
...
@@ -5374,8 +5361,29 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
table
&&
table
!=
first_not_own
;
table
&&
table
!=
first_not_own
;
table
=
table
->
next_global
)
table
=
table
->
next_global
)
{
{
if
(
!
table
->
placeholder
()
&&
if
(
table
->
placeholder
())
check_lock_and_start_stmt
(
thd
,
table
->
table
,
table
->
lock_type
))
continue
;
/*
In a stored function or trigger we should ensure that we won't change
a table that is already used by the calling statement.
*/
if
(
thd
->
prelocked_mode
&&
table
->
lock_type
>=
TL_WRITE_ALLOW_WRITE
)
{
for
(
TABLE
*
opentab
=
thd
->
open_tables
;
opentab
;
opentab
=
opentab
->
next
)
{
if
(
table
->
table
->
s
==
opentab
->
s
&&
opentab
->
query_id
&&
table
->
table
->
query_id
!=
opentab
->
query_id
)
{
my_error
(
ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
,
MYF
(
0
),
table
->
table
->
s
->
table_name
.
str
);
DBUG_RETURN
(
-
1
);
}
}
}
if
(
check_lock_and_start_stmt
(
thd
,
table
->
table
,
table
->
lock_type
))
{
{
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
}
}
...
...
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