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
*
#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"
#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"
/* 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;
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:
/*
*/
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;
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;
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);
-}
#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"
#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"
/*
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);
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);
+ }
+}
#include "utils/rel.h"
#include "utils/syscache.h"
-static void AlterCollationOwner_internal(Relation rel, Oid collationOid,
- Oid newOwnerId);
-
/*
* CREATE COLLATION
*/
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
*/
#include "utils/rel.h"
#include "utils/syscache.h"
-static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
- Oid newOwnerId);
-
/*
* CREATE CONVERSION
*/
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);
-}
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);
-}
#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.
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
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
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
*
#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
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);
-}
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
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
*
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
*/
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 -----------------------*/
/*
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
*/
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(object);
COPY_NODE_FIELD(objarg);
- COPY_STRING_FIELD(addname);
COPY_STRING_FIELD(newowner);
return newnode;
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(object);
COMPARE_NODE_FIELD(objarg);
- COMPARE_STRING_FIELD(addname);
COMPARE_STRING_FIELD(newowner);
return true;
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;
}
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;
}
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 */
#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 */
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);
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 */
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);
/* 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);
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);
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);
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);
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);
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);
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;