9
9
*
10
10
*
11
11
* 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 $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
@@ -186,7 +186,6 @@ inv_getsize(LargeObjectDesc *obj_desc)
186
186
{
187
187
bool found = false;
188
188
uint32 lastbyte = 0 ;
189
- uint32 thislastbyte ;
190
189
ScanKeyData skey [1 ];
191
190
IndexScanDesc sd ;
192
191
RetrieveIndexResult indexRes ;
@@ -209,7 +208,13 @@ inv_getsize(LargeObjectDesc *obj_desc)
209
208
tuple .t_datamcxt = CurrentMemoryContext ;
210
209
tuple .t_data = NULL ;
211
210
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 )))
213
218
{
214
219
tuple .t_self = indexRes -> heap_iptr ;
215
220
heap_fetch (obj_desc -> heap_r , SnapshotNow , & tuple , & buffer );
@@ -226,12 +231,11 @@ inv_getsize(LargeObjectDesc *obj_desc)
226
231
heap_tuple_untoast_attr ((varattrib * ) datafield );
227
232
pfreeit = true;
228
233
}
229
- thislastbyte = data -> pageno * LOBLKSIZE + getbytealen (datafield );
230
- if (thislastbyte > lastbyte )
231
- lastbyte = thislastbyte ;
234
+ lastbyte = data -> pageno * LOBLKSIZE + getbytealen (datafield );
232
235
if (pfreeit )
233
236
pfree (datafield );
234
237
ReleaseBuffer (buffer );
238
+ break ;
235
239
}
236
240
237
241
index_endscan (sd );
@@ -254,16 +258,17 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
254
258
obj_desc -> offset = offset ;
255
259
break ;
256
260
case SEEK_CUR :
257
- if (( obj_desc -> offset + offset ) < 0 )
261
+ if (offset < 0 && obj_desc -> offset < (( uint32 ) ( - offset )) )
258
262
elog (ERROR , "inv_seek: invalid offset: %d" , offset );
259
263
obj_desc -> offset += offset ;
260
264
break ;
261
265
case SEEK_END :
262
266
{
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 ;
267
272
}
268
273
break ;
269
274
default :
0 commit comments