Skip to content

Commit 55742d4

Browse files
committed
Back-patch large-object fix.
1 parent c545ec5 commit 55742d4

File tree

1 file changed

+33
-23
lines changed

1 file changed

+33
-23
lines changed

src/backend/storage/large_object/inv_api.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.67 2000/04/12 17:15:37 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.67.2.1 2000/06/15 06:10:27 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -185,6 +185,7 @@ inv_create(int flags)
185185
retval->idesc = RelationGetDescr(indr);
186186
retval->offset = retval->lowbyte = retval->highbyte = 0;
187187
ItemPointerSetInvalid(&(retval->htid));
188+
retval->flags = 0;
188189

189190
if (flags & INV_WRITE)
190191
{
@@ -196,7 +197,7 @@ inv_create(int flags)
196197
LockRelation(r, ShareLock);
197198
retval->flags = IFS_RDLOCK;
198199
}
199-
retval->flags |= IFS_ATEOF;
200+
retval->flags |= IFS_ATEOF; /* since we know the object is empty */
200201

201202
return retval;
202203
}
@@ -233,6 +234,7 @@ inv_open(Oid lobjId, int flags)
233234
retval->idesc = RelationGetDescr(indrel);
234235
retval->offset = retval->lowbyte = retval->highbyte = 0;
235236
ItemPointerSetInvalid(&(retval->htid));
237+
retval->flags = 0;
236238

237239
if (flags & INV_WRITE)
238240
{
@@ -371,14 +373,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
371373
if (whence == SEEK_CUR)
372374
{
373375
offset += obj_desc->offset; /* calculate absolute position */
374-
return inv_seek(obj_desc, offset, SEEK_SET);
375376
}
376-
377-
/*
378-
* if you seek past the end (offset > 0) I have no clue what happens
379-
* :-( B.L. 9/1/93
380-
*/
381-
if (whence == SEEK_END)
377+
else if (whence == SEEK_END)
382378
{
383379
/* need read lock for getsize */
384380
if (!(obj_desc->flags & IFS_RDLOCK))
@@ -389,8 +385,8 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
389385
offset += _inv_getsize(obj_desc->heap_r,
390386
obj_desc->hdesc,
391387
obj_desc->index_r);
392-
return inv_seek(obj_desc, offset, SEEK_SET);
393388
}
389+
/* now we can assume that the operation is SEEK_SET */
394390

395391
/*
396392
* Whenever we do a seek, we turn off the EOF flag bit to force
@@ -414,17 +410,13 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
414410
* stores the offset of the last byte that appears on it, and we have
415411
* an index on this.
416412
*/
417-
418-
419-
/* right now, just assume that the operation is SEEK_SET */
420413
if (obj_desc->iscan != (IndexScanDesc) NULL)
421414
{
422415
d = Int32GetDatum(offset);
423416
btmovescan(obj_desc->iscan, d);
424417
}
425418
else
426419
{
427-
428420
ScanKeyEntryInitialize(&skey, 0x0, 1, F_INT4GE,
429421
Int32GetDatum(offset));
430422

@@ -487,9 +479,27 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
487479

488480
/* copy the data from this block into the buffer */
489481
d = heap_getattr(&tuple, 2, obj_desc->hdesc, &isNull);
482+
fsblock = (struct varlena *) DatumGetPointer(d);
490483
ReleaseBuffer(buffer);
491484

492-
fsblock = (struct varlena *) DatumGetPointer(d);
485+
/*
486+
* If block starts beyond current seek point, then we are looking
487+
* at a "hole" (unwritten area) in the object. Return zeroes for
488+
* the "hole".
489+
*/
490+
if (obj_desc->offset < obj_desc->lowbyte)
491+
{
492+
int nzeroes = obj_desc->lowbyte - obj_desc->offset;
493+
494+
if (nzeroes > (nbytes - nread))
495+
nzeroes = (nbytes - nread);
496+
MemSet(buf, 0, nzeroes);
497+
buf += nzeroes;
498+
nread += nzeroes;
499+
obj_desc->offset += nzeroes;
500+
if (nread >= nbytes)
501+
break;
502+
}
493503

494504
off = obj_desc->offset - obj_desc->lowbyte;
495505
ncopy = obj_desc->highbyte - obj_desc->offset + 1;
@@ -535,14 +545,11 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
535545
Buffer buffer;
536546

537547
/*
538-
* Fetch the current inversion file system block. If the class
539-
* storing the inversion file is empty, we don't want to do an
540-
* index lookup, since index lookups choke on empty files (should
541-
* be fixed someday).
548+
* Fetch the current inversion file system block. We can skip
549+
* the work if we already know we are at EOF.
542550
*/
543551

544-
if ((obj_desc->flags & IFS_ATEOF)
545-
|| obj_desc->heap_r->rd_nblocks == 0)
552+
if (obj_desc->flags & IFS_ATEOF)
546553
tuple.t_data = NULL;
547554
else
548555
inv_fetchtup(obj_desc, &tuple, &buffer);
@@ -657,6 +664,7 @@ inv_fetchtup(LargeObjectDesc *obj_desc, HeapTuple tuple, Buffer *buffer)
657664
}
658665
else
659666
index_rescan(obj_desc->iscan, false, &skey);
667+
660668
do
661669
{
662670
res = index_getnext(obj_desc->iscan, ForwardScanDirection);
@@ -1147,7 +1155,8 @@ inv_indextup(LargeObjectDesc *obj_desc, HeapTuple tuple)
11471155
pfree(res);
11481156
}
11491157

1150-
/*
1158+
#ifdef NOT_USED
1159+
11511160
static void
11521161
DumpPage(Page page, int blkno)
11531162
{
@@ -1237,7 +1246,8 @@ ItemPointerFormExternal(ItemPointer pointer)
12371246

12381247
return itemPointerString;
12391248
}
1240-
*/
1249+
1250+
#endif
12411251

12421252
static int
12431253
_inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)

0 commit comments

Comments
 (0)