99 *
1010 *
1111 * IDENTIFICATION
12- * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.79 2000/10/24 01:38:29 tgl Exp $
12+ * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.80 2000/11/02 23:52:06 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -186,7 +186,6 @@ inv_getsize(LargeObjectDesc *obj_desc)
186186{
187187bool found = false;
188188uint32 lastbyte = 0 ;
189- uint32 thislastbyte ;
190189ScanKeyData skey [1 ];
191190IndexScanDesc sd ;
192191RetrieveIndexResult indexRes ;
@@ -209,7 +208,13 @@ inv_getsize(LargeObjectDesc *obj_desc)
209208tuple .t_datamcxt = CurrentMemoryContext ;
210209tuple .t_data = NULL ;
211210
212- while ((indexRes = index_getnext (sd ,ForwardScanDirection )))
211+ /*
212+ * Because the pg_largeobject index is on both loid and pageno,
213+ * but we constrain only loid, a backwards scan should visit all
214+ * pages of the large object in reverse pageno order. So, it's
215+ * sufficient to examine the first valid tuple (== last valid page).
216+ */
217+ while ((indexRes = index_getnext (sd ,BackwardScanDirection )))
213218{
214219tuple .t_self = indexRes -> heap_iptr ;
215220heap_fetch (obj_desc -> heap_r ,SnapshotNow ,& tuple ,& buffer );
@@ -226,12 +231,11 @@ inv_getsize(LargeObjectDesc *obj_desc)
226231heap_tuple_untoast_attr ((varattrib * )datafield );
227232pfreeit = true;
228233}
229- thislastbyte = data -> pageno * LOBLKSIZE + getbytealen (datafield );
230- if (thislastbyte > lastbyte )
231- lastbyte = thislastbyte ;
234+ lastbyte = data -> pageno * LOBLKSIZE + getbytealen (datafield );
232235if (pfreeit )
233236pfree (datafield );
234237ReleaseBuffer (buffer );
238+ break ;
235239}
236240
237241index_endscan (sd );
@@ -254,16 +258,17 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
254258obj_desc -> offset = offset ;
255259break ;
256260case SEEK_CUR :
257- if (( obj_desc -> offset + offset ) < 0 )
261+ if (offset < 0 && obj_desc -> offset < (( uint32 ) ( - offset )) )
258262elog (ERROR ,"inv_seek: invalid offset: %d" ,offset );
259263obj_desc -> offset += offset ;
260264break ;
261265case SEEK_END :
262266{
263- uint32 size = inv_getsize (obj_desc );
264- if (offset < 0 || ((uint32 )offset )> size )
265- elog (ERROR ,"inv_seek: invalid offset" );
266- obj_desc -> offset = size - offset ;
267+ uint32 size = inv_getsize (obj_desc );
268+
269+ if (offset < 0 && size < ((uint32 ) (- offset )))
270+ elog (ERROR ,"inv_seek: invalid offset: %d" ,offset );
271+ obj_desc -> offset = size + offset ;
267272}
268273break ;
269274default :