-/*
- * 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);
-}
-