/* * 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); } }
/* * Change tablespace owner */ void AlterTableSpaceOwner(const char *name, Oid newOwnerId) { Relation rel; Oid tablespaceoid; cqContext cqc; cqContext *pcqCtx; Form_pg_tablespace spcForm; HeapTuple tup; /* Search pg_tablespace */ rel = heap_open(TableSpaceRelationId, RowExclusiveLock); pcqCtx = caql_addrel(cqclr(&cqc), rel); tup = caql_getfirst( pcqCtx, cql("SELECT * FROM pg_tablespace " " WHERE spcname = :1 " " FOR UPDATE ", CStringGetDatum(name))); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("tablespace \"%s\" does not exist", name))); tablespaceoid = HeapTupleGetOid(tup); 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(tablespaceoid, 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 = caql_modify_current(pcqCtx, repl_val, repl_null, repl_repl); caql_update_current(pcqCtx, newtuple); /* and Update indexes (implicit) */ /* MPP-6929: metadata tracking */ if (Gp_role == GP_ROLE_DISPATCH) MetaTrackUpdObject(TableSpaceRelationId, tablespaceoid, GetUserId(), "ALTER", "OWNER" ); heap_freetuple(newtuple); /* Update owner dependency reference */ changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup), newOwnerId); } 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); }
/* * 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); }