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.29 2006/05/19 19:08:26 alvherre 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 PgStat_StatTabEntry *tabentry;
68 relid = PG_GETARG_OID(0);
70 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
73 result = (int64) (tabentry->numscans);
75 PG_RETURN_INT64(result);
80 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
82 PgStat_StatTabEntry *tabentry;
86 relid = PG_GETARG_OID(0);
88 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
91 result = (int64) (tabentry->tuples_returned);
93 PG_RETURN_INT64(result);
98 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
100 PgStat_StatTabEntry *tabentry;
104 relid = PG_GETARG_OID(0);
106 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
109 result = (int64) (tabentry->tuples_fetched);
111 PG_RETURN_INT64(result);
116 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
118 PgStat_StatTabEntry *tabentry;
122 relid = PG_GETARG_OID(0);
124 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
127 result = (int64) (tabentry->tuples_inserted);
129 PG_RETURN_INT64(result);
134 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
136 PgStat_StatTabEntry *tabentry;
140 relid = PG_GETARG_OID(0);
142 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
145 result = (int64) (tabentry->tuples_updated);
147 PG_RETURN_INT64(result);
152 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
154 PgStat_StatTabEntry *tabentry;
158 relid = PG_GETARG_OID(0);
160 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
163 result = (int64) (tabentry->tuples_deleted);
165 PG_RETURN_INT64(result);
170 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
172 PgStat_StatTabEntry *tabentry;
176 relid = PG_GETARG_OID(0);
178 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
181 result = (int64) (tabentry->blocks_fetched);
183 PG_RETURN_INT64(result);
188 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
190 PgStat_StatTabEntry *tabentry;
194 relid = PG_GETARG_OID(0);
196 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
199 result = (int64) (tabentry->blocks_hit);
201 PG_RETURN_INT64(result);
205 pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
207 PgStat_StatTabEntry *tabentry;
211 relid = PG_GETARG_OID(0);
213 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
216 result = tabentry->vacuum_timestamp;
221 PG_RETURN_TIMESTAMPTZ(result);
225 pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
227 PgStat_StatTabEntry *tabentry;
231 relid = PG_GETARG_OID(0);
233 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
236 result = tabentry->autovac_vacuum_timestamp;
241 PG_RETURN_TIMESTAMPTZ(result);
245 pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
247 PgStat_StatTabEntry *tabentry;
251 relid = PG_GETARG_OID(0);
253 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
256 result = tabentry->analyze_timestamp;
261 PG_RETURN_TIMESTAMPTZ(result);
265 pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
267 PgStat_StatTabEntry *tabentry;
271 relid = PG_GETARG_OID(0);
273 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
276 result = tabentry->autovac_analyze_timestamp;
281 PG_RETURN_TIMESTAMPTZ(result);
285 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
287 FuncCallContext *funcctx;
291 /* stuff done only on the first call of the function */
292 if (SRF_IS_FIRSTCALL())
294 /* create a function context for cross-call persistence */
295 funcctx = SRF_FIRSTCALL_INIT();
297 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
299 funcctx->user_fctx = fctx;
302 fctx[1] = pgstat_fetch_stat_numbackends();
305 /* stuff done on every call of the function */
306 funcctx = SRF_PERCALL_SETUP();
307 fctx = funcctx->user_fctx;
312 if (result <= fctx[1])
314 /* do when there is more left to send */
315 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
319 /* do when there is no more left */
320 SRF_RETURN_DONE(funcctx);
326 pg_backend_pid(PG_FUNCTION_ARGS)
328 PG_RETURN_INT32(MyProcPid);
332 * Built-in function for resetting the counters
335 pg_stat_reset(PG_FUNCTION_ARGS)
337 pgstat_reset_counters();
339 PG_RETURN_BOOL(true);
343 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
345 PgStat_StatBeEntry *beentry;
348 beid = PG_GETARG_INT32(0);
350 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
353 PG_RETURN_INT32(beentry->procpid);
358 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
360 PgStat_StatBeEntry *beentry;
363 beid = PG_GETARG_INT32(0);
365 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
368 /* Not initialized yet? */
369 if (!OidIsValid(beentry->databaseid))
372 PG_RETURN_OID(beentry->databaseid);
377 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
379 PgStat_StatBeEntry *beentry;
382 beid = PG_GETARG_INT32(0);
384 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
387 /* Not initialized yet? */
388 if (!OidIsValid(beentry->userid))
391 PG_RETURN_OID(beentry->userid);
396 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
398 PgStat_StatBeEntry *beentry;
404 beid = PG_GETARG_INT32(0);
406 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
407 activity = "<backend information not available>";
408 else if (!superuser() && beentry->userid != GetUserId())
409 activity = "<insufficient privilege>";
410 else if (*(beentry->activity) == '\0')
411 activity = "<command string not enabled>";
413 activity = beentry->activity;
415 len = strlen(activity);
416 result = palloc(VARHDRSZ + len);
417 VARATT_SIZEP(result) = VARHDRSZ + len;
418 memcpy(VARDATA(result), activity, len);
420 PG_RETURN_TEXT_P(result);
425 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
427 int32 beid = PG_GETARG_INT32(0);
429 PgStat_StatBeEntry *beentry;
431 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
434 if (!superuser() && beentry->userid != GetUserId())
437 result = beentry->activity_start_timestamp;
440 * No time recorded for start of current query -- this is the case if the
441 * user hasn't enabled query-level stats collection.
446 PG_RETURN_TIMESTAMPTZ(result);
450 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
452 int32 beid = PG_GETARG_INT32(0);
454 PgStat_StatBeEntry *beentry;
456 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
459 if (!superuser() && beentry->userid != GetUserId())
462 result = beentry->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 PgStat_StatBeEntry *beentry;
475 SockAddr zero_clientaddr;
477 char remote_host[NI_MAXHOST];
480 beid = PG_GETARG_INT32(0);
482 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
485 /* Not initialized yet? */
486 if (!OidIsValid(beentry->userid))
489 if (!superuser() && beentry->userid != GetUserId())
492 /* A zeroed client addr means we don't know */
493 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
494 if (memcmp(&(beentry->clientaddr), &zero_clientaddr,
495 sizeof(zero_clientaddr) == 0))
498 switch (beentry->clientaddr.addr.ss_family)
509 remote_host[0] = '\0';
510 ret = pg_getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
511 remote_host, sizeof(remote_host),
513 NI_NUMERICHOST | NI_NUMERICSERV);
517 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
518 CStringGetDatum(remote_host)));
522 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
524 PgStat_StatBeEntry *beentry;
525 SockAddr zero_clientaddr;
527 char remote_port[NI_MAXSERV];
530 beid = PG_GETARG_INT32(0);
532 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
535 /* Not initialized yet? */
536 if (!OidIsValid(beentry->userid))
539 if (!superuser() && beentry->userid != GetUserId())
542 /* A zeroed client addr means we don't know */
543 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
544 if (memcmp(&(beentry->clientaddr), &zero_clientaddr,
545 sizeof(zero_clientaddr) == 0))
548 switch (beentry->clientaddr.addr.ss_family)
561 remote_port[0] = '\0';
562 ret = pg_getnameinfo_all(&beentry->clientaddr.addr,
563 beentry->clientaddr.salen,
565 remote_port, sizeof(remote_port),
566 NI_NUMERICHOST | NI_NUMERICSERV);
570 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
575 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
577 PgStat_StatDBEntry *dbentry;
581 dbid = PG_GETARG_OID(0);
583 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
586 result = (int32) (dbentry->n_backends);
588 PG_RETURN_INT32(result);
593 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
595 PgStat_StatDBEntry *dbentry;
599 dbid = PG_GETARG_OID(0);
601 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
604 result = (int64) (dbentry->n_xact_commit);
606 PG_RETURN_INT64(result);
611 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
613 PgStat_StatDBEntry *dbentry;
617 dbid = PG_GETARG_OID(0);
619 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
622 result = (int64) (dbentry->n_xact_rollback);
624 PG_RETURN_INT64(result);
629 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
631 PgStat_StatDBEntry *dbentry;
635 dbid = PG_GETARG_OID(0);
637 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
640 result = (int64) (dbentry->n_blocks_fetched);
642 PG_RETURN_INT64(result);
647 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
649 PgStat_StatDBEntry *dbentry;
653 dbid = PG_GETARG_OID(0);
655 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
658 result = (int64) (dbentry->n_blocks_hit);
660 PG_RETURN_INT64(result);