LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pgstatfuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15beta1 Lines: 528 1012 52.2 %
Date: 2022-05-18 02:09:37 Functions: 47 109 43.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pgstatfuncs.c
       4             :  *    Functions for accessing various forms of statistics data
       5             :  *
       6             :  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/adt/pgstatfuncs.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/htup_details.h"
      18             : #include "access/xlog.h"
      19             : #include "access/xlogprefetcher.h"
      20             : #include "catalog/pg_authid.h"
      21             : #include "catalog/pg_type.h"
      22             : #include "common/ip.h"
      23             : #include "funcapi.h"
      24             : #include "miscadmin.h"
      25             : #include "pgstat.h"
      26             : #include "postmaster/bgworker_internals.h"
      27             : #include "postmaster/postmaster.h"
      28             : #include "storage/proc.h"
      29             : #include "storage/procarray.h"
      30             : #include "utils/acl.h"
      31             : #include "utils/builtins.h"
      32             : #include "utils/inet.h"
      33             : #include "utils/timestamp.h"
      34             : 
      35             : #define UINT32_ACCESS_ONCE(var)      ((uint32)(*((volatile uint32 *)&(var))))
      36             : 
      37             : #define HAS_PGSTAT_PERMISSIONS(role)     (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
      38             : 
      39             : Datum
      40          86 : pg_stat_get_numscans(PG_FUNCTION_ARGS)
      41             : {
      42          86 :     Oid         relid = PG_GETARG_OID(0);
      43             :     int64       result;
      44             :     PgStat_StatTabEntry *tabentry;
      45             : 
      46          86 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
      47           4 :         result = 0;
      48             :     else
      49          82 :         result = (int64) (tabentry->numscans);
      50             : 
      51          86 :     PG_RETURN_INT64(result);
      52             : }
      53             : 
      54             : 
      55             : Datum
      56          50 : pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
      57             : {
      58          50 :     Oid         relid = PG_GETARG_OID(0);
      59             :     int64       result;
      60             :     PgStat_StatTabEntry *tabentry;
      61             : 
      62          50 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
      63           4 :         result = 0;
      64             :     else
      65          46 :         result = (int64) (tabentry->tuples_returned);
      66             : 
      67          50 :     PG_RETURN_INT64(result);
      68             : }
      69             : 
      70             : 
      71             : Datum
      72          48 : pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
      73             : {
      74          48 :     Oid         relid = PG_GETARG_OID(0);
      75             :     int64       result;
      76             :     PgStat_StatTabEntry *tabentry;
      77             : 
      78          48 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
      79           0 :         result = 0;
      80             :     else
      81          48 :         result = (int64) (tabentry->tuples_fetched);
      82             : 
      83          48 :     PG_RETURN_INT64(result);
      84             : }
      85             : 
      86             : 
      87             : Datum
      88          92 : pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
      89             : {
      90          92 :     Oid         relid = PG_GETARG_OID(0);
      91             :     int64       result;
      92             :     PgStat_StatTabEntry *tabentry;
      93             : 
      94          92 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
      95          10 :         result = 0;
      96             :     else
      97          82 :         result = (int64) (tabentry->tuples_inserted);
      98             : 
      99          92 :     PG_RETURN_INT64(result);
     100             : }
     101             : 
     102             : 
     103             : Datum
     104          68 : pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
     105             : {
     106          68 :     Oid         relid = PG_GETARG_OID(0);
     107             :     int64       result;
     108             :     PgStat_StatTabEntry *tabentry;
     109             : 
     110          68 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     111           4 :         result = 0;
     112             :     else
     113          64 :         result = (int64) (tabentry->tuples_updated);
     114             : 
     115          68 :     PG_RETURN_INT64(result);
     116             : }
     117             : 
     118             : 
     119             : Datum
     120          68 : pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
     121             : {
     122          68 :     Oid         relid = PG_GETARG_OID(0);
     123             :     int64       result;
     124             :     PgStat_StatTabEntry *tabentry;
     125             : 
     126          68 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     127           4 :         result = 0;
     128             :     else
     129          64 :         result = (int64) (tabentry->tuples_deleted);
     130             : 
     131          68 :     PG_RETURN_INT64(result);
     132             : }
     133             : 
     134             : 
     135             : Datum
     136           6 : pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
     137             : {
     138           6 :     Oid         relid = PG_GETARG_OID(0);
     139             :     int64       result;
     140             :     PgStat_StatTabEntry *tabentry;
     141             : 
     142           6 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     143           0 :         result = 0;
     144             :     else
     145           6 :         result = (int64) (tabentry->tuples_hot_updated);
     146             : 
     147           6 :     PG_RETURN_INT64(result);
     148             : }
     149             : 
     150             : 
     151             : Datum
     152         140 : pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
     153             : {
     154         140 :     Oid         relid = PG_GETARG_OID(0);
     155             :     int64       result;
     156             :     PgStat_StatTabEntry *tabentry;
     157             : 
     158         140 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     159          22 :         result = 0;
     160             :     else
     161         118 :         result = (int64) (tabentry->n_live_tuples);
     162             : 
     163         140 :     PG_RETURN_INT64(result);
     164             : }
     165             : 
     166             : 
     167             : Datum
     168          68 : pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
     169             : {
     170          68 :     Oid         relid = PG_GETARG_OID(0);
     171             :     int64       result;
     172             :     PgStat_StatTabEntry *tabentry;
     173             : 
     174          68 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     175           4 :         result = 0;
     176             :     else
     177          64 :         result = (int64) (tabentry->n_dead_tuples);
     178             : 
     179          68 :     PG_RETURN_INT64(result);
     180             : }
     181             : 
     182             : 
     183             : Datum
     184           0 : pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
     185             : {
     186           0 :     Oid         relid = PG_GETARG_OID(0);
     187             :     int64       result;
     188             :     PgStat_StatTabEntry *tabentry;
     189             : 
     190           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     191           0 :         result = 0;
     192             :     else
     193           0 :         result = (int64) (tabentry->changes_since_analyze);
     194             : 
     195           0 :     PG_RETURN_INT64(result);
     196             : }
     197             : 
     198             : 
     199             : Datum
     200           0 : pg_stat_get_ins_since_vacuum(PG_FUNCTION_ARGS)
     201             : {
     202           0 :     Oid         relid = PG_GETARG_OID(0);
     203             :     int64       result;
     204             :     PgStat_StatTabEntry *tabentry;
     205             : 
     206           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     207           0 :         result = 0;
     208             :     else
     209           0 :         result = (int64) (tabentry->inserts_since_vacuum);
     210             : 
     211           0 :     PG_RETURN_INT64(result);
     212             : }
     213             : 
     214             : 
     215             : Datum
     216          48 : pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
     217             : {
     218          48 :     Oid         relid = PG_GETARG_OID(0);
     219             :     int64       result;
     220             :     PgStat_StatTabEntry *tabentry;
     221             : 
     222          48 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     223           0 :         result = 0;
     224             :     else
     225          48 :         result = (int64) (tabentry->blocks_fetched);
     226             : 
     227          48 :     PG_RETURN_INT64(result);
     228             : }
     229             : 
     230             : 
     231             : Datum
     232          96 : pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
     233             : {
     234          96 :     Oid         relid = PG_GETARG_OID(0);
     235             :     int64       result;
     236             :     PgStat_StatTabEntry *tabentry;
     237             : 
     238          96 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     239           0 :         result = 0;
     240             :     else
     241          96 :         result = (int64) (tabentry->blocks_hit);
     242             : 
     243          96 :     PG_RETURN_INT64(result);
     244             : }
     245             : 
     246             : Datum
     247           0 : pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
     248             : {
     249           0 :     Oid         relid = PG_GETARG_OID(0);
     250             :     TimestampTz result;
     251             :     PgStat_StatTabEntry *tabentry;
     252             : 
     253           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     254           0 :         result = 0;
     255             :     else
     256           0 :         result = tabentry->vacuum_timestamp;
     257             : 
     258           0 :     if (result == 0)
     259           0 :         PG_RETURN_NULL();
     260             :     else
     261           0 :         PG_RETURN_TIMESTAMPTZ(result);
     262             : }
     263             : 
     264             : Datum
     265           0 : pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
     266             : {
     267           0 :     Oid         relid = PG_GETARG_OID(0);
     268             :     TimestampTz result;
     269             :     PgStat_StatTabEntry *tabentry;
     270             : 
     271           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     272           0 :         result = 0;
     273             :     else
     274           0 :         result = tabentry->autovac_vacuum_timestamp;
     275             : 
     276           0 :     if (result == 0)
     277           0 :         PG_RETURN_NULL();
     278             :     else
     279           0 :         PG_RETURN_TIMESTAMPTZ(result);
     280             : }
     281             : 
     282             : Datum
     283           0 : pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
     284             : {
     285           0 :     Oid         relid = PG_GETARG_OID(0);
     286             :     TimestampTz result;
     287             :     PgStat_StatTabEntry *tabentry;
     288             : 
     289           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     290           0 :         result = 0;
     291             :     else
     292           0 :         result = tabentry->analyze_timestamp;
     293             : 
     294           0 :     if (result == 0)
     295           0 :         PG_RETURN_NULL();
     296             :     else
     297           0 :         PG_RETURN_TIMESTAMPTZ(result);
     298             : }
     299             : 
     300             : Datum
     301           0 : pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
     302             : {
     303           0 :     Oid         relid = PG_GETARG_OID(0);
     304             :     TimestampTz result;
     305             :     PgStat_StatTabEntry *tabentry;
     306             : 
     307           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     308           0 :         result = 0;
     309             :     else
     310           0 :         result = tabentry->autovac_analyze_timestamp;
     311             : 
     312           0 :     if (result == 0)
     313           0 :         PG_RETURN_NULL();
     314             :     else
     315           0 :         PG_RETURN_TIMESTAMPTZ(result);
     316             : }
     317             : 
     318             : Datum
     319          38 : pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
     320             : {
     321          38 :     Oid         relid = PG_GETARG_OID(0);
     322             :     int64       result;
     323             :     PgStat_StatTabEntry *tabentry;
     324             : 
     325          38 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     326           4 :         result = 0;
     327             :     else
     328          34 :         result = (int64) (tabentry->vacuum_count);
     329             : 
     330          38 :     PG_RETURN_INT64(result);
     331             : }
     332             : 
     333             : Datum
     334           0 : pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
     335             : {
     336           0 :     Oid         relid = PG_GETARG_OID(0);
     337             :     int64       result;
     338             :     PgStat_StatTabEntry *tabentry;
     339             : 
     340           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     341           0 :         result = 0;
     342             :     else
     343           0 :         result = (int64) (tabentry->autovac_vacuum_count);
     344             : 
     345           0 :     PG_RETURN_INT64(result);
     346             : }
     347             : 
     348             : Datum
     349           0 : pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
     350             : {
     351           0 :     Oid         relid = PG_GETARG_OID(0);
     352             :     int64       result;
     353             :     PgStat_StatTabEntry *tabentry;
     354             : 
     355           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     356           0 :         result = 0;
     357             :     else
     358           0 :         result = (int64) (tabentry->analyze_count);
     359             : 
     360           0 :     PG_RETURN_INT64(result);
     361             : }
     362             : 
     363             : Datum
     364           0 : pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
     365             : {
     366           0 :     Oid         relid = PG_GETARG_OID(0);
     367             :     int64       result;
     368             :     PgStat_StatTabEntry *tabentry;
     369             : 
     370           0 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
     371           0 :         result = 0;
     372             :     else
     373           0 :         result = (int64) (tabentry->autovac_analyze_count);
     374             : 
     375           0 :     PG_RETURN_INT64(result);
     376             : }
     377             : 
     378             : Datum
     379         260 : pg_stat_get_function_calls(PG_FUNCTION_ARGS)
     380             : {
     381         260 :     Oid         funcid = PG_GETARG_OID(0);
     382             :     PgStat_StatFuncEntry *funcentry;
     383             : 
     384         260 :     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
     385         106 :         PG_RETURN_NULL();
     386         154 :     PG_RETURN_INT64(funcentry->f_numcalls);
     387             : }
     388             : 
     389             : Datum
     390         154 : pg_stat_get_function_total_time(PG_FUNCTION_ARGS)
     391             : {
     392         154 :     Oid         funcid = PG_GETARG_OID(0);
     393             :     PgStat_StatFuncEntry *funcentry;
     394             : 
     395         154 :     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
     396          66 :         PG_RETURN_NULL();
     397             :     /* convert counter from microsec to millisec for display */
     398          88 :     PG_RETURN_FLOAT8(((double) funcentry->f_total_time) / 1000.0);
     399             : }
     400             : 
     401             : Datum
     402         154 : pg_stat_get_function_self_time(PG_FUNCTION_ARGS)
     403             : {
     404         154 :     Oid         funcid = PG_GETARG_OID(0);
     405             :     PgStat_StatFuncEntry *funcentry;
     406             : 
     407         154 :     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
     408          66 :         PG_RETURN_NULL();
     409             :     /* convert counter from microsec to millisec for display */
     410          88 :     PG_RETURN_FLOAT8(((double) funcentry->f_self_time) / 1000.0);
     411             : }
     412             : 
     413             : Datum
     414           0 : pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
     415             : {
     416             :     FuncCallContext *funcctx;
     417             :     int        *fctx;
     418             :     int32       result;
     419             : 
     420             :     /* stuff done only on the first call of the function */
     421           0 :     if (SRF_IS_FIRSTCALL())
     422             :     {
     423             :         /* create a function context for cross-call persistence */
     424           0 :         funcctx = SRF_FIRSTCALL_INIT();
     425             : 
     426           0 :         fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
     427             :                                   2 * sizeof(int));
     428           0 :         funcctx->user_fctx = fctx;
     429             : 
     430           0 :         fctx[0] = 0;
     431           0 :         fctx[1] = pgstat_fetch_stat_numbackends();
     432             :     }
     433             : 
     434             :     /* stuff done on every call of the function */
     435           0 :     funcctx = SRF_PERCALL_SETUP();
     436           0 :     fctx = funcctx->user_fctx;
     437             : 
     438           0 :     fctx[0] += 1;
     439           0 :     result = fctx[0];
     440             : 
     441           0 :     if (result <= fctx[1])
     442             :     {
     443             :         /* do when there is more left to send */
     444           0 :         SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
     445             :     }
     446             :     else
     447             :     {
     448             :         /* do when there is no more left */
     449           0 :         SRF_RETURN_DONE(funcctx);
     450             :     }
     451             : }
     452             : 
     453             : /*
     454             :  * Returns command progress information for the named command.
     455             :  */
     456             : Datum
     457          12 : pg_stat_get_progress_info(PG_FUNCTION_ARGS)
     458             : {
     459             : #define PG_STAT_GET_PROGRESS_COLS   PGSTAT_NUM_PROGRESS_PARAM + 3
     460          12 :     int         num_backends = pgstat_fetch_stat_numbackends();
     461             :     int         curr_backend;
     462          12 :     char       *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0));
     463             :     ProgressCommandType cmdtype;
     464          12 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
     465             : 
     466             :     /* Translate command name into command type code. */
     467          12 :     if (pg_strcasecmp(cmd, "VACUUM") == 0)
     468           0 :         cmdtype = PROGRESS_COMMAND_VACUUM;
     469          12 :     else if (pg_strcasecmp(cmd, "ANALYZE") == 0)
     470           0 :         cmdtype = PROGRESS_COMMAND_ANALYZE;
     471          12 :     else if (pg_strcasecmp(cmd, "CLUSTER") == 0)
     472           0 :         cmdtype = PROGRESS_COMMAND_CLUSTER;
     473          12 :     else if (pg_strcasecmp(cmd, "CREATE INDEX") == 0)
     474           0 :         cmdtype = PROGRESS_COMMAND_CREATE_INDEX;
     475          12 :     else if (pg_strcasecmp(cmd, "BASEBACKUP") == 0)
     476           0 :         cmdtype = PROGRESS_COMMAND_BASEBACKUP;
     477          12 :     else if (pg_strcasecmp(cmd, "COPY") == 0)
     478          12 :         cmdtype = PROGRESS_COMMAND_COPY;
     479             :     else
     480           0 :         ereport(ERROR,
     481             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     482             :                  errmsg("invalid command name: \"%s\"", cmd)));
     483             : 
     484          12 :     SetSingleFuncCall(fcinfo, 0);
     485             : 
     486             :     /* 1-based index */
     487         118 :     for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
     488             :     {
     489             :         LocalPgBackendStatus *local_beentry;
     490             :         PgBackendStatus *beentry;
     491             :         Datum       values[PG_STAT_GET_PROGRESS_COLS];
     492             :         bool        nulls[PG_STAT_GET_PROGRESS_COLS];
     493             :         int         i;
     494             : 
     495        2544 :         MemSet(values, 0, sizeof(values));
     496         106 :         MemSet(nulls, 0, sizeof(nulls));
     497             : 
     498         106 :         local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
     499             : 
     500         106 :         if (!local_beentry)
     501          94 :             continue;
     502             : 
     503         106 :         beentry = &local_beentry->backendStatus;
     504             : 
     505             :         /*
     506             :          * Report values for only those backends which are running the given
     507             :          * command.
     508             :          */
     509         106 :         if (!beentry || beentry->st_progress_command != cmdtype)
     510          94 :             continue;
     511             : 
     512             :         /* Value available to all callers */
     513          12 :         values[0] = Int32GetDatum(beentry->st_procpid);
     514          12 :         values[1] = ObjectIdGetDatum(beentry->st_databaseid);
     515             : 
     516             :         /* show rest of the values including relid only to role members */
     517          12 :         if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     518             :         {
     519          12 :             values[2] = ObjectIdGetDatum(beentry->st_progress_command_target);
     520         252 :             for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
     521         240 :                 values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]);
     522             :         }
     523             :         else
     524             :         {
     525           0 :             nulls[2] = true;
     526           0 :             for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
     527           0 :                 nulls[i + 3] = true;
     528             :         }
     529             : 
     530          12 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
     531             :     }
     532             : 
     533          12 :     return (Datum) 0;
     534             : }
     535             : 
     536             : /*
     537             :  * Returns activity of PG backends.
     538             :  */
     539             : Datum
     540         948 : pg_stat_get_activity(PG_FUNCTION_ARGS)
     541             : {
     542             : #define PG_STAT_GET_ACTIVITY_COLS   30
     543         948 :     int         num_backends = pgstat_fetch_stat_numbackends();
     544             :     int         curr_backend;
     545         948 :     int         pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
     546         948 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
     547             : 
     548         948 :     SetSingleFuncCall(fcinfo, 0);
     549             : 
     550             :     /* 1-based index */
     551        7866 :     for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
     552             :     {
     553             :         /* for each row */
     554             :         Datum       values[PG_STAT_GET_ACTIVITY_COLS];
     555             :         bool        nulls[PG_STAT_GET_ACTIVITY_COLS];
     556             :         LocalPgBackendStatus *local_beentry;
     557             :         PgBackendStatus *beentry;
     558             :         PGPROC     *proc;
     559        6920 :         const char *wait_event_type = NULL;
     560        6920 :         const char *wait_event = NULL;
     561             : 
     562      214520 :         MemSet(values, 0, sizeof(values));
     563        6920 :         MemSet(nulls, 0, sizeof(nulls));
     564             : 
     565             :         /* Get the next one in the list */
     566        6920 :         local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
     567        6920 :         if (!local_beentry)
     568             :         {
     569             :             int         i;
     570             : 
     571             :             /* Ignore missing entries if looking for specific PID */
     572           0 :             if (pid != -1)
     573           4 :                 continue;
     574             : 
     575           0 :             for (i = 0; i < lengthof(nulls); i++)
     576           0 :                 nulls[i] = true;
     577             : 
     578           0 :             nulls[5] = false;
     579           0 :             values[5] = CStringGetTextDatum("<backend information not available>");
     580             : 
     581           0 :             tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
     582           0 :             continue;
     583             :         }
     584             : 
     585        6920 :         beentry = &local_beentry->backendStatus;
     586             : 
     587             :         /* If looking for specific PID, ignore all the others */
     588        6920 :         if (pid != -1 && beentry->st_procpid != pid)
     589           4 :             continue;
     590             : 
     591             :         /* Values available to all callers */
     592        6916 :         if (beentry->st_databaseid != InvalidOid)
     593        1848 :             values[0] = ObjectIdGetDatum(beentry->st_databaseid);
     594             :         else
     595        5068 :             nulls[0] = true;
     596             : 
     597        6916 :         values[1] = Int32GetDatum(beentry->st_procpid);
     598             : 
     599        6916 :         if (beentry->st_userid != InvalidOid)
     600        3130 :             values[2] = ObjectIdGetDatum(beentry->st_userid);
     601             :         else
     602        3786 :             nulls[2] = true;
     603             : 
     604        6916 :         if (beentry->st_appname)
     605        6916 :             values[3] = CStringGetTextDatum(beentry->st_appname);
     606             :         else
     607           0 :             nulls[3] = true;
     608             : 
     609        6916 :         if (TransactionIdIsValid(local_beentry->backend_xid))
     610          32 :             values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
     611             :         else
     612        6884 :             nulls[15] = true;
     613             : 
     614        6916 :         if (TransactionIdIsValid(local_beentry->backend_xmin))
     615         992 :             values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
     616             :         else
     617        5924 :             nulls[16] = true;
     618             : 
     619             :         /* Values only available to role member or pg_read_all_stats */
     620        6916 :         if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     621        6834 :         {
     622             :             SockAddr    zero_clientaddr;
     623             :             char       *clipped_activity;
     624             : 
     625        6834 :             switch (beentry->st_state)
     626             :             {
     627          92 :                 case STATE_IDLE:
     628          92 :                     values[4] = CStringGetTextDatum("idle");
     629          92 :                     break;
     630        2078 :                 case STATE_RUNNING:
     631        2078 :                     values[4] = CStringGetTextDatum("active");
     632        2078 :                     break;
     633          26 :                 case STATE_IDLEINTRANSACTION:
     634          26 :                     values[4] = CStringGetTextDatum("idle in transaction");
     635          26 :                     break;
     636           0 :                 case STATE_FASTPATH:
     637           0 :                     values[4] = CStringGetTextDatum("fastpath function call");
     638           0 :                     break;
     639           0 :                 case STATE_IDLEINTRANSACTION_ABORTED:
     640           0 :                     values[4] = CStringGetTextDatum("idle in transaction (aborted)");
     641           0 :                     break;
     642           0 :                 case STATE_DISABLED:
     643           0 :                     values[4] = CStringGetTextDatum("disabled");
     644           0 :                     break;
     645        4638 :                 case STATE_UNDEFINED:
     646        4638 :                     nulls[4] = true;
     647        4638 :                     break;
     648             :             }
     649             : 
     650        6834 :             clipped_activity = pgstat_clip_activity(beentry->st_activity_raw);
     651        6834 :             values[5] = CStringGetTextDatum(clipped_activity);
     652        6834 :             pfree(clipped_activity);
     653             : 
     654             :             /* leader_pid */
     655        6834 :             nulls[28] = true;
     656             : 
     657        6834 :             proc = BackendPidGetProc(beentry->st_procpid);
     658             : 
     659        6834 :             if (proc == NULL && (beentry->st_backendType != B_BACKEND))
     660             :             {
     661             :                 /*
     662             :                  * For an auxiliary process, retrieve process info from
     663             :                  * AuxiliaryProcs stored in shared-memory.
     664             :                  */
     665        2816 :                 proc = AuxiliaryPidGetProc(beentry->st_procpid);
     666             :             }
     667             : 
     668             :             /*
     669             :              * If a PGPROC entry was retrieved, display wait events and lock
     670             :              * group leader information if any.  To avoid extra overhead, no
     671             :              * extra lock is being held, so there is no guarantee of
     672             :              * consistency across multiple rows.
     673             :              */
     674        6834 :             if (proc != NULL)
     675             :             {
     676             :                 uint32      raw_wait_event;
     677             :                 PGPROC     *leader;
     678             : 
     679        6834 :                 raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info);
     680        6834 :                 wait_event_type = pgstat_get_wait_event_type(raw_wait_event);
     681        6834 :                 wait_event = pgstat_get_wait_event(raw_wait_event);
     682             : 
     683        6834 :                 leader = proc->lockGroupLeader;
     684             : 
     685             :                 /*
     686             :                  * Show the leader only for active parallel workers.  This
     687             :                  * leaves the field as NULL for the leader of a parallel
     688             :                  * group.
     689             :                  */
     690        6834 :                 if (leader && leader->pid != beentry->st_procpid)
     691             :                 {
     692           0 :                     values[28] = Int32GetDatum(leader->pid);
     693           0 :                     nulls[28] = false;
     694             :                 }
     695             :             }
     696             : 
     697        6834 :             if (wait_event_type)
     698        5850 :                 values[6] = CStringGetTextDatum(wait_event_type);
     699             :             else
     700         984 :                 nulls[6] = true;
     701             : 
     702        6834 :             if (wait_event)
     703        5850 :                 values[7] = CStringGetTextDatum(wait_event);
     704             :             else
     705         984 :                 nulls[7] = true;
     706             : 
     707             :             /*
     708             :              * Don't expose transaction time for walsenders; it confuses
     709             :              * monitoring, particularly because we don't keep the time up-to-
     710             :              * date.
     711             :              */
     712        6834 :             if (beentry->st_xact_start_timestamp != 0 &&
     713        1014 :                 beentry->st_backendType != B_WAL_SENDER)
     714        1008 :                 values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
     715             :             else
     716        5826 :                 nulls[8] = true;
     717             : 
     718        6834 :             if (beentry->st_activity_start_timestamp != 0)
     719        2154 :                 values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
     720             :             else
     721        4680 :                 nulls[9] = true;
     722             : 
     723        6834 :             if (beentry->st_proc_start_timestamp != 0)
     724        6834 :                 values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
     725             :             else
     726           0 :                 nulls[10] = true;
     727             : 
     728        6834 :             if (beentry->st_state_start_timestamp != 0)
     729        2196 :                 values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
     730             :             else
     731        4638 :                 nulls[11] = true;
     732             : 
     733             :             /* A zeroed client addr means we don't know */
     734        6834 :             memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
     735        6834 :             if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
     736             :                        sizeof(zero_clientaddr)) == 0)
     737             :             {
     738        4674 :                 nulls[12] = true;
     739        4674 :                 nulls[13] = true;
     740        4674 :                 nulls[14] = true;
     741             :             }
     742             :             else
     743             :             {
     744        2160 :                 if (beentry->st_clientaddr.addr.ss_family == AF_INET
     745             : #ifdef HAVE_IPV6
     746        2146 :                     || beentry->st_clientaddr.addr.ss_family == AF_INET6
     747             : #endif
     748             :                     )
     749          14 :                 {
     750             :                     char        remote_host[NI_MAXHOST];
     751             :                     char        remote_port[NI_MAXSERV];
     752             :                     int         ret;
     753             : 
     754          14 :                     remote_host[0] = '\0';
     755          14 :                     remote_port[0] = '\0';
     756          14 :                     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
     757          14 :                                              beentry->st_clientaddr.salen,
     758             :                                              remote_host, sizeof(remote_host),
     759             :                                              remote_port, sizeof(remote_port),
     760             :                                              NI_NUMERICHOST | NI_NUMERICSERV);
     761          14 :                     if (ret == 0)
     762             :                     {
     763          14 :                         clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
     764          14 :                         values[12] = DirectFunctionCall1(inet_in,
     765             :                                                          CStringGetDatum(remote_host));
     766          14 :                         if (beentry->st_clienthostname &&
     767          14 :                             beentry->st_clienthostname[0])
     768          14 :                             values[13] = CStringGetTextDatum(beentry->st_clienthostname);
     769             :                         else
     770           0 :                             nulls[13] = true;
     771          14 :                         values[14] = Int32GetDatum(atoi(remote_port));
     772             :                     }
     773             :                     else
     774             :                     {
     775           0 :                         nulls[12] = true;
     776           0 :                         nulls[13] = true;
     777           0 :                         nulls[14] = true;
     778             :                     }
     779             :                 }
     780        2146 :                 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
     781             :                 {
     782             :                     /*
     783             :                      * Unix sockets always reports NULL for host and -1 for
     784             :                      * port, so it's possible to tell the difference to
     785             :                      * connections we have no permissions to view, or with
     786             :                      * errors.
     787             :                      */
     788        2146 :                     nulls[12] = true;
     789        2146 :                     nulls[13] = true;
     790        2146 :                     values[14] = Int32GetDatum(-1);
     791             :                 }
     792             :                 else
     793             :                 {
     794             :                     /* Unknown address type, should never happen */
     795           0 :                     nulls[12] = true;
     796           0 :                     nulls[13] = true;
     797           0 :                     nulls[14] = true;
     798             :                 }
     799             :             }
     800             :             /* Add backend type */
     801        6834 :             if (beentry->st_backendType == B_BG_WORKER)
     802             :             {
     803             :                 const char *bgw_type;
     804             : 
     805         952 :                 bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid);
     806         952 :                 if (bgw_type)
     807         952 :                     values[17] = CStringGetTextDatum(bgw_type);
     808             :                 else
     809           0 :                     nulls[17] = true;
     810             :             }
     811             :             else
     812        5882 :                 values[17] =
     813        5882 :                     CStringGetTextDatum(GetBackendTypeDesc(beentry->st_backendType));
     814             : 
     815             :             /* SSL information */
     816        6834 :             if (beentry->st_ssl)
     817             :             {
     818          14 :                 values[18] = BoolGetDatum(true);    /* ssl */
     819          14 :                 values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
     820          14 :                 values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
     821          14 :                 values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
     822             : 
     823          14 :                 if (beentry->st_sslstatus->ssl_client_dn[0])
     824          12 :                     values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_client_dn);
     825             :                 else
     826           2 :                     nulls[22] = true;
     827             : 
     828          14 :                 if (beentry->st_sslstatus->ssl_client_serial[0])
     829          12 :                     values[23] = DirectFunctionCall3(numeric_in,
     830             :                                                      CStringGetDatum(beentry->st_sslstatus->ssl_client_serial),
     831             :                                                      ObjectIdGetDatum(InvalidOid),
     832             :                                                      Int32GetDatum(-1));
     833             :                 else
     834           2 :                     nulls[23] = true;
     835             : 
     836          14 :                 if (beentry->st_sslstatus->ssl_issuer_dn[0])
     837          12 :                     values[24] = CStringGetTextDatum(beentry->st_sslstatus->ssl_issuer_dn);
     838             :                 else
     839           2 :                     nulls[24] = true;
     840             :             }
     841             :             else
     842             :             {
     843        6820 :                 values[18] = BoolGetDatum(false);   /* ssl */
     844        6820 :                 nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = nulls[24] = true;
     845             :             }
     846             : 
     847             :             /* GSSAPI information */
     848        6834 :             if (beentry->st_gss)
     849             :             {
     850           0 :                 values[25] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */
     851           0 :                 values[26] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ);
     852           0 :                 values[27] = BoolGetDatum(beentry->st_gssstatus->gss_enc);    /* GSS Encryption in use */
     853             :             }
     854             :             else
     855             :             {
     856        6834 :                 values[25] = BoolGetDatum(false);   /* gss_auth */
     857        6834 :                 nulls[26] = true;   /* No GSS principal */
     858        6834 :                 values[27] = BoolGetDatum(false);   /* GSS Encryption not in
     859             :                                                      * use */
     860             :             }
     861        6834 :             if (beentry->st_query_id == 0)
     862        6834 :                 nulls[29] = true;
     863             :             else
     864           0 :                 values[29] = UInt64GetDatum(beentry->st_query_id);
     865             :         }
     866             :         else
     867             :         {
     868             :             /* No permissions to view data about this session */
     869          82 :             values[5] = CStringGetTextDatum("<insufficient privilege>");
     870          82 :             nulls[4] = true;
     871          82 :             nulls[6] = true;
     872          82 :             nulls[7] = true;
     873          82 :             nulls[8] = true;
     874          82 :             nulls[9] = true;
     875          82 :             nulls[10] = true;
     876          82 :             nulls[11] = true;
     877          82 :             nulls[12] = true;
     878          82 :             nulls[13] = true;
     879          82 :             nulls[14] = true;
     880          82 :             nulls[17] = true;
     881          82 :             nulls[18] = true;
     882          82 :             nulls[19] = true;
     883          82 :             nulls[20] = true;
     884          82 :             nulls[21] = true;
     885          82 :             nulls[22] = true;
     886          82 :             nulls[23] = true;
     887          82 :             nulls[24] = true;
     888          82 :             nulls[25] = true;
     889          82 :             nulls[26] = true;
     890          82 :             nulls[27] = true;
     891          82 :             nulls[28] = true;
     892          82 :             nulls[29] = true;
     893             :         }
     894             : 
     895        6916 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
     896             : 
     897             :         /* If only a single backend was requested, and we found it, break. */
     898        6916 :         if (pid != -1)
     899           2 :             break;
     900             :     }
     901             : 
     902         948 :     return (Datum) 0;
     903             : }
     904             : 
     905             : 
     906             : Datum
     907         472 : pg_backend_pid(PG_FUNCTION_ARGS)
     908             : {
     909         472 :     PG_RETURN_INT32(MyProcPid);
     910             : }
     911             : 
     912             : 
     913             : Datum
     914           0 : pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
     915             : {
     916           0 :     int32       beid = PG_GETARG_INT32(0);
     917             :     PgBackendStatus *beentry;
     918             : 
     919           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     920           0 :         PG_RETURN_NULL();
     921             : 
     922           0 :     PG_RETURN_INT32(beentry->st_procpid);
     923             : }
     924             : 
     925             : 
     926             : Datum
     927           0 : pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
     928             : {
     929           0 :     int32       beid = PG_GETARG_INT32(0);
     930             :     PgBackendStatus *beentry;
     931             : 
     932           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     933           0 :         PG_RETURN_NULL();
     934             : 
     935           0 :     PG_RETURN_OID(beentry->st_databaseid);
     936             : }
     937             : 
     938             : 
     939             : Datum
     940           0 : pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
     941             : {
     942           0 :     int32       beid = PG_GETARG_INT32(0);
     943             :     PgBackendStatus *beentry;
     944             : 
     945           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     946           0 :         PG_RETURN_NULL();
     947             : 
     948           0 :     PG_RETURN_OID(beentry->st_userid);
     949             : }
     950             : 
     951             : 
     952             : Datum
     953           0 : pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
     954             : {
     955           0 :     int32       beid = PG_GETARG_INT32(0);
     956             :     PgBackendStatus *beentry;
     957             :     const char *activity;
     958             :     char       *clipped_activity;
     959             :     text       *ret;
     960             : 
     961           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     962           0 :         activity = "<backend information not available>";
     963           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     964           0 :         activity = "<insufficient privilege>";
     965           0 :     else if (*(beentry->st_activity_raw) == '\0')
     966           0 :         activity = "<command string not enabled>";
     967             :     else
     968           0 :         activity = beentry->st_activity_raw;
     969             : 
     970           0 :     clipped_activity = pgstat_clip_activity(activity);
     971           0 :     ret = cstring_to_text(activity);
     972           0 :     pfree(clipped_activity);
     973             : 
     974           0 :     PG_RETURN_TEXT_P(ret);
     975             : }
     976             : 
     977             : Datum
     978           0 : pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS)
     979             : {
     980           0 :     int32       beid = PG_GETARG_INT32(0);
     981             :     PgBackendStatus *beentry;
     982             :     PGPROC     *proc;
     983           0 :     const char *wait_event_type = NULL;
     984             : 
     985           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     986           0 :         wait_event_type = "<backend information not available>";
     987           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     988           0 :         wait_event_type = "<insufficient privilege>";
     989           0 :     else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
     990           0 :         wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
     991             : 
     992           0 :     if (!wait_event_type)
     993           0 :         PG_RETURN_NULL();
     994             : 
     995           0 :     PG_RETURN_TEXT_P(cstring_to_text(wait_event_type));
     996             : }
     997             : 
     998             : Datum
     999           0 : pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS)
    1000             : {
    1001           0 :     int32       beid = PG_GETARG_INT32(0);
    1002             :     PgBackendStatus *beentry;
    1003             :     PGPROC     *proc;
    1004           0 :     const char *wait_event = NULL;
    1005             : 
    1006           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1007           0 :         wait_event = "<backend information not available>";
    1008           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1009           0 :         wait_event = "<insufficient privilege>";
    1010           0 :     else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
    1011           0 :         wait_event = pgstat_get_wait_event(proc->wait_event_info);
    1012             : 
    1013           0 :     if (!wait_event)
    1014           0 :         PG_RETURN_NULL();
    1015             : 
    1016           0 :     PG_RETURN_TEXT_P(cstring_to_text(wait_event));
    1017             : }
    1018             : 
    1019             : 
    1020             : Datum
    1021           0 : pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
    1022             : {
    1023           0 :     int32       beid = PG_GETARG_INT32(0);
    1024             :     TimestampTz result;
    1025             :     PgBackendStatus *beentry;
    1026             : 
    1027           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1028           0 :         PG_RETURN_NULL();
    1029             : 
    1030           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1031           0 :         PG_RETURN_NULL();
    1032             : 
    1033           0 :     result = beentry->st_activity_start_timestamp;
    1034             : 
    1035             :     /*
    1036             :      * No time recorded for start of current query -- this is the case if the
    1037             :      * user hasn't enabled query-level stats collection.
    1038             :      */
    1039           0 :     if (result == 0)
    1040           0 :         PG_RETURN_NULL();
    1041             : 
    1042           0 :     PG_RETURN_TIMESTAMPTZ(result);
    1043             : }
    1044             : 
    1045             : 
    1046             : Datum
    1047           0 : pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
    1048             : {
    1049           0 :     int32       beid = PG_GETARG_INT32(0);
    1050             :     TimestampTz result;
    1051             :     PgBackendStatus *beentry;
    1052             : 
    1053           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1054           0 :         PG_RETURN_NULL();
    1055             : 
    1056           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1057           0 :         PG_RETURN_NULL();
    1058             : 
    1059           0 :     result = beentry->st_xact_start_timestamp;
    1060             : 
    1061           0 :     if (result == 0)            /* not in a transaction */
    1062           0 :         PG_RETURN_NULL();
    1063             : 
    1064           0 :     PG_RETURN_TIMESTAMPTZ(result);
    1065             : }
    1066             : 
    1067             : 
    1068             : Datum
    1069           0 : pg_stat_get_backend_start(PG_FUNCTION_ARGS)
    1070             : {
    1071           0 :     int32       beid = PG_GETARG_INT32(0);
    1072             :     TimestampTz result;
    1073             :     PgBackendStatus *beentry;
    1074             : 
    1075           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1076           0 :         PG_RETURN_NULL();
    1077             : 
    1078           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1079           0 :         PG_RETURN_NULL();
    1080             : 
    1081           0 :     result = beentry->st_proc_start_timestamp;
    1082             : 
    1083           0 :     if (result == 0)            /* probably can't happen? */
    1084           0 :         PG_RETURN_NULL();
    1085             : 
    1086           0 :     PG_RETURN_TIMESTAMPTZ(result);
    1087             : }
    1088             : 
    1089             : 
    1090             : Datum
    1091           0 : pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
    1092             : {
    1093           0 :     int32       beid = PG_GETARG_INT32(0);
    1094             :     PgBackendStatus *beentry;
    1095             :     SockAddr    zero_clientaddr;
    1096             :     char        remote_host[NI_MAXHOST];
    1097             :     int         ret;
    1098             : 
    1099           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1100           0 :         PG_RETURN_NULL();
    1101             : 
    1102           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1103           0 :         PG_RETURN_NULL();
    1104             : 
    1105             :     /* A zeroed client addr means we don't know */
    1106           0 :     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
    1107           0 :     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
    1108             :                sizeof(zero_clientaddr)) == 0)
    1109           0 :         PG_RETURN_NULL();
    1110             : 
    1111           0 :     switch (beentry->st_clientaddr.addr.ss_family)
    1112             :     {
    1113           0 :         case AF_INET:
    1114             : #ifdef HAVE_IPV6
    1115             :         case AF_INET6:
    1116             : #endif
    1117           0 :             break;
    1118           0 :         default:
    1119           0 :             PG_RETURN_NULL();
    1120             :     }
    1121             : 
    1122           0 :     remote_host[0] = '\0';
    1123           0 :     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
    1124           0 :                              beentry->st_clientaddr.salen,
    1125             :                              remote_host, sizeof(remote_host),
    1126             :                              NULL, 0,
    1127             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1128           0 :     if (ret != 0)
    1129           0 :         PG_RETURN_NULL();
    1130             : 
    1131           0 :     clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
    1132             : 
    1133           0 :     PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
    1134             :                                          CStringGetDatum(remote_host)));
    1135             : }
    1136             : 
    1137             : Datum
    1138           0 : pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
    1139             : {
    1140           0 :     int32       beid = PG_GETARG_INT32(0);
    1141             :     PgBackendStatus *beentry;
    1142             :     SockAddr    zero_clientaddr;
    1143             :     char        remote_port[NI_MAXSERV];
    1144             :     int         ret;
    1145             : 
    1146           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
    1147           0 :         PG_RETURN_NULL();
    1148             : 
    1149           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
    1150           0 :         PG_RETURN_NULL();
    1151             : 
    1152             :     /* A zeroed client addr means we don't know */
    1153           0 :     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
    1154           0 :     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
    1155             :                sizeof(zero_clientaddr)) == 0)
    1156           0 :         PG_RETURN_NULL();
    1157             : 
    1158           0 :     switch (beentry->st_clientaddr.addr.ss_family)
    1159             :     {
    1160           0 :         case AF_INET:
    1161             : #ifdef HAVE_IPV6
    1162             :         case AF_INET6:
    1163             : #endif
    1164           0 :             break;
    1165           0 :         case AF_UNIX:
    1166           0 :             PG_RETURN_INT32(-1);
    1167           0 :         default:
    1168           0 :             PG_RETURN_NULL();
    1169             :     }
    1170             : 
    1171           0 :     remote_port[0] = '\0';
    1172           0 :     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
    1173           0 :                              beentry->st_clientaddr.salen,
    1174             :                              NULL, 0,
    1175             :                              remote_port, sizeof(remote_port),
    1176             :                              NI_NUMERICHOST | NI_NUMERICSERV);
    1177           0 :     if (ret != 0)
    1178           0 :         PG_RETURN_NULL();
    1179             : 
    1180           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in,
    1181             :                                         CStringGetDatum(remote_port)));
    1182             : }
    1183             : 
    1184             : 
    1185             : Datum
    1186           0 : pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
    1187             : {
    1188           0 :     Oid         dbid = PG_GETARG_OID(0);
    1189             :     int32       result;
    1190           0 :     int         tot_backends = pgstat_fetch_stat_numbackends();
    1191             :     int         beid;
    1192             : 
    1193           0 :     result = 0;
    1194           0 :     for (beid = 1; beid <= tot_backends; beid++)
    1195             :     {
    1196           0 :         PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
    1197             : 
    1198           0 :         if (beentry && beentry->st_databaseid == dbid)
    1199           0 :             result++;
    1200             :     }
    1201             : 
    1202           0 :     PG_RETURN_INT32(result);
    1203             : }
    1204             : 
    1205             : 
    1206             : Datum
    1207           0 : pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
    1208             : {
    1209           0 :     Oid         dbid = PG_GETARG_OID(0);
    1210             :     int64       result;
    1211             :     PgStat_StatDBEntry *dbentry;
    1212             : 
    1213           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1214           0 :         result = 0;
    1215             :     else
    1216           0 :         result = (int64) (dbentry->n_xact_commit);
    1217             : 
    1218           0 :     PG_RETURN_INT64(result);
    1219             : }
    1220             : 
    1221             : 
    1222             : Datum
    1223           0 : pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
    1224             : {
    1225           0 :     Oid         dbid = PG_GETARG_OID(0);
    1226             :     int64       result;
    1227             :     PgStat_StatDBEntry *dbentry;
    1228             : 
    1229           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1230           0 :         result = 0;
    1231             :     else
    1232           0 :         result = (int64) (dbentry->n_xact_rollback);
    1233             : 
    1234           0 :     PG_RETURN_INT64(result);
    1235             : }
    1236             : 
    1237             : 
    1238             : Datum
    1239           0 : pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
    1240             : {
    1241           0 :     Oid         dbid = PG_GETARG_OID(0);
    1242             :     int64       result;
    1243             :     PgStat_StatDBEntry *dbentry;
    1244             : 
    1245           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1246           0 :         result = 0;
    1247             :     else
    1248           0 :         result = (int64) (dbentry->n_blocks_fetched);
    1249             : 
    1250           0 :     PG_RETURN_INT64(result);
    1251             : }
    1252             : 
    1253             : 
    1254             : Datum
    1255           0 : pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
    1256             : {
    1257           0 :     Oid         dbid = PG_GETARG_OID(0);
    1258             :     int64       result;
    1259             :     PgStat_StatDBEntry *dbentry;
    1260             : 
    1261           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1262           0 :         result = 0;
    1263             :     else
    1264           0 :         result = (int64) (dbentry->n_blocks_hit);
    1265             : 
    1266           0 :     PG_RETURN_INT64(result);
    1267             : }
    1268             : 
    1269             : 
    1270             : Datum
    1271           0 : pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
    1272             : {
    1273           0 :     Oid         dbid = PG_GETARG_OID(0);
    1274             :     int64       result;
    1275             :     PgStat_StatDBEntry *dbentry;
    1276             : 
    1277           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1278           0 :         result = 0;
    1279             :     else
    1280           0 :         result = (int64) (dbentry->n_tuples_returned);
    1281             : 
    1282           0 :     PG_RETURN_INT64(result);
    1283             : }
    1284             : 
    1285             : 
    1286             : Datum
    1287           0 : pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
    1288             : {
    1289           0 :     Oid         dbid = PG_GETARG_OID(0);
    1290             :     int64       result;
    1291             :     PgStat_StatDBEntry *dbentry;
    1292             : 
    1293           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1294           0 :         result = 0;
    1295             :     else
    1296           0 :         result = (int64) (dbentry->n_tuples_fetched);
    1297             : 
    1298           0 :     PG_RETURN_INT64(result);
    1299             : }
    1300             : 
    1301             : 
    1302             : Datum
    1303           0 : pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
    1304             : {
    1305           0 :     Oid         dbid = PG_GETARG_OID(0);
    1306             :     int64       result;
    1307             :     PgStat_StatDBEntry *dbentry;
    1308             : 
    1309           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1310           0 :         result = 0;
    1311             :     else
    1312           0 :         result = (int64) (dbentry->n_tuples_inserted);
    1313             : 
    1314           0 :     PG_RETURN_INT64(result);
    1315             : }
    1316             : 
    1317             : 
    1318             : Datum
    1319           0 : pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
    1320             : {
    1321           0 :     Oid         dbid = PG_GETARG_OID(0);
    1322             :     int64       result;
    1323             :     PgStat_StatDBEntry *dbentry;
    1324             : 
    1325           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1326           0 :         result = 0;
    1327             :     else
    1328           0 :         result = (int64) (dbentry->n_tuples_updated);
    1329             : 
    1330           0 :     PG_RETURN_INT64(result);
    1331             : }
    1332             : 
    1333             : 
    1334             : Datum
    1335           0 : pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
    1336             : {
    1337           0 :     Oid         dbid = PG_GETARG_OID(0);
    1338             :     int64       result;
    1339             :     PgStat_StatDBEntry *dbentry;
    1340             : 
    1341           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1342           0 :         result = 0;
    1343             :     else
    1344           0 :         result = (int64) (dbentry->n_tuples_deleted);
    1345             : 
    1346           0 :     PG_RETURN_INT64(result);
    1347             : }
    1348             : 
    1349             : Datum
    1350          12 : pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
    1351             : {
    1352          12 :     Oid         dbid = PG_GETARG_OID(0);
    1353             :     TimestampTz result;
    1354             :     PgStat_StatDBEntry *dbentry;
    1355             : 
    1356          12 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1357           0 :         result = 0;
    1358             :     else
    1359          12 :         result = dbentry->stat_reset_timestamp;
    1360             : 
    1361          12 :     if (result == 0)
    1362           0 :         PG_RETURN_NULL();
    1363             :     else
    1364          12 :         PG_RETURN_TIMESTAMPTZ(result);
    1365             : }
    1366             : 
    1367             : Datum
    1368           0 : pg_stat_get_db_temp_files(PG_FUNCTION_ARGS)
    1369             : {
    1370           0 :     Oid         dbid = PG_GETARG_OID(0);
    1371             :     int64       result;
    1372             :     PgStat_StatDBEntry *dbentry;
    1373             : 
    1374           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1375           0 :         result = 0;
    1376             :     else
    1377           0 :         result = dbentry->n_temp_files;
    1378             : 
    1379           0 :     PG_RETURN_INT64(result);
    1380             : }
    1381             : 
    1382             : 
    1383             : Datum
    1384           0 : pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS)
    1385             : {
    1386           0 :     Oid         dbid = PG_GETARG_OID(0);
    1387             :     int64       result;
    1388             :     PgStat_StatDBEntry *dbentry;
    1389             : 
    1390           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1391           0 :         result = 0;
    1392             :     else
    1393           0 :         result = dbentry->n_temp_bytes;
    1394             : 
    1395           0 :     PG_RETURN_INT64(result);
    1396             : }
    1397             : 
    1398             : Datum
    1399           2 : pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS)
    1400             : {
    1401           2 :     Oid         dbid = PG_GETARG_OID(0);
    1402             :     int64       result;
    1403             :     PgStat_StatDBEntry *dbentry;
    1404             : 
    1405           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1406           0 :         result = 0;
    1407             :     else
    1408           2 :         result = (int64) (dbentry->n_conflict_tablespace);
    1409             : 
    1410           2 :     PG_RETURN_INT64(result);
    1411             : }
    1412             : 
    1413             : Datum
    1414           2 : pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS)
    1415             : {
    1416           2 :     Oid         dbid = PG_GETARG_OID(0);
    1417             :     int64       result;
    1418             :     PgStat_StatDBEntry *dbentry;
    1419             : 
    1420           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1421           0 :         result = 0;
    1422             :     else
    1423           2 :         result = (int64) (dbentry->n_conflict_lock);
    1424             : 
    1425           2 :     PG_RETURN_INT64(result);
    1426             : }
    1427             : 
    1428             : Datum
    1429           2 : pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS)
    1430             : {
    1431           2 :     Oid         dbid = PG_GETARG_OID(0);
    1432             :     int64       result;
    1433             :     PgStat_StatDBEntry *dbentry;
    1434             : 
    1435           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1436           0 :         result = 0;
    1437             :     else
    1438           2 :         result = (int64) (dbentry->n_conflict_snapshot);
    1439             : 
    1440           2 :     PG_RETURN_INT64(result);
    1441             : }
    1442             : 
    1443             : Datum
    1444           2 : pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS)
    1445             : {
    1446           2 :     Oid         dbid = PG_GETARG_OID(0);
    1447             :     int64       result;
    1448             :     PgStat_StatDBEntry *dbentry;
    1449             : 
    1450           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1451           0 :         result = 0;
    1452             :     else
    1453           2 :         result = (int64) (dbentry->n_conflict_bufferpin);
    1454             : 
    1455           2 :     PG_RETURN_INT64(result);
    1456             : }
    1457             : 
    1458             : Datum
    1459           2 : pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS)
    1460             : {
    1461           2 :     Oid         dbid = PG_GETARG_OID(0);
    1462             :     int64       result;
    1463             :     PgStat_StatDBEntry *dbentry;
    1464             : 
    1465           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1466           0 :         result = 0;
    1467             :     else
    1468           2 :         result = (int64) (dbentry->n_conflict_startup_deadlock);
    1469             : 
    1470           2 :     PG_RETURN_INT64(result);
    1471             : }
    1472             : 
    1473             : Datum
    1474           2 : pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
    1475             : {
    1476           2 :     Oid         dbid = PG_GETARG_OID(0);
    1477             :     int64       result;
    1478             :     PgStat_StatDBEntry *dbentry;
    1479             : 
    1480           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1481           0 :         result = 0;
    1482             :     else
    1483           2 :         result = (int64) (dbentry->n_conflict_tablespace +
    1484           2 :                           dbentry->n_conflict_lock +
    1485           2 :                           dbentry->n_conflict_snapshot +
    1486           2 :                           dbentry->n_conflict_bufferpin +
    1487           2 :                           dbentry->n_conflict_startup_deadlock);
    1488             : 
    1489           2 :     PG_RETURN_INT64(result);
    1490             : }
    1491             : 
    1492             : Datum
    1493           2 : pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS)
    1494             : {
    1495           2 :     Oid         dbid = PG_GETARG_OID(0);
    1496             :     int64       result;
    1497             :     PgStat_StatDBEntry *dbentry;
    1498             : 
    1499           2 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1500           0 :         result = 0;
    1501             :     else
    1502           2 :         result = (int64) (dbentry->n_deadlocks);
    1503             : 
    1504           2 :     PG_RETURN_INT64(result);
    1505             : }
    1506             : 
    1507             : Datum
    1508           0 : pg_stat_get_db_checksum_failures(PG_FUNCTION_ARGS)
    1509             : {
    1510           0 :     Oid         dbid = PG_GETARG_OID(0);
    1511             :     int64       result;
    1512             :     PgStat_StatDBEntry *dbentry;
    1513             : 
    1514           0 :     if (!DataChecksumsEnabled())
    1515           0 :         PG_RETURN_NULL();
    1516             : 
    1517           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1518           0 :         result = 0;
    1519             :     else
    1520           0 :         result = (int64) (dbentry->n_checksum_failures);
    1521             : 
    1522           0 :     PG_RETURN_INT64(result);
    1523             : }
    1524             : 
    1525             : Datum
    1526           0 : pg_stat_get_db_checksum_last_failure(PG_FUNCTION_ARGS)
    1527             : {
    1528           0 :     Oid         dbid = PG_GETARG_OID(0);
    1529             :     TimestampTz result;
    1530             :     PgStat_StatDBEntry *dbentry;
    1531             : 
    1532           0 :     if (!DataChecksumsEnabled())
    1533           0 :         PG_RETURN_NULL();
    1534             : 
    1535           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1536           0 :         result = 0;
    1537             :     else
    1538           0 :         result = dbentry->last_checksum_failure;
    1539             : 
    1540           0 :     if (result == 0)
    1541           0 :         PG_RETURN_NULL();
    1542             :     else
    1543           0 :         PG_RETURN_TIMESTAMPTZ(result);
    1544             : }
    1545             : 
    1546             : Datum
    1547           0 : pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS)
    1548             : {
    1549           0 :     Oid         dbid = PG_GETARG_OID(0);
    1550             :     double      result;
    1551             :     PgStat_StatDBEntry *dbentry;
    1552             : 
    1553             :     /* convert counter from microsec to millisec for display */
    1554           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1555           0 :         result = 0;
    1556             :     else
    1557           0 :         result = ((double) dbentry->n_block_read_time) / 1000.0;
    1558             : 
    1559           0 :     PG_RETURN_FLOAT8(result);
    1560             : }
    1561             : 
    1562             : Datum
    1563           0 : pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS)
    1564             : {
    1565           0 :     Oid         dbid = PG_GETARG_OID(0);
    1566             :     double      result;
    1567             :     PgStat_StatDBEntry *dbentry;
    1568             : 
    1569             :     /* convert counter from microsec to millisec for display */
    1570           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1571           0 :         result = 0;
    1572             :     else
    1573           0 :         result = ((double) dbentry->n_block_write_time) / 1000.0;
    1574             : 
    1575           0 :     PG_RETURN_FLOAT8(result);
    1576             : }
    1577             : 
    1578             : Datum
    1579           0 : pg_stat_get_db_session_time(PG_FUNCTION_ARGS)
    1580             : {
    1581           0 :     Oid         dbid = PG_GETARG_OID(0);
    1582           0 :     double      result = 0.0;
    1583             :     PgStat_StatDBEntry *dbentry;
    1584             : 
    1585             :     /* convert counter from microsec to millisec for display */
    1586           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1587           0 :         result = ((double) dbentry->total_session_time) / 1000.0;
    1588             : 
    1589           0 :     PG_RETURN_FLOAT8(result);
    1590             : }
    1591             : 
    1592             : Datum
    1593           0 : pg_stat_get_db_active_time(PG_FUNCTION_ARGS)
    1594             : {
    1595           0 :     Oid         dbid = PG_GETARG_OID(0);
    1596           0 :     double      result = 0.0;
    1597             :     PgStat_StatDBEntry *dbentry;
    1598             : 
    1599             :     /* convert counter from microsec to millisec for display */
    1600           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1601           0 :         result = ((double) dbentry->total_active_time) / 1000.0;
    1602             : 
    1603           0 :     PG_RETURN_FLOAT8(result);
    1604             : }
    1605             : 
    1606             : Datum
    1607           0 : pg_stat_get_db_idle_in_transaction_time(PG_FUNCTION_ARGS)
    1608             : {
    1609           0 :     Oid         dbid = PG_GETARG_OID(0);
    1610           0 :     double      result = 0.0;
    1611             :     PgStat_StatDBEntry *dbentry;
    1612             : 
    1613             :     /* convert counter from microsec to millisec for display */
    1614           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1615           0 :         result = ((double) dbentry->total_idle_in_xact_time) / 1000.0;
    1616             : 
    1617           0 :     PG_RETURN_FLOAT8(result);
    1618             : }
    1619             : 
    1620             : Datum
    1621          12 : pg_stat_get_db_sessions(PG_FUNCTION_ARGS)
    1622             : {
    1623          12 :     Oid         dbid = PG_GETARG_OID(0);
    1624          12 :     int64       result = 0;
    1625             :     PgStat_StatDBEntry *dbentry;
    1626             : 
    1627          12 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1628          12 :         result = (int64) (dbentry->n_sessions);
    1629             : 
    1630          12 :     PG_RETURN_INT64(result);
    1631             : }
    1632             : 
    1633             : Datum
    1634           0 : pg_stat_get_db_sessions_abandoned(PG_FUNCTION_ARGS)
    1635             : {
    1636           0 :     Oid         dbid = PG_GETARG_OID(0);
    1637           0 :     int64       result = 0;
    1638             :     PgStat_StatDBEntry *dbentry;
    1639             : 
    1640           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1641           0 :         result = (int64) (dbentry->n_sessions_abandoned);
    1642             : 
    1643           0 :     PG_RETURN_INT64(result);
    1644             : }
    1645             : 
    1646             : Datum
    1647           0 : pg_stat_get_db_sessions_fatal(PG_FUNCTION_ARGS)
    1648             : {
    1649           0 :     Oid         dbid = PG_GETARG_OID(0);
    1650           0 :     int64       result = 0;
    1651             :     PgStat_StatDBEntry *dbentry;
    1652             : 
    1653           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1654           0 :         result = (int64) (dbentry->n_sessions_fatal);
    1655             : 
    1656           0 :     PG_RETURN_INT64(result);
    1657             : }
    1658             : 
    1659             : Datum
    1660           0 : pg_stat_get_db_sessions_killed(PG_FUNCTION_ARGS)
    1661             : {
    1662           0 :     Oid         dbid = PG_GETARG_OID(0);
    1663           0 :     int64       result = 0;
    1664             :     PgStat_StatDBEntry *dbentry;
    1665             : 
    1666           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
    1667           0 :         result = (int64) (dbentry->n_sessions_killed);
    1668             : 
    1669           0 :     PG_RETURN_INT64(result);
    1670             : }
    1671             : 
    1672             : Datum
    1673           8 : pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
    1674             : {
    1675           8 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->timed_checkpoints);
    1676             : }
    1677             : 
    1678             : Datum
    1679          20 : pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
    1680             : {
    1681          20 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->requested_checkpoints);
    1682             : }
    1683             : 
    1684             : Datum
    1685           0 : pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
    1686             : {
    1687           0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_checkpoints);
    1688             : }
    1689             : 
    1690             : Datum
    1691           0 : pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
    1692             : {
    1693           0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_written_clean);
    1694             : }
    1695             : 
    1696             : Datum
    1697           0 : pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
    1698             : {
    1699           0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->maxwritten_clean);
    1700             : }
    1701             : 
    1702             : Datum
    1703           0 : pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS)
    1704             : {
    1705             :     /* time is already in msec, just convert to double for presentation */
    1706           0 :     PG_RETURN_FLOAT8((double)
    1707             :                      pgstat_fetch_stat_checkpointer()->checkpoint_write_time);
    1708             : }
    1709             : 
    1710             : Datum
    1711           0 : pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS)
    1712             : {
    1713             :     /* time is already in msec, just convert to double for presentation */
    1714           0 :     PG_RETURN_FLOAT8((double)
    1715             :                      pgstat_fetch_stat_checkpointer()->checkpoint_sync_time);
    1716             : }
    1717             : 
    1718             : Datum
    1719          32 : pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS)
    1720             : {
    1721          32 :     PG_RETURN_TIMESTAMPTZ(pgstat_fetch_stat_bgwriter()->stat_reset_timestamp);
    1722             : }
    1723             : 
    1724             : Datum
    1725           0 : pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
    1726             : {
    1727           0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_backend);
    1728             : }
    1729             : 
    1730             : Datum
    1731           0 : pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS)
    1732             : {
    1733           0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_fsync_backend);
    1734             : }
    1735             : 
    1736             : Datum
    1737           0 : pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
    1738             : {
    1739           0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_alloc);
    1740             : }
    1741             : 
    1742             : /*
    1743             :  * Returns statistics of WAL activity
    1744             :  */
    1745             : Datum
    1746          84 : pg_stat_get_wal(PG_FUNCTION_ARGS)
    1747             : {
    1748             : #define PG_STAT_GET_WAL_COLS    9
    1749             :     TupleDesc   tupdesc;
    1750             :     Datum       values[PG_STAT_GET_WAL_COLS];
    1751             :     bool        nulls[PG_STAT_GET_WAL_COLS];
    1752             :     char        buf[256];
    1753             :     PgStat_WalStats *wal_stats;
    1754             : 
    1755             :     /* Initialise values and NULL flags arrays */
    1756         840 :     MemSet(values, 0, sizeof(values));
    1757          84 :     MemSet(nulls, 0, sizeof(nulls));
    1758             : 
    1759             :     /* Initialise attributes information in the tuple descriptor */
    1760          84 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_WAL_COLS);
    1761          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "wal_records",
    1762             :                        INT8OID, -1, 0);
    1763          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "wal_fpi",
    1764             :                        INT8OID, -1, 0);
    1765          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "wal_bytes",
    1766             :                        NUMERICOID, -1, 0);
    1767          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_buffers_full",
    1768             :                        INT8OID, -1, 0);
    1769          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "wal_write",
    1770             :                        INT8OID, -1, 0);
    1771          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "wal_sync",
    1772             :                        INT8OID, -1, 0);
    1773          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "wal_write_time",
    1774             :                        FLOAT8OID, -1, 0);
    1775          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 8, "wal_sync_time",
    1776             :                        FLOAT8OID, -1, 0);
    1777          84 :     TupleDescInitEntry(tupdesc, (AttrNumber) 9, "stats_reset",
    1778             :                        TIMESTAMPTZOID, -1, 0);
    1779             : 
    1780          84 :     BlessTupleDesc(tupdesc);
    1781             : 
    1782             :     /* Get statistics about WAL activity */
    1783          84 :     wal_stats = pgstat_fetch_stat_wal();
    1784             : 
    1785             :     /* Fill values and NULLs */
    1786          84 :     values[0] = Int64GetDatum(wal_stats->wal_records);
    1787          84 :     values[1] = Int64GetDatum(wal_stats->wal_fpi);
    1788             : 
    1789             :     /* Convert to numeric. */
    1790          84 :     snprintf(buf, sizeof buf, UINT64_FORMAT, wal_stats->wal_bytes);
    1791          84 :     values[2] = DirectFunctionCall3(numeric_in,
    1792             :                                     CStringGetDatum(buf),
    1793             :                                     ObjectIdGetDatum(0),
    1794             :                                     Int32GetDatum(-1));
    1795             : 
    1796          84 :     values[3] = Int64GetDatum(wal_stats->wal_buffers_full);
    1797          84 :     values[4] = Int64GetDatum(wal_stats->wal_write);
    1798          84 :     values[5] = Int64GetDatum(wal_stats->wal_sync);
    1799             : 
    1800             :     /* Convert counters from microsec to millisec for display */
    1801          84 :     values[6] = Float8GetDatum(((double) wal_stats->wal_write_time) / 1000.0);
    1802          84 :     values[7] = Float8GetDatum(((double) wal_stats->wal_sync_time) / 1000.0);
    1803             : 
    1804          84 :     values[8] = TimestampTzGetDatum(wal_stats->stat_reset_timestamp);
    1805             : 
    1806             :     /* Returns the record as Datum */
    1807          84 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    1808             : }
    1809             : 
    1810             : /*
    1811             :  * Returns statistics of SLRU caches.
    1812             :  */
    1813             : Datum
    1814         112 : pg_stat_get_slru(PG_FUNCTION_ARGS)
    1815             : {
    1816             : #define PG_STAT_GET_SLRU_COLS   9
    1817         112 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
    1818             :     int         i;
    1819             :     PgStat_SLRUStats *stats;
    1820             : 
    1821         112 :     SetSingleFuncCall(fcinfo, 0);
    1822             : 
    1823             :     /* request SLRU stats from the cumulative stats system */
    1824         112 :     stats = pgstat_fetch_slru();
    1825             : 
    1826         112 :     for (i = 0;; i++)
    1827         896 :     {
    1828             :         /* for each row */
    1829             :         Datum       values[PG_STAT_GET_SLRU_COLS];
    1830             :         bool        nulls[PG_STAT_GET_SLRU_COLS];
    1831             :         PgStat_SLRUStats stat;
    1832             :         const char *name;
    1833             : 
    1834        1008 :         name = pgstat_get_slru_name(i);
    1835             : 
    1836        1008 :         if (!name)
    1837         112 :             break;
    1838             : 
    1839         896 :         stat = stats[i];
    1840        8960 :         MemSet(values, 0, sizeof(values));
    1841         896 :         MemSet(nulls, 0, sizeof(nulls));
    1842             : 
    1843         896 :         values[0] = PointerGetDatum(cstring_to_text(name));
    1844         896 :         values[1] = Int64GetDatum(stat.blocks_zeroed);
    1845         896 :         values[2] = Int64GetDatum(stat.blocks_hit);
    1846         896 :         values[3] = Int64GetDatum(stat.blocks_read);
    1847         896 :         values[4] = Int64GetDatum(stat.blocks_written);
    1848         896 :         values[5] = Int64GetDatum(stat.blocks_exists);
    1849         896 :         values[6] = Int64GetDatum(stat.flush);
    1850         896 :         values[7] = Int64GetDatum(stat.truncate);
    1851         896 :         values[8] = TimestampTzGetDatum(stat.stat_reset_timestamp);
    1852             : 
    1853         896 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
    1854             :     }
    1855             : 
    1856         112 :     return (Datum) 0;
    1857             : }
    1858             : 
    1859             : Datum
    1860           0 : pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
    1861             : {
    1862           0 :     Oid         relid = PG_GETARG_OID(0);
    1863             :     int64       result;
    1864             :     PgStat_TableStatus *tabentry;
    1865             : 
    1866           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1867           0 :         result = 0;
    1868             :     else
    1869           0 :         result = (int64) (tabentry->t_counts.t_numscans);
    1870             : 
    1871           0 :     PG_RETURN_INT64(result);
    1872             : }
    1873             : 
    1874             : Datum
    1875           0 : pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
    1876             : {
    1877           0 :     Oid         relid = PG_GETARG_OID(0);
    1878             :     int64       result;
    1879             :     PgStat_TableStatus *tabentry;
    1880             : 
    1881           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1882           0 :         result = 0;
    1883             :     else
    1884           0 :         result = (int64) (tabentry->t_counts.t_tuples_returned);
    1885             : 
    1886           0 :     PG_RETURN_INT64(result);
    1887             : }
    1888             : 
    1889             : Datum
    1890           0 : pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
    1891             : {
    1892           0 :     Oid         relid = PG_GETARG_OID(0);
    1893             :     int64       result;
    1894             :     PgStat_TableStatus *tabentry;
    1895             : 
    1896           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1897           0 :         result = 0;
    1898             :     else
    1899           0 :         result = (int64) (tabentry->t_counts.t_tuples_fetched);
    1900             : 
    1901           0 :     PG_RETURN_INT64(result);
    1902             : }
    1903             : 
    1904             : Datum
    1905          48 : pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
    1906             : {
    1907          48 :     Oid         relid = PG_GETARG_OID(0);
    1908             :     int64       result;
    1909             :     PgStat_TableStatus *tabentry;
    1910             :     PgStat_TableXactStatus *trans;
    1911             : 
    1912          48 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1913          12 :         result = 0;
    1914             :     else
    1915             :     {
    1916          36 :         result = tabentry->t_counts.t_tuples_inserted;
    1917             :         /* live subtransactions' counts aren't in t_tuples_inserted yet */
    1918          84 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1919          48 :             result += trans->tuples_inserted;
    1920             :     }
    1921             : 
    1922          48 :     PG_RETURN_INT64(result);
    1923             : }
    1924             : 
    1925             : Datum
    1926           0 : pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
    1927             : {
    1928           0 :     Oid         relid = PG_GETARG_OID(0);
    1929             :     int64       result;
    1930             :     PgStat_TableStatus *tabentry;
    1931             :     PgStat_TableXactStatus *trans;
    1932             : 
    1933           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1934           0 :         result = 0;
    1935             :     else
    1936             :     {
    1937           0 :         result = tabentry->t_counts.t_tuples_updated;
    1938             :         /* live subtransactions' counts aren't in t_tuples_updated yet */
    1939           0 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1940           0 :             result += trans->tuples_updated;
    1941             :     }
    1942             : 
    1943           0 :     PG_RETURN_INT64(result);
    1944             : }
    1945             : 
    1946             : Datum
    1947           0 : pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
    1948             : {
    1949           0 :     Oid         relid = PG_GETARG_OID(0);
    1950             :     int64       result;
    1951             :     PgStat_TableStatus *tabentry;
    1952             :     PgStat_TableXactStatus *trans;
    1953             : 
    1954           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1955           0 :         result = 0;
    1956             :     else
    1957             :     {
    1958           0 :         result = tabentry->t_counts.t_tuples_deleted;
    1959             :         /* live subtransactions' counts aren't in t_tuples_deleted yet */
    1960           0 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1961           0 :             result += trans->tuples_deleted;
    1962             :     }
    1963             : 
    1964           0 :     PG_RETURN_INT64(result);
    1965             : }
    1966             : 
    1967             : Datum
    1968           0 : pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
    1969             : {
    1970           0 :     Oid         relid = PG_GETARG_OID(0);
    1971             :     int64       result;
    1972             :     PgStat_TableStatus *tabentry;
    1973             : 
    1974           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1975           0 :         result = 0;
    1976             :     else
    1977           0 :         result = (int64) (tabentry->t_counts.t_tuples_hot_updated);
    1978             : 
    1979           0 :     PG_RETURN_INT64(result);
    1980             : }
    1981             : 
    1982             : Datum
    1983           0 : pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
    1984             : {
    1985           0 :     Oid         relid = PG_GETARG_OID(0);
    1986             :     int64       result;
    1987             :     PgStat_TableStatus *tabentry;
    1988             : 
    1989           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1990           0 :         result = 0;
    1991             :     else
    1992           0 :         result = (int64) (tabentry->t_counts.t_blocks_fetched);
    1993             : 
    1994           0 :     PG_RETURN_INT64(result);
    1995             : }
    1996             : 
    1997             : Datum
    1998           0 : pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
    1999             : {
    2000           0 :     Oid         relid = PG_GETARG_OID(0);
    2001             :     int64       result;
    2002             :     PgStat_TableStatus *tabentry;
    2003             : 
    2004           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    2005           0 :         result = 0;
    2006             :     else
    2007           0 :         result = (int64) (tabentry->t_counts.t_blocks_hit);
    2008             : 
    2009           0 :     PG_RETURN_INT64(result);
    2010             : }
    2011             : 
    2012             : Datum
    2013          24 : pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
    2014             : {
    2015          24 :     Oid         funcid = PG_GETARG_OID(0);
    2016             :     PgStat_BackendFunctionEntry *funcentry;
    2017             : 
    2018          24 :     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
    2019           6 :         PG_RETURN_NULL();
    2020          18 :     PG_RETURN_INT64(funcentry->f_counts.f_numcalls);
    2021             : }
    2022             : 
    2023             : Datum
    2024           0 : pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS)
    2025             : {
    2026           0 :     Oid         funcid = PG_GETARG_OID(0);
    2027             :     PgStat_BackendFunctionEntry *funcentry;
    2028             : 
    2029           0 :     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
    2030           0 :         PG_RETURN_NULL();
    2031           0 :     PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time));
    2032             : }
    2033             : 
    2034             : Datum
    2035           0 : pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS)
    2036             : {
    2037           0 :     Oid         funcid = PG_GETARG_OID(0);
    2038             :     PgStat_BackendFunctionEntry *funcentry;
    2039             : 
    2040           0 :     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
    2041           0 :         PG_RETURN_NULL();
    2042           0 :     PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time));
    2043             : }
    2044             : 
    2045             : 
    2046             : /* Get the timestamp of the current statistics snapshot */
    2047             : Datum
    2048          30 : pg_stat_get_snapshot_timestamp(PG_FUNCTION_ARGS)
    2049             : {
    2050             :     bool        have_snapshot;
    2051             :     TimestampTz ts;
    2052             : 
    2053          30 :     ts = pgstat_get_stat_snapshot_timestamp(&have_snapshot);
    2054             : 
    2055          30 :     if (!have_snapshot)
    2056          12 :         PG_RETURN_NULL();
    2057             : 
    2058          18 :     PG_RETURN_TIMESTAMPTZ(ts);
    2059             : }
    2060             : 
    2061             : /* Discard the active statistics snapshot */
    2062             : Datum
    2063          14 : pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
    2064             : {
    2065          14 :     pgstat_clear_snapshot();
    2066             : 
    2067          14 :     PG_RETURN_VOID();
    2068             : }
    2069             : 
    2070             : 
    2071             : /* Force statistics to be reported at the next occasion */
    2072             : Datum
    2073         328 : pg_stat_force_next_flush(PG_FUNCTION_ARGS)
    2074             : {
    2075         328 :     pgstat_force_next_flush();
    2076             : 
    2077         328 :     PG_RETURN_VOID();
    2078             : }
    2079             : 
    2080             : 
    2081             : /* Reset all counters for the current database */
    2082             : Datum
    2083          14 : pg_stat_reset(PG_FUNCTION_ARGS)
    2084             : {
    2085          14 :     pgstat_reset_counters();
    2086             : 
    2087          14 :     PG_RETURN_VOID();
    2088             : }
    2089             : 
    2090             : /* Reset some shared cluster-wide counters */
    2091             : Datum
    2092          24 : pg_stat_reset_shared(PG_FUNCTION_ARGS)
    2093             : {
    2094          24 :     char       *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    2095             : 
    2096          24 :     if (strcmp(target, "archiver") == 0)
    2097           8 :         pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER);
    2098          16 :     else if (strcmp(target, "bgwriter") == 0)
    2099             :     {
    2100             :         /*
    2101             :          * Historically checkpointer was part of bgwriter, continue to reset
    2102             :          * both for now.
    2103             :          */
    2104           8 :         pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER);
    2105           8 :         pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER);
    2106             :     }
    2107           8 :     else if (strcmp(target, "recovery_prefetch") == 0)
    2108           0 :         XLogPrefetchResetStats();
    2109           8 :     else if (strcmp(target, "wal") == 0)
    2110           8 :         pgstat_reset_of_kind(PGSTAT_KIND_WAL);
    2111             :     else
    2112           0 :         ereport(ERROR,
    2113             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2114             :                  errmsg("unrecognized reset target: \"%s\"", target),
    2115             :                  errhint("Target must be \"archiver\", \"bgwriter\", \"recovery_prefetch\", or \"wal\".")));
    2116             : 
    2117          24 :     PG_RETURN_VOID();
    2118             : }
    2119             : 
    2120             : /* Reset a single counter in the current database */
    2121             : Datum
    2122           0 : pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
    2123             : {
    2124           0 :     Oid         taboid = PG_GETARG_OID(0);
    2125             : 
    2126           0 :     pgstat_reset(PGSTAT_KIND_RELATION, MyDatabaseId, taboid);
    2127             : 
    2128           0 :     PG_RETURN_VOID();
    2129             : }
    2130             : 
    2131             : Datum
    2132           4 : pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
    2133             : {
    2134           4 :     Oid         funcoid = PG_GETARG_OID(0);
    2135             : 
    2136           4 :     pgstat_reset(PGSTAT_KIND_FUNCTION, MyDatabaseId, funcoid);
    2137             : 
    2138           4 :     PG_RETURN_VOID();
    2139             : }
    2140             : 
    2141             : /* Reset SLRU counters (a specific one or all of them). */
    2142             : Datum
    2143          12 : pg_stat_reset_slru(PG_FUNCTION_ARGS)
    2144             : {
    2145          12 :     char       *target = NULL;
    2146             : 
    2147          12 :     if (PG_ARGISNULL(0))
    2148           6 :         pgstat_reset_of_kind(PGSTAT_KIND_SLRU);
    2149             :     else
    2150             :     {
    2151           6 :         target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    2152           6 :         pgstat_reset_slru(target);
    2153             :     }
    2154             : 
    2155          12 :     PG_RETURN_VOID();
    2156             : }
    2157             : 
    2158             : /* Reset replication slots stats (a specific one or all of them). */
    2159             : Datum
    2160          12 : pg_stat_reset_replication_slot(PG_FUNCTION_ARGS)
    2161             : {
    2162          12 :     char       *target = NULL;
    2163             : 
    2164          12 :     if (PG_ARGISNULL(0))
    2165           4 :         pgstat_reset_of_kind(PGSTAT_KIND_REPLSLOT);
    2166             :     else
    2167             :     {
    2168           8 :         target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    2169           8 :         pgstat_reset_replslot(target);
    2170             :     }
    2171             : 
    2172          10 :     PG_RETURN_VOID();
    2173             : }
    2174             : 
    2175             : /* Reset subscription stats (a specific one or all of them) */
    2176             : Datum
    2177           8 : pg_stat_reset_subscription_stats(PG_FUNCTION_ARGS)
    2178             : {
    2179             :     Oid         subid;
    2180             : 
    2181           8 :     if (PG_ARGISNULL(0))
    2182             :     {
    2183             :         /* Clear all subscription stats */
    2184           4 :         pgstat_reset_of_kind(PGSTAT_KIND_SUBSCRIPTION);
    2185             :     }
    2186             :     else
    2187             :     {
    2188           4 :         subid = PG_GETARG_OID(0);
    2189             : 
    2190           4 :         if (!OidIsValid(subid))
    2191           0 :             ereport(ERROR,
    2192             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    2193             :                      errmsg("invalid subscription OID %u", subid)));
    2194           4 :         pgstat_reset(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid);
    2195             :     }
    2196             : 
    2197           8 :     PG_RETURN_VOID();
    2198             : }
    2199             : 
    2200             : Datum
    2201          46 : pg_stat_get_archiver(PG_FUNCTION_ARGS)
    2202             : {
    2203             :     TupleDesc   tupdesc;
    2204             :     Datum       values[7];
    2205             :     bool        nulls[7];
    2206             :     PgStat_ArchiverStats *archiver_stats;
    2207             : 
    2208             :     /* Initialise values and NULL flags arrays */
    2209         368 :     MemSet(values, 0, sizeof(values));
    2210          46 :     MemSet(nulls, 0, sizeof(nulls));
    2211             : 
    2212             :     /* Initialise attributes information in the tuple descriptor */
    2213          46 :     tupdesc = CreateTemplateTupleDesc(7);
    2214          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_count",
    2215             :                        INT8OID, -1, 0);
    2216          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal",
    2217             :                        TEXTOID, -1, 0);
    2218          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_time",
    2219             :                        TIMESTAMPTZOID, -1, 0);
    2220          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_count",
    2221             :                        INT8OID, -1, 0);
    2222          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal",
    2223             :                        TEXTOID, -1, 0);
    2224          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_time",
    2225             :                        TIMESTAMPTZOID, -1, 0);
    2226          46 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset",
    2227             :                        TIMESTAMPTZOID, -1, 0);
    2228             : 
    2229          46 :     BlessTupleDesc(tupdesc);
    2230             : 
    2231             :     /* Get statistics about the archiver process */
    2232          46 :     archiver_stats = pgstat_fetch_stat_archiver();
    2233             : 
    2234             :     /* Fill values and NULLs */
    2235          46 :     values[0] = Int64GetDatum(archiver_stats->archived_count);
    2236          46 :     if (*(archiver_stats->last_archived_wal) == '\0')
    2237          30 :         nulls[1] = true;
    2238             :     else
    2239          16 :         values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal);
    2240             : 
    2241          46 :     if (archiver_stats->last_archived_timestamp == 0)
    2242          30 :         nulls[2] = true;
    2243             :     else
    2244          16 :         values[2] = TimestampTzGetDatum(archiver_stats->last_archived_timestamp);
    2245             : 
    2246          46 :     values[3] = Int64GetDatum(archiver_stats->failed_count);
    2247          46 :     if (*(archiver_stats->last_failed_wal) == '\0')
    2248          30 :         nulls[4] = true;
    2249             :     else
    2250          16 :         values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal);
    2251             : 
    2252          46 :     if (archiver_stats->last_failed_timestamp == 0)
    2253          30 :         nulls[5] = true;
    2254             :     else
    2255          16 :         values[5] = TimestampTzGetDatum(archiver_stats->last_failed_timestamp);
    2256             : 
    2257          46 :     if (archiver_stats->stat_reset_timestamp == 0)
    2258           0 :         nulls[6] = true;
    2259             :     else
    2260          46 :         values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp);
    2261             : 
    2262             :     /* Returns the record as Datum */
    2263          46 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    2264             : }
    2265             : 
    2266             : /*
    2267             :  * Get the statistics for the replication slot. If the slot statistics is not
    2268             :  * available, return all-zeroes stats.
    2269             :  */
    2270             : Datum
    2271          86 : pg_stat_get_replication_slot(PG_FUNCTION_ARGS)
    2272             : {
    2273             : #define PG_STAT_GET_REPLICATION_SLOT_COLS 10
    2274          86 :     text       *slotname_text = PG_GETARG_TEXT_P(0);
    2275             :     NameData    slotname;
    2276             :     TupleDesc   tupdesc;
    2277             :     Datum       values[PG_STAT_GET_REPLICATION_SLOT_COLS];
    2278             :     bool        nulls[PG_STAT_GET_REPLICATION_SLOT_COLS];
    2279             :     PgStat_StatReplSlotEntry *slotent;
    2280             :     PgStat_StatReplSlotEntry allzero;
    2281             : 
    2282             :     /* Initialise values and NULL flags arrays */
    2283         946 :     MemSet(values, 0, sizeof(values));
    2284          86 :     MemSet(nulls, 0, sizeof(nulls));
    2285             : 
    2286             :     /* Initialise attributes information in the tuple descriptor */
    2287          86 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_REPLICATION_SLOT_COLS);
    2288          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "slot_name",
    2289             :                        TEXTOID, -1, 0);
    2290          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "spill_txns",
    2291             :                        INT8OID, -1, 0);
    2292          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "spill_count",
    2293             :                        INT8OID, -1, 0);
    2294          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "spill_bytes",
    2295             :                        INT8OID, -1, 0);
    2296          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "stream_txns",
    2297             :                        INT8OID, -1, 0);
    2298          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "stream_count",
    2299             :                        INT8OID, -1, 0);
    2300          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stream_bytes",
    2301             :                        INT8OID, -1, 0);
    2302          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_txns",
    2303             :                        INT8OID, -1, 0);
    2304          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_bytes",
    2305             :                        INT8OID, -1, 0);
    2306          86 :     TupleDescInitEntry(tupdesc, (AttrNumber) 10, "stats_reset",
    2307             :                        TIMESTAMPTZOID, -1, 0);
    2308          86 :     BlessTupleDesc(tupdesc);
    2309             : 
    2310          86 :     namestrcpy(&slotname, text_to_cstring(slotname_text));
    2311          86 :     slotent = pgstat_fetch_replslot(slotname);
    2312          86 :     if (!slotent)
    2313             :     {
    2314             :         /*
    2315             :          * If the slot is not found, initialise its stats. This is possible if
    2316             :          * the create slot message is lost.
    2317             :          */
    2318           4 :         memset(&allzero, 0, sizeof(PgStat_StatReplSlotEntry));
    2319           4 :         slotent = &allzero;
    2320             :     }
    2321             : 
    2322          86 :     values[0] = CStringGetTextDatum(NameStr(slotname));
    2323          86 :     values[1] = Int64GetDatum(slotent->spill_txns);
    2324          86 :     values[2] = Int64GetDatum(slotent->spill_count);
    2325          86 :     values[3] = Int64GetDatum(slotent->spill_bytes);
    2326          86 :     values[4] = Int64GetDatum(slotent->stream_txns);
    2327          86 :     values[5] = Int64GetDatum(slotent->stream_count);
    2328          86 :     values[6] = Int64GetDatum(slotent->stream_bytes);
    2329          86 :     values[7] = Int64GetDatum(slotent->total_txns);
    2330          86 :     values[8] = Int64GetDatum(slotent->total_bytes);
    2331             : 
    2332          86 :     if (slotent->stat_reset_timestamp == 0)
    2333          50 :         nulls[9] = true;
    2334             :     else
    2335          36 :         values[9] = TimestampTzGetDatum(slotent->stat_reset_timestamp);
    2336             : 
    2337             :     /* Returns the record as Datum */
    2338          86 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    2339             : }
    2340             : 
    2341             : /*
    2342             :  * Get the subscription statistics for the given subscription. If the
    2343             :  * subscription statistics is not available, return all-zeros stats.
    2344             :  */
    2345             : Datum
    2346          34 : pg_stat_get_subscription_stats(PG_FUNCTION_ARGS)
    2347             : {
    2348             : #define PG_STAT_GET_SUBSCRIPTION_STATS_COLS 4
    2349          34 :     Oid         subid = PG_GETARG_OID(0);
    2350             :     TupleDesc   tupdesc;
    2351             :     Datum       values[PG_STAT_GET_SUBSCRIPTION_STATS_COLS];
    2352             :     bool        nulls[PG_STAT_GET_SUBSCRIPTION_STATS_COLS];
    2353             :     PgStat_StatSubEntry *subentry;
    2354             :     PgStat_StatSubEntry allzero;
    2355             : 
    2356             :     /* Get subscription stats */
    2357          34 :     subentry = pgstat_fetch_stat_subscription(subid);
    2358             : 
    2359             :     /* Initialise attributes information in the tuple descriptor */
    2360          34 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_SUBSCRIPTION_STATS_COLS);
    2361          34 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "subid",
    2362             :                        OIDOID, -1, 0);
    2363          34 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "apply_error_count",
    2364             :                        INT8OID, -1, 0);
    2365          34 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "sync_error_count",
    2366             :                        INT8OID, -1, 0);
    2367          34 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "stats_reset",
    2368             :                        TIMESTAMPTZOID, -1, 0);
    2369          34 :     BlessTupleDesc(tupdesc);
    2370             : 
    2371             :     /* Initialise values and NULL flags arrays */
    2372         170 :     MemSet(values, 0, sizeof(values));
    2373          34 :     MemSet(nulls, 0, sizeof(nulls));
    2374             : 
    2375          34 :     if (!subentry)
    2376             :     {
    2377             :         /* If the subscription is not found, initialise its stats */
    2378           0 :         memset(&allzero, 0, sizeof(PgStat_StatSubEntry));
    2379           0 :         subentry = &allzero;
    2380             :     }
    2381             : 
    2382             :     /* subid */
    2383          34 :     values[0] = ObjectIdGetDatum(subid);
    2384             : 
    2385             :     /* apply_error_count */
    2386          34 :     values[1] = Int64GetDatum(subentry->apply_error_count);
    2387             : 
    2388             :     /* sync_error_count */
    2389          34 :     values[2] = Int64GetDatum(subentry->sync_error_count);
    2390             : 
    2391             :     /* stats_reset */
    2392          34 :     if (subentry->stat_reset_timestamp == 0)
    2393          14 :         nulls[3] = true;
    2394             :     else
    2395          20 :         values[3] = TimestampTzGetDatum(subentry->stat_reset_timestamp);
    2396             : 
    2397             :     /* Returns the record as Datum */
    2398          34 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    2399             : }
    2400             : 
    2401             : /*
    2402             :  * Checks for presence of stats for object with provided kind, database oid,
    2403             :  * object oid.
    2404             :  *
    2405             :  * This is useful for tests, but not really anything else. Therefore not
    2406             :  * documented.
    2407             :  */
    2408             : Datum
    2409         102 : pg_stat_have_stats(PG_FUNCTION_ARGS)
    2410             : {
    2411         102 :     char       *stats_type = text_to_cstring(PG_GETARG_TEXT_P(0));
    2412         102 :     Oid         dboid = PG_GETARG_OID(1);
    2413         102 :     Oid         objoid = PG_GETARG_OID(2);
    2414         102 :     PgStat_Kind kind = pgstat_get_kind_from_str(stats_type);
    2415             : 
    2416          96 :     PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
    2417             : }

Generated by: LCOV version 1.14