Compare commits

..

No commits in common. "b485ad7f07c80efbfd47329f138f0fe3a5acf013" and "0e917508b89dd21c5bcd9183e77585f01055a20d" have entirely different histories.

15 changed files with 72 additions and 89 deletions

View File

@ -4103,14 +4103,9 @@ object_ownercheck(Oid classid, Oid objectid, Oid roleid)
if (superuser_arg(roleid))
return true;
/* For large objects, the catalog to consult is pg_largeobject_metadata */
if (classid == LargeObjectRelationId)
classid = LargeObjectMetadataRelationId;
cacheid = get_object_catcache_oid(classid);
if (cacheid != -1)
{
/* we can get the object's tuple from the syscache */
HeapTuple tuple;
tuple = SearchSysCache1(cacheid, ObjectIdGetDatum(objectid));
@ -4127,6 +4122,7 @@ object_ownercheck(Oid classid, Oid objectid, Oid roleid)
else
{
/* for catalogs without an appropriate syscache */
Relation rel;
ScanKeyData entry[1];
SysScanDesc scan;
@ -4446,9 +4442,9 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
ReleaseSysCache(tuple);
}
else if (classoid == LargeObjectRelationId)
/* pg_largeobject_metadata */
else if (classoid == LargeObjectMetadataRelationId)
{
/* For large objects, we must consult pg_largeobject_metadata */
Datum aclDatum;
bool isNull;
HeapTuple tuple;

View File

@ -1614,9 +1614,20 @@ shdepReassignOwned(List *roleids, Oid newrole)
case DatabaseRelationId:
case TSConfigRelationId:
case TSDictionaryRelationId:
AlterObjectOwner_internal(sdepForm->classid,
sdepForm->objid,
newrole);
{
Oid classId = sdepForm->classid;
Relation catalog;
if (classId == LargeObjectRelationId)
classId = LargeObjectMetadataRelationId;
catalog = table_open(classId, RowExclusiveLock);
AlterObjectOwner_internal(catalog, sdepForm->objid,
newrole);
table_close(catalog, NoLock);
}
break;
default:

View File

@ -918,7 +918,9 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION:
{
Relation catalog;
Relation relation;
Oid classId;
ObjectAddress address;
address = get_object_address(stmt->objectType,
@ -927,9 +929,20 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
AccessExclusiveLock,
false);
Assert(relation == NULL);
classId = address.classId;
AlterObjectOwner_internal(address.classId, address.objectId,
newowner);
/*
* 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 = table_open(classId, RowExclusiveLock);
AlterObjectOwner_internal(catalog, address.objectId, newowner);
table_close(catalog, RowExclusiveLock);
return address;
}
@ -947,32 +960,25 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
* 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).
*
* classId: OID of catalog containing object
* 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
*
* This will work on large objects, but we have to beware of the fact that
* classId isn't the OID of the catalog to modify in that case.
*/
void
AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
{
/* For large objects, the catalog to modify is pg_largeobject_metadata */
Oid catalogId = (classId == LargeObjectRelationId) ? LargeObjectMetadataRelationId : classId;
AttrNumber Anum_oid = get_object_attnum_oid(catalogId);
AttrNumber Anum_owner = get_object_attnum_owner(catalogId);
AttrNumber Anum_namespace = get_object_attnum_namespace(catalogId);
AttrNumber Anum_acl = get_object_attnum_acl(catalogId);
AttrNumber Anum_name = get_object_attnum_name(catalogId);
Relation rel;
Oid classId = RelationGetRelid(rel);
AttrNumber Anum_oid = get_object_attnum_oid(classId);
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;
rel = table_open(catalogId, RowExclusiveLock);
oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId);
if (oldtup == NULL)
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
@ -1020,8 +1026,7 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
snprintf(namebuf, sizeof(namebuf), "%u", objectId);
objname = namebuf;
}
aclcheck_error(ACLCHECK_NOT_OWNER,
get_object_type(catalogId, objectId),
aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
objname);
}
/* Must be able to become new owner */
@ -1074,6 +1079,8 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
CatalogTupleUpdate(rel, &newtup->t_self, newtup);
/* Update owner dependency reference */
if (classId == LargeObjectMetadataRelationId)
classId = LargeObjectRelationId;
changeDependencyOnOwner(classId, objectId, new_ownerId);
/* Release memory */
@ -1082,8 +1089,5 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
pfree(replaces);
}
/* Note the post-alter hook gets classId not catalogId */
InvokeObjectPostAlterHook(classId, objectId, 0);
table_close(rel, RowExclusiveLock);
}

View File

@ -43,7 +43,7 @@
#include <unistd.h>
#include "access/xact.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "libpq/be-fsstubs.h"
#include "libpq/libpq-fs.h"
#include "miscadmin.h"
@ -323,7 +323,7 @@ be_lo_unlink(PG_FUNCTION_ARGS)
* relevant FDs.
*/
if (!lo_compat_privileges &&
!object_ownercheck(LargeObjectRelationId, lobjId, GetUserId()))
!object_ownercheck(LargeObjectMetadataRelationId, lobjId, GetUserId()))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be owner of large object %u", lobjId)));

View File

@ -569,7 +569,7 @@ PrefetchSharedBuffer(SMgrRelation smgr_reln,
* recovery if the relation file doesn't exist.
*/
if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
smgrprefetch(smgr_reln, forkNum, blockNum, 1))
smgrprefetch(smgr_reln, forkNum, blockNum))
{
result.initiated_io = true;
}

View File

@ -94,7 +94,7 @@ PrefetchLocalBuffer(SMgrRelation smgr, ForkNumber forkNum,
#ifdef USE_PREFETCH
/* Not in buffers, so initiate prefetch */
if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
smgrprefetch(smgr, forkNum, blockNum, 1))
smgrprefetch(smgr, forkNum, blockNum))
{
result.initiated_io = true;
}

View File

@ -221,10 +221,11 @@ inv_create(Oid lobjId)
/*
* dependency on the owner of largeobject
*
* Note that LO dependencies are recorded using classId
* LargeObjectRelationId for backwards-compatibility reasons. Using
* LargeObjectMetadataRelationId instead would simplify matters for the
* backend, but it'd complicate pg_dump and possibly break other clients.
* The reason why we use LargeObjectRelationId instead of
* LargeObjectMetadataRelationId here is to provide backward compatibility
* to the applications which utilize a knowledge about internal layout of
* system catalogs. OID of pg_largeobject_metadata and loid of
* pg_largeobject are same value, so there are no actual differences here.
*/
recordDependencyOnOwner(LargeObjectRelationId,
lobjId_new, GetUserId());

View File

@ -710,44 +710,27 @@ mdclose(SMgrRelation reln, ForkNumber forknum)
}
/*
* mdprefetch() -- Initiate asynchronous read of the specified blocks of a relation
* mdprefetch() -- Initiate asynchronous read of the specified block of a relation
*/
bool
mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
int nblocks)
mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
{
#ifdef USE_PREFETCH
off_t seekpos;
MdfdVec *v;
Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
if ((uint64) blocknum + nblocks > (uint64) MaxBlockNumber + 1)
v = _mdfd_getseg(reln, forknum, blocknum, false,
InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
if (v == NULL)
return false;
while (nblocks > 0)
{
off_t seekpos;
MdfdVec *v;
int nblocks_this_segment;
seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
v = _mdfd_getseg(reln, forknum, blocknum, false,
InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
if (v == NULL)
return false;
Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE));
Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
nblocks_this_segment =
Min(nblocks,
RELSEG_SIZE - (blocknum % ((BlockNumber) RELSEG_SIZE)));
(void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ * nblocks_this_segment,
WAIT_EVENT_DATA_FILE_PREFETCH);
blocknum += nblocks_this_segment;
nblocks -= nblocks_this_segment;
}
(void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
#endif /* USE_PREFETCH */
return true;

View File

@ -54,7 +54,7 @@ typedef struct f_smgr
void (*smgr_zeroextend) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync);
bool (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks);
BlockNumber blocknum);
void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, void *buffer);
void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
@ -547,10 +547,9 @@ smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
* record).
*/
bool
smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
int nblocks)
smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
{
return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum, nblocks);
return smgrsw[reln->smgr_which].smgr_prefetch(reln, forknum, blocknum);
}
/*

View File

@ -17,6 +17,7 @@
#include "catalog/dependency.h"
#include "catalog/objectaddress.h"
#include "nodes/parsenodes.h"
#include "utils/relcache.h"
extern ObjectAddress ExecRenameStmt(RenameStmt *stmt);
@ -28,7 +29,7 @@ extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
ObjectAddresses *objsMoved);
extern ObjectAddress ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
extern void AlterObjectOwner_internal(Oid classId, Oid objectId,
extern void AlterObjectOwner_internal(Relation rel, Oid objectId,
Oid new_ownerId);
#endif /* ALTER_H */

View File

@ -31,7 +31,7 @@ extern void mdextend(SMgrRelation reln, ForkNumber forknum,
extern void mdzeroextend(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync);
extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks);
BlockNumber blocknum);
extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
void *buffer);
extern void mdwrite(SMgrRelation reln, ForkNumber forknum,

View File

@ -95,7 +95,7 @@ extern void smgrextend(SMgrRelation reln, ForkNumber forknum,
extern void smgrzeroextend(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync);
extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks);
BlockNumber blocknum);
extern void smgrread(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, void *buffer);
extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,

View File

@ -6,7 +6,7 @@
\getenv abs_builddir PG_ABS_BUILDDIR
-- ensure consistent test output regardless of the default bytea format
SET bytea_output TO escape;
-- Test ALTER LARGE OBJECT OWNER
-- Test ALTER LARGE OBJECT OWNER, GRANT, COMMENT
CREATE ROLE regress_lo_user;
SELECT lo_create(42);
lo_create
@ -15,11 +15,8 @@ SELECT lo_create(42);
(1 row)
ALTER LARGE OBJECT 42 OWNER TO regress_lo_user;
-- Test GRANT, COMMENT as non-superuser
SET SESSION AUTHORIZATION regress_lo_user;
GRANT SELECT ON LARGE OBJECT 42 TO public;
COMMENT ON LARGE OBJECT 42 IS 'the ultimate answer';
RESET SESSION AUTHORIZATION;
-- Test psql's \lo_list et al (we assume no other LOs exist yet)
\lo_list
Large objects

View File

@ -6,7 +6,7 @@
\getenv abs_builddir PG_ABS_BUILDDIR
-- ensure consistent test output regardless of the default bytea format
SET bytea_output TO escape;
-- Test ALTER LARGE OBJECT OWNER
-- Test ALTER LARGE OBJECT OWNER, GRANT, COMMENT
CREATE ROLE regress_lo_user;
SELECT lo_create(42);
lo_create
@ -15,11 +15,8 @@ SELECT lo_create(42);
(1 row)
ALTER LARGE OBJECT 42 OWNER TO regress_lo_user;
-- Test GRANT, COMMENT as non-superuser
SET SESSION AUTHORIZATION regress_lo_user;
GRANT SELECT ON LARGE OBJECT 42 TO public;
COMMENT ON LARGE OBJECT 42 IS 'the ultimate answer';
RESET SESSION AUTHORIZATION;
-- Test psql's \lo_list et al (we assume no other LOs exist yet)
\lo_list
Large objects

View File

@ -9,19 +9,13 @@
-- ensure consistent test output regardless of the default bytea format
SET bytea_output TO escape;
-- Test ALTER LARGE OBJECT OWNER
-- Test ALTER LARGE OBJECT OWNER, GRANT, COMMENT
CREATE ROLE regress_lo_user;
SELECT lo_create(42);
ALTER LARGE OBJECT 42 OWNER TO regress_lo_user;
-- Test GRANT, COMMENT as non-superuser
SET SESSION AUTHORIZATION regress_lo_user;
GRANT SELECT ON LARGE OBJECT 42 TO public;
COMMENT ON LARGE OBJECT 42 IS 'the ultimate answer';
RESET SESSION AUTHORIZATION;
-- Test psql's \lo_list et al (we assume no other LOs exist yet)
\lo_list
\lo_list+