mirror of
https://github.com/postgres/postgres.git
synced 2025-11-22 12:22:45 +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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user