1 /*-------------------------------------------------------------------------
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2007, 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.40 2007/03/16 17:57:36 mha 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_live_tuples(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_dead_tuples(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
37 extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
38 extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
40 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
41 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
42 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
45 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_txn_start(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
50 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
56 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
57 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
58 extern Datum pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS);
59 extern Datum pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS);
60 extern Datum pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS);
61 extern Datum pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS);
62 extern Datum pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS);
64 extern Datum pg_stat_clear_snapshot(PG_FUNCTION_ARGS);
65 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
69 pg_stat_get_numscans(PG_FUNCTION_ARGS)
71 Oid relid = PG_GETARG_OID(0);
73 PgStat_StatTabEntry *tabentry;
75 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
78 result = (int64) (tabentry->numscans);
80 PG_RETURN_INT64(result);
85 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
87 Oid relid = PG_GETARG_OID(0);
89 PgStat_StatTabEntry *tabentry;
91 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
94 result = (int64) (tabentry->tuples_returned);
96 PG_RETURN_INT64(result);
101 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
103 Oid relid = PG_GETARG_OID(0);
105 PgStat_StatTabEntry *tabentry;
107 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
110 result = (int64) (tabentry->tuples_fetched);
112 PG_RETURN_INT64(result);
117 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
119 Oid relid = PG_GETARG_OID(0);
121 PgStat_StatTabEntry *tabentry;
123 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
126 result = (int64) (tabentry->tuples_inserted);
128 PG_RETURN_INT64(result);
133 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
135 Oid relid = PG_GETARG_OID(0);
137 PgStat_StatTabEntry *tabentry;
139 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
142 result = (int64) (tabentry->tuples_updated);
144 PG_RETURN_INT64(result);
149 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
151 Oid relid = PG_GETARG_OID(0);
153 PgStat_StatTabEntry *tabentry;
155 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
158 result = (int64) (tabentry->tuples_deleted);
160 PG_RETURN_INT64(result);
165 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
167 Oid relid = PG_GETARG_OID(0);
169 PgStat_StatTabEntry *tabentry;
171 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
174 result = (int64) (tabentry->n_live_tuples);
176 PG_RETURN_INT64(result);
181 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
183 Oid relid = PG_GETARG_OID(0);
185 PgStat_StatTabEntry *tabentry;
187 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
190 result = (int64) (tabentry->n_dead_tuples);
192 PG_RETURN_INT64(result);
197 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
199 Oid relid = PG_GETARG_OID(0);
201 PgStat_StatTabEntry *tabentry;
203 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
206 result = (int64) (tabentry->blocks_fetched);
208 PG_RETURN_INT64(result);
213 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
215 Oid relid = PG_GETARG_OID(0);
217 PgStat_StatTabEntry *tabentry;
219 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
222 result = (int64) (tabentry->blocks_hit);
224 PG_RETURN_INT64(result);
228 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
230 Oid relid = PG_GETARG_OID(0);
232 PgStat_StatTabEntry *tabentry;
234 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
237 result = tabentry->vacuum_timestamp;
242 PG_RETURN_TIMESTAMPTZ(result);
246 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
248 Oid relid = PG_GETARG_OID(0);
250 PgStat_StatTabEntry *tabentry;
252 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
255 result = tabentry->autovac_vacuum_timestamp;
260 PG_RETURN_TIMESTAMPTZ(result);
264 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
266 Oid relid = PG_GETARG_OID(0);
268 PgStat_StatTabEntry *tabentry;
270 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
273 result = tabentry->analyze_timestamp;
278 PG_RETURN_TIMESTAMPTZ(result);
282 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
284 Oid relid = PG_GETARG_OID(0);
286 PgStat_StatTabEntry *tabentry;
288 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
291 result = tabentry->autovac_analyze_timestamp;
296 PG_RETURN_TIMESTAMPTZ(result);
300 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
302 FuncCallContext *funcctx;
306 /* stuff done only on the first call of the function */
307 if (SRF_IS_FIRSTCALL())
309 /* create a function context for cross-call persistence */
310 funcctx = SRF_FIRSTCALL_INIT();
312 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
314 funcctx->user_fctx = fctx;
317 fctx[1] = pgstat_fetch_stat_numbackends();
320 /* stuff done on every call of the function */
321 funcctx = SRF_PERCALL_SETUP();
322 fctx = funcctx->user_fctx;
327 if (result <= fctx[1])
329 /* do when there is more left to send */
330 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
334 /* do when there is no more left */
335 SRF_RETURN_DONE(funcctx);
341 pg_backend_pid(PG_FUNCTION_ARGS)
343 PG_RETURN_INT32(MyProcPid);
348 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
350 int32 beid = PG_GETARG_INT32(0);
351 PgBackendStatus *beentry;
353 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
356 PG_RETURN_INT32(beentry->st_procpid);
361 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
363 int32 beid = PG_GETARG_INT32(0);
364 PgBackendStatus *beentry;
366 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
369 PG_RETURN_OID(beentry->st_databaseid);
374 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
376 int32 beid = PG_GETARG_INT32(0);
377 PgBackendStatus *beentry;
379 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
382 PG_RETURN_OID(beentry->st_userid);
387 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
389 int32 beid = PG_GETARG_INT32(0);
391 PgBackendStatus *beentry;
393 const char *activity;
395 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
396 activity = "<backend information not available>";
397 else if (!superuser() && beentry->st_userid != GetUserId())
398 activity = "<insufficient privilege>";
399 else if (*(beentry->st_activity) == '\0')
400 activity = "<command string not enabled>";
402 activity = beentry->st_activity;
404 len = strlen(activity);
405 result = palloc(VARHDRSZ + len);
406 SET_VARSIZE(result, VARHDRSZ + len);
407 memcpy(VARDATA(result), activity, len);
409 PG_RETURN_TEXT_P(result);
414 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
416 int32 beid = PG_GETARG_INT32(0);
418 PgBackendStatus *beentry;
420 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
423 if (!superuser() && beentry->st_userid != GetUserId())
426 result = beentry->st_waiting;
428 PG_RETURN_BOOL(result);
433 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
435 int32 beid = PG_GETARG_INT32(0);
437 PgBackendStatus *beentry;
439 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
442 if (!superuser() && beentry->st_userid != GetUserId())
445 result = beentry->st_activity_start_timestamp;
448 * No time recorded for start of current query -- this is the case if the
449 * user hasn't enabled query-level stats collection.
454 PG_RETURN_TIMESTAMPTZ(result);
459 pg_stat_get_backend_txn_start(PG_FUNCTION_ARGS)
461 int32 beid = PG_GETARG_INT32(0);
463 PgBackendStatus *beentry;
465 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
468 if (!superuser() && beentry->st_userid != GetUserId())
471 result = beentry->st_txn_start_timestamp;
473 if (result == 0) /* not in a transaction */
476 PG_RETURN_TIMESTAMPTZ(result);
481 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
483 int32 beid = PG_GETARG_INT32(0);
485 PgBackendStatus *beentry;
487 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
490 if (!superuser() && beentry->st_userid != GetUserId())
493 result = beentry->st_proc_start_timestamp;
495 if (result == 0) /* probably can't happen? */
498 PG_RETURN_TIMESTAMPTZ(result);
503 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
505 int32 beid = PG_GETARG_INT32(0);
506 PgBackendStatus *beentry;
507 SockAddr zero_clientaddr;
508 char remote_host[NI_MAXHOST];
511 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
514 if (!superuser() && beentry->st_userid != GetUserId())
517 /* A zeroed client addr means we don't know */
518 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
519 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
520 sizeof(zero_clientaddr) == 0))
523 switch (beentry->st_clientaddr.addr.ss_family)
534 remote_host[0] = '\0';
535 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
536 beentry->st_clientaddr.salen,
537 remote_host, sizeof(remote_host),
539 NI_NUMERICHOST | NI_NUMERICSERV);
543 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
544 CStringGetDatum(remote_host)));
548 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
550 int32 beid = PG_GETARG_INT32(0);
551 PgBackendStatus *beentry;
552 SockAddr zero_clientaddr;
553 char remote_port[NI_MAXSERV];
556 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
559 if (!superuser() && beentry->st_userid != GetUserId())
562 /* A zeroed client addr means we don't know */
563 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
564 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
565 sizeof(zero_clientaddr) == 0))
568 switch (beentry->st_clientaddr.addr.ss_family)
581 remote_port[0] = '\0';
582 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
583 beentry->st_clientaddr.salen,
585 remote_port, sizeof(remote_port),
586 NI_NUMERICHOST | NI_NUMERICSERV);
590 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
591 CStringGetDatum(remote_port)));
596 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
598 Oid dbid = PG_GETARG_OID(0);
600 int tot_backends = pgstat_fetch_stat_numbackends();
604 for (beid = 1; beid <= tot_backends; beid++)
606 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
608 if (beentry && beentry->st_databaseid == dbid)
612 PG_RETURN_INT32(result);
617 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
619 Oid dbid = PG_GETARG_OID(0);
621 PgStat_StatDBEntry *dbentry;
623 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
626 result = (int64) (dbentry->n_xact_commit);
628 PG_RETURN_INT64(result);
633 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
635 Oid dbid = PG_GETARG_OID(0);
637 PgStat_StatDBEntry *dbentry;
639 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
642 result = (int64) (dbentry->n_xact_rollback);
644 PG_RETURN_INT64(result);
649 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
651 Oid dbid = PG_GETARG_OID(0);
653 PgStat_StatDBEntry *dbentry;
655 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
658 result = (int64) (dbentry->n_blocks_fetched);
660 PG_RETURN_INT64(result);
665 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
667 Oid dbid = PG_GETARG_OID(0);
669 PgStat_StatDBEntry *dbentry;
671 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
674 result = (int64) (dbentry->n_blocks_hit);
676 PG_RETURN_INT64(result);
681 pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
683 Oid dbid = PG_GETARG_OID(0);
685 PgStat_StatDBEntry *dbentry;
687 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
690 result = (int64) (dbentry->n_tuples_returned);
692 PG_RETURN_INT64(result);
697 pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
699 Oid dbid = PG_GETARG_OID(0);
701 PgStat_StatDBEntry *dbentry;
703 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
706 result = (int64) (dbentry->n_tuples_fetched);
708 PG_RETURN_INT64(result);
713 pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
715 Oid dbid = PG_GETARG_OID(0);
717 PgStat_StatDBEntry *dbentry;
719 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
722 result = (int64) (dbentry->n_tuples_inserted);
724 PG_RETURN_INT64(result);
729 pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
731 Oid dbid = PG_GETARG_OID(0);
733 PgStat_StatDBEntry *dbentry;
735 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
738 result = (int64) (dbentry->n_tuples_updated);
740 PG_RETURN_INT64(result);
745 pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
747 Oid dbid = PG_GETARG_OID(0);
749 PgStat_StatDBEntry *dbentry;
751 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
754 result = (int64) (dbentry->n_tuples_deleted);
756 PG_RETURN_INT64(result);
760 /* Discard the active statistics snapshot */
762 pg_stat_clear_snapshot(PG_FUNCTION_ARGS)
764 pgstat_clear_snapshot();
770 /* Reset all counters for the current database */
772 pg_stat_reset(PG_FUNCTION_ARGS)
774 pgstat_reset_counters();