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

View File

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

View File

@ -918,7 +918,9 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
case OBJECT_TSDICTIONARY: case OBJECT_TSDICTIONARY:
case OBJECT_TSCONFIGURATION: case OBJECT_TSCONFIGURATION:
{ {
Relation catalog;
Relation relation; Relation relation;
Oid classId;
ObjectAddress address; ObjectAddress address;
address = get_object_address(stmt->objectType, address = get_object_address(stmt->objectType,
@ -927,9 +929,20 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
AccessExclusiveLock, AccessExclusiveLock,
false); false);
Assert(relation == NULL); 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; 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 * 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). * 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 * objectId: OID of object to change the ownership of
* new_ownerId: OID of new object owner * 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 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 classId = RelationGetRelid(rel);
Oid catalogId = (classId == LargeObjectRelationId) ? LargeObjectMetadataRelationId : classId; AttrNumber Anum_oid = get_object_attnum_oid(classId);
AttrNumber Anum_oid = get_object_attnum_oid(catalogId); AttrNumber Anum_owner = get_object_attnum_owner(classId);
AttrNumber Anum_owner = get_object_attnum_owner(catalogId); AttrNumber Anum_namespace = get_object_attnum_namespace(classId);
AttrNumber Anum_namespace = get_object_attnum_namespace(catalogId); AttrNumber Anum_acl = get_object_attnum_acl(classId);
AttrNumber Anum_acl = get_object_attnum_acl(catalogId); AttrNumber Anum_name = get_object_attnum_name(classId);
AttrNumber Anum_name = get_object_attnum_name(catalogId);
Relation rel;
HeapTuple oldtup; HeapTuple oldtup;
Datum datum; Datum datum;
bool isnull; bool isnull;
Oid old_ownerId; Oid old_ownerId;
Oid namespaceId = InvalidOid; Oid namespaceId = InvalidOid;
rel = table_open(catalogId, RowExclusiveLock);
oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId); oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId);
if (oldtup == NULL) if (oldtup == NULL)
elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", 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); snprintf(namebuf, sizeof(namebuf), "%u", objectId);
objname = namebuf; objname = namebuf;
} }
aclcheck_error(ACLCHECK_NOT_OWNER, aclcheck_error(ACLCHECK_NOT_OWNER, get_object_type(classId, objectId),
get_object_type(catalogId, objectId),
objname); objname);
} }
/* Must be able to become new owner */ /* 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); CatalogTupleUpdate(rel, &newtup->t_self, newtup);
/* Update owner dependency reference */ /* Update owner dependency reference */
if (classId == LargeObjectMetadataRelationId)
classId = LargeObjectRelationId;
changeDependencyOnOwner(classId, objectId, new_ownerId); changeDependencyOnOwner(classId, objectId, new_ownerId);
/* Release memory */ /* Release memory */
@ -1082,8 +1089,5 @@ AlterObjectOwner_internal(Oid classId, Oid objectId, Oid new_ownerId)
pfree(replaces); pfree(replaces);
} }
/* Note the post-alter hook gets classId not catalogId */
InvokeObjectPostAlterHook(classId, objectId, 0); InvokeObjectPostAlterHook(classId, objectId, 0);
table_close(rel, RowExclusiveLock);
} }

View File

@ -43,7 +43,7 @@
#include <unistd.h> #include <unistd.h>
#include "access/xact.h" #include "access/xact.h"
#include "catalog/pg_largeobject.h" #include "catalog/pg_largeobject_metadata.h"
#include "libpq/be-fsstubs.h" #include "libpq/be-fsstubs.h"
#include "libpq/libpq-fs.h" #include "libpq/libpq-fs.h"
#include "miscadmin.h" #include "miscadmin.h"
@ -323,7 +323,7 @@ be_lo_unlink(PG_FUNCTION_ARGS)
* relevant FDs. * relevant FDs.
*/ */
if (!lo_compat_privileges && if (!lo_compat_privileges &&
!object_ownercheck(LargeObjectRelationId, lobjId, GetUserId())) !object_ownercheck(LargeObjectMetadataRelationId, lobjId, GetUserId()))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be owner of large object %u", lobjId))); 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. * recovery if the relation file doesn't exist.
*/ */
if ((io_direct_flags & IO_DIRECT_DATA) == 0 && if ((io_direct_flags & IO_DIRECT_DATA) == 0 &&
smgrprefetch(smgr_reln, forkNum, blockNum, 1)) smgrprefetch(smgr_reln, forkNum, blockNum))
{ {
result.initiated_io = true; result.initiated_io = true;
} }

View File

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

View File

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

View File

@ -710,24 +710,16 @@ 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 bool
mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
int nblocks)
{ {
#ifdef USE_PREFETCH #ifdef USE_PREFETCH
Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
if ((uint64) blocknum + nblocks > (uint64) MaxBlockNumber + 1)
return false;
while (nblocks > 0)
{
off_t seekpos; off_t seekpos;
MdfdVec *v; MdfdVec *v;
int nblocks_this_segment;
Assert((io_direct_flags & IO_DIRECT_DATA) == 0);
v = _mdfd_getseg(reln, forknum, blocknum, false, v = _mdfd_getseg(reln, forknum, blocknum, false,
InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL); InRecovery ? EXTENSION_RETURN_NULL : EXTENSION_FAIL);
@ -738,16 +730,7 @@ mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE); Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE);
nblocks_this_segment = (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ, WAIT_EVENT_DATA_FILE_PREFETCH);
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;
}
#endif /* USE_PREFETCH */ #endif /* USE_PREFETCH */
return true; return true;

View File

@ -54,7 +54,7 @@ typedef struct f_smgr
void (*smgr_zeroextend) (SMgrRelation reln, ForkNumber forknum, void (*smgr_zeroextend) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync); BlockNumber blocknum, int nblocks, bool skipFsync);
bool (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum, bool (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks); BlockNumber blocknum);
void (*smgr_read) (SMgrRelation reln, ForkNumber forknum, void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, void *buffer); BlockNumber blocknum, void *buffer);
void (*smgr_write) (SMgrRelation reln, ForkNumber forknum, void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
@ -547,10 +547,9 @@ smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
* record). * record).
*/ */
bool bool
smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum)
int nblocks)
{ {
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/dependency.h"
#include "catalog/objectaddress.h" #include "catalog/objectaddress.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "utils/relcache.h"
extern ObjectAddress ExecRenameStmt(RenameStmt *stmt); extern ObjectAddress ExecRenameStmt(RenameStmt *stmt);
@ -28,7 +29,7 @@ extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
ObjectAddresses *objsMoved); ObjectAddresses *objsMoved);
extern ObjectAddress ExecAlterOwnerStmt(AlterOwnerStmt *stmt); extern ObjectAddress ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
extern void AlterObjectOwner_internal(Oid classId, Oid objectId, extern void AlterObjectOwner_internal(Relation rel, Oid objectId,
Oid new_ownerId); Oid new_ownerId);
#endif /* ALTER_H */ #endif /* ALTER_H */

View File

@ -31,7 +31,7 @@ extern void mdextend(SMgrRelation reln, ForkNumber forknum,
extern void mdzeroextend(SMgrRelation reln, ForkNumber forknum, extern void mdzeroextend(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync); BlockNumber blocknum, int nblocks, bool skipFsync);
extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum, extern bool mdprefetch(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks); BlockNumber blocknum);
extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, extern void mdread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
void *buffer); void *buffer);
extern void mdwrite(SMgrRelation reln, ForkNumber forknum, 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, extern void smgrzeroextend(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks, bool skipFsync); BlockNumber blocknum, int nblocks, bool skipFsync);
extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum, extern bool smgrprefetch(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, int nblocks); BlockNumber blocknum);
extern void smgrread(SMgrRelation reln, ForkNumber forknum, extern void smgrread(SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, void *buffer); BlockNumber blocknum, void *buffer);
extern void smgrwrite(SMgrRelation reln, ForkNumber forknum, extern void smgrwrite(SMgrRelation reln, ForkNumber forknum,

View File

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

View File

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

View File

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