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.35 2006/12/06 18:06:47 neilc 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_blocks_fetched(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
38 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
39 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
40 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
41 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
42 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
43 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
45 extern Datum pg_stat_get_backend_waiting(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_txn_start(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
50 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
56 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
60 pg_stat_get_numscans(PG_FUNCTION_ARGS)
62 Oid relid = PG_GETARG_OID(0);
64 PgStat_StatTabEntry *tabentry;
66 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
69 result = (int64) (tabentry->numscans);
71 PG_RETURN_INT64(result);
76 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
78 Oid relid = PG_GETARG_OID(0);
80 PgStat_StatTabEntry *tabentry;
82 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
85 result = (int64) (tabentry->tuples_returned);
87 PG_RETURN_INT64(result);
92 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
94 Oid relid = PG_GETARG_OID(0);
96 PgStat_StatTabEntry *tabentry;
98 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
101 result = (int64) (tabentry->tuples_fetched);
103 PG_RETURN_INT64(result);
108 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
110 Oid relid = PG_GETARG_OID(0);
112 PgStat_StatTabEntry *tabentry;
114 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
117 result = (int64) (tabentry->tuples_inserted);
119 PG_RETURN_INT64(result);
124 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
126 Oid relid = PG_GETARG_OID(0);
128 PgStat_StatTabEntry *tabentry;
130 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
133 result = (int64) (tabentry->tuples_updated);
135 PG_RETURN_INT64(result);
140 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
142 Oid relid = PG_GETARG_OID(0);
144 PgStat_StatTabEntry *tabentry;
146 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
149 result = (int64) (tabentry->tuples_deleted);
151 PG_RETURN_INT64(result);
156 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
158 Oid relid = PG_GETARG_OID(0);
160 PgStat_StatTabEntry *tabentry;
162 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
165 result = (int64) (tabentry->blocks_fetched);
167 PG_RETURN_INT64(result);
172 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
174 Oid relid = PG_GETARG_OID(0);
176 PgStat_StatTabEntry *tabentry;
178 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
181 result = (int64) (tabentry->blocks_hit);
183 PG_RETURN_INT64(result);
187 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
189 Oid relid = PG_GETARG_OID(0);
191 PgStat_StatTabEntry *tabentry;
193 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
196 result = tabentry->vacuum_timestamp;
201 PG_RETURN_TIMESTAMPTZ(result);
205 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
207 Oid relid = PG_GETARG_OID(0);
209 PgStat_StatTabEntry *tabentry;
211 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
214 result = tabentry->autovac_vacuum_timestamp;
219 PG_RETURN_TIMESTAMPTZ(result);
223 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
225 Oid relid = PG_GETARG_OID(0);
227 PgStat_StatTabEntry *tabentry;
229 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
232 result = tabentry->analyze_timestamp;
237 PG_RETURN_TIMESTAMPTZ(result);
241 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
243 Oid relid = PG_GETARG_OID(0);
245 PgStat_StatTabEntry *tabentry;
247 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
250 result = tabentry->autovac_analyze_timestamp;
255 PG_RETURN_TIMESTAMPTZ(result);
259 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
261 FuncCallContext *funcctx;
265 /* stuff done only on the first call of the function */
266 if (SRF_IS_FIRSTCALL())
268 /* create a function context for cross-call persistence */
269 funcctx = SRF_FIRSTCALL_INIT();
271 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
273 funcctx->user_fctx = fctx;
276 fctx[1] = pgstat_fetch_stat_numbackends();
279 /* stuff done on every call of the function */
280 funcctx = SRF_PERCALL_SETUP();
281 fctx = funcctx->user_fctx;
286 if (result <= fctx[1])
288 /* do when there is more left to send */
289 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
293 /* do when there is no more left */
294 SRF_RETURN_DONE(funcctx);
300 pg_backend_pid(PG_FUNCTION_ARGS)
302 PG_RETURN_INT32(MyProcPid);
306 * Built-in function for resetting the counters
309 pg_stat_reset(PG_FUNCTION_ARGS)
311 pgstat_reset_counters();
313 PG_RETURN_BOOL(true);
317 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
319 int32 beid = PG_GETARG_INT32(0);
320 PgBackendStatus *beentry;
322 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
325 PG_RETURN_INT32(beentry->st_procpid);
330 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
332 int32 beid = PG_GETARG_INT32(0);
333 PgBackendStatus *beentry;
335 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
338 PG_RETURN_OID(beentry->st_databaseid);
343 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
345 int32 beid = PG_GETARG_INT32(0);
346 PgBackendStatus *beentry;
348 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
351 PG_RETURN_OID(beentry->st_userid);
356 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
358 int32 beid = PG_GETARG_INT32(0);
360 PgBackendStatus *beentry;
362 const char *activity;
364 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
365 activity = "<backend information not available>";
366 else if (!superuser() && beentry->st_userid != GetUserId())
367 activity = "<insufficient privilege>";
368 else if (*(beentry->st_activity) == '\0')
369 activity = "<command string not enabled>";
371 activity = beentry->st_activity;
373 len = strlen(activity);
374 result = palloc(VARHDRSZ + len);
375 VARATT_SIZEP(result) = VARHDRSZ + len;
376 memcpy(VARDATA(result), activity, len);
378 PG_RETURN_TEXT_P(result);
383 pg_stat_get_backend_waiting(PG_FUNCTION_ARGS)
385 int32 beid = PG_GETARG_INT32(0);
387 PgBackendStatus *beentry;
389 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
392 if (!superuser() && beentry->st_userid != GetUserId())
395 result = beentry->st_waiting;
397 PG_RETURN_BOOL(result);
402 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
404 int32 beid = PG_GETARG_INT32(0);
406 PgBackendStatus *beentry;
408 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
411 if (!superuser() && beentry->st_userid != GetUserId())
414 result = beentry->st_activity_start_timestamp;
417 * No time recorded for start of current query -- this is the case if the
418 * user hasn't enabled query-level stats collection.
423 PG_RETURN_TIMESTAMPTZ(result);
428 pg_stat_get_backend_txn_start(PG_FUNCTION_ARGS)
430 int32 beid = PG_GETARG_INT32(0);
432 PgBackendStatus *beentry;
434 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
437 if (!superuser() && beentry->st_userid != GetUserId())
440 result = beentry->st_txn_start_timestamp;
442 if (result == 0) /* not in a transaction */
445 PG_RETURN_TIMESTAMPTZ(result);
450 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
452 int32 beid = PG_GETARG_INT32(0);
454 PgBackendStatus *beentry;
456 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
459 if (!superuser() && beentry->st_userid != GetUserId())
462 result = beentry->st_proc_start_timestamp;
464 if (result == 0) /* probably can't happen? */
467 PG_RETURN_TIMESTAMPTZ(result);
472 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
474 int32 beid = PG_GETARG_INT32(0);
475 PgBackendStatus *beentry;
476 SockAddr zero_clientaddr;
477 char remote_host[NI_MAXHOST];
480 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
483 if (!superuser() && beentry->st_userid != GetUserId())
486 /* A zeroed client addr means we don't know */
487 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
488 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
489 sizeof(zero_clientaddr) == 0))
492 switch (beentry->st_clientaddr.addr.ss_family)
503 remote_host[0] = '\0';
504 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
505 beentry->st_clientaddr.salen,
506 remote_host, sizeof(remote_host),
508 NI_NUMERICHOST | NI_NUMERICSERV);
512 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
513 CStringGetDatum(remote_host)));
517 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
519 int32 beid = PG_GETARG_INT32(0);
520 PgBackendStatus *beentry;
521 SockAddr zero_clientaddr;
522 char remote_port[NI_MAXSERV];
525 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
528 if (!superuser() && beentry->st_userid != GetUserId())
531 /* A zeroed client addr means we don't know */
532 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
533 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
534 sizeof(zero_clientaddr) == 0))
537 switch (beentry->st_clientaddr.addr.ss_family)
550 remote_port[0] = '\0';
551 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
552 beentry->st_clientaddr.salen,
554 remote_port, sizeof(remote_port),
555 NI_NUMERICHOST | NI_NUMERICSERV);
559 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
560 CStringGetDatum(remote_port)));
565 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
567 Oid dbid = PG_GETARG_OID(0);
569 int tot_backends = pgstat_fetch_stat_numbackends();
573 for (beid = 1; beid <= tot_backends; beid++)
575 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
577 if (beentry && beentry->st_databaseid == dbid)
581 PG_RETURN_INT32(result);
586 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
588 Oid dbid = PG_GETARG_OID(0);
590 PgStat_StatDBEntry *dbentry;
592 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
595 result = (int64) (dbentry->n_xact_commit);
597 PG_RETURN_INT64(result);
602 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
604 Oid dbid = PG_GETARG_OID(0);
606 PgStat_StatDBEntry *dbentry;
608 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
611 result = (int64) (dbentry->n_xact_rollback);
613 PG_RETURN_INT64(result);
618 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
620 Oid dbid = PG_GETARG_OID(0);
622 PgStat_StatDBEntry *dbentry;
624 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
627 result = (int64) (dbentry->n_blocks_fetched);
629 PG_RETURN_INT64(result);
634 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
636 Oid dbid = PG_GETARG_OID(0);
638 PgStat_StatDBEntry *dbentry;
640 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
643 result = (int64) (dbentry->n_blocks_hit);
645 PG_RETURN_INT64(result);