1 /*-------------------------------------------------------------------------
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.49 2008/03/25 22:42:44 tgl Exp $
13 *-------------------------------------------------------------------------
18 #include "miscadmin.h"
20 #include "utils/builtins.h"
21 #include "utils/inet.h"
24 /* bogus ... these externs should be in a header file */
25 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
26 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
27 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
28 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
29 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
30 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
31 extern Datum pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_dead_tuples(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS);
37 extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
38 extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
39 extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
41 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
42 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
45 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS);
50 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
56 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
57 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
58 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
59 extern Datum pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS);
60 extern Datum pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS);
61 extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
62 extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
63 extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
65 extern Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS);
66 extern Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS);
67 extern Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS);
68 extern Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS);
69 extern Datum pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS);
70 extern Datum pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS);
71 extern Datum pg_stat_get_buf_alloc(PG_FUNCTION_ARGS);
73 extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
74 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
76 /* Global bgwriter statistics, from bgwriter.c */
77 extern PgStat_MsgBgWriter bgwriterStats;
80 pg_stat_get_numscans(PG_FUNCTION_ARGS)
82 Oid relid = PG_GETARG_OID(0);
84 PgStat_StatTabEntry *tabentry;
86 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
89 result = (int64) (tabentry->numscans);
91 PG_RETURN_INT64(result);
96 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
98 Oid relid = PG_GETARG_OID(0);
100 PgStat_StatTabEntry *tabentry;
102 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
105 result = (int64) (tabentry->tuples_returned);
107 PG_RETURN_INT64(result);
112 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
114 Oid relid = PG_GETARG_OID(0);
116 PgStat_StatTabEntry *tabentry;
118 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
121 result = (int64) (tabentry->tuples_fetched);
123 PG_RETURN_INT64(result);
128 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
130 Oid relid = PG_GETARG_OID(0);
132 PgStat_StatTabEntry *tabentry;
134 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
137 result = (int64) (tabentry->tuples_inserted);
139 PG_RETURN_INT64(result);
144 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
146 Oid relid = PG_GETARG_OID(0);
148 PgStat_StatTabEntry *tabentry;
150 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
153 result = (int64) (tabentry->tuples_updated);
155 PG_RETURN_INT64(result);
160 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
162 Oid relid = PG_GETARG_OID(0);
164 PgStat_StatTabEntry *tabentry;
166 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
169 result = (int64) (tabentry->tuples_deleted);
171 PG_RETURN_INT64(result);
176 pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
178 Oid relid = PG_GETARG_OID(0);
180 PgStat_StatTabEntry *tabentry;
182 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
185 result = (int64) (tabentry->tuples_hot_updated);
187 PG_RETURN_INT64(result);
192 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
194 Oid relid = PG_GETARG_OID(0);
196 PgStat_StatTabEntry *tabentry;
198 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
201 result = (int64) (tabentry->n_live_tuples);
203 PG_RETURN_INT64(result);
208 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
210 Oid relid = PG_GETARG_OID(0);
212 PgStat_StatTabEntry *tabentry;
214 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
217 result = (int64) (tabentry->n_dead_tuples);
219 PG_RETURN_INT64(result);
224 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
226 Oid relid = PG_GETARG_OID(0);
228 PgStat_StatTabEntry *tabentry;
230 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
233 result = (int64) (tabentry->blocks_fetched);
235 PG_RETURN_INT64(result);
240 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
242 Oid relid = PG_GETARG_OID(0);
244 PgStat_StatTabEntry *tabentry;
246 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
249 result = (int64) (tabentry->blocks_hit);
251 PG_RETURN_INT64(result);
255 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
257 Oid relid = PG_GETARG_OID(0);
259 PgStat_StatTabEntry *tabentry;
261 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
264 result = tabentry->vacuum_timestamp;
269 PG_RETURN_TIMESTAMPTZ(result);
273 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
275 Oid relid = PG_GETARG_OID(0);
277 PgStat_StatTabEntry *tabentry;
279 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
282 result = tabentry->autovac_vacuum_timestamp;
287 PG_RETURN_TIMESTAMPTZ(result);
291 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
293 Oid relid = PG_GETARG_OID(0);
295 PgStat_StatTabEntry *tabentry;
297 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
300 result = tabentry->analyze_timestamp;
305 PG_RETURN_TIMESTAMPTZ(result);
309 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
311 Oid relid = PG_GETARG_OID(0);
313 PgStat_StatTabEntry *tabentry;
315 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
318 result = tabentry->autovac_analyze_timestamp;
323 PG_RETURN_TIMESTAMPTZ(result);
327 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
329 FuncCallContext *funcctx;
333 /* stuff done only on the first call of the function */
334 if (SRF_IS_FIRSTCALL())
336 /* create a function context for cross-call persistence */
337 funcctx = SRF_FIRSTCALL_INIT();
339 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
341 funcctx->user_fctx = fctx;
344 fctx[1] = pgstat_fetch_stat_numbackends();
347 /* stuff done on every call of the function */
348 funcctx = SRF_PERCALL_SETUP();
349 fctx = funcctx->user_fctx;
354 if (result <= fctx[1])
356 /* do when there is more left to send */
357 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
361 /* do when there is no more left */
362 SRF_RETURN_DONE(funcctx);
368 pg_backend_pid(PG_FUNCTION_ARGS)
370 PG_RETURN_INT32(MyProcPid);
375 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
377 int32 beid = PG_GETARG_INT32(0);
378 PgBackendStatus *beentry;
380 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
383 PG_RETURN_INT32(beentry->st_procpid);
388 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
390 int32 beid = PG_GETARG_INT32(0);
391 PgBackendStatus *beentry;
393 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
396 PG_RETURN_OID(beentry->st_databaseid);
401 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
403 int32 beid = PG_GETARG_INT32(0);
404 PgBackendStatus *beentry;
406 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
409 PG_RETURN_OID(beentry->st_userid);
414 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
416 int32 beid = PG_GETARG_INT32(0);
417 PgBackendStatus *beentry;
418 const char *activity;
420 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
421 activity = "<backend information not available>";
422 else if (!superuser() && beentry->st_userid != GetUserId())
423 activity = "<insufficient privilege>";
424 else if (*(beentry->st_activity) == '\0')
425 activity = "<command string not enabled>";
427 activity = beentry->st_activity;
429 PG_RETURN_TEXT_P(cstring_to_text(activity));
434 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
436 int32 beid = PG_GETARG_INT32(0);
438 PgBackendStatus *beentry;
440 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
443 if (!superuser() && beentry->st_userid != GetUserId())
446 result = beentry->st_waiting;
448 PG_RETURN_BOOL(result);
453 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
455 int32 beid = PG_GETARG_INT32(0);
457 PgBackendStatus *beentry;
459 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
462 if (!superuser() && beentry->st_userid != GetUserId())
465 result = beentry->st_activity_start_timestamp;
468 * No time recorded for start of current query -- this is the case if the
469 * user hasn't enabled query-level stats collection.
474 PG_RETURN_TIMESTAMPTZ(result);
479 pg_stat_get_backend_xact_start(PG_FUNCTION_ARGS)
481 int32 beid = PG_GETARG_INT32(0);
483 PgBackendStatus *beentry;
485 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
488 if (!superuser() && beentry->st_userid != GetUserId())
491 result = beentry->st_xact_start_timestamp;
493 if (result == 0) /* not in a transaction */
496 PG_RETURN_TIMESTAMPTZ(result);
501 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
503 int32 beid = PG_GETARG_INT32(0);
505 PgBackendStatus *beentry;
507 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
510 if (!superuser() && beentry->st_userid != GetUserId())
513 result = beentry->st_proc_start_timestamp;
515 if (result == 0) /* probably can't happen? */
518 PG_RETURN_TIMESTAMPTZ(result);
523 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
525 int32 beid = PG_GETARG_INT32(0);
526 PgBackendStatus *beentry;
527 SockAddr zero_clientaddr;
528 char remote_host[NI_MAXHOST];
531 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
534 if (!superuser() && beentry->st_userid != GetUserId())
537 /* A zeroed client addr means we don't know */
538 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
539 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
540 sizeof(zero_clientaddr) == 0))
543 switch (beentry->st_clientaddr.addr.ss_family)
554 remote_host[0] = '\0';
555 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
556 beentry->st_clientaddr.salen,
557 remote_host, sizeof(remote_host),
559 NI_NUMERICHOST | NI_NUMERICSERV);
563 clean_ipv6_addr(beentry->st_clientaddr.addr.ss_family, remote_host);
565 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
566 CStringGetDatum(remote_host)));
570 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
572 int32 beid = PG_GETARG_INT32(0);
573 PgBackendStatus *beentry;
574 SockAddr zero_clientaddr;
575 char remote_port[NI_MAXSERV];
578 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
581 if (!superuser() && beentry->st_userid != GetUserId())
584 /* A zeroed client addr means we don't know */
585 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
586 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
587 sizeof(zero_clientaddr) == 0))
590 switch (beentry->st_clientaddr.addr.ss_family)
603 remote_port[0] = '\0';
604 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
605 beentry->st_clientaddr.salen,
607 remote_port, sizeof(remote_port),
608 NI_NUMERICHOST | NI_NUMERICSERV);
612 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
613 CStringGetDatum(remote_port)));
618 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
620 Oid dbid = PG_GETARG_OID(0);
622 int tot_backends = pgstat_fetch_stat_numbackends();
626 for (beid = 1; beid <= tot_backends; beid++)
628 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
630 if (beentry && beentry->st_databaseid == dbid)
634 PG_RETURN_INT32(result);
639 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
641 Oid dbid = PG_GETARG_OID(0);
643 PgStat_StatDBEntry *dbentry;
645 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
648 result = (int64) (dbentry->n_xact_commit);
650 PG_RETURN_INT64(result);
655 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
657 Oid dbid = PG_GETARG_OID(0);
659 PgStat_StatDBEntry *dbentry;
661 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
664 result = (int64) (dbentry->n_xact_rollback);
666 PG_RETURN_INT64(result);
671 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
673 Oid dbid = PG_GETARG_OID(0);
675 PgStat_StatDBEntry *dbentry;
677 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
680 result = (int64) (dbentry->n_blocks_fetched);
682 PG_RETURN_INT64(result);
687 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
689 Oid dbid = PG_GETARG_OID(0);
691 PgStat_StatDBEntry *dbentry;
693 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
696 result = (int64) (dbentry->n_blocks_hit);
698 PG_RETURN_INT64(result);
703 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
705 Oid dbid = PG_GETARG_OID(0);
707 PgStat_StatDBEntry *dbentry;
709 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
712 result = (int64) (dbentry->n_tuples_returned);
714 PG_RETURN_INT64(result);
719 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
721 Oid dbid = PG_GETARG_OID(0);
723 PgStat_StatDBEntry *dbentry;
725 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
728 result = (int64) (dbentry->n_tuples_fetched);
730 PG_RETURN_INT64(result);
735 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
737 Oid dbid = PG_GETARG_OID(0);
739 PgStat_StatDBEntry *dbentry;
741 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
744 result = (int64) (dbentry->n_tuples_inserted);
746 PG_RETURN_INT64(result);
751 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
753 Oid dbid = PG_GETARG_OID(0);
755 PgStat_StatDBEntry *dbentry;
757 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
760 result = (int64) (dbentry->n_tuples_updated);
762 PG_RETURN_INT64(result);
767 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
769 Oid dbid = PG_GETARG_OID(0);
771 PgStat_StatDBEntry *dbentry;
773 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
776 result = (int64) (dbentry->n_tuples_deleted);
778 PG_RETURN_INT64(result);
782 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
784 PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints);
788 pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS)
790 PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints);
794 pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS)
796 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints);
800 pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS)
802 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean);
806 pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS)
808 PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean);
812 pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS)
814 PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend);
818 pg_stat_get_buf_alloc(PG_FUNCTION_ARGS)
820 PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc);
824 /* Discard the active statistics snapshot */
826 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
828 pgstat_clear_snapshot();
834 /* Reset all counters for the current database */
836 pg_stat_reset(PG_FUNCTION_ARGS)
838 pgstat_reset_counters();