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