/* * Read [offset, offset+nbytes) within LO; when nbytes is -1, read to end. */ static bytea * lo_get_fragment_internal(Oid loOid, int64 offset, int32 nbytes) { LargeObjectDesc *loDesc; int64 loSize; int64 result_length; int total_read PG_USED_FOR_ASSERTS_ONLY; bytea *result = NULL; /* * We don't actually need to store into fscxt, but create it anyway to * ensure that AtEOXact_LargeObject knows there is state to clean up */ CreateFSContext(); loDesc = inv_open(loOid, INV_READ, fscxt); /* * Compute number of bytes we'll actually read, accommodating nbytes == -1 * and reads beyond the end of the LO. */ loSize = inv_seek(loDesc, 0, SEEK_END); if (loSize > offset) { if (nbytes >= 0 && nbytes <= loSize - offset) result_length = nbytes; /* request is wholly inside LO */ else result_length = loSize - offset; /* adjust to end of LO */ } else result_length = 0; /* request is wholly outside LO */ /* * A result_length calculated from loSize may not fit in a size_t. Check * that the size will satisfy this and subsequently-enforced size limits. */ if (result_length > MaxAllocSize - VARHDRSZ) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("large object read request is too large"))); result = (bytea *) palloc(VARHDRSZ + result_length); inv_seek(loDesc, offset, SEEK_SET); total_read = inv_read(loDesc, VARDATA(result), result_length); Assert(total_read == result_length); SET_VARSIZE(result, result_length + VARHDRSZ); inv_close(loDesc); return result; }
/* * Update range within LO */ Datum be_lo_put(PG_FUNCTION_ARGS) { Oid loOid = PG_GETARG_OID(0); int64 offset = PG_GETARG_INT64(1); bytea *str = PG_GETARG_BYTEA_PP(2); LargeObjectDesc *loDesc; int written PG_USED_FOR_ASSERTS_ONLY; CreateFSContext(); loDesc = inv_open(loOid, INV_WRITE, fscxt); /* Permission check */ if (!lo_compat_privileges && pg_largeobject_aclcheck_snapshot(loDesc->id, GetUserId(), ACL_UPDATE, loDesc->snapshot) != ACLCHECK_OK) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied for large object %u", loDesc->id))); inv_seek(loDesc, offset, SEEK_SET); written = inv_write(loDesc, VARDATA_ANY(str), VARSIZE_ANY_EXHDR(str)); Assert(written == VARSIZE_ANY_EXHDR(str)); inv_close(loDesc); PG_RETURN_VOID(); }
Datum lo_lseek64(PG_FUNCTION_ARGS) { int32 fd = PG_GETARG_INT32(0); int64 offset = PG_GETARG_INT64(1); int32 whence = PG_GETARG_INT32(2); int64 status; #ifdef PGXC #ifdef XCP ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Postgres-XL does not yet support large objects"), errdetail("The feature is not currently supported"))); #else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Postgres-XC does not support large object yet"), errdetail("The feature is not currently supported"))); #endif #endif if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("invalid large-object descriptor: %d", fd))); status = inv_seek(cookies[fd], offset, whence); PG_RETURN_INT64(status); }
Datum lo_lseek(PG_FUNCTION_ARGS) { int32 fd = PG_GETARG_INT32(0); int32 offset = PG_GETARG_INT32(1); int32 whence = PG_GETARG_INT32(2); int64 status; ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("large objects are not supported"))); if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("invalid large-object descriptor: %d", fd))); status = inv_seek(cookies[fd], offset, whence); /* guard against result overflow */ if (status != (int32) status) ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("lo_lseek result out of range for large-object descriptor %d", fd))); PG_RETURN_INT32((int32) status); }
Datum lo_lseek(PG_FUNCTION_ARGS) { int32 fd = PG_GETARG_INT32(0); int32 offset = PG_GETARG_INT32(1); int32 whence = PG_GETARG_INT32(2); int status; if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("invalid large-object descriptor: %d", fd))); status = inv_seek(cookies[fd], offset, whence); PG_RETURN_INT32(status); }
/* * Update range within LO */ Datum lo_put(PG_FUNCTION_ARGS) { Oid loOid = PG_GETARG_OID(0); int64 offset = PG_GETARG_INT64(1); bytea *str = PG_GETARG_BYTEA_PP(2); LargeObjectDesc *loDesc; int written PG_USED_FOR_ASSERTS_ONLY; CreateFSContext(); loDesc = inv_open(loOid, INV_WRITE, fscxt); inv_seek(loDesc, offset, SEEK_SET); written = inv_write(loDesc, VARDATA_ANY(str), VARSIZE_ANY_EXHDR(str)); Assert(written == VARSIZE_ANY_EXHDR(str)); inv_close(loDesc); PG_RETURN_VOID(); }