1 /*-------------------------------------------------------------------------
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2006, 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.36 2007/01/02 20:59:31 momjian 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_reset(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_txn_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);
62 pg_stat_get_numscans(PG_FUNCTION_ARGS)
64 Oid relid = PG_GETARG_OID(0);
66 PgStat_StatTabEntry *tabentry;
68 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
71 result = (int64) (tabentry->numscans);
73 PG_RETURN_INT64(result);
78 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
80 Oid relid = PG_GETARG_OID(0);
82 PgStat_StatTabEntry *tabentry;
84 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
87 result = (int64) (tabentry->tuples_returned);
89 PG_RETURN_INT64(result);
94 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
96 Oid relid = PG_GETARG_OID(0);
98 PgStat_StatTabEntry *tabentry;
100 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
103 result = (int64) (tabentry->tuples_fetched);
105 PG_RETURN_INT64(result);
110 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
112 Oid relid = PG_GETARG_OID(0);
114 PgStat_StatTabEntry *tabentry;
116 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
119 result = (int64) (tabentry->tuples_inserted);
121 PG_RETURN_INT64(result);
126 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
128 Oid relid = PG_GETARG_OID(0);
130 PgStat_StatTabEntry *tabentry;
132 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
135 result = (int64) (tabentry->tuples_updated);
137 PG_RETURN_INT64(result);
142 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
144 Oid relid = PG_GETARG_OID(0);
146 PgStat_StatTabEntry *tabentry;
148 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
151 result = (int64) (tabentry->tuples_deleted);
153 PG_RETURN_INT64(result);
158 pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
160 Oid relid = PG_GETARG_OID(0);
162 PgStat_StatTabEntry *tabentry;
164 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
167 result = (int64) (tabentry->n_live_tuples);
169 PG_RETURN_INT64(result);
174 pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
176 Oid relid = PG_GETARG_OID(0);
178 PgStat_StatTabEntry *tabentry;
180 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
183 result = (int64) (tabentry->n_dead_tuples);
185 PG_RETURN_INT64(result);
190 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
192 Oid relid = PG_GETARG_OID(0);
194 PgStat_StatTabEntry *tabentry;
196 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
199 result = (int64) (tabentry->blocks_fetched);
201 PG_RETURN_INT64(result);
206 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
208 Oid relid = PG_GETARG_OID(0);
210 PgStat_StatTabEntry *tabentry;
212 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
215 result = (int64) (tabentry->blocks_hit);
217 PG_RETURN_INT64(result);
221 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
223 Oid relid = PG_GETARG_OID(0);
225 PgStat_StatTabEntry *tabentry;
227 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
230 result = tabentry->vacuum_timestamp;
235 PG_RETURN_TIMESTAMPTZ(result);
239 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
241 Oid relid = PG_GETARG_OID(0);
243 PgStat_StatTabEntry *tabentry;
245 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
248 result = tabentry->autovac_vacuum_timestamp;
253 PG_RETURN_TIMESTAMPTZ(result);
257 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
259 Oid relid = PG_GETARG_OID(0);
261 PgStat_StatTabEntry *tabentry;
263 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
266 result = tabentry->analyze_timestamp;
271 PG_RETURN_TIMESTAMPTZ(result);
275 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
277 Oid relid = PG_GETARG_OID(0);
279 PgStat_StatTabEntry *tabentry;
281 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
284 result = tabentry->autovac_analyze_timestamp;
289 PG_RETURN_TIMESTAMPTZ(result);
293 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
295 FuncCallContext *funcctx;
299 /* stuff done only on the first call of the function */
300 if (SRF_IS_FIRSTCALL())
302 /* create a function context for cross-call persistence */
303 funcctx = SRF_FIRSTCALL_INIT();
305 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
307 funcctx->user_fctx = fctx;
310 fctx[1] = pgstat_fetch_stat_numbackends();
313 /* stuff done on every call of the function */
314 funcctx = SRF_PERCALL_SETUP();
315 fctx = funcctx->user_fctx;
320 if (result <= fctx[1])
322 /* do when there is more left to send */
323 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
327 /* do when there is no more left */
328 SRF_RETURN_DONE(funcctx);
334 pg_backend_pid(PG_FUNCTION_ARGS)
336 PG_RETURN_INT32(MyProcPid);
340 * Built-in function for resetting the counters
343 pg_stat_reset(PG_FUNCTION_ARGS)
345 pgstat_reset_counters();
347 PG_RETURN_BOOL(true);
351 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
353 int32 beid = PG_GETARG_INT32(0);
354 PgBackendStatus *beentry;
356 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
359 PG_RETURN_INT32(beentry->st_procpid);
364 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
366 int32 beid = PG_GETARG_INT32(0);
367 PgBackendStatus *beentry;
369 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
372 PG_RETURN_OID(beentry->st_databaseid);
377 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
379 int32 beid = PG_GETARG_INT32(0);
380 PgBackendStatus *beentry;
382 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
385 PG_RETURN_OID(beentry->st_userid);
390 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
392 int32 beid = PG_GETARG_INT32(0);
394 PgBackendStatus *beentry;
396 const char *activity;
398 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
399 activity = "<backend information not available>";
400 else if (!superuser() && beentry->st_userid != GetUserId())
401 activity = "<insufficient privilege>";
402 else if (*(beentry->st_activity) == '\0')
403 activity = "<command string not enabled>";
405 activity = beentry->st_activity;
407 len = strlen(activity);
408 result = palloc(VARHDRSZ + len);
409 VARATT_SIZEP(result) = VARHDRSZ + len;
410 memcpy(VARDATA(result), activity, len);
412 PG_RETURN_TEXT_P(result);
417 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
419 int32 beid = PG_GETARG_INT32(0);
421 PgBackendStatus *beentry;
423 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
426 if (!superuser() && beentry->st_userid != GetUserId())
429 result = beentry->st_waiting;
431 PG_RETURN_BOOL(result);
436 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
438 int32 beid = PG_GETARG_INT32(0);
440 PgBackendStatus *beentry;
442 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
445 if (!superuser() && beentry->st_userid != GetUserId())
448 result = beentry->st_activity_start_timestamp;
451 * No time recorded for start of current query -- this is the case if the
452 * user hasn't enabled query-level stats collection.
457 PG_RETURN_TIMESTAMPTZ(result);
462 pg_stat_get_backend_txn_start(PG_FUNCTION_ARGS)
464 int32 beid = PG_GETARG_INT32(0);
466 PgBackendStatus *beentry;
468 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
471 if (!superuser() && beentry->st_userid != GetUserId())
474 result = beentry->st_txn_start_timestamp;
476 if (result == 0) /* not in a transaction */
479 PG_RETURN_TIMESTAMPTZ(result);
484 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
486 int32 beid = PG_GETARG_INT32(0);
488 PgBackendStatus *beentry;
490 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
493 if (!superuser() && beentry->st_userid != GetUserId())
496 result = beentry->st_proc_start_timestamp;
498 if (result == 0) /* probably can't happen? */
501 PG_RETURN_TIMESTAMPTZ(result);
506 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
508 int32 beid = PG_GETARG_INT32(0);
509 PgBackendStatus *beentry;
510 SockAddr zero_clientaddr;
511 char remote_host[NI_MAXHOST];
514 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
517 if (!superuser() && beentry->st_userid != GetUserId())
520 /* A zeroed client addr means we don't know */
521 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
522 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
523 sizeof(zero_clientaddr) == 0))
526 switch (beentry->st_clientaddr.addr.ss_family)
537 remote_host[0] = '\0';
538 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
539 beentry->st_clientaddr.salen,
540 remote_host, sizeof(remote_host),
542 NI_NUMERICHOST | NI_NUMERICSERV);
546 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
547 CStringGetDatum(remote_host)));
551 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
553 int32 beid = PG_GETARG_INT32(0);
554 PgBackendStatus *beentry;
555 SockAddr zero_clientaddr;
556 char remote_port[NI_MAXSERV];
559 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
562 if (!superuser() && beentry->st_userid != GetUserId())
565 /* A zeroed client addr means we don't know */
566 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
567 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
568 sizeof(zero_clientaddr) == 0))
571 switch (beentry->st_clientaddr.addr.ss_family)
584 remote_port[0] = '\0';
585 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
586 beentry->st_clientaddr.salen,
588 remote_port, sizeof(remote_port),
589 NI_NUMERICHOST | NI_NUMERICSERV);
593 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
594 CStringGetDatum(remote_port)));
599 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
601 Oid dbid = PG_GETARG_OID(0);
603 int tot_backends = pgstat_fetch_stat_numbackends();
607 for (beid = 1; beid <= tot_backends; beid++)
609 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
611 if (beentry && beentry->st_databaseid == dbid)
615 PG_RETURN_INT32(result);
620 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
622 Oid dbid = PG_GETARG_OID(0);
624 PgStat_StatDBEntry *dbentry;
626 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
629 result = (int64) (dbentry->n_xact_commit);
631 PG_RETURN_INT64(result);
636 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
638 Oid dbid = PG_GETARG_OID(0);
640 PgStat_StatDBEntry *dbentry;
642 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
645 result = (int64) (dbentry->n_xact_rollback);
647 PG_RETURN_INT64(result);
652 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
654 Oid dbid = PG_GETARG_OID(0);
656 PgStat_StatDBEntry *dbentry;
658 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
661 result = (int64) (dbentry->n_blocks_fetched);
663 PG_RETURN_INT64(result);
668 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
670 Oid dbid = PG_GETARG_OID(0);
672 PgStat_StatDBEntry *dbentry;
674 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
677 result = (int64) (dbentry->n_blocks_hit);
679 PG_RETURN_INT64(result);