On Thu, Dec 15, 2011 at 07:04:20PM -0500, Robert Haas wrote:
> On Fri, Dec 9, 2011 at 5:41 PM, Noah Misch <[email protected]> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers