mirror of
https://github.com/postgres/postgres.git
synced 2026-04-15 22:10:45 -04:00
Back-patch large-object fix.
This commit is contained in:
parent
c545ec54f8
commit
55742d4b1c
1 changed files with 33 additions and 23 deletions
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.67 2000/04/12 17:15:37 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.67.2.1 2000/06/15 06:10:27 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -185,6 +185,7 @@ inv_create(int flags)
|
|||
retval->idesc = RelationGetDescr(indr);
|
||||
retval->offset = retval->lowbyte = retval->highbyte = 0;
|
||||
ItemPointerSetInvalid(&(retval->htid));
|
||||
retval->flags = 0;
|
||||
|
||||
if (flags & INV_WRITE)
|
||||
{
|
||||
|
|
@ -196,7 +197,7 @@ inv_create(int flags)
|
|||
LockRelation(r, ShareLock);
|
||||
retval->flags = IFS_RDLOCK;
|
||||
}
|
||||
retval->flags |= IFS_ATEOF;
|
||||
retval->flags |= IFS_ATEOF; /* since we know the object is empty */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -233,6 +234,7 @@ inv_open(Oid lobjId, int flags)
|
|||
retval->idesc = RelationGetDescr(indrel);
|
||||
retval->offset = retval->lowbyte = retval->highbyte = 0;
|
||||
ItemPointerSetInvalid(&(retval->htid));
|
||||
retval->flags = 0;
|
||||
|
||||
if (flags & INV_WRITE)
|
||||
{
|
||||
|
|
@ -371,14 +373,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
|
|||
if (whence == SEEK_CUR)
|
||||
{
|
||||
offset += obj_desc->offset; /* calculate absolute position */
|
||||
return inv_seek(obj_desc, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
* if you seek past the end (offset > 0) I have no clue what happens
|
||||
* :-( B.L. 9/1/93
|
||||
*/
|
||||
if (whence == SEEK_END)
|
||||
else if (whence == SEEK_END)
|
||||
{
|
||||
/* need read lock for getsize */
|
||||
if (!(obj_desc->flags & IFS_RDLOCK))
|
||||
|
|
@ -389,8 +385,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
|
|||
offset += _inv_getsize(obj_desc->heap_r,
|
||||
obj_desc->hdesc,
|
||||
obj_desc->index_r);
|
||||
return inv_seek(obj_desc, offset, SEEK_SET);
|
||||
}
|
||||
/* now we can assume that the operation is SEEK_SET */
|
||||
|
||||
/*
|
||||
* Whenever we do a seek, we turn off the EOF flag bit to force
|
||||
|
|
@ -414,9 +410,6 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
|
|||
* stores the offset of the last byte that appears on it, and we have
|
||||
* an index on this.
|
||||
*/
|
||||
|
||||
|
||||
/* right now, just assume that the operation is SEEK_SET */
|
||||
if (obj_desc->iscan != (IndexScanDesc) NULL)
|
||||
{
|
||||
d = Int32GetDatum(offset);
|
||||
|
|
@ -424,7 +417,6 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
ScanKeyEntryInitialize(&skey, 0x0, 1, F_INT4GE,
|
||||
Int32GetDatum(offset));
|
||||
|
||||
|
|
@ -487,9 +479,27 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
|
|||
|
||||
/* copy the data from this block into the buffer */
|
||||
d = heap_getattr(&tuple, 2, obj_desc->hdesc, &isNull);
|
||||
fsblock = (struct varlena *) DatumGetPointer(d);
|
||||
ReleaseBuffer(buffer);
|
||||
|
||||
fsblock = (struct varlena *) DatumGetPointer(d);
|
||||
/*
|
||||
* If block starts beyond current seek point, then we are looking
|
||||
* at a "hole" (unwritten area) in the object. Return zeroes for
|
||||
* the "hole".
|
||||
*/
|
||||
if (obj_desc->offset < obj_desc->lowbyte)
|
||||
{
|
||||
int nzeroes = obj_desc->lowbyte - obj_desc->offset;
|
||||
|
||||
if (nzeroes > (nbytes - nread))
|
||||
nzeroes = (nbytes - nread);
|
||||
MemSet(buf, 0, nzeroes);
|
||||
buf += nzeroes;
|
||||
nread += nzeroes;
|
||||
obj_desc->offset += nzeroes;
|
||||
if (nread >= nbytes)
|
||||
break;
|
||||
}
|
||||
|
||||
off = obj_desc->offset - obj_desc->lowbyte;
|
||||
ncopy = obj_desc->highbyte - obj_desc->offset + 1;
|
||||
|
|
@ -535,14 +545,11 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
|
|||
Buffer buffer;
|
||||
|
||||
/*
|
||||
* Fetch the current inversion file system block. If the class
|
||||
* storing the inversion file is empty, we don't want to do an
|
||||
* index lookup, since index lookups choke on empty files (should
|
||||
* be fixed someday).
|
||||
* Fetch the current inversion file system block. We can skip
|
||||
* the work if we already know we are at EOF.
|
||||
*/
|
||||
|
||||
if ((obj_desc->flags & IFS_ATEOF)
|
||||
|| obj_desc->heap_r->rd_nblocks == 0)
|
||||
if (obj_desc->flags & IFS_ATEOF)
|
||||
tuple.t_data = NULL;
|
||||
else
|
||||
inv_fetchtup(obj_desc, &tuple, &buffer);
|
||||
|
|
@ -657,6 +664,7 @@ inv_fetchtup(LargeObjectDesc *obj_desc, HeapTuple tuple, Buffer *buffer)
|
|||
}
|
||||
else
|
||||
index_rescan(obj_desc->iscan, false, &skey);
|
||||
|
||||
do
|
||||
{
|
||||
res = index_getnext(obj_desc->iscan, ForwardScanDirection);
|
||||
|
|
@ -1147,7 +1155,8 @@ inv_indextup(LargeObjectDesc *obj_desc, HeapTuple tuple)
|
|||
pfree(res);
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef NOT_USED
|
||||
|
||||
static void
|
||||
DumpPage(Page page, int blkno)
|
||||
{
|
||||
|
|
@ -1237,7 +1246,8 @@ ItemPointerFormExternal(ItemPointer pointer)
|
|||
|
||||
return itemPointerString;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
_inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)
|
||||
|
|
|
|||
Loading…
Reference in a new issue