diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/storage/large_object/inv_api.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 0def1decd0d..aeda7a2c766 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -232,39 +232,47 @@ LargeObjectDesc * inv_open(Oid lobjId, int flags, MemoryContext mcxt) { LargeObjectDesc *retval; - - retval = (LargeObjectDesc *) MemoryContextAlloc(mcxt, - sizeof(LargeObjectDesc)); - - retval->id = lobjId; - retval->subid = GetCurrentSubTransactionId(); - retval->offset = 0; + Snapshot snapshot = NULL; + int descflags = 0; if (flags & INV_WRITE) { - retval->snapshot = SnapshotNow; - retval->flags = IFS_WRLOCK | IFS_RDLOCK; + snapshot = SnapshotNow; + descflags = IFS_WRLOCK | IFS_RDLOCK; } else if (flags & INV_READ) { - /* - * We must register the snapshot in TopTransaction's resowner, because - * it must stay alive until the LO is closed rather than until the - * current portal shuts down. - */ - retval->snapshot = RegisterSnapshotOnOwner(GetActiveSnapshot(), - TopTransactionResourceOwner); - retval->flags = IFS_RDLOCK; + snapshot = GetActiveSnapshot(); + descflags = IFS_RDLOCK; } else elog(ERROR, "invalid flags: %d", flags); /* Can't use LargeObjectExists here because it always uses SnapshotNow */ - if (!myLargeObjectExists(lobjId, retval->snapshot)) + if (!myLargeObjectExists(lobjId, snapshot)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("large object %u does not exist", lobjId))); + /* + * We must register the snapshot in TopTransaction's resowner, because + * it must stay alive until the LO is closed rather than until the + * current portal shuts down. Do this after checking that the LO exists, + * to avoid leaking the snapshot if an error is thrown. + */ + if (snapshot != SnapshotNow) + snapshot = RegisterSnapshotOnOwner(snapshot, + TopTransactionResourceOwner); + + /* All set, create a descriptor */ + retval = (LargeObjectDesc *) MemoryContextAlloc(mcxt, + sizeof(LargeObjectDesc)); + retval->id = lobjId; + retval->subid = GetCurrentSubTransactionId(); + retval->offset = 0; + retval->snapshot = snapshot; + retval->flags = descflags; + return retval; } |