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