refactor ALTER some-obj SET OWNER implementation
Remove duplicate implementation of catalog munging and miscellaneous privilege and consistency checks. Instead rely on already existing data in objectaddress.c to do the work. Author: KaiGai Kohei Tweaked by me Reviewed by Robert Haas
This commit is contained in:
parent
1f91c8ca1d
commit
994c36e01d
|
@ -139,108 +139,6 @@ LargeObjectDrop(Oid loid)
|
|||
heap_close(pg_lo_meta, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* LargeObjectAlterOwner
|
||||
*
|
||||
* Implementation of ALTER LARGE OBJECT statement
|
||||
*/
|
||||
void
|
||||
LargeObjectAlterOwner(Oid loid, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_largeobject_metadata form_lo_meta;
|
||||
Relation pg_lo_meta;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc scan;
|
||||
HeapTuple oldtup;
|
||||
HeapTuple newtup;
|
||||
|
||||
pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
|
||||
RowExclusiveLock);
|
||||
|
||||
ScanKeyInit(&skey[0],
|
||||
ObjectIdAttributeNumber,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(loid));
|
||||
|
||||
scan = systable_beginscan(pg_lo_meta,
|
||||
LargeObjectMetadataOidIndexId, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
oldtup = systable_getnext(scan);
|
||||
if (!HeapTupleIsValid(oldtup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("large object %u does not exist", loid)));
|
||||
|
||||
form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(oldtup);
|
||||
if (form_lo_meta->lomowner != newOwnerId)
|
||||
{
|
||||
Datum values[Natts_pg_largeobject_metadata];
|
||||
bool nulls[Natts_pg_largeobject_metadata];
|
||||
bool replaces[Natts_pg_largeobject_metadata];
|
||||
Acl *newAcl;
|
||||
Datum aclDatum;
|
||||
bool isnull;
|
||||
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/*
|
||||
* lo_compat_privileges is not checked here, because ALTER LARGE
|
||||
* OBJECT ... OWNER did not exist at all prior to PostgreSQL 9.0.
|
||||
*
|
||||
* We must be the owner of the existing object.
|
||||
*/
|
||||
if (!pg_largeobject_ownercheck(loid, GetUserId()))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||
errmsg("must be owner of large object %u", loid)));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
}
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(nulls, false, sizeof(nulls));
|
||||
memset(replaces, false, sizeof(nulls));
|
||||
|
||||
values[Anum_pg_largeobject_metadata_lomowner - 1]
|
||||
= ObjectIdGetDatum(newOwnerId);
|
||||
replaces[Anum_pg_largeobject_metadata_lomowner - 1] = true;
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = heap_getattr(oldtup,
|
||||
Anum_pg_largeobject_metadata_lomacl,
|
||||
RelationGetDescr(pg_lo_meta), &isnull);
|
||||
if (!isnull)
|
||||
{
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum),
|
||||
form_lo_meta->lomowner, newOwnerId);
|
||||
values[Anum_pg_largeobject_metadata_lomacl - 1]
|
||||
= PointerGetDatum(newAcl);
|
||||
replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
|
||||
}
|
||||
|
||||
newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_lo_meta),
|
||||
values, nulls, replaces);
|
||||
|
||||
simple_heap_update(pg_lo_meta, &newtup->t_self, newtup);
|
||||
CatalogUpdateIndexes(pg_lo_meta, newtup);
|
||||
|
||||
heap_freetuple(newtup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(LargeObjectRelationId,
|
||||
loid, newOwnerId);
|
||||
}
|
||||
systable_endscan(scan);
|
||||
|
||||
heap_close(pg_lo_meta, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* LargeObjectExists
|
||||
*
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "catalog/pg_foreign_server.h"
|
||||
#include "catalog/pg_language.h"
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "catalog/pg_largeobject_metadata.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
|
@ -40,6 +41,7 @@
|
|||
#include "catalog/pg_shdepend.h"
|
||||
#include "catalog/pg_tablespace.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "commands/alter.h"
|
||||
#include "commands/dbcommands.h"
|
||||
#include "commands/collationcmds.h"
|
||||
#include "commands/conversioncmds.h"
|
||||
|
@ -1335,22 +1337,10 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||
/* Issue the appropriate ALTER OWNER call */
|
||||
switch (sdepForm->classid)
|
||||
{
|
||||
case CollationRelationId:
|
||||
AlterCollationOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case ConversionRelationId:
|
||||
AlterConversionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case TypeRelationId:
|
||||
AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
|
||||
break;
|
||||
|
||||
case OperatorRelationId:
|
||||
AlterOperatorOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case NamespaceRelationId:
|
||||
AlterSchemaOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
@ -1365,18 +1355,6 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||
ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
|
||||
break;
|
||||
|
||||
case ProcedureRelationId:
|
||||
AlterFunctionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case LanguageRelationId:
|
||||
AlterLanguageOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case LargeObjectRelationId:
|
||||
LargeObjectAlterOwner(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case DefaultAclRelationId:
|
||||
|
||||
/*
|
||||
|
@ -1385,14 +1363,6 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||
*/
|
||||
break;
|
||||
|
||||
case OperatorClassRelationId:
|
||||
AlterOpClassOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case OperatorFamilyRelationId:
|
||||
AlterOpFamilyOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case ForeignServerRelationId:
|
||||
AlterForeignServerOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
@ -1401,14 +1371,36 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||
AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case ExtensionRelationId:
|
||||
AlterExtensionOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
case EventTriggerRelationId:
|
||||
AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
|
||||
break;
|
||||
|
||||
/* Generic alter owner cases */
|
||||
case CollationRelationId:
|
||||
case ConversionRelationId:
|
||||
case OperatorRelationId:
|
||||
case ProcedureRelationId:
|
||||
case LanguageRelationId:
|
||||
case LargeObjectRelationId:
|
||||
case OperatorFamilyRelationId:
|
||||
case OperatorClassRelationId:
|
||||
case ExtensionRelationId:
|
||||
{
|
||||
Oid classId = sdepForm->classid;
|
||||
Relation catalog;
|
||||
|
||||
if (classId == LargeObjectRelationId)
|
||||
classId = LargeObjectMetadataRelationId;
|
||||
|
||||
catalog = heap_open(classId, RowExclusiveLock);
|
||||
|
||||
AlterObjectOwner_internal(catalog, sdepForm->objid,
|
||||
newrole);
|
||||
|
||||
heap_close(catalog, NoLock);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unexpected classid %u", sdepForm->classid);
|
||||
break;
|
||||
|
|
|
@ -267,18 +267,3 @@ RenameAggregate(List *name, List *args, const char *newname)
|
|||
heap_close(rel, NoLock);
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change aggregate owner
|
||||
*/
|
||||
void
|
||||
AlterAggregateOwner(List *name, List *args, Oid newOwnerId)
|
||||
{
|
||||
Oid procOid;
|
||||
|
||||
/* Look up function and make sure it's an aggregate */
|
||||
procOid = LookupAggNameTypeNames(name, args, false);
|
||||
|
||||
/* The rest is just like a function */
|
||||
AlterFunctionOwner_oid(procOid, newOwnerId);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
#include "postgres.h"
|
||||
|
||||
#include "access/htup_details.h"
|
||||
#include "access/sysattr.h"
|
||||
#include "catalog/dependency.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_largeobject.h"
|
||||
#include "catalog/pg_largeobject_metadata.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "commands/alter.h"
|
||||
#include "commands/collationcmds.h"
|
||||
|
@ -37,9 +39,11 @@
|
|||
#include "miscadmin.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -446,71 +450,19 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
|||
|
||||
switch (stmt->objectType)
|
||||
{
|
||||
case OBJECT_AGGREGATE:
|
||||
AlterAggregateOwner(stmt->object, stmt->objarg, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_COLLATION:
|
||||
AlterCollationOwner(stmt->object, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_CONVERSION:
|
||||
AlterConversionOwner(stmt->object, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_DATABASE:
|
||||
AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_FUNCTION:
|
||||
AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_LANGUAGE:
|
||||
AlterLanguageOwner(strVal(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_LARGEOBJECT:
|
||||
LargeObjectAlterOwner(oidparse(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_OPERATOR:
|
||||
Assert(list_length(stmt->objarg) == 2);
|
||||
AlterOperatorOwner(stmt->object,
|
||||
(TypeName *) linitial(stmt->objarg),
|
||||
(TypeName *) lsecond(stmt->objarg),
|
||||
newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_OPCLASS:
|
||||
AlterOpClassOwner(stmt->object, stmt->addname, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_OPFAMILY:
|
||||
AlterOpFamilyOwner(stmt->object, stmt->addname, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_SCHEMA:
|
||||
AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_TABLESPACE:
|
||||
AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_TYPE:
|
||||
case OBJECT_DOMAIN: /* same as TYPE */
|
||||
AlterTypeOwner(stmt->object, newowner, stmt->objectType);
|
||||
break;
|
||||
|
||||
case OBJECT_TSDICTIONARY:
|
||||
AlterTSDictionaryOwner(stmt->object, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_TSCONFIGURATION:
|
||||
AlterTSConfigurationOwner(stmt->object, newowner);
|
||||
break;
|
||||
|
||||
case OBJECT_FDW:
|
||||
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
|
||||
newowner);
|
||||
|
@ -524,8 +476,240 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
|||
AlterEventTriggerOwner(strVal(linitial(stmt->object)), newowner);
|
||||
break;
|
||||
|
||||
/* Generic cases */
|
||||
case OBJECT_AGGREGATE:
|
||||
case OBJECT_COLLATION:
|
||||
case OBJECT_CONVERSION:
|
||||
case OBJECT_FUNCTION:
|
||||
case OBJECT_LANGUAGE:
|
||||
case OBJECT_LARGEOBJECT:
|
||||
case OBJECT_OPERATOR:
|
||||
case OBJECT_OPCLASS:
|
||||
case OBJECT_OPFAMILY:
|
||||
case OBJECT_TABLESPACE:
|
||||
case OBJECT_TSDICTIONARY:
|
||||
case OBJECT_TSCONFIGURATION:
|
||||
{
|
||||
Relation catalog;
|
||||
Relation relation;
|
||||
Oid classId;
|
||||
ObjectAddress address;
|
||||
|
||||
address = get_object_address(stmt->objectType,
|
||||
stmt->object,
|
||||
stmt->objarg,
|
||||
&relation,
|
||||
AccessExclusiveLock,
|
||||
false);
|
||||
Assert(relation == NULL);
|
||||
classId = address.classId;
|
||||
|
||||
/*
|
||||
* XXX - get_object_address returns Oid of pg_largeobject
|
||||
* catalog for OBJECT_LARGEOBJECT because of historical
|
||||
* reasons. Fix up it here.
|
||||
*/
|
||||
if (classId == LargeObjectRelationId)
|
||||
classId = LargeObjectMetadataRelationId;
|
||||
|
||||
catalog = heap_open(classId, RowExclusiveLock);
|
||||
|
||||
AlterObjectOwner_internal(catalog, address.objectId, newowner);
|
||||
heap_close(catalog, RowExclusiveLock);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
|
||||
(int) stmt->objectType);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a copy of the tuple for the object with the given object OID, from
|
||||
* the given catalog (which must have been opened by the caller and suitably
|
||||
* locked). NULL is returned if the OID is not found.
|
||||
*
|
||||
* We try a syscache first, if available.
|
||||
*
|
||||
* XXX this function seems general in possible usage. Given sufficient callers
|
||||
* elsewhere, we should consider moving it to a more appropriate place.
|
||||
*/
|
||||
static HeapTuple
|
||||
get_catalog_object_by_oid(Relation catalog, Oid objectId)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
Oid classId = RelationGetRelid(catalog);
|
||||
int oidCacheId = get_object_catcache_oid(classId);
|
||||
|
||||
if (oidCacheId > 0)
|
||||
{
|
||||
tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
|
||||
if (!HeapTupleIsValid(tuple)) /* should not happen */
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Oid oidIndexId = get_object_oid_index(classId);
|
||||
SysScanDesc scan;
|
||||
ScanKeyData skey;
|
||||
|
||||
Assert(OidIsValid(oidIndexId));
|
||||
|
||||
ScanKeyInit(&skey,
|
||||
ObjectIdAttributeNumber,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(objectId));
|
||||
|
||||
scan = systable_beginscan(catalog, oidIndexId, true,
|
||||
SnapshotNow, 1, &skey);
|
||||
tuple = systable_getnext(scan);
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
{
|
||||
systable_endscan(scan);
|
||||
return NULL;
|
||||
}
|
||||
tuple = heap_copytuple(tuple);
|
||||
|
||||
systable_endscan(scan);
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic function to change the ownership of a given object, for simple
|
||||
* cases (won't work for tables, nor other cases where we need to do more than
|
||||
* change the ownership column of a single catalog entry).
|
||||
*
|
||||
* rel: catalog relation containing object (RowExclusiveLock'd by caller)
|
||||
* objectId: OID of object to change the ownership of
|
||||
* new_ownerId: OID of new object owner
|
||||
*/
|
||||
void
|
||||
AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
|
||||
{
|
||||
Oid classId = RelationGetRelid(rel);
|
||||
AttrNumber Anum_owner = get_object_attnum_owner(classId);
|
||||
AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
|
||||
AttrNumber Anum_acl = get_object_attnum_acl(classId);
|
||||
AttrNumber Anum_name = get_object_attnum_name(classId);
|
||||
HeapTuple oldtup;
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
Oid old_ownerId;
|
||||
Oid namespaceId = InvalidOid;
|
||||
|
||||
oldtup = get_catalog_object_by_oid(rel, objectId);
|
||||
if (oldtup == NULL)
|
||||
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
|
||||
objectId, RelationGetRelationName(rel));
|
||||
|
||||
datum = heap_getattr(oldtup, Anum_owner,
|
||||
RelationGetDescr(rel), &isnull);
|
||||
Assert(!isnull);
|
||||
old_ownerId = DatumGetObjectId(datum);
|
||||
|
||||
if (Anum_namespace != InvalidAttrNumber)
|
||||
{
|
||||
datum = heap_getattr(oldtup, Anum_namespace,
|
||||
RelationGetDescr(rel), &isnull);
|
||||
Assert(!isnull);
|
||||
namespaceId = DatumGetObjectId(datum);
|
||||
}
|
||||
|
||||
if (old_ownerId != new_ownerId)
|
||||
{
|
||||
AttrNumber nattrs;
|
||||
HeapTuple newtup;
|
||||
Datum *values;
|
||||
bool *nulls;
|
||||
bool *replaces;
|
||||
|
||||
/* Superusers can bypass permission checks */
|
||||
if (!superuser())
|
||||
{
|
||||
AclObjectKind aclkind = get_object_aclkind(classId);
|
||||
|
||||
/* must be owner */
|
||||
if (!has_privs_of_role(GetUserId(), old_ownerId))
|
||||
{
|
||||
char *objname;
|
||||
char namebuf[NAMEDATALEN];
|
||||
|
||||
if (Anum_name != InvalidAttrNumber)
|
||||
{
|
||||
datum = heap_getattr(oldtup, Anum_name,
|
||||
RelationGetDescr(rel), &isnull);
|
||||
Assert(!isnull);
|
||||
objname = NameStr(*DatumGetName(datum));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(namebuf, sizeof(namebuf), "%u",
|
||||
HeapTupleGetOid(oldtup));
|
||||
objname = namebuf;
|
||||
}
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, aclkind, objname);
|
||||
}
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), new_ownerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
if (OidIsValid(namespaceId))
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, aclkind,
|
||||
get_namespace_name(namespaceId));
|
||||
}
|
||||
}
|
||||
|
||||
/* Build a modified tuple */
|
||||
nattrs = RelationGetNumberOfAttributes(rel);
|
||||
values = palloc0(nattrs * sizeof(Datum));
|
||||
nulls = palloc0(nattrs * sizeof(bool));
|
||||
replaces = palloc0(nattrs * sizeof(bool));
|
||||
values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
|
||||
replaces[Anum_owner - 1] = true;
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
if (Anum_acl != InvalidAttrNumber)
|
||||
{
|
||||
datum = heap_getattr(oldtup,
|
||||
Anum_acl, RelationGetDescr(rel), &isnull);
|
||||
if (!isnull)
|
||||
{
|
||||
Acl *newAcl;
|
||||
|
||||
newAcl = aclnewowner(DatumGetAclP(datum),
|
||||
old_ownerId, new_ownerId);
|
||||
values[Anum_acl - 1] = PointerGetDatum(newAcl);
|
||||
replaces[Anum_acl - 1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
|
||||
values, nulls, replaces);
|
||||
|
||||
/* Perform actual update */
|
||||
simple_heap_update(rel, &newtup->t_self, newtup);
|
||||
CatalogUpdateIndexes(rel, newtup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
if (classId == LargeObjectMetadataRelationId)
|
||||
classId = LargeObjectRelationId;
|
||||
changeDependencyOnOwner(classId, HeapTupleGetOid(newtup), new_ownerId);
|
||||
|
||||
/* Release memory */
|
||||
pfree(values);
|
||||
pfree(nulls);
|
||||
pfree(replaces);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static void AlterCollationOwner_internal(Relation rel, Oid collationOid,
|
||||
Oid newOwnerId);
|
||||
|
||||
/*
|
||||
* CREATE COLLATION
|
||||
*/
|
||||
|
@ -211,104 +208,6 @@ RenameCollation(List *name, const char *newname)
|
|||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change collation owner, by name
|
||||
*/
|
||||
void
|
||||
AlterCollationOwner(List *name, Oid newOwnerId)
|
||||
{
|
||||
Oid collationOid;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(CollationRelationId, RowExclusiveLock);
|
||||
|
||||
collationOid = get_collation_oid(name, false);
|
||||
|
||||
AlterCollationOwner_internal(rel, collationOid, newOwnerId);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change collation owner, by oid
|
||||
*/
|
||||
void
|
||||
AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(CollationRelationId, RowExclusiveLock);
|
||||
|
||||
AlterCollationOwner_internal(rel, collationOid, newOwnerId);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* AlterCollationOwner_internal
|
||||
*
|
||||
* Internal routine for changing the owner. rel must be pg_collation, already
|
||||
* open and suitably locked; it will not be closed.
|
||||
*/
|
||||
static void
|
||||
AlterCollationOwner_internal(Relation rel, Oid collationOid, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_collation collForm;
|
||||
HeapTuple tup;
|
||||
|
||||
Assert(RelationGetRelid(rel) == CollationRelationId);
|
||||
|
||||
tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collationOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for collation %u", collationOid);
|
||||
|
||||
collForm = (Form_pg_collation) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (collForm->collowner != newOwnerId)
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_collation_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
|
||||
NameStr(collForm->collname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(collForm->collnamespace,
|
||||
newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(collForm->collnamespace));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
collForm->collowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(CollationRelationId, collationOid,
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute ALTER COLLATION SET SCHEMA
|
||||
*/
|
||||
|
|
|
@ -31,9 +31,6 @@
|
|||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
|
||||
Oid newOwnerId);
|
||||
|
||||
/*
|
||||
* CREATE CONVERSION
|
||||
*/
|
||||
|
@ -168,101 +165,3 @@ RenameConversion(List *name, const char *newname)
|
|||
heap_close(rel, NoLock);
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change conversion owner, by name
|
||||
*/
|
||||
void
|
||||
AlterConversionOwner(List *name, Oid newOwnerId)
|
||||
{
|
||||
Oid conversionOid;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
||||
|
||||
conversionOid = get_conversion_oid(name, false);
|
||||
|
||||
AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change conversion owner, by oid
|
||||
*/
|
||||
void
|
||||
AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(ConversionRelationId, RowExclusiveLock);
|
||||
|
||||
AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* AlterConversionOwner_internal
|
||||
*
|
||||
* Internal routine for changing the owner. rel must be pg_conversion, already
|
||||
* open and suitably locked; it will not be closed.
|
||||
*/
|
||||
static void
|
||||
AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_conversion convForm;
|
||||
HeapTuple tup;
|
||||
|
||||
Assert(RelationGetRelid(rel) == ConversionRelationId);
|
||||
|
||||
tup = SearchSysCacheCopy1(CONVOID, ObjectIdGetDatum(conversionOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
|
||||
|
||||
convForm = (Form_pg_conversion) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (convForm->conowner != newOwnerId)
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
|
||||
NameStr(convForm->conname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(convForm->connamespace,
|
||||
newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(convForm->connamespace));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
convForm->conowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(ConversionRelationId, conversionOid,
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
|
|
@ -2750,95 +2750,3 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
|
|||
if (relation != NULL)
|
||||
relation_close(relation, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* AlterExtensionOwner_internal
|
||||
*
|
||||
* Internal routine for changing the owner of an extension. rel must be
|
||||
* pg_extension, already open and suitably locked; it will not be closed.
|
||||
*
|
||||
* Note that this only changes ownership of the extension itself; it doesn't
|
||||
* change the ownership of objects it contains. Since this function is
|
||||
* currently only called from REASSIGN OWNED, this restriction is okay because
|
||||
* said objects would also be affected by our caller. But it's not enough for
|
||||
* a full-fledged ALTER OWNER implementation, so beware.
|
||||
*/
|
||||
static void
|
||||
AlterExtensionOwner_internal(Relation rel, Oid extensionOid, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_extension extForm;
|
||||
HeapTuple tup;
|
||||
SysScanDesc scandesc;
|
||||
ScanKeyData entry[1];
|
||||
|
||||
Assert(RelationGetRelid(rel) == ExtensionRelationId);
|
||||
|
||||
ScanKeyInit(&entry[0],
|
||||
ObjectIdAttributeNumber,
|
||||
BTEqualStrategyNumber, F_OIDEQ,
|
||||
ObjectIdGetDatum(extensionOid));
|
||||
|
||||
scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
|
||||
SnapshotNow, 1, entry);
|
||||
|
||||
/* We assume that there can be at most one matching tuple */
|
||||
tup = systable_getnext(scandesc);
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for extension %u", extensionOid);
|
||||
|
||||
tup = heap_copytuple(tup);
|
||||
systable_endscan(scandesc);
|
||||
|
||||
extForm = (Form_pg_extension) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (extForm->extowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_extension_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
|
||||
NameStr(extForm->extname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* no privilege checks on namespace are required */
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
extForm->extowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(ExtensionRelationId, extensionOid,
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change extension owner, by OID
|
||||
*/
|
||||
void
|
||||
AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(ExtensionRelationId, RowExclusiveLock);
|
||||
|
||||
AlterExtensionOwner_internal(rel, extensionOid, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
|
|
@ -66,11 +66,6 @@
|
|||
#include "utils/syscache.h"
|
||||
#include "utils/tqual.h"
|
||||
|
||||
|
||||
static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
|
||||
Oid newOwnerId);
|
||||
|
||||
|
||||
/*
|
||||
* Examine the RETURNS clause of the CREATE FUNCTION statement
|
||||
* and return information about it as *prorettype_p and *returnsSet.
|
||||
|
@ -1109,138 +1104,6 @@ RenameFunction(List *name, List *argtypes, const char *newname)
|
|||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change function owner by name and args
|
||||
*/
|
||||
void
|
||||
AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
Oid procOid;
|
||||
HeapTuple tup;
|
||||
|
||||
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||
|
||||
procOid = LookupFuncNameTypeNames(name, argtypes, false);
|
||||
|
||||
tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for function %u", procOid);
|
||||
|
||||
if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||
errmsg("\"%s\" is an aggregate function",
|
||||
NameListToString(name)),
|
||||
errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
|
||||
|
||||
AlterFunctionOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change function owner by Oid
|
||||
*/
|
||||
void
|
||||
AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
|
||||
rel = heap_open(ProcedureRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for function %u", procOid);
|
||||
AlterFunctionOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
static void
|
||||
AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_proc procForm;
|
||||
AclResult aclresult;
|
||||
Oid procOid;
|
||||
|
||||
Assert(RelationGetRelid(rel) == ProcedureRelationId);
|
||||
Assert(tup->t_tableOid == ProcedureRelationId);
|
||||
|
||||
procForm = (Form_pg_proc) GETSTRUCT(tup);
|
||||
procOid = HeapTupleGetOid(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (procForm->proowner != newOwnerId)
|
||||
{
|
||||
Datum repl_val[Natts_pg_proc];
|
||||
bool repl_null[Natts_pg_proc];
|
||||
bool repl_repl[Natts_pg_proc];
|
||||
Acl *newAcl;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
HeapTuple newtuple;
|
||||
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_proc_ownercheck(procOid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
||||
NameStr(procForm->proname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(procForm->pronamespace,
|
||||
newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(procForm->pronamespace));
|
||||
}
|
||||
|
||||
memset(repl_null, false, sizeof(repl_null));
|
||||
memset(repl_repl, false, sizeof(repl_repl));
|
||||
|
||||
repl_repl[Anum_pg_proc_proowner - 1] = true;
|
||||
repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId);
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = SysCacheGetAttr(PROCOID, tup,
|
||||
Anum_pg_proc_proacl,
|
||||
&isNull);
|
||||
if (!isNull)
|
||||
{
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum),
|
||||
procForm->proowner, newOwnerId);
|
||||
repl_repl[Anum_pg_proc_proacl - 1] = true;
|
||||
repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
|
||||
}
|
||||
|
||||
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
|
||||
repl_null, repl_repl);
|
||||
|
||||
simple_heap_update(rel, &newtuple->t_self, newtuple);
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId);
|
||||
}
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implements the ALTER FUNCTION utility command (except for the
|
||||
* RENAME and OWNER clauses, which are handled as part of the generic
|
||||
|
|
|
@ -81,11 +81,6 @@ static void dropOperators(List *opfamilyname, Oid amoid, Oid opfamilyoid,
|
|||
List *operators);
|
||||
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid,
|
||||
List *procedures);
|
||||
static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple,
|
||||
Oid newOwnerId);
|
||||
static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple,
|
||||
Oid newOwnerId);
|
||||
|
||||
|
||||
/*
|
||||
* OpFamilyCacheLookup
|
||||
|
@ -1809,249 +1804,6 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
|
|||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change opclass owner by name
|
||||
*/
|
||||
void
|
||||
AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
|
||||
{
|
||||
Oid amOid;
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
HeapTuple origtup;
|
||||
|
||||
amOid = get_am_oid(access_method, false);
|
||||
|
||||
rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
|
||||
|
||||
/* Look up the opclass. */
|
||||
origtup = OpClassCacheLookup(amOid, name, false);
|
||||
tup = heap_copytuple(origtup);
|
||||
ReleaseSysCache(origtup);
|
||||
|
||||
AlterOpClassOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change operator class owner, specified by OID
|
||||
*/
|
||||
void
|
||||
AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCacheCopy1(CLAOID, ObjectIdGetDatum(opclassOid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
|
||||
|
||||
AlterOpClassOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The first parameter is pg_opclass, opened and suitably locked. The second
|
||||
* parameter is a copy of the tuple from pg_opclass we want to modify.
|
||||
*/
|
||||
static void
|
||||
AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
|
||||
{
|
||||
Oid namespaceOid;
|
||||
AclResult aclresult;
|
||||
Form_pg_opclass opcForm;
|
||||
|
||||
Assert(tup->t_tableOid == OperatorClassRelationId);
|
||||
Assert(RelationGetRelid(rel) == OperatorClassRelationId);
|
||||
|
||||
opcForm = (Form_pg_opclass) GETSTRUCT(tup);
|
||||
|
||||
namespaceOid = opcForm->opcnamespace;
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (opcForm->opcowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_opclass_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
|
||||
NameStr(opcForm->opcname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(namespaceOid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
opcForm->opcowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(OperatorClassRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Change opfamily owner by name
|
||||
*/
|
||||
void
|
||||
AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId)
|
||||
{
|
||||
Oid amOid;
|
||||
Relation rel;
|
||||
HeapTuple tup;
|
||||
char *opfname;
|
||||
char *schemaname;
|
||||
|
||||
amOid = get_am_oid(access_method, false);
|
||||
|
||||
rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
|
||||
|
||||
/*
|
||||
* Look up the opfamily
|
||||
*/
|
||||
DeconstructQualifiedName(name, &schemaname, &opfname);
|
||||
|
||||
if (schemaname)
|
||||
{
|
||||
Oid namespaceOid;
|
||||
|
||||
namespaceOid = LookupExplicitNamespace(schemaname);
|
||||
|
||||
tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
|
||||
ObjectIdGetDatum(amOid),
|
||||
PointerGetDatum(opfname),
|
||||
ObjectIdGetDatum(namespaceOid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator family \"%s\" does not exist for access method \"%s\"",
|
||||
opfname, access_method)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Oid opfOid;
|
||||
|
||||
opfOid = OpfamilynameGetOpfid(amOid, opfname);
|
||||
if (!OidIsValid(opfOid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("operator family \"%s\" does not exist for access method \"%s\"",
|
||||
opfname, access_method)));
|
||||
|
||||
tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for opfamily %u", opfOid);
|
||||
}
|
||||
|
||||
AlterOpFamilyOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change operator family owner, specified by OID
|
||||
*/
|
||||
void
|
||||
AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
|
||||
|
||||
AlterOpFamilyOwner_internal(rel, tup, newOwnerId);
|
||||
|
||||
heap_freetuple(tup);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* The first parameter is pg_opfamily, opened and suitably locked. The second
|
||||
* parameter is a copy of the tuple from pg_opfamily we want to modify.
|
||||
*/
|
||||
static void
|
||||
AlterOpFamilyOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
|
||||
{
|
||||
Oid namespaceOid;
|
||||
AclResult aclresult;
|
||||
Form_pg_opfamily opfForm;
|
||||
|
||||
Assert(tup->t_tableOid == OperatorFamilyRelationId);
|
||||
Assert(RelationGetRelid(rel) == OperatorFamilyRelationId);
|
||||
|
||||
opfForm = (Form_pg_opfamily) GETSTRUCT(tup);
|
||||
|
||||
namespaceOid = opfForm->opfnamespace;
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (opfForm->opfowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_opfamily_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
|
||||
NameStr(opfForm->opfname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(namespaceOid));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
opfForm->opfowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(OperatorFamilyRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_am_oid - given an access method name, look up the OID
|
||||
*
|
||||
|
|
|
@ -51,9 +51,6 @@
|
|||
#include "utils/rel.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
static void AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId);
|
||||
|
||||
/*
|
||||
* DefineOperator
|
||||
* this function extracts all the information from the
|
||||
|
@ -333,93 +330,3 @@ RemoveOperatorById(Oid operOid)
|
|||
|
||||
heap_close(relation, RowExclusiveLock);
|
||||
}
|
||||
|
||||
void
|
||||
AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(OperatorRelationId, RowExclusiveLock);
|
||||
|
||||
AlterOperatorOwner_internal(rel, operOid, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* change operator owner
|
||||
*/
|
||||
void
|
||||
AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
|
||||
Oid newOwnerId)
|
||||
{
|
||||
Oid operOid;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(OperatorRelationId, RowExclusiveLock);
|
||||
|
||||
operOid = LookupOperNameTypeNames(NULL, name,
|
||||
typeName1, typeName2,
|
||||
false, -1);
|
||||
|
||||
AlterOperatorOwner_internal(rel, operOid, newOwnerId);
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
static void
|
||||
AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
AclResult aclresult;
|
||||
Form_pg_operator oprForm;
|
||||
|
||||
Assert(RelationGetRelid(rel) == OperatorRelationId);
|
||||
|
||||
tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(operOid));
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for operator %u", operOid);
|
||||
|
||||
oprForm = (Form_pg_operator) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (oprForm->oprowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_oper_ownercheck(operOid, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
|
||||
NameStr(oprForm->oprname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(oprForm->oprnamespace,
|
||||
newOwnerId,
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(oprForm->oprnamespace));
|
||||
}
|
||||
|
||||
/*
|
||||
* Modify the owner --- okay to scribble on tup because it's a copy
|
||||
*/
|
||||
oprForm->oprowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(OperatorRelationId, operOid, newOwnerId);
|
||||
}
|
||||
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
|
|
@ -55,9 +55,6 @@ static void create_proc_lang(const char *languageName, bool replace,
|
|||
Oid languageOwner, Oid handlerOid, Oid inlineOid,
|
||||
Oid valOid, bool trusted);
|
||||
static PLTemplate *find_language_template(const char *languageName);
|
||||
static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
|
||||
Oid newOwnerId);
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* CREATE PROCEDURAL LANGUAGE
|
||||
|
@ -574,120 +571,6 @@ RenameLanguage(const char *oldname, const char *newname)
|
|||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change language owner
|
||||
*/
|
||||
void
|
||||
AlterLanguageOwner(const char *name, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(LanguageRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCache1(LANGNAME, CStringGetDatum(name));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("language \"%s\" does not exist", name)));
|
||||
|
||||
AlterLanguageOwner_internal(tup, rel, newOwnerId);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Change language owner, specified by OID
|
||||
*/
|
||||
void
|
||||
AlterLanguageOwner_oid(Oid oid, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
|
||||
rel = heap_open(LanguageRelationId, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCache1(LANGOID, ObjectIdGetDatum(oid));
|
||||
if (!HeapTupleIsValid(tup))
|
||||
elog(ERROR, "cache lookup failed for language %u", oid);
|
||||
|
||||
AlterLanguageOwner_internal(tup, rel, newOwnerId);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
||||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Workhorse for AlterLanguageOwner variants
|
||||
*/
|
||||
static void
|
||||
AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
|
||||
{
|
||||
Form_pg_language lanForm;
|
||||
|
||||
lanForm = (Form_pg_language) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (lanForm->lanowner != newOwnerId)
|
||||
{
|
||||
Datum repl_val[Natts_pg_language];
|
||||
bool repl_null[Natts_pg_language];
|
||||
bool repl_repl[Natts_pg_language];
|
||||
Acl *newAcl;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
HeapTuple newtuple;
|
||||
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
|
||||
NameStr(lanForm->lanname));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
memset(repl_null, false, sizeof(repl_null));
|
||||
memset(repl_repl, false, sizeof(repl_repl));
|
||||
|
||||
repl_repl[Anum_pg_language_lanowner - 1] = true;
|
||||
repl_val[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(newOwnerId);
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = SysCacheGetAttr(LANGNAME, tup,
|
||||
Anum_pg_language_lanacl,
|
||||
&isNull);
|
||||
if (!isNull)
|
||||
{
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum),
|
||||
lanForm->lanowner, newOwnerId);
|
||||
repl_repl[Anum_pg_language_lanacl - 1] = true;
|
||||
repl_val[Anum_pg_language_lanacl - 1] = PointerGetDatum(newAcl);
|
||||
}
|
||||
|
||||
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
|
||||
repl_val, repl_null, repl_repl);
|
||||
|
||||
simple_heap_update(rel, &newtuple->t_self, newtuple);
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(LanguageRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_language_oid - given a language name, look up the OID
|
||||
*
|
||||
|
|
|
@ -883,105 +883,6 @@ RenameTableSpace(const char *oldname, const char *newname)
|
|||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change tablespace owner
|
||||
*/
|
||||
void
|
||||
AlterTableSpaceOwner(const char *name, Oid newOwnerId)
|
||||
{
|
||||
Relation rel;
|
||||
ScanKeyData entry[1];
|
||||
HeapScanDesc scandesc;
|
||||
Form_pg_tablespace spcForm;
|
||||
HeapTuple tup;
|
||||
|
||||
/* Search pg_tablespace */
|
||||
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
|
||||
|
||||
ScanKeyInit(&entry[0],
|
||||
Anum_pg_tablespace_spcname,
|
||||
BTEqualStrategyNumber, F_NAMEEQ,
|
||||
CStringGetDatum(name));
|
||||
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
|
||||
tup = heap_getnext(scandesc, ForwardScanDirection);
|
||||
if (!HeapTupleIsValid(tup))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("tablespace \"%s\" does not exist", name)));
|
||||
|
||||
spcForm = (Form_pg_tablespace) GETSTRUCT(tup);
|
||||
|
||||
/*
|
||||
* If the new owner is the same as the existing owner, consider the
|
||||
* command to have succeeded. This is for dump restoration purposes.
|
||||
*/
|
||||
if (spcForm->spcowner != newOwnerId)
|
||||
{
|
||||
Datum repl_val[Natts_pg_tablespace];
|
||||
bool repl_null[Natts_pg_tablespace];
|
||||
bool repl_repl[Natts_pg_tablespace];
|
||||
Acl *newAcl;
|
||||
Datum aclDatum;
|
||||
bool isNull;
|
||||
HeapTuple newtuple;
|
||||
|
||||
/* Otherwise, must be owner of the existing object */
|
||||
if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
|
||||
name);
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/*
|
||||
* Normally we would also check for create permissions here, but there
|
||||
* are none for tablespaces so we follow what rename tablespace does
|
||||
* and omit the create permissions check.
|
||||
*
|
||||
* NOTE: Only superusers may create tablespaces to begin with and so
|
||||
* initially only a superuser would be able to change its ownership
|
||||
* anyway.
|
||||
*/
|
||||
|
||||
memset(repl_null, false, sizeof(repl_null));
|
||||
memset(repl_repl, false, sizeof(repl_repl));
|
||||
|
||||
repl_repl[Anum_pg_tablespace_spcowner - 1] = true;
|
||||
repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId);
|
||||
|
||||
/*
|
||||
* Determine the modified ACL for the new owner. This is only
|
||||
* necessary when the ACL is non-null.
|
||||
*/
|
||||
aclDatum = heap_getattr(tup,
|
||||
Anum_pg_tablespace_spcacl,
|
||||
RelationGetDescr(rel),
|
||||
&isNull);
|
||||
if (!isNull)
|
||||
{
|
||||
newAcl = aclnewowner(DatumGetAclP(aclDatum),
|
||||
spcForm->spcowner, newOwnerId);
|
||||
repl_repl[Anum_pg_tablespace_spcacl - 1] = true;
|
||||
repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl);
|
||||
}
|
||||
|
||||
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
|
||||
|
||||
simple_heap_update(rel, &newtuple->t_self, newtuple);
|
||||
CatalogUpdateIndexes(rel, newtuple);
|
||||
|
||||
heap_freetuple(newtuple);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_endscan(scandesc);
|
||||
heap_close(rel, NoLock);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Alter table space options
|
||||
*/
|
||||
|
|
|
@ -716,66 +716,6 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
|
|||
heap_close(rel, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER TEXT SEARCH DICTIONARY OWNER
|
||||
*/
|
||||
void
|
||||
AlterTSDictionaryOwner(List *name, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
Oid dictId;
|
||||
Oid namespaceOid;
|
||||
AclResult aclresult;
|
||||
Form_pg_ts_dict form;
|
||||
|
||||
rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
|
||||
|
||||
dictId = get_ts_dict_oid(name, false);
|
||||
|
||||
tup = SearchSysCacheCopy1(TSDICTOID, ObjectIdGetDatum(dictId));
|
||||
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for text search dictionary %u",
|
||||
dictId);
|
||||
|
||||
form = (Form_pg_ts_dict) GETSTRUCT(tup);
|
||||
namespaceOid = form->dictnamespace;
|
||||
|
||||
if (form->dictowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* must be owner */
|
||||
if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
|
||||
NameListToString(name));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(namespaceOid));
|
||||
}
|
||||
|
||||
form->dictowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(TSDictionaryRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/* ---------------------- TS Template commands -----------------------*/
|
||||
|
||||
/*
|
||||
|
@ -1390,66 +1330,6 @@ RemoveTSConfigurationById(Oid cfgId)
|
|||
heap_close(relMap, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER TEXT SEARCH CONFIGURATION OWNER
|
||||
*/
|
||||
void
|
||||
AlterTSConfigurationOwner(List *name, Oid newOwnerId)
|
||||
{
|
||||
HeapTuple tup;
|
||||
Relation rel;
|
||||
Oid cfgId;
|
||||
AclResult aclresult;
|
||||
Oid namespaceOid;
|
||||
Form_pg_ts_config form;
|
||||
|
||||
rel = heap_open(TSConfigRelationId, RowExclusiveLock);
|
||||
|
||||
cfgId = get_ts_config_oid(name, false);
|
||||
|
||||
tup = SearchSysCacheCopy1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
|
||||
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "cache lookup failed for text search configuration %u",
|
||||
cfgId);
|
||||
|
||||
form = (Form_pg_ts_config) GETSTRUCT(tup);
|
||||
namespaceOid = form->cfgnamespace;
|
||||
|
||||
if (form->cfgowner != newOwnerId)
|
||||
{
|
||||
/* Superusers can always do it */
|
||||
if (!superuser())
|
||||
{
|
||||
/* must be owner */
|
||||
if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
|
||||
NameListToString(name));
|
||||
|
||||
/* Must be able to become new owner */
|
||||
check_is_member_of_role(GetUserId(), newOwnerId);
|
||||
|
||||
/* New owner must have CREATE privilege on namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||
get_namespace_name(namespaceOid));
|
||||
}
|
||||
|
||||
form->cfgowner = newOwnerId;
|
||||
|
||||
simple_heap_update(rel, &tup->t_self, tup);
|
||||
CatalogUpdateIndexes(rel, tup);
|
||||
|
||||
/* Update owner dependency reference */
|
||||
changeDependencyOnOwner(TSConfigRelationId, HeapTupleGetOid(tup),
|
||||
newOwnerId);
|
||||
}
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
heap_freetuple(tup);
|
||||
}
|
||||
|
||||
/*
|
||||
* ALTER TEXT SEARCH CONFIGURATION - main entry point
|
||||
*/
|
||||
|
|
|
@ -2947,7 +2947,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from)
|
|||
COPY_NODE_FIELD(relation);
|
||||
COPY_NODE_FIELD(object);
|
||||
COPY_NODE_FIELD(objarg);
|
||||
COPY_STRING_FIELD(addname);
|
||||
COPY_STRING_FIELD(newowner);
|
||||
|
||||
return newnode;
|
||||
|
|
|
@ -1349,7 +1349,6 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b)
|
|||
COMPARE_NODE_FIELD(relation);
|
||||
COMPARE_NODE_FIELD(object);
|
||||
COMPARE_NODE_FIELD(objarg);
|
||||
COMPARE_STRING_FIELD(addname);
|
||||
COMPARE_STRING_FIELD(newowner);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -7366,7 +7366,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
|
|||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||
n->objectType = OBJECT_OPCLASS;
|
||||
n->object = $4;
|
||||
n->addname = $6;
|
||||
n->objarg = list_make1(makeString($6));
|
||||
n->newowner = $9;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
|
@ -7375,7 +7375,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
|
|||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||
n->objectType = OBJECT_OPFAMILY;
|
||||
n->object = $4;
|
||||
n->addname = $6;
|
||||
n->objarg = list_make1(makeString($6));
|
||||
n->newowner = $9;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ typedef FormData_pg_largeobject *Form_pg_largeobject;
|
|||
|
||||
extern Oid LargeObjectCreate(Oid loid);
|
||||
extern void LargeObjectDrop(Oid loid);
|
||||
extern void LargeObjectAlterOwner(Oid loid, Oid newOwnerId);
|
||||
extern bool LargeObjectExists(Oid loid);
|
||||
|
||||
#endif /* PG_LARGEOBJECT_H */
|
||||
|
|
|
@ -18,9 +18,13 @@
|
|||
#include "utils/relcache.h"
|
||||
|
||||
extern void ExecRenameStmt(RenameStmt *stmt);
|
||||
|
||||
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
|
||||
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
|
||||
extern Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
|
||||
|
||||
extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
|
||||
extern void AlterObjectOwner_internal(Relation catalog, Oid objectId,
|
||||
Oid new_ownerId);
|
||||
|
||||
#endif /* ALTER_H */
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
extern void DefineCollation(List *names, List *parameters);
|
||||
extern void RenameCollation(List *name, const char *newname);
|
||||
extern void AlterCollationOwner(List *name, Oid newOwnerId);
|
||||
extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId);
|
||||
extern void AlterCollationNamespace(List *name, const char *newschema);
|
||||
extern Oid AlterCollationNamespace_oid(Oid collOid, Oid newNspOid);
|
||||
|
||||
|
|
|
@ -19,7 +19,5 @@
|
|||
|
||||
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
|
||||
extern void RenameConversion(List *name, const char *newname);
|
||||
extern void AlterConversionOwner(List *name, Oid newOwnerId);
|
||||
extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
|
||||
|
||||
#endif /* CONVERSIONCMDS_H */
|
||||
|
|
|
@ -47,8 +47,6 @@ extern void RemoveFunctionById(Oid funcOid);
|
|||
extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
||||
extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
|
||||
extern void RenameFunction(List *name, List *argtypes, const char *newname);
|
||||
extern void AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId);
|
||||
extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId);
|
||||
extern void AlterFunction(AlterFunctionStmt *stmt);
|
||||
extern void CreateCast(CreateCastStmt *stmt);
|
||||
extern void DropCastById(Oid castOid);
|
||||
|
@ -61,15 +59,11 @@ extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
|
|||
/* commands/operatorcmds.c */
|
||||
extern void DefineOperator(List *names, List *parameters);
|
||||
extern void RemoveOperatorById(Oid operOid);
|
||||
extern void AlterOperatorOwner(List *name, TypeName *typeName1,
|
||||
TypeName *typename2, Oid newOwnerId);
|
||||
extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
|
||||
|
||||
/* commands/aggregatecmds.c */
|
||||
extern void DefineAggregate(List *name, List *args, bool oldstyle,
|
||||
List *parameters);
|
||||
extern void RenameAggregate(List *name, List *args, const char *newname);
|
||||
extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId);
|
||||
|
||||
/* commands/opclasscmds.c */
|
||||
extern void DefineOpClass(CreateOpClassStmt *stmt);
|
||||
|
@ -81,10 +75,6 @@ extern void RemoveAmOpEntryById(Oid entryOid);
|
|||
extern void RemoveAmProcEntryById(Oid entryOid);
|
||||
extern void RenameOpClass(List *name, const char *access_method, const char *newname);
|
||||
extern void RenameOpFamily(List *name, const char *access_method, const char *newname);
|
||||
extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
|
||||
extern void AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId);
|
||||
extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId);
|
||||
extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId);
|
||||
extern Oid get_am_oid(const char *amname, bool missing_ok);
|
||||
extern Oid get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
|
||||
extern Oid get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
|
||||
|
@ -98,7 +88,6 @@ extern void DefineTSDictionary(List *names, List *parameters);
|
|||
extern void RenameTSDictionary(List *oldname, const char *newname);
|
||||
extern void RemoveTSDictionaryById(Oid dictId);
|
||||
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
|
||||
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
|
||||
|
||||
extern void DefineTSTemplate(List *names, List *parameters);
|
||||
extern void RenameTSTemplate(List *oldname, const char *newname);
|
||||
|
@ -108,7 +97,6 @@ extern void DefineTSConfiguration(List *names, List *parameters);
|
|||
extern void RenameTSConfiguration(List *oldname, const char *newname);
|
||||
extern void RemoveTSConfigurationById(Oid cfgId);
|
||||
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
|
||||
extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
|
||||
|
||||
extern text *serialize_deflist(List *deflist);
|
||||
extern List *deserialize_deflist(Datum txt);
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
|
||||
extern void DropProceduralLanguageById(Oid langOid);
|
||||
extern void RenameLanguage(const char *oldname, const char *newname);
|
||||
extern void AlterLanguageOwner(const char *name, Oid newOwnerId);
|
||||
extern void AlterLanguageOwner_oid(Oid oid, Oid newOwnerId);
|
||||
extern bool PLTemplateExists(const char *languageName);
|
||||
extern Oid get_language_oid(const char *langname, bool missing_ok);
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ typedef struct TableSpaceOpts
|
|||
extern void CreateTableSpace(CreateTableSpaceStmt *stmt);
|
||||
extern void DropTableSpace(DropTableSpaceStmt *stmt);
|
||||
extern void RenameTableSpace(const char *oldname, const char *newname);
|
||||
extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId);
|
||||
extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
|
||||
|
||||
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
||||
|
|
|
@ -2183,7 +2183,6 @@ typedef struct AlterOwnerStmt
|
|||
RangeVar *relation; /* in case it's a table */
|
||||
List *object; /* in case it's some other object */
|
||||
List *objarg; /* argument types, if applicable */
|
||||
char *addname; /* additional name if needed */
|
||||
char *newowner; /* the new owner */
|
||||
} AlterOwnerStmt;
|
||||
|
||||
|
|
Loading…
Reference in New Issue