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