LCOV - differential code coverage report
Current view: top level - contrib/pgrowlocks - pgrowlocks.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 90.7 % 108 98 10 98
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 3 3 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 1 1 1
Legend: Lines: hit not hit (240..) days: 90.7 % 107 97 10 97
Function coverage date bins:
(240..) days: 100.0 % 3 3 3

 Age         Owner                  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/builtins.h"
                                 41                 : #include "utils/rel.h"
                                 42                 : #include "utils/snapmgr.h"
                                 43                 : #include "utils/varlena.h"
                                 44                 : 
 6158 tgl                        45 CBC           2 : PG_MODULE_MAGIC;
                                 46                 : 
 6195 ishii                      47               2 : PG_FUNCTION_INFO_V1(pgrowlocks);
                                 48                 : 
                                 49                 : /* ----------
                                 50                 :  * pgrowlocks:
                                 51                 :  * returns tids of rows being locked
                                 52                 :  * ----------
                                 53                 :  */
                                 54                 : 
                                 55                 : #define NCHARS 32
                                 56                 : 
                                 57                 : #define     Atnum_tid       0
                                 58                 : #define     Atnum_xmax      1
                                 59                 : #define     Atnum_ismulti   2
                                 60                 : #define     Atnum_xids      3
                                 61                 : #define     Atnum_modes     4
                                 62                 : #define     Atnum_pids      5
                                 63                 : 
                                 64                 : Datum
                                 65              12 : pgrowlocks(PG_FUNCTION_ARGS)
                                 66                 : {
 1119 tgl                        67              12 :     text       *relname = PG_GETARG_TEXT_PP(0);
                                 68              12 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
                                 69                 :     AttInMetadata *attinmeta;
                                 70                 :     Relation    rel;
                                 71                 :     RangeVar   *relrv;
                                 72                 :     TableScanDesc scan;
                                 73                 :     HeapScanDesc hscan;
                                 74                 :     HeapTuple   tuple;
                                 75                 :     AclResult   aclresult;
                                 76                 :     char      **values;
                                 77                 : 
  173 michael                    78              12 :     InitMaterializedSRF(fcinfo, 0);
                                 79                 : 
                                 80                 :     /* Access the table */
 1119 tgl                        81              12 :     relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
                                 82              12 :     rel = relation_openrv(relrv, AccessShareLock);
                                 83                 : 
                                 84              12 :     if (rel->rd_rel->relam != HEAP_TABLE_AM_OID)
 1119 tgl                        85 UBC           0 :         ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 86                 :                         errmsg("only heap AM is supported")));
                                 87                 : 
 1119 tgl                        88 CBC          12 :     if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
 1119 tgl                        89 UBC           0 :         ereport(ERROR,
                                 90                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 91                 :                  errmsg("\"%s\" is a partitioned table",
                                 92                 :                         RelationGetRelationName(rel)),
                                 93                 :                  errdetail("Partitioned tables do not contain rows.")));
 1119 tgl                        94 CBC          12 :     else if (rel->rd_rel->relkind != RELKIND_RELATION)
 1119 tgl                        95 UBC           0 :         ereport(ERROR,
                                 96                 :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 97                 :                  errmsg("\"%s\" is not a table",
                                 98                 :                         RelationGetRelationName(rel))));
                                 99                 : 
                                100                 :     /*
                                101                 :      * check permissions: must have SELECT on table or be in
                                102                 :      * pg_stat_scan_tables
                                103                 :      */
 1119 tgl                       104 CBC          12 :     aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
                                105                 :                                   ACL_SELECT);
                                106              12 :     if (aclresult != ACLCHECK_OK)
  377 mail                      107 UBC           0 :         aclresult = has_privs_of_role(GetUserId(), ROLE_PG_STAT_SCAN_TABLES) ? ACLCHECK_OK : ACLCHECK_NO_PRIV;
                                108                 : 
 1119 tgl                       109 CBC          12 :     if (aclresult != ACLCHECK_OK)
 1119 tgl                       110 UBC           0 :         aclcheck_error(aclresult, get_relkind_objtype(rel->rd_rel->relkind),
                                111               0 :                        RelationGetRelationName(rel));
                                112                 : 
                                113                 :     /* Scan the relation */
 1119 tgl                       114 CBC          12 :     scan = table_beginscan(rel, GetActiveSnapshot(), 0, NULL);
                                115              12 :     hscan = (HeapScanDesc) scan;
                                116                 : 
  397 michael                   117              12 :     attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
                                118                 : 
                                119              12 :     values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *));
                                120                 : 
 6195 ishii                     121              36 :     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
                                122                 :     {
                                123                 :         TM_Result   htsu;
                                124                 :         TransactionId xmax;
                                125                 :         uint16      infomask;
                                126                 : 
                                127                 :         /* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
 1490 andres                    128              24 :         LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_SHARE);
                                129                 : 
 3548 rhaas                     130              24 :         htsu = HeapTupleSatisfiesUpdate(tuple,
                                131                 :                                         GetCurrentCommandId(false),
                                132                 :                                         hscan->rs_cbuf);
 3728 alvherre                  133              24 :         xmax = HeapTupleHeaderGetRawXmax(tuple->t_data);
                                134              24 :         infomask = tuple->t_data->t_infomask;
                                135                 : 
                                136                 :         /*
                                137                 :          * A tuple is locked if HTSU returns BeingModified.
                                138                 :          */
 1478 andres                    139              24 :         if (htsu == TM_BeingModified)
                                140                 :         {
 3728 alvherre                  141              22 :             values[Atnum_tid] = (char *) DirectFunctionCall1(tidout,
                                142                 :                                                              PointerGetDatum(&tuple->t_self));
                                143                 : 
                                144              22 :             values[Atnum_xmax] = palloc(NCHARS * sizeof(char));
  487 peter                     145              22 :             snprintf(values[Atnum_xmax], NCHARS, "%u", xmax);
 3728 alvherre                  146              22 :             if (infomask & HEAP_XMAX_IS_MULTI)
                                147                 :             {
                                148                 :                 MultiXactMember *members;
                                149                 :                 int         nmembers;
                                150               8 :                 bool        first = true;
                                151                 :                 bool        allow_old;
                                152                 : 
                                153               8 :                 values[Atnum_ismulti] = pstrdup("true");
                                154                 : 
 2480                           155               8 :                 allow_old = HEAP_LOCKED_UPGRADED(infomask);
 3176                           156               8 :                 nmembers = GetMultiXactIdMembers(xmax, &members, allow_old,
                                157                 :                                                  false);
 3728                           158               8 :                 if (nmembers == -1)
                                159                 :                 {
 3728 alvherre                  160 UBC           0 :                     values[Atnum_xids] = "{0}";
                                161               0 :                     values[Atnum_modes] = "{transient upgrade status}";
                                162               0 :                     values[Atnum_pids] = "{0}";
                                163                 :                 }
                                164                 :                 else
                                165                 :                 {
                                166                 :                     int         j;
                                167                 : 
 3728 alvherre                  168 CBC           8 :                     values[Atnum_xids] = palloc(NCHARS * nmembers);
                                169               8 :                     values[Atnum_modes] = palloc(NCHARS * nmembers);
                                170               8 :                     values[Atnum_pids] = palloc(NCHARS * nmembers);
                                171                 : 
                                172               8 :                     strcpy(values[Atnum_xids], "{");
                                173               8 :                     strcpy(values[Atnum_modes], "{");
                                174               8 :                     strcpy(values[Atnum_pids], "{");
                                175                 : 
                                176              24 :                     for (j = 0; j < nmembers; j++)
                                177                 :                     {
                                178                 :                         char        buf[NCHARS];
                                179                 : 
                                180              16 :                         if (!first)
                                181                 :                         {
                                182               8 :                             strcat(values[Atnum_xids], ",");
                                183               8 :                             strcat(values[Atnum_modes], ",");
                                184               8 :                             strcat(values[Atnum_pids], ",");
                                185                 :                         }
  487 peter                     186              16 :                         snprintf(buf, NCHARS, "%u", members[j].xid);
 3728 alvherre                  187              16 :                         strcat(values[Atnum_xids], buf);
                                188              16 :                         switch (members[j].status)
                                189                 :                         {
                                190               1 :                             case MultiXactStatusUpdate:
                                191               1 :                                 snprintf(buf, NCHARS, "Update");
                                192               1 :                                 break;
                                193               1 :                             case MultiXactStatusNoKeyUpdate:
                                194               1 :                                 snprintf(buf, NCHARS, "No Key Update");
                                195               1 :                                 break;
                                196               2 :                             case MultiXactStatusForUpdate:
                                197               2 :                                 snprintf(buf, NCHARS, "For Update");
                                198               2 :                                 break;
                                199               2 :                             case MultiXactStatusForNoKeyUpdate:
                                200               2 :                                 snprintf(buf, NCHARS, "For No Key Update");
                                201               2 :                                 break;
                                202               2 :                             case MultiXactStatusForShare:
                                203               2 :                                 snprintf(buf, NCHARS, "Share");
                                204               2 :                                 break;
                                205               8 :                             case MultiXactStatusForKeyShare:
                                206               8 :                                 snprintf(buf, NCHARS, "Key Share");
                                207               8 :                                 break;
                                208                 :                         }
                                209              16 :                         strcat(values[Atnum_modes], buf);
                                210              16 :                         snprintf(buf, NCHARS, "%d",
                                211              16 :                                  BackendXidGetPid(members[j].xid));
                                212              16 :                         strcat(values[Atnum_pids], buf);
                                213                 : 
                                214              16 :                         first = false;
                                215                 :                     }
                                216                 : 
                                217               8 :                     strcat(values[Atnum_xids], "}");
                                218               8 :                     strcat(values[Atnum_modes], "}");
                                219               8 :                     strcat(values[Atnum_pids], "}");
                                220                 :                 }
                                221                 :             }
                                222                 :             else
                                223                 :             {
                                224              14 :                 values[Atnum_ismulti] = pstrdup("false");
                                225                 : 
                                226              14 :                 values[Atnum_xids] = palloc(NCHARS * sizeof(char));
  487 peter                     227              14 :                 snprintf(values[Atnum_xids], NCHARS, "{%u}", xmax);
                                228                 : 
 3728 alvherre                  229              14 :                 values[Atnum_modes] = palloc(NCHARS);
                                230              14 :                 if (infomask & HEAP_XMAX_LOCK_ONLY)
                                231                 :                 {
                                232              12 :                     if (HEAP_XMAX_IS_SHR_LOCKED(infomask))
                                233               2 :                         snprintf(values[Atnum_modes], NCHARS, "{For Share}");
                                234              10 :                     else if (HEAP_XMAX_IS_KEYSHR_LOCKED(infomask))
                                235               6 :                         snprintf(values[Atnum_modes], NCHARS, "{For Key Share}");
                                236               4 :                     else if (HEAP_XMAX_IS_EXCL_LOCKED(infomask))
                                237                 :                     {
 3720                           238               4 :                         if (tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)
                                239               2 :                             snprintf(values[Atnum_modes], NCHARS, "{For Update}");
                                240                 :                         else
                                241               2 :                             snprintf(values[Atnum_modes], NCHARS, "{For No Key Update}");
                                242                 :                     }
                                243                 :                     else
                                244                 :                         /* neither keyshare nor exclusive bit it set */
 3728 alvherre                  245 UBC           0 :                         snprintf(values[Atnum_modes], NCHARS,
                                246                 :                                  "{transient upgrade status}");
                                247                 :                 }
                                248                 :                 else
                                249                 :                 {
 3728 alvherre                  250 CBC           2 :                     if (tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)
                                251               1 :                         snprintf(values[Atnum_modes], NCHARS, "{Update}");
                                252                 :                     else
 3720                           253               1 :                         snprintf(values[Atnum_modes], NCHARS, "{No Key Update}");
                                254                 :                 }
                                255                 : 
 3728                           256              14 :                 values[Atnum_pids] = palloc(NCHARS * sizeof(char));
                                257              14 :                 snprintf(values[Atnum_pids], NCHARS, "{%d}",
                                258                 :                          BackendXidGetPid(xmax));
                                259                 :             }
                                260                 : 
 1490 andres                    261              22 :             LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_UNLOCK);
                                262                 : 
                                263                 :             /* build a tuple */
 6195 ishii                     264              22 :             tuple = BuildTupleFromCStrings(attinmeta, values);
  397 michael                   265              22 :             tuplestore_puttuple(rsinfo->setResult, tuple);
                                266                 :         }
                                267                 :         else
                                268                 :         {
 1490 andres                    269               2 :             LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_UNLOCK);
                                270                 :         }
                                271                 :     }
                                272                 : 
                                273              12 :     table_endscan(scan);
 1119 tgl                       274              12 :     table_close(rel, AccessShareLock);
                                275              12 :     return (Datum) 0;
                                276                 : }
        

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