Skip to content

Commit a61fd53

Browse files
committed
Support opfamily members in get_object_address
In the spirit of 890192e and 4464303: have get_object_address understand individual pg_amop and pg_amproc objects. There is no way to refer to such objects directly in the grammar -- rather, they are almost always considered an integral part of the opfamily that contains them. (The only case that deals with them individually is ALTER OPERATOR FAMILY ADD/DROP, which carries the opfamily address separately and thus does not need it to be part of each added/dropped element's address.) In event triggers it becomes possible to become involved with individual amop/amproc elements, and this commit enables pg_get_object_address to do so as well. To make the overall coding simpler, this commit also slightly changes the get_object_address representation for opclasses and opfamilies: instead of having the AM name in the objargs array, I moved it as the first element of the objnames array. This enables the new code to use objargs for the type names used by pg_amop and pg_amproc. Reviewed by: Stephen Frost
1 parent 8d1f239 commit a61fd53

File tree

7 files changed

+264
-117
lines changed

7 files changed

+264
-117
lines changed

src/backend/catalog/objectaddress.c

Lines changed: 185 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,9 @@ ObjectTypeMap[] =
492492
/* OCLASS_OPFAMILY */
493493
{ "operator family", OBJECT_OPFAMILY },
494494
/* OCLASS_AMOP */
495-
{ "operator of access method", -1 }, /* unmapped */
495+
{ "operator of access method", OBJECT_AMOP },
496496
/* OCLASS_AMPROC */
497-
{ "function of access method", -1 }, /* unmapped */
497+
{ "function of access method", OBJECT_AMPROC },
498498
/* OCLASS_REWRITE */
499499
{ "rule", OBJECT_RULE },
500500
/* OCLASS_TRIGGER */
@@ -552,9 +552,12 @@ static ObjectAddress get_object_address_attrdef(ObjectType objtype,
552552
List *objname, Relation *relp, LOCKMODE lockmode,
553553
bool missing_ok);
554554
static ObjectAddress get_object_address_type(ObjectType objtype,
555-
List *objname, bool missing_ok);
555+
ListCell *typecell, bool missing_ok);
556556
static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
557-
List *objargs, bool missing_ok);
557+
bool missing_ok);
558+
static ObjectAddress get_object_address_opf_member(ObjectType objtype,
559+
List *objname, List *objargs, bool missing_ok);
560+
558561
static ObjectAddress get_object_address_usermapping(List *objname,
559562
List *objargs, bool missing_ok);
560563
static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
@@ -567,8 +570,7 @@ static void getRelationTypeDescription(StringInfo buffer, Oid relid,
567570
int32 objectSubId);
568571
static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
569572
static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
570-
static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname,
571-
List **objargs);
573+
static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname);
572574
static void getRelationIdentity(StringInfo buffer, Oid relid, List **objname);
573575

574576
/*
@@ -661,7 +663,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
661663
ObjectAddress domaddr;
662664
char *constrname;
663665

664-
domaddr = get_object_address_type(OBJECT_DOMAIN, objname, missing_ok);
666+
domaddr = get_object_address_type(OBJECT_DOMAIN,
667+
list_head(objname), missing_ok);
665668
constrname = strVal(linitial(objargs));
666669

667670
address.classId = ConstraintRelationId;
@@ -685,7 +688,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
685688
break;
686689
case OBJECT_TYPE:
687690
case OBJECT_DOMAIN:
688-
address = get_object_address_type(objtype, objname, missing_ok);
691+
address = get_object_address_type(objtype, list_head(objname), missing_ok);
689692
break;
690693
case OBJECT_AGGREGATE:
691694
address.classId = ProcedureRelationId;
@@ -721,8 +724,12 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
721724
break;
722725
case OBJECT_OPCLASS:
723726
case OBJECT_OPFAMILY:
724-
address = get_object_address_opcf(objtype,
725-
objname, objargs, missing_ok);
727+
address = get_object_address_opcf(objtype, objname, missing_ok);
728+
break;
729+
case OBJECT_AMOP:
730+
case OBJECT_AMPROC:
731+
address = get_object_address_opf_member(objtype, objname,
732+
objargs, missing_ok);
726733
break;
727734
case OBJECT_LARGEOBJECT:
728735
Assert(list_length(objname) == 1);
@@ -1309,13 +1316,13 @@ get_object_address_attrdef(ObjectType objtype, List *objname,
13091316
* Find the ObjectAddress for a type or domain
13101317
*/
13111318
static ObjectAddress
1312-
get_object_address_type(ObjectType objtype, List *objname, bool missing_ok)
1319+
get_object_address_type(ObjectType objtype, ListCell *typecell, bool missing_ok)
13131320
{
13141321
ObjectAddress address;
13151322
TypeName *typename;
13161323
Type tup;
13171324

1318-
typename = (TypeName *) linitial(objname);
1325+
typename = (TypeName *) lfirst(typecell);
13191326

13201327
address.classId = TypeRelationId;
13211328
address.objectId = InvalidOid;
@@ -1351,15 +1358,14 @@ get_object_address_type(ObjectType objtype, List *objname, bool missing_ok)
13511358
* Find the ObjectAddress for an opclass or opfamily.
13521359
*/
13531360
static ObjectAddress
1354-
get_object_address_opcf(ObjectType objtype,
1355-
List *objname, List *objargs, bool missing_ok)
1361+
get_object_address_opcf(ObjectType objtype, List *objname, bool missing_ok)
13561362
{
13571363
Oid amoid;
13581364
ObjectAddress address;
13591365

1360-
Assert(list_length(objargs) == 1);
13611366
/* XXX no missing_ok support here */
1362-
amoid = get_am_oid(strVal(linitial(objargs)), false);
1367+
amoid = get_am_oid(strVal(linitial(objname)), false);
1368+
objname = list_copy_tail(objname, 1);
13631369

13641370
switch (objtype)
13651371
{
@@ -1384,6 +1390,114 @@ get_object_address_opcf(ObjectType objtype,
13841390
return address;
13851391
}
13861392

1393+
/*
1394+
* Find the ObjectAddress for an opclass/opfamily member.
1395+
*
1396+
* (The returned address corresponds to a pg_amop/pg_amproc object).
1397+
*/
1398+
static ObjectAddress
1399+
get_object_address_opf_member(ObjectType objtype,
1400+
List *objname, List *objargs, bool missing_ok)
1401+
{
1402+
ObjectAddress famaddr;
1403+
ObjectAddress address;
1404+
ListCell *cell;
1405+
List *copy;
1406+
char *typenames[2];
1407+
Oid typeoids[2];
1408+
int membernum;
1409+
int i;
1410+
1411+
/*
1412+
* The last element of the objname list contains the strategy or procedure
1413+
* number. We need to strip that out before getting the opclass/family
1414+
* address. The rest can be used directly by get_object_address_opcf().
1415+
*/
1416+
membernum = atoi(strVal(llast(objname)));
1417+
copy = list_truncate(list_copy(objname), list_length(objname) - 1);
1418+
1419+
/* no missing_ok support here */
1420+
famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
1421+
1422+
/* find out left/right type names and OIDs */
1423+
i = 0;
1424+
foreach (cell, objargs)
1425+
{
1426+
ObjectAddress typaddr;
1427+
1428+
typenames[i] = strVal(lfirst(cell));
1429+
typaddr = get_object_address_type(OBJECT_TYPE, cell, missing_ok);
1430+
typeoids[i] = typaddr.objectId;
1431+
if (i++ >= 2)
1432+
break;
1433+
}
1434+
1435+
switch (objtype)
1436+
{
1437+
case OBJECT_AMOP:
1438+
{
1439+
HeapTuple tp;
1440+
1441+
ObjectAddressSet(address, AccessMethodOperatorRelationId,
1442+
InvalidOid);
1443+
1444+
tp = SearchSysCache4(AMOPSTRATEGY,
1445+
ObjectIdGetDatum(famaddr.objectId),
1446+
ObjectIdGetDatum(typeoids[0]),
1447+
ObjectIdGetDatum(typeoids[1]),
1448+
Int16GetDatum(membernum));
1449+
if (!HeapTupleIsValid(tp))
1450+
{
1451+
if (!missing_ok)
1452+
ereport(ERROR,
1453+
(errcode(ERRCODE_UNDEFINED_OBJECT),
1454+
errmsg("operator %d (%s, %s) of %s does not exist",
1455+
membernum, typenames[0], typenames[1],
1456+
getObjectDescription(&famaddr))));
1457+
}
1458+
else
1459+
{
1460+
address.objectId = HeapTupleGetOid(tp);
1461+
ReleaseSysCache(tp);
1462+
}
1463+
}
1464+
break;
1465+
1466+
case OBJECT_AMPROC:
1467+
{
1468+
HeapTuple tp;
1469+
1470+
ObjectAddressSet(address, AccessMethodProcedureRelationId,
1471+
InvalidOid);
1472+
1473+
tp = SearchSysCache4(AMPROCNUM,
1474+
ObjectIdGetDatum(famaddr.objectId),
1475+
ObjectIdGetDatum(typeoids[0]),
1476+
ObjectIdGetDatum(typeoids[1]),
1477+
Int16GetDatum(membernum));
1478+
if (!HeapTupleIsValid(tp))
1479+
{
1480+
if (!missing_ok)
1481+
ereport(ERROR,
1482+
(errcode(ERRCODE_UNDEFINED_OBJECT),
1483+
errmsg("function %d (%s, %s) of %s does not exist",
1484+
membernum, typenames[0], typenames[1],
1485+
getObjectDescription(&famaddr))));
1486+
}
1487+
else
1488+
{
1489+
address.objectId = HeapTupleGetOid(tp);
1490+
ReleaseSysCache(tp);
1491+
}
1492+
}
1493+
break;
1494+
default:
1495+
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
1496+
}
1497+
1498+
return address;
1499+
}
1500+
13871501
/*
13881502
* Find the ObjectAddress for a user mapping.
13891503
*/
@@ -1673,7 +1787,9 @@ pg_get_object_address(PG_FUNCTION_ARGS)
16731787
if (type == OBJECT_AGGREGATE ||
16741788
type == OBJECT_FUNCTION ||
16751789
type == OBJECT_OPERATOR ||
1676-
type == OBJECT_CAST)
1790+
type == OBJECT_CAST ||
1791+
type == OBJECT_AMOP ||
1792+
type == OBJECT_AMPROC)
16771793
{
16781794
/* in these cases, the args list must be of TypeName */
16791795
Datum *elems;
@@ -1708,8 +1824,6 @@ pg_get_object_address(PG_FUNCTION_ARGS)
17081824
switch (type)
17091825
{
17101826
case OBJECT_DOMCONSTRAINT:
1711-
case OBJECT_OPCLASS:
1712-
case OBJECT_OPFAMILY:
17131827
case OBJECT_CAST:
17141828
case OBJECT_USER_MAPPING:
17151829
case OBJECT_DEFACL:
@@ -1718,6 +1832,20 @@ pg_get_object_address(PG_FUNCTION_ARGS)
17181832
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
17191833
errmsg("argument list length must be exactly %d", 1)));
17201834
break;
1835+
case OBJECT_OPFAMILY:
1836+
case OBJECT_OPCLASS:
1837+
if (list_length(name) < 2)
1838+
ereport(ERROR,
1839+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1840+
errmsg("name list length must be at least %d", 2)));
1841+
break;
1842+
case OBJECT_AMOP:
1843+
case OBJECT_AMPROC:
1844+
if (list_length(name) < 3)
1845+
ereport(ERROR,
1846+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1847+
errmsg("name list length must be at least %d", 3)));
1848+
/* fall through to check args length */
17211849
case OBJECT_OPERATOR:
17221850
if (list_length(args) != 2)
17231851
ereport(ERROR,
@@ -3730,24 +3858,22 @@ getObjectIdentityParts(const ObjectAddress *object,
37303858
opcForm->opcmethod);
37313859
amForm = (Form_pg_am) GETSTRUCT(amTup);
37323860

3733-
appendStringInfoString(&buffer,
3734-
quote_qualified_identifier(schema,
3735-
NameStr(opcForm->opcname)));
3736-
appendStringInfo(&buffer, " USING %s",
3861+
appendStringInfo(&buffer, "%s USING %s",
3862+
quote_qualified_identifier(schema,
3863+
NameStr(opcForm->opcname)),
37373864
quote_identifier(NameStr(amForm->amname)));
37383865
if (objname)
3739-
{
3740-
*objname = list_make2(pstrdup(schema),
3866+
*objname = list_make3(pstrdup(NameStr(amForm->amname)),
3867+
schema,
37413868
pstrdup(NameStr(opcForm->opcname)));
3742-
*objargs = list_make1(pstrdup(NameStr(amForm->amname)));
3743-
}
3869+
37443870
ReleaseSysCache(amTup);
37453871
ReleaseSysCache(opcTup);
37463872
break;
37473873
}
37483874

37493875
case OCLASS_OPFAMILY:
3750-
getOpFamilyIdentity(&buffer, object->objectId, objname, objargs);
3876+
getOpFamilyIdentity(&buffer, object->objectId, objname);
37513877
break;
37523878

37533879
case OCLASS_AMOP:
@@ -3758,10 +3884,8 @@ getObjectIdentityParts(const ObjectAddress *object,
37583884
SysScanDesc amscan;
37593885
Form_pg_amop amopForm;
37603886
StringInfoData opfam;
3761-
3762-
/* no objname support here */
3763-
if (objname)
3764-
*objname = NIL;
3887+
char *ltype;
3888+
char *rtype;
37653889

37663890
amopDesc = heap_open(AccessMethodOperatorRelationId,
37673891
AccessShareLock);
@@ -3783,13 +3907,21 @@ getObjectIdentityParts(const ObjectAddress *object,
37833907
amopForm = (Form_pg_amop) GETSTRUCT(tup);
37843908

37853909
initStringInfo(&opfam);
3786-
getOpFamilyIdentity(&opfam, amopForm->amopfamily, NULL, NULL);
3910+
getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname);
3911+
3912+
ltype = format_type_be_qualified(amopForm->amoplefttype);
3913+
rtype = format_type_be_qualified(amopForm->amoprighttype);
3914+
3915+
if (objname)
3916+
{
3917+
*objname = lappend(*objname,
3918+
psprintf("%d", amopForm->amopstrategy));
3919+
*objargs = list_make2(ltype, rtype);
3920+
}
37873921

37883922
appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
37893923
amopForm->amopstrategy,
3790-
format_type_be_qualified(amopForm->amoplefttype),
3791-
format_type_be_qualified(amopForm->amoprighttype),
3792-
opfam.data);
3924+
ltype, rtype, opfam.data);
37933925

37943926
pfree(opfam.data);
37953927

@@ -3806,10 +3938,8 @@ getObjectIdentityParts(const ObjectAddress *object,
38063938
HeapTuple tup;
38073939
Form_pg_amproc amprocForm;
38083940
StringInfoData opfam;
3809-
3810-
/* no objname support here */
3811-
if (objname)
3812-
*objname = NIL;
3941+
char *ltype;
3942+
char *rtype;
38133943

38143944
amprocDesc = heap_open(AccessMethodProcedureRelationId,
38153945
AccessShareLock);
@@ -3831,13 +3961,21 @@ getObjectIdentityParts(const ObjectAddress *object,
38313961
amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
38323962

38333963
initStringInfo(&opfam);
3834-
getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, NULL, NULL);
3964+
getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname);
3965+
3966+
ltype = format_type_be_qualified(amprocForm->amproclefttype);
3967+
rtype = format_type_be_qualified(amprocForm->amprocrighttype);
3968+
3969+
if (objname)
3970+
{
3971+
*objname = lappend(*objname,
3972+
psprintf("%d", amprocForm->amprocnum));
3973+
*objargs = list_make2(ltype, rtype);
3974+
}
38353975

38363976
appendStringInfo(&buffer, "function %d (%s, %s) of %s",
38373977
amprocForm->amprocnum,
3838-
format_type_be_qualified(amprocForm->amproclefttype),
3839-
format_type_be_qualified(amprocForm->amprocrighttype),
3840-
opfam.data);
3978+
ltype, rtype, opfam.data);
38413979

38423980
pfree(opfam.data);
38433981

@@ -4263,7 +4401,7 @@ getObjectIdentityParts(const ObjectAddress *object,
42634401
}
42644402

42654403
static void
4266-
getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname, List **objargs)
4404+
getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname)
42674405
{
42684406
HeapTuple opfTup;
42694407
Form_pg_opfamily opfForm;
@@ -4289,11 +4427,9 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname, List **objargs
42894427
NameStr(amForm->amname));
42904428

42914429
if (objname)
4292-
{
4293-
*objname = list_make2(pstrdup(schema),
4430+
*objname = list_make3(pstrdup(NameStr(amForm->amname)),
4431+
pstrdup(schema),
42944432
pstrdup(NameStr(opfForm->opfname)));
4295-
*objargs = list_make1(pstrdup(NameStr(amForm->amname)));
4296-
}
42974433

42984434
ReleaseSysCache(amTup);
42994435
ReleaseSysCache(opfTup);

0 commit comments

Comments
 (0)