On Thu, Dec 15, 2011 at 07:04:20PM -0500, Robert Haas wrote:
> On Fri, Dec 9, 2011 at 5:41 PM, Noah Misch <n...@leadboat.com> wrote:
> > It also seems my last explanation didn't convey the point. ?Yes, nearly 
> > every
> > command has a different set of permissions checks. ?However, we don't 
> > benefit
> > equally from performing each of those checks before acquiring a lock.
> > Consider renameatt(), which checks three things: you must own the relation,
> > the relation must be of a supported relkind, and the relation must not be a
> > typed table. ?To limit opportunities for denial of service, let's definitely
> > perform the ownership check before taking a lock. ?The other two checks can
> > wait until we hold that lock. ?The benefit of checking them early is to 
> > avoid
> > making a careless relation owner wait for a lock before discovering the
> > invalidity of his command. ?That's nice as far as it goes, but let's not
> > proliferate callbacks for such a third-order benefit.
> 
> I agree, but my point is that so far we have no callbacks that differ
> only in that detail.  I accept that we'd probably want to avoid that.

To illustrate what I had in mind, here's a version of your patch that has five
callers sharing a callback.  The patch is against d039fd51f79e, just prior to
your recent commits.
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
***************
*** 211,217 **** Datum          pg_is_other_temp_schema(PG_FUNCTION_ARGS);
  
  
  /*
!  * RangeVarGetRelid
   *            Given a RangeVar describing an existing relation,
   *            select the proper namespace and look up the relation OID.
   *
--- 211,217 ----
  
  
  /*
!  * RangeVarGetRelidExtended
   *            Given a RangeVar describing an existing relation,
   *            select the proper namespace and look up the relation OID.
   *
***************
*** 409,414 **** RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE 
lockmode,
--- 409,427 ----
  }
  
  /*
+  * RangeVarCallbackCheckOwner
+  *            RangeVarGetRelidExtended() callback to check ownership alone.
+  */
+ void
+ RangeVarCallbackCheckOwner(const RangeVar *relation,
+                                                  Oid relId, Oid oldRelId, 
void *arg)
+ {
+       /* Nothing to do if the relation was not found. */
+       if (OidIsValid(relId) && !pg_class_ownercheck(relId, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, 
relation->relname);
+ }
+ 
+ /*
   * RangeVarGetCreationNamespace
   *            Given a RangeVar describing a to-be-created relation,
   *            choose which namespace to create it in.
*** a/src/backend/commands/alter.c
--- b/src/backend/commands/alter.c
***************
*** 105,166 **** ExecRenameStmt(RenameStmt *stmt)
                case OBJECT_SEQUENCE:
                case OBJECT_VIEW:
                case OBJECT_INDEX:
                case OBJECT_COLUMN:
                case OBJECT_ATTRIBUTE:
                case OBJECT_TRIGGER:
!               case OBJECT_FOREIGN_TABLE:
!                       {
!                               Oid                     relid;
! 
!                               CheckRelationOwnership(stmt->relation, true);
! 
!                               /*
!                                * Lock level used here should match what will 
be taken later,
!                                * in RenameRelation, renameatt, or renametrig.
!                                */
!                               relid = RangeVarGetRelid(stmt->relation, 
AccessExclusiveLock,
!                                                                               
 false);
! 
!                               switch (stmt->renameType)
!                               {
!                                       case OBJECT_TABLE:
!                                       case OBJECT_SEQUENCE:
!                                       case OBJECT_VIEW:
!                                       case OBJECT_INDEX:
!                                       case OBJECT_FOREIGN_TABLE:
!                                               {
!                                                       /*
!                                                        * RENAME TABLE 
requires that we (still) hold
!                                                        * CREATE rights on the 
containing namespace, as
!                                                        * well as ownership of 
the table.
!                                                        */
!                                                       Oid                     
namespaceId = get_rel_namespace(relid);
!                                                       AclResult       
aclresult;
! 
!                                                       aclresult = 
pg_namespace_aclcheck(namespaceId,
!                                                                               
                                          GetUserId(),
!                                                                               
                                          ACL_CREATE);
!                                                       if (aclresult != 
ACLCHECK_OK)
!                                                               
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
!                                                                               
        get_namespace_name(namespaceId));
! 
!                                                       RenameRelation(relid, 
stmt->newname, stmt->renameType);
!                                                       break;
!                                               }
!                                       case OBJECT_COLUMN:
!                                       case OBJECT_ATTRIBUTE:
!                                               renameatt(relid, stmt);
!                                               break;
!                                       case OBJECT_TRIGGER:
!                                               renametrig(relid,
!                                                                  
stmt->subname,               /* old att name */
!                                                                  
stmt->newname);              /* new att name */
!                                               break;
!                                       default:
!                                                /* can't happen */ ;
!                               }
!                               break;
!                       }
  
                case OBJECT_TSPARSER:
                        RenameTSParser(stmt->object, stmt->newname);
--- 105,122 ----
                case OBJECT_SEQUENCE:
                case OBJECT_VIEW:
                case OBJECT_INDEX:
+               case OBJECT_FOREIGN_TABLE:
+                       RenameRelation(stmt);
+                       break;
+ 
                case OBJECT_COLUMN:
                case OBJECT_ATTRIBUTE:
+                       renameatt(stmt);
+                       break;
+ 
                case OBJECT_TRIGGER:
!                       renametrig(stmt);
!                       break;
  
                case OBJECT_TSPARSER:
                        RenameTSParser(stmt->object, stmt->newname);
***************
*** 235,241 **** ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
                case OBJECT_TABLE:
                case OBJECT_VIEW:
                case OBJECT_FOREIGN_TABLE:
-                       CheckRelationOwnership(stmt->relation, true);
                        AlterTableNamespace(stmt->relation, stmt->newschema,
                                                                
stmt->objectType, AccessExclusiveLock);
                        break;
--- 191,196 ----
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
***************
*** 1474,1501 **** finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
                {
                        Relation        toastrel;
                        Oid                     toastidx;
-                       Oid                     toastnamespace;
                        char            NewToastName[NAMEDATALEN];
  
                        toastrel = relation_open(newrel->rd_rel->reltoastrelid,
                                                                         
AccessShareLock);
                        toastidx = toastrel->rd_rel->reltoastidxid;
-                       toastnamespace = toastrel->rd_rel->relnamespace;
                        relation_close(toastrel, AccessShareLock);
  
                        /* rename the toast table ... */
                        snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
                                         OIDOldHeap);
                        RenameRelationInternal(newrel->rd_rel->reltoastrelid,
!                                                                  NewToastName,
!                                                                  
toastnamespace);
  
                        /* ... and its index too */
                        snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
                                         OIDOldHeap);
                        RenameRelationInternal(toastidx,
!                                                                  NewToastName,
!                                                                  
toastnamespace);
                }
                relation_close(newrel, NoLock);
        }
--- 1474,1497 ----
                {
                        Relation        toastrel;
                        Oid                     toastidx;
                        char            NewToastName[NAMEDATALEN];
  
                        toastrel = relation_open(newrel->rd_rel->reltoastrelid,
                                                                         
AccessShareLock);
                        toastidx = toastrel->rd_rel->reltoastidxid;
                        relation_close(toastrel, AccessShareLock);
  
                        /* rename the toast table ... */
                        snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
                                         OIDOldHeap);
                        RenameRelationInternal(newrel->rd_rel->reltoastrelid,
!                                                                  
NewToastName);
  
                        /* ... and its index too */
                        snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
                                         OIDOldHeap);
                        RenameRelationInternal(toastidx,
!                                                                  
NewToastName);
                }
                relation_close(newrel, NoLock);
        }
*** a/src/backend/commands/indexcmds.c
--- b/src/backend/commands/indexcmds.c
***************
*** 63,70 **** static void ComputeIndexAttrs(IndexInfo *indexInfo,
  static Oid GetIndexOpClass(List *opclass, Oid attrType,
                                char *accessMethodName, Oid accessMethodId);
  static char *ChooseIndexNameAddition(List *colnames);
- static void RangeVarCallbackForReindexTable(const RangeVar *relation,
-                                                               Oid relId, Oid 
oldRelId, void *arg);
  static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
                                                                Oid relId, Oid 
oldRelId, void *arg);
  
--- 63,68 ----
***************
*** 1806,1815 **** void
  ReindexTable(RangeVar *relation)
  {
        Oid                     heapOid;
  
        /* The lock level used here should match reindex_relation(). */
        heapOid = RangeVarGetRelidExtended(relation, ShareLock, false, false,
!                                                                          
RangeVarCallbackForReindexTable, NULL);
  
        if (!reindex_relation(heapOid, REINDEX_REL_PROCESS_TOAST))
                ereport(NOTICE,
--- 1804,1826 ----
  ReindexTable(RangeVar *relation)
  {
        Oid                     heapOid;
+       HeapTuple       tuple;
  
        /* The lock level used here should match reindex_relation(). */
        heapOid = RangeVarGetRelidExtended(relation, ShareLock, false, false,
!                                                                          
RangeVarCallbackCheckOwner, NULL);
!       tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(heapOid));
!       if (!HeapTupleIsValid(tuple))           /* shouldn't happen */
!               elog(ERROR, "cache lookup failed for relation %u", heapOid);
! 
!       if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION &&
!               ((Form_pg_class) GETSTRUCT(tuple))->relkind != 
RELKIND_TOASTVALUE)
!               ereport(ERROR,
!                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
!                                errmsg("\"%s\" is not a table",
!                                               relation->relname)));
! 
!       ReleaseSysCache(tuple);
  
        if (!reindex_relation(heapOid, REINDEX_REL_PROCESS_TOAST))
                ereport(NOTICE,
***************
*** 1818,1854 **** ReindexTable(RangeVar *relation)
  }
  
  /*
-  * Check permissions on table before acquiring relation lock.
-  */
- static void
- RangeVarCallbackForReindexTable(const RangeVar *relation,
-                                                               Oid relId, Oid 
oldRelId, void *arg)
- {
-       char            relkind;
- 
-       /* Nothing to do if the relation was not found. */
-       if (!OidIsValid(relId))
-               return;
- 
-       /*
-        * If the relation does exist, check whether it's an index.  But note
-        * that the relation might have been dropped between the time we did the
-        * name lookup and now.  In that case, there's nothing to do.
-        */
-       relkind = get_rel_relkind(relId);
-       if (!relkind)
-               return;
-       if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE)
-               ereport(ERROR,
-                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("\"%s\" is not a table", 
relation->relname)));
- 
-       /* Check permissions */
-       if (!pg_class_ownercheck(relId, GetUserId()))
-               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, 
relation->relname);
- }
- 
- /*
   * ReindexDatabase
   *            Recreate indexes of a database.
   *
--- 1829,1834 ----
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 2257,2264 **** renameatt_internal(Oid myrelid,
   *            renameatt               - changes the name of a attribute in a 
relation
   */
  void
! renameatt(Oid myrelid, RenameStmt *stmt)
  {
        renameatt_internal(myrelid,
                                           stmt->subname,       /* old att name 
*/
                                           stmt->newname,       /* new att name 
*/
--- 2257,2270 ----
   *            renameatt               - changes the name of a attribute in a 
relation
   */
  void
! renameatt(RenameStmt *stmt)
  {
+       Oid                     myrelid;
+ 
+       /* lock level taken here should match renameatt_internal */
+       myrelid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
+                                                                          
false, false,
+                                                                          
RangeVarCallbackCheckOwner, NULL);
        renameatt_internal(myrelid,
                                           stmt->subname,       /* old att name 
*/
                                           stmt->newname,       /* new att name 
*/
***************
*** 2269,2295 **** renameatt(Oid myrelid, RenameStmt *stmt)
  }
  
  
! /*
!  * Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE RENAME
!  *
!  * Caller has already done permissions checks.
!  */
  void
! RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
  {
        Relation        targetrelation;
        Oid                     namespaceId;
        char            relkind;
  
        /*
         * Grab an exclusive lock on the target table, index, sequence or view,
         * which we will NOT release until end of transaction.
         *
!        * Lock level used here should match ExecRenameStmt
         */
        targetrelation = relation_open(myrelid, AccessExclusiveLock);
  
        namespaceId = RelationGetNamespace(targetrelation);
        relkind = targetrelation->rd_rel->relkind;
  
        /*
--- 2275,2316 ----
  }
  
  
! /* Execute ALTER TABLE/INDEX/SEQUENCE/VIEW/FOREIGN TABLE RENAME */
  void
! RenameRelation(RenameStmt *stmt)
  {
+       Oid                     myrelid;
        Relation        targetrelation;
        Oid                     namespaceId;
+       AclResult       aclresult;
        char            relkind;
+       ObjectType      reltype = stmt->renameType;
  
        /*
         * Grab an exclusive lock on the target table, index, sequence or view,
         * which we will NOT release until end of transaction.
         *
!        * Lock level used here should match RenameRelationInternal, to avoid
!        * lock escalation.
         */
+       myrelid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
+                                                                          
false, false,
+                                                                          
RangeVarCallbackCheckOwner, NULL);
        targetrelation = relation_open(myrelid, AccessExclusiveLock);
  
+       if (!allowSystemTableMods && IsSystemRelation(targetrelation))
+               ereport(ERROR,
+                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+                                errmsg("permission denied: \"%s\" is a system 
catalog",
+                                               
RelationGetRelationName(targetrelation))));
+ 
+       /* Must (still) have CREATE rights on containing namespace. */
        namespaceId = RelationGetNamespace(targetrelation);
+       aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
+       if (aclresult != ACLCHECK_OK)
+               aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+                                          get_namespace_name(namespaceId));
+ 
        relkind = targetrelation->rd_rel->relkind;
  
        /*
***************
*** 2328,2334 **** RenameRelation(Oid myrelid, const char *newrelname, 
ObjectType reltype)
                                 errhint("Use ALTER TYPE instead.")));
  
        /* Do the work */
!       RenameRelationInternal(myrelid, newrelname, namespaceId);
  
        /*
         * Close rel, but keep exclusive lock!
--- 2349,2355 ----
                                 errhint("Use ALTER TYPE instead.")));
  
        /* Do the work */
!       RenameRelationInternal(myrelid, stmt->newname);
  
        /*
         * Close rel, but keep exclusive lock!
***************
*** 2346,2363 **** RenameRelation(Oid myrelid, const char *newrelname, 
ObjectType reltype)
   *                      sequence, AFAIK there's no need for it to be there.
   */
  void
! RenameRelationInternal(Oid myrelid, const char *newrelname, Oid namespaceId)
  {
        Relation        targetrelation;
        Relation        relrelation;    /* for RELATION relation */
        HeapTuple       reltup;
        Form_pg_class relform;
  
        /*
         * Grab an exclusive lock on the target table, index, sequence or view,
         * which we will NOT release until end of transaction.
         */
        targetrelation = relation_open(myrelid, AccessExclusiveLock);
  
        /*
         * Find relation's pg_class tuple, and make sure newrelname isn't in 
use.
--- 2367,2386 ----
   *                      sequence, AFAIK there's no need for it to be there.
   */
  void
! RenameRelationInternal(Oid myrelid, const char *newrelname)
  {
        Relation        targetrelation;
        Relation        relrelation;    /* for RELATION relation */
        HeapTuple       reltup;
        Form_pg_class relform;
+       Oid                     namespaceId;
  
        /*
         * Grab an exclusive lock on the target table, index, sequence or view,
         * which we will NOT release until end of transaction.
         */
        targetrelation = relation_open(myrelid, AccessExclusiveLock);
+       namespaceId = RelationGetNamespace(targetrelation);
  
        /*
         * Find relation's pg_class tuple, and make sure newrelname isn't in 
use.
***************
*** 5376,5382 **** ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
                ereport(NOTICE,
                                (errmsg("ALTER TABLE / ADD CONSTRAINT USING 
INDEX will rename index \"%s\" to \"%s\"",
                                                indexName, constraintName)));
!               RenameRelation(index_oid, constraintName, OBJECT_INDEX);
        }
  
        /* Extra checks needed if making primary key */
--- 5399,5405 ----
                ereport(NOTICE,
                                (errmsg("ALTER TABLE / ADD CONSTRAINT USING 
INDEX will rename index \"%s\" to \"%s\"",
                                                indexName, constraintName)));
!               RenameRelationInternal(index_oid, constraintName);
        }
  
        /* Extra checks needed if making primary key */
***************
*** 9316,9326 **** ATExecGenericOptions(Relation rel, List *options)
  }
  
  
! /*
!  * Execute ALTER TABLE SET SCHEMA
!  *
!  * Note: caller must have checked ownership of the relation already
!  */
  void
  AlterTableNamespace(RangeVar *relation, const char *newschema,
                                        ObjectType stmttype, LOCKMODE lockmode)
--- 9339,9345 ----
  }
  
  
! /* Execute ALTER TABLE SET SCHEMA */
  void
  AlterTableNamespace(RangeVar *relation, const char *newschema,
                                        ObjectType stmttype, LOCKMODE lockmode)
***************
*** 9331,9339 **** AlterTableNamespace(RangeVar *relation, const char 
*newschema,
        Oid                     nspOid;
        Relation        classRel;
  
        rel = relation_openrv(relation, lockmode);
  
!       relid = RelationGetRelid(rel);
        oldNspOid = RelationGetNamespace(rel);
  
        /* Check relation type against type specified in the ALTER command */
--- 9350,9365 ----
        Oid                     nspOid;
        Relation        classRel;
  
+       relid = RangeVarGetRelidExtended(relation, lockmode, false, false,
+                                                                        
RangeVarCallbackCheckOwner, NULL);
        rel = relation_openrv(relation, lockmode);
  
!       if (!allowSystemTableMods && IsSystemRelation(rel))
!               ereport(ERROR,
!                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
!                                errmsg("permission denied: \"%s\" is a system 
catalog",
!                                               RelationGetRelationName(rel))));
! 
        oldNspOid = RelationGetNamespace(rel);
  
        /* Check relation type against type specified in the ALTER command */
*** a/src/backend/commands/trigger.c
--- b/src/backend/commands/trigger.c
***************
*** 1165,1185 **** get_trigger_oid(Oid relid, const char *trigname, bool 
missing_ok)
   *            update row in catalog
   */
  void
! renametrig(Oid relid,
!                  const char *oldname,
!                  const char *newname)
  {
        Relation        targetrel;
        Relation        tgrel;
        HeapTuple       tuple;
        SysScanDesc tgscan;
        ScanKeyData key[2];
  
        /*
!        * Grab an exclusive lock on the target table, which we will NOT release
!        * until end of transaction.
         */
!       targetrel = heap_open(relid, AccessExclusiveLock);
  
        /*
         * Scan pg_trigger twice for existing triggers on relation.  We do this 
in
--- 1165,1195 ----
   *            update row in catalog
   */
  void
! renametrig(RenameStmt *stmt)
  {
        Relation        targetrel;
        Relation        tgrel;
        HeapTuple       tuple;
        SysScanDesc tgscan;
        ScanKeyData key[2];
+       Oid                     relid;
  
        /*
!        * Look up name, check permissions, and acquire lock (which we will NOT
!        * release until end of transaction).
         */
!       relid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock,
!                                                                        false, 
false,
!                                                                        
RangeVarCallbackCheckOwner, NULL);
! 
!       /* Have lock already, so just need to build relcache entry. */
!       targetrel = heap_open(relid, NoLock);
! 
!       if (!allowSystemTableMods && IsSystemRelation(targetrel))
!               ereport(ERROR,
!                               (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
!                                errmsg("permission denied: \"%s\" is a system 
catalog",
!                                               
RelationGetRelationName(targetrel))));
  
        /*
         * Scan pg_trigger twice for existing triggers on relation.  We do this 
in
***************
*** 1202,1215 **** renametrig(Oid relid,
        ScanKeyInit(&key[1],
                                Anum_pg_trigger_tgname,
                                BTEqualStrategyNumber, F_NAMEEQ,
!                               PointerGetDatum(newname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
                                                                SnapshotNow, 2, 
key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
                                 errmsg("trigger \"%s\" for relation \"%s\" 
already exists",
!                                               newname, 
RelationGetRelationName(targetrel))));
        systable_endscan(tgscan);
  
        /*
--- 1212,1225 ----
        ScanKeyInit(&key[1],
                                Anum_pg_trigger_tgname,
                                BTEqualStrategyNumber, F_NAMEEQ,
!                               PointerGetDatum(stmt->newname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
                                                                SnapshotNow, 2, 
key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
                ereport(ERROR,
                                (errcode(ERRCODE_DUPLICATE_OBJECT),
                                 errmsg("trigger \"%s\" for relation \"%s\" 
already exists",
!                                               stmt->newname, 
RelationGetRelationName(targetrel))));
        systable_endscan(tgscan);
  
        /*
***************
*** 1222,1228 **** renametrig(Oid relid,
        ScanKeyInit(&key[1],
                                Anum_pg_trigger_tgname,
                                BTEqualStrategyNumber, F_NAMEEQ,
!                               PointerGetDatum(oldname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
                                                                SnapshotNow, 2, 
key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
--- 1232,1238 ----
        ScanKeyInit(&key[1],
                                Anum_pg_trigger_tgname,
                                BTEqualStrategyNumber, F_NAMEEQ,
!                               PointerGetDatum(stmt->subname));
        tgscan = systable_beginscan(tgrel, TriggerRelidNameIndexId, true,
                                                                SnapshotNow, 2, 
key);
        if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
***************
*** 1232,1238 **** renametrig(Oid relid,
                 */
                tuple = heap_copytuple(tuple);  /* need a modifiable copy */
  
!               namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname, 
newname);
  
                simple_heap_update(tgrel, &tuple->t_self, tuple);
  
--- 1242,1249 ----
                 */
                tuple = heap_copytuple(tuple);  /* need a modifiable copy */
  
!               namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
!                                  stmt->newname);
  
                simple_heap_update(tgrel, &tuple->t_self, tuple);
  
***************
*** 1251,1257 **** renametrig(Oid relid,
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                                 errmsg("trigger \"%s\" for table \"%s\" does 
not exist",
!                                               oldname, 
RelationGetRelationName(targetrel))));
        }
  
        systable_endscan(tgscan);
--- 1262,1268 ----
                ereport(ERROR,
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                                 errmsg("trigger \"%s\" for table \"%s\" does 
not exist",
!                                               stmt->subname, 
RelationGetRelationName(targetrel))));
        }
  
        systable_endscan(tgscan);
*** a/src/backend/commands/typecmds.c
--- b/src/backend/commands/typecmds.c
***************
*** 3121,3128 **** RenameType(List *names, const char *newTypeName)
         * RenameRelationInternal will call RenameTypeInternal automatically.
         */
        if (typTup->typtype == TYPTYPE_COMPOSITE)
!               RenameRelationInternal(typTup->typrelid, newTypeName,
!                                                          
typTup->typnamespace);
        else
                RenameTypeInternal(typeOid, newTypeName,
                                                   typTup->typnamespace);
--- 3121,3127 ----
         * RenameRelationInternal will call RenameTypeInternal automatically.
         */
        if (typTup->typtype == TYPTYPE_COMPOSITE)
!               RenameRelationInternal(typTup->typrelid, newTypeName);
        else
                RenameTypeInternal(typeOid, newTypeName,
                                                   typTup->typnamespace);
*** a/src/include/catalog/namespace.h
--- b/src/include/catalog/namespace.h
***************
*** 57,62 **** extern Oid       RangeVarGetRelidExtended(const RangeVar 
*relation,
--- 57,64 ----
                                                 LOCKMODE lockmode, bool 
missing_ok, bool nowait,
                                                 RangeVarGetRelidCallback 
callback,
                                                 void *callback_arg);
+ extern void RangeVarCallbackCheckOwner(const RangeVar *relation,
+                                                  Oid relId, Oid oldRelId, 
void *arg);
  extern Oid    RangeVarGetCreationNamespace(const RangeVar *newRelation);
  extern Oid    RangeVarGetAndCheckCreationNamespace(const RangeVar 
*newRelation);
  extern void RangeVarAdjustRelationPersistence(RangeVar *newRelation, Oid 
nspid);
*** a/src/include/commands/tablecmds.h
--- b/src/include/commands/tablecmds.h
***************
*** 45,59 **** extern void ExecuteTruncate(TruncateStmt *stmt);
  
  extern void SetRelationHasSubclass(Oid relationId, bool relhassubclass);
  
! extern void renameatt(Oid myrelid, RenameStmt *stmt);
  
! extern void RenameRelation(Oid myrelid,
!                          const char *newrelname,
!                          ObjectType reltype);
  
  extern void RenameRelationInternal(Oid myrelid,
!                                          const char *newrelname,
!                                          Oid namespaceId);
  
  extern void find_composite_type_dependencies(Oid typeOid,
                                                                 Relation 
origRelation,
--- 45,56 ----
  
  extern void SetRelationHasSubclass(Oid relationId, bool relhassubclass);
  
! extern void renameatt(RenameStmt *stmt);
  
! extern void RenameRelation(RenameStmt *stmt);
  
  extern void RenameRelationInternal(Oid myrelid,
!                                          const char *newrelname);
  
  extern void find_composite_type_dependencies(Oid typeOid,
                                                                 Relation 
origRelation,
*** a/src/include/commands/trigger.h
--- b/src/include/commands/trigger.h
***************
*** 115,121 **** extern Oid CreateTrigger(CreateTrigStmt *stmt, const char 
*queryString,
  extern void RemoveTriggerById(Oid trigOid);
  extern Oid    get_trigger_oid(Oid relid, const char *name, bool missing_ok);
  
! extern void renametrig(Oid relid, const char *oldname, const char *newname);
  
  extern void EnableDisableTrigger(Relation rel, const char *tgname,
                                         char fires_when, bool skip_system);
--- 115,121 ----
  extern void RemoveTriggerById(Oid trigOid);
  extern Oid    get_trigger_oid(Oid relid, const char *name, bool missing_ok);
  
! extern void renametrig(RenameStmt *stmt);
  
  extern void EnableDisableTrigger(Relation rel, const char *tgname,
                                         char fires_when, bool skip_system);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to