1 /*-------------------------------------------------------------------------
4 * Functions for accessing the statistics collector data
6 * Portions Copyright (c) 1996-2005, 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.22 2005/05/11 01:41:41 neilc Exp $
13 *-------------------------------------------------------------------------
17 #include "access/xact.h"
18 #include "catalog/pg_shadow.h"
21 #include "miscadmin.h"
22 #include "nodes/execnodes.h"
24 #include "utils/hsearch.h"
25 #include "utils/inet.h"
26 #include "utils/builtins.h"
29 /* bogus ... these externs should be in a header file */
30 extern Datum pg_stat_get_numscans(PG_FUNCTION_ARGS);
31 extern Datum pg_stat_get_tuples_returned(PG_FUNCTION_ARGS);
32 extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS);
33 extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS);
34 extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS);
35 extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS);
36 extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS);
37 extern Datum pg_stat_get_blocks_hit(PG_FUNCTION_ARGS);
39 extern Datum pg_stat_get_backend_idset(PG_FUNCTION_ARGS);
40 extern Datum pg_backend_pid(PG_FUNCTION_ARGS);
41 extern Datum pg_stat_reset(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_activity_start(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
49 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
55 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
59 pg_stat_get_numscans(PG_FUNCTION_ARGS)
61 PgStat_StatTabEntry *tabentry;
65 relid = PG_GETARG_OID(0);
67 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
70 result = (int64) (tabentry->numscans);
72 PG_RETURN_INT64(result);
77 pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
79 PgStat_StatTabEntry *tabentry;
83 relid = PG_GETARG_OID(0);
85 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
88 result = (int64) (tabentry->tuples_returned);
90 PG_RETURN_INT64(result);
95 pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
97 PgStat_StatTabEntry *tabentry;
101 relid = PG_GETARG_OID(0);
103 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
106 result = (int64) (tabentry->tuples_fetched);
108 PG_RETURN_INT64(result);
113 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
115 PgStat_StatTabEntry *tabentry;
119 relid = PG_GETARG_OID(0);
121 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
124 result = (int64) (tabentry->tuples_inserted);
126 PG_RETURN_INT64(result);
131 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
133 PgStat_StatTabEntry *tabentry;
137 relid = PG_GETARG_OID(0);
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 PgStat_StatTabEntry *tabentry;
155 relid = PG_GETARG_OID(0);
157 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
160 result = (int64) (tabentry->tuples_deleted);
162 PG_RETURN_INT64(result);
167 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
169 PgStat_StatTabEntry *tabentry;
173 relid = PG_GETARG_OID(0);
175 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
178 result = (int64) (tabentry->blocks_fetched);
180 PG_RETURN_INT64(result);
185 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
187 PgStat_StatTabEntry *tabentry;
191 relid = PG_GETARG_OID(0);
193 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
196 result = (int64) (tabentry->blocks_hit);
198 PG_RETURN_INT64(result);
203 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
205 FuncCallContext *funcctx;
209 /* stuff done only on the first call of the function */
210 if (SRF_IS_FIRSTCALL())
212 /* create a function context for cross-call persistence */
213 funcctx = SRF_FIRSTCALL_INIT();
215 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
217 funcctx->user_fctx = fctx;
220 fctx[1] = pgstat_fetch_stat_numbackends();
223 /* stuff done on every call of the function */
224 funcctx = SRF_PERCALL_SETUP();
225 fctx = funcctx->user_fctx;
230 if (result <= fctx[1])
232 /* do when there is more left to send */
233 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
237 /* do when there is no more left */
238 SRF_RETURN_DONE(funcctx);
244 pg_backend_pid(PG_FUNCTION_ARGS)
246 PG_RETURN_INT32(MyProcPid);
250 * Built-in function for resetting the counters
253 pg_stat_reset(PG_FUNCTION_ARGS)
255 pgstat_reset_counters();
257 PG_RETURN_BOOL(true);
261 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
263 PgStat_StatBeEntry *beentry;
266 beid = PG_GETARG_INT32(0);
268 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
271 PG_RETURN_INT32(beentry->procpid);
276 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
278 PgStat_StatBeEntry *beentry;
281 beid = PG_GETARG_INT32(0);
283 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
286 /* Not initialized yet? */
287 if (!OidIsValid(beentry->databaseid))
290 PG_RETURN_OID(beentry->databaseid);
295 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
297 PgStat_StatBeEntry *beentry;
300 beid = PG_GETARG_INT32(0);
302 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
305 /* Not initialized yet? */
306 if (!OidIsValid(beentry->userid))
309 PG_RETURN_INT32(beentry->userid);
314 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
316 PgStat_StatBeEntry *beentry;
322 beid = PG_GETARG_INT32(0);
324 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
325 activity = "<backend information not available>";
326 else if (!superuser() && beentry->userid != GetUserId())
327 activity = "<insufficient privilege>";
328 else if (*(beentry->activity) == '\0')
329 activity = "<command string not enabled>";
331 activity = beentry->activity;
333 len = strlen(activity);
334 result = palloc(VARHDRSZ + len);
335 VARATT_SIZEP(result) = VARHDRSZ + len;
336 memcpy(VARDATA(result), activity, len);
338 PG_RETURN_TEXT_P(result);
343 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
345 PgStat_StatBeEntry *beentry;
351 beid = PG_GETARG_INT32(0);
353 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
356 if (!superuser() && beentry->userid != GetUserId())
359 sec = beentry->activity_start_sec;
360 usec = beentry->activity_start_usec;
363 * No time recorded for start of current query -- this is the case if
364 * the user hasn't enabled query-level stats collection.
366 if (sec == 0 && usec == 0)
369 result = AbsoluteTimeUsecToTimestampTz(sec, usec);
371 PG_RETURN_TIMESTAMPTZ(result);
375 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
377 PgStat_StatBeEntry *beentry;
383 beid = PG_GETARG_INT32(0);
385 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
388 if (!superuser() && beentry->userid != GetUserId())
391 sec = beentry->start_sec;
392 usec = beentry->start_usec;
394 if (sec == 0 && usec == 0)
397 result = AbsoluteTimeUsecToTimestampTz(sec, usec);
399 PG_RETURN_TIMESTAMPTZ(result);
404 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
406 PgStat_StatBeEntry *beentry;
408 char remote_host[NI_MAXHOST];
411 beid = PG_GETARG_INT32(0);
413 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
416 /* Not initialized yet? */
417 if (!OidIsValid(beentry->userid))
420 if (!superuser() && beentry->userid != GetUserId())
423 switch (beentry->clientaddr.addr.ss_family)
434 remote_host[0] = '\0';
435 ret = getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
436 remote_host, sizeof(remote_host),
438 NI_NUMERICHOST | NI_NUMERICSERV);
442 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
443 CStringGetDatum(remote_host)));
447 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
449 PgStat_StatBeEntry *beentry;
451 char remote_port[NI_MAXSERV];
454 beid = PG_GETARG_INT32(0);
456 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
459 /* Not initialized yet? */
460 if (!OidIsValid(beentry->userid))
463 if (!superuser() && beentry->userid != GetUserId())
466 switch (beentry->clientaddr.addr.ss_family)
479 remote_port[0] = '\0';
480 ret = getnameinfo_all(&beentry->clientaddr.addr,
481 beentry->clientaddr.salen,
483 remote_port, sizeof(remote_port),
484 NI_NUMERICHOST | NI_NUMERICSERV);
488 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
493 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
495 PgStat_StatDBEntry *dbentry;
499 dbid = PG_GETARG_OID(0);
501 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
504 result = (int32) (dbentry->n_backends);
506 PG_RETURN_INT32(result);
511 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
513 PgStat_StatDBEntry *dbentry;
517 dbid = PG_GETARG_OID(0);
519 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
522 result = (int64) (dbentry->n_xact_commit);
524 PG_RETURN_INT64(result);
529 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
531 PgStat_StatDBEntry *dbentry;
535 dbid = PG_GETARG_OID(0);
537 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
540 result = (int64) (dbentry->n_xact_rollback);
542 PG_RETURN_INT64(result);
547 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
549 PgStat_StatDBEntry *dbentry;
553 dbid = PG_GETARG_OID(0);
555 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
558 result = (int64) (dbentry->n_blocks_fetched);
560 PG_RETURN_INT64(result);
565 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
567 PgStat_StatDBEntry *dbentry;
571 dbid = PG_GETARG_OID(0);
573 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
576 result = (int64) (dbentry->n_blocks_hit);
578 PG_RETURN_INT64(result);