drop trigger syntax

This commit is contained in:
nnuanyang
2022-12-01 18:30:57 -08:00
parent 84fbe6cc91
commit 69668e89d5
15 changed files with 214 additions and 24 deletions

View File

@ -15,6 +15,8 @@
<refsynopsisdiv>
<synopsis>
DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
In B compatibility also support:
DROP TRIGGER [ IF EXISTS ] name [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
</refentry>

View File

@ -700,12 +700,19 @@ static ObjectAddress get_object_address_relobject(ObjectType objtype, List* objn
* work. But objects other than rules don't get this special
* treatment.
*/
if (objtype != OBJECT_RULE)
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NODE_STATE), errmsg("must specify relation and object name")));
address.classId = RewriteRelationId;
address.objectId = get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
address.objectSubId = 0;
/*mysql drop trigger syntax*/
if (objtype == OBJECT_TRIGGER && u_sess->attr.attr_sql.sql_compatibility == B_FORMAT)
{
address.classId = TriggerRelationId;
address.objectId = get_trigger_oid_b(depname, &reloid, missing_ok);
address.objectSubId = 0;
} else {
if (objtype != OBJECT_RULE)
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NODE_STATE), errmsg("must specify relation and object name")));
address.classId = RewriteRelationId;
address.objectId = get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
address.objectSubId = 0;
}
/*
* Caller is expecting to get back the relation, even though we didn't
* end up using it to find the rule.

View File

@ -11197,6 +11197,52 @@ DropTrigStmt:
n->concurrent = false;
$$ = (Node *) n;
}
| DROP TRIGGER name opt_drop_behavior
{
#ifdef ENABLE_MULTIPLE_NODES
const char* message = "drop trigger name is not yet supported in distributed database.";
InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc);
ereport(errstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("drop trigger name is not yet supported in distributed database.")));
#endif
if (u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) {
ereport(errstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("drop trigger without table name only support in B-format database")));
}
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_TRIGGER;
n->objects = list_make1(list_make1(makeString($3)));
n->arguments = NIL;
n->behavior = $4;
n->missing_ok = false;
n->concurrent = false;
$$ = (Node *) n;
}
| DROP TRIGGER IF_P EXISTS name opt_drop_behavior
{
#ifdef ENABLE_MULTIPLE_NODES
const char* message = "drop trigger if exists name is not yet supported in distributed database.";
InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc);
ereport(errstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("drop trigger if exists name is not yet supported in distributed database.")));
#endif
if (u_sess->attr.attr_sql.sql_compatibility != B_FORMAT) {
ereport(errstate,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("drop trigger without table name only support in B-format database")));
}
DropStmt *n = makeNode(DropStmt);
n->removeType = OBJECT_TRIGGER;
n->objects = list_make1(list_make1(makeString($5)));
n->arguments = NIL;
n->behavior = $6;
n->missing_ok = true;
n->concurrent = false;
$$ = (Node *) n;
}
;

View File

@ -59,7 +59,7 @@ bool open_join_children = true;
bool will_shutdown = false;
/* hard-wired binary version number */
const uint32 GRAND_VERSION_NUM = 92836;
const uint32 GRAND_VERSION_NUM = 92837;
const uint32 SELECT_INTO_VAR_VERSION_NUM = 92834;
const uint32 DOLPHIN_ENABLE_DROP_NUM = 92830;

View File

@ -376,10 +376,16 @@ static void does_not_exist_skipping(ObjectType objtype, List* objname, List* obj
args = format_type_be(typenameTypeId(NULL, (TypeName*)linitial(objargs)));
break;
case OBJECT_TRIGGER:
msg = gettext_noop("trigger \"%s\" for table \"%s\" does not exist");
name = NameListToString(objname);
args = NameListToString(list_truncate(list_copy(objname), list_length(objname) - 1));
break;
if (list_length(objname) == 1) {
msg = gettext_noop("trigger \"%s\" does not exist");
name = NameListToString(objname);
break;
} else {
msg = gettext_noop("trigger \"%s\" for table \"%s\" does not exist");
name = NameListToString(objname);
args = NameListToString(list_truncate(list_copy(objname), list_length(objname) - 1));
break;
}
case OBJECT_RULE:
msg = gettext_noop("rule \"%s\" for relation \"%s\" does not exist");
name = strVal(llast(objname));

View File

@ -467,23 +467,38 @@ Oid CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid relOid, Oid
* relation, so the trigger set won't be changing underneath us.
*/
if (!isInternal) {
ScanKeyInit(
&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel)));
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, NULL, 1, &key);
while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) {
Form_pg_trigger pg_trigger = (Form_pg_trigger)GETSTRUCT(tuple);
if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) {
if (stmt->funcSource != NULL && u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) {
ScanKeyInit(
&key, Anum_pg_trigger_tgname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(trigname));
tgscan = systable_beginscan(tgrel, TriggerNameIndexId, true, NULL, 1, &key);
if (HeapTupleIsValid(tuple = systable_getnext(tgscan))) {
if (stmt->if_not_exists) {
ereport(NOTICE,
(errmsg("trigger \"%s\" for relation \"%s\" already exists,skipping",
trigname,
RelationGetRelationName(rel))));
(errmsg("trigger \"%s\" already exists, skipping",
trigname)));
systable_endscan(tgscan);
heap_close(tgrel, RowExclusiveLock);
heap_close(rel, NoLock);
return trigoid;
}
else {
systable_endscan(tgscan);
heap_close(tgrel, RowExclusiveLock);
heap_close(rel, NoLock);
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("trigger \"%s\" already exists",
trigname)));
}
}
systable_endscan(tgscan);
} else {
ScanKeyInit(
&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel)));
tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true, NULL, 1, &key);
while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) {
Form_pg_trigger pg_trigger = (Form_pg_trigger)GETSTRUCT(tuple);
if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) {
systable_endscan(tgscan);
heap_close(tgrel, RowExclusiveLock);
heap_close(rel, NoLock);
@ -494,11 +509,10 @@ Oid CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid relOid, Oid
RelationGetRelationName(rel))));
}
}
systable_endscan(tgscan);
}
systable_endscan(tgscan);
}
if (stmt->funcSource != NULL && u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) {
CreateFunctionStmt* n = makeNode(CreateFunctionStmt);
n->isOraStyle = false;
@ -1302,6 +1316,53 @@ Oid get_trigger_oid(Oid relid, const char* trigname, bool missing_ok)
return oid;
}
Oid get_trigger_oid_b(const char* trigname, Oid* reloid, bool missing_ok)
{
Relation tgrel;
ScanKeyData skey;
SysScanDesc tgscan;
HeapTuple tup;
Oid oid;
int count = 0;
/*
* Find the trigger, verify permissions, set up object address
*/
tgrel = heap_open(TriggerRelationId, AccessShareLock);
ScanKeyInit(&skey, Anum_pg_trigger_tgname, BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(trigname));
tgscan = systable_beginscan(tgrel, TriggerNameIndexId, true, NULL, 1, &skey);
while (HeapTupleIsValid(tup = systable_getnext(tgscan))) {
count ++;
if (count == 1) {
Form_pg_trigger pg_trigger = (Form_pg_trigger)GETSTRUCT(tup);
*reloid = pg_trigger->tgrelid;
oid = HeapTupleGetOid(tup);
} else if (count > 1) {
systable_endscan(tgscan);
heap_close(tgrel, AccessShareLock);
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("trigger named \"%s\" has more than one trigger, please use drop trigger on syntax", trigname)));
}
}
if (count == 0) {
if (!missing_ok) {
systable_endscan(tgscan);
heap_close(tgrel, AccessShareLock);
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("trigger \"%s\" does not exist", trigname)));
}
oid = InvalidOid;
}
systable_endscan(tgscan);
heap_close(tgrel, AccessShareLock);
return oid;
}
/*
* Perform permissions and integrity checks before acquiring a relation lock.
*/

View File

@ -270,6 +270,8 @@ DECLARE_UNIQUE_INDEX(pg_tablespace_spcname_index, 2698, on pg_tablespace using b
/* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_trigger_tgconstraint_index, 2699, on pg_trigger using btree(tgconstraint oid_ops));
#define TriggerConstraintIndexId 2699
DECLARE_INDEX(pg_trigger_tgname_index, 2700, on pg_trigger using btree(tgname name_ops));
#define TriggerNameIndexId 2700
DECLARE_UNIQUE_INDEX(pg_trigger_tgrelid_tgname_index, 2701, on pg_trigger using btree(tgrelid oid_ops, tgname name_ops));
#define TriggerRelidNameIndexId 2701
DECLARE_UNIQUE_INDEX(pg_trigger_oid_index, 2702, on pg_trigger using btree(oid oid_ops));

View File

@ -0,0 +1 @@
DROP INDEX IF EXISTS pg_catalog.pg_trigger_tgname_index;

View File

@ -0,0 +1 @@
DROP INDEX IF EXISTS pg_catalog.pg_trigger_tgname_index;

View File

@ -0,0 +1,3 @@
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 2700;
CREATE INDEX pg_catalog.pg_trigger_tgname_index ON pg_catalog.pg_trigger USING BTREE(tgname name_ops);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0;

View File

@ -0,0 +1,3 @@
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 2700;
CREATE INDEX pg_catalog.pg_trigger_tgname_index ON pg_catalog.pg_trigger USING BTREE(tgname name_ops);
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0;

View File

@ -104,6 +104,7 @@ extern Oid CreateTrigger(CreateTrigStmt* stmt, const char* queryString, Oid relO
extern void RemoveTriggerById(Oid trigOid);
extern Oid get_trigger_oid(Oid relid, const char* name, bool missing_ok);
extern Oid get_trigger_oid_b(const char* name, Oid* reloid, bool missing_ok);
extern void renametrig(RenameStmt* stmt);

View File

@ -152,7 +152,7 @@ begin
insert into food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now());
end;
/
ERROR: trigger "animal_trigger1" for relation "animals" already exists
ERROR: trigger "animal_trigger1" already exists
create trigger if not exists animal_trigger1
after insert on animals
for each row
@ -160,7 +160,31 @@ begin
insert into food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now());
end;
/
NOTICE: trigger "animal_trigger1" for relation "animals" already exists,skipping
NOTICE: trigger "animal_trigger1" already exists, skipping
CREATE OR REPLACE FUNCTION tri_insert_func() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now());
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
create trigger trigger_rename_test
after insert on animals
for each row
EXECUTE PROCEDURE tri_insert_func();
create trigger trigger_rename_test
after insert on food
for each row
EXECUTE PROCEDURE tri_insert_func();
drop trigger trigger_rename_test;
ERROR: trigger named "trigger_rename_test" has more than one trigger, please use drop trigger on syntax
-- drop trigger test
drop trigger animal_trigger1;
drop trigger animal_trigger1;
ERROR: trigger "animal_trigger1" does not exist
drop trigger if exists animal_trigger1;
NOTICE: trigger "animal_trigger1" does not exist, skipping
drop table food;
drop table animals;
DROP TABLE t_trigger cascade;
@ -331,6 +355,10 @@ END;
ERROR: bad SQLSTATE '00000'
CONTEXT: compilation of PL/pgSQL function "test_condition_6" near line 3
\c regression
drop trigger animal_trigger1;
ERROR: drop trigger without table name only support in B-format database
drop trigger if exists animal_trigger1;
ERROR: drop trigger without table name only support in B-format database
drop database db_mysql;
-- test declare condition in other compatibility
create or replace procedure test_condition_1 as

View File

@ -642,6 +642,8 @@ Command: DROP TRIGGER
Description: remove a trigger
Syntax:
DROP TRIGGER [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
In B compatibility also support:
DROP TRIGGER [ IF EXISTS ] name [ CASCADE | RESTRICT ]
\h alter table
Command: ALTER TABLE

View File

@ -139,6 +139,31 @@ begin
insert into food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now());
end;
/
CREATE OR REPLACE FUNCTION tri_insert_func() RETURNS TRIGGER AS
$$
DECLARE
BEGIN
INSERT INTO food(id, foodtype, remark, time_flag) values (1,'ice cream', 'sdsdsdsd', now());
RETURN NEW;
END
$$ LANGUAGE PLPGSQL;
create trigger trigger_rename_test
after insert on animals
for each row
EXECUTE PROCEDURE tri_insert_func();
create trigger trigger_rename_test
after insert on food
for each row
EXECUTE PROCEDURE tri_insert_func();
drop trigger trigger_rename_test;
-- drop trigger test
drop trigger animal_trigger1;
drop trigger animal_trigger1;
drop trigger if exists animal_trigger1;
drop table food;
drop table animals;
@ -263,6 +288,8 @@ END;
/
\c regression
drop trigger animal_trigger1;
drop trigger if exists animal_trigger1;
drop database db_mysql;
-- test declare condition in other compatibility