LCOV - differential code coverage report
Current view: top level - contrib/pageinspect - hashfuncs.c (source / functions) Coverage Total Hit LBC UIC UBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.9 % 209 167 4 14 24 46 6 115 16 41 2 7
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 12 12 3 1 8 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 79.9 % 209 167 4 14 24 46 6 115 16 41
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 80.0 % 15 12 3 1 8 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * hashfuncs.c
                                  3                 :  *      Functions to investigate the content of HASH indexes
                                  4                 :  *
                                  5                 :  * Copyright (c) 2017-2023, PostgreSQL Global Development Group
                                  6                 :  *
                                  7                 :  * IDENTIFICATION
                                  8                 :  *      contrib/pageinspect/hashfuncs.c
                                  9                 :  */
                                 10                 : 
                                 11                 : #include "postgres.h"
                                 12                 : 
                                 13                 : #include "access/hash.h"
                                 14                 : #include "access/htup_details.h"
                                 15                 : #include "catalog/pg_am.h"
                                 16                 : #include "catalog/pg_type.h"
                                 17                 : #include "funcapi.h"
                                 18                 : #include "miscadmin.h"
                                 19                 : #include "pageinspect.h"
                                 20                 : #include "utils/array.h"
                                 21                 : #include "utils/builtins.h"
                                 22                 : #include "utils/rel.h"
                                 23                 : 
 2257 rhaas                      24 CBC           7 : PG_FUNCTION_INFO_V1(hash_page_type);
                                 25               7 : PG_FUNCTION_INFO_V1(hash_page_stats);
                                 26               7 : PG_FUNCTION_INFO_V1(hash_page_items);
                                 27               7 : PG_FUNCTION_INFO_V1(hash_bitmap_info);
                                 28               7 : PG_FUNCTION_INFO_V1(hash_metapage_info);
                                 29                 : 
                                 30                 : #define IS_HASH(r) ((r)->rd_rel->relam == HASH_AM_OID)
                                 31                 : 
                                 32                 : /* ------------------------------------------------
                                 33                 :  * structure for single hash page statistics
                                 34                 :  * ------------------------------------------------
                                 35                 :  */
                                 36                 : typedef struct HashPageStat
                                 37                 : {
                                 38                 :     int         live_items;
                                 39                 :     int         dead_items;
                                 40                 :     int         page_size;
                                 41                 :     int         free_size;
                                 42                 : 
                                 43                 :     /* opaque data */
                                 44                 :     BlockNumber hasho_prevblkno;
                                 45                 :     BlockNumber hasho_nextblkno;
                                 46                 :     Bucket      hasho_bucket;
                                 47                 :     uint16      hasho_flag;
                                 48                 :     uint16      hasho_page_id;
                                 49                 : } HashPageStat;
                                 50                 : 
                                 51                 : 
                                 52                 : /*
                                 53                 :  * Verify that the given bytea contains a HASH page, or die in the attempt.
                                 54                 :  * A pointer to a palloc'd, properly aligned copy of the page is returned.
                                 55                 :  */
                                 56                 : static Page
                                 57              36 : verify_hash_page(bytea *raw_page, int flags)
                                 58                 : {
 2256 tgl                        59              36 :     Page        page = get_page_from_raw(raw_page);
 2195 rhaas                      60              32 :     int         pagetype = LH_UNUSED_PAGE;
                                 61                 : 
                                 62                 :     /* Treat new pages as unused. */
                                 63              32 :     if (!PageIsNew(page))
                                 64                 :     {
                                 65                 :         HashPageOpaque pageopaque;
                                 66                 : 
                                 67              28 :         if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData)))
                                 68               4 :             ereport(ERROR,
                                 69                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 70                 :                      errmsg("input page is not a valid %s page", "hash"),
                                 71                 :                      errdetail("Expected special size %d, got %d.",
                                 72                 :                                (int) MAXALIGN(sizeof(HashPageOpaqueData)),
                                 73                 :                                (int) PageGetSpecialSize(page))));
                                 74                 : 
  373 michael                    75              24 :         pageopaque = HashPageGetOpaque(page);
 2195 rhaas                      76              24 :         if (pageopaque->hasho_page_id != HASHO_PAGE_ID)
 2195 rhaas                      77 UBC           0 :             ereport(ERROR,
                                 78                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 79                 :                      errmsg("input page is not a valid %s page", "hash"),
                                 80                 :                      errdetail("Expected %08x, got %08x.",
                                 81                 :                                HASHO_PAGE_ID, pageopaque->hasho_page_id)));
                                 82                 : 
 2195 rhaas                      83 CBC          24 :         pagetype = pageopaque->hasho_flag & LH_PAGE_TYPE;
                                 84                 :     }
                                 85                 : 
                                 86                 :     /* Check that page type is sane. */
 2257                            87              28 :     if (pagetype != LH_OVERFLOW_PAGE && pagetype != LH_BUCKET_PAGE &&
 2195                            88               8 :         pagetype != LH_BITMAP_PAGE && pagetype != LH_META_PAGE &&
                                 89                 :         pagetype != LH_UNUSED_PAGE)
 2257 rhaas                      90 UBC           0 :         ereport(ERROR,
                                 91                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 92                 :                  errmsg("invalid hash page type %08x", pagetype)));
                                 93                 : 
                                 94                 :     /* If requested, verify page type. */
 2257 rhaas                      95 CBC          28 :     if (flags != 0 && (pagetype & flags) == 0)
                                 96                 :     {
                                 97              12 :         switch (flags)
                                 98                 :         {
                                 99               6 :             case LH_META_PAGE:
                                100               6 :                 ereport(ERROR,
                                101                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                102                 :                          errmsg("page is not a hash meta page")));
                                103                 :                 break;
                                104               6 :             case LH_BUCKET_PAGE | LH_OVERFLOW_PAGE:
                                105               6 :                 ereport(ERROR,
                                106                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                107                 :                          errmsg("page is not a hash bucket or overflow page")));
                                108                 :                 break;
 2257 rhaas                     109 UBC           0 :             case LH_OVERFLOW_PAGE:
                                110               0 :                 ereport(ERROR,
                                111                 :                         (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                112                 :                          errmsg("page is not a hash overflow page")));
                                113                 :                 break;
                                114               0 :             default:
                                115               0 :                 elog(ERROR,
                                116                 :                      "hash page of type %08x not in mask %08x",
                                117                 :                      pagetype, flags);
                                118                 :                 break;
                                119                 :         }
                                120                 :     }
                                121                 : 
                                122                 :     /*
                                123                 :      * If it is the metapage, also verify magic number and version.
                                124                 :      */
 2257 rhaas                     125 CBC          16 :     if (pagetype == LH_META_PAGE)
                                126                 :     {
                                127               2 :         HashMetaPage metap = HashPageGetMeta(page);
                                128                 : 
                                129               2 :         if (metap->hashm_magic != HASH_MAGIC)
 2257 rhaas                     130 UBC           0 :             ereport(ERROR,
                                131                 :                     (errcode(ERRCODE_INDEX_CORRUPTED),
                                132                 :                      errmsg("invalid magic number for metadata"),
                                133                 :                      errdetail("Expected 0x%08x, got 0x%08x.",
                                134                 :                                HASH_MAGIC, metap->hashm_magic)));
                                135                 : 
 2257 rhaas                     136 CBC           2 :         if (metap->hashm_version != HASH_VERSION)
 2257 rhaas                     137 UBC           0 :             ereport(ERROR,
                                138                 :                     (errcode(ERRCODE_INDEX_CORRUPTED),
                                139                 :                      errmsg("invalid version for metadata"),
                                140                 :                      errdetail("Expected %d, got %d.",
                                141                 :                                HASH_VERSION, metap->hashm_version)));
                                142                 :     }
                                143                 : 
 2257 rhaas                     144 CBC          16 :     return page;
                                145                 : }
                                146                 : 
                                147                 : /* -------------------------------------------------
                                148                 :  * GetHashPageStatistics()
                                149                 :  *
                                150                 :  * Collect statistics of single hash page
                                151                 :  * -------------------------------------------------
                                152                 :  */
                                153                 : static void
 2153 bruce                     154               4 : GetHashPageStatistics(Page page, HashPageStat *stat)
                                155                 : {
 2257 rhaas                     156               4 :     OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
  373 michael                   157               4 :     HashPageOpaque opaque = HashPageGetOpaque(page);
                                158                 :     int         off;
                                159                 : 
 2257 rhaas                     160               4 :     stat->dead_items = stat->live_items = 0;
                                161               4 :     stat->page_size = PageGetPageSize(page);
                                162                 : 
                                163                 :     /* hash page opaque data */
                                164               4 :     stat->hasho_prevblkno = opaque->hasho_prevblkno;
                                165               4 :     stat->hasho_nextblkno = opaque->hasho_nextblkno;
                                166               4 :     stat->hasho_bucket = opaque->hasho_bucket;
                                167               4 :     stat->hasho_flag = opaque->hasho_flag;
                                168               4 :     stat->hasho_page_id = opaque->hasho_page_id;
                                169                 : 
                                170                 :     /* count live and dead tuples, and free space */
                                171               5 :     for (off = FirstOffsetNumber; off <= maxoff; off++)
                                172                 :     {
                                173               1 :         ItemId      id = PageGetItemId(page, off);
                                174                 : 
                                175               1 :         if (!ItemIdIsDead(id))
                                176               1 :             stat->live_items++;
                                177                 :         else
 2257 rhaas                     178 UBC           0 :             stat->dead_items++;
                                179                 :     }
 2257 rhaas                     180 CBC           4 :     stat->free_size = PageGetFreeSpace(page);
                                181               4 : }
                                182                 : 
                                183                 : /* ---------------------------------------------------
                                184                 :  * hash_page_type()
                                185                 :  *
                                186                 :  * Usage: SELECT hash_page_type(get_raw_page('con_hash_index', 1));
                                187                 :  * ---------------------------------------------------
                                188                 :  */
                                189                 : Datum
                                190               9 : hash_page_type(PG_FUNCTION_ARGS)
                                191                 : {
                                192               9 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                193                 :     Page        page;
                                194                 :     HashPageOpaque opaque;
                                195                 :     int         pagetype;
                                196                 :     const char *type;
                                197                 : 
                                198               9 :     if (!superuser())
 2257 rhaas                     199 UBC           0 :         ereport(ERROR,
                                200                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                201                 :                  errmsg("must be superuser to use raw page functions")));
                                202                 : 
 2257 rhaas                     203 CBC           9 :     page = verify_hash_page(raw_page, 0);
                                204                 : 
 2195                           205               7 :     if (PageIsNew(page))
 2257                           206               1 :         type = "unused";
                                207                 :     else
                                208                 :     {
  373 michael                   209               6 :         opaque = HashPageGetOpaque(page);
                                210                 : 
                                211                 :         /* page type (flags) */
 2186 tgl                       212               6 :         pagetype = opaque->hasho_flag & LH_PAGE_TYPE;
                                213               6 :         if (pagetype == LH_META_PAGE)
 2195 rhaas                     214               1 :             type = "metapage";
 2186 tgl                       215               5 :         else if (pagetype == LH_OVERFLOW_PAGE)
 2195 rhaas                     216 UBC           0 :             type = "overflow";
 2186 tgl                       217 CBC           5 :         else if (pagetype == LH_BUCKET_PAGE)
 2195 rhaas                     218               4 :             type = "bucket";
 2186 tgl                       219               1 :         else if (pagetype == LH_BITMAP_PAGE)
 2195 rhaas                     220               1 :             type = "bitmap";
                                221                 :         else
 2195 rhaas                     222 UBC           0 :             type = "unused";
                                223                 :     }
                                224                 : 
 2257 rhaas                     225 CBC           7 :     PG_RETURN_TEXT_P(cstring_to_text(type));
                                226                 : }
                                227                 : 
                                228                 : /* ---------------------------------------------------
                                229                 :  * hash_page_stats()
                                230                 :  *
                                231                 :  * Usage: SELECT * FROM hash_page_stats(get_raw_page('con_hash_index', 1));
                                232                 :  * ---------------------------------------------------
                                233                 :  */
                                234                 : Datum
                                235               9 : hash_page_stats(PG_FUNCTION_ARGS)
                                236                 : {
                                237               9 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                238                 :     Page        page;
                                239                 :     int         j;
                                240                 :     Datum       values[9];
  267 peter                     241 GNC           9 :     bool        nulls[9] = {0};
                                242                 :     HashPageStat stat;
                                243                 :     HeapTuple   tuple;
                                244                 :     TupleDesc   tupleDesc;
                                245                 : 
 2257 rhaas                     246 CBC           9 :     if (!superuser())
 2257 rhaas                     247 UBC           0 :         ereport(ERROR,
                                248                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                249                 :                  errmsg("must be superuser to use raw page functions")));
                                250                 : 
 2257 rhaas                     251 CBC           9 :     page = verify_hash_page(raw_page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
                                252                 : 
                                253                 :     /* keep compiler quiet */
                                254               4 :     stat.hasho_prevblkno = stat.hasho_nextblkno = InvalidBlockNumber;
                                255               4 :     stat.hasho_flag = stat.hasho_page_id = stat.free_size = 0;
                                256                 : 
                                257               4 :     GetHashPageStatistics(page, &stat);
                                258                 : 
                                259                 :     /* Build a tuple descriptor for our result type */
                                260               4 :     if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
 2257 rhaas                     261 UBC           0 :         elog(ERROR, "return type must be a row type");
 2257 rhaas                     262 CBC           4 :     tupleDesc = BlessTupleDesc(tupleDesc);
                                263                 : 
                                264               4 :     j = 0;
                                265               4 :     values[j++] = Int32GetDatum(stat.live_items);
                                266               4 :     values[j++] = Int32GetDatum(stat.dead_items);
                                267               4 :     values[j++] = Int32GetDatum(stat.page_size);
                                268               4 :     values[j++] = Int32GetDatum(stat.free_size);
                                269               4 :     values[j++] = Int64GetDatum((int64) stat.hasho_prevblkno);
                                270               4 :     values[j++] = Int64GetDatum((int64) stat.hasho_nextblkno);
                                271               4 :     values[j++] = Int64GetDatum((int64) stat.hasho_bucket);
 2257 rhaas                     272 GIC           4 :     values[j++] = Int32GetDatum((int32) stat.hasho_flag);
 2257 rhaas                     273 CBC           4 :     values[j++] = Int32GetDatum((int32) stat.hasho_page_id);
                                274                 : 
                                275               4 :     tuple = heap_form_tuple(tupleDesc, values, nulls);
                                276                 : 
 2257 rhaas                     277 GIC           4 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
                                278                 : }
                                279                 : 
                                280                 : /*
                                281                 :  * cross-call data structure for SRF
                                282                 :  */
                                283                 : struct user_args
                                284                 : {
                                285                 :     Page        page;
                                286                 :     OffsetNumber offset;
                                287                 : };
                                288                 : 
                                289                 : /*-------------------------------------------------------
                                290                 :  * hash_page_items()
                                291                 :  *
                                292                 :  * Get IndexTupleData set in a hash page
                                293                 :  *
                                294                 :  * Usage: SELECT * FROM hash_page_items(get_raw_page('con_hash_index', 1));
                                295                 :  *-------------------------------------------------------
 2257 rhaas                     296 ECB             :  */
                                297                 : Datum
 2257 rhaas                     298 CBC          10 : hash_page_items(PG_FUNCTION_ARGS)
                                299                 : {
 2257 rhaas                     300 GIC          10 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                301                 :     Page        page;
 2257 rhaas                     302 ECB             :     Datum       result;
                                303                 :     Datum       values[3];
  267 peter                     304 GNC          10 :     bool        nulls[3] = {0};
                                305                 :     uint32      hashkey;
                                306                 :     HeapTuple   tuple;
                                307                 :     FuncCallContext *fctx;
                                308                 :     MemoryContext mctx;
 2257 rhaas                     309 ECB             :     struct user_args *uargs;
 2257 rhaas                     310 EUB             : 
 2257 rhaas                     311 GIC          10 :     if (!superuser())
 2257 rhaas                     312 UIC           0 :         ereport(ERROR,
                                313                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 1165 alvherre                  314 ECB             :                  errmsg("must be superuser to use raw page functions")));
                                315                 : 
 2257 rhaas                     316 GIC          10 :     if (SRF_IS_FIRSTCALL())
                                317                 :     {
 2257 rhaas                     318 ECB             :         TupleDesc   tupleDesc;
                                319                 : 
 2257 rhaas                     320 CBC           9 :         fctx = SRF_FIRSTCALL_INIT();
                                321                 : 
                                322               9 :         mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
                                323                 : 
 1899                           324               9 :         page = verify_hash_page(raw_page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
                                325                 : 
 2257                           326               4 :         uargs = palloc(sizeof(struct user_args));
                                327                 : 
                                328               4 :         uargs->page = page;
                                329                 : 
                                330               4 :         uargs->offset = FirstOffsetNumber;
                                331                 : 
 2257 rhaas                     332 GIC           4 :         fctx->max_calls = PageGetMaxOffsetNumber(uargs->page);
 2257 rhaas                     333 ECB             : 
 2257 rhaas                     334 EUB             :         /* Build a tuple descriptor for our result type */
 2257 rhaas                     335 CBC           4 :         if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
 2257 rhaas                     336 UIC           0 :             elog(ERROR, "return type must be a row type");
 2257 rhaas                     337 CBC           4 :         tupleDesc = BlessTupleDesc(tupleDesc);
                                338                 : 
                                339               4 :         fctx->attinmeta = TupleDescGetAttInMetadata(tupleDesc);
                                340                 : 
                                341               4 :         fctx->user_fctx = uargs;
                                342                 : 
 2257 rhaas                     343 GIC           4 :         MemoryContextSwitchTo(mctx);
 2257 rhaas                     344 ECB             :     }
                                345                 : 
 2257 rhaas                     346 GIC           5 :     fctx = SRF_PERCALL_SETUP();
 2257 rhaas                     347 CBC           5 :     uargs = fctx->user_fctx;
                                348                 : 
 2257 rhaas                     349 GIC           5 :     if (fctx->call_cntr < fctx->max_calls)
                                350                 :     {
                                351                 :         ItemId      id;
                                352                 :         IndexTuple  itup;
 2257 rhaas                     353 ECB             :         int         j;
                                354                 : 
 2257 rhaas                     355 CBC           1 :         id = PageGetItemId(uargs->page, uargs->offset);
 2257 rhaas                     356 EUB             : 
 2257 rhaas                     357 GIC           1 :         if (!ItemIdIsValid(id))
 2257 rhaas                     358 LBC           0 :             elog(ERROR, "invalid ItemId");
                                359                 : 
 2257 rhaas                     360 CBC           1 :         itup = (IndexTuple) PageGetItem(uargs->page, id);
 2257 rhaas                     361 ECB             : 
 2257 rhaas                     362 CBC           1 :         j = 0;
 2256                           363               1 :         values[j++] = Int32GetDatum((int32) uargs->offset);
 2257 rhaas                     364 GIC           1 :         values[j++] = PointerGetDatum(&itup->t_tid);
 2257 rhaas                     365 ECB             : 
 2257 rhaas                     366 CBC           1 :         hashkey = _hash_get_indextuple_hashkey(itup);
 2256 rhaas                     367 GIC           1 :         values[j] = Int64GetDatum((int64) hashkey);
 2257 rhaas                     368 ECB             : 
 2257 rhaas                     369 GIC           1 :         tuple = heap_form_tuple(fctx->attinmeta->tupdesc, values, nulls);
 2257 rhaas                     370 CBC           1 :         result = HeapTupleGetDatum(tuple);
                                371                 : 
 2257 rhaas                     372 GIC           1 :         uargs->offset = uargs->offset + 1;
 2257 rhaas                     373 ECB             : 
 2257 rhaas                     374 GIC           1 :         SRF_RETURN_NEXT(fctx, result);
                                375                 :     }
                                376                 : 
 1119 tgl                       377               4 :     SRF_RETURN_DONE(fctx);
                                378                 : }
                                379                 : 
                                380                 : /* ------------------------------------------------
                                381                 :  * hash_bitmap_info()
                                382                 :  *
                                383                 :  * Get bitmap information for a particular overflow page
                                384                 :  *
 2257 rhaas                     385 ECB             :  * Usage: SELECT * FROM hash_bitmap_info('con_hash_index'::regclass, 5);
                                386                 :  * ------------------------------------------------
                                387                 :  */
                                388                 : Datum
 2257 rhaas                     389 GIC           9 : hash_bitmap_info(PG_FUNCTION_ARGS)
                                390                 : {
                                391               9 :     Oid         indexRelid = PG_GETARG_OID(0);
  810 peter                     392               9 :     int64       ovflblkno = PG_GETARG_INT64(1);
                                393                 :     HashMetaPage metap;
 2250 rhaas                     394 ECB             :     Buffer      metabuf,
                                395                 :                 mapbuf;
                                396                 :     BlockNumber bitmapblkno;
                                397                 :     Page        mappage;
 2257 rhaas                     398 GIC           9 :     bool        bit = false;
                                399                 :     TupleDesc   tupleDesc;
                                400                 :     Relation    indexRel;
                                401                 :     uint32      ovflbitno;
                                402                 :     int32       bitmappage,
                                403                 :                 bitmapbit;
 2257 rhaas                     404 ECB             :     HeapTuple   tuple;
                                405                 :     int         i,
                                406                 :                 j;
                                407                 :     Datum       values[3];
  267 peter                     408 GNC           9 :     bool        nulls[3] = {0};
                                409                 :     uint32     *freep;
                                410                 : 
 2257 rhaas                     411 GIC           9 :     if (!superuser())
 2257 rhaas                     412 LBC           0 :         ereport(ERROR,
                                413                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 1165 alvherre                  414 ECB             :                  errmsg("must be superuser to use raw page functions")));
 2257 rhaas                     415                 : 
 2257 rhaas                     416 GIC           9 :     indexRel = index_open(indexRelid, AccessShareLock);
                                417                 : 
                                418               9 :     if (!IS_HASH(indexRel))
  389 michael                   419               1 :         ereport(ERROR,
  389 michael                   420 ECB             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
  389 michael                   421 EUB             :                  errmsg("\"%s\" is not a %s index",
                                422                 :                         RelationGetRelationName(indexRel), "hash")));
                                423                 : 
 2257 rhaas                     424 GIC           8 :     if (RELATION_IS_OTHER_TEMP(indexRel))
 2257 rhaas                     425 LBC           0 :         ereport(ERROR,
 2257 rhaas                     426 ECB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                427                 :                  errmsg("cannot access temporary tables of other sessions")));
                                428                 : 
  810 peter                     429 GIC           8 :     if (ovflblkno < 0 || ovflblkno > MaxBlockNumber)
  810 peter                     430 CBC           1 :         ereport(ERROR,
  810 peter                     431 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                432                 :                  errmsg("invalid block number")));
                                433                 : 
 2257 tgl                       434 GIC           7 :     if (ovflblkno >= RelationGetNumberOfBlocks(indexRel))
      rhaas                     435               1 :         ereport(ERROR,
                                436                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  810 peter                     437 ECB             :                  errmsg("block number %lld is out of range for relation \"%s\"",
                                438                 :                         (long long int) ovflblkno, RelationGetRelationName(indexRel))));
                                439                 : 
                                440                 :     /* Read the metapage so we can determine which bitmap page to use */
 2257 rhaas                     441 GIC           6 :     metabuf = _hash_getbuf(indexRel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
                                442               6 :     metap = HashPageGetMeta(BufferGetPage(metabuf));
                                443                 : 
 2250 rhaas                     444 ECB             :     /*
                                445                 :      * Reject attempt to read the bit for a metapage or bitmap page; this is
                                446                 :      * only meaningful for overflow pages.
                                447                 :      */
 2250 rhaas                     448 GIC           6 :     if (ovflblkno == 0)
 2250 rhaas                     449 CBC           1 :         ereport(ERROR,
 2250 rhaas                     450 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                451                 :                  errmsg("invalid overflow block number %u",
                                452                 :                         (BlockNumber) ovflblkno)));
 2250 rhaas                     453 GIC           9 :     for (i = 0; i < metap->hashm_nmaps; i++)
                                454               5 :         if (metap->hashm_mapp[i] == ovflblkno)
                                455               1 :             ereport(ERROR,
                                456                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                457                 :                      errmsg("invalid overflow block number %u",
                                458                 :                             (BlockNumber) ovflblkno)));
                                459                 : 
 2250 rhaas                     460 ECB             :     /*
                                461                 :      * Identify overflow bit number.  This will error out for primary bucket
 2250 rhaas                     462 EUB             :      * pages, and we've already rejected the metapage and bitmap pages above.
                                463                 :      */
 2257 tgl                       464 GIC           4 :     ovflbitno = _hash_ovflblkno_to_bitno(metap, (BlockNumber) ovflblkno);
 2257 rhaas                     465 EUB             : 
 2257 rhaas                     466 UBC           0 :     bitmappage = ovflbitno >> BMPG_SHIFT(metap);
 2257 rhaas                     467 UIC           0 :     bitmapbit = ovflbitno & BMPG_MASK(metap);
                                468                 : 
                                469               0 :     if (bitmappage >= metap->hashm_nmaps)
                                470               0 :         ereport(ERROR,
 2257 rhaas                     471 EUB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                472                 :                  errmsg("invalid overflow block number %u",
 2250                           473                 :                         (BlockNumber) ovflblkno)));
                                474                 : 
 2257 rhaas                     475 UIC           0 :     bitmapblkno = metap->hashm_mapp[bitmappage];
 2257 rhaas                     476 EUB             : 
 2257 rhaas                     477 UBC           0 :     _hash_relbuf(indexRel, metabuf);
 2257 rhaas                     478 EUB             : 
                                479                 :     /* Check the status of bitmap bit for overflow page */
 2250 rhaas                     480 UBC           0 :     mapbuf = _hash_getbuf(indexRel, bitmapblkno, HASH_READ, LH_BITMAP_PAGE);
 2250 rhaas                     481 UIC           0 :     mappage = BufferGetPage(mapbuf);
 2250 rhaas                     482 UBC           0 :     freep = HashPageGetBitmap(mappage);
 2250 rhaas                     483 EUB             : 
 2250 rhaas                     484 UIC           0 :     bit = ISSET(freep, bitmapbit) != 0;
                                485                 : 
 2250 rhaas                     486 UBC           0 :     _hash_relbuf(indexRel, mapbuf);
 2257                           487               0 :     index_close(indexRel, AccessShareLock);
 2257 rhaas                     488 EUB             : 
                                489                 :     /* Build a tuple descriptor for our result type */
 2257 rhaas                     490 UBC           0 :     if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
                                491               0 :         elog(ERROR, "return type must be a row type");
                                492               0 :     tupleDesc = BlessTupleDesc(tupleDesc);
 2257 rhaas                     493 EUB             : 
 2257 rhaas                     494 UIC           0 :     j = 0;
 2256 rhaas                     495 UBC           0 :     values[j++] = Int64GetDatum((int64) bitmapblkno);
 2257 rhaas                     496 UIC           0 :     values[j++] = Int32GetDatum(bitmapbit);
                                497               0 :     values[j++] = BoolGetDatum(bit);
                                498                 : 
                                499               0 :     tuple = heap_form_tuple(tupleDesc, values, nulls);
                                500                 : 
                                501               0 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
                                502                 : }
                                503                 : 
                                504                 : /* ------------------------------------------------
                                505                 :  * hash_metapage_info()
                                506                 :  *
 2257 rhaas                     507 ECB             :  * Get the meta-page information for a hash index
                                508                 :  *
                                509                 :  * Usage: SELECT * FROM hash_metapage_info(get_raw_page('con_hash_index', 0))
                                510                 :  * ------------------------------------------------
                                511                 :  */
                                512                 : Datum
 2257 rhaas                     513 GIC           9 : hash_metapage_info(PG_FUNCTION_ARGS)
                                514                 : {
                                515               9 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                516                 :     Page        page;
 2257 rhaas                     517 ECB             :     HashMetaPageData *metad;
                                518                 :     TupleDesc   tupleDesc;
                                519                 :     HeapTuple   tuple;
                                520                 :     int         i,
                                521                 :                 j;
 2257 rhaas                     522 EUB             :     Datum       values[16];
  267 peter                     523 GNC           9 :     bool        nulls[16] = {0};
                                524                 :     Datum       spares[HASH_MAX_SPLITPOINTS];
                                525                 :     Datum       mapp[HASH_MAX_BITMAPS];
 2257 rhaas                     526 ECB             : 
 2257 rhaas                     527 GIC           9 :     if (!superuser())
 2257 rhaas                     528 UIC           0 :         ereport(ERROR,
 2257 rhaas                     529 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 1165 alvherre                  530 EUB             :                  errmsg("must be superuser to use raw page functions")));
 2257 rhaas                     531 ECB             : 
 2257 rhaas                     532 GIC           9 :     page = verify_hash_page(raw_page, LH_META_PAGE);
 2257 rhaas                     533 ECB             : 
                                534                 :     /* Build a tuple descriptor for our result type */
 2257 rhaas                     535 CBC           1 :     if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
 2257 rhaas                     536 LBC           0 :         elog(ERROR, "return type must be a row type");
 2257 rhaas                     537 CBC           1 :     tupleDesc = BlessTupleDesc(tupleDesc);
 2257 rhaas                     538 ECB             : 
 2257 rhaas                     539 CBC           1 :     metad = HashPageGetMeta(page);
 2257 rhaas                     540 ECB             : 
 2257 rhaas                     541 CBC           1 :     j = 0;
 2256                           542               1 :     values[j++] = Int64GetDatum((int64) metad->hashm_magic);
                                543               1 :     values[j++] = Int64GetDatum((int64) metad->hashm_version);
 2257                           544               1 :     values[j++] = Float8GetDatum(metad->hashm_ntuples);
 2256                           545               1 :     values[j++] = Int32GetDatum((int32) metad->hashm_ffactor);
                                546               1 :     values[j++] = Int32GetDatum((int32) metad->hashm_bsize);
                                547               1 :     values[j++] = Int32GetDatum((int32) metad->hashm_bmsize);
 2256 rhaas                     548 GIC           1 :     values[j++] = Int32GetDatum((int32) metad->hashm_bmshift);
 2256 rhaas                     549 CBC           1 :     values[j++] = Int64GetDatum((int64) metad->hashm_maxbucket);
                                550               1 :     values[j++] = Int64GetDatum((int64) metad->hashm_highmask);
                                551               1 :     values[j++] = Int64GetDatum((int64) metad->hashm_lowmask);
 2256 rhaas                     552 GIC           1 :     values[j++] = Int64GetDatum((int64) metad->hashm_ovflpoint);
 2256 rhaas                     553 CBC           1 :     values[j++] = Int64GetDatum((int64) metad->hashm_firstfree);
                                554               1 :     values[j++] = Int64GetDatum((int64) metad->hashm_nmaps);
                                555               1 :     values[j++] = ObjectIdGetDatum((Oid) metad->hashm_procid);
                                556                 : 
 2257                           557              99 :     for (i = 0; i < HASH_MAX_SPLITPOINTS; i++)
 2237 rhaas                     558 GIC          98 :         spares[i] = Int64GetDatum((int64) metad->hashm_spares[i]);
  282 peter                     559 GNC           1 :     values[j++] = PointerGetDatum(construct_array_builtin(spares, HASH_MAX_SPLITPOINTS, INT8OID));
                                560                 : 
 2257 rhaas                     561 GIC        1025 :     for (i = 0; i < HASH_MAX_BITMAPS; i++)
 2256                           562            1024 :         mapp[i] = Int64GetDatum((int64) metad->hashm_mapp[i]);
  282 peter                     563 GNC           1 :     values[j++] = PointerGetDatum(construct_array_builtin(mapp, HASH_MAX_BITMAPS, INT8OID));
                                564                 : 
 2257 rhaas                     565 GIC           1 :     tuple = heap_form_tuple(tupleDesc, values, nulls);
                                566                 : 
                                567               1 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
                                568                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a