LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - pgstatfuncs.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 66.0 % 802 529 62 39 126 46 57 282 120 70 110 148 60 272
Current Date: 2023-04-08 15:15:32 Functions: 47.5 % 118 56 39 23 29 27 38 29 24 27
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * pgstatfuncs.c
       4                 :  *    Functions for accessing various forms of statistics data
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, 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 "replication/logicallauncher.h"
      29                 : #include "storage/proc.h"
      30                 : #include "storage/procarray.h"
      31                 : #include "utils/acl.h"
      32                 : #include "utils/builtins.h"
      33                 : #include "utils/inet.h"
      34                 : #include "utils/timestamp.h"
      35                 : 
      36                 : #define UINT32_ACCESS_ONCE(var)      ((uint32)(*((volatile uint32 *)&(var))))
      37                 : 
      38                 : #define HAS_PGSTAT_PERMISSIONS(role)     (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
      39                 : 
      40                 : #define PG_STAT_GET_RELENTRY_INT64(stat)                        \
      41                 : Datum                                                           \
      42                 : CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)                  \
      43                 : {                                                               \
      44                 :     Oid         relid = PG_GETARG_OID(0);                       \
      45                 :     int64       result;                                         \
      46                 :     PgStat_StatTabEntry *tabentry;                              \
      47                 :                                                                 \
      48                 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
      49                 :         result = 0;                                             \
      50                 :     else                                                        \
      51                 :         result = (int64) (tabentry->stat);                       \
      52                 :                                                                 \
      53                 :     PG_RETURN_INT64(result);                                    \
      54                 : }
      55                 : 
      56                 : /* pg_stat_get_analyze_count */
      57 UNC           0 : PG_STAT_GET_RELENTRY_INT64(analyze_count)
      58                 : 
      59                 : /* pg_stat_get_autoanalyze_count */
      60               0 : PG_STAT_GET_RELENTRY_INT64(autoanalyze_count)
      61                 : 
      62                 : /* pg_stat_get_autovacuum_count */
      63               0 : PG_STAT_GET_RELENTRY_INT64(autovacuum_count)
      64 ECB             : 
      65                 : /* pg_stat_get_blocks_fetched */
      66 GNC          24 : PG_STAT_GET_RELENTRY_INT64(blocks_fetched)
      67                 : 
      68                 : /* pg_stat_get_blocks_hit */
      69              48 : PG_STAT_GET_RELENTRY_INT64(blocks_hit)
      70                 : 
      71                 : /* pg_stat_get_dead_tuples */
      72              34 : PG_STAT_GET_RELENTRY_INT64(dead_tuples)
      73                 : 
      74                 : /* pg_stat_get_ins_since_vacuum */
      75 UNC           0 : PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum)
      76                 : 
      77                 : /* pg_stat_get_live_tuples */
      78 GNC          70 : PG_STAT_GET_RELENTRY_INT64(live_tuples)
      79                 : 
      80                 : /* pg_stat_get_mods_since_analyze */
      81 UNC           0 : PG_STAT_GET_RELENTRY_INT64(mod_since_analyze)
      82                 : 
      83                 : /* pg_stat_get_numscans */
      84 GNC          82 : PG_STAT_GET_RELENTRY_INT64(numscans)
      85                 : 
      86                 : /* pg_stat_get_tuples_deleted */
      87              34 : PG_STAT_GET_RELENTRY_INT64(tuples_deleted)
      88                 : 
      89                 : /* pg_stat_get_tuples_fetched */
      90              24 : PG_STAT_GET_RELENTRY_INT64(tuples_fetched)
      91                 : 
      92                 : /* pg_stat_get_tuples_hot_updated */
      93               6 : PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated)
      94                 : 
      95                 : /* pg_stat_get_tuples_newpage_updated */
      96 UNC           0 : PG_STAT_GET_RELENTRY_INT64(tuples_newpage_updated)
      97                 : 
      98                 : /* pg_stat_get_tuples_inserted */
      99 GNC          46 : PG_STAT_GET_RELENTRY_INT64(tuples_inserted)
     100                 : 
     101                 : /* pg_stat_get_tuples_returned */
     102              25 : PG_STAT_GET_RELENTRY_INT64(tuples_returned)
     103                 : 
     104                 : /* pg_stat_get_tuples_updated */
     105              34 : PG_STAT_GET_RELENTRY_INT64(tuples_updated)
     106                 : 
     107                 : /* pg_stat_get_vacuum_count */
     108            3779 : PG_STAT_GET_RELENTRY_INT64(vacuum_count)
     109                 : 
     110                 : #define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat)                  \
     111                 : Datum                                                           \
     112                 : CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)                  \
     113                 : {                                                               \
     114                 :     Oid         relid = PG_GETARG_OID(0);                       \
     115                 :     TimestampTz result;                                         \
     116                 :     PgStat_StatTabEntry *tabentry;                              \
     117                 :                                                                 \
     118                 :     if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
     119                 :         result = 0;                                             \
     120                 :     else                                                        \
     121                 :         result = tabentry->stat;                             \
     122                 :                                                                 \
     123                 :     if (result == 0)                                            \
     124                 :         PG_RETURN_NULL();                                       \
     125                 :     else                                                        \
     126                 :         PG_RETURN_TIMESTAMPTZ(result);                          \
     127                 : }
     128 ECB             : 
     129                 : /* pg_stat_get_last_analyze_time */
     130 UNC           0 : PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time)
     131                 : 
     132                 : /* pg_stat_get_last_autoanalyze_time */
     133               0 : PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time)
     134                 : 
     135                 : /* pg_stat_get_last_autovacuum_time */
     136               0 : PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time)
     137                 : 
     138                 : /* pg_stat_get_last_vacuum_time */
     139               0 : PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time)
     140                 : 
     141                 : /* pg_stat_get_lastscan */
     142 GNC          42 : PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan)
     143 ECB             : 
     144                 : Datum
     145 GBC         130 : pg_stat_get_function_calls(PG_FUNCTION_ARGS)
     146 EUB             : {
     147 GBC         130 :     Oid         funcid = PG_GETARG_OID(0);
     148 EUB             :     PgStat_StatFuncEntry *funcentry;
     149                 : 
     150 GBC         130 :     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)
     151              53 :         PG_RETURN_NULL();
     152 GNC          77 :     PG_RETURN_INT64(funcentry->numcalls);
     153 EUB             : }
     154 ECB             : 
     155                 : /* convert counter from microsec to millisec for display */
     156                 : #define PG_STAT_GET_FUNCENTRY_FLOAT8_MS(stat)                       \
     157                 : Datum                                                               \
     158                 : CppConcat(pg_stat_get_function_,stat)(PG_FUNCTION_ARGS)             \
     159                 : {                                                                   \
     160                 :     Oid         funcid = PG_GETARG_OID(0);                          \
     161                 :     double      result;                                             \
     162                 :     PgStat_StatFuncEntry *funcentry;                                \
     163                 :                                                                     \
     164                 :     if ((funcentry = pgstat_fetch_stat_funcentry(funcid)) == NULL)  \
     165                 :         PG_RETURN_NULL();                                           \
     166                 :     result = ((double) funcentry->stat) / 1000.0;                    \
     167                 :     PG_RETURN_FLOAT8(result);                                       \
     168                 : }
     169                 : 
     170                 : /* pg_stat_get_function_total_time */
     171 GNC          77 : PG_STAT_GET_FUNCENTRY_FLOAT8_MS(total_time)
     172                 : 
     173                 : /* pg_stat_get_function_self_time */
     174              77 : PG_STAT_GET_FUNCENTRY_FLOAT8_MS(self_time)
     175                 : 
     176                 : Datum
     177 GIC          38 : pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
     178                 : {
     179                 :     FuncCallContext *funcctx;
     180 ECB             :     int        *fctx;
     181                 : 
     182                 :     /* stuff done only on the first call of the function */
     183 GIC          38 :     if (SRF_IS_FIRSTCALL())
     184 ECB             :     {
     185                 :         /* create a function context for cross-call persistence */
     186 CBC           3 :         funcctx = SRF_FIRSTCALL_INIT();
     187                 : 
     188               3 :         fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
     189                 :                                   sizeof(int));
     190 GIC           3 :         funcctx->user_fctx = fctx;
     191                 : 
     192               3 :         fctx[0] = 0;
     193                 :     }
     194 ECB             : 
     195                 :     /* stuff done on every call of the function */
     196 GBC          38 :     funcctx = SRF_PERCALL_SETUP();
     197              38 :     fctx = funcctx->user_fctx;
     198                 : 
     199 CBC          38 :     fctx[0] += 1;
     200 ECB             : 
     201                 :     /*
     202                 :      * We recheck pgstat_fetch_stat_numbackends() each time through, just in
     203                 :      * case the local status data has been refreshed since we started.  It's
     204                 :      * plenty cheap enough if not.  If a refresh does happen, we'll likely
     205                 :      * miss or duplicate some backend IDs, but we're content not to crash.
     206                 :      * (Refreshing midway through such a query would be problematic usage
     207                 :      * anyway, since the backend IDs we've already returned might no longer
     208                 :      * refer to extant sessions.)
     209                 :      */
     210 GNC          38 :     if (fctx[0] <= pgstat_fetch_stat_numbackends())
     211 ECB             :     {
     212                 :         /* do when there is more left to send */
     213 GNC          35 :         LocalPgBackendStatus *local_beentry = pgstat_fetch_stat_local_beentry(fctx[0]);
     214                 : 
     215              35 :         SRF_RETURN_NEXT(funcctx, Int32GetDatum(local_beentry->backend_id));
     216 EUB             :     }
     217                 :     else
     218                 :     {
     219                 :         /* do when there is no more left */
     220 GIC           3 :         SRF_RETURN_DONE(funcctx);
     221 ECB             :     }
     222                 : }
     223                 : 
     224                 : /*
     225                 :  * Returns command progress information for the named command.
     226                 :  */
     227                 : Datum
     228 GIC           7 : pg_stat_get_progress_info(PG_FUNCTION_ARGS)
     229 ECB             : {
     230                 : #define PG_STAT_GET_PROGRESS_COLS   PGSTAT_NUM_PROGRESS_PARAM + 3
     231 GIC           7 :     int         num_backends = pgstat_fetch_stat_numbackends();
     232                 :     int         curr_backend;
     233               7 :     char       *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0));
     234                 :     ProgressCommandType cmdtype;
     235               7 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
     236 ECB             : 
     237                 :     /* Translate command name into command type code. */
     238 CBC           7 :     if (pg_strcasecmp(cmd, "VACUUM") == 0)
     239 UIC           0 :         cmdtype = PROGRESS_COMMAND_VACUUM;
     240 CBC           7 :     else if (pg_strcasecmp(cmd, "ANALYZE") == 0)
     241 UIC           0 :         cmdtype = PROGRESS_COMMAND_ANALYZE;
     242 CBC           7 :     else if (pg_strcasecmp(cmd, "CLUSTER") == 0)
     243 LBC           0 :         cmdtype = PROGRESS_COMMAND_CLUSTER;
     244 GIC           7 :     else if (pg_strcasecmp(cmd, "CREATE INDEX") == 0)
     245 LBC           0 :         cmdtype = PROGRESS_COMMAND_CREATE_INDEX;
     246 GIC           7 :     else if (pg_strcasecmp(cmd, "BASEBACKUP") == 0)
     247 CBC           1 :         cmdtype = PROGRESS_COMMAND_BASEBACKUP;
     248               6 :     else if (pg_strcasecmp(cmd, "COPY") == 0)
     249 GIC           6 :         cmdtype = PROGRESS_COMMAND_COPY;
     250 EUB             :     else
     251 UIC           0 :         ereport(ERROR,
     252 ECB             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     253                 :                  errmsg("invalid command name: \"%s\"", cmd)));
     254                 : 
     255 CBC           7 :     InitMaterializedSRF(fcinfo, 0);
     256                 : 
     257                 :     /* 1-based index */
     258              66 :     for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
     259 ECB             :     {
     260                 :         LocalPgBackendStatus *local_beentry;
     261                 :         PgBackendStatus *beentry;
     262 GNC          59 :         Datum       values[PG_STAT_GET_PROGRESS_COLS] = {0};
     263              59 :         bool        nulls[PG_STAT_GET_PROGRESS_COLS] = {0};
     264 ECB             :         int         i;
     265                 : 
     266 CBC          59 :         local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
     267 GIC          59 :         beentry = &local_beentry->backendStatus;
     268 ECB             : 
     269                 :         /*
     270                 :          * Report values for only those backends which are running the given
     271                 :          * command.
     272                 :          */
     273 GNC          59 :         if (beentry->st_progress_command != cmdtype)
     274 GIC          52 :             continue;
     275 ECB             : 
     276                 :         /* Value available to all callers */
     277 CBC           7 :         values[0] = Int32GetDatum(beentry->st_procpid);
     278               7 :         values[1] = ObjectIdGetDatum(beentry->st_databaseid);
     279                 : 
     280 ECB             :         /* show rest of the values including relid only to role members */
     281 CBC           7 :         if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     282 ECB             :         {
     283 GIC           7 :             values[2] = ObjectIdGetDatum(beentry->st_progress_command_target);
     284 CBC         147 :             for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
     285             140 :                 values[i + 3] = Int64GetDatum(beentry->st_progress_param[i]);
     286                 :         }
     287                 :         else
     288                 :         {
     289 UBC           0 :             nulls[2] = true;
     290               0 :             for (i = 0; i < PGSTAT_NUM_PROGRESS_PARAM; i++)
     291               0 :                 nulls[i + 3] = true;
     292                 :         }
     293                 : 
     294 CBC           7 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
     295                 :     }
     296                 : 
     297 GIC           7 :     return (Datum) 0;
     298                 : }
     299                 : 
     300                 : /*
     301                 :  * Returns activity of PG backends.
     302 ECB             :  */
     303                 : Datum
     304 CBC         575 : pg_stat_get_activity(PG_FUNCTION_ARGS)
     305                 : {
     306                 : #define PG_STAT_GET_ACTIVITY_COLS   30
     307 GIC         575 :     int         num_backends = pgstat_fetch_stat_numbackends();
     308                 :     int         curr_backend;
     309 GBC         575 :     int         pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
     310             575 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
     311 EUB             : 
     312 GIC         575 :     InitMaterializedSRF(fcinfo, 0);
     313                 : 
     314                 :     /* 1-based index */
     315 CBC        4783 :     for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
     316                 :     {
     317                 :         /* for each row */
     318 GNC        4209 :         Datum       values[PG_STAT_GET_ACTIVITY_COLS] = {0};
     319            4209 :         bool        nulls[PG_STAT_GET_ACTIVITY_COLS] = {0};
     320 ECB             :         LocalPgBackendStatus *local_beentry;
     321                 :         PgBackendStatus *beentry;
     322                 :         PGPROC     *proc;
     323 GBC        4209 :         const char *wait_event_type = NULL;
     324 GIC        4209 :         const char *wait_event = NULL;
     325                 : 
     326                 :         /* Get the next one in the list */
     327 CBC        4209 :         local_beentry = pgstat_fetch_stat_local_beentry(curr_backend);
     328 GIC        4209 :         beentry = &local_beentry->backendStatus;
     329 ECB             : 
     330                 :         /* If looking for specific PID, ignore all the others */
     331 GIC        4209 :         if (pid != -1 && beentry->st_procpid != pid)
     332 CBC           3 :             continue;
     333                 : 
     334                 :         /* Values available to all callers */
     335 GIC        4206 :         if (beentry->st_databaseid != InvalidOid)
     336 CBC        1144 :             values[0] = ObjectIdGetDatum(beentry->st_databaseid);
     337 ECB             :         else
     338 GIC        3062 :             nulls[0] = true;
     339                 : 
     340            4206 :         values[1] = Int32GetDatum(beentry->st_procpid);
     341 ECB             : 
     342 GIC        4206 :         if (beentry->st_userid != InvalidOid)
     343 CBC        1893 :             values[2] = ObjectIdGetDatum(beentry->st_userid);
     344 ECB             :         else
     345 CBC        2313 :             nulls[2] = true;
     346                 : 
     347 GIC        4206 :         if (beentry->st_appname)
     348            4206 :             values[3] = CStringGetTextDatum(beentry->st_appname);
     349 ECB             :         else
     350 LBC           0 :             nulls[3] = true;
     351 ECB             : 
     352 GIC        4206 :         if (TransactionIdIsValid(local_beentry->backend_xid))
     353              17 :             values[15] = TransactionIdGetDatum(local_beentry->backend_xid);
     354 ECB             :         else
     355 CBC        4189 :             nulls[15] = true;
     356                 : 
     357            4206 :         if (TransactionIdIsValid(local_beentry->backend_xmin))
     358 GIC         611 :             values[16] = TransactionIdGetDatum(local_beentry->backend_xmin);
     359                 :         else
     360            3595 :             nulls[16] = true;
     361                 : 
     362 ECB             :         /* Values only available to role member or pg_read_all_stats */
     363 CBC        4206 :         if (HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     364            4125 :         {
     365 ECB             :             SockAddr    zero_clientaddr;
     366                 :             char       *clipped_activity;
     367                 : 
     368 CBC        4125 :             switch (beentry->st_state)
     369 ECB             :             {
     370 CBC          61 :                 case STATE_IDLE:
     371              61 :                     values[4] = CStringGetTextDatum("idle");
     372              61 :                     break;
     373            1255 :                 case STATE_RUNNING:
     374            1255 :                     values[4] = CStringGetTextDatum("active");
     375            1255 :                     break;
     376              11 :                 case STATE_IDLEINTRANSACTION:
     377              11 :                     values[4] = CStringGetTextDatum("idle in transaction");
     378              11 :                     break;
     379 LBC           0 :                 case STATE_FASTPATH:
     380               0 :                     values[4] = CStringGetTextDatum("fastpath function call");
     381               0 :                     break;
     382               0 :                 case STATE_IDLEINTRANSACTION_ABORTED:
     383               0 :                     values[4] = CStringGetTextDatum("idle in transaction (aborted)");
     384               0 :                     break;
     385               0 :                 case STATE_DISABLED:
     386 UIC           0 :                     values[4] = CStringGetTextDatum("disabled");
     387               0 :                     break;
     388 CBC        2798 :                 case STATE_UNDEFINED:
     389 GIC        2798 :                     nulls[4] = true;
     390            2798 :                     break;
     391 ECB             :             }
     392                 : 
     393 GIC        4125 :             clipped_activity = pgstat_clip_activity(beentry->st_activity_raw);
     394            4125 :             values[5] = CStringGetTextDatum(clipped_activity);
     395 CBC        4125 :             pfree(clipped_activity);
     396                 : 
     397                 :             /* leader_pid */
     398 GIC        4125 :             nulls[28] = true;
     399                 : 
     400 CBC        4125 :             proc = BackendPidGetProc(beentry->st_procpid);
     401                 : 
     402            4125 :             if (proc == NULL && (beentry->st_backendType != B_BACKEND))
     403                 :             {
     404                 :                 /*
     405                 :                  * For an auxiliary process, retrieve process info from
     406                 :                  * AuxiliaryProcs stored in shared-memory.
     407 ECB             :                  */
     408 GIC        1704 :                 proc = AuxiliaryPidGetProc(beentry->st_procpid);
     409 ECB             :             }
     410                 : 
     411                 :             /*
     412                 :              * If a PGPROC entry was retrieved, display wait events and lock
     413                 :              * group leader or apply leader information if any.  To avoid
     414                 :              * extra overhead, no extra lock is being held, so there is no
     415                 :              * guarantee of consistency across multiple rows.
     416                 :              */
     417 GIC        4125 :             if (proc != NULL)
     418                 :             {
     419                 :                 uint32      raw_wait_event;
     420 EUB             :                 PGPROC     *leader;
     421                 : 
     422 GBC        4125 :                 raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info);
     423 GIC        4125 :                 wait_event_type = pgstat_get_wait_event_type(raw_wait_event);
     424            4125 :                 wait_event = pgstat_get_wait_event(raw_wait_event);
     425 EUB             : 
     426 GBC        4125 :                 leader = proc->lockGroupLeader;
     427                 : 
     428 EUB             :                 /*
     429                 :                  * Show the leader only for active parallel workers.  This
     430                 :                  * leaves the field as NULL for the leader of a parallel group
     431                 :                  * or the leader of parallel apply workers.
     432                 :                  */
     433 GBC        4125 :                 if (leader && leader->pid != beentry->st_procpid)
     434                 :                 {
     435 UBC           0 :                     values[28] = Int32GetDatum(leader->pid);
     436 UIC           0 :                     nulls[28] = false;
     437                 :                 }
     438 GNC        4125 :                 else if (beentry->st_backendType == B_BG_WORKER)
     439                 :                 {
     440             582 :                     int         leader_pid = GetLeaderApplyWorkerPid(beentry->st_procpid);
     441                 : 
     442             582 :                     if (leader_pid != InvalidPid)
     443                 :                     {
     444 UNC           0 :                         values[28] = Int32GetDatum(leader_pid);
     445               0 :                         nulls[28] = false;
     446                 :                     }
     447                 :                 }
     448 EUB             :             }
     449                 : 
     450 GIC        4125 :             if (wait_event_type)
     451 GBC        3506 :                 values[6] = CStringGetTextDatum(wait_event_type);
     452                 :             else
     453 GIC         619 :                 nulls[6] = true;
     454                 : 
     455 GBC        4125 :             if (wait_event)
     456 GIC        3506 :                 values[7] = CStringGetTextDatum(wait_event);
     457                 :             else
     458             619 :                 nulls[7] = true;
     459                 : 
     460                 :             /*
     461 EUB             :              * Don't expose transaction time for walsenders; it confuses
     462                 :              * monitoring, particularly because we don't keep the time up-to-
     463                 :              * date.
     464                 :              */
     465 GBC        4125 :             if (beentry->st_xact_start_timestamp != 0 &&
     466             624 :                 beentry->st_backendType != B_WAL_SENDER)
     467 GIC         620 :                 values[8] = TimestampTzGetDatum(beentry->st_xact_start_timestamp);
     468                 :             else
     469 GBC        3505 :                 nulls[8] = true;
     470 EUB             : 
     471 GIC        4125 :             if (beentry->st_activity_start_timestamp != 0)
     472 GBC        1292 :                 values[9] = TimestampTzGetDatum(beentry->st_activity_start_timestamp);
     473                 :             else
     474 GIC        2833 :                 nulls[9] = true;
     475 EUB             : 
     476 GIC        4125 :             if (beentry->st_proc_start_timestamp != 0)
     477 GBC        4125 :                 values[10] = TimestampTzGetDatum(beentry->st_proc_start_timestamp);
     478                 :             else
     479 UIC           0 :                 nulls[10] = true;
     480 EUB             : 
     481 GBC        4125 :             if (beentry->st_state_start_timestamp != 0)
     482 GIC        1327 :                 values[11] = TimestampTzGetDatum(beentry->st_state_start_timestamp);
     483                 :             else
     484            2798 :                 nulls[11] = true;
     485 EUB             : 
     486                 :             /* A zeroed client addr means we don't know */
     487 GIC        4125 :             memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
     488            4125 :             if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
     489                 :                        sizeof(zero_clientaddr)) == 0)
     490 EUB             :             {
     491 GIC        2831 :                 nulls[12] = true;
     492            2831 :                 nulls[13] = true;
     493            2831 :                 nulls[14] = true;
     494 EUB             :             }
     495                 :             else
     496                 :             {
     497 GNC        1294 :                 if (beentry->st_clientaddr.addr.ss_family == AF_INET ||
     498            1279 :                     beentry->st_clientaddr.addr.ss_family == AF_INET6)
     499 GBC          15 :                 {
     500 EUB             :                     char        remote_host[NI_MAXHOST];
     501                 :                     char        remote_port[NI_MAXSERV];
     502                 :                     int         ret;
     503                 : 
     504 GBC          15 :                     remote_host[0] = '\0';
     505 GIC          15 :                     remote_port[0] = '\0';
     506 GBC          15 :                     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
     507 GIC          15 :                                              beentry->st_clientaddr.salen,
     508 EUB             :                                              remote_host, sizeof(remote_host),
     509                 :                                              remote_port, sizeof(remote_port),
     510                 :                                              NI_NUMERICHOST | NI_NUMERICSERV);
     511 GIC          15 :                     if (ret == 0)
     512 EUB             :                     {
     513 GIC          15 :                         clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
     514              15 :                         values[12] = DirectFunctionCall1(inet_in,
     515                 :                                                          CStringGetDatum(remote_host));
     516 GBC          15 :                         if (beentry->st_clienthostname &&
     517 GIC          15 :                             beentry->st_clienthostname[0])
     518 GBC           7 :                             values[13] = CStringGetTextDatum(beentry->st_clienthostname);
     519                 :                         else
     520 GIC           8 :                             nulls[13] = true;
     521 GBC          15 :                         values[14] = Int32GetDatum(atoi(remote_port));
     522                 :                     }
     523 EUB             :                     else
     524                 :                     {
     525 UBC           0 :                         nulls[12] = true;
     526               0 :                         nulls[13] = true;
     527               0 :                         nulls[14] = true;
     528 EUB             :                     }
     529                 :                 }
     530 GBC        1279 :                 else if (beentry->st_clientaddr.addr.ss_family == AF_UNIX)
     531 EUB             :                 {
     532                 :                     /*
     533                 :                      * Unix sockets always reports NULL for host and -1 for
     534                 :                      * port, so it's possible to tell the difference to
     535                 :                      * connections we have no permissions to view, or with
     536                 :                      * errors.
     537                 :                      */
     538 GIC        1279 :                     nulls[12] = true;
     539 GBC        1279 :                     nulls[13] = true;
     540 GIC        1279 :                     values[14] = Int32GetDatum(-1);
     541                 :                 }
     542 EUB             :                 else
     543                 :                 {
     544                 :                     /* Unknown address type, should never happen */
     545 UBC           0 :                     nulls[12] = true;
     546               0 :                     nulls[13] = true;
     547               0 :                     nulls[14] = true;
     548 EUB             :                 }
     549                 :             }
     550                 :             /* Add backend type */
     551 GBC        4125 :             if (beentry->st_backendType == B_BG_WORKER)
     552 EUB             :             {
     553                 :                 const char *bgw_type;
     554                 : 
     555 GIC         582 :                 bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid);
     556             582 :                 if (bgw_type)
     557             582 :                     values[17] = CStringGetTextDatum(bgw_type);
     558                 :                 else
     559 UBC           0 :                     nulls[17] = true;
     560                 :             }
     561 EUB             :             else
     562 GIC        3543 :                 values[17] =
     563            3543 :                     CStringGetTextDatum(GetBackendTypeDesc(beentry->st_backendType));
     564                 : 
     565 EUB             :             /* SSL information */
     566 GBC        4125 :             if (beentry->st_ssl)
     567                 :             {
     568               7 :                 values[18] = BoolGetDatum(true);    /* ssl */
     569               7 :                 values[19] = CStringGetTextDatum(beentry->st_sslstatus->ssl_version);
     570 GIC           7 :                 values[20] = CStringGetTextDatum(beentry->st_sslstatus->ssl_cipher);
     571 GBC           7 :                 values[21] = Int32GetDatum(beentry->st_sslstatus->ssl_bits);
     572                 : 
     573 GIC           7 :                 if (beentry->st_sslstatus->ssl_client_dn[0])
     574               6 :                     values[22] = CStringGetTextDatum(beentry->st_sslstatus->ssl_client_dn);
     575                 :                 else
     576               1 :                     nulls[22] = true;
     577 EUB             : 
     578 GBC           7 :                 if (beentry->st_sslstatus->ssl_client_serial[0])
     579 GIC           6 :                     values[23] = DirectFunctionCall3(numeric_in,
     580 EUB             :                                                      CStringGetDatum(beentry->st_sslstatus->ssl_client_serial),
     581                 :                                                      ObjectIdGetDatum(InvalidOid),
     582                 :                                                      Int32GetDatum(-1));
     583                 :                 else
     584 GIC           1 :                     nulls[23] = true;
     585 EUB             : 
     586 GIC           7 :                 if (beentry->st_sslstatus->ssl_issuer_dn[0])
     587 GBC           6 :                     values[24] = CStringGetTextDatum(beentry->st_sslstatus->ssl_issuer_dn);
     588                 :                 else
     589 GIC           1 :                     nulls[24] = true;
     590                 :             }
     591 EUB             :             else
     592                 :             {
     593 GIC        4118 :                 values[18] = BoolGetDatum(false);   /* ssl */
     594 GBC        4118 :                 nulls[19] = nulls[20] = nulls[21] = nulls[22] = nulls[23] = nulls[24] = true;
     595 EUB             :             }
     596                 : 
     597                 :             /* GSSAPI information */
     598 GIC        4125 :             if (beentry->st_gss)
     599 EUB             :             {
     600 GBC           8 :                 values[25] = BoolGetDatum(beentry->st_gssstatus->gss_auth); /* gss_auth */
     601 GIC           8 :                 values[26] = CStringGetTextDatum(beentry->st_gssstatus->gss_princ);
     602 GBC           8 :                 values[27] = BoolGetDatum(beentry->st_gssstatus->gss_enc);    /* GSS Encryption in use */
     603                 :             }
     604                 :             else
     605                 :             {
     606 GIC        4117 :                 values[25] = BoolGetDatum(false);   /* gss_auth */
     607 GBC        4117 :                 nulls[26] = true;   /* No GSS principal */
     608 GIC        4117 :                 values[27] = BoolGetDatum(false);   /* GSS Encryption not in
     609 EUB             :                                                      * use */
     610                 :             }
     611 GIC        4125 :             if (beentry->st_query_id == 0)
     612            4112 :                 nulls[29] = true;
     613 EUB             :             else
     614 GBC          13 :                 values[29] = UInt64GetDatum(beentry->st_query_id);
     615                 :         }
     616 EUB             :         else
     617                 :         {
     618                 :             /* No permissions to view data about this session */
     619 GBC          81 :             values[5] = CStringGetTextDatum("<insufficient privilege>");
     620 GIC          81 :             nulls[4] = true;
     621 GBC          81 :             nulls[6] = true;
     622              81 :             nulls[7] = true;
     623 GIC          81 :             nulls[8] = true;
     624 GBC          81 :             nulls[9] = true;
     625 GIC          81 :             nulls[10] = true;
     626              81 :             nulls[11] = true;
     627              81 :             nulls[12] = true;
     628              81 :             nulls[13] = true;
     629 GBC          81 :             nulls[14] = true;
     630 GIC          81 :             nulls[17] = true;
     631 GBC          81 :             nulls[18] = true;
     632 GIC          81 :             nulls[19] = true;
     633              81 :             nulls[20] = true;
     634              81 :             nulls[21] = true;
     635              81 :             nulls[22] = true;
     636              81 :             nulls[23] = true;
     637 GBC          81 :             nulls[24] = true;
     638              81 :             nulls[25] = true;
     639 GIC          81 :             nulls[26] = true;
     640 GBC          81 :             nulls[27] = true;
     641              81 :             nulls[28] = true;
     642 GIC          81 :             nulls[29] = true;
     643                 :         }
     644 EUB             : 
     645 GBC        4206 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
     646                 : 
     647 EUB             :         /* If only a single backend was requested, and we found it, break. */
     648 GIC        4206 :         if (pid != -1)
     649 GBC           1 :             break;
     650                 :     }
     651 EUB             : 
     652 GIC         575 :     return (Datum) 0;
     653 EUB             : }
     654                 : 
     655                 : 
     656                 : Datum
     657 GIC         570 : pg_backend_pid(PG_FUNCTION_ARGS)
     658 EUB             : {
     659 GBC         570 :     PG_RETURN_INT32(MyProcPid);
     660 EUB             : }
     661                 : 
     662                 : 
     663                 : Datum
     664 GBC          35 : pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
     665 EUB             : {
     666 GIC          35 :     int32       beid = PG_GETARG_INT32(0);
     667 EUB             :     PgBackendStatus *beentry;
     668                 : 
     669 GBC          35 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     670 UIC           0 :         PG_RETURN_NULL();
     671                 : 
     672 GIC          35 :     PG_RETURN_INT32(beentry->st_procpid);
     673                 : }
     674 EUB             : 
     675                 : 
     676                 : Datum
     677 UIC           0 : pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
     678                 : {
     679               0 :     int32       beid = PG_GETARG_INT32(0);
     680                 :     PgBackendStatus *beentry;
     681                 : 
     682 UBC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     683               0 :         PG_RETURN_NULL();
     684                 : 
     685               0 :     PG_RETURN_OID(beentry->st_databaseid);
     686 EUB             : }
     687                 : 
     688                 : 
     689                 : Datum
     690 UBC           0 : pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
     691                 : {
     692               0 :     int32       beid = PG_GETARG_INT32(0);
     693                 :     PgBackendStatus *beentry;
     694 EUB             : 
     695 UIC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     696 UBC           0 :         PG_RETURN_NULL();
     697                 : 
     698               0 :     PG_RETURN_OID(beentry->st_userid);
     699 EUB             : }
     700                 : 
     701                 : Datum
     702 UNC           0 : pg_stat_get_backend_subxact(PG_FUNCTION_ARGS)
     703                 : {
     704                 : #define PG_STAT_GET_SUBXACT_COLS    2
     705                 :     TupleDesc   tupdesc;
     706                 :     Datum       values[PG_STAT_GET_SUBXACT_COLS];
     707                 :     bool        nulls[PG_STAT_GET_SUBXACT_COLS];
     708               0 :     int32       beid = PG_GETARG_INT32(0);
     709                 :     LocalPgBackendStatus *local_beentry;
     710                 : 
     711                 :     /* Initialise values and NULL flags arrays */
     712               0 :     MemSet(values, 0, sizeof(values));
     713               0 :     MemSet(nulls, 0, sizeof(nulls));
     714                 : 
     715                 :     /* Initialise attributes information in the tuple descriptor */
     716               0 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_SUBXACT_COLS);
     717               0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "subxact_count",
     718                 :                        INT4OID, -1, 0);
     719               0 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "subxact_overflow",
     720                 :                        BOOLOID, -1, 0);
     721                 : 
     722               0 :     BlessTupleDesc(tupdesc);
     723                 : 
     724               0 :     if ((local_beentry = pgstat_fetch_stat_local_beentry(beid)) != NULL)
     725                 :     {
     726                 :         /* Fill values and NULLs */
     727               0 :         values[0] = Int32GetDatum(local_beentry->backend_subxact_count);
     728               0 :         values[1] = BoolGetDatum(local_beentry->backend_subxact_overflowed);
     729                 :     }
     730                 :     else
     731                 :     {
     732               0 :         nulls[0] = true;
     733               0 :         nulls[1] = true;
     734                 :     }
     735                 : 
     736                 :     /* Returns the record as Datum */
     737               0 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
     738                 : }
     739 EUB             : 
     740                 : Datum
     741 UIC           0 : pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
     742                 : {
     743 UBC           0 :     int32       beid = PG_GETARG_INT32(0);
     744 EUB             :     PgBackendStatus *beentry;
     745                 :     const char *activity;
     746                 :     char       *clipped_activity;
     747                 :     text       *ret;
     748                 : 
     749 UBC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     750               0 :         activity = "<backend information not available>";
     751 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     752 UBC           0 :         activity = "<insufficient privilege>";
     753 UIC           0 :     else if (*(beentry->st_activity_raw) == '\0')
     754               0 :         activity = "<command string not enabled>";
     755                 :     else
     756               0 :         activity = beentry->st_activity_raw;
     757                 : 
     758 UBC           0 :     clipped_activity = pgstat_clip_activity(activity);
     759 UIC           0 :     ret = cstring_to_text(activity);
     760 UBC           0 :     pfree(clipped_activity);
     761                 : 
     762               0 :     PG_RETURN_TEXT_P(ret);
     763                 : }
     764                 : 
     765 EUB             : Datum
     766 UBC           0 : pg_stat_get_backend_wait_event_type(PG_FUNCTION_ARGS)
     767                 : {
     768               0 :     int32       beid = PG_GETARG_INT32(0);
     769                 :     PgBackendStatus *beentry;
     770 EUB             :     PGPROC     *proc;
     771 UBC           0 :     const char *wait_event_type = NULL;
     772                 : 
     773 UIC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     774 UBC           0 :         wait_event_type = "<backend information not available>";
     775 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     776               0 :         wait_event_type = "<insufficient privilege>";
     777               0 :     else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
     778               0 :         wait_event_type = pgstat_get_wait_event_type(proc->wait_event_info);
     779                 : 
     780               0 :     if (!wait_event_type)
     781               0 :         PG_RETURN_NULL();
     782                 : 
     783               0 :     PG_RETURN_TEXT_P(cstring_to_text(wait_event_type));
     784                 : }
     785                 : 
     786                 : Datum
     787               0 : pg_stat_get_backend_wait_event(PG_FUNCTION_ARGS)
     788                 : {
     789               0 :     int32       beid = PG_GETARG_INT32(0);
     790                 :     PgBackendStatus *beentry;
     791                 :     PGPROC     *proc;
     792               0 :     const char *wait_event = NULL;
     793                 : 
     794               0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     795 UBC           0 :         wait_event = "<backend information not available>";
     796 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     797               0 :         wait_event = "<insufficient privilege>";
     798 UBC           0 :     else if ((proc = BackendPidGetProc(beentry->st_procpid)) != NULL)
     799 UIC           0 :         wait_event = pgstat_get_wait_event(proc->wait_event_info);
     800                 : 
     801 LBC           0 :     if (!wait_event)
     802 UIC           0 :         PG_RETURN_NULL();
     803                 : 
     804 LBC           0 :     PG_RETURN_TEXT_P(cstring_to_text(wait_event));
     805                 : }
     806                 : 
     807 ECB             : 
     808                 : Datum
     809 UIC           0 : pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
     810 ECB             : {
     811 UIC           0 :     int32       beid = PG_GETARG_INT32(0);
     812                 :     TimestampTz result;
     813 ECB             :     PgBackendStatus *beentry;
     814                 : 
     815 UIC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     816 LBC           0 :         PG_RETURN_NULL();
     817                 : 
     818 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     819 LBC           0 :         PG_RETURN_NULL();
     820                 : 
     821 UIC           0 :     result = beentry->st_activity_start_timestamp;
     822 EUB             : 
     823                 :     /*
     824                 :      * No time recorded for start of current query -- this is the case if the
     825                 :      * user hasn't enabled query-level stats collection.
     826                 :      */
     827 UIC           0 :     if (result == 0)
     828 UBC           0 :         PG_RETURN_NULL();
     829                 : 
     830 UIC           0 :     PG_RETURN_TIMESTAMPTZ(result);
     831 EUB             : }
     832                 : 
     833                 : 
     834                 : Datum
     835 UIC           0 : pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
     836                 : {
     837 UBC           0 :     int32       beid = PG_GETARG_INT32(0);
     838                 :     TimestampTz result;
     839                 :     PgBackendStatus *beentry;
     840 EUB             : 
     841 UIC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     842               0 :         PG_RETURN_NULL();
     843 EUB             : 
     844 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     845               0 :         PG_RETURN_NULL();
     846 EUB             : 
     847 UIC           0 :     result = beentry->st_xact_start_timestamp;
     848                 : 
     849 UBC           0 :     if (result == 0)            /* not in a transaction */
     850 UIC           0 :         PG_RETURN_NULL();
     851                 : 
     852 UBC           0 :     PG_RETURN_TIMESTAMPTZ(result);
     853                 : }
     854                 : 
     855 EUB             : 
     856                 : Datum
     857 UIC           0 : pg_stat_get_backend_start(PG_FUNCTION_ARGS)
     858 ECB             : {
     859 UIC           0 :     int32       beid = PG_GETARG_INT32(0);
     860                 :     TimestampTz result;
     861 ECB             :     PgBackendStatus *beentry;
     862                 : 
     863 LBC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     864 UIC           0 :         PG_RETURN_NULL();
     865                 : 
     866               0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     867 LBC           0 :         PG_RETURN_NULL();
     868 EUB             : 
     869 UIC           0 :     result = beentry->st_proc_start_timestamp;
     870 ECB             : 
     871 UIC           0 :     if (result == 0)            /* probably can't happen? */
     872 LBC           0 :         PG_RETURN_NULL();
     873 EUB             : 
     874 UIC           0 :     PG_RETURN_TIMESTAMPTZ(result);
     875 ECB             : }
     876                 : 
     877                 : 
     878                 : Datum
     879 UIC           0 : pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
     880 ECB             : {
     881 UIC           0 :     int32       beid = PG_GETARG_INT32(0);
     882 ECB             :     PgBackendStatus *beentry;
     883                 :     SockAddr    zero_clientaddr;
     884                 :     char        remote_host[NI_MAXHOST];
     885                 :     int         ret;
     886                 : 
     887 UBC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     888 UIC           0 :         PG_RETURN_NULL();
     889 ECB             : 
     890 LBC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     891               0 :         PG_RETURN_NULL();
     892 ECB             : 
     893                 :     /* A zeroed client addr means we don't know */
     894 LBC           0 :     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
     895 UIC           0 :     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
     896 ECB             :                sizeof(zero_clientaddr)) == 0)
     897 UIC           0 :         PG_RETURN_NULL();
     898                 : 
     899               0 :     switch (beentry->st_clientaddr.addr.ss_family)
     900 EUB             :     {
     901 UIC           0 :         case AF_INET:
     902                 :         case AF_INET6:
     903               0 :             break;
     904 UBC           0 :         default:
     905               0 :             PG_RETURN_NULL();
     906                 :     }
     907 EUB             : 
     908 UBC           0 :     remote_host[0] = '\0';
     909 UIC           0 :     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
     910 UBC           0 :                              beentry->st_clientaddr.salen,
     911                 :                              remote_host, sizeof(remote_host),
     912 EUB             :                              NULL, 0,
     913                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
     914 UIC           0 :     if (ret != 0)
     915               0 :         PG_RETURN_NULL();
     916 EUB             : 
     917 UIC           0 :     clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
     918 EUB             : 
     919 UNC           0 :     PG_RETURN_DATUM(DirectFunctionCall1(inet_in,
     920                 :                                         CStringGetDatum(remote_host)));
     921                 : }
     922 EUB             : 
     923                 : Datum
     924 UIC           0 : pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
     925 EUB             : {
     926 UBC           0 :     int32       beid = PG_GETARG_INT32(0);
     927                 :     PgBackendStatus *beentry;
     928 EUB             :     SockAddr    zero_clientaddr;
     929                 :     char        remote_port[NI_MAXSERV];
     930                 :     int         ret;
     931                 : 
     932 UIC           0 :     if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
     933 UBC           0 :         PG_RETURN_NULL();
     934                 : 
     935 UIC           0 :     else if (!HAS_PGSTAT_PERMISSIONS(beentry->st_userid))
     936               0 :         PG_RETURN_NULL();
     937                 : 
     938                 :     /* A zeroed client addr means we don't know */
     939               0 :     memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
     940               0 :     if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
     941                 :                sizeof(zero_clientaddr)) == 0)
     942               0 :         PG_RETURN_NULL();
     943                 : 
     944               0 :     switch (beentry->st_clientaddr.addr.ss_family)
     945                 :     {
     946               0 :         case AF_INET:
     947                 :         case AF_INET6:
     948               0 :             break;
     949               0 :         case AF_UNIX:
     950               0 :             PG_RETURN_INT32(-1);
     951               0 :         default:
     952 UBC           0 :             PG_RETURN_NULL();
     953                 :     }
     954                 : 
     955               0 :     remote_port[0] = '\0';
     956 UIC           0 :     ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
     957               0 :                              beentry->st_clientaddr.salen,
     958 EUB             :                              NULL, 0,
     959                 :                              remote_port, sizeof(remote_port),
     960                 :                              NI_NUMERICHOST | NI_NUMERICSERV);
     961 UBC           0 :     if (ret != 0)
     962 UIC           0 :         PG_RETURN_NULL();
     963                 : 
     964 UBC           0 :     PG_RETURN_DATUM(DirectFunctionCall1(int4in,
     965                 :                                         CStringGetDatum(remote_port)));
     966                 : }
     967 ECB             : 
     968                 : 
     969                 : Datum
     970 UIC           0 : pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
     971                 : {
     972               0 :     Oid         dbid = PG_GETARG_OID(0);
     973 ECB             :     int32       result;
     974 UIC           0 :     int         tot_backends = pgstat_fetch_stat_numbackends();
     975 ECB             :     int         beid;
     976                 : 
     977 UIC           0 :     result = 0;
     978               0 :     for (beid = 1; beid <= tot_backends; beid++)
     979 EUB             :     {
     980 UNC           0 :         LocalPgBackendStatus *local_beentry = pgstat_fetch_stat_local_beentry(beid);
     981 EUB             : 
     982 UNC           0 :         if (local_beentry->backendStatus.st_databaseid == dbid)
     983 UIC           0 :             result++;
     984                 :     }
     985 EUB             : 
     986 UIC           0 :     PG_RETURN_INT32(result);
     987 EUB             : }
     988                 : 
     989                 : 
     990                 : #define PG_STAT_GET_DBENTRY_INT64(stat)                         \
     991                 : Datum                                                           \
     992                 : CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)               \
     993                 : {                                                               \
     994                 :     Oid         dbid = PG_GETARG_OID(0);                        \
     995                 :     int64       result;                                         \
     996                 :     PgStat_StatDBEntry *dbentry;                                \
     997                 :                                                                 \
     998                 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)    \
     999                 :         result = 0;                                             \
    1000                 :     else                                                        \
    1001                 :         result = (int64) (dbentry->stat);                        \
    1002                 :                                                                 \
    1003                 :     PG_RETURN_INT64(result);                                    \
    1004                 : }
    1005                 : 
    1006                 : /* pg_stat_get_db_blocks_fetched */
    1007 UNC           0 : PG_STAT_GET_DBENTRY_INT64(blocks_fetched)
    1008 EUB             : 
    1009                 : /* pg_stat_get_db_blocks_hit */
    1010 UNC           0 : PG_STAT_GET_DBENTRY_INT64(blocks_hit)
    1011                 : 
    1012                 : /* pg_stat_get_db_conflict_bufferpin */
    1013 GNC           1 : PG_STAT_GET_DBENTRY_INT64(conflict_bufferpin)
    1014                 : 
    1015                 : /* pg_stat_get_db_conflict_lock */
    1016               1 : PG_STAT_GET_DBENTRY_INT64(conflict_lock)
    1017                 : 
    1018                 : /* pg_stat_get_db_conflict_snapshot */
    1019               1 : PG_STAT_GET_DBENTRY_INT64(conflict_snapshot)
    1020 EUB             : 
    1021                 : /* pg_stat_get_db_conflict_startup_deadlock */
    1022 GNC           1 : PG_STAT_GET_DBENTRY_INT64(conflict_startup_deadlock)
    1023                 : 
    1024                 : /* pg_stat_get_db_conflict_tablespace */
    1025               1 : PG_STAT_GET_DBENTRY_INT64(conflict_tablespace)
    1026 EUB             : 
    1027                 : /* pg_stat_get_db_deadlocks */
    1028 GNC           1 : PG_STAT_GET_DBENTRY_INT64(deadlocks)
    1029                 : 
    1030                 : /* pg_stat_get_db_sessions */
    1031               6 : PG_STAT_GET_DBENTRY_INT64(sessions)
    1032                 : 
    1033                 : /* pg_stat_get_db_sessions_abandoned */
    1034 UNC           0 : PG_STAT_GET_DBENTRY_INT64(sessions_abandoned)
    1035                 : 
    1036                 : /* pg_stat_get_db_sessions_fatal */
    1037               0 : PG_STAT_GET_DBENTRY_INT64(sessions_fatal)
    1038                 : 
    1039                 : /* pg_stat_get_db_sessions_killed */
    1040               0 : PG_STAT_GET_DBENTRY_INT64(sessions_killed)
    1041                 : 
    1042                 : /* pg_stat_get_db_temp_bytes */
    1043               0 : PG_STAT_GET_DBENTRY_INT64(temp_bytes)
    1044                 : 
    1045                 : /* pg_stat_get_db_temp_files */
    1046               0 : PG_STAT_GET_DBENTRY_INT64(temp_files)
    1047                 : 
    1048                 : /* pg_stat_get_db_tuples_deleted */
    1049               0 : PG_STAT_GET_DBENTRY_INT64(tuples_deleted)
    1050                 : 
    1051                 : /* pg_stat_get_db_tuples_fetched */
    1052               0 : PG_STAT_GET_DBENTRY_INT64(tuples_fetched)
    1053                 : 
    1054                 : /* pg_stat_get_db_tuples_inserted */
    1055               0 : PG_STAT_GET_DBENTRY_INT64(tuples_inserted)
    1056 ECB             : 
    1057                 : /* pg_stat_get_db_tuples_returned */
    1058 UNC           0 : PG_STAT_GET_DBENTRY_INT64(tuples_returned)
    1059 ECB             : 
    1060                 : /* pg_stat_get_db_tuples_updated */
    1061 UNC           0 : PG_STAT_GET_DBENTRY_INT64(tuples_updated)
    1062 ECB             : 
    1063                 : /* pg_stat_get_db_xact_commit */
    1064 UNC           0 : PG_STAT_GET_DBENTRY_INT64(xact_commit)
    1065 ECB             : 
    1066                 : /* pg_stat_get_db_xact_rollback */
    1067 UNC           0 : PG_STAT_GET_DBENTRY_INT64(xact_rollback)
    1068                 : 
    1069                 : /* pg_stat_get_db_conflict_logicalslot */
    1070 GNC           6 : PG_STAT_GET_DBENTRY_INT64(conflict_logicalslot)
    1071                 : 
    1072 ECB             : Datum
    1073 GIC           6 : pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
    1074 ECB             : {
    1075 GIC           6 :     Oid         dbid = PG_GETARG_OID(0);
    1076 ECB             :     TimestampTz result;
    1077                 :     PgStat_StatDBEntry *dbentry;
    1078                 : 
    1079 CBC           6 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1080 UIC           0 :         result = 0;
    1081                 :     else
    1082 GIC           6 :         result = dbentry->stat_reset_timestamp;
    1083                 : 
    1084               6 :     if (result == 0)
    1085 UIC           0 :         PG_RETURN_NULL();
    1086 ECB             :     else
    1087 GIC           6 :         PG_RETURN_TIMESTAMPTZ(result);
    1088                 : }
    1089                 : 
    1090                 : 
    1091 ECB             : Datum
    1092 GIC           1 : pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
    1093 ECB             : {
    1094 GIC           1 :     Oid         dbid = PG_GETARG_OID(0);
    1095 ECB             :     int64       result;
    1096                 :     PgStat_StatDBEntry *dbentry;
    1097                 : 
    1098 GIC           1 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1099 UIC           0 :         result = 0;
    1100 ECB             :     else
    1101 GNC           1 :         result = (int64) (dbentry->conflict_tablespace +
    1102               1 :                           dbentry->conflict_lock +
    1103               1 :                           dbentry->conflict_snapshot +
    1104               1 :                           dbentry->conflict_logicalslot +
    1105               1 :                           dbentry->conflict_bufferpin +
    1106               1 :                           dbentry->conflict_startup_deadlock);
    1107 ECB             : 
    1108 CBC           1 :     PG_RETURN_INT64(result);
    1109                 : }
    1110 ECB             : 
    1111                 : Datum
    1112 UIC           0 : pg_stat_get_db_checksum_failures(PG_FUNCTION_ARGS)
    1113 ECB             : {
    1114 UIC           0 :     Oid         dbid = PG_GETARG_OID(0);
    1115                 :     int64       result;
    1116                 :     PgStat_StatDBEntry *dbentry;
    1117                 : 
    1118               0 :     if (!DataChecksumsEnabled())
    1119               0 :         PG_RETURN_NULL();
    1120 ECB             : 
    1121 UIC           0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1122               0 :         result = 0;
    1123 ECB             :     else
    1124 UNC           0 :         result = (int64) (dbentry->checksum_failures);
    1125                 : 
    1126 UIC           0 :     PG_RETURN_INT64(result);
    1127 ECB             : }
    1128                 : 
    1129                 : Datum
    1130 LBC           0 : pg_stat_get_db_checksum_last_failure(PG_FUNCTION_ARGS)
    1131                 : {
    1132               0 :     Oid         dbid = PG_GETARG_OID(0);
    1133 ECB             :     TimestampTz result;
    1134                 :     PgStat_StatDBEntry *dbentry;
    1135                 : 
    1136 LBC           0 :     if (!DataChecksumsEnabled())
    1137 UIC           0 :         PG_RETURN_NULL();
    1138                 : 
    1139               0 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
    1140 LBC           0 :         result = 0;
    1141                 :     else
    1142               0 :         result = dbentry->last_checksum_failure;
    1143 ECB             : 
    1144 UIC           0 :     if (result == 0)
    1145 LBC           0 :         PG_RETURN_NULL();
    1146                 :     else
    1147               0 :         PG_RETURN_TIMESTAMPTZ(result);
    1148 ECB             : }
    1149                 : 
    1150                 : /* convert counter from microsec to millisec for display */
    1151                 : #define PG_STAT_GET_DBENTRY_FLOAT8_MS(stat)                     \
    1152                 : Datum                                                           \
    1153                 : CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)               \
    1154                 : {                                                               \
    1155                 :     Oid         dbid = PG_GETARG_OID(0);                        \
    1156                 :     double      result;                                         \
    1157                 :     PgStat_StatDBEntry *dbentry;                                \
    1158                 :                                                                 \
    1159                 :     if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)    \
    1160                 :         result = 0;                                             \
    1161                 :     else                                                        \
    1162                 :         result = ((double) dbentry->stat) / 1000.0;              \
    1163                 :                                                                 \
    1164                 :     PG_RETURN_FLOAT8(result);                                   \
    1165                 : }
    1166                 : 
    1167                 : /* pg_stat_get_db_active_time */
    1168 UNC           0 : PG_STAT_GET_DBENTRY_FLOAT8_MS(active_time)
    1169                 : 
    1170                 : /* pg_stat_get_db_blk_read_time */
    1171               0 : PG_STAT_GET_DBENTRY_FLOAT8_MS(blk_read_time)
    1172                 : 
    1173                 : /* pg_stat_get_db_blk_write_time */
    1174               0 : PG_STAT_GET_DBENTRY_FLOAT8_MS(blk_write_time)
    1175                 : 
    1176                 : /* pg_stat_get_db_idle_in_transaction_time */
    1177               0 : PG_STAT_GET_DBENTRY_FLOAT8_MS(idle_in_transaction_time)
    1178                 : 
    1179                 : /* pg_stat_get_db_session_time */
    1180               0 : PG_STAT_GET_DBENTRY_FLOAT8_MS(session_time)
    1181                 : 
    1182                 : Datum
    1183 GIC           4 : pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
    1184                 : {
    1185               4 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->timed_checkpoints);
    1186                 : }
    1187                 : 
    1188                 : Datum
    1189              10 : pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
    1190                 : {
    1191              10 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->requested_checkpoints);
    1192                 : }
    1193 EUB             : 
    1194                 : Datum
    1195 UIC           0 : pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
    1196 EUB             : {
    1197 UIC           0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_checkpoints);
    1198                 : }
    1199                 : 
    1200 ECB             : Datum
    1201 UIC           0 : pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
    1202                 : {
    1203               0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_written_clean);
    1204                 : }
    1205 ECB             : 
    1206                 : Datum
    1207 LBC           0 : pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
    1208 ECB             : {
    1209 UIC           0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->maxwritten_clean);
    1210 ECB             : }
    1211                 : 
    1212                 : Datum
    1213 UIC           0 : pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS)
    1214                 : {
    1215 ECB             :     /* time is already in msec, just convert to double for presentation */
    1216 UIC           0 :     PG_RETURN_FLOAT8((double)
    1217 ECB             :                      pgstat_fetch_stat_checkpointer()->checkpoint_write_time);
    1218                 : }
    1219                 : 
    1220                 : Datum
    1221 UIC           0 : pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS)
    1222                 : {
    1223                 :     /* time is already in msec, just convert to double for presentation */
    1224               0 :     PG_RETURN_FLOAT8((double)
    1225 ECB             :                      pgstat_fetch_stat_checkpointer()->checkpoint_sync_time);
    1226                 : }
    1227                 : 
    1228                 : Datum
    1229 CBC          16 : pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS)
    1230                 : {
    1231 GIC          16 :     PG_RETURN_TIMESTAMPTZ(pgstat_fetch_stat_bgwriter()->stat_reset_timestamp);
    1232                 : }
    1233                 : 
    1234                 : Datum
    1235 LBC           0 : pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
    1236                 : {
    1237               0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_backend);
    1238                 : }
    1239 ECB             : 
    1240                 : Datum
    1241 UIC           0 : pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS)
    1242                 : {
    1243               0 :     PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_fsync_backend);
    1244                 : }
    1245                 : 
    1246                 : Datum
    1247               0 : pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
    1248                 : {
    1249 LBC           0 :     PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_alloc);
    1250                 : }
    1251 ECB             : 
    1252                 : /*
    1253                 : * When adding a new column to the pg_stat_io view, add a new enum value
    1254                 : * here above IO_NUM_COLUMNS.
    1255                 : */
    1256                 : typedef enum io_stat_col
    1257                 : {
    1258                 :     IO_COL_INVALID = -1,
    1259                 :     IO_COL_BACKEND_TYPE,
    1260                 :     IO_COL_IO_OBJECT,
    1261                 :     IO_COL_IO_CONTEXT,
    1262                 :     IO_COL_READS,
    1263                 :     IO_COL_READ_TIME,
    1264                 :     IO_COL_WRITES,
    1265                 :     IO_COL_WRITE_TIME,
    1266                 :     IO_COL_EXTENDS,
    1267                 :     IO_COL_EXTEND_TIME,
    1268                 :     IO_COL_CONVERSION,
    1269                 :     IO_COL_HITS,
    1270                 :     IO_COL_EVICTIONS,
    1271                 :     IO_COL_REUSES,
    1272                 :     IO_COL_FSYNCS,
    1273                 :     IO_COL_FSYNC_TIME,
    1274                 :     IO_COL_RESET_TIME,
    1275                 :     IO_NUM_COLUMNS,
    1276                 : } io_stat_col;
    1277                 : 
    1278                 : /*
    1279                 :  * When adding a new IOOp, add a new io_stat_col and add a case to this
    1280                 :  * function returning the corresponding io_stat_col.
    1281                 :  */
    1282                 : static io_stat_col
    1283 GNC       18480 : pgstat_get_io_op_index(IOOp io_op)
    1284                 : {
    1285           18480 :     switch (io_op)
    1286                 :     {
    1287            1680 :         case IOOP_EVICT:
    1288            1680 :             return IO_COL_EVICTIONS;
    1289            3360 :         case IOOP_EXTEND:
    1290            3360 :             return IO_COL_EXTENDS;
    1291            3360 :         case IOOP_FSYNC:
    1292            3360 :             return IO_COL_FSYNCS;
    1293            1680 :         case IOOP_HIT:
    1294            1680 :             return IO_COL_HITS;
    1295            3360 :         case IOOP_READ:
    1296            3360 :             return IO_COL_READS;
    1297            1680 :         case IOOP_REUSE:
    1298            1680 :             return IO_COL_REUSES;
    1299            3360 :         case IOOP_WRITE:
    1300            3360 :             return IO_COL_WRITES;
    1301                 :     }
    1302                 : 
    1303 UNC           0 :     elog(ERROR, "unrecognized IOOp value: %d", io_op);
    1304                 :     pg_unreachable();
    1305                 : }
    1306                 : 
    1307                 : /*
    1308                 :  * Get the number of the column containing IO times for the specified IOOp.
    1309                 :  * This function encodes our assumption that IO time for an IOOp is displayed
    1310                 :  * in the view in the column directly after the IOOp counts. If an op has no
    1311                 :  * associated time, IO_COL_INVALID is returned.
    1312                 :  */
    1313                 : static io_stat_col
    1314 GNC       11760 : pgstat_get_io_time_index(IOOp io_op)
    1315                 : {
    1316           11760 :     switch (io_op)
    1317                 :     {
    1318            6720 :         case IOOP_READ:
    1319                 :         case IOOP_WRITE:
    1320                 :         case IOOP_EXTEND:
    1321                 :         case IOOP_FSYNC:
    1322            6720 :             return pgstat_get_io_op_index(io_op) + 1;
    1323            5040 :         case IOOP_EVICT:
    1324                 :         case IOOP_HIT:
    1325                 :         case IOOP_REUSE:
    1326            5040 :             return IO_COL_INVALID;
    1327                 :     }
    1328                 : 
    1329 UNC           0 :     elog(ERROR, "unrecognized IOOp value: %d", io_op);
    1330                 :     pg_unreachable();
    1331                 : }
    1332                 : 
    1333                 : static inline double
    1334 GNC        4872 : pg_stat_us_to_ms(PgStat_Counter val_ms)
    1335                 : {
    1336            4872 :     return val_ms * (double) 0.001;
    1337                 : }
    1338                 : 
    1339                 : Datum
    1340              56 : pg_stat_get_io(PG_FUNCTION_ARGS)
    1341                 : {
    1342                 :     ReturnSetInfo *rsinfo;
    1343                 :     PgStat_IO  *backends_io_stats;
    1344                 :     Datum       reset_time;
    1345                 : 
    1346              56 :     InitMaterializedSRF(fcinfo, 0);
    1347              56 :     rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
    1348                 : 
    1349              56 :     backends_io_stats = pgstat_fetch_stat_io();
    1350                 : 
    1351              56 :     reset_time = TimestampTzGetDatum(backends_io_stats->stat_reset_timestamp);
    1352                 : 
    1353             840 :     for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++)
    1354                 :     {
    1355             784 :         Datum       bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype));
    1356             784 :         PgStat_BktypeIO *bktype_stats = &backends_io_stats->stats[bktype];
    1357                 : 
    1358                 :         /*
    1359                 :          * In Assert builds, we can afford an extra loop through all of the
    1360                 :          * counters checking that only expected stats are non-zero, since it
    1361                 :          * keeps the non-Assert code cleaner.
    1362                 :          */
    1363             784 :         Assert(pgstat_bktype_io_stats_valid(bktype_stats, bktype));
    1364                 : 
    1365                 :         /*
    1366                 :          * For those BackendTypes without IO Operation stats, skip
    1367                 :          * representing them in the view altogether.
    1368                 :          */
    1369             784 :         if (!pgstat_tracks_io_bktype(bktype))
    1370             280 :             continue;
    1371                 : 
    1372            1512 :         for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++)
    1373                 :         {
    1374            1008 :             const char *obj_name = pgstat_get_io_object_name(io_obj);
    1375                 : 
    1376            5040 :             for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
    1377                 :             {
    1378            4032 :                 const char *context_name = pgstat_get_io_context_name(io_context);
    1379                 : 
    1380            4032 :                 Datum       values[IO_NUM_COLUMNS] = {0};
    1381            4032 :                 bool        nulls[IO_NUM_COLUMNS] = {0};
    1382                 : 
    1383                 :                 /*
    1384                 :                  * Some combinations of BackendType, IOObject, and IOContext
    1385                 :                  * are not valid for any type of IOOp. In such cases, omit the
    1386                 :                  * entire row from the view.
    1387                 :                  */
    1388            4032 :                 if (!pgstat_tracks_io_object(bktype, io_obj, io_context))
    1389            2352 :                     continue;
    1390                 : 
    1391            1680 :                 values[IO_COL_BACKEND_TYPE] = bktype_desc;
    1392            1680 :                 values[IO_COL_IO_CONTEXT] = CStringGetTextDatum(context_name);
    1393            1680 :                 values[IO_COL_IO_OBJECT] = CStringGetTextDatum(obj_name);
    1394            1680 :                 values[IO_COL_RESET_TIME] = TimestampTzGetDatum(reset_time);
    1395                 : 
    1396                 :                 /*
    1397                 :                  * Hard-code this to the value of BLCKSZ for now. Future
    1398                 :                  * values could include XLOG_BLCKSZ, once WAL IO is tracked,
    1399                 :                  * and constant multipliers, once non-block-oriented IO (e.g.
    1400                 :                  * temporary file IO) is tracked.
    1401                 :                  */
    1402            1680 :                 values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ);
    1403                 : 
    1404           13440 :                 for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
    1405                 :                 {
    1406           11760 :                     int         op_idx = pgstat_get_io_op_index(io_op);
    1407           11760 :                     int         time_idx = pgstat_get_io_time_index(io_op);
    1408                 : 
    1409                 :                     /*
    1410                 :                      * Some combinations of BackendType and IOOp, of IOContext
    1411                 :                      * and IOOp, and of IOObject and IOOp are not tracked. Set
    1412                 :                      * these cells in the view NULL.
    1413                 :                      */
    1414           11760 :                     if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op))
    1415                 :                     {
    1416            9016 :                         PgStat_Counter count =
    1417                 :                             bktype_stats->counts[io_obj][io_context][io_op];
    1418                 : 
    1419            9016 :                         values[op_idx] = Int64GetDatum(count);
    1420                 :                     }
    1421                 :                     else
    1422            2744 :                         nulls[op_idx] = true;
    1423                 : 
    1424                 :                     /* not every operation is timed */
    1425           11760 :                     if (time_idx == IO_COL_INVALID)
    1426            5040 :                         continue;
    1427                 : 
    1428            6720 :                     if (!nulls[op_idx])
    1429                 :                     {
    1430            4872 :                         PgStat_Counter time =
    1431                 :                             bktype_stats->times[io_obj][io_context][io_op];
    1432                 : 
    1433            4872 :                         values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time));
    1434                 :                     }
    1435                 :                     else
    1436            1848 :                         nulls[time_idx] = true;
    1437                 :                 }
    1438                 : 
    1439            1680 :                 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
    1440                 :                                      values, nulls);
    1441                 :             }
    1442                 :         }
    1443                 :     }
    1444                 : 
    1445              56 :     return (Datum) 0;
    1446                 : }
    1447                 : 
    1448                 : /*
    1449 ECB             :  * Returns statistics of WAL activity
    1450                 :  */
    1451                 : Datum
    1452 GIC          41 : pg_stat_get_wal(PG_FUNCTION_ARGS)
    1453                 : {
    1454                 : #define PG_STAT_GET_WAL_COLS    9
    1455                 :     TupleDesc   tupdesc;
    1456 GNC          41 :     Datum       values[PG_STAT_GET_WAL_COLS] = {0};
    1457              41 :     bool        nulls[PG_STAT_GET_WAL_COLS] = {0};
    1458 ECB             :     char        buf[256];
    1459                 :     PgStat_WalStats *wal_stats;
    1460                 : 
    1461                 :     /* Initialise attributes information in the tuple descriptor */
    1462 GIC          41 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_WAL_COLS);
    1463 GBC          41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "wal_records",
    1464                 :                        INT8OID, -1, 0);
    1465 GIC          41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "wal_fpi",
    1466                 :                        INT8OID, -1, 0);
    1467              41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "wal_bytes",
    1468 ECB             :                        NUMERICOID, -1, 0);
    1469 GIC          41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "wal_buffers_full",
    1470                 :                        INT8OID, -1, 0);
    1471              41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "wal_write",
    1472                 :                        INT8OID, -1, 0);
    1473 CBC          41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "wal_sync",
    1474                 :                        INT8OID, -1, 0);
    1475              41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "wal_write_time",
    1476                 :                        FLOAT8OID, -1, 0);
    1477              41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 8, "wal_sync_time",
    1478                 :                        FLOAT8OID, -1, 0);
    1479              41 :     TupleDescInitEntry(tupdesc, (AttrNumber) 9, "stats_reset",
    1480                 :                        TIMESTAMPTZOID, -1, 0);
    1481                 : 
    1482 GIC          41 :     BlessTupleDesc(tupdesc);
    1483 ECB             : 
    1484                 :     /* Get statistics about WAL activity */
    1485 CBC          41 :     wal_stats = pgstat_fetch_stat_wal();
    1486                 : 
    1487 ECB             :     /* Fill values and NULLs */
    1488 GIC          41 :     values[0] = Int64GetDatum(wal_stats->wal_records);
    1489 CBC          41 :     values[1] = Int64GetDatum(wal_stats->wal_fpi);
    1490                 : 
    1491                 :     /* Convert to numeric. */
    1492 GIC          41 :     snprintf(buf, sizeof buf, UINT64_FORMAT, wal_stats->wal_bytes);
    1493              41 :     values[2] = DirectFunctionCall3(numeric_in,
    1494 ECB             :                                     CStringGetDatum(buf),
    1495                 :                                     ObjectIdGetDatum(0),
    1496                 :                                     Int32GetDatum(-1));
    1497                 : 
    1498 CBC          41 :     values[3] = Int64GetDatum(wal_stats->wal_buffers_full);
    1499              41 :     values[4] = Int64GetDatum(wal_stats->wal_write);
    1500 GIC          41 :     values[5] = Int64GetDatum(wal_stats->wal_sync);
    1501                 : 
    1502 ECB             :     /* Convert counters from microsec to millisec for display */
    1503 CBC          41 :     values[6] = Float8GetDatum(((double) wal_stats->wal_write_time) / 1000.0);
    1504 GIC          41 :     values[7] = Float8GetDatum(((double) wal_stats->wal_sync_time) / 1000.0);
    1505                 : 
    1506 CBC          41 :     values[8] = TimestampTzGetDatum(wal_stats->stat_reset_timestamp);
    1507                 : 
    1508                 :     /* Returns the record as Datum */
    1509 GIC          41 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    1510                 : }
    1511 ECB             : 
    1512                 : /*
    1513                 :  * Returns statistics of SLRU caches.
    1514                 :  */
    1515                 : Datum
    1516 CBC          56 : pg_stat_get_slru(PG_FUNCTION_ARGS)
    1517                 : {
    1518                 : #define PG_STAT_GET_SLRU_COLS   9
    1519              56 :     ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
    1520 ECB             :     int         i;
    1521                 :     PgStat_SLRUStats *stats;
    1522                 : 
    1523 CBC          56 :     InitMaterializedSRF(fcinfo, 0);
    1524                 : 
    1525                 :     /* request SLRU stats from the cumulative stats system */
    1526 GIC          56 :     stats = pgstat_fetch_slru();
    1527                 : 
    1528 CBC          56 :     for (i = 0;; i++)
    1529 GIC         448 :     {
    1530                 :         /* for each row */
    1531 GNC         504 :         Datum       values[PG_STAT_GET_SLRU_COLS] = {0};
    1532             504 :         bool        nulls[PG_STAT_GET_SLRU_COLS] = {0};
    1533                 :         PgStat_SLRUStats stat;
    1534                 :         const char *name;
    1535 ECB             : 
    1536 GIC         504 :         name = pgstat_get_slru_name(i);
    1537                 : 
    1538             504 :         if (!name)
    1539 CBC          56 :             break;
    1540                 : 
    1541             448 :         stat = stats[i];
    1542                 : 
    1543             448 :         values[0] = PointerGetDatum(cstring_to_text(name));
    1544 GIC         448 :         values[1] = Int64GetDatum(stat.blocks_zeroed);
    1545             448 :         values[2] = Int64GetDatum(stat.blocks_hit);
    1546 CBC         448 :         values[3] = Int64GetDatum(stat.blocks_read);
    1547 GIC         448 :         values[4] = Int64GetDatum(stat.blocks_written);
    1548             448 :         values[5] = Int64GetDatum(stat.blocks_exists);
    1549             448 :         values[6] = Int64GetDatum(stat.flush);
    1550 CBC         448 :         values[7] = Int64GetDatum(stat.truncate);
    1551 GIC         448 :         values[8] = TimestampTzGetDatum(stat.stat_reset_timestamp);
    1552                 : 
    1553 CBC         448 :         tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
    1554 ECB             :     }
    1555                 : 
    1556 GIC          56 :     return (Datum) 0;
    1557                 : }
    1558 ECB             : 
    1559                 : #define PG_STAT_GET_XACT_RELENTRY_INT64(stat)           \
    1560                 : Datum                                                   \
    1561                 : CppConcat(pg_stat_get_xact_,stat)(PG_FUNCTION_ARGS)     \
    1562                 : {                                                       \
    1563                 :     Oid         relid = PG_GETARG_OID(0);               \
    1564                 :     int64       result;                                 \
    1565                 :     PgStat_TableStatus *tabentry;                       \
    1566                 :                                                         \
    1567                 :     if ((tabentry = find_tabstat_entry(relid)) == NULL) \
    1568                 :         result = 0;                                     \
    1569                 :     else                                                \
    1570                 :         result = (int64) (tabentry->counts.stat);        \
    1571                 :                                                         \
    1572                 :     PG_RETURN_INT64(result);                            \
    1573                 : }
    1574                 : 
    1575                 : /* pg_stat_get_xact_numscans */
    1576 UNC           0 : PG_STAT_GET_XACT_RELENTRY_INT64(numscans)
    1577 ECB             : 
    1578                 : /* pg_stat_get_xact_tuples_returned */
    1579 UNC           0 : PG_STAT_GET_XACT_RELENTRY_INT64(tuples_returned)
    1580                 : 
    1581                 : /* pg_stat_get_xact_tuples_fetched */
    1582               0 : PG_STAT_GET_XACT_RELENTRY_INT64(tuples_fetched)
    1583                 : 
    1584                 : /* pg_stat_get_xact_tuples_hot_updated */
    1585               0 : PG_STAT_GET_XACT_RELENTRY_INT64(tuples_hot_updated)
    1586 ECB             : 
    1587                 : /* pg_stat_get_xact_tuples_newpage_updated */
    1588 UNC           0 : PG_STAT_GET_XACT_RELENTRY_INT64(tuples_newpage_updated)
    1589 ECB             : 
    1590                 : /* pg_stat_get_xact_blocks_fetched */
    1591 UNC           0 : PG_STAT_GET_XACT_RELENTRY_INT64(blocks_fetched)
    1592                 : 
    1593                 : /* pg_stat_get_xact_blocks_hit */
    1594               0 : PG_STAT_GET_XACT_RELENTRY_INT64(blocks_hit)
    1595 EUB             : 
    1596                 : Datum
    1597 CBC          24 : pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
    1598                 : {
    1599 GIC          24 :     Oid         relid = PG_GETARG_OID(0);
    1600 ECB             :     int64       result;
    1601                 :     PgStat_TableStatus *tabentry;
    1602                 :     PgStat_TableXactStatus *trans;
    1603                 : 
    1604 GIC          24 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1605               6 :         result = 0;
    1606                 :     else
    1607                 :     {
    1608 GNC          18 :         result = tabentry->counts.tuples_inserted;
    1609                 :         /* live subtransactions' counts aren't in tuples_inserted yet */
    1610 GIC          42 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1611 CBC          24 :             result += trans->tuples_inserted;
    1612                 :     }
    1613                 : 
    1614              24 :     PG_RETURN_INT64(result);
    1615 ECB             : }
    1616                 : 
    1617                 : Datum
    1618 UIC           0 : pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
    1619                 : {
    1620 LBC           0 :     Oid         relid = PG_GETARG_OID(0);
    1621 ECB             :     int64       result;
    1622                 :     PgStat_TableStatus *tabentry;
    1623                 :     PgStat_TableXactStatus *trans;
    1624                 : 
    1625 LBC           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1626 UIC           0 :         result = 0;
    1627 ECB             :     else
    1628                 :     {
    1629 UNC           0 :         result = tabentry->counts.tuples_updated;
    1630                 :         /* live subtransactions' counts aren't in tuples_updated yet */
    1631 LBC           0 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1632 UIC           0 :             result += trans->tuples_updated;
    1633 ECB             :     }
    1634                 : 
    1635 LBC           0 :     PG_RETURN_INT64(result);
    1636                 : }
    1637 ECB             : 
    1638                 : Datum
    1639 LBC           0 : pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
    1640                 : {
    1641               0 :     Oid         relid = PG_GETARG_OID(0);
    1642                 :     int64       result;
    1643 ECB             :     PgStat_TableStatus *tabentry;
    1644                 :     PgStat_TableXactStatus *trans;
    1645                 : 
    1646 UIC           0 :     if ((tabentry = find_tabstat_entry(relid)) == NULL)
    1647               0 :         result = 0;
    1648                 :     else
    1649                 :     {
    1650 UNC           0 :         result = tabentry->counts.tuples_deleted;
    1651                 :         /* live subtransactions' counts aren't in tuples_deleted yet */
    1652 LBC           0 :         for (trans = tabentry->trans; trans != NULL; trans = trans->upper)
    1653 UIC           0 :             result += trans->tuples_deleted;
    1654                 :     }
    1655 ECB             : 
    1656 LBC           0 :     PG_RETURN_INT64(result);
    1657 ECB             : }
    1658                 : 
    1659                 : Datum
    1660 GIC          12 : pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
    1661                 : {
    1662 GBC          12 :     Oid         funcid = PG_GETARG_OID(0);
    1663                 :     PgStat_FunctionCounts *funcentry;
    1664                 : 
    1665 GIC          12 :     if ((funcentry = find_funcstat_entry(funcid)) == NULL)
    1666               3 :         PG_RETURN_NULL();
    1667 GNC           9 :     PG_RETURN_INT64(funcentry->numcalls);
    1668                 : }
    1669                 : 
    1670                 : #define PG_STAT_GET_XACT_FUNCENTRY_FLOAT8_MS(stat)              \
    1671                 : Datum                                                           \
    1672                 : CppConcat(pg_stat_get_xact_function_,stat)(PG_FUNCTION_ARGS)    \
    1673                 : {                                                               \
    1674                 :     Oid         funcid = PG_GETARG_OID(0);                      \
    1675                 :     PgStat_FunctionCounts *funcentry;                           \
    1676                 :                                                                 \
    1677                 :     if ((funcentry = find_funcstat_entry(funcid)) == NULL)      \
    1678                 :         PG_RETURN_NULL();                                       \
    1679                 :     PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->stat));  \
    1680 ECB             : }
    1681                 : 
    1682                 : /* pg_stat_get_xact_function_total_time */
    1683 UNC           0 : PG_STAT_GET_XACT_FUNCENTRY_FLOAT8_MS(total_time)
    1684                 : 
    1685                 : /* pg_stat_get_xact_function_self_time */
    1686               0 : PG_STAT_GET_XACT_FUNCENTRY_FLOAT8_MS(self_time)
    1687                 : 
    1688 ECB             : /* Get the timestamp of the current statistics snapshot */
    1689                 : Datum
    1690 CBC          15 : pg_stat_get_snapshot_timestamp(PG_FUNCTION_ARGS)
    1691 ECB             : {
    1692                 :     bool        have_snapshot;
    1693                 :     TimestampTz ts;
    1694                 : 
    1695 CBC          15 :     ts = pgstat_get_stat_snapshot_timestamp(&have_snapshot);
    1696                 : 
    1697 GIC          15 :     if (!have_snapshot)
    1698               6 :         PG_RETURN_NULL();
    1699                 : 
    1700               9 :     PG_RETURN_TIMESTAMPTZ(ts);
    1701                 : }
    1702                 : 
    1703                 : /* Discard the active statistics snapshot */
    1704                 : Datum
    1705               7 : pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
    1706                 : {
    1707               7 :     pgstat_clear_snapshot();
    1708                 : 
    1709               7 :     PG_RETURN_VOID();
    1710                 : }
    1711                 : 
    1712                 : 
    1713                 : /* Force statistics to be reported at the next occasion */
    1714                 : Datum
    1715             201 : pg_stat_force_next_flush(PG_FUNCTION_ARGS)
    1716                 : {
    1717             201 :     pgstat_force_next_flush();
    1718                 : 
    1719             201 :     PG_RETURN_VOID();
    1720                 : }
    1721                 : 
    1722                 : 
    1723                 : /* Reset all counters for the current database */
    1724                 : Datum
    1725              13 : pg_stat_reset(PG_FUNCTION_ARGS)
    1726                 : {
    1727              13 :     pgstat_reset_counters();
    1728                 : 
    1729              13 :     PG_RETURN_VOID();
    1730                 : }
    1731                 : 
    1732                 : /*
    1733                 :  * Reset some shared cluster-wide counters
    1734                 :  *
    1735                 :  * When adding a new reset target, ideally the name should match that in
    1736                 :  * pgstat_kind_infos, if relevant.
    1737                 :  */
    1738                 : Datum
    1739              14 : pg_stat_reset_shared(PG_FUNCTION_ARGS)
    1740                 : {
    1741              14 :     char       *target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    1742                 : 
    1743              14 :     if (strcmp(target, "archiver") == 0)
    1744               3 :         pgstat_reset_of_kind(PGSTAT_KIND_ARCHIVER);
    1745              11 :     else if (strcmp(target, "bgwriter") == 0)
    1746                 :     {
    1747                 :         /*
    1748                 :          * Historically checkpointer was part of bgwriter, continue to reset
    1749                 :          * both for now.
    1750                 :          */
    1751               4 :         pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER);
    1752               4 :         pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER);
    1753                 :     }
    1754 GNC           7 :     else if (strcmp(target, "io") == 0)
    1755               3 :         pgstat_reset_of_kind(PGSTAT_KIND_IO);
    1756 GIC           4 :     else if (strcmp(target, "recovery_prefetch") == 0)
    1757 UIC           0 :         XLogPrefetchResetStats();
    1758 GIC           4 :     else if (strcmp(target, "wal") == 0)
    1759               4 :         pgstat_reset_of_kind(PGSTAT_KIND_WAL);
    1760                 :     else
    1761 UIC           0 :         ereport(ERROR,
    1762                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1763                 :                  errmsg("unrecognized reset target: \"%s\"", target),
    1764                 :                  errhint("Target must be \"archiver\", \"bgwriter\", \"io\", \"recovery_prefetch\", or \"wal\".")));
    1765                 : 
    1766 GIC          14 :     PG_RETURN_VOID();
    1767                 : }
    1768                 : 
    1769                 : /* Reset a single counter in the current database */
    1770                 : Datum
    1771               3 : pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
    1772                 : {
    1773               3 :     Oid         taboid = PG_GETARG_OID(0);
    1774                 : 
    1775               3 :     pgstat_reset(PGSTAT_KIND_RELATION, MyDatabaseId, taboid);
    1776                 : 
    1777               3 :     PG_RETURN_VOID();
    1778                 : }
    1779                 : 
    1780                 : Datum
    1781               2 : pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
    1782                 : {
    1783               2 :     Oid         funcoid = PG_GETARG_OID(0);
    1784                 : 
    1785               2 :     pgstat_reset(PGSTAT_KIND_FUNCTION, MyDatabaseId, funcoid);
    1786                 : 
    1787               2 :     PG_RETURN_VOID();
    1788                 : }
    1789                 : 
    1790                 : /* Reset SLRU counters (a specific one or all of them). */
    1791                 : Datum
    1792               6 : pg_stat_reset_slru(PG_FUNCTION_ARGS)
    1793                 : {
    1794               6 :     char       *target = NULL;
    1795                 : 
    1796               6 :     if (PG_ARGISNULL(0))
    1797               3 :         pgstat_reset_of_kind(PGSTAT_KIND_SLRU);
    1798                 :     else
    1799                 :     {
    1800               3 :         target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    1801               3 :         pgstat_reset_slru(target);
    1802                 :     }
    1803                 : 
    1804               6 :     PG_RETURN_VOID();
    1805                 : }
    1806                 : 
    1807                 : /* Reset replication slots stats (a specific one or all of them). */
    1808                 : Datum
    1809               6 : pg_stat_reset_replication_slot(PG_FUNCTION_ARGS)
    1810                 : {
    1811               6 :     char       *target = NULL;
    1812                 : 
    1813               6 :     if (PG_ARGISNULL(0))
    1814               2 :         pgstat_reset_of_kind(PGSTAT_KIND_REPLSLOT);
    1815                 :     else
    1816                 :     {
    1817               4 :         target = text_to_cstring(PG_GETARG_TEXT_PP(0));
    1818               4 :         pgstat_reset_replslot(target);
    1819                 :     }
    1820                 : 
    1821               5 :     PG_RETURN_VOID();
    1822                 : }
    1823                 : 
    1824                 : /* Reset subscription stats (a specific one or all of them) */
    1825                 : Datum
    1826              10 : pg_stat_reset_subscription_stats(PG_FUNCTION_ARGS)
    1827                 : {
    1828                 :     Oid         subid;
    1829                 : 
    1830              10 :     if (PG_ARGISNULL(0))
    1831                 :     {
    1832                 :         /* Clear all subscription stats */
    1833               2 :         pgstat_reset_of_kind(PGSTAT_KIND_SUBSCRIPTION);
    1834                 :     }
    1835                 :     else
    1836                 :     {
    1837               8 :         subid = PG_GETARG_OID(0);
    1838                 : 
    1839               8 :         if (!OidIsValid(subid))
    1840 UIC           0 :             ereport(ERROR,
    1841                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1842                 :                      errmsg("invalid subscription OID %u", subid)));
    1843 GIC           8 :         pgstat_reset(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid);
    1844                 :     }
    1845                 : 
    1846              10 :     PG_RETURN_VOID();
    1847                 : }
    1848                 : 
    1849                 : Datum
    1850              22 : pg_stat_get_archiver(PG_FUNCTION_ARGS)
    1851                 : {
    1852                 :     TupleDesc   tupdesc;
    1853 GNC          22 :     Datum       values[7] = {0};
    1854              22 :     bool        nulls[7] = {0};
    1855                 :     PgStat_ArchiverStats *archiver_stats;
    1856                 : 
    1857                 :     /* Initialise attributes information in the tuple descriptor */
    1858 GIC          22 :     tupdesc = CreateTemplateTupleDesc(7);
    1859              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_count",
    1860                 :                        INT8OID, -1, 0);
    1861              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal",
    1862                 :                        TEXTOID, -1, 0);
    1863              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "last_archived_time",
    1864                 :                        TIMESTAMPTZOID, -1, 0);
    1865              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "failed_count",
    1866                 :                        INT8OID, -1, 0);
    1867              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "last_failed_wal",
    1868                 :                        TEXTOID, -1, 0);
    1869              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "last_failed_time",
    1870                 :                        TIMESTAMPTZOID, -1, 0);
    1871              22 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stats_reset",
    1872                 :                        TIMESTAMPTZOID, -1, 0);
    1873                 : 
    1874              22 :     BlessTupleDesc(tupdesc);
    1875                 : 
    1876                 :     /* Get statistics about the archiver process */
    1877              22 :     archiver_stats = pgstat_fetch_stat_archiver();
    1878                 : 
    1879                 :     /* Fill values and NULLs */
    1880              22 :     values[0] = Int64GetDatum(archiver_stats->archived_count);
    1881              22 :     if (*(archiver_stats->last_archived_wal) == '\0')
    1882              13 :         nulls[1] = true;
    1883                 :     else
    1884               9 :         values[1] = CStringGetTextDatum(archiver_stats->last_archived_wal);
    1885                 : 
    1886              22 :     if (archiver_stats->last_archived_timestamp == 0)
    1887              13 :         nulls[2] = true;
    1888                 :     else
    1889               9 :         values[2] = TimestampTzGetDatum(archiver_stats->last_archived_timestamp);
    1890                 : 
    1891              22 :     values[3] = Int64GetDatum(archiver_stats->failed_count);
    1892              22 :     if (*(archiver_stats->last_failed_wal) == '\0')
    1893              15 :         nulls[4] = true;
    1894                 :     else
    1895               7 :         values[4] = CStringGetTextDatum(archiver_stats->last_failed_wal);
    1896                 : 
    1897              22 :     if (archiver_stats->last_failed_timestamp == 0)
    1898              15 :         nulls[5] = true;
    1899                 :     else
    1900               7 :         values[5] = TimestampTzGetDatum(archiver_stats->last_failed_timestamp);
    1901                 : 
    1902              22 :     if (archiver_stats->stat_reset_timestamp == 0)
    1903 UIC           0 :         nulls[6] = true;
    1904                 :     else
    1905 GIC          22 :         values[6] = TimestampTzGetDatum(archiver_stats->stat_reset_timestamp);
    1906                 : 
    1907                 :     /* Returns the record as Datum */
    1908              22 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    1909                 : }
    1910                 : 
    1911                 : /*
    1912                 :  * Get the statistics for the replication slot. If the slot statistics is not
    1913                 :  * available, return all-zeroes stats.
    1914                 :  */
    1915                 : Datum
    1916              43 : pg_stat_get_replication_slot(PG_FUNCTION_ARGS)
    1917                 : {
    1918                 : #define PG_STAT_GET_REPLICATION_SLOT_COLS 10
    1919              43 :     text       *slotname_text = PG_GETARG_TEXT_P(0);
    1920                 :     NameData    slotname;
    1921                 :     TupleDesc   tupdesc;
    1922 GNC          43 :     Datum       values[PG_STAT_GET_REPLICATION_SLOT_COLS] = {0};
    1923              43 :     bool        nulls[PG_STAT_GET_REPLICATION_SLOT_COLS] = {0};
    1924                 :     PgStat_StatReplSlotEntry *slotent;
    1925                 :     PgStat_StatReplSlotEntry allzero;
    1926                 : 
    1927                 :     /* Initialise attributes information in the tuple descriptor */
    1928 GIC          43 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_REPLICATION_SLOT_COLS);
    1929              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "slot_name",
    1930                 :                        TEXTOID, -1, 0);
    1931              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "spill_txns",
    1932                 :                        INT8OID, -1, 0);
    1933              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "spill_count",
    1934                 :                        INT8OID, -1, 0);
    1935              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "spill_bytes",
    1936                 :                        INT8OID, -1, 0);
    1937              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 5, "stream_txns",
    1938                 :                        INT8OID, -1, 0);
    1939              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 6, "stream_count",
    1940                 :                        INT8OID, -1, 0);
    1941              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 7, "stream_bytes",
    1942                 :                        INT8OID, -1, 0);
    1943              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 8, "total_txns",
    1944                 :                        INT8OID, -1, 0);
    1945              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 9, "total_bytes",
    1946                 :                        INT8OID, -1, 0);
    1947              43 :     TupleDescInitEntry(tupdesc, (AttrNumber) 10, "stats_reset",
    1948                 :                        TIMESTAMPTZOID, -1, 0);
    1949              43 :     BlessTupleDesc(tupdesc);
    1950                 : 
    1951              43 :     namestrcpy(&slotname, text_to_cstring(slotname_text));
    1952              43 :     slotent = pgstat_fetch_replslot(slotname);
    1953              43 :     if (!slotent)
    1954                 :     {
    1955                 :         /*
    1956                 :          * If the slot is not found, initialise its stats. This is possible if
    1957                 :          * the create slot message is lost.
    1958                 :          */
    1959               2 :         memset(&allzero, 0, sizeof(PgStat_StatReplSlotEntry));
    1960               2 :         slotent = &allzero;
    1961                 :     }
    1962                 : 
    1963              43 :     values[0] = CStringGetTextDatum(NameStr(slotname));
    1964              43 :     values[1] = Int64GetDatum(slotent->spill_txns);
    1965              43 :     values[2] = Int64GetDatum(slotent->spill_count);
    1966              43 :     values[3] = Int64GetDatum(slotent->spill_bytes);
    1967              43 :     values[4] = Int64GetDatum(slotent->stream_txns);
    1968              43 :     values[5] = Int64GetDatum(slotent->stream_count);
    1969              43 :     values[6] = Int64GetDatum(slotent->stream_bytes);
    1970              43 :     values[7] = Int64GetDatum(slotent->total_txns);
    1971              43 :     values[8] = Int64GetDatum(slotent->total_bytes);
    1972                 : 
    1973              43 :     if (slotent->stat_reset_timestamp == 0)
    1974              22 :         nulls[9] = true;
    1975                 :     else
    1976              21 :         values[9] = TimestampTzGetDatum(slotent->stat_reset_timestamp);
    1977                 : 
    1978                 :     /* Returns the record as Datum */
    1979              43 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    1980                 : }
    1981                 : 
    1982                 : /*
    1983                 :  * Get the subscription statistics for the given subscription. If the
    1984                 :  * subscription statistics is not available, return all-zeros stats.
    1985                 :  */
    1986                 : Datum
    1987              29 : pg_stat_get_subscription_stats(PG_FUNCTION_ARGS)
    1988                 : {
    1989                 : #define PG_STAT_GET_SUBSCRIPTION_STATS_COLS 4
    1990              29 :     Oid         subid = PG_GETARG_OID(0);
    1991                 :     TupleDesc   tupdesc;
    1992 GNC          29 :     Datum       values[PG_STAT_GET_SUBSCRIPTION_STATS_COLS] = {0};
    1993              29 :     bool        nulls[PG_STAT_GET_SUBSCRIPTION_STATS_COLS] = {0};
    1994                 :     PgStat_StatSubEntry *subentry;
    1995                 :     PgStat_StatSubEntry allzero;
    1996                 : 
    1997                 :     /* Get subscription stats */
    1998 GIC          29 :     subentry = pgstat_fetch_stat_subscription(subid);
    1999                 : 
    2000                 :     /* Initialise attributes information in the tuple descriptor */
    2001              29 :     tupdesc = CreateTemplateTupleDesc(PG_STAT_GET_SUBSCRIPTION_STATS_COLS);
    2002              29 :     TupleDescInitEntry(tupdesc, (AttrNumber) 1, "subid",
    2003                 :                        OIDOID, -1, 0);
    2004              29 :     TupleDescInitEntry(tupdesc, (AttrNumber) 2, "apply_error_count",
    2005                 :                        INT8OID, -1, 0);
    2006              29 :     TupleDescInitEntry(tupdesc, (AttrNumber) 3, "sync_error_count",
    2007                 :                        INT8OID, -1, 0);
    2008              29 :     TupleDescInitEntry(tupdesc, (AttrNumber) 4, "stats_reset",
    2009                 :                        TIMESTAMPTZOID, -1, 0);
    2010              29 :     BlessTupleDesc(tupdesc);
    2011                 : 
    2012              29 :     if (!subentry)
    2013                 :     {
    2014                 :         /* If the subscription is not found, initialise its stats */
    2015 UIC           0 :         memset(&allzero, 0, sizeof(PgStat_StatSubEntry));
    2016               0 :         subentry = &allzero;
    2017                 :     }
    2018                 : 
    2019                 :     /* subid */
    2020 GIC          29 :     values[0] = ObjectIdGetDatum(subid);
    2021                 : 
    2022                 :     /* apply_error_count */
    2023              29 :     values[1] = Int64GetDatum(subentry->apply_error_count);
    2024                 : 
    2025                 :     /* sync_error_count */
    2026              29 :     values[2] = Int64GetDatum(subentry->sync_error_count);
    2027                 : 
    2028                 :     /* stats_reset */
    2029              29 :     if (subentry->stat_reset_timestamp == 0)
    2030              10 :         nulls[3] = true;
    2031                 :     else
    2032              19 :         values[3] = TimestampTzGetDatum(subentry->stat_reset_timestamp);
    2033                 : 
    2034                 :     /* Returns the record as Datum */
    2035              29 :     PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
    2036                 : }
    2037                 : 
    2038                 : /*
    2039                 :  * Checks for presence of stats for object with provided kind, database oid,
    2040                 :  * object oid.
    2041                 :  *
    2042                 :  * This is useful for tests, but not really anything else. Therefore not
    2043                 :  * documented.
    2044                 :  */
    2045                 : Datum
    2046              82 : pg_stat_have_stats(PG_FUNCTION_ARGS)
    2047                 : {
    2048              82 :     char       *stats_type = text_to_cstring(PG_GETARG_TEXT_P(0));
    2049              82 :     Oid         dboid = PG_GETARG_OID(1);
    2050              82 :     Oid         objoid = PG_GETARG_OID(2);
    2051              82 :     PgStat_Kind kind = pgstat_get_kind_from_str(stats_type);
    2052                 : 
    2053              79 :     PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
    2054                 : }
        

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