LCOV - differential code coverage report
Current view: top level - contrib/pageinspect - gistfuncs.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 87.0 % 115 100 7 5 3 4 56 1 39 8 53 1
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 7 7 4 3 4
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 93.8 % 16 15 1 10 5 1 7
Legend: Lines: hit not hit (120,180] days: 100.0 % 2 2 1 1
(240..) days: 85.6 % 97 83 7 4 3 4 45 1 33 7 46
Function coverage date bins:
[..60] days: 50.0 % 4 2 2 2
(240..) days: 71.4 % 7 5 2 3 2

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * gistfuncs.c
                                  3                 :  *      Functions to investigate the content of GiST indexes
                                  4                 :  *
                                  5                 :  * Copyright (c) 2014-2023, PostgreSQL Global Development Group
                                  6                 :  *
                                  7                 :  * IDENTIFICATION
                                  8                 :  *      contrib/pageinspect/gistfuncs.c
                                  9                 :  */
                                 10                 : #include "postgres.h"
                                 11                 : 
                                 12                 : #include "access/gist.h"
                                 13                 : #include "access/gist_private.h"
                                 14                 : #include "access/htup.h"
                                 15                 : #include "access/relation.h"
                                 16                 : #include "catalog/namespace.h"
                                 17                 : #include "catalog/pg_am_d.h"
                                 18                 : #include "funcapi.h"
                                 19                 : #include "miscadmin.h"
                                 20                 : #include "pageinspect.h"
                                 21                 : #include "storage/itemptr.h"
                                 22                 : #include "utils/array.h"
                                 23                 : #include "utils/builtins.h"
                                 24                 : #include "utils/rel.h"
                                 25                 : #include "utils/pg_lsn.h"
                                 26                 : #include "utils/varlena.h"
                                 27                 : 
  816 heikki.linnakangas         28 CBC           7 : PG_FUNCTION_INFO_V1(gist_page_opaque_info);
                                 29               7 : PG_FUNCTION_INFO_V1(gist_page_items);
                                 30               7 : PG_FUNCTION_INFO_V1(gist_page_items_bytea);
                                 31                 : 
                                 32                 : #define IS_GIST(r) ((r)->rd_rel->relam == GIST_AM_OID)
                                 33                 : 
                                 34                 : 
                                 35                 : static Page verify_gist_page(bytea *raw_page);
                                 36                 : 
                                 37                 : /*
                                 38                 :  * Verify that the given bytea contains a GIST page or die in the attempt.
                                 39                 :  * A pointer to the page is returned.
   38 michael                    40 ECB             :  */
                                 41                 : static Page
   38 michael                    42 CBC          16 : verify_gist_page(bytea *raw_page)
                                 43                 : {
   38 michael                    44 GIC          16 :     Page        page = get_page_from_raw(raw_page);
  816 heikki.linnakangas         45 ECB             :     GISTPageOpaque opaq;
                                 46                 : 
  360 michael                    47 GIC          13 :     if (PageIsNew(page))
   38                            48               3 :         return page;
  360 michael                    49 ECB             : 
  378                            50                 :     /* verify the special space has the expected size */
  378 michael                    51 GIC          10 :     if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
  332 tgl                        52               2 :         ereport(ERROR,
                                 53                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 54                 :                  errmsg("input page is not a valid %s page", "GiST"),
                                 55                 :                  errdetail("Expected special size %d, got %d.",
                                 56                 :                            (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
  332 tgl                        57 ECB             :                            (int) PageGetSpecialSize(page))));
  378 michael                    58                 : 
  372 michael                    59 CBC           8 :     opaq = GistPageGetOpaque(page);
  378 michael                    60 GIC           8 :     if (opaq->gist_page_id != GIST_PAGE_ID)
  332 tgl                        61               2 :         ereport(ERROR,
                                 62                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 63                 :                  errmsg("input page is not a valid %s page", "GiST"),
                                 64                 :                  errdetail("Expected %08x, got %08x.",
                                 65                 :                            GIST_PAGE_ID,
  332 tgl                        66 ECB             :                            opaq->gist_page_id)));
                                 67                 : 
   38 michael                    68 GIC           6 :     return page;
                                 69                 : }
   38 michael                    70 ECB             : 
                                 71                 : Datum
   38 michael                    72 CBC           6 : gist_page_opaque_info(PG_FUNCTION_ARGS)
                                 73                 : {
   38 michael                    74 GIC           6 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                 75                 :     TupleDesc   tupdesc;
                                 76                 :     Page        page;
                                 77                 :     HeapTuple   resultTuple;
                                 78                 :     Datum       values[4];
   38 michael                    79 ECB             :     bool        nulls[4];
                                 80                 :     Datum       flags[16];
   38 michael                    81 GIC           6 :     int         nflags = 0;
   38 michael                    82 ECB             :     uint16      flagbits;
   38 michael                    83 EUB             : 
   38 michael                    84 GIC           6 :     if (!superuser())
   38 michael                    85 UIC           0 :         ereport(ERROR,
                                 86                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
   38 michael                    87 ECB             :                  errmsg("must be superuser to use raw page functions")));
                                 88                 : 
   38 michael                    89 CBC           6 :     page = verify_gist_page(raw_page);
   38 michael                    90 ECB             : 
   38 michael                    91 GIC           4 :     if (PageIsNew(page))
                                 92               1 :         PG_RETURN_NULL();
   38 michael                    93 ECB             : 
  816 heikki.linnakangas         94 EUB             :     /* Build a tuple descriptor for our result type */
  816 heikki.linnakangas         95 GIC           3 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  816 heikki.linnakangas         96 UIC           0 :         elog(ERROR, "return type must be a row type");
  816 heikki.linnakangas         97 ECB             : 
                                 98                 :     /* Convert the flags bitmask to an array of human-readable names */
   38 michael                    99 CBC           3 :     flagbits = GistPageGetOpaque(page)->flags;
  816 heikki.linnakangas        100               3 :     if (flagbits & F_LEAF)
  816 heikki.linnakangas        101 GBC           2 :         flags[nflags++] = CStringGetTextDatum("leaf");
  816 heikki.linnakangas        102 CBC           3 :     if (flagbits & F_DELETED)
  816 heikki.linnakangas        103 UBC           0 :         flags[nflags++] = CStringGetTextDatum("deleted");
  816 heikki.linnakangas        104 CBC           3 :     if (flagbits & F_TUPLES_DELETED)
  816 heikki.linnakangas        105 UBC           0 :         flags[nflags++] = CStringGetTextDatum("tuples_deleted");
  816 heikki.linnakangas        106 CBC           3 :     if (flagbits & F_FOLLOW_RIGHT)
  816 heikki.linnakangas        107 UBC           0 :         flags[nflags++] = CStringGetTextDatum("follow_right");
  816 heikki.linnakangas        108 CBC           3 :     if (flagbits & F_HAS_GARBAGE)
  816 heikki.linnakangas        109 LBC           0 :         flags[nflags++] = CStringGetTextDatum("has_garbage");
  816 heikki.linnakangas        110 GIC           3 :     flagbits &= ~(F_LEAF | F_DELETED | F_TUPLES_DELETED | F_FOLLOW_RIGHT | F_HAS_GARBAGE);
                                111               3 :     if (flagbits)
  816 heikki.linnakangas        112 EUB             :     {
                                113                 :         /* any flags we don't recognize are printed in hex */
  816 heikki.linnakangas        114 UIC           0 :         flags[nflags++] = DirectFunctionCall1(to_hex32, Int32GetDatum(flagbits));
  816 heikki.linnakangas        115 ECB             :     }
                                116                 : 
  816 heikki.linnakangas        117 CBC           3 :     memset(nulls, 0, sizeof(nulls));
  816 heikki.linnakangas        118 ECB             : 
  816 heikki.linnakangas        119 CBC           3 :     values[0] = LSNGetDatum(PageGetLSN(page));
                                120               3 :     values[1] = LSNGetDatum(GistPageGetNSN(page));
   38 michael                   121 GIC           3 :     values[2] = Int64GetDatum(GistPageGetOpaque(page)->rightlink);
  282 peter                     122 GNC           3 :     values[3] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID));
  816 heikki.linnakangas        123 ECB             : 
                                124                 :     /* Build and return the result tuple. */
  816 heikki.linnakangas        125 GIC           3 :     resultTuple = heap_form_tuple(tupdesc, values, nulls);
                                126                 : 
  816 heikki.linnakangas        127 CBC           3 :     return HeapTupleGetDatum(resultTuple);
                                128                 : }
  816 heikki.linnakangas        129 ECB             : 
                                130                 : Datum
  816 heikki.linnakangas        131 GIC           5 : gist_page_items_bytea(PG_FUNCTION_ARGS)
                                132                 : {
  816 heikki.linnakangas        133 CBC           5 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
  811 heikki.linnakangas        134 GIC           5 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
  811 heikki.linnakangas        135 ECB             :     Page        page;
  811 heikki.linnakangas        136 EUB             :     OffsetNumber offset;
  784 pg                        137 GIC           5 :     OffsetNumber maxoff = InvalidOffsetNumber;
                                138                 : 
  816 heikki.linnakangas        139               5 :     if (!superuser())
  816 heikki.linnakangas        140 LBC           0 :         ereport(ERROR,
                                141                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  816 heikki.linnakangas        142 ECB             :                  errmsg("must be superuser to use raw page functions")));
                                143                 : 
  173 michael                   144 CBC           5 :     InitMaterializedSRF(fcinfo, 0);
  816 heikki.linnakangas        145 ECB             : 
   38 michael                   146 GIC           5 :     page = verify_gist_page(raw_page);
                                147                 : 
  360 michael                   148 CBC           2 :     if (PageIsNew(page))
  360 michael                   149 GBC           1 :         PG_RETURN_NULL();
                                150                 : 
  784 pg                        151 ECB             :     /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
  811 heikki.linnakangas        152 GIC           1 :     if (GistPageIsDeleted(page))
  811 heikki.linnakangas        153 LBC           0 :         elog(NOTICE, "page is deleted");
  784 pg                        154 ECB             :     else
  784 pg                        155 CBC           1 :         maxoff = PageGetMaxOffsetNumber(page);
                                156                 : 
  811 heikki.linnakangas        157 GIC           1 :     for (offset = FirstOffsetNumber;
  784 pg                        158               7 :          offset <= maxoff;
  811 heikki.linnakangas        159               6 :          offset++)
                                160                 :     {
                                161                 :         Datum       values[5];
                                162                 :         bool        nulls[5];
                                163                 :         ItemId      id;
  816 heikki.linnakangas        164 ECB             :         IndexTuple  itup;
                                165                 :         bytea      *tuple_bytea;
                                166                 :         int         tuple_len;
  816 heikki.linnakangas        167 EUB             : 
  816 heikki.linnakangas        168 GIC           6 :         id = PageGetItemId(page, offset);
  816 heikki.linnakangas        169 ECB             : 
  816 heikki.linnakangas        170 CBC           6 :         if (!ItemIdIsValid(id))
  816 heikki.linnakangas        171 UIC           0 :             elog(ERROR, "invalid ItemId");
  816 heikki.linnakangas        172 ECB             : 
  816 heikki.linnakangas        173 GIC           6 :         itup = (IndexTuple) PageGetItem(page, id);
  816 heikki.linnakangas        174 CBC           6 :         tuple_len = IndexTupleSize(itup);
  816 heikki.linnakangas        175 ECB             : 
  816 heikki.linnakangas        176 CBC           6 :         memset(nulls, 0, sizeof(nulls));
                                177                 : 
                                178               6 :         values[0] = DatumGetInt16(offset);
                                179               6 :         values[1] = ItemPointerGetDatum(&itup->t_tid);
                                180               6 :         values[2] = Int32GetDatum((int) IndexTupleSize(itup));
  816 heikki.linnakangas        181 ECB             : 
  816 heikki.linnakangas        182 CBC           6 :         tuple_bytea = (bytea *) palloc(tuple_len + VARHDRSZ);
  816 heikki.linnakangas        183 GIC           6 :         SET_VARSIZE(tuple_bytea, tuple_len + VARHDRSZ);
  816 heikki.linnakangas        184 CBC           6 :         memcpy(VARDATA(tuple_bytea), itup, tuple_len);
  784 pg                        185 GIC           6 :         values[3] = BoolGetDatum(ItemIdIsDead(id));
                                186               6 :         values[4] = PointerGetDatum(tuple_bytea);
  816 heikki.linnakangas        187 ECB             : 
  397 michael                   188 GIC           6 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
                                189                 :     }
                                190                 : 
  811 heikki.linnakangas        191 CBC           1 :     return (Datum) 0;
                                192                 : }
  816 heikki.linnakangas        193 ECB             : 
                                194                 : Datum
  816 heikki.linnakangas        195 CBC           6 : gist_page_items(PG_FUNCTION_ARGS)
                                196                 : {
  816 heikki.linnakangas        197 GIC           6 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                198               6 :     Oid         indexRelid = PG_GETARG_OID(1);
  811 heikki.linnakangas        199 CBC           6 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                200                 :     Relation    indexRel;
  811 heikki.linnakangas        201 ECB             :     Page        page;
  811 heikki.linnakangas        202 EUB             :     OffsetNumber offset;
  784 pg                        203 GIC           6 :     OffsetNumber maxoff = InvalidOffsetNumber;
                                204                 : 
  816 heikki.linnakangas        205               6 :     if (!superuser())
  816 heikki.linnakangas        206 LBC           0 :         ereport(ERROR,
                                207                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                208                 :                  errmsg("must be superuser to use raw page functions")));
  816 heikki.linnakangas        209 ECB             : 
  173 michael                   210 GIC           6 :     InitMaterializedSRF(fcinfo, 0);
  816 heikki.linnakangas        211 ECB             : 
  811                           212                 :     /* Open the relation */
  811 heikki.linnakangas        213 GIC           6 :     indexRel = index_open(indexRelid, AccessShareLock);
                                214                 : 
  389 michael                   215               6 :     if (!IS_GIST(indexRel))
                                216               1 :         ereport(ERROR,
  389 michael                   217 ECB             :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                218                 :                  errmsg("\"%s\" is not a %s index",
                                219                 :                         RelationGetRelationName(indexRel), "GiST")));
                                220                 : 
   38 michael                   221 CBC           5 :     page = verify_gist_page(raw_page);
  816 heikki.linnakangas        222 ECB             : 
  360 michael                   223 GIC           3 :     if (PageIsNew(page))
                                224                 :     {
                                225               1 :         index_close(indexRel, AccessShareLock);
  360 michael                   226 CBC           1 :         PG_RETURN_NULL();
  360 michael                   227 EUB             :     }
                                228                 : 
  784 pg                        229 ECB             :     /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
  811 heikki.linnakangas        230 GIC           2 :     if (GistPageIsDeleted(page))
  811 heikki.linnakangas        231 LBC           0 :         elog(NOTICE, "page is deleted");
  784 pg                        232 ECB             :     else
  784 pg                        233 CBC           2 :         maxoff = PageGetMaxOffsetNumber(page);
                                234                 : 
  811 heikki.linnakangas        235 GIC           2 :     for (offset = FirstOffsetNumber;
  784 pg                        236             193 :          offset <= maxoff;
  811 heikki.linnakangas        237             191 :          offset++)
                                238                 :     {
                                239                 :         Datum       values[5];
                                240                 :         bool        nulls[5];
                                241                 :         ItemId      id;
                                242                 :         IndexTuple  itup;
  816 heikki.linnakangas        243 ECB             :         Datum       itup_values[INDEX_MAX_KEYS];
                                244                 :         bool        itup_isnull[INDEX_MAX_KEYS];
                                245                 :         char       *key_desc;
  816 heikki.linnakangas        246 EUB             : 
  816 heikki.linnakangas        247 GIC         191 :         id = PageGetItemId(page, offset);
  816 heikki.linnakangas        248 ECB             : 
  816 heikki.linnakangas        249 GIC         191 :         if (!ItemIdIsValid(id))
  816 heikki.linnakangas        250 LBC           0 :             elog(ERROR, "invalid ItemId");
                                251                 : 
  816 heikki.linnakangas        252 GIC         191 :         itup = (IndexTuple) PageGetItem(page, id);
  816 heikki.linnakangas        253 ECB             : 
  811 heikki.linnakangas        254 GIC         191 :         index_deform_tuple(itup, RelationGetDescr(indexRel),
  816 heikki.linnakangas        255 ECB             :                            itup_values, itup_isnull);
                                256                 : 
  816 heikki.linnakangas        257 CBC         191 :         memset(nulls, 0, sizeof(nulls));
  816 heikki.linnakangas        258 ECB             : 
  816 heikki.linnakangas        259 GIC         191 :         values[0] = DatumGetInt16(offset);
  816 heikki.linnakangas        260 CBC         191 :         values[1] = ItemPointerGetDatum(&itup->t_tid);
                                261             191 :         values[2] = Int32GetDatum((int) IndexTupleSize(itup));
  784 pg                        262             191 :         values[3] = BoolGetDatum(ItemIdIsDead(id));
                                263                 : 
  811 heikki.linnakangas        264 GIC         191 :         key_desc = BuildIndexValueDescription(indexRel, itup_values, itup_isnull);
  811 heikki.linnakangas        265 GBC         191 :         if (key_desc)
  784 pg                        266             191 :             values[4] = CStringGetTextDatum(key_desc);
                                267                 :         else
                                268                 :         {
  784 pg                        269 LBC           0 :             values[4] = (Datum) 0;
  784 pg                        270 UIC           0 :             nulls[4] = true;
                                271                 :         }
  816 heikki.linnakangas        272 ECB             : 
  397 michael                   273 GIC         191 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
  816 heikki.linnakangas        274 ECB             :     }
                                275                 : 
  811 heikki.linnakangas        276 GIC           2 :     relation_close(indexRel, AccessShareLock);
                                277                 : 
                                278               2 :     return (Datum) 0;
                                279                 : }
        

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