LCOV - differential code coverage report
Current view: top level - contrib/pgrowlocks - pgrowlocks.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 90.7 % 108 98 10 1 97 1
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 3 3 1 2
Baseline: lcov-20250906-005545-baseline Branches: 70.2 % 47 33 14 33
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 1 1 1
(30,360] days: 100.0 % 1 1 1
(360..) days: 90.6 % 106 96 10 96
Function coverage date bins:
(30,360] days: 100.0 % 1 1 1
(360..) days: 100.0 % 2 2 1 1
Branch coverage date bins:
(360..) days: 70.2 % 47 33 14 33

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*
                                  2                 :                :  * contrib/pgrowlocks/pgrowlocks.c
                                  3                 :                :  *
                                  4                 :                :  * Copyright (c) 2005-2006  Tatsuo Ishii
                                  5                 :                :  *
                                  6                 :                :  * Permission to use, copy, modify, and distribute this software and
                                  7                 :                :  * its documentation for any purpose, without fee, and without a
                                  8                 :                :  * written agreement is hereby granted, provided that the above
                                  9                 :                :  * copyright notice and this paragraph and the following two
                                 10                 :                :  * paragraphs appear in all copies.
                                 11                 :                :  *
                                 12                 :                :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
                                 13                 :                :  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
                                 14                 :                :  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
                                 15                 :                :  * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
                                 16                 :                :  * OF THE POSSIBILITY OF SUCH DAMAGE.
                                 17                 :                :  *
                                 18                 :                :  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
                                 19                 :                :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                                 20                 :                :  * A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
                                 21                 :                :  * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
                                 22                 :                :  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
                                 23                 :                :  */
                                 24                 :                : 
                                 25                 :                : #include "postgres.h"
                                 26                 :                : 
                                 27                 :                : #include "access/heapam.h"
                                 28                 :                : #include "access/multixact.h"
                                 29                 :                : #include "access/relscan.h"
                                 30                 :                : #include "access/tableam.h"
                                 31                 :                : #include "access/xact.h"
                                 32                 :                : #include "catalog/namespace.h"
                                 33                 :                : #include "catalog/pg_am_d.h"
                                 34                 :                : #include "catalog/pg_authid.h"
                                 35                 :                : #include "funcapi.h"
                                 36                 :                : #include "miscadmin.h"
                                 37                 :                : #include "storage/bufmgr.h"
                                 38                 :                : #include "storage/procarray.h"
                                 39                 :                : #include "utils/acl.h"
                                 40                 :                : #include "utils/fmgrprotos.h"
                                 41                 :                : #include "utils/rel.h"
                                 42                 :                : #include "utils/snapmgr.h"
                                 43                 :                : #include "utils/varlena.h"
                                 44                 :                : 
  164 tgl@sss.pgh.pa.us          45                 :CBC           2 : PG_MODULE_MAGIC_EXT(
                                 46                 :                :                     .name = "pgrowlocks",
                                 47                 :                :                     .version = PG_VERSION
                                 48                 :                : );
                                 49                 :                : 
 7076 ishii@postgresql.org       50                 :              2 : PG_FUNCTION_INFO_V1(pgrowlocks);
                                 51                 :                : 
                                 52                 :                : /* ----------
                                 53                 :                :  * pgrowlocks:
                                 54                 :                :  * returns tids of rows being locked
                                 55                 :                :  * ----------
                                 56                 :                :  */
                                 57                 :                : 
                                 58                 :                : #define NCHARS 32
                                 59                 :                : 
                                 60                 :                : #define     Atnum_tid       0
                                 61                 :                : #define     Atnum_xmax      1
                                 62                 :                : #define     Atnum_ismulti   2
                                 63                 :                : #define     Atnum_xids      3
                                 64                 :                : #define     Atnum_modes     4
                                 65                 :                : #define     Atnum_pids      5
                                 66                 :                : 
                                 67                 :                : Datum
                                 68                 :             12 : pgrowlocks(PG_FUNCTION_ARGS)
                                 69                 :                : {
 2000 tgl@sss.pgh.pa.us          70                 :             12 :     text       *relname = PG_GETARG_TEXT_PP(0);
                                 71                 :             12 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                 72                 :                :     AttInMetadata *attinmeta;
                                 73                 :                :     Relation    rel;
                                 74                 :                :     RangeVar   *relrv;
                                 75                 :                :     TableScanDesc scan;
                                 76                 :                :     HeapScanDesc hscan;
                                 77                 :                :     HeapTuple   tuple;
                                 78                 :                :     AclResult   aclresult;
                                 79                 :                :     char      **values;
                                 80                 :                : 
 1054 michael@paquier.xyz        81                 :             12 :     InitMaterializedSRF(fcinfo, 0);
                                 82                 :                : 
                                 83                 :                :     /* Access the table */
 2000 tgl@sss.pgh.pa.us          84                 :             12 :     relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
                                 85                 :             12 :     rel = relation_openrv(relrv, AccessShareLock);
                                 86                 :                : 
                                 87         [ -  + ]:             12 :     if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 2000 tgl@sss.pgh.pa.us          88         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 89                 :                :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 90                 :                :                  errmsg("\"%s\" is a partitioned table",
                                 91                 :                :                         RelationGetRelationName(rel)),
                                 92                 :                :                  errdetail("Partitioned tables do not contain rows.")));
 2000 tgl@sss.pgh.pa.us          93         [ -  + ]:CBC          12 :     else if (rel->rd_rel->relkind != RELKIND_RELATION)
 2000 tgl@sss.pgh.pa.us          94         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 95                 :                :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 96                 :                :                  errmsg("\"%s\" is not a table",
                                 97                 :                :                         RelationGetRelationName(rel))));
  676 drowley@postgresql.o       98         [ -  + ]:CBC          12 :     else if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
  676 drowley@postgresql.o       99         [ #  # ]:UBC           0 :         ereport(ERROR,
                                100                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                101                 :                :                  errmsg("only heap AM is supported")));
                                102                 :                : 
                                103                 :                :     /*
                                104                 :                :      * check permissions: must have SELECT on table or be in
                                105                 :                :      * pg_stat_scan_tables
                                106                 :                :      */
 2000 tgl@sss.pgh.pa.us         107                 :CBC          12 :     aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
                                108                 :                :                                   ACL_SELECT);
                                109         [ -  + ]:             12 :     if (aclresult != ACLCHECK_OK)
 1258 mail@joeconway.com        110                 :UBC           0 :         aclresult = has_privs_of_role(GetUserId(), ROLE_PG_STAT_SCAN_TABLES) ? ACLCHECK_OK : ACLCHECK_NO_PRIV;
                                111                 :                : 
 2000 tgl@sss.pgh.pa.us         112         [ -  + ]:CBC          12 :     if (aclresult != ACLCHECK_OK)
 2000 tgl@sss.pgh.pa.us         113                 :UBC           0 :         aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
                                114                 :              0 :                        RelationGetRelationName(rel));
                                115                 :                : 
                                116                 :                :     /* Scan the relation */
 2000 tgl@sss.pgh.pa.us         117                 :CBC          12 :     scan = table_beginscan(rel, GetActiveSnapshot(), 0, NULL);
                                118                 :             12 :     hscan = (HeapScanDesc) scan;
                                119                 :                : 
 1278 michael@paquier.xyz       120                 :             12 :     attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
                                121                 :                : 
                                122                 :             12 :     values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *));
                                123                 :                : 
 7076 ishii@postgresql.org      124         [ +  + ]:             36 :     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
                                125                 :                :     {
                                126                 :                :         TM_Result   htsu;
                                127                 :                :         TransactionId xmax;
                                128                 :                :         uint16      infomask;
                                129                 :                : 
                                130                 :                :         /* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
 2371 andres@anarazel.de        131                 :             24 :         LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_SHARE);
                                132                 :                : 
 4429 rhaas@postgresql.org      133                 :             24 :         htsu = HeapTupleSatisfiesUpdate(tuple,
                                134                 :                :                                         GetCurrentCommandId(false),
                                135                 :                :                                         hscan->rs_cbuf);
 4609 alvherre@alvh.no-ip.      136                 :             24 :         xmax = HeapTupleHeaderGetRawXmax(tuple->t_data);
                                137                 :             24 :         infomask = tuple->t_data->t_infomask;
                                138                 :                : 
                                139                 :                :         /*
                                140                 :                :          * A tuple is locked if HTSU returns BeingModified.
                                141                 :                :          */
 2359 andres@anarazel.de        142         [ +  + ]:             24 :         if (htsu == TM_BeingModified)
                                143                 :                :         {
   29 peter@eisentraut.org      144                 :GNC          22 :             values[Atnum_tid] = DatumGetCString(DirectFunctionCall1(tidout,
                                145                 :                :                                                                     PointerGetDatum(&tuple->t_self)));
                                146                 :                : 
 4609 alvherre@alvh.no-ip.      147                 :CBC          22 :             values[Atnum_xmax] = palloc(NCHARS * sizeof(char));
 1368 peter@eisentraut.org      148                 :             22 :             snprintf(values[Atnum_xmax], NCHARS, "%u", xmax);
 4609 alvherre@alvh.no-ip.      149         [ +  + ]:             22 :             if (infomask & HEAP_XMAX_IS_MULTI)
                                150                 :                :             {
                                151                 :                :                 MultiXactMember *members;
                                152                 :                :                 int         nmembers;
                                153                 :              8 :                 bool        first = true;
                                154                 :                :                 bool        allow_old;
                                155                 :                : 
                                156                 :              8 :                 values[Atnum_ismulti] = pstrdup("true");
                                157                 :                : 
 3361                           158                 :              8 :                 allow_old = HEAP_LOCKED_UPGRADED(infomask);
 4057                           159                 :              8 :                 nmembers = GetMultiXactIdMembers(xmax, &members, allow_old,
                                160                 :                :                                                  false);
 4609                           161         [ -  + ]:              8 :                 if (nmembers == -1)
                                162                 :                :                 {
 4609 alvherre@alvh.no-ip.      163                 :UBC           0 :                     values[Atnum_xids] = "{0}";
                                164                 :              0 :                     values[Atnum_modes] = "{transient upgrade status}";
                                165                 :              0 :                     values[Atnum_pids] = "{0}";
                                166                 :                :                 }
                                167                 :                :                 else
                                168                 :                :                 {
                                169                 :                :                     int         j;
                                170                 :                : 
 4609 alvherre@alvh.no-ip.      171                 :CBC           8 :                     values[Atnum_xids] = palloc(NCHARS * nmembers);
                                172                 :              8 :                     values[Atnum_modes] = palloc(NCHARS * nmembers);
                                173                 :              8 :                     values[Atnum_pids] = palloc(NCHARS * nmembers);
                                174                 :                : 
                                175                 :              8 :                     strcpy(values[Atnum_xids], "{");
                                176                 :              8 :                     strcpy(values[Atnum_modes], "{");
                                177                 :              8 :                     strcpy(values[Atnum_pids], "{");
                                178                 :                : 
                                179         [ +  + ]:             24 :                     for (j = 0; j < nmembers; j++)
                                180                 :                :                     {
                                181                 :                :                         char        buf[NCHARS];
                                182                 :                : 
                                183         [ +  + ]:             16 :                         if (!first)
                                184                 :                :                         {
                                185                 :              8 :                             strcat(values[Atnum_xids], ",");
                                186                 :              8 :                             strcat(values[Atnum_modes], ",");
                                187                 :              8 :                             strcat(values[Atnum_pids], ",");
                                188                 :                :                         }
 1368 peter@eisentraut.org      189                 :             16 :                         snprintf(buf, NCHARS, "%u", members[j].xid);
 4609 alvherre@alvh.no-ip.      190                 :             16 :                         strcat(values[Atnum_xids], buf);
                                191   [ +  +  +  +  :             16 :                         switch (members[j].status)
                                           +  +  - ]
                                192                 :                :                         {
                                193                 :              1 :                             case MultiXactStatusUpdate:
                                194                 :              1 :                                 snprintf(buf, NCHARS, "Update");
                                195                 :              1 :                                 break;
                                196                 :              1 :                             case MultiXactStatusNoKeyUpdate:
                                197                 :              1 :                                 snprintf(buf, NCHARS, "No Key Update");
                                198                 :              1 :                                 break;
                                199                 :              2 :                             case MultiXactStatusForUpdate:
                                200                 :              2 :                                 snprintf(buf, NCHARS, "For Update");
                                201                 :              2 :                                 break;
                                202                 :              2 :                             case MultiXactStatusForNoKeyUpdate:
                                203                 :              2 :                                 snprintf(buf, NCHARS, "For No Key Update");
                                204                 :              2 :                                 break;
                                205                 :              2 :                             case MultiXactStatusForShare:
  711 bruce@momjian.us          206                 :              2 :                                 snprintf(buf, NCHARS, "For Share");
 4609 alvherre@alvh.no-ip.      207                 :              2 :                                 break;
                                208                 :              8 :                             case MultiXactStatusForKeyShare:
  711 bruce@momjian.us          209                 :              8 :                                 snprintf(buf, NCHARS, "For Key Share");
 4609 alvherre@alvh.no-ip.      210                 :              8 :                                 break;
                                211                 :                :                         }
                                212                 :             16 :                         strcat(values[Atnum_modes], buf);
                                213                 :             16 :                         snprintf(buf, NCHARS, "%d",
                                214                 :             16 :                                  BackendXidGetPid(members[j].xid));
                                215                 :             16 :                         strcat(values[Atnum_pids], buf);
                                216                 :                : 
                                217                 :             16 :                         first = false;
                                218                 :                :                     }
                                219                 :                : 
                                220                 :              8 :                     strcat(values[Atnum_xids], "}");
                                221                 :              8 :                     strcat(values[Atnum_modes], "}");
                                222                 :              8 :                     strcat(values[Atnum_pids], "}");
                                223                 :                :                 }
                                224                 :                :             }
                                225                 :                :             else
                                226                 :                :             {
                                227                 :             14 :                 values[Atnum_ismulti] = pstrdup("false");
                                228                 :                : 
                                229                 :             14 :                 values[Atnum_xids] = palloc(NCHARS * sizeof(char));
 1368 peter@eisentraut.org      230                 :             14 :                 snprintf(values[Atnum_xids], NCHARS, "{%u}", xmax);
                                231                 :                : 
 4609 alvherre@alvh.no-ip.      232                 :             14 :                 values[Atnum_modes] = palloc(NCHARS);
                                233         [ +  + ]:             14 :                 if (infomask & HEAP_XMAX_LOCK_ONLY)
                                234                 :                :                 {
                                235         [ +  + ]:             12 :                     if (HEAP_XMAX_IS_SHR_LOCKED(infomask))
                                236                 :              2 :                         snprintf(values[Atnum_modes], NCHARS, "{For Share}");
                                237         [ +  + ]:             10 :                     else if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask))
                                238                 :              6 :                         snprintf(values[Atnum_modes], NCHARS, "{For Key Share}");
                                239         [ +  - ]:              4 :                     else if (HEAP_XMAX_IS_EXCL_LOCKED(infomask))
                                240                 :                :                     {
 4601                           241         [ +  + ]:              4 :                         if (tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)
                                242                 :              2 :                             snprintf(values[Atnum_modes], NCHARS, "{For Update}");
                                243                 :                :                         else
                                244                 :              2 :                             snprintf(values[Atnum_modes], NCHARS, "{For No Key Update}");
                                245                 :                :                     }
                                246                 :                :                     else
                                247                 :                :                         /* neither keyshare nor exclusive bit it set */
 4609 alvherre@alvh.no-ip.      248                 :UBC           0 :                         snprintf(values[Atnum_modes], NCHARS,
                                249                 :                :                                  "{transient upgrade status}");
                                250                 :                :                 }
                                251                 :                :                 else
                                252                 :                :                 {
 4609 alvherre@alvh.no-ip.      253         [ +  + ]:CBC           2 :                     if (tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)
                                254                 :              1 :                         snprintf(values[Atnum_modes], NCHARS, "{Update}");
                                255                 :                :                     else
 4601                           256                 :              1 :                         snprintf(values[Atnum_modes], NCHARS, "{No Key Update}");
                                257                 :                :                 }
                                258                 :                : 
 4609                           259                 :             14 :                 values[Atnum_pids] = palloc(NCHARS * sizeof(char));
                                260                 :             14 :                 snprintf(values[Atnum_pids], NCHARS, "{%d}",
                                261                 :                :                          BackendXidGetPid(xmax));
                                262                 :                :             }
                                263                 :                : 
 2371 andres@anarazel.de        264                 :             22 :             LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_UNLOCK);
                                265                 :                : 
                                266                 :                :             /* build a tuple */
 7076 ishii@postgresql.org      267                 :             22 :             tuple = BuildTupleFromCStrings(attinmeta, values);
 1278 michael@paquier.xyz       268                 :             22 :             tuplestore_puttuple(rsinfo->setResult, tuple);
                                269                 :                :         }
                                270                 :                :         else
                                271                 :                :         {
 2371 andres@anarazel.de        272                 :              2 :             LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_UNLOCK);
                                273                 :                :         }
                                274                 :                :     }
                                275                 :                : 
                                276                 :             12 :     table_endscan(scan);
 2000 tgl@sss.pgh.pa.us         277                 :             12 :     table_close(rel, AccessShareLock);
                                278                 :             12 :     return (Datum) 0;
                                279                 :                : }
        

Generated by: LCOV version 2.4-beta