Skip to content

Commit

Permalink
BABEL: Support duplicate trigger name in different databases (yugabyt…
Browse files Browse the repository at this point in the history
…e#50)

Previously, duplicate trigger name was not allowed in different databases.
But in tsql, different databases can have the same trigger name. Here, we
check if a trigger with the same name is in current database. If not, then the
trigger can be created. And during drop trigger, we modify the pre check
trigger in parsing stage to not throw error, and find the correct trigger to
drop with trigger and database name.

Task:BABEL-3117
Signed-off-by: Zhenye Li <zhenye@amazon.com>
(cherry picked from commit ab122807cfde7a4b33f2ea4fa0017075efbd9487)
  • Loading branch information
ZhenyeLee authored and abhinab-yb committed Nov 14, 2024
1 parent f8ca83c commit e3f9692
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 91 deletions.
93 changes: 6 additions & 87 deletions src/postgres/src/backend/catalog/objectaddress.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,8 @@ static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object,
bool missing_ok);
static void getRelationIdentity(StringInfo buffer, Oid relid, List **object,
bool missing_ok);


get_trigger_object_address_hook_type get_trigger_object_address_hook = NULL;
/*
* Translate an object name and arguments (as passed by the parser) to an
* ObjectAddress.
Expand Down Expand Up @@ -1034,9 +1035,10 @@ get_object_address(ObjectType objtype, Node *object,
&relation, missing_ok);
break;
case OBJECT_TRIGGER:
if(sql_dialect == SQL_DIALECT_TSQL)
address = get_object_address_trigger_tsql(castNode(List, object),
&relation, missing_ok);
if(get_trigger_object_address_hook){
address = (*get_trigger_object_address_hook)(castNode(List, object),
&relation, missing_ok,false);
}
else
address = get_object_address_relobject(objtype, castNode(List, object),
&relation, missing_ok);
Expand Down Expand Up @@ -1573,89 +1575,6 @@ get_object_address_relobject(ObjectType objtype, List *object,
*relp = relation;
return address;
}

/*
* A special case of the get_object_address_relobject() function, specifically
* for the case of triggers in tsql dialect. We add a pg_trigger lookup to search
* for the relation that the trigger is associated with, since the relation name
* is not supplied by the user, and thus not a part of the *object list.
* TODO: we can use a new hook and use this function for triggers or expand it
* for all objects in tsql dialect case.
*/
ObjectAddress
get_object_address_trigger_tsql(List *object, Relation *relp,
bool missing_ok)
{
ObjectAddress address;
Relation relation = NULL;
const char *depname;
Oid reloid;
Relation tgrel;
ScanKeyData key;
SysScanDesc tgscan;
HeapTuple tuple;

/* Extract name of dependent object. */
depname = strVal(llast(object));

/*
* Get the table name of the trigger from pg_trigger. We know that
* trigger names are forced to be unique in the tsql dialect, so we
* can rely on searching for trigger name to find the corresponding
* relation name.
*/
tgrel = table_open(TriggerRelationId, AccessShareLock);

ScanKeyInit(&key,
Anum_pg_trigger_tgname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(depname));

tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, false,
NULL, 1, &key);

while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
{
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);

if (namestrcmp(&(pg_trigger->tgname), depname) == 0)
{
reloid = OidIsValid(pg_trigger->tgrelid) ? pg_trigger->tgrelid :
InvalidOid;
relation = RelationIdGetRelation(reloid);
RelationClose(relation);
}
}
systable_endscan(tgscan);

table_close(tgrel, AccessShareLock);
address.classId = TriggerRelationId;
address.objectId = relation ?
get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
if (!relation && !missing_ok)
{
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("trigger \"%s\" does not exist",
depname)));
}
address.objectSubId = 0;

/* Avoid relcache leak when object not found. */
if (!OidIsValid(address.objectId))
{
if (relation != NULL)
table_close(relation, AccessShareLock);

relation = NULL; /* department of accident prevention */
return address;
}

/* Done. */
*relp = relation;
return address;
}

/*
* Find the ObjectAddress for an attribute.
*/
Expand Down
9 changes: 7 additions & 2 deletions src/postgres/src/backend/commands/trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
bool existing_isInternal = false;
bool existing_isClone = false;
bool is_composite_trigger = false;
char *pg_trigger_schema_name;
char *newtrigger_schema_name;

is_composite_trigger = IsCompositeTrigger(funcoid, stmt->funcname);

Expand Down Expand Up @@ -943,8 +945,11 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
while (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
{
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);

if (namestrcmp(&(pg_trigger->tgname), trigname) == 0)
pg_trigger_schema_name = get_namespace_name(get_rel_namespace(pg_trigger->tgrelid));
newtrigger_schema_name = get_namespace_name(get_rel_namespace(RelationGetRelid(rel)));

if (namestrcmp(&(pg_trigger->tgname), trigname) == 0
&& strcasecmp(newtrigger_schema_name, pg_trigger_schema_name) == 0)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("trigger \"%s\" already exists in the database",
Expand Down
4 changes: 2 additions & 2 deletions src/postgres/src/include/catalog/objectaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ extern struct ArrayType *strlist_to_textarray(List *list);

extern ObjectType get_relkind_objtype(char relkind);

extern ObjectAddress get_object_address_trigger_tsql(List *object,
Relation *relp, bool missing_ok);
typedef ObjectAddress (*get_trigger_object_address_hook_type)(List *object, Relation *relp, bool missing_ok,bool object_from_input);
extern PGDLLIMPORT get_trigger_object_address_hook_type get_trigger_object_address_hook;

#endif /* OBJECTADDRESS_H */

0 comments on commit e3f9692

Please sign in to comment.