@@ -380,21 +380,22 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
380
380
Oid indexRelid = PG_GETARG_OID (0 );
381
381
uint64 ovflblkno = PG_GETARG_INT64 (1 );
382
382
HashMetaPage metap ;
383
- Buffer buf ,
384
- metabuf ;
383
+ Buffer metabuf ,
384
+ mapbuf ;
385
385
BlockNumber bitmapblkno ;
386
- Page page ;
386
+ Page mappage ;
387
387
bool bit = false;
388
- HashPageOpaque opaque ;
389
388
TupleDesc tupleDesc ;
390
389
Relation indexRel ;
391
390
uint32 ovflbitno ;
392
391
int32 bitmappage ,
393
392
bitmapbit ;
394
393
HeapTuple tuple ;
395
- int j ;
394
+ int i ,
395
+ j ;
396
396
Datum values [3 ];
397
397
bool nulls [3 ];
398
+ uint32 * freep ;
398
399
399
400
if (!superuser ())
400
401
ereport (ERROR ,
@@ -418,30 +419,30 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
418
419
errmsg ("block number " UINT64_FORMAT " is out of range for relation \"%s\"" ,
419
420
ovflblkno , RelationGetRelationName (indexRel ))));
420
421
421
- buf = ReadBufferExtended (indexRel , MAIN_FORKNUM , (BlockNumber ) ovflblkno ,
422
- RBM_NORMAL , NULL );
423
- LockBuffer (buf , BUFFER_LOCK_SHARE );
424
- _hash_checkpage (indexRel , buf , LH_PAGE_TYPE );
425
- page = BufferGetPage (buf );
426
- opaque = (HashPageOpaque ) PageGetSpecialPointer (page );
427
-
428
- if (opaque -> hasho_flag != LH_OVERFLOW_PAGE )
429
- ereport (ERROR ,
430
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
431
- errmsg ("page is not an overflow page" ),
432
- errdetail ("Expected %08x, got %08x." ,
433
- LH_OVERFLOW_PAGE , opaque -> hasho_flag )));
434
-
435
- if (BlockNumberIsValid (opaque -> hasho_prevblkno ))
436
- bit = true;
437
-
438
- UnlockReleaseBuffer (buf );
439
-
440
422
/* Read the metapage so we can determine which bitmap page to use */
441
423
metabuf = _hash_getbuf (indexRel , HASH_METAPAGE , HASH_READ , LH_META_PAGE );
442
424
metap = HashPageGetMeta (BufferGetPage (metabuf ));
443
425
444
- /* Identify overflow bit number */
426
+ /*
427
+ * Reject attempt to read the bit for a metapage or bitmap page; this is
428
+ * only meaningful for overflow pages.
429
+ */
430
+ if (ovflblkno == 0 )
431
+ ereport (ERROR ,
432
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
433
+ errmsg ("invalid overflow block number %u" ,
434
+ (BlockNumber ) ovflblkno )));
435
+ for (i = 0 ; i < metap -> hashm_nmaps ; i ++ )
436
+ if (metap -> hashm_mapp [i ] == ovflblkno )
437
+ ereport (ERROR ,
438
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
439
+ errmsg ("invalid overflow block number %u" ,
440
+ (BlockNumber ) ovflblkno )));
441
+
442
+ /*
443
+ * Identify overflow bit number. This will error out for primary bucket
444
+ * pages, and we've already rejected the metapage and bitmap pages above.
445
+ */
445
446
ovflbitno = _hash_ovflblkno_to_bitno (metap , (BlockNumber ) ovflblkno );
446
447
447
448
bitmappage = ovflbitno >> BMPG_SHIFT (metap );
@@ -450,12 +451,21 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
450
451
if (bitmappage >= metap -> hashm_nmaps )
451
452
ereport (ERROR ,
452
453
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
453
- errmsg ("invalid overflow bit number %u" , ovflbitno )));
454
+ errmsg ("invalid overflow block number %u" ,
455
+ (BlockNumber ) ovflblkno )));
454
456
455
457
bitmapblkno = metap -> hashm_mapp [bitmappage ];
456
458
457
459
_hash_relbuf (indexRel , metabuf );
458
460
461
+ /* Check the status of bitmap bit for overflow page */
462
+ mapbuf = _hash_getbuf (indexRel , bitmapblkno , HASH_READ , LH_BITMAP_PAGE );
463
+ mappage = BufferGetPage (mapbuf );
464
+ freep = HashPageGetBitmap (mappage );
465
+
466
+ bit = ISSET (freep , bitmapbit ) != 0 ;
467
+
468
+ _hash_relbuf (indexRel , mapbuf );
459
469
index_close (indexRel , AccessShareLock );
460
470
461
471
/* Build a tuple descriptor for our result type */
0 commit comments