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.30 2006/06/19 01:51:21 tgl Exp $
13 *-------------------------------------------------------------------------
17 #include "access/xact.h"
20 #include "miscadmin.h"
21 #include "nodes/execnodes.h"
23 #include "utils/hsearch.h"
24 #include "utils/inet.h"
25 #include "utils/builtins.h"
28 /* bogus ... these externs should be in a header file */
29 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
30 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
31 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
37 extern Datum pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS);
38 extern Datum pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS);
39 extern Datum pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS);
40 extern Datum pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS);
42 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
43 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
44 extern Datum pg_stat_reset(PG_FUNCTION_ARGS);
45 extern Datum pg_stat_get_backend_pid(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_dbid(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_userid(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_activity(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_activity_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_blocks_fetched(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->blocks_fetched);
169 PG_RETURN_INT64(result);
174 pg_stat_get_blocks_hit(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->blocks_hit);
185 PG_RETURN_INT64(result);
189 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
191 Oid relid = PG_GETARG_OID(0);
193 PgStat_StatTabEntry *tabentry;
195 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
198 result = tabentry->vacuum_timestamp;
203 PG_RETURN_TIMESTAMPTZ(result);
207 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
209 Oid relid = PG_GETARG_OID(0);
211 PgStat_StatTabEntry *tabentry;
213 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
216 result = tabentry->autovac_vacuum_timestamp;
221 PG_RETURN_TIMESTAMPTZ(result);
225 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
227 Oid relid = PG_GETARG_OID(0);
229 PgStat_StatTabEntry *tabentry;
231 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
234 result = tabentry->analyze_timestamp;
239 PG_RETURN_TIMESTAMPTZ(result);
243 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
245 Oid relid = PG_GETARG_OID(0);
247 PgStat_StatTabEntry *tabentry;
249 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
252 result = tabentry->autovac_analyze_timestamp;
257 PG_RETURN_TIMESTAMPTZ(result);
261 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
263 FuncCallContext *funcctx;
267 /* stuff done only on the first call of the function */
268 if (SRF_IS_FIRSTCALL())
270 /* create a function context for cross-call persistence */
271 funcctx = SRF_FIRSTCALL_INIT();
273 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
275 funcctx->user_fctx = fctx;
278 fctx[1] = pgstat_fetch_stat_numbackends();
281 /* stuff done on every call of the function */
282 funcctx = SRF_PERCALL_SETUP();
283 fctx = funcctx->user_fctx;
288 if (result <= fctx[1])
290 /* do when there is more left to send */
291 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
295 /* do when there is no more left */
296 SRF_RETURN_DONE(funcctx);
302 pg_backend_pid(PG_FUNCTION_ARGS)
304 PG_RETURN_INT32(MyProcPid);
308 * Built-in function for resetting the counters
311 pg_stat_reset(PG_FUNCTION_ARGS)
313 pgstat_reset_counters();
315 PG_RETURN_BOOL(true);
319 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
321 int32 beid = PG_GETARG_INT32(0);
322 PgBackendStatus *beentry;
324 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
327 PG_RETURN_INT32(beentry->st_procpid);
332 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
334 int32 beid = PG_GETARG_INT32(0);
335 PgBackendStatus *beentry;
337 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
340 PG_RETURN_OID(beentry->st_databaseid);
345 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
347 int32 beid = PG_GETARG_INT32(0);
348 PgBackendStatus *beentry;
350 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
353 PG_RETURN_OID(beentry->st_userid);
358 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
360 int32 beid = PG_GETARG_INT32(0);
362 PgBackendStatus *beentry;
364 const char *activity;
366 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
367 activity = "<backend information not available>";
368 else if (!superuser() && beentry->st_userid != GetUserId())
369 activity = "<insufficient privilege>";
370 else if (*(beentry->st_activity) == '\0')
371 activity = "<command string not enabled>";
373 activity = beentry->st_activity;
375 len = strlen(activity);
376 result = palloc(VARHDRSZ + len);
377 VARATT_SIZEP(result) = VARHDRSZ + len;
378 memcpy(VARDATA(result), activity, len);
380 PG_RETURN_TEXT_P(result);
385 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
387 int32 beid = PG_GETARG_INT32(0);
389 PgBackendStatus *beentry;
391 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
394 if (!superuser() && beentry->st_userid != GetUserId())
397 result = beentry->st_activity_start_timestamp;
400 * No time recorded for start of current query -- this is the case if the
401 * user hasn't enabled query-level stats collection.
406 PG_RETURN_TIMESTAMPTZ(result);
410 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
412 int32 beid = PG_GETARG_INT32(0);
414 PgBackendStatus *beentry;
416 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
419 if (!superuser() && beentry->st_userid != GetUserId())
422 result = beentry->st_proc_start_timestamp;
424 if (result == 0) /* probably can't happen? */
427 PG_RETURN_TIMESTAMPTZ(result);
432 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
434 int32 beid = PG_GETARG_INT32(0);
435 PgBackendStatus *beentry;
436 SockAddr zero_clientaddr;
437 char remote_host[NI_MAXHOST];
440 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
443 if (!superuser() && beentry->st_userid != GetUserId())
446 /* A zeroed client addr means we don't know */
447 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
448 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
449 sizeof(zero_clientaddr) == 0))
452 switch (beentry->st_clientaddr.addr.ss_family)
463 remote_host[0] = '\0';
464 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
465 beentry->st_clientaddr.salen,
466 remote_host, sizeof(remote_host),
468 NI_NUMERICHOST | NI_NUMERICSERV);
472 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
473 CStringGetDatum(remote_host)));
477 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
479 int32 beid = PG_GETARG_INT32(0);
480 PgBackendStatus *beentry;
481 SockAddr zero_clientaddr;
482 char remote_port[NI_MAXSERV];
485 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
488 if (!superuser() && beentry->st_userid != GetUserId())
491 /* A zeroed client addr means we don't know */
492 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
493 if (memcmp(&(beentry->st_clientaddr), &zero_clientaddr,
494 sizeof(zero_clientaddr) == 0))
497 switch (beentry->st_clientaddr.addr.ss_family)
510 remote_port[0] = '\0';
511 ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
512 beentry->st_clientaddr.salen,
514 remote_port, sizeof(remote_port),
515 NI_NUMERICHOST | NI_NUMERICSERV);
519 PG_RETURN_DATUM(DirectFunctionCall1(int4in,
520 CStringGetDatum(remote_port)));
525 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
527 Oid dbid = PG_GETARG_OID(0);
529 int tot_backends = pgstat_fetch_stat_numbackends();
533 for (beid = 1; beid <= tot_backends; beid++)
535 PgBackendStatus *beentry = pgstat_fetch_stat_beentry(beid);
537 if (beentry && beentry->st_databaseid == dbid)
541 PG_RETURN_INT32(result);
546 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
548 Oid dbid = PG_GETARG_OID(0);
550 PgStat_StatDBEntry *dbentry;
552 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
555 result = (int64) (dbentry->n_xact_commit);
557 PG_RETURN_INT64(result);
562 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
564 Oid dbid = PG_GETARG_OID(0);
566 PgStat_StatDBEntry *dbentry;
568 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
571 result = (int64) (dbentry->n_xact_rollback);
573 PG_RETURN_INT64(result);
578 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
580 Oid dbid = PG_GETARG_OID(0);
582 PgStat_StatDBEntry *dbentry;
584 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
587 result = (int64) (dbentry->n_blocks_fetched);
589 PG_RETURN_INT64(result);
594 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
596 Oid dbid = PG_GETARG_OID(0);
598 PgStat_StatDBEntry *dbentry;
600 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
603 result = (int64) (dbentry->n_blocks_hit);
605 PG_RETURN_INT64(result);