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