diff --git a/doc/src/sgml/ref/create_trigger.sgmlin b/doc/src/sgml/ref/create_trigger.sgmlin index b5e88d2c7..5e807d2e8 100644 --- a/doc/src/sgml/ref/create_trigger.sgmlin +++ b/doc/src/sgml/ref/create_trigger.sgmlin @@ -22,12 +22,25 @@ CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments ) +In B compatibility also support: +CREATE [ DEFINER = user ] TRIGGER [ IF NOT EXISTS ] name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] } + ON table_name + [ FROM referenced_table_name ] + { NOT DEFERRABLE | [ DEFERRABLE ] { INITIALLY IMMEDIATE | INITIALLY DEFERRED } } + [ FOR [ EACH ] { ROW | STATEMENT } ] + [ WHEN ( condition ) ] + [ trigger_order ] + trigger_body + where event can be one of: INSERT UPDATE [ OF column_name [, ... ] ] DELETE TRUNCATE + +where trigger_order can be [ FOLLOWS | PRECEDES ] + diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 4c341ef42..1c1174282 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -10724,9 +10724,9 @@ CreateTrigStmt: { parser_yyerror("syntax error found"); } - if (u_sess->attr.attr_sql.sql_compatibility != B_FORMAT && $3 != NULL) + if ($3 != NULL) { - parser_yyerror("only support definer in mysql compatibility database"); + parser_yyerror("only support definer in B compatibility database and B syntax"); } CreateTrigStmt *n = makeNode(CreateTrigStmt); n->definer = $3; @@ -10788,7 +10788,7 @@ CreateTrigStmt: { if (u_sess->attr.attr_sql.sql_compatibility != B_FORMAT || $2 != false) { - parser_yyerror("only support definer, trigger_order, subprogram_body in mysql compatibility database"); + parser_yyerror("only support definer, trigger_order, subprogram_body in B compatibility database"); } CreateTrigStmt *n = makeNode(CreateTrigStmt); if ($2 != false) @@ -10826,7 +10826,7 @@ CreateTrigStmt: { if (u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) { - parser_yyerror("only support definer, if not exists, trigger_order, subprogram_body in mysql compatibility database"); + parser_yyerror("only support definer, if not exists, trigger_order, subprogram_body in B compatibility database"); } CreateTrigStmt *n = makeNode(CreateTrigStmt); if ($2 != false) diff --git a/src/gausskernel/optimizer/commands/trigger.cpp b/src/gausskernel/optimizer/commands/trigger.cpp index bd8e25d20..6037176b8 100644 --- a/src/gausskernel/optimizer/commands/trigger.cpp +++ b/src/gausskernel/optimizer/commands/trigger.cpp @@ -526,9 +526,9 @@ Oid CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid relOid, Oid ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("trigger function body has syntax error"))); } - ret = memcpy_s(bodySrcTemp, bodySrcTempSize, stmt->funcSource->bodySrc, last_end - 1); + ret = memcpy_s(bodySrcTemp, bodySrcTempSize, stmt->funcSource->bodySrc, last_end); securec_check_c(ret, "\0", "\0"); - bodySrcTemp[last_end - 1] = '\0'; + bodySrcTemp[last_end] = '\0'; ret = strcat_s(bodySrcTemp, bodySrcTempSize, inlineProcessDesc); securec_check_c(ret, "\0", "\0"); n->options = lappend(n->options, makeDefElem("as", (Node*)list_make1(makeString(bodySrcTemp)))); @@ -683,8 +683,14 @@ Oid CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid relOid, Oid while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) { Form_pg_trigger pg_trigger = (Form_pg_trigger)GETSTRUCT(tuple); if (namestrcmp(&(pg_trigger->tgname), needTestName) == 0) { - is_find = true; - break; + if (pg_trigger->tgtype == tgtype) { + is_find = true; + break; + } else { + ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), + errmsg("trigger \"%s\" type is not same as current trigger", + needTestName))); + } } } systable_endscan(tgscan); diff --git a/src/test/regress/expected/mysql_syntax.out b/src/test/regress/expected/mysql_syntax.out index 32279f616..2fed3d13b 100644 --- a/src/test/regress/expected/mysql_syntax.out +++ b/src/test/regress/expected/mysql_syntax.out @@ -49,6 +49,16 @@ begin insert into food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now()); end; / +--different type trigger follows|precedes +create trigger animal_trigger2 +before insert on animals +for each row +follows animal_trigger1 +begin + insert into food(id, foodtype, remark, time_flag) values (2,'chocolate', 'sdsdsdsd', now()); +end; +/ +ERROR: trigger "animal_trigger1" type is not same as current trigger create trigger animal_trigger2 after insert on animals for each row @@ -153,5 +163,30 @@ end; NOTICE: trigger "animal_trigger1" for relation "animals" already exists,skipping drop table food; drop table animals; +DROP TABLE t_trigger cascade; +ERROR: table "t_trigger" does not exist +CREATE TABLE t_trigger( +id int primary key, +name varchar(20) not null +)partition by hash(id) +(partition p1 , +partition p2, +partition p3); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t_trigger_pkey" for table "t_trigger" +INSERT INTO t_trigger values(1,'liuyi'); +INSERT INTO t_trigger values(2,'chener'); +DROP TABLE t_func_trigger; +ERROR: table "t_func_trigger" does not exist +CREATE TABLE t_func_trigger(rep text); +create user vbadmin password 'Aa@111111'; +CREATE definer=vbadmin TRIGGER trigger_insert +AFTER insert +ON t_trigger +FOR EACH ROW +BEGIN +insert into t_func_trigger(rep) values('after insert');END; +/ +drop trigger trigger_insert on t_trigger; +drop user vbadmin; \c regression drop database db_mysql; diff --git a/src/test/regress/expected/xc_triggers_1.out b/src/test/regress/expected/xc_triggers_1.out index 3119df57c..3bf4129cf 100644 --- a/src/test/regress/expected/xc_triggers_1.out +++ b/src/test/regress/expected/xc_triggers_1.out @@ -612,6 +612,16 @@ CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments ) +In B compatibility also support: +CREATE [ DEFINER = user ] TRIGGER [ IF NOT EXISTS ] name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] } + ON table_name + [ FROM referenced_table_name ] + { NOT DEFERRABLE | [ DEFERRABLE ] { INITIALLY IMMEDIATE | INITIALLY DEFERRED } } + [ FOR [ EACH ] { ROW | STATEMENT } ] + [ WHEN ( condition ) ] + [ trigger_order ] + trigger_body + where event can be one of: INSERT @@ -619,6 +629,8 @@ where event can be one of: DELETE TRUNCATE +where trigger_order can be [ FOLLOWS | PRECEDES ] + \h alter trigger Command: ALTER TRIGGER Description: change the definition of a trigger diff --git a/src/test/regress/sql/mysql_syntax.sql b/src/test/regress/sql/mysql_syntax.sql index 76f94c849..ec0dfdafb 100644 --- a/src/test/regress/sql/mysql_syntax.sql +++ b/src/test/regress/sql/mysql_syntax.sql @@ -49,6 +49,17 @@ begin end; / +--different type trigger follows|precedes + +create trigger animal_trigger2 +before insert on animals +for each row +follows animal_trigger1 +begin + insert into food(id, foodtype, remark, time_flag) values (2,'chocolate', 'sdsdsdsd', now()); +end; +/ + create trigger animal_trigger2 after insert on animals for each row @@ -130,5 +141,28 @@ end; / drop table food; drop table animals; + +DROP TABLE t_trigger cascade; +CREATE TABLE t_trigger( +id int primary key, +name varchar(20) not null +)partition by hash(id) +(partition p1 , +partition p2, +partition p3); +INSERT INTO t_trigger values(1,'liuyi'); +INSERT INTO t_trigger values(2,'chener'); +DROP TABLE t_func_trigger; +CREATE TABLE t_func_trigger(rep text); +create user vbadmin password 'Aa@111111'; +CREATE definer=vbadmin TRIGGER trigger_insert +AFTER insert +ON t_trigger +FOR EACH ROW +BEGIN +insert into t_func_trigger(rep) values('after insert');END; +/ +drop trigger trigger_insert on t_trigger; +drop user vbadmin; \c regression drop database db_mysql;