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