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