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
edcdd6cf
Commit
edcdd6cf
authored
Jul 19, 2005
by
unknown
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-tn
parents
3b4d10a2
de1b1108
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
644 additions
and
130 deletions
+644
-130
mysql-test/r/information_schema.result
mysql-test/r/information_schema.result
+75
-2
mysql-test/r/information_schema_db.result
mysql-test/r/information_schema_db.result
+2
-0
mysql-test/r/rpl_sp.result
mysql-test/r/rpl_sp.result
+2
-2
mysql-test/r/trigger.result
mysql-test/r/trigger.result
+34
-19
mysql-test/r/view.result
mysql-test/r/view.result
+1
-1
mysql-test/t/information_schema.test
mysql-test/t/information_schema.test
+35
-0
mysql-test/t/rpl_sp.test
mysql-test/t/rpl_sp.test
+1
-1
mysql-test/t/trigger.test
mysql-test/t/trigger.test
+39
-20
mysql-test/t/view.test
mysql-test/t/view.test
+1
-1
sql/handler.cc
sql/handler.cc
+1
-0
sql/item.h
sql/item.h
+2
-2
sql/lex.h
sql/lex.h
+1
-0
sql/mysql_priv.h
sql/mysql_priv.h
+1
-0
sql/mysqld.cc
sql/mysqld.cc
+1
-0
sql/share/errmsg.txt
sql/share/errmsg.txt
+2
-0
sql/sp.cc
sql/sp.cc
+2
-2
sql/sql_base.cc
sql/sql_base.cc
+1
-1
sql/sql_lex.h
sql/sql_lex.h
+1
-0
sql/sql_parse.cc
sql/sql_parse.cc
+1
-0
sql/sql_show.cc
sql/sql_show.cc
+94
-0
sql/sql_table.cc
sql/sql_table.cc
+4
-10
sql/sql_trigger.cc
sql/sql_trigger.cc
+316
-51
sql/sql_trigger.h
sql/sql_trigger.h
+9
-2
sql/sql_yacc.yy
sql/sql_yacc.yy
+17
-15
sql/table.h
sql/table.h
+1
-1
No files found.
mysql-test/r/information_schema.result
View file @
edcdd6cf
...
...
@@ -48,6 +48,7 @@ TABLE_PRIVILEGES
COLUMN_PRIVILEGES
TABLE_CONSTRAINTS
KEY_COLUMN_USAGE
TRIGGERS
columns_priv
db
func
...
...
@@ -77,6 +78,7 @@ c table_name
TABLES TABLES
TABLE_PRIVILEGES TABLE_PRIVILEGES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
time_zone_leap_second time_zone_leap_second
...
...
@@ -94,6 +96,7 @@ c table_name
TABLES TABLES
TABLE_PRIVILEGES TABLE_PRIVILEGES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
time_zone_leap_second time_zone_leap_second
...
...
@@ -111,6 +114,7 @@ c table_name
TABLES TABLES
TABLE_PRIVILEGES TABLE_PRIVILEGES
TABLE_CONSTRAINTS TABLE_CONSTRAINTS
TRIGGERS TRIGGERS
tables_priv tables_priv
time_zone time_zone
time_zone_leap_second time_zone_leap_second
...
...
@@ -580,6 +584,7 @@ Tables_in_information_schema (T%)
TABLES
TABLE_PRIVILEGES
TABLE_CONSTRAINTS
TRIGGERS
create database information_schema;
ERROR HY000: Can't create database 'information_schema'; database exists
use information_schema;
...
...
@@ -588,6 +593,7 @@ Tables_in_information_schema (T%) Table_type
TABLES TEMPORARY
TABLE_PRIVILEGES TEMPORARY
TABLE_CONSTRAINTS TEMPORARY
TRIGGERS TEMPORARY
create table t1(a int);
ERROR 42S02: Unknown table 't1' in information_schema
use test;
...
...
@@ -599,6 +605,7 @@ Tables_in_information_schema (T%)
TABLES
TABLE_PRIVILEGES
TABLE_CONSTRAINTS
TRIGGERS
select table_name from tables where table_name='user';
table_name
user
...
...
@@ -693,7 +700,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
10
0
10
1
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
...
...
@@ -704,6 +711,8 @@ information_schema COLUMNS COLUMN_TYPE
information_schema ROUTINES ROUTINE_DEFINITION
information_schema ROUTINES SQL_MODE
information_schema VIEWS VIEW_DEFINITION
information_schema TRIGGERS ACTION_CONDITION
information_schema TRIGGERS ACTION_STATEMENT
select table_name, column_name, data_type from information_schema.columns
where data_type = 'datetime';
table_name column_name data_type
...
...
@@ -712,6 +721,7 @@ TABLES UPDATE_TIME datetime
TABLES CHECK_TIME datetime
ROUTINES CREATED datetime
ROUTINES LAST_ALTERED datetime
TRIGGERS CREATED datetime
SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A
WHERE NOT EXISTS
(SELECT * FROM INFORMATION_SCHEMA.COLUMNS B
...
...
@@ -758,8 +768,71 @@ delete from mysql.db where user='mysqltest_4';
flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
information_schema 1
5
information_schema 1
6
mysql 17
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
begin
if new.j > 10 then
set new.j := 10;
end if;
end|
create trigger trg2 before update on t1 for each row
begin
if old.i % 2 = 0 then
set new.j := -1;
end if;
end|
create trigger trg3 after update on t1 for each row
begin
if new.j = -1 then
set @fired:= "Yes";
end if;
end|
show triggers;
Trigger Event Table Statement Timing Created
trg1 INSERT t1
begin
if new.j > 10 then
set new.j := 10;
end if;
end BEFORE NULL
trg2 UPDATE t1
begin
if old.i % 2 = 0 then
set new.j := -1;
end if;
end BEFORE NULL
trg3 UPDATE t1
begin
if new.j = -1 then
set @fired:= "Yes";
end if;
end AFTER NULL
select * from information_schema.triggers;
TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED
NULL test trg1 INSERT NULL test t1 0 NULL
begin
if new.j > 10 then
set new.j := 10;
end if;
end ROW BEFORE NULL NULL OLD NEW NULL
NULL test trg2 UPDATE NULL test t1 0 NULL
begin
if old.i % 2 = 0 then
set new.j := -1;
end if;
end ROW BEFORE NULL NULL OLD NEW NULL
NULL test trg3 UPDATE NULL test t1 0 NULL
begin
if new.j = -1 then
set @fired:= "Yes";
end if;
end ROW AFTER NULL NULL OLD NEW NULL
drop trigger trg1;
drop trigger trg2;
drop trigger trg3;
drop table t1;
create database mysqltest;
create table mysqltest.t1 (f1 int, f2 int);
create table mysqltest.t2 (f1 int);
...
...
mysql-test/r/information_schema_db.result
View file @
edcdd6cf
...
...
@@ -16,11 +16,13 @@ TABLE_PRIVILEGES
COLUMN_PRIVILEGES
TABLE_CONSTRAINTS
KEY_COLUMN_USAGE
TRIGGERS
show tables from INFORMATION_SCHEMA like 'T%';
Tables_in_information_schema (T%)
TABLES
TABLE_PRIVILEGES
TABLE_CONSTRAINTS
TRIGGERS
create database `inf%`;
use `inf%`;
show tables;
...
...
mysql-test/r/rpl_sp.result
View file @
edcdd6cf
...
...
@@ -237,7 +237,7 @@ select * from t1;
a
10
delete from t1;
drop trigger t
1.t
rg;
drop trigger trg;
insert into t1 values (1);
select * from t1;
a
...
...
@@ -248,7 +248,7 @@ master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000002 # Query 1 # use `mysqltest1`; create trigger trg before insert on t1 for each row set new.a= 10
master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
master-bin.000002 # Query 1 # use `mysqltest1`; delete from t1
master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger t
1.t
rg
master-bin.000002 # Query 1 # use `mysqltest1`; drop trigger trg
master-bin.000002 # Query 1 # use `mysqltest1`; insert into t1 values (1)
select * from t1;
a
...
...
mysql-test/r/trigger.result
View file @
edcdd6cf
...
...
@@ -12,13 +12,13 @@ insert into t1 values (1);
select @a;
@a
1
drop trigger t
1.t
rg;
drop trigger trg;
create trigger trg before insert on t1 for each row set @a:=new.i;
insert into t1 values (123);
select @a;
@a
123
drop trigger t
1.t
rg;
drop trigger trg;
drop table t1;
create table t1 (i int not null, j int);
create trigger trg before insert on t1 for each row
...
...
@@ -33,7 +33,7 @@ select * from t1|
i j
1 10
2 3
drop trigger t
1.t
rg|
drop trigger trg|
drop table t1|
create table t1 (i int not null primary key);
create trigger trg after insert on t1 for each row
...
...
@@ -43,7 +43,7 @@ insert into t1 values (2),(3),(4),(5);
select @a;
@a
2:3:4:5
drop trigger t
1.t
rg;
drop trigger trg;
drop table t1;
create table t1 (aid int not null primary key, balance int not null default 0);
insert into t1 values (1, 1000), (2,3000);
...
...
@@ -65,7 +65,7 @@ Too big change for aid = 2
aid balance
1 1500
2 3000
drop trigger t
1.t
rg|
drop trigger trg|
drop table t1|
create table t1 (i int);
insert into t1 values (1),(2),(3),(4);
...
...
@@ -76,7 +76,7 @@ update t1 set i=3;
select @total_change;
@total_change
2
drop trigger t
1.t
rg;
drop trigger trg;
drop table t1;
create table t1 (i int);
insert into t1 values (1),(2),(3),(4);
...
...
@@ -87,7 +87,7 @@ delete from t1 where i <= 3;
select @del_sum;
@del_sum
6
drop trigger t
1.t
rg;
drop trigger trg;
drop table t1;
create table t1 (i int);
insert into t1 values (1),(2),(3),(4);
...
...
@@ -97,7 +97,7 @@ delete from t1 where i <> 0;
select @del;
@del
1
drop trigger t
1.t
rg;
drop trigger trg;
drop table t1;
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
...
...
@@ -137,9 +137,9 @@ i j
1 20
2 -1
3 20
drop trigger t
1.t
rg1;
drop trigger t
1.t
rg2;
drop trigger t
1.t
rg3;
drop trigger trg1;
drop trigger trg2;
drop trigger trg3;
drop table t1;
create table t1 (id int not null primary key, data int);
create trigger t1_bi before insert on t1 for each row
...
...
@@ -197,7 +197,7 @@ select * from t2;
event
INSERT INTO t1 id=1 data='one'
INSERT INTO t1 id=2 data='two'
drop trigger t1
.t1
_ai;
drop trigger 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
...
...
@@ -271,6 +271,7 @@ id copy
3 NULL
drop table t1, t2;
create table t1 (i int);
create table t3 (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
create trigger trg before delete on t1 for each row set @a:= new.i;
...
...
@@ -292,14 +293,19 @@ create trigger trg after insert on t1 for each row set @a:=1;
ERROR HY000: Trigger already exists
create trigger trg2 before insert on t1 for each row set @a:=1;
ERROR HY000: Trigger already exists
drop trigger t1.trg;
drop trigger t1.trg;
create trigger trg before insert on t3 for each row set @a:=1;
ERROR HY000: Trigger already exists
create trigger trg2 before insert on t3 for each row set @a:=1;
drop trigger trg2;
drop trigger trg;
drop trigger trg;
ERROR HY000: Trigger does not exist
create view v1 as select * from t1;
create trigger trg before insert on v1 for each row set @a:=1;
ERROR HY000: 'test.v1' is not BASE TABLE
drop view v1;
drop table t1;
drop table t3;
create temporary table t1 (i int);
create trigger trg before insert on t1 for each row set @a:=1;
ERROR HY000: Trigger's 't1' is view or temporary table
...
...
@@ -307,7 +313,7 @@ drop table t1;
create table t1 (x1col char);
create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
insert into t1 values ('y');
drop trigger t
1.t
x1;
drop trigger tx1;
drop table t1;
create table t1 (i int) engine=myisam;
insert into t1 values (1), (2);
...
...
@@ -318,8 +324,8 @@ delete from t1;
select @del_before, @del_after;
@del_before @del_after
3 3
drop trigger t
1.t
rg1;
drop trigger t
1.t
rg2;
drop trigger trg1;
drop trigger trg2;
drop table t1;
create table t1 (a int);
create trigger trg1 before insert on t1 for each row set new.a= 10;
...
...
@@ -336,6 +342,15 @@ create table t1 (i int);
create trigger trg1 before insert on t1 for each row set @a:= 1;
drop database mysqltest;
use test;
create database mysqltest;
create table mysqltest.t1 (i int);
create trigger trg1 before insert on mysqltest.t1 for each row set @a:= 1;
ERROR HY000: Trigger in wrong schema
use mysqltest;
create trigger test.trg1 before insert on t1 for each row set @a:= 1;
ERROR HY000: Trigger in wrong schema
drop database mysqltest;
use test;
create table t1 (i int, j int default 10, k int not null, key (k));
create table t2 (i int);
insert into t1 (i, k) values (1, 1);
...
...
@@ -549,7 +564,7 @@ i k
1 1
2 2
alter table t1 add primary key (i);
drop trigger
t1.
bi;
drop trigger bi;
insert into t1 values (2, 4) on duplicate key update k= k + 10;
ERROR 42S22: Unknown column 'bt' in 'NEW'
select * from t1;
...
...
@@ -578,5 +593,5 @@ create trigger t1_bu before update on t1 for each row set new.col1= bug5893();
drop function bug5893;
update t1 set col2 = 4;
ERROR 42000: FUNCTION test.bug5893 does not exist
drop trigger t1
.t1
_bu;
drop trigger t1_bu;
drop table t1;
mysql-test/r/view.result
View file @
edcdd6cf
...
...
@@ -1245,7 +1245,7 @@ select * from v1;
s1
select * from t1;
s1
drop trigger t1
.t1
_bi;
drop trigger t1_bi;
drop view v1;
drop table t1;
create table t1 (s1 tinyint);
...
...
mysql-test/t/information_schema.test
View file @
edcdd6cf
...
...
@@ -507,6 +507,41 @@ flush privileges;
#
SELECT
table_schema
,
count
(
*
)
FROM
information_schema
.
TABLES
GROUP
BY
TABLE_SCHEMA
;
#
# TRIGGERS table test
#
create
table
t1
(
i
int
,
j
int
);
delimiter
|
;
create
trigger
trg1
before
insert
on
t1
for
each
row
begin
if
new
.
j
>
10
then
set
new
.
j
:=
10
;
end
if
;
end
|
create
trigger
trg2
before
update
on
t1
for
each
row
begin
if
old
.
i
%
2
=
0
then
set
new
.
j
:=
-
1
;
end
if
;
end
|
create
trigger
trg3
after
update
on
t1
for
each
row
begin
if
new
.
j
=
-
1
then
set
@
fired
:=
"Yes"
;
end
if
;
end
|
delimiter
;
|
show
triggers
;
select
*
from
information_schema
.
triggers
;
drop
trigger
trg1
;
drop
trigger
trg2
;
drop
trigger
trg3
;
drop
table
t1
;
#
# Bug #10964 Information Schema:Authorization check on privilege tables is improper
#
...
...
mysql-test/t/rpl_sp.test
View file @
edcdd6cf
...
...
@@ -249,7 +249,7 @@ select * from t1;
connection
master
;
delete
from
t1
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
insert
into
t1
values
(
1
);
select
*
from
t1
;
--
replace_column
2
# 5 #
...
...
mysql-test/t/trigger.test
View file @
edcdd6cf
...
...
@@ -17,13 +17,13 @@ set @a:=0;
select
@
a
;
insert
into
t1
values
(
1
);
select
@
a
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
# let us test simple trigger reading some values
create
trigger
trg
before
insert
on
t1
for
each
row
set
@
a
:=
new
.
i
;
insert
into
t1
values
(
123
);
select
@
a
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
drop
table
t1
;
...
...
@@ -40,7 +40,7 @@ end|
insert
into
t1
(
i
)
values
(
1
)
|
insert
into
t1
(
i
,
j
)
values
(
2
,
3
)
|
select
*
from
t1
|
drop
trigger
t
1
.
t
rg
|
drop
trigger
trg
|
drop
table
t1
|
delimiter
;
|
...
...
@@ -52,7 +52,7 @@ create trigger trg after insert on t1 for each row
set
@
a
:=
""
;
insert
into
t1
values
(
2
),(
3
),(
4
),(
5
);
select
@
a
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
drop
table
t1
;
# PS doesn't work with multi-row statements
...
...
@@ -75,7 +75,7 @@ set @update_failed:=""|
update
t1
set
balance
=
1500
|
select
@
update_failed
;
select
*
from
t1
|
drop
trigger
t
1
.
t
rg
|
drop
trigger
trg
|
drop
table
t1
|
delimiter
;
|
--
enable_ps_protocol
...
...
@@ -88,7 +88,7 @@ create trigger trg after update on t1 for each row
set
@
total_change
:=
0
;
update
t1
set
i
=
3
;
select
@
total_change
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
drop
table
t1
;
# Before delete trigger
...
...
@@ -100,7 +100,7 @@ create trigger trg before delete on t1 for each row
set
@
del_sum
:=
0
;
delete
from
t1
where
i
<=
3
;
select
@
del_sum
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
drop
table
t1
;
# After delete trigger.
...
...
@@ -111,7 +111,7 @@ create trigger trg after delete on t1 for each row set @del:= 1;
set
@
del
:=
0
;
delete
from
t1
where
i
<>
0
;
select
@
del
;
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
drop
table
t1
;
# Several triggers on one table
...
...
@@ -145,9 +145,9 @@ update t1 set j= 20;
select
@
fired
;
select
*
from
t1
;
drop
trigger
t
1
.
t
rg1
;
drop
trigger
t
1
.
t
rg2
;
drop
trigger
t
1
.
t
rg3
;
drop
trigger
trg1
;
drop
trigger
trg2
;
drop
trigger
trg3
;
drop
table
t1
;
...
...
@@ -212,7 +212,7 @@ create trigger t1_ai after insert on t1 for each row
insert
into
t1
(
id
,
data
)
values
(
1
,
"one"
),
(
2
,
"two"
);
select
*
from
t1
;
select
*
from
t2
;
drop
trigger
t1
.
t1
_ai
;
drop
trigger
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
...
...
@@ -282,6 +282,7 @@ drop table t1, t2;
# Test of wrong column specifiers in triggers
#
create
table
t1
(
i
int
);
create
table
t3
(
i
int
);
--
error
1363
create
trigger
trg
before
insert
on
t1
for
each
row
set
@
a
:=
old
.
i
;
...
...
@@ -301,7 +302,7 @@ create trigger trg before update on t1 for each row set @a:=old.j;
#
# Let us test various trigger creation errors
#
#
Also quickly test table namespace (bug#5892/6182)
#
--
error
1146
create
trigger
trg
before
insert
on
t2
for
each
row
set
@
a
:=
1
;
...
...
@@ -311,10 +312,14 @@ create trigger trg before insert on t1 for each row set @a:=1;
create
trigger
trg
after
insert
on
t1
for
each
row
set
@
a
:=
1
;
--
error
1359
create
trigger
trg2
before
insert
on
t1
for
each
row
set
@
a
:=
1
;
drop
trigger
t1
.
trg
;
--
error
1359
create
trigger
trg
before
insert
on
t3
for
each
row
set
@
a
:=
1
;
create
trigger
trg2
before
insert
on
t3
for
each
row
set
@
a
:=
1
;
drop
trigger
trg2
;
drop
trigger
trg
;
--
error
1360
drop
trigger
t
1
.
t
rg
;
drop
trigger
trg
;
create
view
v1
as
select
*
from
t1
;
--
error
1347
...
...
@@ -322,6 +327,7 @@ create trigger trg before insert on v1 for each row set @a:=1;
drop
view
v1
;
drop
table
t1
;
drop
table
t3
;
create
temporary
table
t1
(
i
int
);
--
error
1361
...
...
@@ -339,7 +345,7 @@ drop table t1;
create
table
t1
(
x1col
char
);
create
trigger
tx1
before
insert
on
t1
for
each
row
set
new
.
x1col
=
'x'
;
insert
into
t1
values
(
'y'
);
drop
trigger
t
1
.
t
x1
;
drop
trigger
tx1
;
drop
table
t1
;
#
...
...
@@ -355,8 +361,8 @@ create trigger trg2 after delete on t1 for each row set @del_after:= @del_after
set
@
del_before
:=
0
,
@
del_after
:=
0
;
delete
from
t1
;
select
@
del_before
,
@
del_after
;
drop
trigger
t
1
.
t
rg1
;
drop
trigger
t
1
.
t
rg2
;
drop
trigger
trg1
;
drop
trigger
trg2
;
drop
table
t1
;
# Test for bug #5859 "DROP TABLE does not drop triggers". Trigger should not
...
...
@@ -378,6 +384,19 @@ create trigger trg1 before insert on t1 for each row set @a:= 1;
drop
database
mysqltest
;
use
test
;
# Test for bug #8791
# "Triggers: Allowed to create triggers on a subject table in a different DB".
create
database
mysqltest
;
create
table
mysqltest
.
t1
(
i
int
);
--
error
ER_TRG_IN_WRONG_SCHEMA
create
trigger
trg1
before
insert
on
mysqltest
.
t1
for
each
row
set
@
a
:=
1
;
use
mysqltest
;
--
error
ER_TRG_IN_WRONG_SCHEMA
create
trigger
test
.
trg1
before
insert
on
t1
for
each
row
set
@
a
:=
1
;
drop
database
mysqltest
;
use
test
;
# Test for bug #5860 "Multi-table UPDATE does not activate update triggers"
# We will also test how delete triggers wor for multi-table DELETE.
create
table
t1
(
i
int
,
j
int
default
10
,
k
int
not
null
,
key
(
k
));
...
...
@@ -559,7 +578,7 @@ select * from t1;
# To test properly code-paths different from those that are used
# in ordinary INSERT we need to drop "before insert" trigger.
alter
table
t1
add
primary
key
(
i
);
drop
trigger
t1
.
bi
;
drop
trigger
bi
;
--
error
1054
insert
into
t1
values
(
2
,
4
)
on
duplicate
key
update
k
=
k
+
10
;
select
*
from
t1
;
...
...
@@ -589,5 +608,5 @@ drop function bug5893;
--
error
1305
update
t1
set
col2
=
4
;
# This should not crash server too.
drop
trigger
t1
.
t1
_bu
;
drop
trigger
t1_bu
;
drop
table
t1
;
mysql-test/t/view.test
View file @
edcdd6cf
...
...
@@ -1182,7 +1182,7 @@ create view v1 as select * from t1 where s1 <> 127 with check option;
insert
into
v1
values
(
0
);
select
*
from
v1
;
select
*
from
t1
;
drop
trigger
t1
.
t1
_bi
;
drop
trigger
t1_bi
;
drop
view
v1
;
drop
table
t1
;
...
...
sql/handler.cc
View file @
edcdd6cf
...
...
@@ -2434,6 +2434,7 @@ TYPELIB *ha_known_exts(void)
known_extensions_id
=
mysys_usage_id
;
found_exts
.
push_back
((
char
*
)
triggers_file_ext
);
found_exts
.
push_back
((
char
*
)
trigname_file_ext
);
for
(
types
=
sys_table_types
;
types
->
type
;
types
++
)
{
if
(
*
types
->
value
==
SHOW_OPTION_YES
)
...
...
sql/item.h
View file @
edcdd6cf
...
...
@@ -1781,7 +1781,7 @@ class Item_insert_value : public Item_field
*/
enum
trg_action_time_type
{
TRG_ACTION_BEFORE
=
0
,
TRG_ACTION_AFTER
=
1
TRG_ACTION_BEFORE
=
0
,
TRG_ACTION_AFTER
=
1
,
TRG_ACTION_MAX
};
/*
...
...
@@ -1789,7 +1789,7 @@ enum trg_action_time_type
*/
enum
trg_event_type
{
TRG_EVENT_INSERT
=
0
,
TRG_EVENT_UPDATE
=
1
,
TRG_EVENT_DELETE
=
2
TRG_EVENT_INSERT
=
0
,
TRG_EVENT_UPDATE
=
1
,
TRG_EVENT_DELETE
=
2
,
TRG_EVENT_MAX
};
class
Table_triggers_list
;
...
...
sql/lex.h
View file @
edcdd6cf
...
...
@@ -497,6 +497,7 @@ static SYMBOL symbols[] = {
{
"TRAILING"
,
SYM
(
TRAILING
)},
{
"TRANSACTION"
,
SYM
(
TRANSACTION_SYM
)},
{
"TRIGGER"
,
SYM
(
TRIGGER_SYM
)},
{
"TRIGGERS"
,
SYM
(
TRIGGERS_SYM
)},
{
"TRUE"
,
SYM
(
TRUE_SYM
)},
{
"TRUNCATE"
,
SYM
(
TRUNCATE_SYM
)},
{
"TYPE"
,
SYM
(
TYPE_SYM
)},
...
...
sql/mysql_priv.h
View file @
edcdd6cf
...
...
@@ -1082,6 +1082,7 @@ extern const char **errmesg; /* Error messages */
extern
const
char
*
myisam_recover_options_str
;
extern
const
char
*
in_left_expr_name
,
*
in_additional_cond
;
extern
const
char
*
const
triggers_file_ext
;
extern
const
char
*
const
trigname_file_ext
;
extern
Eq_creator
eq_creator
;
extern
Ne_creator
ne_creator
;
extern
Gt_creator
gt_creator
;
...
...
sql/mysqld.cc
View file @
edcdd6cf
...
...
@@ -5728,6 +5728,7 @@ struct show_var_st status_vars[]= {
{
"Com_show_status"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_STATUS
]),
SHOW_LONG_STATUS
},
{
"Com_show_storage_engines"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_STORAGE_ENGINES
]),
SHOW_LONG_STATUS
},
{
"Com_show_tables"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_TABLES
]),
SHOW_LONG_STATUS
},
{
"Com_show_triggers"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_TRIGGERS
]),
SHOW_LONG_STATUS
},
{
"Com_show_variables"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_VARIABLES
]),
SHOW_LONG_STATUS
},
{
"Com_show_warnings"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_WARNS
]),
SHOW_LONG_STATUS
},
{
"Com_slave_start"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SLAVE_START
]),
SHOW_LONG_STATUS
},
...
...
sql/share/errmsg.txt
View file @
edcdd6cf
...
...
@@ -5382,3 +5382,5 @@ ER_FOREIGN_DATA_STRING_INVALID
eng "The data source connection string '%-.64s' is not in the correct format"
ER_CANT_CREATE_FEDERATED_TABLE
eng "Can't create federated table. Foreign data src error : '%-.64s'"
ER_TRG_IN_WRONG_SCHEMA
eng "Trigger in wrong schema"
sql/sp.cc
View file @
edcdd6cf
...
...
@@ -1442,8 +1442,8 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
{
Sroutine_hash_entry
**
last_cached_routine_ptr
=
(
Sroutine_hash_entry
**
)
lex
->
sroutines_list
.
next
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
for
(
int
j
=
0
;
j
<
2
;
j
++
)
for
(
int
i
=
0
;
i
<
(
int
)
TRG_EVENT_MAX
;
i
++
)
for
(
int
j
=
0
;
j
<
(
int
)
TRG_ACTION_MAX
;
j
++
)
if
(
triggers
->
bodies
[
i
][
j
])
{
(
void
)
triggers
->
bodies
[
i
][
j
]
->
add_used_tables_to_table_list
(
thd
,
...
...
sql/sql_base.cc
View file @
edcdd6cf
...
...
@@ -1740,7 +1740,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
!
my_strcasecmp
(
system_charset_info
,
name
,
"proc"
))
entry
->
s
->
system_table
=
1
;
if
(
Table_triggers_list
::
check_n_load
(
thd
,
db
,
name
,
entry
))
if
(
Table_triggers_list
::
check_n_load
(
thd
,
db
,
name
,
entry
,
0
))
goto
err
;
/*
...
...
sql/sql_lex.h
View file @
edcdd6cf
...
...
@@ -57,6 +57,7 @@ enum enum_sql_command {
SQLCOM_SHOW_PROCESSLIST
,
SQLCOM_SHOW_MASTER_STAT
,
SQLCOM_SHOW_SLAVE_STAT
,
SQLCOM_SHOW_GRANTS
,
SQLCOM_SHOW_CREATE
,
SQLCOM_SHOW_CHARSETS
,
SQLCOM_SHOW_COLLATIONS
,
SQLCOM_SHOW_CREATE_DB
,
SQLCOM_SHOW_TABLE_STATUS
,
SQLCOM_SHOW_TRIGGERS
,
SQLCOM_LOAD
,
SQLCOM_SET_OPTION
,
SQLCOM_LOCK_TABLES
,
SQLCOM_UNLOCK_TABLES
,
SQLCOM_GRANT
,
...
...
sql/sql_parse.cc
View file @
edcdd6cf
...
...
@@ -2104,6 +2104,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
case
SCH_TABLE_NAMES
:
case
SCH_TABLES
:
case
SCH_VIEWS
:
case
SCH_TRIGGERS
:
#ifdef DONT_ALLOW_SHOW_COMMANDS
my_message
(
ER_NOT_ALLOWED_COMMAND
,
ER
(
ER_NOT_ALLOWED_COMMAND
),
MYF
(
0
));
/* purecov: inspected */
...
...
sql/sql_show.cc
View file @
edcdd6cf
...
...
@@ -21,6 +21,7 @@
#include "sql_select.h" // For select_describe
#include "repl_failsafe.h"
#include "sp_head.h"
#include "sql_trigger.h"
#include <my_dir.h>
#ifdef HAVE_BERKELEY_DB
...
...
@@ -1696,6 +1697,7 @@ void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
break
;
case
SQLCOM_SHOW_TABLES
:
case
SQLCOM_SHOW_TABLE_STATUS
:
case
SQLCOM_SHOW_TRIGGERS
:
index_field_values
->
db_value
=
lex
->
current_select
->
db
;
index_field_values
->
table_value
=
wild
;
break
;
...
...
@@ -2977,6 +2979,73 @@ static int get_schema_constraints_record(THD *thd, struct st_table_list *tables,
}
static
bool
store_trigger
(
THD
*
thd
,
TABLE
*
table
,
const
char
*
db
,
const
char
*
tname
,
LEX_STRING
*
trigger_name
,
enum
trg_event_type
event
,
enum
trg_action_time_type
timing
,
LEX_STRING
*
trigger_stmt
)
{
CHARSET_INFO
*
cs
=
system_charset_info
;
restore_record
(
table
,
s
->
default_values
);
table
->
field
[
1
]
->
store
(
db
,
strlen
(
db
),
cs
);
table
->
field
[
2
]
->
store
(
trigger_name
->
str
,
trigger_name
->
length
,
cs
);
table
->
field
[
3
]
->
store
(
trg_event_type_names
[
event
].
str
,
trg_event_type_names
[
event
].
length
,
cs
);
table
->
field
[
5
]
->
store
(
db
,
strlen
(
db
),
cs
);
table
->
field
[
6
]
->
store
(
tname
,
strlen
(
tname
),
cs
);
table
->
field
[
9
]
->
store
(
trigger_stmt
->
str
,
trigger_stmt
->
length
,
cs
);
table
->
field
[
10
]
->
store
(
"ROW"
,
3
,
cs
);
table
->
field
[
11
]
->
store
(
trg_action_time_type_names
[
timing
].
str
,
trg_action_time_type_names
[
timing
].
length
,
cs
);
table
->
field
[
14
]
->
store
(
"OLD"
,
3
,
cs
);
table
->
field
[
15
]
->
store
(
"NEW"
,
3
,
cs
);
return
schema_table_store_record
(
thd
,
table
);
}
static
int
get_schema_triggers_record
(
THD
*
thd
,
struct
st_table_list
*
tables
,
TABLE
*
table
,
bool
res
,
const
char
*
base_name
,
const
char
*
file_name
)
{
DBUG_ENTER
(
"get_schema_triggers_record"
);
/*
res can be non zero value when processed table is a view or
error happened during opening of processed table.
*/
if
(
res
)
{
if
(
!
tables
->
view
)
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
thd
->
net
.
last_errno
,
thd
->
net
.
last_error
);
thd
->
clear_error
();
DBUG_RETURN
(
0
);
}
if
(
!
tables
->
view
&&
tables
->
table
->
triggers
)
{
Table_triggers_list
*
triggers
=
tables
->
table
->
triggers
;
int
event
,
timing
;
for
(
event
=
0
;
event
<
(
int
)
TRG_EVENT_MAX
;
event
++
)
{
for
(
timing
=
0
;
timing
<
(
int
)
TRG_ACTION_MAX
;
timing
++
)
{
LEX_STRING
trigger_name
;
LEX_STRING
trigger_stmt
;
if
(
triggers
->
get_trigger_info
(
thd
,
(
enum
trg_event_type
)
event
,
(
enum
trg_action_time_type
)
timing
,
&
trigger_name
,
&
trigger_stmt
))
continue
;
if
(
store_trigger
(
thd
,
table
,
base_name
,
file_name
,
&
trigger_name
,
(
enum
trg_event_type
)
event
,
(
enum
trg_action_time_type
)
timing
,
&
trigger_stmt
))
DBUG_RETURN
(
1
);
}
}
}
DBUG_RETURN
(
0
);
}
void
store_key_column_usage
(
TABLE
*
table
,
const
char
*
db
,
const
char
*
tname
,
const
char
*
key_name
,
uint
key_len
,
const
char
*
con_type
,
uint
con_len
,
longlong
idx
)
...
...
@@ -3861,6 +3930,29 @@ ST_FIELD_INFO open_tables_fields_info[]=
};
ST_FIELD_INFO
triggers_fields_info
[]
=
{
{
"TRIGGER_CATALOG"
,
FN_REFLEN
,
MYSQL_TYPE_STRING
,
0
,
1
,
0
},
{
"TRIGGER_SCHEMA"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
},
{
"TRIGGER_NAME"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Trigger"
},
{
"EVENT_MANIPULATION"
,
6
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Event"
},
{
"EVENT_OBJECT_CATALOG"
,
FN_REFLEN
,
MYSQL_TYPE_STRING
,
0
,
1
,
0
},
{
"EVENT_OBJECT_SCHEMA"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
},
{
"EVENT_OBJECT_TABLE"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Table"
},
{
"ACTION_ORDER"
,
4
,
MYSQL_TYPE_LONG
,
0
,
0
,
0
},
{
"ACTION_CONDITION"
,
65535
,
MYSQL_TYPE_STRING
,
0
,
1
,
0
},
{
"ACTION_STATEMENT"
,
65535
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Statement"
},
{
"ACTION_ORIENTATION"
,
9
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
},
{
"ACTION_TIMING"
,
6
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Timing"
},
{
"ACTION_REFERENCE_OLD_TABLE"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
1
,
0
},
{
"ACTION_REFERENCE_NEW_TABLE"
,
NAME_LEN
,
MYSQL_TYPE_STRING
,
0
,
1
,
0
},
{
"ACTION_REFERENCE_OLD_ROW"
,
3
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
},
{
"ACTION_REFERENCE_NEW_ROW"
,
3
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
},
{
"CREATED"
,
0
,
MYSQL_TYPE_TIMESTAMP
,
0
,
1
,
"Created"
},
{
0
,
0
,
MYSQL_TYPE_STRING
,
0
,
0
,
0
}
};
ST_FIELD_INFO
variables_fields_info
[]
=
{
{
"Variable_name"
,
80
,
MYSQL_TYPE_STRING
,
0
,
0
,
"Variable_name"
},
...
...
@@ -3911,6 +4003,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_open_tables
,
make_old_format
,
0
,
-
1
,
-
1
,
1
},
{
"STATUS"
,
variables_fields_info
,
create_schema_table
,
fill_status
,
make_old_format
,
0
,
-
1
,
-
1
,
1
},
{
"TRIGGERS"
,
triggers_fields_info
,
create_schema_table
,
get_all_tables
,
make_old_format
,
get_schema_triggers_record
,
5
,
6
,
0
},
{
"VARIABLES"
,
variables_fields_info
,
create_schema_table
,
fill_variables
,
make_old_format
,
0
,
-
1
,
-
1
,
1
},
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
}
...
...
sql/sql_table.cc
View file @
edcdd6cf
...
...
@@ -23,6 +23,8 @@
#include <hash.h>
#include <myisam.h>
#include <my_dir.h>
#include "sp_head.h"
#include "sql_trigger.h"
#ifdef __WIN__
#include <io.h>
...
...
@@ -290,16 +292,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if
(
!
(
new_error
=
my_delete
(
path
,
MYF
(
MY_WME
))))
{
some_tables_deleted
=
1
;
/*
Destroy triggers for this table if there are any.
We won't need this as soon as we will have new .FRM format,
in which we will store trigger definitions in the same .FRM
files as table descriptions.
*/
strmov
(
end
,
triggers_file_ext
);
if
(
!
access
(
path
,
F_OK
))
new_error
=
my_delete
(
path
,
MYF
(
MY_WME
));
new_error
=
Table_triggers_list
::
drop_all_triggers
(
thd
,
db
,
table
->
table_name
);
}
error
|=
new_error
;
}
...
...
sql/sql_trigger.cc
View file @
edcdd6cf
...
...
@@ -38,6 +38,45 @@ static File_option triggers_file_parameters[]=
};
/*
Structure representing contents of .TRN file which are used to support
database wide trigger namespace.
*/
struct
st_trigname
{
LEX_STRING
trigger_table
;
};
static
const
LEX_STRING
trigname_file_type
=
{(
char
*
)
"TRIGGERNAME"
,
11
};
const
char
*
const
trigname_file_ext
=
".TRN"
;
static
File_option
trigname_file_parameters
[]
=
{
{{(
char
*
)
"trigger_table"
,
15
},
offsetof
(
struct
st_trigname
,
trigger_table
),
FILE_OPTIONS_ESTRING
},
{{
0
,
0
},
0
,
FILE_OPTIONS_STRING
}
};
const
LEX_STRING
trg_action_time_type_names
[]
=
{
{
(
char
*
)
STRING_WITH_LEN
(
"BEFORE"
)
},
{
(
char
*
)
STRING_WITH_LEN
(
"AFTER"
)
}
};
const
LEX_STRING
trg_event_type_names
[]
=
{
{
(
char
*
)
STRING_WITH_LEN
(
"INSERT"
)
},
{
(
char
*
)
STRING_WITH_LEN
(
"UPDATE"
)
},
{
(
char
*
)
STRING_WITH_LEN
(
"DELETE"
)
}
};
static
TABLE_LIST
*
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trig
);
/*
Create or drop trigger for table.
...
...
@@ -69,6 +108,10 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
But do we want this ?
*/
if
(
!
create
&&
!
(
tables
=
add_table_for_trigger
(
thd
,
thd
->
lex
->
spname
)))
DBUG_RETURN
(
TRUE
);
/* We should have only one table in table list. */
DBUG_ASSERT
(
tables
->
next_global
==
0
);
...
...
@@ -174,28 +217,28 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
{
LEX
*
lex
=
thd
->
lex
;
TABLE
*
table
=
tables
->
table
;
char
dir_buff
[
FN_REFLEN
],
file_buff
[
FN_REFLEN
];
LEX_STRING
dir
,
file
;
char
dir_buff
[
FN_REFLEN
],
file_buff
[
FN_REFLEN
],
trigname_buff
[
FN_REFLEN
],
trigname_path
[
FN_REFLEN
];
LEX_STRING
dir
,
file
,
trigname_file
;
LEX_STRING
*
trg_def
,
*
name
;
Item_trigger_field
*
trg_field
;
List_iterator_fast
<
LEX_STRING
>
it
(
names_list
)
;
struct
st_trigname
trigname
;
/* We don't allow creation of several triggers of the same type yet */
if
(
bodies
[
lex
->
trg_chistics
.
event
][
lex
->
trg_chistics
.
action_time
])
/* Trigger must be in the same schema as target table. */
if
(
my_strcasecmp
(
system_charset_info
,
table
->
s
->
db
,
lex
->
spname
->
m_db
.
str
?
lex
->
spname
->
m_db
.
str
:
thd
->
db
))
{
my_
message
(
ER_TRG_ALREADY_EXISTS
,
ER
(
ER_TRG_ALREADY_EXISTS
)
,
MYF
(
0
));
my_
error
(
ER_TRG_IN_WRONG_SCHEMA
,
MYF
(
0
));
return
1
;
}
/*
Let us check if trigger with the same name exists
*/
while
((
name
=
it
++
)
)
/*
We don't allow creation of several triggers of the same type yet
*/
if
(
bodies
[
lex
->
trg_chistics
.
event
][
lex
->
trg_chistics
.
action_time
]
)
{
if
(
my_strcasecmp
(
system_charset_info
,
lex
->
ident
.
str
,
name
->
str
)
==
0
)
{
my_message
(
ER_TRG_ALREADY_EXISTS
,
ER
(
ER_TRG_ALREADY_EXISTS
),
MYF
(
0
));
return
1
;
}
my_message
(
ER_TRG_ALREADY_EXISTS
,
ER
(
ER_TRG_ALREADY_EXISTS
),
MYF
(
0
));
return
1
;
}
/*
...
...
@@ -234,6 +277,25 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
file
.
length
=
strxnmov
(
file_buff
,
FN_REFLEN
,
tables
->
table_name
,
triggers_file_ext
,
NullS
)
-
file_buff
;
file
.
str
=
file_buff
;
trigname_file
.
length
=
strxnmov
(
trigname_buff
,
FN_REFLEN
,
lex
->
spname
->
m_name
.
str
,
trigname_file_ext
,
NullS
)
-
trigname_buff
;
trigname_file
.
str
=
trigname_buff
;
strxnmov
(
trigname_path
,
FN_REFLEN
,
dir_buff
,
trigname_buff
,
NullS
);
/* Use the filesystem to enforce trigger namespace constraints. */
if
(
!
access
(
trigname_path
,
F_OK
))
{
my_error
(
ER_TRG_ALREADY_EXISTS
,
MYF
(
0
));
return
1
;
}
trigname
.
trigger_table
.
str
=
tables
->
table_name
;
trigname
.
trigger_table
.
length
=
tables
->
table_name_length
;
if
(
sql_create_definition_file
(
&
dir
,
&
trigname_file
,
&
trigname_file_type
,
(
gptr
)
&
trigname
,
trigname_file_parameters
,
0
))
return
1
;
/*
Soon we will invalidate table object and thus Table_triggers_list object
...
...
@@ -246,13 +308,66 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
if
(
!
(
trg_def
=
(
LEX_STRING
*
)
alloc_root
(
&
table
->
mem_root
,
sizeof
(
LEX_STRING
)))
||
definitions_list
.
push_back
(
trg_def
,
&
table
->
mem_root
))
return
1
;
goto
err_with_cleanup
;
trg_def
->
str
=
thd
->
query
;
trg_def
->
length
=
thd
->
query_length
;
return
sql_create_definition_file
(
&
dir
,
&
file
,
&
triggers_file_type
,
(
gptr
)
this
,
triggers_file_parameters
,
3
);
if
(
!
sql_create_definition_file
(
&
dir
,
&
file
,
&
triggers_file_type
,
(
gptr
)
this
,
triggers_file_parameters
,
3
))
return
0
;
err_with_cleanup:
my_delete
(
trigname_path
,
MYF
(
MY_WME
));
return
1
;
}
/*
Deletes the .TRG file for a table
SYNOPSIS
rm_trigger_file()
path - char buffer of size FN_REFLEN to be used
for constructing path to .TRG file.
db - table's database name
table_name - table's name
RETURN VALUE
False - success
True - error
*/
static
bool
rm_trigger_file
(
char
*
path
,
char
*
db
,
char
*
table_name
)
{
strxnmov
(
path
,
FN_REFLEN
,
mysql_data_home
,
"/"
,
db
,
"/"
,
table_name
,
triggers_file_ext
,
NullS
);
unpack_filename
(
path
,
path
);
return
my_delete
(
path
,
MYF
(
MY_WME
));
}
/*
Deletes the .TRN file for a trigger
SYNOPSIS
rm_trigname_file()
path - char buffer of size FN_REFLEN to be used
for constructing path to .TRN file.
db - trigger's database name
table_name - trigger's name
RETURN VALUE
False - success
True - error
*/
static
bool
rm_trigname_file
(
char
*
path
,
char
*
db
,
char
*
trigger_name
)
{
strxnmov
(
path
,
FN_REFLEN
,
mysql_data_home
,
"/"
,
db
,
"/"
,
trigger_name
,
trigname_file_ext
,
NullS
);
unpack_filename
(
path
,
path
);
return
my_delete
(
path
,
MYF
(
MY_WME
));
}
...
...
@@ -275,12 +390,13 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
LEX_STRING
*
name
;
List_iterator_fast
<
LEX_STRING
>
it_name
(
names_list
);
List_iterator
<
LEX_STRING
>
it_def
(
definitions_list
);
char
path
[
FN_REFLEN
];
while
((
name
=
it_name
++
))
{
it_def
++
;
if
(
my_strcasecmp
(
system_charset_info
,
lex
->
ident
.
str
,
if
(
my_strcasecmp
(
system_charset_info
,
lex
->
spname
->
m_name
.
str
,
name
->
str
)
==
0
)
{
/*
...
...
@@ -291,18 +407,14 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
if
(
definitions_list
.
is_empty
())
{
char
path
[
FN_REFLEN
];
/*
TODO: Probably instead of removing .TRG file we should move
to archive directory but this should be done as part of
parse_file.cc functionality (because we will need it
elsewhere).
*/
strxnmov
(
path
,
FN_REFLEN
,
mysql_data_home
,
"/"
,
tables
->
db
,
"/"
,
tables
->
table_name
,
triggers_file_ext
,
NullS
);
unpack_filename
(
path
,
path
);
return
my_delete
(
path
,
MYF
(
MY_WME
));
if
(
rm_trigger_file
(
path
,
tables
->
db
,
tables
->
table_name
))
return
1
;
}
else
{
...
...
@@ -317,10 +429,15 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
triggers_file_ext
,
NullS
)
-
file_buff
;
file
.
str
=
file_buff
;
return
sql_create_definition_file
(
&
dir
,
&
file
,
&
triggers_file_type
,
(
gptr
)
this
,
triggers_file_parameters
,
3
);
if
(
sql_create_definition_file
(
&
dir
,
&
file
,
&
triggers_file_type
,
(
gptr
)
this
,
triggers_file_parameters
,
3
))
return
1
;
}
if
(
rm_trigname_file
(
path
,
tables
->
db
,
lex
->
spname
->
m_name
.
str
))
return
1
;
return
0
;
}
}
...
...
@@ -331,8 +448,8 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
Table_triggers_list
::~
Table_triggers_list
()
{
for
(
int
i
=
0
;
i
<
3
;
i
++
)
for
(
int
j
=
0
;
j
<
2
;
j
++
)
for
(
int
i
=
0
;
i
<
(
int
)
TRG_EVENT_MAX
;
i
++
)
for
(
int
j
=
0
;
j
<
(
int
)
TRG_ACTION_MAX
;
j
++
)
delete
bodies
[
i
][
j
];
if
(
record1_field
)
...
...
@@ -389,13 +506,16 @@ bool Table_triggers_list::prepare_record1_accessors(TABLE *table)
db - table's database name
table_name - table's name
table - pointer to table object
names_only - stop after loading trigger names
RETURN VALUE
False - success
True - error
*/
bool
Table_triggers_list
::
check_n_load
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
,
TABLE
*
table
)
const
char
*
table_name
,
TABLE
*
table
,
bool
names_only
)
{
char
path_buff
[
FN_REFLEN
];
LEX_STRING
path
;
...
...
@@ -451,7 +571,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
TODO: This could be avoided if there is no triggers
for UPDATE and DELETE.
*/
if
(
triggers
->
prepare_record1_accessors
(
table
))
if
(
!
names_only
&&
triggers
->
prepare_record1_accessors
(
table
))
DBUG_RETURN
(
1
);
List_iterator_fast
<
LEX_STRING
>
it
(
triggers
->
definitions_list
);
...
...
@@ -471,32 +591,20 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
Free lex associated resources
QQ: Do we really need all this stuff here ?
*/
if
(
lex
.
sphead
)
{
delete
lex
.
sphead
;
lex
.
sphead
=
0
;
}
delete
lex
.
sphead
;
goto
err_with_lex_cleanup
;
}
triggers
->
bodies
[
lex
.
trg_chistics
.
event
]
[
lex
.
trg_chistics
.
action_time
]
=
lex
.
sphead
;
lex
.
sphead
=
0
;
if
(
!
(
trg_name_buff
=
alloc_root
(
&
table
->
mem_root
,
sizeof
(
LEX_STRING
)
+
lex
.
ident
.
length
+
1
)))
goto
err_with_lex_cleanup
;
trg_name_str
=
(
LEX_STRING
*
)
trg_name_buff
;
trg_name_buff
+=
sizeof
(
LEX_STRING
);
memcpy
(
trg_name_buff
,
lex
.
ident
.
str
,
lex
.
ident
.
length
+
1
);
trg_name_str
->
str
=
trg_name_buff
;
trg_name_str
->
length
=
lex
.
ident
.
length
;
if
(
triggers
->
names_list
.
push_back
(
&
lex
.
sphead
->
m_name
,
&
table
->
mem_root
))
goto
err_with_lex_cleanup
;
if
(
triggers
->
names_list
.
push_back
(
trg_name_str
,
&
table
->
mem_root
))
goto
err_with_lex_cleanup
;
if
(
names_only
)
{
lex_end
(
&
lex
);
continue
;
}
/*
Let us bind Item_trigger_field objects representing access to fields
...
...
@@ -537,3 +645,160 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
DBUG_RETURN
(
1
);
}
/*
Obtains and returns trigger metadata
SYNOPSIS
get_trigger_info()
thd - current thread context
event - trigger event type
time_type - trigger action time
name - returns name of trigger
stmt - returns statement of trigger
RETURN VALUE
False - success
True - error
*/
bool
Table_triggers_list
::
get_trigger_info
(
THD
*
thd
,
trg_event_type
event
,
trg_action_time_type
time_type
,
LEX_STRING
*
trigger_name
,
LEX_STRING
*
trigger_stmt
)
{
sp_head
*
body
;
DBUG_ENTER
(
"get_trigger_info"
);
if
((
body
=
bodies
[
event
][
time_type
]))
{
*
trigger_name
=
body
->
m_name
;
*
trigger_stmt
=
body
->
m_body
;
DBUG_RETURN
(
0
);
}
DBUG_RETURN
(
1
);
}
/*
Find trigger's table from trigger identifier and add it to
the statement table list.
SYNOPSIS
mysql_table_for_trigger()
thd - current thread context
trig - identifier for trigger
RETURN VALUE
0 - error
# - pointer to TABLE_LIST object for the table
*/
static
TABLE_LIST
*
add_table_for_trigger
(
THD
*
thd
,
sp_name
*
trig
)
{
const
char
*
db
=
!
trig
->
m_db
.
str
?
thd
->
db
:
trig
->
m_db
.
str
;
LEX
*
lex
=
thd
->
lex
;
char
path_buff
[
FN_REFLEN
];
LEX_STRING
path
;
File_parser
*
parser
;
struct
st_trigname
trigname
;
DBUG_ENTER
(
"add_table_for_trigger"
);
strxnmov
(
path_buff
,
FN_REFLEN
,
mysql_data_home
,
"/"
,
db
,
"/"
,
trig
->
m_name
.
str
,
trigname_file_ext
,
NullS
);
path
.
length
=
unpack_filename
(
path_buff
,
path_buff
);
path
.
str
=
path_buff
;
if
(
access
(
path_buff
,
F_OK
))
{
my_error
(
ER_TRG_DOES_NOT_EXIST
,
MYF
(
0
));
DBUG_RETURN
(
0
);
}
if
(
!
(
parser
=
sql_parse_prepare
(
&
path
,
thd
->
mem_root
,
1
)))
DBUG_RETURN
(
0
);
if
(
strncmp
(
trigname_file_type
.
str
,
parser
->
type
()
->
str
,
parser
->
type
()
->
length
))
{
my_error
(
ER_WRONG_OBJECT
,
MYF
(
0
),
trig
->
m_name
.
str
,
trigname_file_ext
,
"TRIGGERNAME"
);
DBUG_RETURN
(
0
);
}
if
(
parser
->
parse
((
gptr
)
&
trigname
,
thd
->
mem_root
,
trigname_file_parameters
,
1
))
DBUG_RETURN
(
0
);
/* We need to reset statement table list to be PS/SP friendly. */
lex
->
query_tables
=
0
;
lex
->
query_tables_last
=
&
lex
->
query_tables
;
DBUG_RETURN
(
sp_add_to_query_tables
(
thd
,
lex
,
db
,
trigname
.
trigger_table
.
str
,
TL_WRITE
));
}
/*
Drop all triggers for table.
SYNOPSIS
drop_all_triggers()
thd - current thread context
db - schema for table
name - name for table
NOTE
The calling thread should hold the LOCK_open mutex;
RETURN VALUE
False - success
True - error
*/
bool
Table_triggers_list
::
drop_all_triggers
(
THD
*
thd
,
char
*
db
,
char
*
name
)
{
TABLE
table
;
char
path
[
FN_REFLEN
];
bool
result
=
0
;
DBUG_ENTER
(
"drop_all_triggers"
);
bzero
(
&
table
,
sizeof
(
table
));
init_alloc_root
(
&
table
.
mem_root
,
8192
,
0
);
safe_mutex_assert_owner
(
&
LOCK_open
);
if
(
Table_triggers_list
::
check_n_load
(
thd
,
db
,
name
,
&
table
,
1
))
{
result
=
1
;
goto
end
;
}
if
(
table
.
triggers
)
{
LEX_STRING
*
trigger
;
List_iterator_fast
<
LEX_STRING
>
it_name
(
table
.
triggers
->
names_list
);
while
((
trigger
=
it_name
++
))
{
if
(
rm_trigname_file
(
path
,
db
,
trigger
->
str
))
{
/*
Instead of immediately bailing out with error if we were unable
to remove .TRN file we will try to drop other files.
*/
result
=
1
;
continue
;
}
}
if
(
rm_trigger_file
(
path
,
db
,
name
))
{
result
=
1
;
goto
end
;
}
}
end:
if
(
table
.
triggers
)
delete
table
.
triggers
;
free_root
(
&
table
.
mem_root
,
MYF
(
0
));
DBUG_RETURN
(
result
);
}
sql/sql_trigger.h
View file @
edcdd6cf
...
...
@@ -23,7 +23,7 @@
class
Table_triggers_list
:
public
Sql_alloc
{
/* Triggers as SPs grouped by event, action_time */
sp_head
*
bodies
[
3
][
2
];
sp_head
*
bodies
[
TRG_EVENT_MAX
][
TRG_ACTION_MAX
];
/*
Copy of TABLE::Field array with field pointers set to TABLE::record[1]
buffer instead of TABLE::record[0] (used for OLD values in on UPDATE
...
...
@@ -121,9 +121,13 @@ class Table_triggers_list: public Sql_alloc
return
res
;
}
bool
get_trigger_info
(
THD
*
thd
,
trg_event_type
event
,
trg_action_time_type
time_type
,
LEX_STRING
*
trigger_name
,
LEX_STRING
*
trigger_stmt
);
static
bool
check_n_load
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
,
TABLE
*
table
);
TABLE
*
table
,
bool
names_only
);
static
bool
drop_all_triggers
(
THD
*
thd
,
char
*
db
,
char
*
table_name
);
bool
has_delete_triggers
()
{
...
...
@@ -143,3 +147,6 @@ class Table_triggers_list: public Sql_alloc
private:
bool
prepare_record1_accessors
(
TABLE
*
table
);
};
extern
const
LEX_STRING
trg_action_time_type_names
[];
extern
const
LEX_STRING
trg_event_type_names
[];
sql/sql_yacc.yy
View file @
edcdd6cf
...
...
@@ -599,6 +599,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token TRAILING
%token TRANSACTION_SYM
%token TRIGGER_SYM
%token TRIGGERS_SYM
%token TRIM
%token TRUE_SYM
%token TRUNCATE_SYM
...
...
@@ -1266,7 +1267,7 @@ create:
}
opt_view_list AS select_init check_option
{}
| CREATE TRIGGER_SYM
ident
trg_action_time trg_event
| CREATE TRIGGER_SYM
sp_name
trg_action_time trg_event
ON table_ident FOR_SYM EACH_SYM ROW_SYM
{
LEX *lex= Lex;
...
...
@@ -1285,6 +1286,7 @@ create:
sp->m_type= TYPE_ENUM_TRIGGER;
lex->sphead= sp;
lex->spname= $3;
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
stored procedure, otherwise yylex will chop it into pieces
...
...
@@ -1295,7 +1297,7 @@ create:
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->
tok_start
;
lex->sphead->m_body_begin= lex->
ptr
;
}
sp_proc_stmt
{
...
...
@@ -1303,14 +1305,12 @@ create:
sp_head *sp= lex->sphead;
lex->sql_command= SQLCOM_CREATE_TRIGGER;
sp->init_strings(YYTHD, lex,
NULL
);
sp->init_strings(YYTHD, lex,
$3
);
/* Restore flag if it was cleared above */
if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
sp->restore_thd_mem_root(YYTHD);
lex->ident= $3;
/*
We have to do it after parsing trigger body, because some of
sp_proc_stmt alternatives are not saving/restoring LEX, so
...
...
@@ -5919,19 +5919,11 @@ drop:
lex->sql_command= SQLCOM_DROP_VIEW;
lex->drop_if_exists= $3;
}
| DROP TRIGGER_SYM
ident '.' ident
| DROP TRIGGER_SYM
sp_name
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_TRIGGER;
/* QQ: Could we loosen lock type in certain cases ? */
if (!lex->select_lex.add_table_to_list(YYTHD,
new Table_ident($3),
(LEX_STRING*) 0,
TL_OPTION_UPDATING,
TL_WRITE))
YYABORT;
lex->ident= $5;
lex->spname= $3;
}
;
...
...
@@ -6296,6 +6288,15 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
YYABORT;
}
| opt_full TRIGGERS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS;
lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
...
...
@@ -7590,6 +7591,7 @@ keyword_sp:
| TEMPTABLE_SYM {}
| TEXT_SYM {}
| TRANSACTION_SYM {}
| TRIGGERS_SYM {}
| TIMESTAMP {}
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
...
...
sql/table.h
View file @
edcdd6cf
...
...
@@ -282,7 +282,7 @@ enum enum_schema_tables
SCH_COLLATION_CHARACTER_SET_APPLICABILITY
,
SCH_PROCEDURES
,
SCH_STATISTICS
,
SCH_VIEWS
,
SCH_USER_PRIVILEGES
,
SCH_SCHEMA_PRIVILEGES
,
SCH_TABLE_PRIVILEGES
,
SCH_COLUMN_PRIVILEGES
,
SCH_TABLE_CONSTRAINTS
,
SCH_KEY_COLUMN_USAGE
,
SCH_TABLE_NAMES
,
SCH_OPEN_TABLES
,
SCH_STATUS
,
SCH_VARIABLES
SCH_TABLE_NAMES
,
SCH_OPEN_TABLES
,
SCH_STATUS
,
SCH_
TRIGGERS
,
SCH_
VARIABLES
};
...
...
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