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