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