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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy