mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
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:
@ -139,108 +139,6 @@ LargeObjectDrop(Oid loid)
|
|||||||
heap_close(pg_lo_meta, RowExclusiveLock);
|
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
|
* LargeObjectExists
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "catalog/pg_foreign_server.h"
|
#include "catalog/pg_foreign_server.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
|
#include "catalog/pg_largeobject_metadata.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
#include "catalog/pg_operator.h"
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
@ -40,6 +41,7 @@
|
|||||||
#include "catalog/pg_shdepend.h"
|
#include "catalog/pg_shdepend.h"
|
||||||
#include "catalog/pg_tablespace.h"
|
#include "catalog/pg_tablespace.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "commands/alter.h"
|
||||||
#include "commands/dbcommands.h"
|
#include "commands/dbcommands.h"
|
||||||
#include "commands/collationcmds.h"
|
#include "commands/collationcmds.h"
|
||||||
#include "commands/conversioncmds.h"
|
#include "commands/conversioncmds.h"
|
||||||
@ -1335,22 +1337,10 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||||||
/* Issue the appropriate ALTER OWNER call */
|
/* Issue the appropriate ALTER OWNER call */
|
||||||
switch (sdepForm->classid)
|
switch (sdepForm->classid)
|
||||||
{
|
{
|
||||||
case CollationRelationId:
|
|
||||||
AlterCollationOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ConversionRelationId:
|
|
||||||
AlterConversionOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TypeRelationId:
|
case TypeRelationId:
|
||||||
AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
|
AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OperatorRelationId:
|
|
||||||
AlterOperatorOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NamespaceRelationId:
|
case NamespaceRelationId:
|
||||||
AlterSchemaOwner_oid(sdepForm->objid, newrole);
|
AlterSchemaOwner_oid(sdepForm->objid, newrole);
|
||||||
break;
|
break;
|
||||||
@ -1365,18 +1355,6 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||||||
ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
|
ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
|
||||||
break;
|
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:
|
case DefaultAclRelationId:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1385,14 +1363,6 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OperatorClassRelationId:
|
|
||||||
AlterOpClassOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OperatorFamilyRelationId:
|
|
||||||
AlterOpFamilyOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ForeignServerRelationId:
|
case ForeignServerRelationId:
|
||||||
AlterForeignServerOwner_oid(sdepForm->objid, newrole);
|
AlterForeignServerOwner_oid(sdepForm->objid, newrole);
|
||||||
break;
|
break;
|
||||||
@ -1401,14 +1371,36 @@ shdepReassignOwned(List *roleids, Oid newrole)
|
|||||||
AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
|
AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ExtensionRelationId:
|
|
||||||
AlterExtensionOwner_oid(sdepForm->objid, newrole);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EventTriggerRelationId:
|
case EventTriggerRelationId:
|
||||||
AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
|
AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
|
||||||
break;
|
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:
|
default:
|
||||||
elog(ERROR, "unexpected classid %u", sdepForm->classid);
|
elog(ERROR, "unexpected classid %u", sdepForm->classid);
|
||||||
break;
|
break;
|
||||||
|
@ -267,18 +267,3 @@ RenameAggregate(List *name, List *args, const char *newname)
|
|||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
heap_freetuple(tup);
|
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 "postgres.h"
|
||||||
|
|
||||||
#include "access/htup_details.h"
|
#include "access/htup_details.h"
|
||||||
|
#include "access/sysattr.h"
|
||||||
#include "catalog/dependency.h"
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_largeobject.h"
|
#include "catalog/pg_largeobject.h"
|
||||||
|
#include "catalog/pg_largeobject_metadata.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
#include "commands/alter.h"
|
#include "commands/alter.h"
|
||||||
#include "commands/collationcmds.h"
|
#include "commands/collationcmds.h"
|
||||||
@ -37,9 +39,11 @@
|
|||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "utils/tqual.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -446,71 +450,19 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
|||||||
|
|
||||||
switch (stmt->objectType)
|
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:
|
case OBJECT_DATABASE:
|
||||||
AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
|
AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
|
||||||
break;
|
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:
|
case OBJECT_SCHEMA:
|
||||||
AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
|
AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OBJECT_TABLESPACE:
|
|
||||||
AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OBJECT_TYPE:
|
case OBJECT_TYPE:
|
||||||
case OBJECT_DOMAIN: /* same as TYPE */
|
case OBJECT_DOMAIN: /* same as TYPE */
|
||||||
AlterTypeOwner(stmt->object, newowner, stmt->objectType);
|
AlterTypeOwner(stmt->object, newowner, stmt->objectType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OBJECT_TSDICTIONARY:
|
|
||||||
AlterTSDictionaryOwner(stmt->object, newowner);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OBJECT_TSCONFIGURATION:
|
|
||||||
AlterTSConfigurationOwner(stmt->object, newowner);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OBJECT_FDW:
|
case OBJECT_FDW:
|
||||||
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
|
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
|
||||||
newowner);
|
newowner);
|
||||||
@ -524,8 +476,240 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
|
|||||||
AlterEventTriggerOwner(strVal(linitial(stmt->object)), newowner);
|
AlterEventTriggerOwner(strVal(linitial(stmt->object)), newowner);
|
||||||
break;
|
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:
|
default:
|
||||||
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
|
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
|
||||||
(int) stmt->objectType);
|
(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/rel.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
static void AlterCollationOwner_internal(Relation rel, Oid collationOid,
|
|
||||||
Oid newOwnerId);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CREATE COLLATION
|
* CREATE COLLATION
|
||||||
*/
|
*/
|
||||||
@ -211,104 +208,6 @@ RenameCollation(List *name, const char *newname)
|
|||||||
heap_close(rel, RowExclusiveLock);
|
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
|
* Execute ALTER COLLATION SET SCHEMA
|
||||||
*/
|
*/
|
||||||
|
@ -31,9 +31,6 @@
|
|||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
|
|
||||||
Oid newOwnerId);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CREATE CONVERSION
|
* CREATE CONVERSION
|
||||||
*/
|
*/
|
||||||
@ -168,101 +165,3 @@ RenameConversion(List *name, const char *newname)
|
|||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
heap_freetuple(tup);
|
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)
|
if (relation != NULL)
|
||||||
relation_close(relation, NoLock);
|
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/syscache.h"
|
||||||
#include "utils/tqual.h"
|
#include "utils/tqual.h"
|
||||||
|
|
||||||
|
|
||||||
static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
|
|
||||||
Oid newOwnerId);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Examine the RETURNS clause of the CREATE FUNCTION statement
|
* Examine the RETURNS clause of the CREATE FUNCTION statement
|
||||||
* and return information about it as *prorettype_p and *returnsSet.
|
* 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);
|
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
|
* Implements the ALTER FUNCTION utility command (except for the
|
||||||
* RENAME and OWNER clauses, which are handled as part of the generic
|
* 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);
|
List *operators);
|
||||||
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid,
|
static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid,
|
||||||
List *procedures);
|
List *procedures);
|
||||||
static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple,
|
|
||||||
Oid newOwnerId);
|
|
||||||
static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple,
|
|
||||||
Oid newOwnerId);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OpFamilyCacheLookup
|
* OpFamilyCacheLookup
|
||||||
@ -1809,249 +1804,6 @@ RenameOpFamily(List *name, const char *access_method, const char *newname)
|
|||||||
heap_freetuple(tup);
|
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
|
* get_am_oid - given an access method name, look up the OID
|
||||||
*
|
*
|
||||||
|
@ -51,9 +51,6 @@
|
|||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
static void AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DefineOperator
|
* DefineOperator
|
||||||
* this function extracts all the information from the
|
* this function extracts all the information from the
|
||||||
@ -333,93 +330,3 @@ RemoveOperatorById(Oid operOid)
|
|||||||
|
|
||||||
heap_close(relation, RowExclusiveLock);
|
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 languageOwner, Oid handlerOid, Oid inlineOid,
|
||||||
Oid valOid, bool trusted);
|
Oid valOid, bool trusted);
|
||||||
static PLTemplate *find_language_template(const char *languageName);
|
static PLTemplate *find_language_template(const char *languageName);
|
||||||
static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
|
|
||||||
Oid newOwnerId);
|
|
||||||
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------
|
/* ---------------------------------------------------------------------
|
||||||
* CREATE PROCEDURAL LANGUAGE
|
* CREATE PROCEDURAL LANGUAGE
|
||||||
@ -574,120 +571,6 @@ RenameLanguage(const char *oldname, const char *newname)
|
|||||||
heap_freetuple(tup);
|
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
|
* 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);
|
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
|
* Alter table space options
|
||||||
*/
|
*/
|
||||||
|
@ -716,66 +716,6 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
|
|||||||
heap_close(rel, RowExclusiveLock);
|
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 -----------------------*/
|
/* ---------------------- TS Template commands -----------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1390,66 +1330,6 @@ RemoveTSConfigurationById(Oid cfgId)
|
|||||||
heap_close(relMap, RowExclusiveLock);
|
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
|
* ALTER TEXT SEARCH CONFIGURATION - main entry point
|
||||||
*/
|
*/
|
||||||
|
@ -2947,7 +2947,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from)
|
|||||||
COPY_NODE_FIELD(relation);
|
COPY_NODE_FIELD(relation);
|
||||||
COPY_NODE_FIELD(object);
|
COPY_NODE_FIELD(object);
|
||||||
COPY_NODE_FIELD(objarg);
|
COPY_NODE_FIELD(objarg);
|
||||||
COPY_STRING_FIELD(addname);
|
|
||||||
COPY_STRING_FIELD(newowner);
|
COPY_STRING_FIELD(newowner);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
|
@ -1349,7 +1349,6 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b)
|
|||||||
COMPARE_NODE_FIELD(relation);
|
COMPARE_NODE_FIELD(relation);
|
||||||
COMPARE_NODE_FIELD(object);
|
COMPARE_NODE_FIELD(object);
|
||||||
COMPARE_NODE_FIELD(objarg);
|
COMPARE_NODE_FIELD(objarg);
|
||||||
COMPARE_STRING_FIELD(addname);
|
|
||||||
COMPARE_STRING_FIELD(newowner);
|
COMPARE_STRING_FIELD(newowner);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -7366,7 +7366,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
|
|||||||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||||
n->objectType = OBJECT_OPCLASS;
|
n->objectType = OBJECT_OPCLASS;
|
||||||
n->object = $4;
|
n->object = $4;
|
||||||
n->addname = $6;
|
n->objarg = list_make1(makeString($6));
|
||||||
n->newowner = $9;
|
n->newowner = $9;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
@ -7375,7 +7375,7 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
|
|||||||
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
|
||||||
n->objectType = OBJECT_OPFAMILY;
|
n->objectType = OBJECT_OPFAMILY;
|
||||||
n->object = $4;
|
n->object = $4;
|
||||||
n->addname = $6;
|
n->objarg = list_make1(makeString($6));
|
||||||
n->newowner = $9;
|
n->newowner = $9;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,6 @@ typedef FormData_pg_largeobject *Form_pg_largeobject;
|
|||||||
|
|
||||||
extern Oid LargeObjectCreate(Oid loid);
|
extern Oid LargeObjectCreate(Oid loid);
|
||||||
extern void LargeObjectDrop(Oid loid);
|
extern void LargeObjectDrop(Oid loid);
|
||||||
extern void LargeObjectAlterOwner(Oid loid, Oid newOwnerId);
|
|
||||||
extern bool LargeObjectExists(Oid loid);
|
extern bool LargeObjectExists(Oid loid);
|
||||||
|
|
||||||
#endif /* PG_LARGEOBJECT_H */
|
#endif /* PG_LARGEOBJECT_H */
|
||||||
|
@ -18,9 +18,13 @@
|
|||||||
#include "utils/relcache.h"
|
#include "utils/relcache.h"
|
||||||
|
|
||||||
extern void ExecRenameStmt(RenameStmt *stmt);
|
extern void ExecRenameStmt(RenameStmt *stmt);
|
||||||
|
|
||||||
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
|
extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
|
||||||
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
|
extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
|
||||||
extern Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
|
extern Oid AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
|
||||||
|
|
||||||
extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
|
extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
|
||||||
|
extern void AlterObjectOwner_internal(Relation catalog, Oid objectId,
|
||||||
|
Oid new_ownerId);
|
||||||
|
|
||||||
#endif /* ALTER_H */
|
#endif /* ALTER_H */
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
extern void DefineCollation(List *names, List *parameters);
|
extern void DefineCollation(List *names, List *parameters);
|
||||||
extern void RenameCollation(List *name, const char *newname);
|
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 void AlterCollationNamespace(List *name, const char *newschema);
|
||||||
extern Oid AlterCollationNamespace_oid(Oid collOid, Oid newNspOid);
|
extern Oid AlterCollationNamespace_oid(Oid collOid, Oid newNspOid);
|
||||||
|
|
||||||
|
@ -19,7 +19,5 @@
|
|||||||
|
|
||||||
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
|
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
|
||||||
extern void RenameConversion(List *name, const char *newname);
|
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 */
|
#endif /* CONVERSIONCMDS_H */
|
||||||
|
@ -47,8 +47,6 @@ extern void RemoveFunctionById(Oid funcOid);
|
|||||||
extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
|
||||||
extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
|
extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
|
||||||
extern void RenameFunction(List *name, List *argtypes, const char *newname);
|
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 AlterFunction(AlterFunctionStmt *stmt);
|
||||||
extern void CreateCast(CreateCastStmt *stmt);
|
extern void CreateCast(CreateCastStmt *stmt);
|
||||||
extern void DropCastById(Oid castOid);
|
extern void DropCastById(Oid castOid);
|
||||||
@ -61,15 +59,11 @@ extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
|
|||||||
/* commands/operatorcmds.c */
|
/* commands/operatorcmds.c */
|
||||||
extern void DefineOperator(List *names, List *parameters);
|
extern void DefineOperator(List *names, List *parameters);
|
||||||
extern void RemoveOperatorById(Oid operOid);
|
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 */
|
/* commands/aggregatecmds.c */
|
||||||
extern void DefineAggregate(List *name, List *args, bool oldstyle,
|
extern void DefineAggregate(List *name, List *args, bool oldstyle,
|
||||||
List *parameters);
|
List *parameters);
|
||||||
extern void RenameAggregate(List *name, List *args, const char *newname);
|
extern void RenameAggregate(List *name, List *args, const char *newname);
|
||||||
extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId);
|
|
||||||
|
|
||||||
/* commands/opclasscmds.c */
|
/* commands/opclasscmds.c */
|
||||||
extern void DefineOpClass(CreateOpClassStmt *stmt);
|
extern void DefineOpClass(CreateOpClassStmt *stmt);
|
||||||
@ -81,10 +75,6 @@ extern void RemoveAmOpEntryById(Oid entryOid);
|
|||||||
extern void RemoveAmProcEntryById(Oid entryOid);
|
extern void RemoveAmProcEntryById(Oid entryOid);
|
||||||
extern void RenameOpClass(List *name, const char *access_method, const char *newname);
|
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 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_am_oid(const char *amname, bool missing_ok);
|
||||||
extern Oid get_opclass_oid(Oid amID, List *opclassname, 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 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 RenameTSDictionary(List *oldname, const char *newname);
|
||||||
extern void RemoveTSDictionaryById(Oid dictId);
|
extern void RemoveTSDictionaryById(Oid dictId);
|
||||||
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
|
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
|
||||||
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
|
|
||||||
|
|
||||||
extern void DefineTSTemplate(List *names, List *parameters);
|
extern void DefineTSTemplate(List *names, List *parameters);
|
||||||
extern void RenameTSTemplate(List *oldname, const char *newname);
|
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 RenameTSConfiguration(List *oldname, const char *newname);
|
||||||
extern void RemoveTSConfigurationById(Oid cfgId);
|
extern void RemoveTSConfigurationById(Oid cfgId);
|
||||||
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
|
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
|
||||||
extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
|
|
||||||
|
|
||||||
extern text *serialize_deflist(List *deflist);
|
extern text *serialize_deflist(List *deflist);
|
||||||
extern List *deserialize_deflist(Datum txt);
|
extern List *deserialize_deflist(Datum txt);
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
|
extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
|
||||||
extern void DropProceduralLanguageById(Oid langOid);
|
extern void DropProceduralLanguageById(Oid langOid);
|
||||||
extern void RenameLanguage(const char *oldname, const char *newname);
|
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 bool PLTemplateExists(const char *languageName);
|
||||||
extern Oid get_language_oid(const char *langname, bool missing_ok);
|
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 CreateTableSpace(CreateTableSpaceStmt *stmt);
|
||||||
extern void DropTableSpace(DropTableSpaceStmt *stmt);
|
extern void DropTableSpace(DropTableSpaceStmt *stmt);
|
||||||
extern void RenameTableSpace(const char *oldname, const char *newname);
|
extern void RenameTableSpace(const char *oldname, const char *newname);
|
||||||
extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId);
|
|
||||||
extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
|
extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
|
||||||
|
|
||||||
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
||||||
|
@ -2183,7 +2183,6 @@ typedef struct AlterOwnerStmt
|
|||||||
RangeVar *relation; /* in case it's a table */
|
RangeVar *relation; /* in case it's a table */
|
||||||
List *object; /* in case it's some other object */
|
List *object; /* in case it's some other object */
|
||||||
List *objarg; /* argument types, if applicable */
|
List *objarg; /* argument types, if applicable */
|
||||||
char *addname; /* additional name if needed */
|
|
||||||
char *newowner; /* the new owner */
|
char *newowner; /* the new owner */
|
||||||
} AlterOwnerStmt;
|
} AlterOwnerStmt;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user