mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Prevent write operations on large objects in read-only transactions
Attempting such an operation would already fail, but in various and confusing ways. For example, while in recovery, some elog() messages would be reported, but these should never be user-facing. This commit restricts any write operations done on large objects in a read-only context, so as the errors generated are more user-friendly. This is per the discussion done with Tom Lane and Robert Haas. Some regression tests are added to check the case of all the SQL functions working on large objects (including an update of the test's alternate output). Author: Yugo Nagata Discussion: https://postgr.es/m/20220527153028.61a4608f66abcd026fd3806f@sraoss.co.jp
This commit is contained in:
@@ -93,6 +93,9 @@ be_lo_open(PG_FUNCTION_ARGS)
|
||||
elog(DEBUG4, "lo_open(%u,%d)", lobjId, mode);
|
||||
#endif
|
||||
|
||||
if (mode & INV_WRITE)
|
||||
PreventCommandIfReadOnly("lo_open(INV_WRITE)");
|
||||
|
||||
/*
|
||||
* Allocate a large object descriptor first. This will also create
|
||||
* 'fscxt' if this is the first LO opened in this transaction.
|
||||
@@ -245,6 +248,8 @@ be_lo_creat(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid lobjId;
|
||||
|
||||
PreventCommandIfReadOnly("lo_creat()");
|
||||
|
||||
lo_cleanup_needed = true;
|
||||
lobjId = inv_create(InvalidOid);
|
||||
|
||||
@@ -256,6 +261,8 @@ be_lo_create(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid lobjId = PG_GETARG_OID(0);
|
||||
|
||||
PreventCommandIfReadOnly("lo_create()");
|
||||
|
||||
lo_cleanup_needed = true;
|
||||
lobjId = inv_create(lobjId);
|
||||
|
||||
@@ -306,6 +313,8 @@ be_lo_unlink(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid lobjId = PG_GETARG_OID(0);
|
||||
|
||||
PreventCommandIfReadOnly("lo_unlink()");
|
||||
|
||||
/*
|
||||
* Must be owner of the large object. It would be cleaner to check this
|
||||
* in inv_drop(), but we want to throw the error before not after closing
|
||||
@@ -368,6 +377,8 @@ be_lowrite(PG_FUNCTION_ARGS)
|
||||
int bytestowrite;
|
||||
int totalwritten;
|
||||
|
||||
PreventCommandIfReadOnly("lowrite()");
|
||||
|
||||
bytestowrite = VARSIZE_ANY_EXHDR(wbuf);
|
||||
totalwritten = lo_write(fd, VARDATA_ANY(wbuf), bytestowrite);
|
||||
PG_RETURN_INT32(totalwritten);
|
||||
@@ -413,6 +424,8 @@ lo_import_internal(text *filename, Oid lobjOid)
|
||||
LargeObjectDesc *lobj;
|
||||
Oid oid;
|
||||
|
||||
PreventCommandIfReadOnly("lo_import()");
|
||||
|
||||
/*
|
||||
* open the file to be read in
|
||||
*/
|
||||
@@ -561,6 +574,8 @@ be_lo_truncate(PG_FUNCTION_ARGS)
|
||||
int32 fd = PG_GETARG_INT32(0);
|
||||
int32 len = PG_GETARG_INT32(1);
|
||||
|
||||
PreventCommandIfReadOnly("lo_truncate()");
|
||||
|
||||
lo_truncate_internal(fd, len);
|
||||
PG_RETURN_INT32(0);
|
||||
}
|
||||
@@ -571,6 +586,8 @@ be_lo_truncate64(PG_FUNCTION_ARGS)
|
||||
int32 fd = PG_GETARG_INT32(0);
|
||||
int64 len = PG_GETARG_INT64(1);
|
||||
|
||||
PreventCommandIfReadOnly("lo_truncate64()");
|
||||
|
||||
lo_truncate_internal(fd, len);
|
||||
PG_RETURN_INT32(0);
|
||||
}
|
||||
@@ -815,6 +832,8 @@ be_lo_from_bytea(PG_FUNCTION_ARGS)
|
||||
LargeObjectDesc *loDesc;
|
||||
int written PG_USED_FOR_ASSERTS_ONLY;
|
||||
|
||||
PreventCommandIfReadOnly("lo_from_bytea()");
|
||||
|
||||
lo_cleanup_needed = true;
|
||||
loOid = inv_create(loOid);
|
||||
loDesc = inv_open(loOid, INV_WRITE, CurrentMemoryContext);
|
||||
@@ -837,6 +856,8 @@ be_lo_put(PG_FUNCTION_ARGS)
|
||||
LargeObjectDesc *loDesc;
|
||||
int written PG_USED_FOR_ASSERTS_ONLY;
|
||||
|
||||
PreventCommandIfReadOnly("lo_put()");
|
||||
|
||||
lo_cleanup_needed = true;
|
||||
loDesc = inv_open(loOid, INV_WRITE, CurrentMemoryContext);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user