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.28 2006/05/19 15:15:37 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);
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_activity_start(PG_FUNCTION_ARGS);
46 extern Datum pg_stat_get_backend_start(PG_FUNCTION_ARGS);
47 extern Datum pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS);
48 extern Datum pg_stat_get_backend_client_port(PG_FUNCTION_ARGS);
50 extern Datum pg_stat_get_db_numbackends(PG_FUNCTION_ARGS);
51 extern Datum pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS);
52 extern Datum pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS);
53 extern Datum pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS);
54 extern Datum pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS);
58 pg_stat_get_numscans(PG_FUNCTION_ARGS)
60 PgStat_StatTabEntry *tabentry;
64 relid = PG_GETARG_OID(0);
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 PgStat_StatTabEntry *tabentry;
82 relid = PG_GETARG_OID(0);
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 PgStat_StatTabEntry *tabentry;
100 relid = PG_GETARG_OID(0);
102 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
105 result = (int64) (tabentry->tuples_fetched);
107 PG_RETURN_INT64(result);
112 pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
114 PgStat_StatTabEntry *tabentry;
118 relid = PG_GETARG_OID(0);
120 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
123 result = (int64) (tabentry->tuples_inserted);
125 PG_RETURN_INT64(result);
130 pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
132 PgStat_StatTabEntry *tabentry;
136 relid = PG_GETARG_OID(0);
138 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
141 result = (int64) (tabentry->tuples_updated);
143 PG_RETURN_INT64(result);
148 pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
150 PgStat_StatTabEntry *tabentry;
154 relid = PG_GETARG_OID(0);
156 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
159 result = (int64) (tabentry->tuples_deleted);
161 PG_RETURN_INT64(result);
166 pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
168 PgStat_StatTabEntry *tabentry;
172 relid = PG_GETARG_OID(0);
174 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
177 result = (int64) (tabentry->blocks_fetched);
179 PG_RETURN_INT64(result);
184 pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
186 PgStat_StatTabEntry *tabentry;
190 relid = PG_GETARG_OID(0);
192 if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
195 result = (int64) (tabentry->blocks_hit);
197 PG_RETURN_INT64(result);
202 pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
204 FuncCallContext *funcctx;
208 /* stuff done only on the first call of the function */
209 if (SRF_IS_FIRSTCALL())
211 /* create a function context for cross-call persistence */
212 funcctx = SRF_FIRSTCALL_INIT();
214 fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
216 funcctx->user_fctx = fctx;
219 fctx[1] = pgstat_fetch_stat_numbackends();
222 /* stuff done on every call of the function */
223 funcctx = SRF_PERCALL_SETUP();
224 fctx = funcctx->user_fctx;
229 if (result <= fctx[1])
231 /* do when there is more left to send */
232 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
236 /* do when there is no more left */
237 SRF_RETURN_DONE(funcctx);
243 pg_backend_pid(PG_FUNCTION_ARGS)
245 PG_RETURN_INT32(MyProcPid);
249 * Built-in function for resetting the counters
252 pg_stat_reset(PG_FUNCTION_ARGS)
254 pgstat_reset_counters();
256 PG_RETURN_BOOL(true);
260 pg_stat_get_backend_pid(PG_FUNCTION_ARGS)
262 PgStat_StatBeEntry *beentry;
265 beid = PG_GETARG_INT32(0);
267 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
270 PG_RETURN_INT32(beentry->procpid);
275 pg_stat_get_backend_dbid(PG_FUNCTION_ARGS)
277 PgStat_StatBeEntry *beentry;
280 beid = PG_GETARG_INT32(0);
282 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
285 /* Not initialized yet? */
286 if (!OidIsValid(beentry->databaseid))
289 PG_RETURN_OID(beentry->databaseid);
294 pg_stat_get_backend_userid(PG_FUNCTION_ARGS)
296 PgStat_StatBeEntry *beentry;
299 beid = PG_GETARG_INT32(0);
301 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
304 /* Not initialized yet? */
305 if (!OidIsValid(beentry->userid))
308 PG_RETURN_OID(beentry->userid);
313 pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
315 PgStat_StatBeEntry *beentry;
321 beid = PG_GETARG_INT32(0);
323 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
324 activity = "<backend information not available>";
325 else if (!superuser() && beentry->userid != GetUserId())
326 activity = "<insufficient privilege>";
327 else if (*(beentry->activity) == '\0')
328 activity = "<command string not enabled>";
330 activity = beentry->activity;
332 len = strlen(activity);
333 result = palloc(VARHDRSZ + len);
334 VARATT_SIZEP(result) = VARHDRSZ + len;
335 memcpy(VARDATA(result), activity, len);
337 PG_RETURN_TEXT_P(result);
342 pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS)
344 int32 beid = PG_GETARG_INT32(0);
346 PgStat_StatBeEntry *beentry;
348 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
351 if (!superuser() && beentry->userid != GetUserId())
354 result = beentry->activity_start_timestamp;
357 * No time recorded for start of current query -- this is the case if the
358 * user hasn't enabled query-level stats collection.
363 PG_RETURN_TIMESTAMPTZ(result);
367 pg_stat_get_backend_start(PG_FUNCTION_ARGS)
369 int32 beid = PG_GETARG_INT32(0);
371 PgStat_StatBeEntry *beentry;
373 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
376 if (!superuser() && beentry->userid != GetUserId())
379 result = beentry->start_timestamp;
381 if (result == 0) /* probably can't happen? */
384 PG_RETURN_TIMESTAMPTZ(result);
389 pg_stat_get_backend_client_addr(PG_FUNCTION_ARGS)
391 PgStat_StatBeEntry *beentry;
392 SockAddr zero_clientaddr;
394 char remote_host[NI_MAXHOST];
397 beid = PG_GETARG_INT32(0);
399 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
402 /* Not initialized yet? */
403 if (!OidIsValid(beentry->userid))
406 if (!superuser() && beentry->userid != GetUserId())
409 /* A zeroed client addr means we don't know */
410 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
411 if (memcmp(&(beentry->clientaddr), &zero_clientaddr,
412 sizeof(zero_clientaddr) == 0))
415 switch (beentry->clientaddr.addr.ss_family)
426 remote_host[0] = '\0';
427 ret = pg_getnameinfo_all(&beentry->clientaddr.addr, beentry->clientaddr.salen,
428 remote_host, sizeof(remote_host),
430 NI_NUMERICHOST | NI_NUMERICSERV);
434 PG_RETURN_INET_P(DirectFunctionCall1(inet_in,
435 CStringGetDatum(remote_host)));
439 pg_stat_get_backend_client_port(PG_FUNCTION_ARGS)
441 PgStat_StatBeEntry *beentry;
442 SockAddr zero_clientaddr;
444 char remote_port[NI_MAXSERV];
447 beid = PG_GETARG_INT32(0);
449 if ((beentry = pgstat_fetch_stat_beentry(beid)) == NULL)
452 /* Not initialized yet? */
453 if (!OidIsValid(beentry->userid))
456 if (!superuser() && beentry->userid != GetUserId())
459 /* A zeroed client addr means we don't know */
460 memset(&zero_clientaddr, 0, sizeof(zero_clientaddr));
461 if (memcmp(&(beentry->clientaddr), &zero_clientaddr,
462 sizeof(zero_clientaddr) == 0))
465 switch (beentry->clientaddr.addr.ss_family)
478 remote_port[0] = '\0';
479 ret = pg_getnameinfo_all(&beentry->clientaddr.addr,
480 beentry->clientaddr.salen,
482 remote_port, sizeof(remote_port),
483 NI_NUMERICHOST | NI_NUMERICSERV);
487 PG_RETURN_DATUM(DirectFunctionCall1(int4in, CStringGetDatum(remote_port)));
492 pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
494 PgStat_StatDBEntry *dbentry;
498 dbid = PG_GETARG_OID(0);
500 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
503 result = (int32) (dbentry->n_backends);
505 PG_RETURN_INT32(result);
510 pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
512 PgStat_StatDBEntry *dbentry;
516 dbid = PG_GETARG_OID(0);
518 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
521 result = (int64) (dbentry->n_xact_commit);
523 PG_RETURN_INT64(result);
528 pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
530 PgStat_StatDBEntry *dbentry;
534 dbid = PG_GETARG_OID(0);
536 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
539 result = (int64) (dbentry->n_xact_rollback);
541 PG_RETURN_INT64(result);
546 pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
548 PgStat_StatDBEntry *dbentry;
552 dbid = PG_GETARG_OID(0);
554 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
557 result = (int64) (dbentry->n_blocks_fetched);
559 PG_RETURN_INT64(result);
564 pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
566 PgStat_StatDBEntry *dbentry;
570 dbid = PG_GETARG_OID(0);
572 if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
575 result = (int64) (dbentry->n_blocks_hit);
577 PG_RETURN_INT64(result);