LCOV - differential code coverage report
Current view: top level - contrib/pageinspect - ginfuncs.c (source / functions) Coverage Total Hit LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 87.8 % 115 101 10 4 8 55 2 36 6 48 7
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 6 6 6 4 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 87.8 % 115 101 10 4 8 55 2 36 6 48
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 60.0 % 10 6 6 4

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * ginfuncs.c
                                  3                 :  *      Functions to investigate the content of GIN indexes
                                  4                 :  *
                                  5                 :  * Copyright (c) 2014-2023, PostgreSQL Global Development Group
                                  6                 :  *
                                  7                 :  * IDENTIFICATION
                                  8                 :  *      contrib/pageinspect/ginfuncs.c
                                  9                 :  */
                                 10                 : #include "postgres.h"
                                 11                 : 
                                 12                 : #include "access/gin.h"
                                 13                 : #include "access/gin_private.h"
                                 14                 : #include "access/htup_details.h"
                                 15                 : #include "catalog/namespace.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                 : 
 3061 heikki.linnakangas         24 ECB             : 
 3061 heikki.linnakangas         25 GIC           7 : PG_FUNCTION_INFO_V1(gin_metapage_info);
                                 26               7 : PG_FUNCTION_INFO_V1(gin_page_opaque_info);
                                 27               7 : PG_FUNCTION_INFO_V1(gin_leafpage_items);
 3061 heikki.linnakangas         28 ECB             : 
                                 29                 : 
                                 30                 : Datum
 3061 heikki.linnakangas         31 GIC           5 : gin_metapage_info(PG_FUNCTION_ARGS)
                                 32                 : {
                                 33               5 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                 34                 :     TupleDesc   tupdesc;
                                 35                 :     Page        page;
                                 36                 :     GinPageOpaque opaq;
                                 37                 :     GinMetaPageData *metadata;
                                 38                 :     HeapTuple   resultTuple;
 3061 heikki.linnakangas         39 ECB             :     Datum       values[10];
 3061 heikki.linnakangas         40 EUB             :     bool        nulls[10];
                                 41                 : 
 3061 heikki.linnakangas         42 GIC           5 :     if (!superuser())
 3061 heikki.linnakangas         43 UIC           0 :         ereport(ERROR,
 3061 heikki.linnakangas         44 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 45                 :                  errmsg("must be superuser to use raw page functions")));
                                 46                 : 
 2347 peter_e                    47 CBC           5 :     page = get_page_from_raw(raw_page);
                                 48                 : 
  360 michael                    49               4 :     if (PageIsNew(page))
                                 50               1 :         PG_RETURN_NULL();
                                 51                 : 
  378 michael                    52 GIC           3 :     if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
                                 53               1 :         ereport(ERROR,
                                 54                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 55                 :                  errmsg("input page is not a valid GIN metapage"),
                                 56                 :                  errdetail("Expected special size %d, got %d.",
  378 michael                    57 ECB             :                            (int) MAXALIGN(sizeof(GinPageOpaqueData)),
                                 58                 :                            (int) PageGetSpecialSize(page))));
                                 59                 : 
  372 michael                    60 CBC           2 :     opaq = GinPageGetOpaque(page);
                                 61                 : 
 3061 heikki.linnakangas         62 GIC           2 :     if (opaq->flags != GIN_META)
                                 63               1 :         ereport(ERROR,
                                 64                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 65                 :                  errmsg("input page is not a GIN metapage"),
                                 66                 :                  errdetail("Flags %04X, expected %04X",
 3061 heikki.linnakangas         67 ECB             :                            opaq->flags, GIN_META)));
 3061 heikki.linnakangas         68 EUB             : 
                                 69                 :     /* Build a tuple descriptor for our result type */
 3061 heikki.linnakangas         70 CBC           1 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 3061 heikki.linnakangas         71 UIC           0 :         elog(ERROR, "return type must be a row type");
 3061 heikki.linnakangas         72 ECB             : 
 3061 heikki.linnakangas         73 GIC           1 :     metadata = GinPageGetMeta(page);
 3061 heikki.linnakangas         74 ECB             : 
 3061 heikki.linnakangas         75 CBC           1 :     memset(nulls, 0, sizeof(nulls));
 3061 heikki.linnakangas         76 ECB             : 
 3061 heikki.linnakangas         77 CBC           1 :     values[0] = Int64GetDatum(metadata->head);
                                 78               1 :     values[1] = Int64GetDatum(metadata->tail);
 3061 heikki.linnakangas         79 GIC           1 :     values[2] = Int32GetDatum(metadata->tailFreeSize);
                                 80               1 :     values[3] = Int64GetDatum(metadata->nPendingPages);
 3061 heikki.linnakangas         81 CBC           1 :     values[4] = Int64GetDatum(metadata->nPendingHeapTuples);
 3061 heikki.linnakangas         82 ECB             : 
                                 83                 :     /* statistics, updated by VACUUM */
 3061 heikki.linnakangas         84 CBC           1 :     values[5] = Int64GetDatum(metadata->nTotalPages);
 3061 heikki.linnakangas         85 GIC           1 :     values[6] = Int64GetDatum(metadata->nEntryPages);
 3061 heikki.linnakangas         86 CBC           1 :     values[7] = Int64GetDatum(metadata->nDataPages);
 3061 heikki.linnakangas         87 GIC           1 :     values[8] = Int64GetDatum(metadata->nEntries);
                                 88                 : 
 3061 heikki.linnakangas         89 CBC           1 :     values[9] = Int32GetDatum(metadata->ginVersion);
                                 90                 : 
 3061 heikki.linnakangas         91 ECB             :     /* Build and return the result tuple. */
 3061 heikki.linnakangas         92 GIC           1 :     resultTuple = heap_form_tuple(tupdesc, values, nulls);
                                 93                 : 
                                 94               1 :     return HeapTupleGetDatum(resultTuple);
                                 95                 : }
 3061 heikki.linnakangas         96 ECB             : 
                                 97                 : 
                                 98                 : Datum
 3061 heikki.linnakangas         99 GIC           4 : gin_page_opaque_info(PG_FUNCTION_ARGS)
                                100                 : {
                                101               4 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                102                 :     TupleDesc   tupdesc;
                                103                 :     Page        page;
                                104                 :     GinPageOpaque opaq;
                                105                 :     HeapTuple   resultTuple;
 3061 heikki.linnakangas        106 ECB             :     Datum       values[3];
                                107                 :     bool        nulls[3];
                                108                 :     Datum       flags[16];
 3061 heikki.linnakangas        109 CBC           4 :     int         nflags = 0;
 3061 heikki.linnakangas        110 EUB             :     uint16      flagbits;
                                111                 : 
 3061 heikki.linnakangas        112 GIC           4 :     if (!superuser())
 3061 heikki.linnakangas        113 UIC           0 :         ereport(ERROR,
 3061 heikki.linnakangas        114 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                115                 :                  errmsg("must be superuser to use raw page functions")));
                                116                 : 
 2347 peter_e                   117 CBC           4 :     page = get_page_from_raw(raw_page);
                                118                 : 
  360 michael                   119               3 :     if (PageIsNew(page))
                                120               1 :         PG_RETURN_NULL();
                                121                 : 
  378 michael                   122 GIC           2 :     if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
                                123               1 :         ereport(ERROR,
                                124                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                125                 :                  errmsg("input page is not a valid GIN data leaf page"),
                                126                 :                  errdetail("Expected special size %d, got %d.",
  378 michael                   127 ECB             :                            (int) MAXALIGN(sizeof(GinPageOpaqueData)),
                                128                 :                            (int) PageGetSpecialSize(page))));
                                129                 : 
  372 michael                   130 CBC           1 :     opaq = GinPageGetOpaque(page);
 3061 heikki.linnakangas        131 EUB             : 
                                132                 :     /* Build a tuple descriptor for our result type */
 3061 heikki.linnakangas        133 GIC           1 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 3061 heikki.linnakangas        134 LBC           0 :         elog(ERROR, "return type must be a row type");
 3061 heikki.linnakangas        135 ECB             : 
 3061 heikki.linnakangas        136 EUB             :     /* Convert the flags bitmask to an array of human-readable names */
 3061 heikki.linnakangas        137 CBC           1 :     flagbits = opaq->flags;
                                138               1 :     if (flagbits & GIN_DATA)
 3061 heikki.linnakangas        139 LBC           0 :         flags[nflags++] = CStringGetTextDatum("data");
 3061 heikki.linnakangas        140 GBC           1 :     if (flagbits & GIN_LEAF)
 3061 heikki.linnakangas        141 CBC           1 :         flags[nflags++] = CStringGetTextDatum("leaf");
 3061 heikki.linnakangas        142 GBC           1 :     if (flagbits & GIN_DELETED)
 3061 heikki.linnakangas        143 LBC           0 :         flags[nflags++] = CStringGetTextDatum("deleted");
 3061 heikki.linnakangas        144 GBC           1 :     if (flagbits & GIN_META)
 3061 heikki.linnakangas        145 LBC           0 :         flags[nflags++] = CStringGetTextDatum("meta");
 3061 heikki.linnakangas        146 GBC           1 :     if (flagbits & GIN_LIST)
 3061 heikki.linnakangas        147 LBC           0 :         flags[nflags++] = CStringGetTextDatum("list");
 3061 heikki.linnakangas        148 GBC           1 :     if (flagbits & GIN_LIST_FULLROW)
 3061 heikki.linnakangas        149 LBC           0 :         flags[nflags++] = CStringGetTextDatum("list_fullrow");
 3061 heikki.linnakangas        150 GBC           1 :     if (flagbits & GIN_INCOMPLETE_SPLIT)
 3061 heikki.linnakangas        151 LBC           0 :         flags[nflags++] = CStringGetTextDatum("incomplete_split");
 3061 heikki.linnakangas        152 GIC           1 :     if (flagbits & GIN_COMPRESSED)
 3061 heikki.linnakangas        153 LBC           0 :         flags[nflags++] = CStringGetTextDatum("compressed");
 3061 heikki.linnakangas        154 GIC           1 :     flagbits &= ~(GIN_DATA | GIN_LEAF | GIN_DELETED | GIN_META | GIN_LIST |
                                155                 :                   GIN_LIST_FULLROW | GIN_INCOMPLETE_SPLIT | GIN_COMPRESSED);
 3061 heikki.linnakangas        156 GBC           1 :     if (flagbits)
                                157                 :     {
                                158                 :         /* any flags we don't recognize are printed in hex */
 3061 heikki.linnakangas        159 LBC           0 :         flags[nflags++] = DirectFunctionCall1(to_hex32, Int32GetDatum(flagbits));
                                160                 :     }
 3061 heikki.linnakangas        161 ECB             : 
 3061 heikki.linnakangas        162 CBC           1 :     memset(nulls, 0, sizeof(nulls));
 3061 heikki.linnakangas        163 ECB             : 
 3061 heikki.linnakangas        164 GIC           1 :     values[0] = Int64GetDatum(opaq->rightlink);
 2349 tgl                       165               1 :     values[1] = Int32GetDatum(opaq->maxoff);
  282 peter                     166 GNC           1 :     values[2] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID));
                                167                 : 
                                168                 :     /* Build and return the result tuple. */
 3061 heikki.linnakangas        169 GIC           1 :     resultTuple = heap_form_tuple(tupdesc, values, nulls);
                                170                 : 
                                171               1 :     return HeapTupleGetDatum(resultTuple);
                                172                 : }
                                173                 : 
                                174                 : typedef struct gin_leafpage_items_state
                                175                 : {
                                176                 :     TupleDesc   tupd;
 3061 heikki.linnakangas        177 ECB             :     GinPostingList *seg;
                                178                 :     GinPostingList *lastseg;
 2878 bruce                     179                 : } gin_leafpage_items_state;
                                180                 : 
                                181                 : Datum
 3061 heikki.linnakangas        182 GIC          26 : gin_leafpage_items(PG_FUNCTION_ARGS)
 3061 heikki.linnakangas        183 ECB             : {
 3061 heikki.linnakangas        184 GBC          26 :     bytea      *raw_page = PG_GETARG_BYTEA_P(0);
                                185                 :     FuncCallContext *fctx;
                                186                 :     gin_leafpage_items_state *inter_call_data;
                                187                 : 
 3061 heikki.linnakangas        188 CBC          26 :     if (!superuser())
 3061 heikki.linnakangas        189 UIC           0 :         ereport(ERROR,
                                190                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                191                 :                  errmsg("must be superuser to use raw page functions")));
                                192                 : 
 3061 heikki.linnakangas        193 GIC          26 :     if (SRF_IS_FIRSTCALL())
                                194                 :     {
 3061 heikki.linnakangas        195 ECB             :         TupleDesc   tupdesc;
                                196                 :         MemoryContext mctx;
                                197                 :         Page        page;
                                198                 :         GinPageOpaque opaq;
                                199                 : 
 2347 tgl                       200 CBC           5 :         fctx = SRF_FIRSTCALL_INIT();
 2347 tgl                       201 GIC           5 :         mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
 2347 tgl                       202 ECB             : 
 2347 peter_e                   203 CBC           5 :         page = get_page_from_raw(raw_page);
                                204                 : 
  360 michael                   205 GIC           4 :         if (PageIsNew(page))
  360 michael                   206 ECB             :         {
  360 michael                   207 CBC           1 :             MemoryContextSwitchTo(mctx);
  360 michael                   208 GIC           1 :             PG_RETURN_NULL();
                                209                 :         }
                                210                 : 
 3061 heikki.linnakangas        211               3 :         if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
                                212               1 :             ereport(ERROR,
                                213                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 3061 heikki.linnakangas        214 ECB             :                      errmsg("input page is not a valid GIN data leaf page"),
  378 michael                   215                 :                      errdetail("Expected special size %d, got %d.",
                                216                 :                                (int) MAXALIGN(sizeof(GinPageOpaqueData)),
                                217                 :                                (int) PageGetSpecialSize(page))));
                                218                 : 
  372 michael                   219 GIC           2 :         opaq = GinPageGetOpaque(page);
 3061 heikki.linnakangas        220               2 :         if (opaq->flags != (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))
                                221               1 :             ereport(ERROR,
                                222                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2118 tgl                       223 ECB             :                      errmsg("input page is not a compressed GIN data leaf page"),
                                224                 :                      errdetail("Flags %04X, expected %04X",
                                225                 :                                opaq->flags,
 3061 heikki.linnakangas        226                 :                                (GIN_DATA | GIN_LEAF | GIN_COMPRESSED))));
 3061 heikki.linnakangas        227 EUB             : 
 3061 heikki.linnakangas        228 GIC           1 :         inter_call_data = palloc(sizeof(gin_leafpage_items_state));
 3061 heikki.linnakangas        229 ECB             : 
                                230                 :         /* Build a tuple descriptor for our result type */
 3061 heikki.linnakangas        231 CBC           1 :         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
 3061 heikki.linnakangas        232 LBC           0 :             elog(ERROR, "return type must be a row type");
 3061 heikki.linnakangas        233 ECB             : 
 3061 heikki.linnakangas        234 CBC           1 :         inter_call_data->tupd = tupdesc;
                                235                 : 
                                236               1 :         inter_call_data->seg = GinDataLeafPageGetPostingList(page);
 3061 heikki.linnakangas        237 GIC           1 :         inter_call_data->lastseg = (GinPostingList *)
 3061 heikki.linnakangas        238 CBC           1 :             (((char *) inter_call_data->seg) +
 3061 heikki.linnakangas        239 GIC           1 :              GinDataLeafPageGetPostingListSize(page));
                                240                 : 
 3061 heikki.linnakangas        241 CBC           1 :         fctx->user_fctx = inter_call_data;
 3061 heikki.linnakangas        242 ECB             : 
 3061 heikki.linnakangas        243 GIC           1 :         MemoryContextSwitchTo(mctx);
 3061 heikki.linnakangas        244 ECB             :     }
                                245                 : 
 3061 heikki.linnakangas        246 CBC          22 :     fctx = SRF_PERCALL_SETUP();
 3061 heikki.linnakangas        247 GIC          22 :     inter_call_data = fctx->user_fctx;
                                248                 : 
                                249              22 :     if (inter_call_data->seg != inter_call_data->lastseg)
                                250                 :     {
                                251              21 :         GinPostingList *cur = inter_call_data->seg;
                                252                 :         HeapTuple   resultTuple;
                                253                 :         Datum       result;
                                254                 :         Datum       values[3];
                                255                 :         bool        nulls[3];
 3061 heikki.linnakangas        256 ECB             :         int         ndecoded,
                                257                 :                     i;
                                258                 :         ItemPointer tids;
                                259                 :         Datum      *tids_datum;
                                260                 : 
 3061 heikki.linnakangas        261 GIC          21 :         memset(nulls, 0, sizeof(nulls));
 3061 heikki.linnakangas        262 ECB             : 
 3061 heikki.linnakangas        263 CBC          21 :         values[0] = ItemPointerGetDatum(&cur->first);
                                264              21 :         values[1] = UInt16GetDatum(cur->nbytes);
 3061 heikki.linnakangas        265 ECB             : 
                                266                 :         /* build an array of decoded item pointers */
 3061 heikki.linnakangas        267 CBC          21 :         tids = ginPostingListDecode(cur, &ndecoded);
                                268              21 :         tids_datum = (Datum *) palloc(ndecoded * sizeof(Datum));
 3061 heikki.linnakangas        269 GIC        6082 :         for (i = 0; i < ndecoded; i++)
                                270            6061 :             tids_datum[i] = ItemPointerGetDatum(&tids[i]);
  282 peter                     271 GNC          21 :         values[2] = PointerGetDatum(construct_array_builtin(tids_datum, ndecoded, TIDOID));
 3061 heikki.linnakangas        272 CBC          21 :         pfree(tids_datum);
 3061 heikki.linnakangas        273 GIC          21 :         pfree(tids);
                                274                 : 
 3061 heikki.linnakangas        275 ECB             :         /* Build and return the result tuple. */
 3061 heikki.linnakangas        276 GIC          21 :         resultTuple = heap_form_tuple(inter_call_data->tupd, values, nulls);
                                277              21 :         result = HeapTupleGetDatum(resultTuple);
                                278                 : 
                                279              21 :         inter_call_data->seg = GinNextPostingListSegment(cur);
                                280                 : 
                                281              21 :         SRF_RETURN_NEXT(fctx, result);
                                282                 :     }
                                283                 : 
 1119 tgl                       284               1 :     SRF_RETURN_DONE(fctx);
                                285                 : }
        

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