Support opfamily members in get_object_address
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 16 Mar 2015 15:06:34 +0000 (12:06 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 16 Mar 2015 15:06:34 +0000 (12:06 -0300)
In the spirit of 890192e99af and 4464303405f: 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

src/backend/catalog/objectaddress.c
src/backend/commands/dropcmds.c
src/backend/commands/event_trigger.c
src/backend/parser/gram.y
src/include/nodes/parsenodes.h
src/test/regress/expected/object_address.out
src/test/regress/sql/object_address.sql

index 142bc689e95cce0350e23e556b546df7daf0a054..46ea09a61188a3c7fe89244d68935b68492e312a 100644 (file)
@@ -492,9 +492,9 @@ ObjectTypeMap[] =
        /* OCLASS_OPFAMILY */
        { "operator family", OBJECT_OPFAMILY },
        /* OCLASS_AMOP */
-       { "operator of access method", -1 },    /* unmapped */
+       { "operator of access method", OBJECT_AMOP },
        /* OCLASS_AMPROC */
-       { "function of access method", -1 },    /* unmapped */
+       { "function of access method", OBJECT_AMPROC },
        /* OCLASS_REWRITE */
        { "rule", OBJECT_RULE },
        /* OCLASS_TRIGGER */
@@ -552,9 +552,12 @@ static ObjectAddress get_object_address_attrdef(ObjectType objtype,
                                                   List *objname, Relation *relp, LOCKMODE lockmode,
                                                   bool missing_ok);
 static ObjectAddress get_object_address_type(ObjectType objtype,
-                                               List *objname, bool missing_ok);
+                                               ListCell *typecell, bool missing_ok);
 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
-                                               List *objargs, bool missing_ok);
+                                               bool missing_ok);
+static ObjectAddress get_object_address_opf_member(ObjectType objtype,
+                                                         List *objname, List *objargs, bool missing_ok);
+
 static ObjectAddress get_object_address_usermapping(List *objname,
                                                           List *objargs, bool missing_ok);
 static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
@@ -567,8 +570,7 @@ static void getRelationTypeDescription(StringInfo buffer, Oid relid,
                                                   int32 objectSubId);
 static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
 static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
-static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname,
-                                       List **objargs);
+static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname);
 static void getRelationIdentity(StringInfo buffer, Oid relid, List **objname);
 
 /*
@@ -661,7 +663,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                                        ObjectAddress   domaddr;
                                        char               *constrname;
 
-                                       domaddr = get_object_address_type(OBJECT_DOMAIN, objname, missing_ok);
+                                       domaddr = get_object_address_type(OBJECT_DOMAIN,
+                                                                                                         list_head(objname), missing_ok);
                                        constrname = strVal(linitial(objargs));
 
                                        address.classId = ConstraintRelationId;
@@ -685,7 +688,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                                break;
                        case OBJECT_TYPE:
                        case OBJECT_DOMAIN:
-                               address = get_object_address_type(objtype, objname, missing_ok);
+                               address = get_object_address_type(objtype, list_head(objname), missing_ok);
                                break;
                        case OBJECT_AGGREGATE:
                                address.classId = ProcedureRelationId;
@@ -721,8 +724,12 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                                break;
                        case OBJECT_OPCLASS:
                        case OBJECT_OPFAMILY:
-                               address = get_object_address_opcf(objtype,
-                                                                                          objname, objargs, missing_ok);
+                               address = get_object_address_opcf(objtype, objname, missing_ok);
+                               break;
+                       case OBJECT_AMOP:
+                       case OBJECT_AMPROC:
+                               address = get_object_address_opf_member(objtype, objname,
+                                                                                                               objargs, missing_ok);
                                break;
                        case OBJECT_LARGEOBJECT:
                                Assert(list_length(objname) == 1);
@@ -1309,13 +1316,13 @@ get_object_address_attrdef(ObjectType objtype, List *objname,
  * Find the ObjectAddress for a type or domain
  */
 static ObjectAddress
-get_object_address_type(ObjectType objtype, List *objname, bool missing_ok)
+get_object_address_type(ObjectType objtype, ListCell *typecell, bool missing_ok)
 {
        ObjectAddress address;
        TypeName   *typename;
        Type            tup;
 
-       typename = (TypeName *) linitial(objname);
+       typename = (TypeName *) lfirst(typecell);
 
        address.classId = TypeRelationId;
        address.objectId = InvalidOid;
@@ -1351,15 +1358,14 @@ get_object_address_type(ObjectType objtype, List *objname, bool missing_ok)
  * Find the ObjectAddress for an opclass or opfamily.
  */
 static ObjectAddress
-get_object_address_opcf(ObjectType objtype,
-                                               List *objname, List *objargs, bool missing_ok)
+get_object_address_opcf(ObjectType objtype, List *objname, bool missing_ok)
 {
        Oid                     amoid;
        ObjectAddress address;
 
-       Assert(list_length(objargs) == 1);
        /* XXX no missing_ok support here */
-       amoid = get_am_oid(strVal(linitial(objargs)), false);
+       amoid = get_am_oid(strVal(linitial(objname)), false);
+       objname = list_copy_tail(objname, 1);
 
        switch (objtype)
        {
@@ -1384,6 +1390,114 @@ get_object_address_opcf(ObjectType objtype,
        return address;
 }
 
+/*
+ * Find the ObjectAddress for an opclass/opfamily member.
+ *
+ * (The returned address corresponds to a pg_amop/pg_amproc object).
+ */
+static ObjectAddress
+get_object_address_opf_member(ObjectType objtype,
+                                                         List *objname, List *objargs, bool missing_ok)
+{
+       ObjectAddress   famaddr;
+       ObjectAddress   address;
+       ListCell *cell;
+       List   *copy;
+       char   *typenames[2];
+       Oid             typeoids[2];
+       int             membernum;
+       int             i;
+
+       /*
+        * The last element of the objname list contains the strategy or procedure
+        * number.  We need to strip that out before getting the opclass/family
+        * address.  The rest can be used directly by get_object_address_opcf().
+        */
+       membernum = atoi(strVal(llast(objname)));
+       copy = list_truncate(list_copy(objname), list_length(objname) - 1);
+
+       /* no missing_ok support here */
+       famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
+
+       /* find out left/right type names and OIDs */
+       i = 0;
+       foreach (cell, objargs)
+       {
+               ObjectAddress   typaddr;
+
+               typenames[i] = strVal(lfirst(cell));
+               typaddr = get_object_address_type(OBJECT_TYPE, cell, missing_ok);
+               typeoids[i] = typaddr.objectId;
+               if (i++ >= 2)
+                       break;
+       }
+
+       switch (objtype)
+       {
+               case OBJECT_AMOP:
+                       {
+                               HeapTuple       tp;
+
+                               ObjectAddressSet(address, AccessMethodOperatorRelationId,
+                                                                InvalidOid);
+
+                               tp = SearchSysCache4(AMOPSTRATEGY,
+                                                                        ObjectIdGetDatum(famaddr.objectId),
+                                                                        ObjectIdGetDatum(typeoids[0]),
+                                                                        ObjectIdGetDatum(typeoids[1]),
+                                                                        Int16GetDatum(membernum));
+                               if (!HeapTupleIsValid(tp))
+                               {
+                                       if (!missing_ok)
+                                               ereport(ERROR,
+                                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                                                errmsg("operator %d (%s, %s) of %s does not exist",
+                                                                               membernum, typenames[0], typenames[1],
+                                                                               getObjectDescription(&famaddr))));
+                               }
+                               else
+                               {
+                                       address.objectId = HeapTupleGetOid(tp);
+                                       ReleaseSysCache(tp);
+                               }
+                       }
+                       break;
+
+               case OBJECT_AMPROC:
+                       {
+                               HeapTuple       tp;
+
+                               ObjectAddressSet(address, AccessMethodProcedureRelationId,
+                                                                InvalidOid);
+
+                               tp = SearchSysCache4(AMPROCNUM,
+                                                                        ObjectIdGetDatum(famaddr.objectId),
+                                                                        ObjectIdGetDatum(typeoids[0]),
+                                                                        ObjectIdGetDatum(typeoids[1]),
+                                                                        Int16GetDatum(membernum));
+                               if (!HeapTupleIsValid(tp))
+                               {
+                                       if (!missing_ok)
+                                               ereport(ERROR,
+                                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                                                errmsg("function %d (%s, %s) of %s does not exist",
+                                                                               membernum, typenames[0], typenames[1],
+                                                                               getObjectDescription(&famaddr))));
+                               }
+                               else
+                               {
+                                       address.objectId = HeapTupleGetOid(tp);
+                                       ReleaseSysCache(tp);
+                               }
+                       }
+                       break;
+               default:
+                       elog(ERROR, "unrecognized objtype: %d", (int) objtype);
+       }
+
+       return address;
+}
+
 /*
  * Find the ObjectAddress for a user mapping.
  */
@@ -1673,7 +1787,9 @@ pg_get_object_address(PG_FUNCTION_ARGS)
        if (type == OBJECT_AGGREGATE ||
                type == OBJECT_FUNCTION ||
                type == OBJECT_OPERATOR ||
-               type == OBJECT_CAST)
+               type == OBJECT_CAST ||
+               type == OBJECT_AMOP ||
+               type == OBJECT_AMPROC)
        {
                /* in these cases, the args list must be of TypeName */
                Datum  *elems;
@@ -1708,8 +1824,6 @@ pg_get_object_address(PG_FUNCTION_ARGS)
        switch (type)
        {
                case OBJECT_DOMCONSTRAINT:
-               case OBJECT_OPCLASS:
-               case OBJECT_OPFAMILY:
                case OBJECT_CAST:
                case OBJECT_USER_MAPPING:
                case OBJECT_DEFACL:
@@ -1718,6 +1832,20 @@ pg_get_object_address(PG_FUNCTION_ARGS)
                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                                 errmsg("argument list length must be exactly %d", 1)));
                        break;
+               case OBJECT_OPFAMILY:
+               case OBJECT_OPCLASS:
+                       if (list_length(name) < 2)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("name list length must be at least %d", 2)));
+                       break;
+               case OBJECT_AMOP:
+               case OBJECT_AMPROC:
+                       if (list_length(name) < 3)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("name list length must be at least %d", 3)));
+                       /* fall through to check args length */
                case OBJECT_OPERATOR:
                        if (list_length(args) != 2)
                                ereport(ERROR,
@@ -3730,24 +3858,22 @@ getObjectIdentityParts(const ObjectAddress *object,
                                                 opcForm->opcmethod);
                                amForm = (Form_pg_am) GETSTRUCT(amTup);
 
-                               appendStringInfoString(&buffer,
-                                                                          quote_qualified_identifier(schema,
-                                                                                                NameStr(opcForm->opcname)));
-                               appendStringInfo(&buffer, " USING %s",
+                               appendStringInfo(&buffer, "%s USING %s",
+                                                                quote_qualified_identifier(schema,
+                                                                                                                       NameStr(opcForm->opcname)),
                                                                 quote_identifier(NameStr(amForm->amname)));
                                if (objname)
-                               {
-                                       *objname = list_make2(pstrdup(schema),
+                                       *objname = list_make3(pstrdup(NameStr(amForm->amname)),
+                                                                                 schema,
                                                                                  pstrdup(NameStr(opcForm->opcname)));
-                                       *objargs = list_make1(pstrdup(NameStr(amForm->amname)));
-                               }
+
                                ReleaseSysCache(amTup);
                                ReleaseSysCache(opcTup);
                                break;
                        }
 
                case OCLASS_OPFAMILY:
-                       getOpFamilyIdentity(&buffer, object->objectId, objname, objargs);
+                       getOpFamilyIdentity(&buffer, object->objectId, objname);
                        break;
 
                case OCLASS_AMOP:
@@ -3758,10 +3884,8 @@ getObjectIdentityParts(const ObjectAddress *object,
                                SysScanDesc amscan;
                                Form_pg_amop amopForm;
                                StringInfoData opfam;
-
-                               /* no objname support here */
-                               if (objname)
-                                       *objname = NIL;
+                               char       *ltype;
+                               char       *rtype;
 
                                amopDesc = heap_open(AccessMethodOperatorRelationId,
                                                                         AccessShareLock);
@@ -3783,13 +3907,21 @@ getObjectIdentityParts(const ObjectAddress *object,
                                amopForm = (Form_pg_amop) GETSTRUCT(tup);
 
                                initStringInfo(&opfam);
-                               getOpFamilyIdentity(&opfam, amopForm->amopfamily, NULL, NULL);
+                               getOpFamilyIdentity(&opfam, amopForm->amopfamily, objname);
+
+                               ltype = format_type_be_qualified(amopForm->amoplefttype);
+                               rtype = format_type_be_qualified(amopForm->amoprighttype);
+
+                               if (objname)
+                               {
+                                       *objname = lappend(*objname,
+                                                                          psprintf("%d", amopForm->amopstrategy));
+                                       *objargs = list_make2(ltype, rtype);
+                               }
 
                                appendStringInfo(&buffer, "operator %d (%s, %s) of %s",
                                                                 amopForm->amopstrategy,
-                                                       format_type_be_qualified(amopForm->amoplefttype),
-                                                  format_type_be_qualified(amopForm->amoprighttype),
-                                                                opfam.data);
+                                                                ltype, rtype, opfam.data);
 
                                pfree(opfam.data);
 
@@ -3806,10 +3938,8 @@ getObjectIdentityParts(const ObjectAddress *object,
                                HeapTuple       tup;
                                Form_pg_amproc amprocForm;
                                StringInfoData opfam;
-
-                               /* no objname support here */
-                               if (objname)
-                                       *objname = NIL;
+                               char       *ltype;
+                               char       *rtype;
 
                                amprocDesc = heap_open(AccessMethodProcedureRelationId,
                                                                           AccessShareLock);
@@ -3831,13 +3961,21 @@ getObjectIdentityParts(const ObjectAddress *object,
                                amprocForm = (Form_pg_amproc) GETSTRUCT(tup);
 
                                initStringInfo(&opfam);
-                               getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, NULL, NULL);
+                               getOpFamilyIdentity(&opfam, amprocForm->amprocfamily, objname);
+
+                               ltype = format_type_be_qualified(amprocForm->amproclefttype);
+                               rtype = format_type_be_qualified(amprocForm->amprocrighttype);
+
+                               if (objname)
+                               {
+                                       *objname = lappend(*objname,
+                                                                          psprintf("%d", amprocForm->amprocnum));
+                                       *objargs = list_make2(ltype, rtype);
+                               }
 
                                appendStringInfo(&buffer, "function %d (%s, %s) of %s",
                                                                 amprocForm->amprocnum,
-                                               format_type_be_qualified(amprocForm->amproclefttype),
-                                          format_type_be_qualified(amprocForm->amprocrighttype),
-                                                                opfam.data);
+                                                                ltype, rtype, opfam.data);
 
                                pfree(opfam.data);
 
@@ -4263,7 +4401,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 }
 
 static void
-getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname, List **objargs)
+getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname)
 {
        HeapTuple       opfTup;
        Form_pg_opfamily opfForm;
@@ -4289,11 +4427,9 @@ getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **objname, List **objargs
                                         NameStr(amForm->amname));
 
        if (objname)
-       {
-               *objname = list_make2(pstrdup(schema),
+               *objname = list_make3(pstrdup(NameStr(amForm->amname)),
+                                                         pstrdup(schema),
                                                          pstrdup(NameStr(opfForm->opfname)));
-               *objargs = list_make1(pstrdup(NameStr(amForm->amname)));
-       }
 
        ReleaseSysCache(amTup);
        ReleaseSysCache(opfTup);
index e5185ba34d256a86322eca08911681b450ec6a8a..a1b0d4d2fa2ad4a2a57bb6138b0519a1a7c40769 100644 (file)
@@ -406,19 +406,27 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
                        name = NameListToString(objname);
                        break;
                case OBJECT_OPCLASS:
-                       if (!schema_does_not_exist_skipping(objname, &msg, &name))
                        {
-                               msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
-                               name = NameListToString(objname);
-                               args = strVal(linitial(objargs));
+                               List *opcname = list_copy_tail(objname, 1);
+
+                               if (!schema_does_not_exist_skipping(opcname, &msg, &name))
+                               {
+                                       msg = gettext_noop("operator class \"%s\" does not exist for access method \"%s\", skipping");
+                                       name = NameListToString(opcname);
+                                       args = strVal(linitial(objname));
+                               }
                        }
                        break;
                case OBJECT_OPFAMILY:
-                       if (!schema_does_not_exist_skipping(objname, &msg, &name))
                        {
-                               msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
-                               name = NameListToString(objname);
-                               args = strVal(linitial(objargs));
+                               List *opfname = list_copy_tail(objname, 1);
+
+                               if (!schema_does_not_exist_skipping(opfname, &msg, &name))
+                               {
+                                       msg = gettext_noop("operator family \"%s\" does not exist for access method \"%s\", skipping");
+                                       name = NameListToString(opfname);
+                                       args = strVal(linitial(objname));
+                               }
                        }
                        break;
                default:
index 3fec57ea2370b7691201d0a75c849fb78b27011d..4bcc327a2b592a6f8d1ed6b35c14da6fb2f2ba88 100644 (file)
@@ -1060,6 +1060,8 @@ EventTriggerSupportsObjectType(ObjectType obtype)
                        /* no support for event triggers on event triggers */
                        return false;
                case OBJECT_AGGREGATE:
+               case OBJECT_AMOP:
+               case OBJECT_AMPROC:
                case OBJECT_ATTRIBUTE:
                case OBJECT_CAST:
                case OBJECT_COLUMN:
index cf0d31744e15a571a0082cb7972ea59715d4c860..149962035dc12d6326a6310c5df99d050270673f 100644 (file)
@@ -3950,8 +3950,7 @@ AlterExtensionContentsStmt:
                                        n->extname = $3;
                                        n->action = $4;
                                        n->objtype = OBJECT_OPCLASS;
-                                       n->objname = $7;
-                                       n->objargs = list_make1(makeString($9));
+                                       n->objname = lcons(makeString($9), $7);
                                        $$ = (Node *)n;
                                }
                        | ALTER EXTENSION name add_drop OPERATOR FAMILY any_name USING access_method
@@ -3960,8 +3959,7 @@ AlterExtensionContentsStmt:
                                        n->extname = $3;
                                        n->action = $4;
                                        n->objtype = OBJECT_OPFAMILY;
-                                       n->objname = $7;
-                                       n->objargs = list_make1(makeString($9));
+                                       n->objname = lcons(makeString($9), $7);
                                        $$ = (Node *)n;
                                }
                        | ALTER EXTENSION name add_drop SCHEMA name
@@ -5362,8 +5360,7 @@ DropOpClassStmt:
                        DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior
                                {
                                        DropStmt *n = makeNode(DropStmt);
-                                       n->objects = list_make1($4);
-                                       n->arguments = list_make1(list_make1(makeString($6)));
+                                       n->objects = list_make1(lcons(makeString($6), $4));
                                        n->removeType = OBJECT_OPCLASS;
                                        n->behavior = $7;
                                        n->missing_ok = false;
@@ -5373,8 +5370,7 @@ DropOpClassStmt:
                        | DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
                                {
                                        DropStmt *n = makeNode(DropStmt);
-                                       n->objects = list_make1($6);
-                                       n->arguments = list_make1(list_make1(makeString($8)));
+                                       n->objects = list_make1(lcons(makeString($8), $6));
                                        n->removeType = OBJECT_OPCLASS;
                                        n->behavior = $9;
                                        n->missing_ok = true;
@@ -5387,8 +5383,7 @@ DropOpFamilyStmt:
                        DROP OPERATOR FAMILY any_name USING access_method opt_drop_behavior
                                {
                                        DropStmt *n = makeNode(DropStmt);
-                                       n->objects = list_make1($4);
-                                       n->arguments = list_make1(list_make1(makeString($6)));
+                                       n->objects = list_make1(lcons(makeString($6), $4));
                                        n->removeType = OBJECT_OPFAMILY;
                                        n->behavior = $7;
                                        n->missing_ok = false;
@@ -5398,8 +5393,7 @@ DropOpFamilyStmt:
                        | DROP OPERATOR FAMILY IF_P EXISTS any_name USING access_method opt_drop_behavior
                                {
                                        DropStmt *n = makeNode(DropStmt);
-                                       n->objects = list_make1($6);
-                                       n->arguments = list_make1(list_make1(makeString($8)));
+                                       n->objects = list_make1(lcons(makeString($8), $6));
                                        n->removeType = OBJECT_OPFAMILY;
                                        n->behavior = $9;
                                        n->missing_ok = true;
@@ -5741,8 +5735,7 @@ CommentStmt:
                                {
                                        CommentStmt *n = makeNode(CommentStmt);
                                        n->objtype = OBJECT_OPCLASS;
-                                       n->objname = $5;
-                                       n->objargs = list_make1(makeString($7));
+                                       n->objname = lcons(makeString($7), $5);
                                        n->comment = $9;
                                        $$ = (Node *) n;
                                }
@@ -5750,8 +5743,8 @@ CommentStmt:
                                {
                                        CommentStmt *n = makeNode(CommentStmt);
                                        n->objtype = OBJECT_OPFAMILY;
-                                       n->objname = $5;
-                                       n->objargs = list_make1(makeString($7));
+                                       n->objname = lcons(makeString($7), $5);
+                                       n->objargs = NIL;
                                        n->comment = $9;
                                        $$ = (Node *) n;
                                }
@@ -7476,8 +7469,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                                {
                                        RenameStmt *n = makeNode(RenameStmt);
                                        n->renameType = OBJECT_OPCLASS;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newname = $9;
                                        n->missing_ok = false;
                                        $$ = (Node *)n;
@@ -7486,8 +7478,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                                {
                                        RenameStmt *n = makeNode(RenameStmt);
                                        n->renameType = OBJECT_OPFAMILY;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newname = $9;
                                        n->missing_ok = false;
                                        $$ = (Node *)n;
@@ -7924,8 +7915,7 @@ AlterObjectSchemaStmt:
                                {
                                        AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
                                        n->objectType = OBJECT_OPCLASS;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newschema = $9;
                                        n->missing_ok = false;
                                        $$ = (Node *)n;
@@ -7934,8 +7924,7 @@ AlterObjectSchemaStmt:
                                {
                                        AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
                                        n->objectType = OBJECT_OPFAMILY;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newschema = $9;
                                        n->missing_ok = false;
                                        $$ = (Node *)n;
@@ -8162,8 +8151,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_OPCLASS;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newowner = $9;
                                        $$ = (Node *)n;
                                }
@@ -8171,8 +8159,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleSpec
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_OPFAMILY;
-                                       n->object = $4;
-                                       n->objarg = list_make1(makeString($6));
+                                       n->object = lcons(makeString($6), $4);
                                        n->newowner = $9;
                                        $$ = (Node *)n;
                                }
index 50e98291bda8452c815a8f7e4a827893eb4f2c03..a5753539a30bea6e64bec313c926d5ad750ea81d 100644 (file)
@@ -1223,6 +1223,8 @@ typedef struct SetOperationStmt
 typedef enum ObjectType
 {
        OBJECT_AGGREGATE,
+       OBJECT_AMOP,
+       OBJECT_AMPROC,
        OBJECT_ATTRIBUTE,                       /* type's attribute, when distinct from column */
        OBJECT_CAST,
        OBJECT_COLUMN,
index 3bcbcd8b65f00e8919cf6f918d5aac7dd3a0b24e..365dcca71837388c319390a07ddf31a57cfee1d1 100644 (file)
@@ -45,8 +45,7 @@ DECLARE
        objtype text;
 BEGIN
        FOR objtype IN VALUES ('toast table'), ('index column'), ('sequence column'),
-               ('toast table column'), ('view column'), ('materialized view column'),
-               ('operator of access method'), ('function of access method')
+               ('toast table column'), ('view column'), ('materialized view column')
        LOOP
                BEGIN
                        PERFORM pg_get_object_address(objtype, '{one}', '{}');
@@ -62,8 +61,6 @@ WARNING:  error for sequence column: unsupported object type "sequence column"
 WARNING:  error for toast table column: unsupported object type "toast table column"
 WARNING:  error for view column: unsupported object type "view column"
 WARNING:  error for materialized view column: unsupported object type "materialized view column"
-WARNING:  error for operator of access method: unsupported object type "operator of access method"
-WARNING:  error for function of access method: unsupported object type "function of access method"
 DO $$
 DECLARE
        objtype text;
@@ -79,7 +76,8 @@ BEGIN
                ('operator'), ('operator class'), ('operator family'), ('rule'), ('trigger'),
                ('text search parser'), ('text search dictionary'),
                ('text search template'), ('text search configuration'),
-               ('policy'), ('user mapping'), ('default acl')
+               ('policy'), ('user mapping'), ('default acl'),
+               ('operator of access method'), ('function of access method')
        LOOP
                FOR names IN VALUES ('{eins}'), ('{addr_nsp, zwei}'), ('{eins, zwei, drei}')
                LOOP
@@ -197,18 +195,18 @@ WARNING:  error for operator,{addr_nsp,zwei},{}: argument list length must be ex
 WARNING:  error for operator,{addr_nsp,zwei},{integer}: argument list length must be exactly 2
 WARNING:  error for operator,{eins,zwei,drei},{}: argument list length must be exactly 2
 WARNING:  error for operator,{eins,zwei,drei},{integer}: argument list length must be exactly 2
-WARNING:  error for operator class,{eins},{}: argument list length must be exactly 1
-WARNING:  error for operator class,{eins},{integer}: access method "integer" does not exist
-WARNING:  error for operator class,{addr_nsp,zwei},{}: argument list length must be exactly 1
-WARNING:  error for operator class,{addr_nsp,zwei},{integer}: access method "integer" does not exist
-WARNING:  error for operator class,{eins,zwei,drei},{}: argument list length must be exactly 1
-WARNING:  error for operator class,{eins,zwei,drei},{integer}: access method "integer" does not exist
-WARNING:  error for operator family,{eins},{}: argument list length must be exactly 1
-WARNING:  error for operator family,{eins},{integer}: access method "integer" does not exist
-WARNING:  error for operator family,{addr_nsp,zwei},{}: argument list length must be exactly 1
-WARNING:  error for operator family,{addr_nsp,zwei},{integer}: access method "integer" does not exist
-WARNING:  error for operator family,{eins,zwei,drei},{}: argument list length must be exactly 1
-WARNING:  error for operator family,{eins,zwei,drei},{integer}: access method "integer" does not exist
+WARNING:  error for operator class,{eins},{}: name list length must be at least 2
+WARNING:  error for operator class,{eins},{integer}: name list length must be at least 2
+WARNING:  error for operator class,{addr_nsp,zwei},{}: access method "addr_nsp" does not exist
+WARNING:  error for operator class,{addr_nsp,zwei},{integer}: access method "addr_nsp" does not exist
+WARNING:  error for operator class,{eins,zwei,drei},{}: access method "eins" does not exist
+WARNING:  error for operator class,{eins,zwei,drei},{integer}: access method "eins" does not exist
+WARNING:  error for operator family,{eins},{}: name list length must be at least 2
+WARNING:  error for operator family,{eins},{integer}: name list length must be at least 2
+WARNING:  error for operator family,{addr_nsp,zwei},{}: access method "addr_nsp" does not exist
+WARNING:  error for operator family,{addr_nsp,zwei},{integer}: access method "addr_nsp" does not exist
+WARNING:  error for operator family,{eins,zwei,drei},{}: access method "eins" does not exist
+WARNING:  error for operator family,{eins,zwei,drei},{integer}: access method "eins" does not exist
 WARNING:  error for rule,{eins},{}: rule "eins" does not exist
 WARNING:  error for rule,{eins},{integer}: rule "eins" does not exist
 WARNING:  error for rule,{addr_nsp,zwei},{}: relation "addr_nsp" does not exist
@@ -263,6 +261,18 @@ WARNING:  error for default acl,{addr_nsp,zwei},{}: argument list length must be
 WARNING:  error for default acl,{addr_nsp,zwei},{integer}: unrecognized default ACL object type i
 WARNING:  error for default acl,{eins,zwei,drei},{}: argument list length must be exactly 1
 WARNING:  error for default acl,{eins,zwei,drei},{integer}: unrecognized default ACL object type i
+WARNING:  error for operator of access method,{eins},{}: name list length must be at least 3
+WARNING:  error for operator of access method,{eins},{integer}: name list length must be at least 3
+WARNING:  error for operator of access method,{addr_nsp,zwei},{}: name list length must be at least 3
+WARNING:  error for operator of access method,{addr_nsp,zwei},{integer}: name list length must be at least 3
+WARNING:  error for operator of access method,{eins,zwei,drei},{}: argument list length must be exactly 2
+WARNING:  error for operator of access method,{eins,zwei,drei},{integer}: argument list length must be exactly 2
+WARNING:  error for function of access method,{eins},{}: name list length must be at least 3
+WARNING:  error for function of access method,{eins},{integer}: name list length must be at least 3
+WARNING:  error for function of access method,{addr_nsp,zwei},{}: name list length must be at least 3
+WARNING:  error for function of access method,{addr_nsp,zwei},{integer}: name list length must be at least 3
+WARNING:  error for function of access method,{eins,zwei,drei},{}: argument list length must be exactly 2
+WARNING:  error for function of access method,{eins,zwei,drei},{integer}: argument list length must be exactly 2
 -- these object types cannot be qualified names
 SELECT pg_get_object_address('language', '{one}', '{}');
 ERROR:  language "one" does not exist
@@ -332,10 +342,10 @@ WITH objects (type, name, args) AS (VALUES
                                ('language', '{plpgsql}', '{}'),
                                -- large object
                                ('operator', '{+}', '{int4, int4}'),
-                               ('operator class', '{int4_ops}', '{btree}'),
-                               ('operator family', '{integer_ops}', '{btree}'),
-                               -- operator of access method
-                               -- function of access method
+                               ('operator class', '{btree, int4_ops}', '{}'),
+                               ('operator family', '{btree, integer_ops}', '{}'),
+                               ('operator of access method', '{btree,integer_ops,1}', '{integer,integer}'),
+                               ('function of access method', '{btree,integer_ops,2}', '{integer,integer}'),
                                ('rule', '{addr_nsp, genview, _RETURN}', '{}'),
                                ('trigger', '{addr_nsp, gentable, t}', '{}'),
                                ('schema', '{addr_nsp}', '{}'),
@@ -362,7 +372,7 @@ SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
          FROM objects, pg_get_object_address(type, name, args) addr1,
                        pg_identify_object_as_address(classid, objid, subobjid) ioa(typ,nms,args),
                        pg_get_object_address(typ, nms, ioa.args) as addr2
-       ORDER BY addr1.classid, addr1.objid;
+       ORDER BY addr1.classid, addr1.objid, addr1.subobjid;
            type            |   schema   |       name        |                               identity                               | ?column? 
 ---------------------------+------------+-------------------+----------------------------------------------------------------------+----------
  default acl               |            |                   | for role regtest_addr_user in schema public on tables                | t
@@ -379,12 +389,14 @@ SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
  index                     | addr_nsp   | gentable_pkey     | addr_nsp.gentable_pkey                                               | t
  view                      | addr_nsp   | genview           | addr_nsp.genview                                                     | t
  materialized view         | addr_nsp   | genmatview        | addr_nsp.genmatview                                                  | t
- foreign table column      | addr_nsp   | genftable         | addr_nsp.genftable.a                                                 | t
  foreign table             | addr_nsp   | genftable         | addr_nsp.genftable                                                   | t
+ foreign table column      | addr_nsp   | genftable         | addr_nsp.genftable.a                                                 | t
  role                      |            | regtest_addr_user | regtest_addr_user                                                    | t
  server                    |            | addr_fserv        | addr_fserv                                                           | t
  user mapping              |            |                   | regtest_addr_user on server integer                                  | t
  foreign-data wrapper      |            | addr_fdw          | addr_fdw                                                             | t
+ operator of access method |            |                   | operator 1 (integer, integer) of pg_catalog.integer_ops USING btree  | t
+ function of access method |            |                   | function 2 (integer, integer) of pg_catalog.integer_ops USING btree  | t
  default value             |            |                   | for addr_nsp.gentable.b                                              | t
  cast                      |            |                   | (bigint AS integer)                                                  | t
  table constraint          | addr_nsp   |                   | a_chk on addr_nsp.gentable                                           | t
@@ -403,7 +415,7 @@ SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
  text search parser        | addr_nsp   | addr_ts_prs       | addr_nsp.addr_ts_prs                                                 | t
  text search configuration | addr_nsp   | addr_ts_conf      | addr_nsp.addr_ts_conf                                                | t
  text search template      | addr_nsp   | addr_ts_temp      | addr_nsp.addr_ts_temp                                                | t
-(38 rows)
+(40 rows)
 
 ---
 --- Cleanup resources
index a49f03fdf7dc3859fa0c8233b74d33613d9302a5..9cf80971241deaf0e21edf54f1aaf4817510a133 100644 (file)
@@ -48,8 +48,7 @@ DECLARE
        objtype text;
 BEGIN
        FOR objtype IN VALUES ('toast table'), ('index column'), ('sequence column'),
-               ('toast table column'), ('view column'), ('materialized view column'),
-               ('operator of access method'), ('function of access method')
+               ('toast table column'), ('view column'), ('materialized view column')
        LOOP
                BEGIN
                        PERFORM pg_get_object_address(objtype, '{one}', '{}');
@@ -75,7 +74,8 @@ BEGIN
                ('operator'), ('operator class'), ('operator family'), ('rule'), ('trigger'),
                ('text search parser'), ('text search dictionary'),
                ('text search template'), ('text search configuration'),
-               ('policy'), ('user mapping'), ('default acl')
+               ('policy'), ('user mapping'), ('default acl'),
+               ('operator of access method'), ('function of access method')
        LOOP
                FOR names IN VALUES ('{eins}'), ('{addr_nsp, zwei}'), ('{eins, zwei, drei}')
                LOOP
@@ -141,10 +141,10 @@ WITH objects (type, name, args) AS (VALUES
                                ('language', '{plpgsql}', '{}'),
                                -- large object
                                ('operator', '{+}', '{int4, int4}'),
-                               ('operator class', '{int4_ops}', '{btree}'),
-                               ('operator family', '{integer_ops}', '{btree}'),
-                               -- operator of access method
-                               -- function of access method
+                               ('operator class', '{btree, int4_ops}', '{}'),
+                               ('operator family', '{btree, integer_ops}', '{}'),
+                               ('operator of access method', '{btree,integer_ops,1}', '{integer,integer}'),
+                               ('function of access method', '{btree,integer_ops,2}', '{integer,integer}'),
                                ('rule', '{addr_nsp, genview, _RETURN}', '{}'),
                                ('trigger', '{addr_nsp, gentable, t}', '{}'),
                                ('schema', '{addr_nsp}', '{}'),
@@ -171,7 +171,7 @@ SELECT (pg_identify_object(addr1.classid, addr1.objid, addr1.subobjid)).*,
          FROM objects, pg_get_object_address(type, name, args) addr1,
                        pg_identify_object_as_address(classid, objid, subobjid) ioa(typ,nms,args),
                        pg_get_object_address(typ, nms, ioa.args) as addr2
-       ORDER BY addr1.classid, addr1.objid;
+       ORDER BY addr1.classid, addr1.objid, addr1.subobjid;
 
 ---
 --- Cleanup resources