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